Rework to use plugins

master
kts of kettek (yan) 2021-05-18 02:33:08 -07:00
parent 48a631395d
commit 0f38865c26
15 changed files with 1307 additions and 2180 deletions

140
index.js
View File

@ -5,51 +5,131 @@ constructed from a collection of md and configuration files in a git repository
located at `srd`.
*/
/* ==== REQUIRES ============================================================ */
var express = require('express');
var doT = require('dot');
var path = require('path');
const express = require('express')
const doT = require('dot')
const path = require('path')
const fs = require('fs')
/* ==== CONFIGURATION ======================================================= */
var app = express();
const exp = express()
const app = {
config: {
srd: 'srd',
plugins: {},
},
live: {
dictionary: {},
conf: {},
menu: '',
},
express: exp,
}
var pub = __dirname + '/public';
var views = __dirname + '/views';
var routes = __dirname + '/routes';
const pub = __dirname + '/public'
const views = __dirname + '/views'
const routes = __dirname + '/routes'
var dot = doT.process({'path': views});
const dot = doT.process({'path': views})
app.use(express.static(pub));
app.use(express.static(__dirname + '/srd'));
app.engine('dot', function(template, options, cb) {
return cb(null, dot[path.parse(template).name](options));
});
try {
app.config = {...app.config, ...require(__dirname + '/config.js')}
} catch(err) {
if (err.code === 'MODULE_NOT_FOUND') {
console.error('missing config')
}
}
exp.use(express.static(pub))
exp.use(express.static(path.join(__dirname, app.config.srd)))
exp.engine('dot', (template, options, cb) => {
return cb(null, dot[path.parse(template).name](options))
})
app.set('views', views);
app.set('view engine', 'dot');
exp.set('views', views)
exp.set('view engine', 'dot')
/* ==== PLUGINS ============================================================= */
const plugins = []
try {
fs.readdirSync('plugins').forEach(f => {
let plugin_path = path.resolve('plugins', f)
if (fs.lstatSync(plugin_path).isDirectory()) {
console.log('plugin preload:', f)
try {
let plugin = {
defaults: null,
config: {},
log: (...args) => {
console.log.apply(console, [f+':', ...args])
},
error: (...args) => {
console.error.apply(console, [f+':', ...args])
},
module: require(plugin_path),
}
if (app.config.plugins[f]) {
plugin.config = app.config.plugins[f]
}
plugin.defaults = o => {
plugin.config = {...o, ...plugin.config}
}
console.log('...ok')
plugins.push(plugin)
} catch(err) {
if (err.code === 'MODULE_NOT_FOUND') {
console.error('plugin', plugin_path, 'is not a valid module')
} else {
console.error('...fail: ', err)
}
}
}
})
if (plugins.length === 0) {
console.warn('no plugins found');
}
} catch(err) {
if (err.code === 'ENOENT') {
console.warn('no plugins directory')
} else {
console.error('plugins', err)
}
}
/* ==== CMDLINE ============================================================= */
var port = 7331;
process.argv.forEach(function(val, index, array) {
var parts = val.split('=');
var key = '';
var value = '';
const port = 7331
process.argv.forEach((val, index, array) => {
let parts = val.split('=')
let key = ''
let value = ''
if (parts[0].substr(0, 2) == '--') {
key = parts[0].substr(2);
value = parts[1];
key = parts[0].substr(2)
value = parts[1]
}
if (key == 'port') {
if (value != '') {
port = Number(value);
port = Number(value)
}
}
});
})
/* ==== RUN ================================================================= */
var server = app.listen(port, function() {
var host = server.address().address;
var port = server.address().port;
const server = exp.listen(port, async () => {
const host = server.address().address
const port = server.address().port
app.use('/', require(routes+'/index.js'));
app.use('/search', require(routes+'/search.js'));
});
for (let plugin of plugins) {
try {
await plugin.module(plugin, app)
} catch(err) {
console.error('plugin', err)
}
}
})
process.on('SIGINT', () => {
process.exit()
})
process.on('exit', () => {
fs.writeFileSync(path.join(__dirname + '/config.js'), 'module.exports = ' + JSON.stringify(app.config, null, '\t'))
})

