commit 7e0c8c4f9399cecc0471523ddb79cdb506827ea4
Author: William Casarin <jb55@jb55.com>
Date: Tue, 26 Oct 2021 21:49:27 -0700
let's do this
Diffstat:
6 files changed, 171 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1 @@
+node_modules
diff --git a/.rgignore b/.rgignore
@@ -0,0 +1 @@
+node_modules
diff --git a/gemfedwiki b/gemfedwiki
@@ -0,0 +1,23 @@
+#!/usr/bin/env node
+
+const fs = require('fs')
+
+const gemfedwiki = require('./')
+
+const cert = read_pem('cert.pem')
+const key = read_pem('key.pem')
+const passphrase = process.env.PASSPHRASE
+
+const server = gemfedwiki({cert, key, passphrase})
+const port = process.env.PORT || 1965
+
+server.listen(port)
+console.log(`gemfedwiki server listening on 0.0.0.0:${port}`)
+
+function read_pem(filename)
+{
+ if (!fs.existsSync(filename))
+ throw new Error(`Couldn't load ${filename}`)
+
+ return fs.readFileSync(filename)
+}
diff --git a/index.gmi b/index.gmi
@@ -0,0 +1,6 @@
+# fed.wiki gemini portal
+
+Welcome to the fediwiki gemini portal. Here are some interesting links to get you started
+
+=> /fed.wiki.org
+=> /dayton.fed.wiki The Dayton Experiment Hyperbook
diff --git a/index.js b/index.js
@@ -0,0 +1,117 @@
+const request = require('superagent')
+const fs = require('fs')
+const {createServer} = require('@derhuerst/gemini')
+
+function push_paragraph(lines, text)
+{
+ lines.push('')
+ lines.push(text)
+}
+
+function slugify(text)
+{
+ return text.toLowerCase().split(/\s+/).join('-')
+}
+
+function parse_links(text)
+{
+ let links = []
+ const matches = text.matchAll(/\[\[([^\]]+)\]\]/g)
+ for (const match of matches) {
+ let [slug, name] = match[1].split(":").map(t => t.trim())
+ if (name == null)
+ name = slug
+ slug = slugify(slug)
+ links.push({slug, name})
+ }
+
+ return links
+}
+
+function process_item(root, lines, item)
+{
+ if (item.type === 'paragraph' || item.type === 'markdown') {
+ const text = item.text.trim()
+ const links = parse_links(text)
+
+ lines.push('')
+ lines.push(text)
+
+ if (links.length !== 0)
+ lines.push('')
+
+ for (const {slug, name} of links) {
+ lines.push(`=> ${root}/${slug} ${name}`)
+ }
+ }
+}
+
+function fedwiki2gmi(root, article)
+{
+ let lines = []
+ lines.push(`# ${article.title}`)
+
+ for (const item of article.story) {
+ process_item(root, lines, item)
+ }
+
+ return lines.join("\n") + "\n"
+}
+
+function last(arr)
+{
+ if (arr.length === 0)
+ return null
+ return arr[arr.length - 1]
+}
+
+async function make_request(json_url, root="")
+{
+ const res = await request.get(json_url)
+ return fedwiki2gmi(root, res.body)
+}
+
+async function make_index_request(host, root="")
+{
+ const res = await request.get(host + '/')
+ const file = last(res.redirects)
+ const json = file.replace(/.html$/, ".json")
+ return await make_request(json, root)
+}
+
+async function handle_request(req, res)
+{
+ console.log(req.path)
+
+ if (req.path === "/") {
+ fs.readFile("index.gmi", (err, dat) => {
+ res.end(dat)
+ })
+ return
+ }
+
+ const indreq = req.path.match(/^\/([^/]+)\/?$/)
+ if (indreq) {
+ const gmi = await make_index_request(indreq[1], "/" + indreq[1])
+ res.end(gmi)
+ return
+ }
+
+ const pathreq = req.path.match(/\/([^/]+)\/(.*)$/)
+ if (!pathreq) return res.gone()
+
+ const host = pathreq[1]
+ const slug = pathreq[2]
+ const url = host + "/" + slug + ".json"
+ const gmi = await make_request(url, "/" + host)
+
+ res.end(gmi)
+}
+
+function serve(opts)
+{
+ // opts = { cert, key, passphrase }
+ return createServer(opts, handle_request)
+}
+
+module.exports = serve
diff --git a/package.json b/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "gemfedwiki",
+ "description": "fedwiki to gemini",
+ "version": "0.1.0",
+ "repository": {
+ "url": "http://git.jb55.com/gemfedwiki"
+ },
+ "main": "index.js",
+ "scripts": {
+ "test": "tap test/*.js"
+ },
+ "bin": {
+ "gemfedwiki": "./gemfedwiki"
+ },
+ "dependencies": {
+ "@derhuerst/gemini": "^1.2.0",
+ "stdin": "0.0.1",
+ "superagent": "^6.1.0"
+ },
+ "devDependencies": {
+ "tap": "~0.2.5"
+ }
+}