aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorRuben Beltran del Rio <git@r.bdr.sh>2024-02-14 16:58:56 +0100
committerRuben Beltran del Rio <git@r.bdr.sh>2024-02-14 16:58:56 +0100
commit6cd62e795e3716aa0cbd2d1ff8c1b3a345803563 (patch)
treef35cfd157529d890d8d5e8e4280c9d44d77a5e01 /lib
parent02f408c24d82d1fac4e55c146c4fa57cbdcdeca4 (diff)
Use modules, use XDG dirs
Diffstat (limited to 'lib')
-rw-r--r--lib/archivers/gemlog.js47
-rw-r--r--lib/blog.js92
-rw-r--r--lib/constants.js4
-rw-r--r--lib/generators/html.js14
-rw-r--r--lib/generators/rss.js16
-rw-r--r--lib/generators/static.js50
-rw-r--r--lib/generators/txt.js15
-rw-r--r--lib/remote.js10
-rw-r--r--lib/remotes/git.js6
-rw-r--r--lib/utils.js48
10 files changed, 165 insertions, 137 deletions
diff --git a/lib/archivers/gemlog.js b/lib/archivers/gemlog.js
index 3443c66..d56a1f6 100644
--- a/lib/archivers/gemlog.js
+++ b/lib/archivers/gemlog.js
@@ -1,10 +1,10 @@
-const { cp, mkdir, readdir, writeFile } = require('fs/promises');
-const { debuglog } = require('util');
-const { resolve, join } = require('path');
-const { rmIfExists } = require('../utils');
+import Dot from 'dot';
+import { cp, mkdir, readdir, readFile, writeFile } from 'fs/promises';
+import { debuglog } from 'util';
+import { join } from 'path';
+import { rmIfExists } from '../utils.js';
const internals = {
- kArchiveName: resolve(join(__dirname, '../..', '.gemlog')),
kIndexName: 'index.gmi',
kGeminiRe: /\.gmi$/i,
@@ -26,13 +26,13 @@ const internals = {
}
};
-module.exports = async function(archiveDirectory) {
- internals.debuglog(`Reading archive ${archiveDirectory}`);
- const postIds = (await readdir(archiveDirectory))
+export default async function(templateDirectory, source, target) {
+ internals.debuglog(`Reading archive ${source}`);
+ const postIds = (await readdir(source))
.sort((a, b) => Number(b) - Number(a));
const posts = [];
for (const id of postIds) {
- const postDirectory = join(archiveDirectory, id);
+ const postDirectory = join(source, id);
const slug = (await readdir(postDirectory))
.filter((entry) => internals.kGeminiRe.test(entry))[0];
@@ -41,26 +41,31 @@ module.exports = async function(archiveDirectory) {
internals.debuglog(`Read ${posts.length} posts`);
- const index = [
- '# Ruben\'s Gemlog Archive', '',
- '=> https://r.bdr.sh/gemlog/feed.xml 📰 RSS Feed',
- '=> https://r.bdr.sh/gemlog/index.txt 📑 http text version (latest 3 posts)',
- '',
- ...posts.map((post) => internals.buildLink(post.id, post.slug)),
- '', '=> ../ ðŸŠī Back to main page'
- ].join('\n');
+ internals.debuglog('Generating Archive Index');
+ const indexLocation = join(templateDirectory, internals.kIndexName);
+
+ internals.debuglog(`Reading ${indexLocation}`);
+ const indexTemplate = await readFile(indexLocation, { encoding: 'utf8' });
+
+ internals.debuglog('Writing Archive Index');
+ const index = Dot.template(indexTemplate, {
+ ...Dot.templateSettings,
+ strip: false
+ })({
+ posts: posts.map((post) => internals.buildLink(post.id, post.slug)).join('\n'),
+ });
try {
internals.debuglog('Removing index');
- await rmIfExists(internals.kArchiveName);
+ await rmIfExists(target);
}
finally {
internals.debuglog('Creating index');
- await mkdir(internals.kArchiveName);
- const indexFile = join(internals.kArchiveName, internals.kIndexName);
+ await mkdir(target);
+ const indexFile = join(target, internals.kIndexName);
await writeFile(indexFile, index);
internals.debuglog('Copying posts to archive');
- await cp(archiveDirectory, internals.kArchiveName, { recursive: true });
+ await cp(source, target, { recursive: true });
}
};
diff --git a/lib/blog.js b/lib/blog.js
index ca944cf..04106b0 100644
--- a/lib/blog.js
+++ b/lib/blog.js
@@ -1,28 +1,26 @@
-'use strict';
-
-const { access, cp, mkdir, readdir, readFile, writeFile } = require('fs/promises');
-const { exec } = require('child_process');
-const { basename, resolve, join } = require('path');
-const ParseGemini = require('gemini-to-html/parse');
-const RenderGemini = require('gemini-to-html/render');
-const { debuglog, promisify } = require('util');
-const { ensureDirectoryExists, rmIfExists } = require('./utils');
-const { kFileNotFoundError } = require('./constants');
+import { access, cp, readdir, readFile, writeFile } from 'fs/promises';
+import { exec } from 'child_process';
+import { basename, resolve, join } from 'path';
+import ParseGemini from 'gemini-to-html/parse.js';
+import RenderGemini from 'gemini-to-html/render.js';
+import { debuglog, promisify } from 'util';
+import { ensureDirectoryExists, rmIfExists } from './utils.js';
+import { kFileNotFoundError } from './constants.js';
// Generators for the Blog
-const StaticGenerator = require('./generators/static');
-const HTMLGenerator = require('./generators/html');
-const RSSGenerator = require('./generators/rss');
-const TXTGenerator = require('./generators/txt');
+import StaticGenerator from './generators/static.js';
+import HTMLGenerator from './generators/html.js';
+import RSSGenerator from './generators/rss.js';
+import TXTGenerator from './generators/txt.js';
// Archiving Methods
-const GemlogArchiver = require('./archivers/gemlog');
+import GemlogArchiver from './archivers/gemlog.js';
// Remote Handler
-const Remote = require('./remote');
+import Remote from './remote.js';
const internals = {
@@ -51,7 +49,7 @@ const internals = {
* @param {Blog.tConfiguration} config the initialization options to
* extend the instance
*/
-module.exports = class Blog {
+export default class Blog {
constructor(config) {
@@ -112,15 +110,15 @@ module.exports = class Blog {
internals.debuglog(`Publishing to ${host}`);
try {
- await internals.exec('which aws');
+ await internals.exec('which rsync');
}
catch (err) {
- console.error('Please install and configure AWS CLI to publish.');
+ console.error('Please install and configure rsync to publish.');
}
try {
- internals.debuglog(`Copying ephemeral blog from ${this.staticDirectory}`);
- await internals.exec(`rsync -r ${this.staticDirectory}/ ${host}`);
+ internals.debuglog(`Copying ephemeral blog from ${this.blogOutputDirectory}`);
+ await internals.exec(`rsync -r ${this.blogOutputDirectory}/ ${host}`);
}
catch (err) {
console.error('Failed to publish');
@@ -150,9 +148,8 @@ module.exports = class Blog {
}
try {
- const gemlogPath = resolve(join(__dirname, '../', '.gemlog'));
- internals.debuglog(`Copying archive from ${gemlogPath}`);
- await internals.exec(`rsync -r ${gemlogPath}/ ${host}`);
+ internals.debuglog(`Copying archive from ${this.archiveOutputDirectory}`);
+ await internals.exec(`rsync -r ${this.archiveOutputDirectory}/ ${host}`);
}
catch (err) {
console.error('Failed to publish archive');
@@ -171,6 +168,7 @@ module.exports = class Blog {
* @instance
*/
async addRemote(remote) {
+ await ensureDirectoryExists(this.configDirectory);
await Remote.add(this.remoteConfig, remote)
}
@@ -197,8 +195,8 @@ module.exports = class Blog {
*/
async syncDown() {
internals.debuglog('Pulling remote state');
- await ensureDirectoryExists(this.postsDirectory);
- await Remote.syncDown(this.remoteConfig, this.blogDirectory)
+ await ensureDirectoryExists(this.dataDirectory);
+ await Remote.syncDown(this.remoteConfig, this.dataDirectory)
internals.debuglog('Pulled remote state');
}
@@ -212,8 +210,8 @@ module.exports = class Blog {
*/
async syncUp() {
internals.debuglog('Pushing remote state');
- await ensureDirectoryExists(this.postsDirectory);
- await Remote.syncUp(this.remoteConfig, this.blogDirectory)
+ await ensureDirectoryExists(this.dataDirectory);
+ await Remote.syncUp(this.remoteConfig, this.dataDirectory)
internals.debuglog('Pushed remote state');
}
@@ -244,12 +242,24 @@ module.exports = class Blog {
const posts = await this._readPosts();
- await StaticGenerator(this.postsDirectory, this.staticDirectory, posts);
- await HTMLGenerator(this.templatesDirectory, this.staticDirectory, posts);
- await RSSGenerator(this.templatesDirectory, this.staticDirectory, posts);
- await TXTGenerator(this.templatesDirectory, this.staticDirectory, posts);
+ // Start from a clean slate.
+ await rmIfExists(this.blogOutputDirectory);
+ await ensureDirectoryExists(this.blogOutputDirectory);
+
+ // Run each generator
+ await StaticGenerator(this.staticDirectory, this.blogOutputDirectory, posts);
+ await HTMLGenerator(await this._templateDirectoryFor('index.html'), this.blogOutputDirectory, posts);
+ await RSSGenerator(await this._templateDirectoryFor('feed.xml'), this.blogOutputDirectory, posts);
+ await TXTGenerator(await this._templateDirectoryFor('index.txt'), this.blogOutputDirectory, posts);
+
+ // Start from a clean slate.
+ await rmIfExists(this.archiveOutputDirectory);
+ await ensureDirectoryExists(this.archiveOutputDirectory);
+ await ensureDirectoryExists(this.archiveDirectory);
- await GemlogArchiver(this.archiveDirectory);
+ // Run each archiver
+ await GemlogArchiver(await this._templateDirectoryFor('index.gmi'), this.archiveDirectory, this.archiveOutputDirectory);
+ // TODO: GopherArchiver
}
// Reads the posts into an array
@@ -410,4 +420,20 @@ module.exports = class Blog {
throw new Error(internals.strings.geminiNotFound);
}
+
+ // Gets the template directory for a given template.
+ async _templateDirectoryFor(template) {
+ try {
+ await access(join(this.templatesDirectory, template));
+ return this.templatesDirectory;
+ }
+ catch (error) {
+ if (error.code === kFileNotFoundError) {
+ internals.debuglog(`No custom template for ${template}`);
+ return this.defaultTemplatesDirectory;
+ }
+
+ throw error;
+ }
+ }
};
diff --git a/lib/constants.js b/lib/constants.js
index 9b4ce31..2142718 100644
--- a/lib/constants.js
+++ b/lib/constants.js
@@ -1,3 +1 @@
-module.exports = {
- kFileNotFoundError: 'ENOENT',
-};
+export const kFileNotFoundError = 'ENOENT';
diff --git a/lib/generators/html.js b/lib/generators/html.js
index 9579cb2..f7c7966 100644
--- a/lib/generators/html.js
+++ b/lib/generators/html.js
@@ -1,9 +1,9 @@
'use strict';
-const { template, templateSettings } = require('dot');
-const { readFile, writeFile } = require('fs/promises');
-const { join } = require('path');
-const { debuglog } = require('util');
+import Dot from 'dot';
+import { readFile, writeFile } from 'fs/promises';
+import { join } from 'path';
+import { debuglog } from 'util';
const internals = {
debuglog: debuglog('blog'),
@@ -19,7 +19,7 @@ const internals = {
* @param {string} target the target directory
* @param {Array.<Blog.tPost>} posts the list of posts
*/
-module.exports = async function HTMLGenerator(source, target, posts) {
+export default async function HTMLGenerator(source, target, posts) {
internals.debuglog('Generating HTML');
const indexTarget = join(target, internals.kIndexName);
@@ -29,8 +29,8 @@ module.exports = async function HTMLGenerator(source, target, posts) {
const indexTemplate = await readFile(indexLocation, { encoding: 'utf8' });
internals.debuglog('Writing HTML');
- const indexHtml = template(indexTemplate, {
- ...templateSettings,
+ const indexHtml = Dot.template(indexTemplate, {
+ ...Dot.templateSettings,
strip: false
})({ posts });
await writeFile(indexTarget, indexHtml);
diff --git a/lib/generators/rss.js b/lib/generators/rss.js
index 4ae3925..a46a394 100644
--- a/lib/generators/rss.js
+++ b/lib/generators/rss.js
@@ -1,10 +1,10 @@
'use strict';
-const { template, templateSettings } = require('dot');
-const { encodeXML } = require('entities');
-const { readFile, writeFile } = require('fs/promises');
-const { join } = require('path');
-const { debuglog } = require('util');
+import Dot from 'dot';
+import { encodeXML } from 'entities';
+import { readFile, writeFile } from 'fs/promises';
+import { join } from 'path';
+import { debuglog } from 'util';
const internals = {
debuglog: debuglog('blog'),
@@ -29,7 +29,7 @@ const internals = {
* @param {string} target the target directory
* @param {Array.<Blog.tPost>} posts the list of posts
*/
-module.exports = async function RSSGenerator(source, target, posts) {
+export default async function RSSGenerator(source, target, posts) {
internals.debuglog('Generating RSS');
const feedTarget = join(target, internals.kFeedName);
@@ -45,8 +45,8 @@ module.exports = async function RSSGenerator(source, target, posts) {
title: internals.extractTitle(post.raw),
html: encodeXML(post.html)
}));
- const feedXml = template(feedTemplate, {
- ...templateSettings,
+ const feedXml = Dot.template(feedTemplate, {
+ ...Dot.templateSettings,
strip: false
})({ posts });
await writeFile(feedTarget, feedXml);
diff --git a/lib/generators/static.js b/lib/generators/static.js
index 416076c..60719e2 100644
--- a/lib/generators/static.js
+++ b/lib/generators/static.js
@@ -1,10 +1,10 @@
'use strict';
-const { access, cp } = require('fs/promises');
-const { join } = require('path');
-const { debuglog } = require('util');
-const { rmIfExists } = require('../utils');
-const { kFileNotFoundError } = require('../constants');
+import { access, cp, readdir } from 'fs/promises';
+import { constants } from 'fs';
+import { join } from 'path';
+import { debuglog } from 'util';
+import { kFileNotFoundError } from '../constants.js';
const internals = {
debuglog: debuglog('blog'),
@@ -19,31 +19,31 @@ const internals = {
* @param {string} target the target directory
* @param {Array.<Blog.tPost>} posts the list of posts
*/
-module.exports = async function StaticGenerator(source, target, posts) {
+export default async function StaticGenerator(source, target, _) {
- const assetsTarget = join(target, internals.kAssetsDirectoryName);
+ try {
+ await access(source, constants.R_OK);
- internals.debuglog(`Removing ${assetsTarget}`);
- await rmIfExists(assetsTarget);
+ const entries = await readdir(source, { withFileTypes: true });
+ for (const entry of entries) {
+ const sourceAsset = join(source, entry.name);
+ const targetAsset = join(target, entry.name);
- for (let i = 0; i < posts.length; ++i) {
- const postSourcePath = join(source, `${i}`);
+ internals.debuglog(`Copying ${sourceAsset} to ${targetAsset}`);
- try {
- await access(postSourcePath);
-
- const assetsSource = join(postSourcePath, internals.kAssetsDirectoryName);
-
- internals.debuglog(`Copying ${assetsSource} to ${assetsTarget}`);
- await cp(assetsSource, assetsTarget, { recursive: true });
- }
- catch (error) {
- if (error.code === kFileNotFoundError) {
- internals.debuglog(`Skipping ${i}`);
- continue;
+ if (entry.isDirectory()) {
+ await cp(sourceAsset, targetAsset, { recursive: true });
+ } else {
+ await cp(sourceAsset, targetAsset);
}
-
- throw error;
}
}
+ catch (error) {
+ if (error.code === kFileNotFoundError) {
+ internals.debuglog(`No static directory found in ${source}`);
+ return;
+ }
+
+ throw error;
+ }
};
diff --git a/lib/generators/txt.js b/lib/generators/txt.js
index af5ec9c..dddcbaf 100644
--- a/lib/generators/txt.js
+++ b/lib/generators/txt.js
@@ -1,9 +1,9 @@
'use strict';
-const { template, templateSettings } = require('dot');
-const { readFile, writeFile } = require('fs/promises');
-const { join } = require('path');
-const { debuglog } = require('util');
+import Dot from 'dot';
+import { readFile, writeFile } from 'fs/promises';
+import { join } from 'path';
+import { debuglog } from 'util';
const internals = {
debuglog: debuglog('blog'),
@@ -19,7 +19,7 @@ const internals = {
* @param {string} target the target directory
* @param {Array.<Blog.tPost>} posts the list of posts
*/
-module.exports = async function TXTGenerator(source, target, posts) {
+export default async function TXTGenerator(source, target, posts) {
internals.debuglog('Generating TXT');
const textTarget = join(target, internals.kTextName);
@@ -29,10 +29,9 @@ module.exports = async function TXTGenerator(source, target, posts) {
const textTemplate = await readFile(textLocation, { encoding: 'utf8' });
internals.debuglog('Writing TXT');
- const text = template(textTemplate, {
- ...templateSettings,
+ const text = Dot.template(textTemplate, {
+ ...Dot.templateSettings,
strip: false
})({ posts });
await writeFile(textTarget, text);
};
-
diff --git a/lib/remote.js b/lib/remote.js
index 373958f..780ea91 100644
--- a/lib/remote.js
+++ b/lib/remote.js
@@ -1,16 +1,18 @@
-const { readFile, writeFile } = require('fs/promises');
-const { rmIfExists } = require('./utils');
+import { readFile, writeFile } from 'fs/promises';
+import { rmIfExists } from './utils.js';
+
+import GitStrategy from './remotes/git.js';
const internals = {
strings: {
configurationNotFound: 'Remote configuration not set, consult help for more info.'
},
strategies: [
- require('./remotes/git')
+ GitStrategy
]
};
-module.exports = {
+export default {
async add(remoteConfig, remote) {
await writeFile(remoteConfig, remote);
diff --git a/lib/remotes/git.js b/lib/remotes/git.js
index 32230ae..f6d0c07 100644
--- a/lib/remotes/git.js
+++ b/lib/remotes/git.js
@@ -1,12 +1,12 @@
-const { exec } = require('child_process');
-const { promisify } = require('util');
+import { exec } from 'child_process';
+import { promisify } from 'util';
const internals = {
// Promisified functions
exec: promisify(exec),
};
-module.exports = {
+export default {
canHandle() {
// For the future: actually check if it's a valid git url
diff --git a/lib/utils.js b/lib/utils.js
index 24b9407..25d204a 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -1,36 +1,34 @@
-const { access, constants, mkdir, rm } = require('fs/promises');
-const { kFileNotFoundError } = require('./constants');
+import { access, constants, mkdir, rm } from 'fs/promises';
+import { kFileNotFoundError } from './constants.js';
// File system utilities
-module.exports = {
- async rmIfExists(location) {
+export async function rmIfExists(location) {
- try {
- await access(location, constants.F_OK);
- await rm(location, { recursive: true });
+ try {
+ await access(location, constants.F_OK);
+ await rm(location, { recursive: true });
+ }
+ catch (error) {
+ if (error.code === kFileNotFoundError) {
+ return;
}
- catch (error) {
- if (error.code === kFileNotFoundError) {
- return;
- }
- throw error;
- }
- },
+ throw error;
+ }
+}
- async ensureDirectoryExists(directory) {
+export async function ensureDirectoryExists(directory) {
- try {
- await access(directory);
+ try {
+ await access(directory);
+ }
+ catch (error) {
+ if (error.code === kFileNotFoundError) {
+ await mkdir(directory, { recursive: true });
+ return;
}
- catch (error) {
- if (error.code === kFileNotFoundError) {
- await mkdir(directory, { recursive: true });
- return;
- }
- throw error;
- }
+ throw error;
}
-};
+}