2467
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
{
"name": "celestial-site",
"name": "srd-site",
"version": "1.0.0",
"description": "Website for the Celestial SRD",
"description": "SRD Wiki Software",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
@ -9,16 +9,7 @@
"author": "",
"license": "GPLv3",
"dependencies": {
"chokidar": "^2.1.1",
"dot": "^1.0.3",
"express": "^4.14.0",
"file-set": "^2.0.1",
"i18n": "^0.8.3",
"markdown-it": "^8.0.1",
"markdown-it-anchor": "^5.0.2",
"markdown-it-custom-block": "^0.1.1",
"markdown-it-header-sections": "^1.0.0",
"markdown-it-title": "^1.0.4",
"memory-cache": "^0.1.6"
"express": "^4.14.0"
}
}

View File

@ -0,0 +1,23 @@
module.exports = async (plugin, app) => {
plugin.defaults({
"interval": 30 * 1000,
})
const sgit = require('simple-git')(app.config.srd)
async function update() {
try {
await sgit.pull()
} catch(err) {
plugin.error(err)
}
}
if (await sgit.checkIsRepo()) {
await update()
plugin.log('updating every', plugin.config['interval'] + 'ms')
setInterval(update, plugin.config['interval'])
} else {
plugin.error('target directory is not a git repository')
}
}

View File

@ -0,0 +1,97 @@
{
"name": "auto-git-updater",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.0.0",
"license": "GPL-3.0",
"dependencies": {
"simple-git": "^2.39.0"
}
},
"node_modules/@kwsites/file-exists": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
"integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==",
"dependencies": {
"debug": "^4.1.1"
}
},
"node_modules/@kwsites/promise-deferred": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz",
"integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw=="
},
"node_modules/debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/simple-git": {
"version": "2.39.0",
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.39.0.tgz",
"integrity": "sha512-VOsrmc3fpp1lGVIpo+1SKNqJzrdVJeSGZCeenPKnJPNo5UouAlSkWFc037pfm9wRYtfxBdwp2deVJGCG8J6C8A==",
"dependencies": {
"@kwsites/file-exists": "^1.1.1",
"@kwsites/promise-deferred": "^1.1.1",
"debug": "^4.3.1"
}
}
},
"dependencies": {
"@kwsites/file-exists": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
"integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==",
"requires": {
"debug": "^4.1.1"
}
},
"@kwsites/promise-deferred": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz",
"integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw=="
},
"debug": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"requires": {
"ms": "2.1.2"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"simple-git": {
"version": "2.39.0",
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.39.0.tgz",
"integrity": "sha512-VOsrmc3fpp1lGVIpo+1SKNqJzrdVJeSGZCeenPKnJPNo5UouAlSkWFc037pfm9wRYtfxBdwp2deVJGCG8J6C8A==",
"requires": {
"@kwsites/file-exists": "^1.1.1",
"@kwsites/promise-deferred": "^1.1.1",
"debug": "^4.3.1"
}
}
}
}

View File

@ -0,0 +1,15 @@
{
"name": "auto-git-updater",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "GPL-3.0",
"dependencies": {
"simple-git": "^2.39.0"
}
}

View File

@ -0,0 +1,5 @@
const path = require('path')
module.exports = (plugin, app) => {
app.express.use(require('./route.js')(plugin, app))
}

View File

