Initial commit :P
This commit is contained in:
commit
815538cda6
|
@ -0,0 +1,4 @@
|
||||||
|
node_modules
|
||||||
|
.env
|
||||||
|
www
|
||||||
|
*.DS_Store
|
|
@ -0,0 +1,7 @@
|
||||||
|
Copyright 2024 Matthew McWilliams
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,3 @@
|
||||||
|
# photosite
|
||||||
|
|
||||||
|
Static site generator for building a simple photo site.
|
|
@ -0,0 +1,4 @@
|
||||||
|
INBOX="~/Photos/toprocess"
|
||||||
|
PHOTOS="~/Photos/photosite"
|
||||||
|
WWW="./www"
|
||||||
|
TEMPLATES="./views"
|
|
@ -0,0 +1,11 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
const log_1 = require("./log");
|
||||||
|
class Build {
|
||||||
|
constructor() {
|
||||||
|
this.log = (0, log_1.createLog)('build');
|
||||||
|
this.log.info(`Building site: ${new Date()}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new Build();
|
||||||
|
//# sourceMappingURL=build.js.map
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"build.js","sourceRoot":"","sources":["../src/build.ts"],"names":[],"mappings":";;AAAA,+BAAkC;AAGlC,MAAM,KAAK;IAEV;QACC,IAAI,CAAC,GAAG,GAAG,IAAA,eAAS,EAAC,OAAO,CAAC,CAAC;QAC9B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;IAC/C,CAAC;CACD;AAED,IAAI,KAAK,EAAE,CAAC"}
|
|
@ -0,0 +1,50 @@
|
||||||
|
'use strict';
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.createLog = void 0;
|
||||||
|
/** @module log */
|
||||||
|
/** Wrapper for winston that tags streams and optionally writes files with a simple interface. */
|
||||||
|
/** Module now also supports optional papertrail integration, other services to follow */
|
||||||
|
const winston_1 = require("winston");
|
||||||
|
const { SPLAT } = require('triple-beam');
|
||||||
|
const { isObject } = require('lodash');
|
||||||
|
const APP_NAME = process.env.APP_NAME || 'default';
|
||||||
|
let winstonPapertrail;
|
||||||
|
function formatObject(param) {
|
||||||
|
if (isObject(param)) {
|
||||||
|
return JSON.stringify(param);
|
||||||
|
}
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
const all = (0, winston_1.format)((info) => {
|
||||||
|
const splat = info[SPLAT] || [];
|
||||||
|
const message = formatObject(info.message);
|
||||||
|
const rest = splat.map(formatObject).join(' ');
|
||||||
|
info.message = `${message} ${rest}`;
|
||||||
|
return info;
|
||||||
|
});
|
||||||
|
const myFormat = winston_1.format.printf(({ level, message, label, timestamp }) => {
|
||||||
|
return `${timestamp} [${label}] ${level}: ${message}`;
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
* Returns a winston logger configured to service
|
||||||
|
*
|
||||||
|
* @param {string} label Label appearing on logger
|
||||||
|
* @param {string} filename Optional file to write log to
|
||||||
|
*
|
||||||
|
* @returns {object} Winston logger
|
||||||
|
*/
|
||||||
|
function createLog(label, filename = null) {
|
||||||
|
const tports = [new (winston_1.transports.Console)()];
|
||||||
|
const fmat = winston_1.format.combine(all(), winston_1.format.label({ label }), winston_1.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }), winston_1.format.colorize(), myFormat);
|
||||||
|
let papertrailOpts;
|
||||||
|
if (filename !== null) {
|
||||||
|
tports.push(new (winston_1.transports.File)({ filename }));
|
||||||
|
}
|
||||||
|
return (0, winston_1.createLogger)({
|
||||||
|
format: fmat,
|
||||||
|
transports: tports
|
||||||
|
});
|
||||||
|
}
|
||||||
|
exports.createLog = createLog;
|
||||||
|
module.exports = { createLog };
|
||||||
|
//# sourceMappingURL=index.js.map
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/log/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;;;AAEZ,kBAAkB;AAClB,iGAAiG;AACjG,yFAAyF;AAEzF,qCAA2D;AAC3D,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AACzC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvC,MAAM,QAAQ,GAAY,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,SAAS,CAAC;AAE5D,IAAI,iBAAiB,CAAC;AAEtB,SAAS,YAAY,CAAE,KAAW;IAChC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,GAAG,GAAG,IAAA,gBAAM,EAAC,CAAC,IAAU,EAAE,EAAE;IAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,CAAC,OAAO,GAAG,GAAG,OAAO,IAAI,IAAI,EAAE,CAAC;IACpC,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC,CAAC;AAEH,MAAM,QAAQ,GAAG,gBAAM,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAQ,EAAE,EAAE;IAC5E,OAAO,GAAG,SAAS,KAAK,KAAK,KAAK,KAAK,KAAK,OAAO,EAAE,CAAC;AACxD,CAAC,CAAC,CAAC;AAEH;;;;;;;EAOE;AACF,SAAgB,SAAS,CAAE,KAAc,EAAE,WAAoB,IAAI;IAC/D,MAAM,MAAM,GAAW,CAAE,IAAI,CAAC,oBAAU,CAAC,OAAO,CAAC,EAAE,CAAE,CAAC;IACtD,MAAM,IAAI,GAAS,gBAAM,CAAC,OAAO,CAC7B,GAAG,EAAE,EACL,gBAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,EACvB,gBAAM,CAAC,SAAS,CAAC,EAAC,MAAM,EAAE,yBAAyB,EAAC,CAAC,EACrD,gBAAM,CAAC,QAAQ,EAAE,EACjB,QAAQ,CACX,CAAC;IACF,IAAI,cAAoB,CAAC;IAEzB,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,CAAC,IAAI,CAAE,IAAI,CAAC,oBAAU,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAE,CAAC;IACvD,CAAC;IAED,OAAO,IAAA,sBAAY,EAAC;QAChB,MAAM,EAAG,IAAI;QACb,UAAU,EAAG,MAAM;KACtB,CAAC,CAAC;AACP,CAAC;AAnBD,8BAmBC;AAED,MAAM,CAAC,OAAO,GAAG,EAAE,SAAS,EAAE,CAAC"}
|
|
@ -0,0 +1,66 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Shell = void 0;
|
||||||
|
const child_process_1 = require("child_process");
|
||||||
|
const log_1 = require("../log");
|
||||||
|
const os_1 = require("os");
|
||||||
|
class Shell {
|
||||||
|
constructor(args, stdio = null, stderr = null, after = null, silent = false) {
|
||||||
|
this.lines = [];
|
||||||
|
this.stdio = null;
|
||||||
|
this.stderr = null;
|
||||||
|
this.after = null;
|
||||||
|
this.silent = false;
|
||||||
|
const bin = args.shift();
|
||||||
|
this.bin = bin;
|
||||||
|
this.args = args;
|
||||||
|
this.stdio = stdio;
|
||||||
|
this.stderr = stderr;
|
||||||
|
this.silent = silent;
|
||||||
|
this.after = after;
|
||||||
|
this.log = (0, log_1.createLog)(bin);
|
||||||
|
}
|
||||||
|
async execute() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.child = (0, child_process_1.spawn)(this.bin, this.args);
|
||||||
|
this.log.info(`Shell: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
this.child.stdout.on('data', (data) => {
|
||||||
|
if (!this.silent)
|
||||||
|
this.log.info(data);
|
||||||
|
if (this.after !== null)
|
||||||
|
this.lines.push(data);
|
||||||
|
if (this.stdio !== null) {
|
||||||
|
this.stdio(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.child.stderr.on('data', (data) => {
|
||||||
|
if (!this.silent)
|
||||||
|
this.log.warn(data);
|
||||||
|
if (this.stderr !== null) {
|
||||||
|
this.stderr(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.child.on('close', (code) => {
|
||||||
|
if (this.after !== null) {
|
||||||
|
this.after(this.lines.join(os_1.EOL));
|
||||||
|
}
|
||||||
|
if (code === 0) {
|
||||||
|
this.log.info(`Complete: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
return resolve(code);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.log.error(`Error executing: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
return reject(code);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
kill() {
|
||||||
|
this.log.warn(`Killing: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
//this.child.stdin.pause();
|
||||||
|
this.child.kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Shell = Shell;
|
||||||
|
module.exports = { Shell };
|
||||||
|
//# sourceMappingURL=index.js.map
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shell/index.ts"],"names":[],"mappings":"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"}
|
|
@ -0,0 +1,74 @@
|
||||||
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Templates = void 0;
|
||||||
|
const handlebars_1 = __importDefault(require("handlebars"));
|
||||||
|
const handlebars_helpers_1 = __importDefault(require("handlebars-helpers"));
|
||||||
|
const promises_1 = require("fs/promises");
|
||||||
|
const path_1 = require("path");
|
||||||
|
const log_1 = require("../log");
|
||||||
|
(0, handlebars_helpers_1.default)();
|
||||||
|
class Templates {
|
||||||
|
constructor(dir = './views') {
|
||||||
|
this.templates = {};
|
||||||
|
this.dir = dir;
|
||||||
|
this.log = (0, log_1.createLog)('tmpl');
|
||||||
|
}
|
||||||
|
async build() {
|
||||||
|
const partialsPath = (0, path_1.join)(this.dir, 'partials');
|
||||||
|
let partials = [];
|
||||||
|
let templates = [];
|
||||||
|
let text;
|
||||||
|
let name;
|
||||||
|
try {
|
||||||
|
partials = await (0, promises_1.readdir)(partialsPath);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.log.error(err);
|
||||||
|
}
|
||||||
|
partials = partials.map(el => (0, path_1.join)(partialsPath, el));
|
||||||
|
for (let partial of partials) {
|
||||||
|
name = (0, path_1.parse)((0, path_1.basename)(partial)).name;
|
||||||
|
try {
|
||||||
|
text = await (0, promises_1.readFile)(partial, 'utf8');
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.log.error(err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
handlebars_1.default.registerPartial(name, text);
|
||||||
|
this.log.info(`[partial] ${name}`);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
templates = await (0, promises_1.readdir)(this.dir);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.log.error(err);
|
||||||
|
}
|
||||||
|
templates = templates
|
||||||
|
.filter(el => el.indexOf('.hbs') !== -1 || el.indexOf('.handlebars') !== -1)
|
||||||
|
.map(el => (0, path_1.join)(this.dir, el));
|
||||||
|
for (let template of templates) {
|
||||||
|
name = (0, path_1.parse)((0, path_1.basename)(template)).name;
|
||||||
|
try {
|
||||||
|
text = await (0, promises_1.readFile)(template, 'utf8');
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
this.log.error(err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.templates[name] = handlebars_1.default.compile(text);
|
||||||
|
this.log.info(`[template] ${name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render(name, data) {
|
||||||
|
const keys = Object.keys(data);
|
||||||
|
this.log.info(`[render] ${name} with keys { ${keys.join(', ')} }`);
|
||||||
|
return this.templates[name](data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Templates = Templates;
|
||||||
|
module.exports = { Templates };
|
||||||
|
//# sourceMappingURL=index.js.map
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"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"}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"name": "photosite",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Static site generator for processing photos.",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "node test/",
|
||||||
|
"compile": "./node_modules/.bin/tsc -p tsconfig.json",
|
||||||
|
"build" : "bash scripts/build.sh",
|
||||||
|
"generate" : "bash scripts/generate.sh",
|
||||||
|
"all" : "bash scripts/generate.sh"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.sixteenmillimeter.com/mattmcw/photosite.git"
|
||||||
|
},
|
||||||
|
"author": "Matthew McWilliams",
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/handlebars-helpers": "^0.5.6",
|
||||||
|
"@types/lodash": "^4.14.202",
|
||||||
|
"@types/node": "^20.10.6",
|
||||||
|
"@types/sqlite3": "^3.1.11",
|
||||||
|
"@types/triple-beam": "^1.3.5",
|
||||||
|
"@types/winston": "^2.4.4",
|
||||||
|
"typescript": "^5.3.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"dotenv": "^16.3.1",
|
||||||
|
"handlebars": "^4.7.8",
|
||||||
|
"handlebars-helpers": "^0.10.0",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"mime": "^4.0.1",
|
||||||
|
"sqlite3": "^5.1.7",
|
||||||
|
"triple-beam": "^1.4.1",
|
||||||
|
"uuid": "^9.0.1",
|
||||||
|
"winston": "^3.11.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
node dist/generate
|
||||||
|
node dist/build
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
node dist/build
|
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
node dist/generate
|
|
@ -0,0 +1,8 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS photos {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS version {
|
||||||
|
id TEXT PRIMARY KEY,
|
||||||
|
updated INTEGER UNIQUE
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { createLog } from './log';
|
||||||
|
import type { Logger } from 'winston';
|
||||||
|
import { Templates } from './templates';
|
||||||
|
import { Database } from 'sqlite3'
|
||||||
|
|
||||||
|
class Build {
|
||||||
|
private log : Logger;
|
||||||
|
constructor () {
|
||||||
|
this.log = createLog('build');
|
||||||
|
this.log.info(`Building site: ${new Date()}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new Build();
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { createLog } from './log';
|
||||||
|
import type { Logger } from 'winston';
|
||||||
|
import { Shell } from './shell';
|
||||||
|
import { Database } from 'sqlite3';
|
||||||
|
|
||||||
|
class Generate {
|
||||||
|
private log : Logger;
|
||||||
|
constructor () {
|
||||||
|
this.log = createLog('generate');
|
||||||
|
this.log.info(`Generating site: ${new Date()}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new Generate();
|
|
@ -0,0 +1,63 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/** @module log */
|
||||||
|
/** Wrapper for winston that tags streams and optionally writes files with a simple interface. */
|
||||||
|
/** Module now also supports optional papertrail integration, other services to follow */
|
||||||
|
|
||||||
|
import { format, transports, createLogger } from 'winston';
|
||||||
|
const { SPLAT } = require('triple-beam');
|
||||||
|
const { isObject } = require('lodash');
|
||||||
|
|
||||||
|
const APP_NAME : string = process.env.APP_NAME || 'default';
|
||||||
|
|
||||||
|
let winstonPapertrail;
|
||||||
|
|
||||||
|
function formatObject (param : any) {
|
||||||
|
if (isObject(param)) {
|
||||||
|
return JSON.stringify(param);
|
||||||
|
}
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
|
const all = format((info : any) => {
|
||||||
|
const splat = info[SPLAT] || [];
|
||||||
|
const message = formatObject(info.message);
|
||||||
|
const rest = splat.map(formatObject).join(' ');
|
||||||
|
info.message = `${message} ${rest}`;
|
||||||
|
return info;
|
||||||
|
});
|
||||||
|
|
||||||
|
const myFormat = format.printf(({ level, message, label, timestamp } : any) => {
|
||||||
|
return `${timestamp} [${label}] ${level}: ${message}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a winston logger configured to service
|
||||||
|
*
|
||||||
|
* @param {string} label Label appearing on logger
|
||||||
|
* @param {string} filename Optional file to write log to
|
||||||
|
*
|
||||||
|
* @returns {object} Winston logger
|
||||||
|
*/
|
||||||
|
export function createLog (label : string, filename : string = null) {
|
||||||
|
const tports : any[] = [ new (transports.Console)() ];
|
||||||
|
const fmat : any = format.combine(
|
||||||
|
all(),
|
||||||
|
format.label({ label }),
|
||||||
|
format.timestamp({format: 'YYYY-MM-DD HH:mm:ss.SSS'}),
|
||||||
|
format.colorize(),
|
||||||
|
myFormat,
|
||||||
|
);
|
||||||
|
let papertrailOpts : any;
|
||||||
|
|
||||||
|
if (filename !== null) {
|
||||||
|
tports.push( new (transports.File)({ filename }) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return createLogger({
|
||||||
|
format : fmat,
|
||||||
|
transports : tports
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { createLog };
|
|
@ -0,0 +1,71 @@
|
||||||
|
import { spawn, ChildProcessWithoutNullStreams } from 'child_process';
|
||||||
|
import { createLog } from '../log';
|
||||||
|
import type { Logger } from 'winston';
|
||||||
|
import { EOL } from 'os';
|
||||||
|
|
||||||
|
export class Shell {
|
||||||
|
private child : ChildProcessWithoutNullStreams;
|
||||||
|
private log : Logger;
|
||||||
|
private bin : string;
|
||||||
|
private args : any[];
|
||||||
|
private lines : string[] = [];
|
||||||
|
private stdio : Function = null;
|
||||||
|
private stderr : Function = null;
|
||||||
|
private after : Function = null;
|
||||||
|
private silent : boolean = false;
|
||||||
|
|
||||||
|
constructor (args : any[], stdio : Function = null, stderr : Function = null, after : Function = null, silent : boolean = false) {
|
||||||
|
const bin : string = args.shift();
|
||||||
|
this.bin = bin;
|
||||||
|
this.args = args;
|
||||||
|
this.stdio = stdio;
|
||||||
|
this.stderr = stderr;
|
||||||
|
this.silent = silent;
|
||||||
|
this.after = after;
|
||||||
|
this.log = createLog(bin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async execute () : Promise<number> {
|
||||||
|
return new Promise((resolve : Function, reject : Function) => {
|
||||||
|
this.child = spawn(this.bin, this.args);
|
||||||
|
|
||||||
|
this.log.info(`Shell: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
|
||||||
|
this.child.stdout.on('data', (data : string) => {
|
||||||
|
if (!this.silent) this.log.info(data);
|
||||||
|
if (this.after !== null) this.lines.push(data);
|
||||||
|
if (this.stdio !== null) {
|
||||||
|
this.stdio(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.child.stderr.on('data', (data : string) => {
|
||||||
|
if (!this.silent) this.log.warn(data);
|
||||||
|
if (this.stderr !== null) {
|
||||||
|
this.stderr(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.child.on('close', (code : number) => {
|
||||||
|
if (this.after !== null) {
|
||||||
|
this.after(this.lines.join(EOL));
|
||||||
|
}
|
||||||
|
if (code === 0) {
|
||||||
|
this.log.info(`Complete: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
return resolve(code);
|
||||||
|
} else {
|
||||||
|
this.log.error(`Error executing: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
return reject(code);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public kill () {
|
||||||
|
this.log.warn(`Killing: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
//this.child.stdin.pause();
|
||||||
|
this.child.kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { Shell };
|
|
@ -0,0 +1,78 @@
|
||||||
|
import Handlebars from 'handlebars';
|
||||||
|
import helpers from 'handlebars-helpers';
|
||||||
|
import { readFile, readdir } from 'fs/promises';
|
||||||
|
import { join, parse, basename } from 'path';
|
||||||
|
import { createLog } from '../log';
|
||||||
|
import type { Logger } from 'winston';
|
||||||
|
|
||||||
|
helpers();
|
||||||
|
|
||||||
|
export class Templates {
|
||||||
|
private log : Logger;
|
||||||
|
private dir : string;
|
||||||
|
private templates : any = {};
|
||||||
|
|
||||||
|
constructor (dir : string = './views') {
|
||||||
|
this.dir = dir;
|
||||||
|
this.log = createLog('tmpl');
|
||||||
|
}
|
||||||
|
|
||||||
|
public async build () {
|
||||||
|
const partialsPath : string = join(this.dir, 'partials');
|
||||||
|
let partials : string[] = [];
|
||||||
|
let templates : string[] = [];
|
||||||
|
let text : string;
|
||||||
|
let name : string;
|
||||||
|
|
||||||
|
try {
|
||||||
|
partials = await readdir(partialsPath);
|
||||||
|
} catch (err) {
|
||||||
|
this.log.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
partials = partials.map(el => join(partialsPath, el));
|
||||||
|
|
||||||
|
for (let partial of partials) {
|
||||||
|
name = parse(basename(partial)).name;
|
||||||
|
try {
|
||||||
|
text = await readFile(partial, 'utf8');
|
||||||
|
} catch (err) {
|
||||||
|
this.log.error(err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Handlebars.registerPartial(name, text);
|
||||||
|
this.log.info(`[partial] ${name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
templates = await readdir(this.dir);
|
||||||
|
} catch (err) {
|
||||||
|
this.log.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
templates = templates
|
||||||
|
.filter(el => el.indexOf('.hbs') !== -1 || el.indexOf('.handlebars') !== -1)
|
||||||
|
.map(el => join(this.dir, el));
|
||||||
|
|
||||||
|
for (let template of templates) {
|
||||||
|
name = parse(basename(template)).name;
|
||||||
|
try {
|
||||||
|
text = await readFile(template, 'utf8');
|
||||||
|
} catch (err) {
|
||||||
|
this.log.error(err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.templates[name] = Handlebars.compile(text);
|
||||||
|
this.log.info(`[template] ${name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public render (name : string, data : any) : string {
|
||||||
|
const keys : string[] = Object.keys(data);
|
||||||
|
this.log.info(`[render] ${name} with keys { ${keys.join(', ')} }`);
|
||||||
|
return this.templates[name](data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { Templates };
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
require('./templates')
|
|
@ -0,0 +1,14 @@
|
||||||
|
const { createLog } = require('../dist/log');
|
||||||
|
const { Templates } = require('../dist/templates');
|
||||||
|
|
||||||
|
const log = createLog('tmpl-test');
|
||||||
|
|
||||||
|
(async function main () {
|
||||||
|
const tmpl = new Templates('./views');
|
||||||
|
try {
|
||||||
|
await tmpl.build();
|
||||||
|
} catch (err) {
|
||||||
|
log.error(err);
|
||||||
|
}
|
||||||
|
log.info(tmpl.render('index', { body : 'test' }));
|
||||||
|
})()
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"target": "ES2020",
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"sourceMap": true,
|
||||||
|
"removeComments" : false,
|
||||||
|
"baseUrl" : "dist",
|
||||||
|
"outDir": "./dist/",
|
||||||
|
"rootDir" : "./src/",
|
||||||
|
"paths" : {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exclude" : [
|
||||||
|
"./dist"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{{> head}}
|
||||||
|
{{{body}}}
|
||||||
|
{{> foot}}
|
|
@ -0,0 +1,5 @@
|
||||||
|
<script src="/js/script.js"></script>
|
||||||
|
<script>
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>{{title}}</title>
|
||||||
|
<link href="/css/style.css" rel="stylesheet" />
|
||||||
|
</head>
|
||||||
|
<body>
|
Loading…
Reference in New Issue