@ -0,0 +1,141 @@
{
"name": "router",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "router",
"version": "1.0.0",
"license": "GPL-3.0",
"dependencies": {
"markdown-it": "^12.0.6",
"markdown-it-anchor": "^7.1.0",
"markdown-it-title": "^3.0.0",
"memory-cache": "^0.2.0"
}
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/entities": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
"integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==",
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/linkify-it": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz",
"integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==",
"dependencies": {
"uc.micro": "^1.0.1"
}
},
"node_modules/markdown-it": {
"version": "12.0.6",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.6.tgz",
"integrity": "sha512-qv3sVLl4lMT96LLtR7xeRJX11OUFjsaD5oVat2/SNBIb21bJXwal2+SklcRbTwGwqWpWH/HRtYavOoJE+seL8w==",
"dependencies": {
"argparse": "^2.0.1",
"entities": "~2.1.0",
"linkify-it": "^3.0.1",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
},
"bin": {
"markdown-it": "bin/markdown-it.js"
}
},
"node_modules/markdown-it-anchor": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-7.1.0.tgz",
"integrity": "sha512-loQggrwsIkkP7TOrESvmYkV2ikbQNNKhHcWyqC7/C2CmfHl1tkUizJJU8C5aGgg7J6oXVQJx17gk7i47tNn/lQ==",
"peerDependencies": {
"markdown-it": "*"
}
},
"node_modules/markdown-it-title": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/markdown-it-title/-/markdown-it-title-3.0.0.tgz",
"integrity": "sha512-iHZptfptAXGJlcboqWxUSWNkJLUyxZ452CobBzkQ7MtwfVhTI77W1LTAy+miQTqo3U+wkDUOFhhXj2XUD0dVWQ=="
},
"node_modules/mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
},
"node_modules/memory-cache": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz",
"integrity": "sha1-eJCwHVLADI68nVM+H46xfjA0hxo="
},
"node_modules/uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
}
},
"dependencies": {
"argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"entities": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.1.0.tgz",
"integrity": "sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w=="
},
"linkify-it": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-3.0.2.tgz",
"integrity": "sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ==",
"requires": {
"uc.micro": "^1.0.1"
}
},
"markdown-it": {
"version": "12.0.6",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-12.0.6.tgz",
"integrity": "sha512-qv3sVLl4lMT96LLtR7xeRJX11OUFjsaD5oVat2/SNBIb21bJXwal2+SklcRbTwGwqWpWH/HRtYavOoJE+seL8w==",
"requires": {
"argparse": "^2.0.1",
"entities": "~2.1.0",
"linkify-it": "^3.0.1",
"mdurl": "^1.0.1",
"uc.micro": "^1.0.5"
}
},
"markdown-it-anchor": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-7.1.0.tgz",
"integrity": "sha512-loQggrwsIkkP7TOrESvmYkV2ikbQNNKhHcWyqC7/C2CmfHl1tkUizJJU8C5aGgg7J6oXVQJx17gk7i47tNn/lQ==",
"requires": {}
},
"markdown-it-title": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/markdown-it-title/-/markdown-it-title-3.0.0.tgz",
"integrity": "sha512-iHZptfptAXGJlcboqWxUSWNkJLUyxZ452CobBzkQ7MtwfVhTI77W1LTAy+miQTqo3U+wkDUOFhhXj2XUD0dVWQ=="
},
"mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
},
"memory-cache": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz",
"integrity": "sha1-eJCwHVLADI68nVM+H46xfjA0hxo="
},
"uc.micro": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz",
"integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA=="
}
}
}

View File

@ -0,0 +1,18 @@
{
"name": "router",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "GPL-3.0",
"dependencies": {
"markdown-it": "^12.0.6",
"markdown-it-anchor": "^7.1.0",
"markdown-it-title": "^3.0.0",
"memory-cache": "^0.2.0"
}
}

View File

@ -0,0 +1,78 @@
const router = require('express').Router()
const mcache = require('memory-cache')
const md = require('markdown-it')({ typographer: true })
md.use(require('markdown-it-anchor'), {permalink: true, level: 2, permalinkBefore: true, permalinkSymbol: "§"})
md.use(require('markdown-it-title'), 0)
const fs = require('fs')
const path = require('path')
module.exports = (plugin, app) => {
const cache = function(duration) {
return function(req, res, next) {
let key = '__'+app.live.conf['shortname']+'__' + req.originalUrl || req.url
let cached = mcache.get(key)
if (cached) {
res.send(cached)
return
} else {
res.sendResponse = res.send
res.send = function(body) {
mcache.put(key, body, duration * 60 * 1000 )
res.sendResponse(body)
}
next()
}
}
}
router.get('*', cache(1), function(req, res) {
let target = req.path
if (target === "/") { // Root
target = '/index'
} else if (target.charAt(target.length-1) == '/') { // Directory Index
target = target.substring(0, target.length-1)
}
let file = path.join(app.config.srd, target+'.md')
let crumbs = target.split('/')
fs.readFile(file, (err, data) => {
if (err) {
res.render('index', {content: '404', menu: app.live.menu, location: '404', title: '404', www_name: app.live.conf.www_name, www_copyright: app.live.conf.www_copyright })
return
//throw err
}
// make a local copy of our dictionary and remove the current page, if existing
let local_dictionary = Object.assign({}, app.dictionary)
delete local_dictionary[crumbs[crumbs.length-1]]
let text
if (Object.keys(local_dictionary).length !== 0) {
// replace words using our local dictionary
let regexp = RegExp ('[^\[(]\\b(' + Object.keys (local_dictionary).join ('|') + ')\\b', 'g')
text = data.toString().replace(regexp, function (_, word) { return _.charAt(0)+local_dictionary[word] })
} else {
text = data.toString()
}
// render out the md
let env = {}
let rendered = md.render(text, env)
// build the location
let loc = '<a href="/">'+app.live.conf['shortname']+'</a>'
for (let i = 1; i < crumbs.length; i++) {
if (crumbs[i] == '') continue
loc += ' &#8594 <a href="'+crumbs.slice(0,i).join('/')+'/'+crumbs[i]+'">'+(i == crumbs.length-1 ? env.title : crumbs[i].replace('-', ' '))+'</a>'
}
let title = env.title
// render with the engine
res.render('index', {content: rendered, menu: app.live.menu, location: loc, title: (title != 'index' ? title : ''), www_name: app.live.conf.www_name, www_copyright: app.live.conf.www_copyright })
})
})
return router
}

View File

@ -0,0 +1,31 @@
const path = require('path')
const chokidar = require('chokidar')
// Watch the srd/sys directory and reload config on changes.
module.exports = async (plugin, app) => {
const sys_path = path.resolve(path.join(app.config.srd, 'sys'))
const dpath = path.join(sys_path, 'dictionary.js')
const cpath = path.join(sys_path, 'conf.js')
const mpath = path.join(sys_path, 'menu.js')
const refresh = () => {
delete require.cache[dpath]
delete require.cache[cpath]
delete require.cache[mpath]
app.live = {
...app.live,
dictionary: require(dpath),
conf: require(cpath),
menu: require(mpath),
}
}
refresh()
const watcher = chokidar.watch(sys_path, {persistent: true})
watcher.on('change', p => {
refresh()
})
plugin.log('watching', sys_path)
}

View File

@ -0,0 +1,293 @@
{
"name": "sys-watcher",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"version": "1.0.0",
"license": "GPL-3.0",
"dependencies": {
"chokidar": "^3.5.1"
}
},
"node_modules/anymatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
"engines": {
"node": ">=8"
}
},
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"dependencies": {
"fill-range": "^7.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/chokidar": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
"integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
"dependencies": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.5.0"
},
"engines": {
"node": ">= 8.10.0"
},
"optionalDependencies": {
"fsevents": "~2.3.1"
}
},
"node_modules/fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dependencies": {
"binary-extensions": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"dependencies": {
"is-extglob": "^2.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/picomatch": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz",
"integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==",
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/readdirp": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
}
},
"dependencies": {
"anymatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
}
},
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
},
"braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
"requires": {
"fill-range": "^7.0.1"
}
},
"chokidar": {
"version": "3.5.1",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz",
"integrity": "sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==",
"requires": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.3.1",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.5.0"
}
},
"fill-range": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
"requires": {
"to-regex-range": "^5.0.1"
}
},
"fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"optional": true
},
"glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"requires": {
"is-glob": "^4.0.1"
}
},
"is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"requires": {
"binary-extensions": "^2.0.0"
}
},
"is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
},
"is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"requires": {
"is-extglob": "^2.1.1"
}
},
"is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
},
"normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
},
"picomatch": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz",
"integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg=="
},
"readdirp": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
"requires": {
"picomatch": "^2.2.1"
}
},
"to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"requires": {
"is-number": "^7.0.0"
}
}
}
}

View File

@ -0,0 +1,15 @@
{
"name": "sys-watcher",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "GPL-3.0",
"dependencies": {
"chokidar": "^3.5.1"
}
}

View File

@ -1,139 +0,0 @@
var router = require('express').Router();
var mcache = require('memory-cache');
var FileSet = require('file-set');
var md = require('markdown-it')({ typographer: true });
md.use(require('markdown-it-anchor'), {permalink: true, level: 2, permalinkBefore: true, permalinkSymbol: "§"});
md.use(require('markdown-it-title'), 0);
md.use(require('markdown-it-custom-block'), {
importTable: function(arg) {
/*var filepath = arg.substring(0, arg.indexOf(' '));
var fileset = new FileSet(path.join('srd', filepath));
for (var i = 0; i < fileset.files.length; i++) {
var data = fs.readFileSync(fileset.files[i], { encoding: 'utf8' });
var parsed = md.parse(data);
var args = arg.substring(filepath.length).split(' ');
var parts = {}
for (var j = 0; j < args.length; j++) {
var key = args[j].substring(0, args[j].indexOf('='));
var value = args[j].substring(key.length+1);
parts[key] = value;
}
console.log(parts);
var table = {}
var state = 0;
for (var j = 0; j < parsed.length; j++) {
switch(state) {
case 0:
if (parsed[j].type == 'heading_open') {
state = 1;
}
break;
case 1:
if (parsed[j].type == 'heading_close') {
state = 2;
} else if (parsed[j].type == 'inline') {
table.title = parsed[j].content;
}
break;
}
}
console.log(fileset.files[i]);
//console.log(parsed);
}
console.log(fileset)*/
return '';
}
});
var fs = require('fs');
var path = require('path');
var chokidar = require('chokidar');
var dictionary = require('../srd/sys/dictionary.js');
var conf = require('../srd/sys/conf.js');
var menu = require('../srd/sys/menu.js');
var cache = function(duration) {
return function(req, res, next) {
var key = '__'+conf['shortname']+'__' + req.originalUrl || req.url;
var cached = mcache.get(key);
if (cached) {
res.send(cached);
return;
} else {
res.sendResponse = res.send;
res.send = function(body) {
mcache.put(key, body, duration * 60 * 1000 );
res.sendResponse(body);
}
next();
}
}
};
router.get('*', cache(1), function(req, res) {
var target = req.path;
if (target === "/") { // Root
target = '/index';
} else if (target.charAt(target.length-1) == '/') { // Directory Index
target = target.substring(0, target.length-1);
}
var file = path.join(__dirname, '..', 'srd', target+'.md');
var crumbs = target.split('/');
fs.readFile(file, (err, data) => {
if (err) {
res.render('index', {content: '404'});
return;
//throw err;
}
// make a local copy of our dictionary and remove the current page, if existing
var local_dictionary = Object.assign({}, dictionary);
delete local_dictionary[crumbs[crumbs.length-1]];
var text;
if (Object.keys(local_dictionary).length !== 0) {
// replace words using our local dictionary
var regexp = RegExp ('[^\[(]\\b(' + Object.keys (local_dictionary).join ('|') + ')\\b', 'g');
text = data.toString().replace(regexp, function (_, word) { return _.charAt(0)+local_dictionary[word]; });
} else {
text = data.toString();
}
// render out the md
var env = {}
var rendered = md.render(text, env);
// build the location
var loc = '<a href="/">'+conf['shortname']+'</a>';
for (var i = 1; i < crumbs.length; i++) {
if (crumbs[i] == '') continue;
loc += ' &#8594; <a href="'+crumbs.slice(0,i).join('/')+'/'+crumbs[i]+'">'+(i == crumbs.length-1 ? env.title : crumbs[i].replace('-', ' '))+'</a>';
}
//var title = crumbs[crumbs.length-1].replace('-', ' ');
var title = env.title
// render with the engine
res.render('index', {content: rendered, menu: menu, location: loc, title: (title != 'index' ? title : ''), www_name: conf.www_name, www_copyright: conf.www_copyright });
});
});
// watch the sys folder and reload requires on change
var watcher = chokidar.watch('../srd/sys/', {ignored: /^./, persistent: true});
watcher.on('change', function(path) {
console.log('Reloading sys files');
delete require.cache['../srd/sys/dictionary.js'];
delete require.cache['../srd/sys/conf.js'];
delete require.cache['../srd/sys/menu.js'];
dictionary = require('../srd/sys/dictionary.js');
conf = require('../srd/sys/conf.js');
menu = require('../srd/sys/menu.js');
});
module.exports = router;

View File

@ -1,10 +0,0 @@
var router = require('express').Router();
router.get('/', function(req, res) {
res.render('search', {title: 'Search', location: 'Search'});
});
router.post('/', function(req, res) {
res.render('search', {title: 'Search', location: 'Search', content: 'Search Results:'});
});
module.exports = router;