commit 8c024d74cda56f2a9133dbfb9648551936ba942d Author: Eric Woodward Date: Fri Sep 23 02:40:26 2022 -0400 Major update - simpler file structure, better layouts, moar content diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..622a699 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +out/ +IDEAS.md +TODO.md diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..7d1b5f5 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +*.ejs +*.min.js diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..de354ad --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018 Douglas Matoso + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..5bd5c1c --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +# Mystic Site Builder (2021 Edition) + +Micro static site generator in Node.js + +Based on the ideas in this post: https://medium.com/douglas-matoso-english/build-static-site-generator-nodejs-8969ebe34b22 + +## Setup + +```console +$ npm i +$ npm run build +$ npm run serve +``` + +Go to http://localhost:5000 to see the generated site. + +## How to use + +If you want to use NanoGen to generate your own site, just fork this repository and add your content to the `src` folder. diff --git a/app.js b/app.js new file mode 100644 index 0000000..c805e94 --- /dev/null +++ b/app.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +"use strict"; + +require("dotenv").config(); + +const path = require("path"), + build = require("./lib/build"), + serve = require("./lib/serve"), + watch = require("./lib/watch"), + { log, readJsonIfExists } = require("./lib/utils"), + { version } = require("./package.json"), + localConfig = + readJsonIfExists(path.resolve(process.cwd(), "site.config.json5")) || + {}, + siteOpts = require("./lib/loadConfig")(localConfig, "MULE"), + config = { + ...siteOpts, + logFunction: log, + }, + yargs = require("yargs") + .version(version) + .alias("v", "version") + .usage("Usage: $0 start|stop") + .demandCommand(1), + { argv } = yargs; + +if (argv._[0] === "build") return build(config); +else if (argv._[0] === "serve") return serve(config); +else if (argv._[0] === "watch") return watch(config); diff --git a/lib/build.js b/lib/build.js new file mode 100644 index 0000000..39537ba --- /dev/null +++ b/lib/build.js @@ -0,0 +1,370 @@ +const { exists } = require("fs-extra/lib/fs"); + +module.exports = async (config) => { + const { promises: fs } = require("fs"), + fse = require("fs-extra"), + path = require("path"), + ejs = require("ejs"), + frontMatter = require("front-matter"), + glob = require("glob"), + hljs = require("highlight.js"), + md = require("markdown-it")({ + highlight: (str, lang) => { + if (lang && hljs.getLanguage(lang)) { + try { + return hljs.highlight(str, { language: lang }).value; + } catch (__) {} + } + + return ""; // use external default escaping + }, + html: true, + linkify: true, + typographer: true, + xhtmlOut: true, + }), + emoji = require("markdown-it-emoji"), + // { readJsonIfExists } = require("./utils"), + { build, isRebuild, logFunction: log = () => {} } = config || {}, + { outputPath, journalsPerPage = 5, srcPath } = build, + { site } = config, + copyAssets = async (directory) => { + const assets = await fs.readdir(directory); + + assets.forEach(async (asset) => { + // we no longer merge scripts and styles, thanks to http/2's parallel file handling + if (asset === "_root") { + fse.copy(path.join(srcPath, "assets", asset), outputPath); + } else { + fse.copy( + path.join(srcPath, "assets", asset), + path.join(outputPath, asset) + ); + } + }); + }, + getReadTime = (text) => { + const WPM = 275, + fixedString = text.replace(/[^\w\s]+/g, ""), + count = fixedString.split(/\s+/).length; + + if (count < WPM) return "less than 1 minute"; + else return `${Math.ceil(count / WPM)} minutes`; + }, + tagSorter = (a, b) => a.toLowerCase().localeCompare(b.toLowerCase()), + parseFile = (file, pagePath, siteData, isSupport) => { + const { dir, ext, name } = path.parse(file) || {}, + hasExt = name.indexOf(".") > -1, + destPath = path.join(outputPath, dir), + filePath = path.join(pagePath, file), + // read page file + data = fse.readFileSync(filePath, "utf-8"), + // render page + { attributes, body } = frontMatter(data), + { content_type: contentType, tags: originalTags = [] } = + attributes, + // TODO: Look for tags in posts as well, link to them, and add them to tag pages + tags = + typeof originalTags === "string" + ? originalTags.split(/\W+/) + : [].concat(originalTags), + innerTags = ( + contentType === "journal" + ? body.match(/\b#(\w+)/g) || [] + : [] + ).map((val) => val.replace("#", "")), + allTags = [...tags, ...innerTags].sort(tagSorter), + updatedBody = + contentType === "journal" + ? allTags.reduce( + (acc, tag) => + acc.replace( + `#${tag}`, + ` + + #${tag} + ` + ), + body + ) + : body; + + return { + ...config, + page: { + name, + ...attributes, + body: updatedBody, + destPath, + filePath, + path: path.join(dir, hasExt ? name : `${name}.html`), + tags: [...tags, ...innerTags].sort(tagSorter), + ext, + }, + site: { + ...site, + pages: isSupport ? siteData : [], + }, + }; + }, + parseContent = (page, siteData) => { + const { + body, + content_type: contentType, + filePath, + // tags, + } = page || {}, + { ext } = path.parse(filePath) || {}, + { pages, tags } = siteData || {}; + + let content = body, + readTime; + + if (ext === ".md") { + if (contentType === "journal" && typeof body === "string") { + readTime = getReadTime(body); + } + content = md.render(body); + } else if (ext === ".ejs") { + content = ejs.render( + body, + { page, site: { ...site, pages, tags } }, + { filename: filePath } + ); + } + + return { ...page, content, readTime }; + }, + renderFile = async (page, isSupport) => { + const { + content, + destPath, + layout, + path: pagePath, + pages, + siteTags, + tags, + } = page || {}; + try { + const layoutFileName = `${srcPath}/layouts/${ + layout || "default" + }.ejs`, + layoutData = await fs.readFile(layoutFileName, "utf-8"), + completePage = isSupport + ? content + : ejs.render(layoutData, { + content, + page, + site: { + ...site, + pages, + tags: + page.content_type === "journal" + ? siteTags + : tags, + }, + filename: layoutFileName, + }); + + if (!completePage) { + console.log("failed!", pagePath, content); + return; + } + + // create destination directory + fse.mkdirsSync(destPath); + + // save the html file + fse.writeFileSync( + path.join(outputPath, pagePath), + completePage + ); + } catch (e) { + console.log("failed!", pagePath); + console.log("paths", destPath, outputPath); + console.error(e); + return; + } + }; + + md.use(emoji); + + log(`${isRebuild ? "Reb" : "B"}uilding...`); + + // clear destination folder + fse.emptyDirSync(outputPath); + + // copy assets folder + await copyAssets(path.join(srcPath, "assets")); + + const files = ["pages", "sitePosts"].reduce((acc, pageDir) => { + return [ + ...acc, + ...glob + .sync("**/*.@(md|ejs|html)", { + cwd: path.join(srcPath, pageDir), + }) + .map((file) => + parseFile(file, path.join(srcPath, pageDir)) + ), + ]; + }, []), + sortByPubDate = (a, b) => { + if (a.date_pub && b.date_pub) { + let a_dt = new Date(a.date_pub).getTime(), + b_dt = new Date(b.date_pub).getTime(); + if (a_dt < b_dt) { + return 1; + } + if (b_dt < a_dt) { + return -1; + } + return 0; + } + if (a.date_pub) return -1; + if (b.date_pub) return 1; + return 0; + }, + pages = files.map(({ page }) => ({ ...page })).sort(sortByPubDate), + tagCloud = pages.reduce((acc, curr) => { + const { tags } = curr; + tags.forEach((tag) => { + if (acc[tag]) acc[tag]++; + else acc[tag] = 1; + }); + return acc; + }, {}), + tags = Object.keys(tagCloud).sort(tagSorter), + yearCloud = pages + .filter(({ content_type = "" }) => content_type === "journal") + .reduce((acc, curr) => { + const { date_pub } = curr; + if (date_pub) { + const year = new Date(date_pub).getFullYear(); + if (acc[year]) acc[year]++; + else acc[year] = 1; + } + return acc; + }, {}), + years = Object.keys(yearCloud).sort().reverse(), + pagesWithContent = pages.map((page) => + parseContent(page, { pages, tags }) + ); + + // add data for the whole site to each page as it's rendered + pagesWithContent.forEach((page) => { + renderFile({ ...page, pages: pagesWithContent, siteTags: tags }); + }); + + /* Journal Stuff - Tags & Years */ + + // make page(s) for each tag + tags.forEach((tag) => { + // check counts + let postCount = tagCloud[tag], + pageCount = Math.ceil(postCount / journalsPerPage); + for (let i = 1; i <= pageCount; i++) { + const firstEntryIndex = journalsPerPage * (i - 1), + lastEntryIndex = journalsPerPage * i; + + renderFile({ + content: tag, + destPath: path.join(outputPath, "journal", "tags", tag), + entriesToList: pagesWithContent + .filter( + (p) => + p && Array.isArray(p.tags) && p.tags.includes(tag) + ) + .slice(firstEntryIndex, lastEntryIndex), + layout: "tag", + path: `journal/tags/${tag}/${ + i === 1 ? "index.html" : `page${i}.html` + }`, + site: { ...site, pages: pagesWithContent, tags }, + pageCount, + pageNum: i, + pages: pagesWithContent, + tag, + tags, + title: `Journal Entries Tagged with #${tag}`, + }); + } + }); + + // make page(s) for each year + years.forEach((year) => { + // check counts + let postCount = yearCloud[year], + pageCount = Math.ceil(postCount / journalsPerPage); + for (let i = 1; i <= pageCount; i++) { + const firstEntryIndex = journalsPerPage * (i - 1), + lastEntryIndex = journalsPerPage * i; + + // TODO: rethink the data passed in here - you're paging solution works (kinda), take it over the finish line! + renderFile({ + content: year, + destPath: path.join(outputPath, "journal", year), + entriesToList: pagesWithContent + .filter(({ content_type = "", date_pub = "" }) => { + if (!date_pub || content_type !== "journal") + return false; + + const p_dt = new Date(date_pub).getTime(), + y1_dt = new Date( + `${year}-01-01T00:00:00-0500` + ).getTime(), + y2_dt = new Date( + `${year}-12-31T23:59:59-0500` + ).getTime(); + return p_dt >= y1_dt && p_dt <= y2_dt; + }) + .slice(firstEntryIndex, lastEntryIndex), + layout: "journal-year", + path: `journal/${year}/${ + i === 1 ? "index.html" : `page${i}.html` + }`, + site: { ...site, pages: pagesWithContent, tags }, + pageCount, + pageNum: i, + pages: pagesWithContent, + tags, + title: `Journal Entries from ${year}`, + year, + }); + } + }); + + /* Support pages - anything too weird / specific for markdown rendering */ + + // collect support pages + const support = ["support"].reduce((acc, pageDir) => { + return [ + ...acc, + ...glob + .sync("**/*.@(md|ejs|html)", { + cwd: path.join(srcPath, pageDir), + }) + .map((file) => + parseFile( + file, + path.join(srcPath, pageDir), + pagesWithContent, + true + ) + ), + ]; + }, []); + + // write each one out + support.forEach((fileData) => { + const { page } = fileData; + if (page?.ext === ".ejs") { + const pageAndContent = parseContent(page, { + pages: pagesWithContent, + tags, + }); + return renderFile({ ...fileData, ...pageAndContent, tags }, true); + } + return renderFile(fileData, true); + }); +}; diff --git a/lib/defaults.json5 b/lib/defaults.json5 new file mode 100644 index 0000000..c4df493 --- /dev/null +++ b/lib/defaults.json5 @@ -0,0 +1,19 @@ +{ + /* + + */ + + /** TACO Express Default Options **/ + + /* + The function used to log output (console.log, morgan, etc). + Should take one (or more) strings as arguments. + */ + logFunction: null, + + build: {}, + site: {}, + serve: { + port: 5000, + }, +} \ No newline at end of file diff --git a/lib/loadConfig.js b/lib/loadConfig.js new file mode 100644 index 0000000..15842ce --- /dev/null +++ b/lib/loadConfig.js @@ -0,0 +1,43 @@ +module.exports = (opts, envKey) => { + const + fs = require('fs'), + path = require('path'), + + json5 = require('json5'), + + { convertCamelToUpperSnakeCase, readJsonIfExists } = require('./utils'), + + { cwd, env } = process, + + def = readJsonIfExists(path.resolve(__dirname, 'defaults.json5')), + + // gets value from ENV || options || defaults (in that order) + getVal = (envName) => { + const snakeEnvName = `${envKey}_${convertCamelToUpperSnakeCase(envName)}`; + if (env[snakeEnvName]) return env[snakeEnvName]; + if (opts[envName]) return opts[envName]; + return def[envName]; + }, + + // gets array from ENV || options || defaults (in that order) + getArray = (envName, optName = '') => { + if (optName === '') { + optName = envName; + envName = convertCamelToUpperSnakeCase(envName); + } + envName = `${envKey}_${envName}`; + if (env[envName]) return env[envName].split(path.delimiter); + if (Array.isArray(opts[optName]) && opts[optName].length) return opts[optName]; + return def[optName]; + }; + + + return { + + ...Object.keys(def).reduce((acc, curr) => { + if (Array.isArray(def[curr])) acc[curr] = getArray(curr); + else acc[curr] = getVal(curr); + return acc; + }, {}), + }; +}; diff --git a/lib/serve.js b/lib/serve.js new file mode 100644 index 0000000..2bf7728 --- /dev/null +++ b/lib/serve.js @@ -0,0 +1,26 @@ +module.exports = async (config) => { + let isReady = false; + const + http = require('http'), + + address = require('network-address'), + handler = require('serve-handler'), + + build = require('./build'), + + { build: buildOpts, logFunction: log = () => {}, serve: serveOpts } = config || {}, + { outputPath, srcPath } = buildOpts || {}, + { port = 5000 } = serveOpts || {}, + + server = http.createServer((request, response) => { + // You pass two more arguments for config and middleware + // More details here: https://github.com/vercel/serve-handler#options + return handler(request, response, { public: outputPath }); + }); + + await build(config); + + server.listen(port, async () => { + log(`Running at http://${address()}:${port} / http://localhost:${port}`); + }); +}; \ No newline at end of file diff --git a/lib/utils.js b/lib/utils.js new file mode 100644 index 0000000..b8b4e0a --- /dev/null +++ b/lib/utils.js @@ -0,0 +1,57 @@ +module.exports = (() => { + const + chalk = require('chalk'), + + getTime = () => { + const + now = new Date(), + tzo = -now.getTimezoneOffset(), + dif = tzo >= 0 ? '+' : '-', + + pad = (num) => { + const norm = Math.floor(Math.abs(num)); + return `${norm < 10 ? '0' : ''}${norm}`; + }; + return [ + now.getFullYear(), + '-', + pad(now.getMonth() + 1), + '-', + pad(now.getDate()), + 'T', + pad(now.getHours()), + ':', + pad(now.getMinutes()), + ':', + pad(now.getSeconds()), + dif, + pad(tzo / 60), + ':', + pad(tzo % 60) + ].join(''); + }; + + return { + convertCamelToUpperSnakeCase: + str => str.replace(/[A-Z]/g, letter => `_${letter}`).toUpperCase(), + + getTime, + + log: (msg) => console.log(`${chalk.grey(`${getTime()}:`)} ${msg}`), + + readJsonIfExists: (filePath) => { + const + fs = require('fs'), + + json5 = require('json5'); + + try { + return json5.parse(fs.readFileSync(filePath, {encoding: 'utf8'})); + } catch (err) { + if (err.code === 'ENOENT') return {}; + throw err; + } + }, + + }; +})(); diff --git a/lib/watch.js b/lib/watch.js new file mode 100644 index 0000000..5ff368b --- /dev/null +++ b/lib/watch.js @@ -0,0 +1,58 @@ +module.exports = async (config) => { + let isReady = false; + const + http = require('http'), + + chokidar = require('chokidar'), + address = require('network-address'), + handler = require('serve-handler'), + + build = require('./build'), + rebuild = (cfg) => { + isReady = false; + build({ ...cfg, isRebuild: true }); + isReady = true; + }, + + { build: buildOpts, logFunction: log = () => {}, serve: serveOpts } = config || {}, + { outputPath, srcPath } = buildOpts || {}, + { port = 5000 } = serveOpts || {}, + + watcher = chokidar.watch([srcPath, '*.json'], { + ignored: /(^|[\/\\])\../, // ignore dotfiles + persistent: true + }) + .on('add', (path) => { + if (isReady) { + log(`File ${path} has been added`) + rebuild(config); + } + }) + .on('change', (path) => { + if (isReady) { + log(`File ${path} has been changed`) + rebuild(config); + } + }) + .on('ready', () => { + isReady = true; + }) + .on('unlink', (path) => { + if (isReady) { + log(`File ${path} has been removed`) + rebuild(config); + } + }), + + server = http.createServer((request, response) => { + // You pass two more arguments for config and middleware + // More details here: https://github.com/vercel/serve-handler#options + return handler(request, response, { public: outputPath }); + }); + + await build(config); + + server.listen(port, () => { + log(`Running at http://${address()}:${port} / http://localhost:${port}`); + }); +}; \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..64e36ac --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2653 @@ +{ + "name": "mystic-site-builder", + "version": "0.8.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "mystic-site-builder", + "version": "0.8.0", + "license": "ISC", + "dependencies": { + "chalk": "^4.1.2", + "chokidar": "^3.4.3", + "dotenv": "^16.0.1", + "highlight.js": "^11.3.1", + "json5": "^2.1.3", + "markdown-it": "^13.0.1", + "markdown-it-emoji": "^2.0.0", + "network-address": "^1.1.2", + "serve-handler": "^6.1.3" + }, + "devDependencies": { + "ejs": "^3.1.5", + "front-matter": "^4.0.2", + "fs-extra": "^10.0.0", + "glob": "^8.0.3", + "serve": "^13.0.2", + "yargs": "^17.3.1" + } + }, + "node_modules/@zeit/schemas": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz", + "integrity": "sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=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/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/arg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-2.0.0.tgz", + "integrity": "sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "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/boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clipboardy": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", + "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", + "dev": true, + "dependencies": { + "arch": "^2.1.1", + "execa": "^1.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", + "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.14", + "debug": "2.6.9", + "on-headers": "~1.0.1", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", + "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==", + "engines": { + "node": ">=12" + } + }, + "node_modules/ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "dependencies": { + "punycode": "^1.3.2" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "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/front-matter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", + "integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==", + "dev": true, + "dependencies": { + "js-yaml": "^3.13.1" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "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/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/highlight.js": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.6.0.tgz", + "integrity": "sha512-ig1eqDzJaB0pqEvlPVIpSSyMaO92bH1N2rJpLMN/nX396wTpDA4Eq0uK+7I/2XG17pFaaKE0kjV/XPeGt7Evjw==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "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-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "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/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-emoji": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-2.0.2.tgz", + "integrity": "sha512-zLftSaNrKuYl0kR5zm4gxXjHaOI3FAOEaloKmRA5hijmJZvSjmxcokOLlzycb/HXlUFWzXqpIEoyEMCE4i9MvQ==" + }, + "node_modules/markdown-it/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/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/network-address": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/network-address/-/network-address-1.1.2.tgz", + "integrity": "sha512-Q6878fmvItA1mE7H9Il46lONgFgTzX2f98zkS0c2YlkCACzNjwvum/8Kq693IQpxe9zy+w+Zm/4p0wQreLEtZw==", + "bin": { + "network-address": "cli.js" + } + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "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/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==" + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "dependencies": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", + "dev": true, + "dependencies": { + "rc": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/serve": { + "version": "13.0.4", + "resolved": "https://registry.npmjs.org/serve/-/serve-13.0.4.tgz", + "integrity": "sha512-Lj8rhXmphJCRQVv5qwu0NQZ2h+0MrRyRJxDZu5y3qLH2i/XY6a0FPj/VmjMUdkJb672MBfE8hJ274PU6JzBd0Q==", + "dev": true, + "dependencies": { + "@zeit/schemas": "2.6.0", + "ajv": "6.12.6", + "arg": "2.0.0", + "boxen": "5.1.2", + "chalk": "2.4.1", + "clipboardy": "2.3.0", + "compression": "1.7.3", + "serve-handler": "6.1.3", + "update-check": "1.5.2" + }, + "bin": { + "serve": "bin/serve.js" + } + }, + "node_modules/serve-handler": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", + "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.0.4", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-handler/node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-handler/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/serve/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/serve/node_modules/chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/serve/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/serve/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/serve/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/serve/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==" + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/update-check": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.2.tgz", + "integrity": "sha512-1TrmYLuLj/5ZovwUS7fFd1jMH3NnFDN1y1A8dboedIDt7zs/zJMo6TwwlhYKkSeEwzleeiSBV5/3c9ufAQWDaQ==", + "dev": true, + "dependencies": { + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "dev": true, + "engines": { + "node": ">=12" + } + } + }, + "dependencies": { + "@zeit/schemas": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz", + "integrity": "sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==", + "dev": true + }, + "accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "requires": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-align": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", + "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "dev": true, + "requires": { + "string-width": "^4.1.0" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "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" + } + }, + "arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true + }, + "arg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-2.0.0.tgz", + "integrity": "sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "boxen": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", + "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^6.2.0", + "chalk": "^4.1.0", + "cli-boxes": "^2.2.1", + "string-width": "^4.2.2", + "type-fest": "^0.20.2", + "widest-line": "^3.1.0", + "wrap-ansi": "^7.0.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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" + } + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==" + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true + }, + "clipboardy": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", + "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", + "dev": true, + "requires": { + "arch": "^2.1.1", + "execa": "^1.0.0", + "is-wsl": "^2.1.1" + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", + "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.14", + "debug": "2.6.9", + "on-headers": "~1.0.1", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA==" + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "dotenv": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", + "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==" + }, + "ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dev": true, + "requires": { + "jake": "^10.8.5" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz", + "integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==" + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", + "requires": { + "punycode": "^1.3.2" + } + }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "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" + } + }, + "front-matter": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/front-matter/-/front-matter-4.0.2.tgz", + "integrity": "sha512-I8ZuJ/qG92NWX8i5x1Y8qyj3vizhXS31OxjKDu3LKP+7/qBgfIKValiZIEwoVoJKUHlhWtYrktkxV1XsX+pPlg==", + "dev": true, + "requires": { + "js-yaml": "^3.13.1" + } + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "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" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "highlight.js": { + "version": "11.6.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.6.0.tgz", + "integrity": "sha512-ig1eqDzJaB0pqEvlPVIpSSyMaO92bH1N2rJpLMN/nX396wTpDA4Eq0uK+7I/2XG17pFaaKE0kjV/XPeGt7Evjw==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "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-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "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==" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dev": true, + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + } + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "linkify-it": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-4.0.1.tgz", + "integrity": "sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==", + "requires": { + "uc.micro": "^1.0.1" + } + }, + "markdown-it": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", + "integrity": "sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==", + "requires": { + "argparse": "^2.0.1", + "entities": "~3.0.1", + "linkify-it": "^4.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "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==" + } + } + }, + "markdown-it-emoji": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-2.0.2.tgz", + "integrity": "sha512-zLftSaNrKuYl0kR5zm4gxXjHaOI3FAOEaloKmRA5hijmJZvSjmxcokOLlzycb/HXlUFWzXqpIEoyEMCE4i9MvQ==" + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==" + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "requires": { + "mime-db": "1.52.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true + }, + "network-address": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/network-address/-/network-address-1.1.2.tgz", + "integrity": "sha512-Q6878fmvItA1mE7H9Il46lONgFgTzX2f98zkS0c2YlkCACzNjwvum/8Kq693IQpxe9zy+w+Zm/4p0wQreLEtZw==" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==" + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "dev": true + }, + "path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A==" + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==", + "dev": true, + "requires": { + "rc": "^1.0.1" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "serve": { + "version": "13.0.4", + "resolved": "https://registry.npmjs.org/serve/-/serve-13.0.4.tgz", + "integrity": "sha512-Lj8rhXmphJCRQVv5qwu0NQZ2h+0MrRyRJxDZu5y3qLH2i/XY6a0FPj/VmjMUdkJb672MBfE8hJ274PU6JzBd0Q==", + "dev": true, + "requires": { + "@zeit/schemas": "2.6.0", + "ajv": "6.12.6", + "arg": "2.0.0", + "boxen": "5.1.2", + "chalk": "2.4.1", + "clipboardy": "2.3.0", + "compression": "1.7.3", + "serve-handler": "6.1.3", + "update-check": "1.5.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "serve-handler": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", + "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "requires": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.0.4", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "requires": { + "mime-db": "~1.33.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "dev": true + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "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" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "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==" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "update-check": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.2.tgz", + "integrity": "sha512-1TrmYLuLj/5ZovwUS7fFd1jMH3NnFDN1y1A8dboedIDt7zs/zJMo6TwwlhYKkSeEwzleeiSBV5/3c9ufAQWDaQ==", + "dev": true, + "requires": { + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "17.5.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.5.1.tgz", + "integrity": "sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.0.0" + } + }, + "yargs-parser": { + "version": "21.0.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", + "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100755 index 0000000..511d66b --- /dev/null +++ b/package.json @@ -0,0 +1,34 @@ +{ + "name": "iew-site-builder", + "version": "0.9.0", + "description": "", + "main": "index.js", + "scripts": { + "build": "node app.js build", + "build:prod": "cross-env NODE_ENV=production node ./lib/build", + "serve": "node app.js serve", + "watch": "node app.js watch" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "chalk": "^4.1.2", + "chokidar": "^3.4.3", + "dotenv": "^16.0.1", + "highlight.js": "^11.3.1", + "json5": "^2.1.3", + "markdown-it": "^13.0.1", + "markdown-it-emoji": "^2.0.0", + "network-address": "^1.1.2", + "serve-handler": "^6.1.3" + }, + "devDependencies": { + "ejs": "^3.1.5", + "front-matter": "^4.0.2", + "fs-extra": "^10.0.0", + "glob": "^8.0.3", + "serve": "^13.0.2", + "yargs": "^17.3.1" + } +} diff --git a/site.config.json5 b/site.config.json5 new file mode 100644 index 0000000..be7aa29 --- /dev/null +++ b/site.config.json5 @@ -0,0 +1,26 @@ +{ + site: { + title: "It's Eric Woodward (dotcom)", + author: { + name: "Eric Woodward", + email: "redacted@nunyodam.com", // not used + photo: "/images/eric-8bit.gif", + site: "https://itsericwoodward.com", + }, + + base_uri: "", + robots: "index,follow", + language: "en-us", + copyright: "Copyright 2014-2022 Eric Woodward, licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.", + basePath: "", + uri: "https://www.itsericwoodward.com", + }, + build: { + journalsPerPage: 5, + srcPath: "src", + outputPath: "out", + }, + serve: { + port: 4997, + }, +} diff --git a/src/assets/_root/browserconfig.xml b/src/assets/_root/browserconfig.xml new file mode 100644 index 0000000..989db79 --- /dev/null +++ b/src/assets/_root/browserconfig.xml @@ -0,0 +1,2 @@ + +#0d1852 diff --git a/src/assets/_root/chim/chim-exe.zip b/src/assets/_root/chim/chim-exe.zip new file mode 100644 index 0000000..6ef9b0f Binary files /dev/null and b/src/assets/_root/chim/chim-exe.zip differ diff --git a/src/assets/_root/chim/js-dos-api.js b/src/assets/_root/chim/js-dos-api.js new file mode 100644 index 0000000..21331e6 --- /dev/null +++ b/src/assets/_root/chim/js-dos-api.js @@ -0,0 +1,348 @@ +/*! + * jQLite JavaScript Library v1.1.1 (http://code.google.com/p/jqlite/) + * Copyright (c) 2010 Brett Fattori (bfattori@gmail.com) + * Licensed under the MIT license + * http://www.opensource.org/licenses/mit-license.php + * + * Many thanks to the jQuery team's efforts. Some code is + * Copyright (c) 2010, John Resig. See + * http://jquery.org/license + * + * @author Brett Fattori (bfattori@gmail.com) + * @author $Author: bfattori $ + * @version $Revision: 145 $ + * + * Created: 03/29/2010 + * Modified: $Date: 2010-06-21 11:08:14 -0400 (Mon, 21 Jun 2010) $ + */ +(function(){function B(){return+new Date}var D=function(a,b){if(a===""&&b)return b;var d=a.split(" "),c=d.shift(),e;if(c.charAt(0)=="#"){var g=i.getElementById(c.substring(1));e=g?[g]:[]}else{e=c.charAt(0)!=="."?c.split(".")[0]:"*";var h=c.split("."),j=null;if(e.indexOf("[")!=-1){j=e;e=e.substr(0,e.indexOf("["))}g=function(o){var n=arguments.callee,k;if(!(k=!n.needClass)){k=n.classes;if(o.className.length==0)k=false;else{for(var r=o.className.split(" "),l=k.length,p=0;p0;g.needAttribute=j!=null;for(c=0;c0;)A.shift()()};var t="jQuery"+B(),S=0,O={};f.noData={embed:true,object:true,applet:true};f.cache={};f.data=function(a,b,d){if(!(a.nodeName&&jQuery.noData[a.nodeName.toLowerCase()])){a=a==window?O:a;var c=a[t];c||(c=a[t]=++S);if(b&&!jQuery.cache[c])jQuery.cache[c]={};if(d!==undefined)jQuery.cache[c][b]=d;return b?jQuery.cache[c][b]:c}};f.removeData= +function(a,b){a=a==window?O:a;var d=a[t];if(b){if(jQuery.cache[d]){delete jQuery.cache[d][b];b="";for(b in jQuery.cache[d])break;b||jQuery.removeData(a)}}else{try{delete a[t]}catch(c){a.removeAttribute&&a.removeAttribute(t)}delete jQuery.cache[d]}};f.ajax={status:-1,statusText:"",responseText:null,responseXML:null,send:function(a,b,d){if(f.isFunction(b)){d=b;b={}}if(a){var c=true,e=null,g=null;if(typeof b.async!=="undefined"){c=b.async;delete b.async}if(typeof b.username!=="undefined"){e=b.username; +delete b.username}if(typeof b.password!=="undefined"){g=b.password;delete b.password}b=f.param(b);if(b.length!=0)a+=(a.indexOf("?")==-1?"?":"&")+b;b=new XMLHttpRequest;b.open("GET",a,c,e,g);b.send();if(c){a=function(h){var j=arguments.callee;h.status==200?f.ajax.complete(h,j.cb):f.ajax.error(h,j.cb)};a.cb=d;d=function(){var h=arguments.callee;h.req.readyState!=4?setTimeout(h,250):h.xcb(h.req)};d.req=b;d.xcb=a;setTimeout(d,250)}}},complete:function(a,b){f.ajax.status=a.status;f.ajax.responseText=a.responseText; +f.ajax.responseXML=a.responseXML;f.isFunction(b)&&b(a.responseText,a.status)},error:function(a,b){f.ajax.status=a.status;f.ajax.statusText=a.statusText;f.isFunction(b)&&b(a.status,a.statusText)}};f.makeArray=function(a,b){var d=b||[];if(a!=null)a.length==null||typeof a==="string"||jQuery.isFunction(a)||typeof a!=="function"&&a.setInterval?L.call(d,a):f.merge(d,a);return d};f.inArray=function(a,b){for(var d=0;d")!=-1){d=f.trim(a).toLowerCase();d=d.indexOf("'); + this.canvas = $(''); + this.overlay = $('
'); + this.loaderMessage = $('
'); + this.loader = $('
').append($('
').append($(''))).append(this.loaderMessage); + this.start = $('
Click to start'); + this.div.append(this.wrapper); + this.wrapper.append(this.canvas); + this.wrapper.append(this.loader); + this.wrapper.append(this.overlay); + this.overlay.append($('
Powered by  ').append($('js-dos.com'))); + this.overlay.append(this.start); + } + + UI.prototype.onStart = function(fun) { + return this.start.click((function(_this) { + return function() { + fun(); + return _this.overlay.hide(); + }; + })(this)); + }; + + UI.prototype.appendCss = function() { + var head, style; + head = document.head || document.getElementsByTagName('head')[0]; + style = document.createElement('style'); + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = this.css; + } else { + style.appendChild(document.createTextNode(this.css)); + } + return head.appendChild(style); + }; + + UI.prototype.showLoader = function() { + this.loader.show(); + return this.loaderMessage.html(''); + }; + + UI.prototype.updateMessage = function(message) { + return this.loaderMessage.html(message); + }; + + UI.prototype.hideLoader = function() { + return this.loader.hide(); + }; + + UI.prototype.css = '.dosbox-container { position: relative; min-width: 320px; min-height: 200px; } .dosbox-canvas { } .dosbox-overlay, .dosbox-loader { position: absolute; left: 0; right: 0; top: 0; bottom: 0; background-color: #333; } .dosbox-start { text-align: center; position: absolute; left: 0; right: 0; bottom: 50%; color: #f80; font-size: 1.5em; text-decoration: underline; cursor: pointer; } .dosbox-overlay a { color: #f80; } .dosbox-loader { display: none; } .dosbox-powered { position: absolute; right: 1em; bottom: 1em; font-size: 0.8em; color: #9C9C9C; } .dosbox-loader-message { text-align: center; position: absolute; left: 0; right: 0; bottom: 50%; margin: 0 0 -3em 0; box-sizing: border-box; color: #f80; font-size: 1.5em; } @-moz-keyframes loading { 0% { left: 0; } 50% { left: 8.33333em; } 100% { left: 0; } } @-webkit-keyframes loading { 0% { left: 0; } 50% { left: 8.33333em; } 100% { left: 0; } } @keyframes loading { 0% { left: 0; } 50% { left: 8.33333em; } 100% { left: 0; } } .st-loader { width: 10em; height: 2.5em; position: absolute; top: 50%; left: 50%; margin: -1.25em 0 0 -5em; box-sizing: border-box; } .st-loader:before, .st-loader:after { content: ""; display: block; position: absolute; top: 0; bottom: 0; width: 1.25em; box-sizing: border-box; border: 0.25em solid #f80; } .st-loader:before { left: -0.76923em; border-right: 0; } .st-loader:after { right: -0.76923em; border-left: 0; } .st-loader .equal { display: block; position: absolute; top: 50%; margin-top: -0.5em; left: 4.16667em; height: 1em; width: 1.66667em; border: 0.25em solid #f80; box-sizing: border-box; border-width: 0.25em 0; -moz-animation: loading 1.5s infinite ease-in-out; -webkit-animation: loading 1.5s infinite ease-in-out; animation: loading 1.5s infinite ease-in-out; }'; + + return UI; + + })(); + +}).call(this); + +(function() { + Dosbox.Xhr = (function() { + function Xhr(url, options) { + var e; + this.success = options.success; + this.progress = options.progress; + if (window.ActiveXObject) { + try { + this.xhr = new ActiveXObject('Microsoft.XMLHTTP'); + } catch (error) { + e = error; + this.xhr = null; + } + } else { + this.xhr = new XMLHttpRequest(); + } + this.xhr.open('GET', url, true); + this.xhr.overrideMimeType('text/plain; charset=x-user-defined'); + this.xhr.addEventListener('progress', (function(_this) { + return function(evt) { + if (_this.progress) { + return _this.progress(evt.total, evt.loaded); + } + }; + })(this)); + this.xhr.onreadystatechange = (function(_this) { + return function() { + return _this._onReadyStateChange(); + }; + })(this); + this.xhr.send(); + } + + Xhr.prototype._onReadyStateChange = function() { + if (this.xhr.readyState === 4 && this.success) { + return this.success(this.xhr.responseText); + } + }; + + return Xhr; + + })(); + +}).call(this); diff --git a/src/assets/_root/favicon.ico b/src/assets/_root/favicon.ico new file mode 100644 index 0000000..d9f98df Binary files /dev/null and b/src/assets/_root/favicon.ico differ diff --git a/src/assets/_root/favicon.png b/src/assets/_root/favicon.png new file mode 100644 index 0000000..8626f74 Binary files /dev/null and b/src/assets/_root/favicon.png differ diff --git a/src/assets/_root/manifest.json b/src/assets/_root/manifest.json new file mode 100644 index 0000000..c81ae3e --- /dev/null +++ b/src/assets/_root/manifest.json @@ -0,0 +1,41 @@ +{ + "name": "Its Eric Woodward! (dotcom)", + "icons": [ + { + "src": "\/images\/favicons\/android-icon-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }, + { + "src": "\/images\/favicons\/android-icon-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }, + { + "src": "\/images\/favicons\/android-icon-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }, + { + "src": "\/images\/favicons\/android-icon-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }, + { + "src": "\/images\/favicons\/android-icon-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }, + { + "src": "\/images\/favicons\/android-icon-192x192.png", + "sizes": "192x192", + "type": "image\/png", + "density": "4.0" + } + ] +} diff --git a/src/assets/_root/root/favicon.ico b/src/assets/_root/root/favicon.ico new file mode 100644 index 0000000..d9f98df Binary files /dev/null and b/src/assets/_root/root/favicon.ico differ diff --git a/src/assets/_root/root/favicon.png b/src/assets/_root/root/favicon.png new file mode 100644 index 0000000..8626f74 Binary files /dev/null and b/src/assets/_root/root/favicon.png differ diff --git a/src/assets/files/chim/chim.exe b/src/assets/files/chim/chim.exe new file mode 100644 index 0000000..46c8a42 Binary files /dev/null and b/src/assets/files/chim/chim.exe differ diff --git a/src/assets/files/chim/chim.faq b/src/assets/files/chim/chim.faq new file mode 100644 index 0000000..d9c31f1 --- /dev/null +++ b/src/assets/files/chim/chim.faq @@ -0,0 +1,422 @@ +ο»Ώβ”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β” β”Œβ”€β” β”Œβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β” β”Œβ”€β” +β”‚ β”Œβ”€β” β”‚ β”‚ β”Œβ”€β”€β” β”‚ β”‚ β”Œβ” β”Œβ” β”‚ β”‚ β”Œβ”€β” β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β” β”‚ β”‚ β”Œβ”€β” β”‚ β”‚ β”Œβ”€β” β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”˜ β”‚ β””β”€β”€β”˜ β”‚ β”‚ β”‚β”‚ β”‚β”‚ β”‚ β”‚ β””β”€β”˜ β”‚ β”‚ β””β”€β”˜ β”‚ β”‚ β””β”€β”€β”˜ β”‚ β”‚ β””β”€β”˜ β”‚ β”‚ β””β”€β”˜ β”‚ β”‚ β””β”€β”˜ β”‚ +β”‚ β”‚ β”Œβ”€β” β”‚ β”Œβ”€β”€β” β”‚ β”‚ β”‚β””β”€β”˜β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”˜ β”‚ β”Œβ”€β” β”‚ β”‚ β”Œβ”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”˜ └─┐ β”Œβ”€β”˜ +β”‚ β””β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ + + β”Œβ”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β” β”Œβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β” β”Œβ”€β” β”Œβ”€β”€β”€β”€β”€β”€β” + └┐ β”Œβ”˜ β”‚ β”Œβ”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”Œβ”€β”€β” β”‚ β”‚ └┐ β”‚ β”‚ └┐ β”Œβ”€β” β”‚ + β”‚ β”‚ β”‚ └───┐ β”‚ β”‚ β”‚ β””β”€β”€β”˜ β”‚ β”‚ β”œβ” └┐│ β”‚ β”‚ β”‚ β”‚ β”‚ + β”‚ β”‚ └───┐ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β” β”‚ β”‚ │└┐ └─ β”‚ β”‚ β”‚ β”‚ β”‚ + β”Œβ”˜ └┐ β”Œβ”€β”€β”€β”˜ β”‚ β”‚ └──┐ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ └┐ β”‚ β”Œβ”˜ β””β”€β”˜ β”‚ + β””β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”˜ + + β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ + β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–„β–„β–„β–ˆβ–ˆ β–ˆβ–ˆβ–„β–„β–„β–„ β–ˆβ–ˆβ–„β–„β–„β–„ β–ˆβ–ˆβ–„β–„β–„β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–„β–„β–„β–„ β–ˆβ–ˆ + β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–€β–€β–€β–ˆβ–ˆ β–€β–€β–€β–€β–ˆβ–ˆ β–€β–€β–€β–€β–ˆβ–ˆ β–ˆβ–ˆβ–€β–€β–€β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–€β–€β–€β–€ β–€β–€ + β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–€ β–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–€ β–ˆβ–ˆ β–ˆβ–ˆ β–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–€ β–ˆβ–ˆ β–€β–ˆβ–ˆ β–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ + β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„ + β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„ + + "We Have Such Sights To Show You... " + +============================================================================= + Camp Happy Island Massacre FAQ v1.1 + by Eric Woodward (hey@itsericwoodward.com) +============================================================================= + +Table of Contents + +Section 1 - The Beginning + 1.0 - SPECIAL NOTE - 20 Years Later + 1.1 - What is 'Camp Happy Island Massacre'? + 1.2 - Who Wrote This Wonderful Game? + 1.3 - What Kind of System Do I Need to Run This Game? + 1.4 - How Do I Install and Run This Game? + 1.5 - How Can I Play This Game Online? + +Section 2 - The Game + 2.1 - The Story So Far... + 2.2 - So How Do I Play? + 2.3 - Is There a Map? + 2.4 - What Horror Movies Inspired This Game (aka The Reference Section)? + 2.5 - Will There Be a Sequel? + +Section 3 - The Boring Stuff + 3.0 - SPECIAL NOTE! + 3.1 - What About Bugs? + 3.2 - What License is CHIM Released Under? + 3.3 - Why Isn't CHIM Open Source? + 3.4 - Where Can I Find This Game? + 3.5 - Game Version History + 3.6 - FAQ Version History + 3.7 - Acknowledgements + 3.8 - Support (Such As It Is) + +Section 4 - The Secrets + 4.1 - The Big (well, Fairly Big) Secret + 4.2 - How Do I Win? + 4.3 - How (Can / Do) I Cheat? + +------------------------- +Section 1 - The Beginning +------------------------- + +1.0 - SPECIAL NOTE - 20 Years Later + The FAQ that you are about to read was originally written in January 1997, + when this game was first released. Since then, alot has happened, and much + of this FAQ had grown *severely* out-of-date. As a result, I've gone in and + cleaned-up some of the questions, updated several of the references in the + answers, and just generally tried to improve the usefulness of these + Frequently Asked Questions. + + Thanks for taking a look! + +1.1 - What is 'Camp Happy Island Massacre'? + 'Camp Happy Island Massacre' (from here-on-out referred to as 'CHIM') is a + single-player computer game, with an interface not entirely unlike the old + (I prefer the term 'classic') script-adventure style of games, like + 'The Hitchhiker's Guide to the Galaxy' or the original 'Zork' (among + others). + + Why this interface? For several reasons: + 1) This is my first full game, and I knew that I couldn't start with + anything much more involved than a script-adventure, + 2) This game was programmed in C++, a language that I am still not + completely at-ease with (and don't particularly care for, TBH), and + 3) I wanted to prove that a game could still be fun without it being 100+ + MBs big and requiring a 3-D graphics card (something that, I feel, + far too many game-making companies don't believe). + + If this sounds boring, it should be noted that the bulk of the game's + appeal lies in it's comedic elements. As one can probably tell based on the + story, the game is supposed to be a tongue-in-cheek parody of horror films, + and, I feel that the game works fairly well in a picture-less format (after + all, the works of Poe, Lovecraft, and even King are much scarier as books + than as movies for just this reason). If you disagree, though, you'll be + glad to hear that the sequel (if it ever happens) will be more visual in + nature (for more information, see the question concerning the sequel). + +1.2 - Who Wrote This Wonderful Game? + I did, over 20 years ago. + + My name is Eric Woodward and, at the time of this game's release, I was in + my second year of college, slowly approaching a degree in Computer Science + (which I completed in 2000). + + In the 20+ years since, I've gotten married, had a couple of kids, and + managed to carve out a fairly comfortable life as a coder / web developer. + But, through it all, CHIM remains the only computer game that I ever + released (although I did manage to put out a tabletop card game earlier + this year called 'Mythic Wars: Clash of the Gods', available at many fine + gaming stores from Excalibre Games -- find out more at + https://mythicwarsgame.com!). + + Oh yeah... I wrote this FAQ, too. + +1.3 - What Kind of System Do I Need to Run This Game? + Initially, I'd said "you need a computer; that's about it. Anything from a + 286 on up to the latest Pentium II should be sufficient to run the game", + and that was true at the time (when MS-DOS still ruled the world). However, + to run this game in 2018, you probably need a copy of DOSBox (see the next + question for more information). + + Or, if you don't want to wait, you can most likely play it in your browser + *right now* on my website: https://www.itsericwoodward.com/chim/. + +1.4 - How Do I Install and Run This Game? + To play the game on your own machine, you'll need a couple of different + programs. Since the game is distributed in the pkzip archive format, you + may need a program to 'unzip' it (unless your OS does it for you, like + Windows 10). Additionally, you'll need a copy of + DOSBox (https://www.dosbox.com/). If I were you, I'd unzip CHIM to its + own folder (ex: `c:\games\chim`), and startup DOSBox. Next, mount the CHIM + folder (ex: `mount m c:\games\chim`) and switch to that drive (ex: `m:`). + Finally, start the game with the `chim` command. + +1.5 - How Can I Play This Game Online? + Thanks to modern software miracles like DOSBox (https://www.dosbox.com/), + Emscripten (http://emscripten.org/), and their unholy lovechild, + JS-DOS (https://js-dos.com/), you can play this game in a modern browser + on my website: https://www.itsericwoodward.com/chim/. + +-------------------- +Section 2 - The Game +-------------------- + +2.1 - The Story So Far... + Some 15 years ago, someone decided to build a summer camp on + 'Happy Island', a small island in Lake Hades, near the town of Springfield. + Despite the fact that the island had been known as 'Death Island' (that is, + until the Springfield Tourism Bureau decided to rename it), or the fact + that the town's resident drunk, homeless, crazy, old Native American, John, + continually warned of a great, ancient evil living on the island, the camp + was built. + + Then, the night before the campers were supposed to arrive, something + horrible happened. The next day, all 13 counselors were found dead, their + body parts scattered all over the island. Needless to say, the camp was + closed. + + Then, 5 years later, someone else decided to re-open the camp, despite the + still unsolved murders of 5 years before, and despite the fact that many of + Springfield's residents had seen strange lights circling in the sky above + the island. Again, 13 counselors were brought from the surrounding areas to + help run the camp, and again, the night before the campers were to arrive, + something horrbile happened. The next day, the strange lights were gone... + and so were the counselors - nothing remained of them but a few scattered + arms and legs. And, again, the camp was closed down. + + And it remained closed until 5 years later, when someone else decided to + re-open the summer camp. This person, being a little superstitious, decided + to hire 14 counselors instead of just 13, hoping to break the apparent + curse over the camp. Unbeknownst to anyone, however, the 14th counselor, + named Jason Frederick Bates-Myers (his friends called him 'Jack', but his + enemies called him 'Mr. Leather-Ghost-Face Man'), was a violent psycopath + who, on the night before the campers were to arrive, killed the 13 other + counselors using a leaf blower and homemade 'explosive' attachment. In the + end, Jack was taken to Belleward Mental Institute, and the camp was closed + down. + + And that was 5 years ago. Now, they want to re-open it again, this time + with 13 brand-new counselors, and a fresh look on life. Finding counselors + was easy - after all, what teenager doesn't want to spend 6 weeks as + relatively unsupervised counselors at a co-ed summer camp, away from + parents, teachers, and other adults? So what if John, the Native American + is talking about the 'ancient evil' again? So what if the strange lights + have re-appeared? And so what if that Bates-Myers guy has escaped from + Belleward? That doesn't mean anything, right? + + Wrong... Because it's the night before the campers are to arrive... And the + camp head, Ranger Bud, has gone into town... And the other 10 counselors + have all disappeared into the woods, leaving only the three of you back at + camp... And you're scared... You're scared that you might not survive... + + The Camp Happy Island Massacre! + +2.2 - So How Do I Play? + When you run the game, it will ask if you need instructions. Moving around + the island is accomplished via four keys: 'N' for North, 'S' for South, + 'E' for East, and 'W' for West. You can't always go all four ways, so it + pays to read the descriptions of the areas you find yourself in (if + something is blocking a certain direction, you can't go that way). + Incidentally, if you can't remember where you can go, you can always use + the 'L' (Look) command to read the description again. + + If you encounter an item while you are walking around, you can try to pick + it up by using the 'G' (Get) command, but don't be surprised if it tells + you that you can't pick an item up (typically, this only happens with items + that are particularly nasty or heavy). Once you have an item, you can take + a closer look at it by using the 'X' (eXamine) command, and you can try to + use it via the 'U' (Use) command. Again, don't be surprised if you beat the + game without ever using certain items - many of them are just there for fun + and can't be used at all. + + The remaining commands are either used to get on-line help ('?' or 'H' for + Quick Help, or 'M' to read the Manual), or to quit the game ('Q'). + + Oh yeah - there are some hidden rooms on the island, one of which you will + have to find in order to beat the game... Good Luck. + +2.3 - Is There a Map? + Included in the distribution should be "MAP.TXT", a map in UTF-8 text-file + format (if your distribution didn't include one, get a new distribution). + Granted, this map is only slightly helpful, as it doesn't have any actual + trails drawn on it, just major landmarks. If you were in fact looking for + a map of trails... sorry, but there isn't one (at least, there isn't one + that I'm distributing...) I feel that having that kind of a map would + subtract SEVERELY from the game's fun-factor. So, in short, make due with + what you got, and if you are an enterprising individual and wish to make + a map, it shouldn't be too hard. + +2.4 - What Horror Movies Inspired This Game (aka The Reference Section)? + This game was, more or less, inspired by a whole slew of movies. Some are + more obvious than others (the many and varied 'Friday the 13th' movies + stand out in my mind), and sometimes it isn't even movies that inspired + certain elements of this game, but rather books (like the works of one H.P. + Lovecraft). Regardless, here's a brief list of movies and movie series that + inspired me: + + Evil Dead (including Army of Darkness), Scream, Friday the 13th, Psycho, + Hellraiser, A Nightmare on Elm Street, Nightbreed, Carrie, Firestarter, + Phantasm, Halloween, Texas Chainsaw Massacre, The Re-Animator, Bad Taste, + Puppet Master, Dead Alive (Braindead), The Frighteners, Alien, Showgirls, + Night of the Living Dead, There's Nothing Out There, and countless others. + +2.5 - Will There Be a Sequel? + Initially, I had planned to make one, "Cause nowadays, ya' gotta have a + sequel!". I had even begun work on one, a CD-ROM-based game complete with + full-motion video, special effects, even a script! But, it never came to + fruition, and by now, the code is lost to time (along with the video, + the photos, and the age of most of the original cast). + + On the other hand, I have considered making a board or card game based on + the characters and concepts from CHIM, so... Who knows what the future has + in store for CHIM? + +---------------------------- +Section 3 - The Boring Stuff +---------------------------- + +3.0 - SPECIAL NOTE! + This version (v1.0) of the game will be the only version ever to be + released. This was not my original intention; I had fully intended to fix + any and all bugs that turned up, colorize the output (to make it pretty), + and then re-release it. Unfortunately, the best laid plans of mice and + men (and me) can't stand up to a total hard-drive loss, especially when + the last remaining copy of the source code was contained therein. So, you + can keep playing CHIM all you want, but there almost certainly won't be a + new version of it, ever. We now return you to your regularly scheduled FAQ. + +3.1 - What About Bugs? + What Bugs? I write perfect programs. + + Not really. Despite my best efforts, my program does have some unintended + (and unwanted) 'features'. The complete (to my knowledge) list is below: + - Some problems with garbage characters popping into descriptions of some + of the areas (caused by a char-pointer problem). + + If you find a bug that isn't listed here, please feel free to e-mail me + at hey@itsericwoodward.com, or snail-mail them to me at the address listed + a little later. + +3.2 - What License is CHIM Released Under? + CHIM was originally released as "-ware", wherein I asked people + who enjoyed the game to "send me something (preferably not something that + is alive, ticking, or that has a strange odor)." In the 20 years since the + game's original release, free software licensing has grown by leaps and + bounds (plus, I'm kind of afraid to ask people to send me things now). + + As a result of these factors, I'm re-releasing CHIM under the so-called + MIT License (a copy of which should have been included in your ZIP file + distribution as "LICENSE.TXT") and which can be found at: + + https://www.itsericwoodward.com/chim/LICENSE.TXT + +3.3 - Is CHIM Open Source? + Well, it would be, but (as noted above), the code was lost during a hard- + drive crash in mid-1997 (just a couple of months after the game was + released). As a result, there is no source to open (otherwise, I would + definitely have re-released it under an open-source license years ago). + +3.4 - Where Can I Find This Game? + The latest version of the game, FAQ, and other related files can always be + found at: + + https://www.itsericwoodward.com/chim/ + +3.5 - Game Version History + v0.9b - released on 10/31/97 (Halloween) - Original Beta Release + v1.0 - released on 01/05/97 - Original Full Release + - Fixed small problem with movement and the map + - Made output prettier + +3.6 - FAQ Version History + v1.0 - released on 01/05/1997 - Original Full Release + v1.1 - released on 10/10/2018 - 21 Years Worth of Updates + +3.7 - Acknowledgements + There are many people I want to thank, but I can't, so I'll just hit the + major ones... + + - Mark, Donnie, Tommy, Jeff, and Sarah for not laughing at me when I + mentioned that I was writing a game; + - My playtester, Mike, for actually doing playtesting (maps and all); + - All of my professors and friends at school for their help, both direct + and implicit; + - And my wonderful wife, Stacie, for supporting me. + +3.8 - Support (Such As It Is) + I offer no promises for support, but feel free to contact me at any of the + following addresses / locations: + + Email: hey@itsericwoodward.com + + WWW: https://www.itsericwoodward.com/chim/ + + Fediverse: @eric@social.wonderdome.net + +----------------------- +Section 4 - The Secrets +----------------------- + + WARNING! - This section contains many gratuitous spoilers. If you read this + section, there is a chance that some of the fun of the game will be lost. + So, I urge you to skip this section entirely. Just so no secrets get out, + let me fill up the rest of this space with, um, filler: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Alright... You asked for it... + +4.1 - The Big (well, Fairly Big) Secret + The Fairly Big Secret is that the game doesn't just have 1 ending. Each + time the game is loaded, there is a random chance that the killer will be + either a group of aliens, an unnamable Thing, or a vengeful psychopath + (Jason Frederick Bates-Myers, to be more specific). + +4.2 - How Do I Win? + First off, you MUST find the radio tower and signal for help (it may sound + like the message didn't get out, but rest assured that it did). + + After that, it depends on who the killer is. + - If it's the Aliens - you need to get the credit card type-thing out of + the cave, take it to the secret room (in the lodge) and use it, and then + go to the baseball field, where the ship will land. + - If it's the Thing - you need to get the Unholy Book from the secret room + (in the lodge), take it to the baseball field and use it, and then go to + the cave, where the thing will be waiting. + - If it's the Psycho - you need to get the flashlight from the baseball + field, take it to the cave and use it to read the words on the wall, and + then you need to go to the secret room (in the lodge) to confront Jason. + +4.3 - How (Can / Do) I Cheat? + Well, it seems to me that that's exactly what you're doing right now. But, + you can cheat by entering one or two command line arguments when executing + the game. They are called by typing 'chim -arg1 -arg2' where the args + can be: + '-nokiller' - tired of the killer getting you before you can get him? Use + this little switch to prevent him from ever finding you until the end of + the game. + '-aliens' - forces the bad guys to be the aliens. + '-thing' - forces the bad guy to be the unnamable thing. + '-psycho' - forces the bad guy to be Jason Frederick Bates-Myers. + + So, to make the bad guys be the aliens, type 'chim -aliens' at the + command prompt. Or, to make it be the psycho, and to keep him from killing + you first, type 'chim -nokiller -psycho'. Of course, entering the + command 'chim -aliens -thing' doesn't work; the bad guy winds up being + the thing. + + And that, my friend, is how you cheat. diff --git a/src/assets/files/chim/chim.zip b/src/assets/files/chim/chim.zip new file mode 100644 index 0000000..9caf871 Binary files /dev/null and b/src/assets/files/chim/chim.zip differ diff --git a/src/assets/files/chim/file_id.diz b/src/assets/files/chim/file_id.diz new file mode 100644 index 0000000..c841c70 --- /dev/null +++ b/src/assets/files/chim/file_id.diz @@ -0,0 +1,9 @@ +ο»ΏCamp Happy Island Massacre v1.0 (1997): +Tongue-in-cheek menu-driven text game, +inspired by 80s horror movies. Play as +the only surviving counselors of an ill- +fated summer camp as you try to figure +out who (or what) is killing everyone +(and how you can survive). 1 player. +Freeware (MIT License) by Eric Woodward. +https://www.itsericwoodward.com/chim/ \ No newline at end of file diff --git a/src/assets/files/chim/intro.txt b/src/assets/files/chim/intro.txt new file mode 100644 index 0000000..8e58c86 --- /dev/null +++ b/src/assets/files/chim/intro.txt @@ -0,0 +1,22 @@ +ο»Ώβ”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β” β”Œβ”€β” β”Œβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β” β”Œβ”€β” +β”‚ β”Œβ”€β” β”‚ β”‚ β”Œβ”€β”€β” β”‚ β”‚ β”Œβ” β”Œβ” β”‚ β”‚ β”Œβ”€β” β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β” β”‚ β”‚ β”Œβ”€β” β”‚ β”‚ β”Œβ”€β” β”‚ β”‚ β”‚ β”‚ β”‚ +β”‚ β”‚ β””β”€β”˜ β”‚ β””β”€β”€β”˜ β”‚ β”‚ β”‚β”‚ β”‚β”‚ β”‚ β”‚ β””β”€β”˜ β”‚ β”‚ β””β”€β”˜ β”‚ β”‚ β””β”€β”€β”˜ β”‚ β”‚ β””β”€β”˜ β”‚ β”‚ β””β”€β”˜ β”‚ β”‚ β””β”€β”˜ β”‚ +β”‚ β”‚ β”Œβ”€β” β”‚ β”Œβ”€β”€β” β”‚ β”‚ β”‚β””β”€β”˜β”‚ β”‚ β”‚ β”Œβ”€β”€β”€β”˜ β”‚ β”Œβ”€β” β”‚ β”‚ β”Œβ”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”˜ └─┐ β”Œβ”€β”˜ +β”‚ β””β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ +β””β”€β”€β”€β”€β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ + + β”Œβ”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β” β”Œβ”€β” β”Œβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β” β”Œβ”€β” β”Œβ”€β”€β”€β”€β”€β”€β” + └┐ β”Œβ”˜ β”‚ β”Œβ”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”Œβ”€β”€β” β”‚ β”‚ └┐ β”‚ β”‚ └┐ β”Œβ”€β” β”‚ + β”‚ β”‚ β”‚ └───┐ β”‚ β”‚ β”‚ β””β”€β”€β”˜ β”‚ β”‚ β”œβ” └┐│ β”‚ β”‚ β”‚ β”‚ β”‚ + β”‚ β”‚ └───┐ β”‚ β”‚ β”‚ β”‚ β”Œβ”€β”€β” β”‚ β”‚ │└┐ └─ β”‚ β”‚ β”‚ β”‚ β”‚ + β”Œβ”˜ └┐ β”Œβ”€β”€β”€β”˜ β”‚ β”‚ └──┐ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ └┐ β”‚ β”Œβ”˜ β””β”€β”˜ β”‚ + β””β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”˜ β””β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”˜ + + β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–„ β–„β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ + β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–„β–„β–„β–ˆβ–ˆ β–ˆβ–ˆβ–„β–„β–„β–„ β–ˆβ–ˆβ–„β–„β–„β–„ β–ˆβ–ˆβ–„β–„β–„β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–„β–„β–„β–„ β–ˆβ–ˆ + β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–€β–€β–€β–ˆβ–ˆ β–€β–€β–€β–€β–ˆβ–ˆ β–€β–€β–€β–€β–ˆβ–ˆ β–ˆβ–ˆβ–€β–€β–€β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆβ–€β–€β–€β–€ β–€β–€ + β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–ˆβ–ˆ β–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–€ β–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–€ β–ˆβ–ˆ β–ˆβ–ˆ β–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–€ β–ˆβ–ˆ β–€β–ˆβ–ˆ β–€β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ β–ˆβ–ˆ + β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„ + β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„β–„ + + "We Have Such Sights To Show You... " diff --git a/src/assets/files/chim/license.txt b/src/assets/files/chim/license.txt new file mode 100644 index 0000000..6184437 --- /dev/null +++ b/src/assets/files/chim/license.txt @@ -0,0 +1,22 @@ +ο»ΏCopyright (c) 1997-2018 Eric Woodward (https://itsericwoodward.com). + +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. + +Camp Happy Island Massacre and all characters and locations from the software +are trademarks of Eric Woodward. \ No newline at end of file diff --git a/src/assets/files/chim/map.txt b/src/assets/files/chim/map.txt new file mode 100644 index 0000000..b763218 --- /dev/null +++ b/src/assets/files/chim/map.txt @@ -0,0 +1,24 @@ +ο»Ώ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ /\ + /^\/^\/^\/^\ T H E M O U N T A I N S /^\/^\/^\/^\ + /^\/^\/^\/^\/^\/^\/^\/^\/^\/^\(*)/^\/^\/^\/^\/^\/^\/^\ + |#++++++++++++++++++++++++++++ ^--- Cave(?) ++++++++#| + |#+ o ++++++++++++++++++++++++++++++++++++++++++++++#| + |#+ | ++++++++++++++++++++++++++++++++++++++++++++++#| + |#+ | <-- Radio Tower ++++++++++++++++++++++ [] ++++#| + LAKE |# /-\ +++++++++++++++++++++++++++++++++++ / \ ++#| LAKE + HADES |#++++++++++++++++++++++++++++++++++++ > [] [] #| HADES + |#++++++++ /^\ <-- Hunting ++++++++++ | ++ \ / ++#| + |#++++++ /| |\ Lodge(?) +++++++++ | ++++ [] ++++#| + |#+++++++ |___| +++++++++++++++++++++ | ++++++++++++#| + |#+++++++++++++++++++++++++++++++++++ \- Baseball ++#| + |#+++++++++++++++++++++++++++++++++++++++ Field(?) +#| + |#++ [====] ++++++++++++++++++++++++++++++++++++++++#| + |#++ |Camp| ++++++++++++++++++++++++++++++++++++++++#| + \#+ [====] +++++++++++++++++++++++++++++++++++++++#/ + \##############################################/ + -------------------------------------------- + # = Beach LAKE Note: Map is NOT + + = Woods HADES drawn to scale. + + ASCII Map for "Camp Happy Island Massacre" by Eric Woodward, + playable online at https://www.itsericwoodward.com/chim/. diff --git a/src/assets/files/public.aexpk b/src/assets/files/public.aexpk new file mode 100644 index 0000000..a4e96ac --- /dev/null +++ b/src/assets/files/public.aexpk @@ -0,0 +1,88 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBFvMxVQBEADbFdW3XzK9sNRWS/JHgiM1tmWE81mTMPF00oPTIoYnqvERG3pw +vGzfxWP5IcBqTAd9k62ZRcDxY63eM9H7lnc3Ad0YFifkC+HFq6sOsJnHdstoOPZW +vQffrN6A6DuRhtGRbwDfeLJgwE1VPLItCuNAB64Ocwe5hfdbVQxpRR29Vmqsmixc +TIlXE39aw20jJo7l0YVMq5n0h/d5MDnCGOp0lpD+rpq9FeEXiCXo/IjmTUUVwk2/ +1+K6W/H2NvyMWK1A94osDYWXrj5IQR3qbMSeAjwjjkYMUVXICrFoCDyjJRYZmNgp +CGZsReTRn0+HG5NEFySbyxtUTPvYDxp2DT3oa3t2XksspwxR5HZY0Y6eZI8Plwjj +NSbZXb2WJhe+gwNrEyTZpspNUfYaIDc68CXiyAS+WjUfB2R/xGNrdwHnIfURV6KQ +vmqImhqmwTlr6VN63Sc7psQ90b0BhCjr92B4jpU3Nhg6Z8lwLSbvehtT1IuvyKSl +W6dXnbje523tAtdZ++eoJiaxiSzY0WhvtFUlUg+0ARUO+WEEkzDKEJ8aNPW469fI +q7ll8Jlb+1TPAHy0YOVGuYiaH7VOtnmazvPGT8hubaBLIqyVz/+bW7rscMlVidXp +dF9ZFRkH3SRkYRK9OpnoLcgAgY4jPCxD4l3cPhDhTjp4347SH0kgr6OmoQARAQAB +tChFcmljIFdvb2R3YXJkIDxlcmljQGl0c2VyaWN3b29kd2FyZC5jb20+iQKCBBMB +CgBsAhsBBQkCUUMABQsJCAcDBRUKCQgLBRYCAwEAAh4BAheAFiEE9QYXiAAjkKOQ +1o1R2Kb2XyPYbFMFAlvNHAEtGGh0dHBzOi8vd3d3Lml0c2VyaWN3b29kd2FyZC5j +b20vcHVibGljLmFleHBrAAoJENim9l8j2GxTTIYQALUZl3JE7enYgJ2KYn1j6RmQ +k/zn21IiNoyWKNLTrEMZTHc3eFHnzXIG64ZEsZd20TSu0sqbqzQwAZd2V8bMzVSH +hOPGEctg9kxVB9FKU+6CfiJ8y2d8SVOG2/iwjkY8wDYsLB9e7oXGtW7qSb1Rya2q +rfbOo97yczLmTlI8HlqrXS7YLKcncuEQVhsc/ZPST1DMpfLVk/fJimrySUR50jN7 +Gxaff9xS7P35tvcLYCWmRXbS21iPG01OJ5GAH10ap9P+cdi8kve8XxRVXI7tI+UN +Ju6U6iN6FsmcLNFbZds+voSB/Hvx9Hoo/RZUYjRu9XTJmRAV4VdviDJ7zf2XYC0M +aVanHZAEk3hMUuODM87Wz6Ps162EaPzGmQW0TIY4ZUur/dE8BlNTyA8mi9K125d+ +y8shdkK3xOotOFbnFcATS1D5NEw28TLihd/2lHE6RgN6BRFD0GQW48GGw3D6OxmZ +TL9THi9nCDz/cs1bvsRXSR2W6Bx44GfT90rLOCtQjquRLCHnHOs7BsrPRnBFjJZr +ZypzKcnrae0ZjxPApMRE36m++kznk9kkzmOBP52929+d1tIxE3VMT/c1AKVcOO2j +Kuv5YBL2yYXn1bErjq602t/Nc346D2t9/hFT5ez62qD+WKjTjlyisSfvfWsirTZA +qcnVxg7hMkoGZw+SNs1OuQINBFvMyzsBEAC7sqUvHYLdRmuKumHLBWNRIxJ2sKZ/ +afavmqidFmFaCD4ZdNApPcyBb4HiCPuzYxK8D6Lqz9wptYeQs/FWndVvya/JyUXo +IHWVpNn3OpM5Imr2ulbqMezIjf4eXEz6ioi5cMaKI95ie+1geO1ZinzGjjIZt1U7 +hzJ9js77eGf2CphpP40GdngCYbpMvDe80pzz0bbNtBU5s53E8rTdfljAIS1GeZoB +vqJvYIGaMunLL5wPiWgWGzi01rdHA8GgZZhhJNvaJ6XsF0mqtFh81UjYCK/ggYiZ +o9BTDk1nZAjYTzHi99Oa8ca11alWH6HiyyZ25FFpjTfabNHWztJ75itGQSOGKDad +pEXX9aw+w45A9b180hWe133DU4OleBB6diUaDp2cQ7EM3Hex+20vJmKlPXwjSqqF +ODClDlY+IH4/5yk8j6vesrfDiRS/pPYIHdC5jr0/2XwnDURZw8SThigPP3u67xg2 +jJAVmasqsvMrjD8IX4nyPLsmVtqIRb+eqnCRBPvEV0D5EpCstaiQlFXe9mMRfK84 ++wenzP2fHNHJDeg6daseBBJ2RothUmCydPk5K74Ex37wE3F9vZGD8+ruIs6sa8Ma +E+5Rgzj743ZeZobLKOSoPTjLiihZUzibMYE5FwbhwY6ZXvtSS7F1DUJNNSWIo8EL +N5sYdz6Yc1o9EQARAQABiQI8BBgBCgAmFiEE9QYXiAAjkKOQ1o1R2Kb2XyPYbFMF +AlvMyzsCGwwFCQJRQwAACgkQ2Kb2XyPYbFP6gQ/8CeTThMj/dMNvyDEO4w4hY7RB +9NAVDL2EjlL5sanrrQLsnAuQPVdG2b5Qzdl1XJDJlIIyaLDOwhm9yNvXegTli1mq +Yi+q1SsQoFjZQ3KzJUKaATC6hx6jgvQbd2nj6wd2XfSWm1Vm1YCh0s2tm0X5ix4Q +phVsqe4768YLYN/Bin04cCwr8eA7RfqxPzDr43MZHnYVw4e4Igsd5IZJ6Onl0/E1 +2h1Hbt/jPeSfS4tMDQRbbf201oo6Xzc8USXFxnFRpCWgTTlZAS5uSSG91SOjSzj4 +SZ9Z9Bdt0NWkTbjnh88zsS6/Ka37G7/lNNP2Q5DaSRYIW6aLtbua4wvP9dzcY0NZ +VwYHLBmZjoJsP1wuNhV1PAxuelUeyJfZwLCaDYdUT24yNZh2XxXfvjNVkiMBStvt +g80fWdzstHSW8OEhgEyyZpVod1ihjxHqVVbxdPhFFFkjceCq6hZZME2i/fl/HWVn +L9jfrwY8Fy9J4zU+8jMIS4Mn6zeYxY90dwB4P9J62mgl6HKiIFjztnpiHdQuuU2a +xyuqgDFt9C3/Ha28gi+Td9PGT9KnqkYRzAU+BC6aVBmD+SWH2IitneRdZP6cvyay +fhUhxyxDOiHM4DXW9VVZh+nnbjLvTc8DDY71z50m+yxZv1TGE+d6+HqZhWwWBsHY +K8n5BK2kflvzGKdT10G5Ag0EW8zPuwEQANf5n6ntBPsrP6Fi/o7Cs9A7OVlo7JDH +j+LOQv9L3C3cmQf3Xw8YjaSg3cdovc7olm3B8D8itudvHl9r4hFOZJCOp5XP7Fit +wGIfiaq5Gj9t96p3ogqCSy7FSWJRLmEs92YelbVWAvxMJQCvbRLocZf8pP/N5ml+ +bVkF2pfJRIYQ3Rx4jLYH8SZmvFOAxOnfT2fPXs47t2jSKq8t+w8iPvZ7c9lvzKWv +KEKl7IaVaQLuNfGsM92yHpVOqkRfRATitE8OPTXgbFBu6gB92/UOUxq0vANNWCql +eq4fmAW9M7rSx+0Jh7mPb5AmGGz244SueO6qZFx+dfT82pb0E2FmqQh9CK3C5Emp +e2mY/c2TQ7MkzNPleIPxUDCKFmWRBRaKPzGCq5mD9OaxFHs2twFxDT9bEnBDCKIu +Pe0WbZCMoxvdvCytb/d9HAhj8DhbBrTwrwQ0NxitAhxxIudQOwzEg/ZevA6knKUE +4Ylnk7F8QOuZOJWffUcLHCC1qCfCzimS+Qmm9S58Bu3cNjheEmaCTCQxJrj+EO05 +NmkcmAVWLcdVlYwtWZGPeobRexLAfZ74p04cYCZVCqOKoLqEqZvw5qyfi02IV5oz +37uWDqjocj3RvH+hSxr+yu//QclK4h8cDC7BaCVjhRCDAUBmgYc9mezfsFws8Roy +uO6LqgB7vk9vABEBAAGJBHIEGAEKACYWIQT1BheIACOQo5DWjVHYpvZfI9hsUwUC +W8zPuwIbAgUJAlFDAAJACRDYpvZfI9hsU8F0IAQZAQoAHRYhBFPeVu8mtxUoJnhw +Bh0wy7oZ2EefBQJbzM+7AAoJEB0wy7oZ2EefoTkP/AgnRJ8Xt2p9rFnbV5ahxGTp +YAdhpaTn9TlPOW9eJq1OQ1QEvFjsqjDhMby1bC1P5MjI0yojdJhptkpA06gd+WDc +WEguAjeyQrfvyj+6io/xcU4juyRIOBfHa7NiUgIkS5IW6njyoVWOhs1UrsOEe12z +OkuwkrwunwsyTJcEjlX4yrITYcXCzCjdMEnx4uX0Tt7Kb9t/w+IV594qo/8ml1BF +wat9bl01pl1yClmhkXf8mt7pPdVZgMnpn05PLRTIZyii18lExvdG2QmkmqBvyF86 +agzKdrPKKNi0Wx3ruVl1uU/mpi7Hy93O+A1kUrzBGg9HbiAeCnRlrmpWdC+yYhJn +mBUrCwd2hUDf09kIb4d/T9sTejPlnhoi1NgSLG9rvBWtj9OhFAeodz5xTJ/psKz8 +KSvo/VRdUUM9cxTFKx7iy5XHCBy226ECqB73dkfka2+iEeVUXsOlWvlDZEutsHc8 +en8ZXo5PHWZ7oa3/N0wjXdAe5Ed52QRFjB+ziF4F4Yin9/2Vv3sNdBaXmBz6ENsR +Ae7KZRA7Aoi5KuST/GW5M1jAsc4OBqluoTyp48Q2QDezOdHeSprw9moQGUgHHCQL +rpmd58mgkrayW8WMdrNQvYtcrS2rhlEz1HxElFs9CtUYBnZ4ThIsAMDalLcCwX4Y +vChOcyg8DgnKr8SJk93I/jYP/RRIlBjVqQTMG8XqTCPl8n73oB461LdgdrGCKO4w +3aWu7euuEUw1Odg0bmiLwg7RGm0Q5QvsRciWkWj33G1AXaU4GP3uh6AU7OArGvCw +EQg54118a+nl1ItlXkN1PTjvpHuKlqQYKHZrZ4NUrXxgdOjYUsoYdWSgYDS1PZLj +26RTzT7cKJprYyPYKW38Zt7pIIj9hrX5f3E3PzWcj7dF4C6GNpsB/bi6NJevWaZD +BzMqv56Uoe2MqDAU5XbKEHKMjtCbFk2jZ/mPI8xpcOeQAbBO8dSSBNFs8OeP2Zzd +LLpSHhs8RXiwj5egFxWvCFgXylsIJBtEDQtDrGN3JCTnfmHgO2BUh+U+FKOTwO5K +2bSi5G2Byjhls/Qkjp824cz1FXZJZIUOjTs+lsH+EnoGn7dzh93pLHdnR+H2NmnM +26Jr7UDcQ3Q9CaBy4nAizh8PQlzaLB3iYSO1xUcvmRWqHHRKlWWG0we8KOuORxGc +BGVjBnHqnSJKJKHxuYLw9ed/B6uK1jJNJUSwlilZgQfr1LfRqYok0NcNKymDh3Gn +UGDy3rJvwMuUm06dmPtBAIWJ0KZGJIKtggiFOKpO28NSEEy6Zbca7tQL2SLqX821 +JuZSrGcR0Q1rJkoLVSN1bDs0H5qwkxFRfrVVhebmHIdXFcFh1xxvLMVFXz+C6Fc/ +cTTc +=tIaI +-----END PGP PUBLIC KEY BLOCK----- diff --git a/src/assets/fonts/exo2/Exo2-Bold-webfont.eot b/src/assets/fonts/exo2/Exo2-Bold-webfont.eot new file mode 100644 index 0000000..1c4607a Binary files /dev/null and b/src/assets/fonts/exo2/Exo2-Bold-webfont.eot differ diff --git a/src/assets/fonts/exo2/Exo2-Bold-webfont.svg b/src/assets/fonts/exo2/Exo2-Bold-webfont.svg new file mode 100644 index 0000000..3275ac4 --- /dev/null +++ b/src/assets/fonts/exo2/Exo2-Bold-webfont.svg @@ -0,0 +1,1718 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/fonts/exo2/Exo2-Bold-webfont.ttf b/src/assets/fonts/exo2/Exo2-Bold-webfont.ttf new file mode 100644 index 0000000..fe15c43 Binary files /dev/null and b/src/assets/fonts/exo2/Exo2-Bold-webfont.ttf differ diff --git a/src/assets/fonts/exo2/Exo2-Bold-webfont.woff b/src/assets/fonts/exo2/Exo2-Bold-webfont.woff new file mode 100644 index 0000000..ed5b79d Binary files /dev/null and b/src/assets/fonts/exo2/Exo2-Bold-webfont.woff differ diff --git a/src/assets/fonts/exo2/Exo2-BoldItalic-webfont.eot b/src/assets/fonts/exo2/Exo2-BoldItalic-webfont.eot new file mode 100644 index 0000000..1201d58 Binary files /dev/null and b/src/assets/fonts/exo2/Exo2-BoldItalic-webfont.eot differ diff --git a/src/assets/fonts/exo2/Exo2-BoldItalic-webfont.svg b/src/assets/fonts/exo2/Exo2-BoldItalic-webfont.svg new file mode 100644 index 0000000..e042e6d --- /dev/null +++ b/src/assets/fonts/exo2/Exo2-BoldItalic-webfont.svg @@ -0,0 +1,1694 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/fonts/exo2/Exo2-BoldItalic-webfont.ttf b/src/assets/fonts/exo2/Exo2-BoldItalic-webfont.ttf new file mode 100644 index 0000000..cbfe6d8 Binary files /dev/null and b/src/assets/fonts/exo2/Exo2-BoldItalic-webfont.ttf differ diff --git a/src/assets/fonts/exo2/Exo2-BoldItalic-webfont.woff b/src/assets/fonts/exo2/Exo2-BoldItalic-webfont.woff new file mode 100644 index 0000000..4f18a95 Binary files /dev/null and b/src/assets/fonts/exo2/Exo2-BoldItalic-webfont.woff differ diff --git a/src/assets/fonts/exo2/Exo2-Italic-webfont.eot b/src/assets/fonts/exo2/Exo2-Italic-webfont.eot new file mode 100644 index 0000000..dcc8a59 Binary files /dev/null and b/src/assets/fonts/exo2/Exo2-Italic-webfont.eot differ diff --git a/src/assets/fonts/exo2/Exo2-Italic-webfont.svg b/src/assets/fonts/exo2/Exo2-Italic-webfont.svg new file mode 100644 index 0000000..c9c0d10 --- /dev/null +++ b/src/assets/fonts/exo2/Exo2-Italic-webfont.svg @@ -0,0 +1,1641 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/fonts/exo2/Exo2-Italic-webfont.ttf b/src/assets/fonts/exo2/Exo2-Italic-webfont.ttf new file mode 100644 index 0000000..0a6f68b Binary files /dev/null and b/src/assets/fonts/exo2/Exo2-Italic-webfont.ttf differ diff --git a/src/assets/fonts/exo2/Exo2-Italic-webfont.woff b/src/assets/fonts/exo2/Exo2-Italic-webfont.woff new file mode 100644 index 0000000..d33e602 Binary files /dev/null and b/src/assets/fonts/exo2/Exo2-Italic-webfont.woff differ diff --git a/src/assets/fonts/exo2/Exo2-Regular-webfont.eot b/src/assets/fonts/exo2/Exo2-Regular-webfont.eot new file mode 100644 index 0000000..93a440d Binary files /dev/null and b/src/assets/fonts/exo2/Exo2-Regular-webfont.eot differ diff --git a/src/assets/fonts/exo2/Exo2-Regular-webfont.svg b/src/assets/fonts/exo2/Exo2-Regular-webfont.svg new file mode 100644 index 0000000..eac205f --- /dev/null +++ b/src/assets/fonts/exo2/Exo2-Regular-webfont.svg @@ -0,0 +1,1648 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/assets/fonts/exo2/Exo2-Regular-webfont.ttf b/src/assets/fonts/exo2/Exo2-Regular-webfont.ttf new file mode 100644 index 0000000..193aa15 Binary files /dev/null and b/src/assets/fonts/exo2/Exo2-Regular-webfont.ttf differ diff --git a/src/assets/fonts/exo2/Exo2-Regular-webfont.woff b/src/assets/fonts/exo2/Exo2-Regular-webfont.woff new file mode 100644 index 0000000..3c8fef9 Binary files /dev/null and b/src/assets/fonts/exo2/Exo2-Regular-webfont.woff differ diff --git a/src/assets/fonts/exo2/SIL Open Font License.txt b/src/assets/fonts/exo2/SIL Open Font License.txt new file mode 100644 index 0000000..cef9c53 --- /dev/null +++ b/src/assets/fonts/exo2/SIL Open Font License.txt @@ -0,0 +1,43 @@ +Copyright (c) 2013, Natanael Gama (www.ndiscovered.com . info(at)ndiscovered.com), with Reserved Font Name Exo. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. + +The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the copyright statement(s). + +"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. + +"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. + +5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. \ No newline at end of file diff --git a/src/assets/images/404-opte-1000x800.jpg b/src/assets/images/404-opte-1000x800.jpg new file mode 100644 index 0000000..ce16d13 Binary files /dev/null and b/src/assets/images/404-opte-1000x800.jpg differ diff --git a/src/assets/images/404/hole-bg-1100x1238-50.jpg b/src/assets/images/404/hole-bg-1100x1238-50.jpg new file mode 100644 index 0000000..c7358e0 Binary files /dev/null and b/src/assets/images/404/hole-bg-1100x1238-50.jpg differ diff --git a/src/assets/images/404/hole-bg-1100x900-50.jpg b/src/assets/images/404/hole-bg-1100x900-50.jpg new file mode 100644 index 0000000..1d03f24 Binary files /dev/null and b/src/assets/images/404/hole-bg-1100x900-50.jpg differ diff --git a/src/assets/images/404/hole-bg-1600x900-50.jpg b/src/assets/images/404/hole-bg-1600x900-50.jpg new file mode 100644 index 0000000..77e416d Binary files /dev/null and b/src/assets/images/404/hole-bg-1600x900-50.jpg differ diff --git a/src/assets/images/404/hole-bg.jpg b/src/assets/images/404/hole-bg.jpg new file mode 100644 index 0000000..c7358e0 Binary files /dev/null and b/src/assets/images/404/hole-bg.jpg differ diff --git a/src/assets/images/anachronism/ana_logo.jpg b/src/assets/images/anachronism/ana_logo.jpg new file mode 100644 index 0000000..3f611ba Binary files /dev/null and b/src/assets/images/anachronism/ana_logo.jpg differ diff --git a/src/assets/images/anachronism/immortals/amanda_darieux.jpg b/src/assets/images/anachronism/immortals/amanda_darieux.jpg new file mode 100644 index 0000000..b2fea9b Binary files /dev/null and b/src/assets/images/anachronism/immortals/amanda_darieux.jpg differ diff --git a/src/assets/images/anachronism/immortals/antonius_kalas.jpg b/src/assets/images/anachronism/immortals/antonius_kalas.jpg new file mode 100644 index 0000000..88c276e Binary files /dev/null and b/src/assets/images/anachronism/immortals/antonius_kalas.jpg differ diff --git a/src/assets/images/anachronism/immortals/black_longcoat.jpg b/src/assets/images/anachronism/immortals/black_longcoat.jpg new file mode 100644 index 0000000..6a941a6 Binary files /dev/null and b/src/assets/images/anachronism/immortals/black_longcoat.jpg differ diff --git a/src/assets/images/anachronism/immortals/black_trenchcoat.jpg b/src/assets/images/anachronism/immortals/black_trenchcoat.jpg new file mode 100644 index 0000000..04861af Binary files /dev/null and b/src/assets/images/anachronism/immortals/black_trenchcoat.jpg differ diff --git a/src/assets/images/anachronism/immortals/clamshell_rapier.jpg b/src/assets/images/anachronism/immortals/clamshell_rapier.jpg new file mode 100644 index 0000000..fd52cb3 Binary files /dev/null and b/src/assets/images/anachronism/immortals/clamshell_rapier.jpg differ diff --git a/src/assets/images/anachronism/immortals/clan_macleod.jpg b/src/assets/images/anachronism/immortals/clan_macleod.jpg new file mode 100644 index 0000000..fe35afd Binary files /dev/null and b/src/assets/images/anachronism/immortals/clan_macleod.jpg differ diff --git a/src/assets/images/anachronism/immortals/connor_macleod.jpg b/src/assets/images/anachronism/immortals/connor_macleod.jpg new file mode 100644 index 0000000..3ca8b2d Binary files /dev/null and b/src/assets/images/anachronism/immortals/connor_macleod.jpg differ diff --git a/src/assets/images/anachronism/immortals/darius.jpg b/src/assets/images/anachronism/immortals/darius.jpg new file mode 100644 index 0000000..b655acc Binary files /dev/null and b/src/assets/images/anachronism/immortals/darius.jpg differ diff --git a/src/assets/images/anachronism/immortals/dragons_head_katana.jpg b/src/assets/images/anachronism/immortals/dragons_head_katana.jpg new file mode 100644 index 0000000..07ac29a Binary files /dev/null and b/src/assets/images/anachronism/immortals/dragons_head_katana.jpg differ diff --git a/src/assets/images/anachronism/immortals/duncan_macleod.jpg b/src/assets/images/anachronism/immortals/duncan_macleod.jpg new file mode 100644 index 0000000..cd408f9 Binary files /dev/null and b/src/assets/images/anachronism/immortals/duncan_macleod.jpg differ diff --git a/src/assets/images/anachronism/immortals/four_horsemen.jpg b/src/assets/images/anachronism/immortals/four_horsemen.jpg new file mode 100644 index 0000000..27b2ebd Binary files /dev/null and b/src/assets/images/anachronism/immortals/four_horsemen.jpg differ diff --git a/src/assets/images/anachronism/immortals/glenfinnan.jpg b/src/assets/images/anachronism/immortals/glenfinnan.jpg new file mode 100644 index 0000000..b64b82f Binary files /dev/null and b/src/assets/images/anachronism/immortals/glenfinnan.jpg differ diff --git a/src/assets/images/anachronism/immortals/grey_trenchcoat.jpg b/src/assets/images/anachronism/immortals/grey_trenchcoat.jpg new file mode 100644 index 0000000..46f16e2 Binary files /dev/null and b/src/assets/images/anachronism/immortals/grey_trenchcoat.jpg differ diff --git a/src/assets/images/anachronism/immortals/holy_ground.jpg b/src/assets/images/anachronism/immortals/holy_ground.jpg new file mode 100644 index 0000000..aa1abd2 Binary files /dev/null and b/src/assets/images/anachronism/immortals/holy_ground.jpg differ diff --git a/src/assets/images/anachronism/immortals/hugh_fitzcairn.jpg b/src/assets/images/anachronism/immortals/hugh_fitzcairn.jpg new file mode 100644 index 0000000..005f31e Binary files /dev/null and b/src/assets/images/anachronism/immortals/hugh_fitzcairn.jpg differ diff --git a/src/assets/images/anachronism/immortals/immortal_healing.jpg b/src/assets/images/anachronism/immortals/immortal_healing.jpg new file mode 100644 index 0000000..28ee62d Binary files /dev/null and b/src/assets/images/anachronism/immortals/immortal_healing.jpg differ diff --git a/src/assets/images/anachronism/immortals/jacob_kell.jpg b/src/assets/images/anachronism/immortals/jacob_kell.jpg new file mode 100644 index 0000000..6c0c5ef Binary files /dev/null and b/src/assets/images/anachronism/immortals/jacob_kell.jpg differ diff --git a/src/assets/images/anachronism/immortals/james_horton.jpg b/src/assets/images/anachronism/immortals/james_horton.jpg new file mode 100644 index 0000000..ca5391f Binary files /dev/null and b/src/assets/images/anachronism/immortals/james_horton.jpg differ diff --git a/src/assets/images/anachronism/immortals/joe_dawson.jpg b/src/assets/images/anachronism/immortals/joe_dawson.jpg new file mode 100644 index 0000000..f3033f8 Binary files /dev/null and b/src/assets/images/anachronism/immortals/joe_dawson.jpg differ diff --git a/src/assets/images/anachronism/immortals/juan_sanchez_ramirez_tak_ne.jpg b/src/assets/images/anachronism/immortals/juan_sanchez_ramirez_tak_ne.jpg new file mode 100644 index 0000000..3dcccca Binary files /dev/null and b/src/assets/images/anachronism/immortals/juan_sanchez_ramirez_tak_ne.jpg differ diff --git a/src/assets/images/anachronism/immortals/kells_gang.jpg b/src/assets/images/anachronism/immortals/kells_gang.jpg new file mode 100644 index 0000000..7e40c19 Binary files /dev/null and b/src/assets/images/anachronism/immortals/kells_gang.jpg differ diff --git a/src/assets/images/anachronism/immortals/kronos.jpg b/src/assets/images/anachronism/immortals/kronos.jpg new file mode 100644 index 0000000..6bf4c43 Binary files /dev/null and b/src/assets/images/anachronism/immortals/kronos.jpg differ diff --git a/src/assets/images/anachronism/immortals/kurgans_broadsword.jpg b/src/assets/images/anachronism/immortals/kurgans_broadsword.jpg new file mode 100644 index 0000000..406d50b Binary files /dev/null and b/src/assets/images/anachronism/immortals/kurgans_broadsword.jpg differ diff --git a/src/assets/images/anachronism/immortals/leather_coat.jpg b/src/assets/images/anachronism/immortals/leather_coat.jpg new file mode 100644 index 0000000..43b7f2f Binary files /dev/null and b/src/assets/images/anachronism/immortals/leather_coat.jpg differ diff --git a/src/assets/images/anachronism/immortals/leather_jacket.jpg b/src/assets/images/anachronism/immortals/leather_jacket.jpg new file mode 100644 index 0000000..a535316 Binary files /dev/null and b/src/assets/images/anachronism/immortals/leather_jacket.jpg differ diff --git a/src/assets/images/anachronism/immortals/masamune_katana.jpg b/src/assets/images/anachronism/immortals/masamune_katana.jpg new file mode 100644 index 0000000..bc04045 Binary files /dev/null and b/src/assets/images/anachronism/immortals/masamune_katana.jpg differ diff --git a/src/assets/images/anachronism/immortals/methos.jpg b/src/assets/images/anachronism/immortals/methos.jpg new file mode 100644 index 0000000..5f543a5 Binary files /dev/null and b/src/assets/images/anachronism/immortals/methos.jpg differ diff --git a/src/assets/images/anachronism/immortals/methos_broadsword.jpg b/src/assets/images/anachronism/immortals/methos_broadsword.jpg new file mode 100644 index 0000000..3377a68 Binary files /dev/null and b/src/assets/images/anachronism/immortals/methos_broadsword.jpg differ diff --git a/src/assets/images/anachronism/immortals/motorcycle_jacket.jpg b/src/assets/images/anachronism/immortals/motorcycle_jacket.jpg new file mode 100644 index 0000000..5c2f224 Binary files /dev/null and b/src/assets/images/anachronism/immortals/motorcycle_jacket.jpg differ diff --git a/src/assets/images/anachronism/immortals/quickening.jpg b/src/assets/images/anachronism/immortals/quickening.jpg new file mode 100644 index 0000000..0dd2922 Binary files /dev/null and b/src/assets/images/anachronism/immortals/quickening.jpg differ diff --git a/src/assets/images/anachronism/immortals/richie_ryan.jpg b/src/assets/images/anachronism/immortals/richie_ryan.jpg new file mode 100644 index 0000000..5fff6c0 Binary files /dev/null and b/src/assets/images/anachronism/immortals/richie_ryan.jpg differ diff --git a/src/assets/images/anachronism/immortals/rocker_jacket.jpg b/src/assets/images/anachronism/immortals/rocker_jacket.jpg new file mode 100644 index 0000000..418f036 Binary files /dev/null and b/src/assets/images/anachronism/immortals/rocker_jacket.jpg differ diff --git a/src/assets/images/anachronism/immortals/tessa_noel.jpg b/src/assets/images/anachronism/immortals/tessa_noel.jpg new file mode 100644 index 0000000..065e21c Binary files /dev/null and b/src/assets/images/anachronism/immortals/tessa_noel.jpg differ diff --git a/src/assets/images/anachronism/immortals/the_game.jpg b/src/assets/images/anachronism/immortals/the_game.jpg new file mode 100644 index 0000000..37b9070 Binary files /dev/null and b/src/assets/images/anachronism/immortals/the_game.jpg differ diff --git a/src/assets/images/anachronism/immortals/the_hunters.jpg b/src/assets/images/anachronism/immortals/the_hunters.jpg new file mode 100644 index 0000000..279c8cd Binary files /dev/null and b/src/assets/images/anachronism/immortals/the_hunters.jpg differ diff --git a/src/assets/images/anachronism/immortals/the_kurgan.jpg b/src/assets/images/anachronism/immortals/the_kurgan.jpg new file mode 100644 index 0000000..1ea6aa9 Binary files /dev/null and b/src/assets/images/anachronism/immortals/the_kurgan.jpg differ diff --git a/src/assets/images/anachronism/immortals/the_prize.jpg b/src/assets/images/anachronism/immortals/the_prize.jpg new file mode 100644 index 0000000..a2f307a Binary files /dev/null and b/src/assets/images/anachronism/immortals/the_prize.jpg differ diff --git a/src/assets/images/anachronism/immortals/the_sword_of_kronos.jpg b/src/assets/images/anachronism/immortals/the_sword_of_kronos.jpg new file mode 100644 index 0000000..84963e8 Binary files /dev/null and b/src/assets/images/anachronism/immortals/the_sword_of_kronos.jpg differ diff --git a/src/assets/images/anachronism/immortals/the_watchers.jpg b/src/assets/images/anachronism/immortals/the_watchers.jpg new file mode 100644 index 0000000..9837cc1 Binary files /dev/null and b/src/assets/images/anachronism/immortals/the_watchers.jpg differ diff --git a/src/assets/images/anachronism/immortals/xavier_saint_cloud.jpg b/src/assets/images/anachronism/immortals/xavier_saint_cloud.jpg new file mode 100644 index 0000000..7452d0d Binary files /dev/null and b/src/assets/images/anachronism/immortals/xavier_saint_cloud.jpg differ diff --git a/src/assets/images/anachronism/links/abraham_lincoln.jpg b/src/assets/images/anachronism/links/abraham_lincoln.jpg new file mode 100644 index 0000000..f4aa0c8 Binary files /dev/null and b/src/assets/images/anachronism/links/abraham_lincoln.jpg differ diff --git a/src/assets/images/anachronism/links/billy_the_kid.jpg b/src/assets/images/anachronism/links/billy_the_kid.jpg new file mode 100644 index 0000000..12c36fd Binary files /dev/null and b/src/assets/images/anachronism/links/billy_the_kid.jpg differ diff --git a/src/assets/images/anachronism/links/george_washington.jpg b/src/assets/images/anachronism/links/george_washington.jpg new file mode 100644 index 0000000..31df375 Binary files /dev/null and b/src/assets/images/anachronism/links/george_washington.jpg differ diff --git a/src/assets/images/anachronism/links/robert_e_lee.jpg b/src/assets/images/anachronism/links/robert_e_lee.jpg new file mode 100644 index 0000000..b8007da Binary files /dev/null and b/src/assets/images/anachronism/links/robert_e_lee.jpg differ diff --git a/src/assets/images/anachronism/links/stetson_hat.jpg b/src/assets/images/anachronism/links/stetson_hat.jpg new file mode 100644 index 0000000..8f7e0a1 Binary files /dev/null and b/src/assets/images/anachronism/links/stetson_hat.jpg differ diff --git a/src/assets/images/anachronism/links/the_dictator.jpg b/src/assets/images/anachronism/links/the_dictator.jpg new file mode 100644 index 0000000..0d4db24 Binary files /dev/null and b/src/assets/images/anachronism/links/the_dictator.jpg differ diff --git a/src/assets/images/anachronism/links/the_us_constitution.jpg b/src/assets/images/anachronism/links/the_us_constitution.jpg new file mode 100644 index 0000000..0f35077 Binary files /dev/null and b/src/assets/images/anachronism/links/the_us_constitution.jpg differ diff --git a/src/assets/images/anachronism/links/ulysses_s_grant.jpg b/src/assets/images/anachronism/links/ulysses_s_grant.jpg new file mode 100644 index 0000000..9086f5b Binary files /dev/null and b/src/assets/images/anachronism/links/ulysses_s_grant.jpg differ diff --git a/src/assets/images/anachronism/links/wyatt_earp.jpg b/src/assets/images/anachronism/links/wyatt_earp.jpg new file mode 100644 index 0000000..d7d26e4 Binary files /dev/null and b/src/assets/images/anachronism/links/wyatt_earp.jpg differ diff --git a/src/assets/images/anachronism/others/bruce_lee.jpg b/src/assets/images/anachronism/others/bruce_lee.jpg new file mode 100644 index 0000000..3535f1c Binary files /dev/null and b/src/assets/images/anachronism/others/bruce_lee.jpg differ diff --git a/src/assets/images/anachronism/others/elric_of_melnibone.jpg b/src/assets/images/anachronism/others/elric_of_melnibone.jpg new file mode 100644 index 0000000..33c2703 Binary files /dev/null and b/src/assets/images/anachronism/others/elric_of_melnibone.jpg differ diff --git a/src/assets/images/anachronism/others/gods_of_law__chaos.jpg b/src/assets/images/anachronism/others/gods_of_law__chaos.jpg new file mode 100644 index 0000000..eb1a17f Binary files /dev/null and b/src/assets/images/anachronism/others/gods_of_law__chaos.jpg differ diff --git a/src/assets/images/anachronism/others/john_blackthorn.jpg b/src/assets/images/anachronism/others/john_blackthorn.jpg new file mode 100644 index 0000000..9702280 Binary files /dev/null and b/src/assets/images/anachronism/others/john_blackthorn.jpg differ diff --git a/src/assets/images/anachronism/others/long_sky.jpg b/src/assets/images/anachronism/others/long_sky.jpg new file mode 100644 index 0000000..0052422 Binary files /dev/null and b/src/assets/images/anachronism/others/long_sky.jpg differ diff --git a/src/assets/images/anachronism/others/moonglum_of_elwher.jpg b/src/assets/images/anachronism/others/moonglum_of_elwher.jpg new file mode 100644 index 0000000..04fd554 Binary files /dev/null and b/src/assets/images/anachronism/others/moonglum_of_elwher.jpg differ diff --git a/src/assets/images/anachronism/others/nameless.jpg b/src/assets/images/anachronism/others/nameless.jpg new file mode 100644 index 0000000..7bef17b Binary files /dev/null and b/src/assets/images/anachronism/others/nameless.jpg differ diff --git a/src/assets/images/anachronism/others/royal_armor_of_melnibone.jpg b/src/assets/images/anachronism/others/royal_armor_of_melnibone.jpg new file mode 100644 index 0000000..a5f05a7 Binary files /dev/null and b/src/assets/images/anachronism/others/royal_armor_of_melnibone.jpg differ diff --git a/src/assets/images/anachronism/others/stormbringer.jpg b/src/assets/images/anachronism/others/stormbringer.jpg new file mode 100644 index 0000000..37862fd Binary files /dev/null and b/src/assets/images/anachronism/others/stormbringer.jpg differ diff --git a/src/assets/images/anachronism/us_americans/abraham_lincoln.jpg b/src/assets/images/anachronism/us_americans/abraham_lincoln.jpg new file mode 100644 index 0000000..8923b99 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/abraham_lincoln.jpg differ diff --git a/src/assets/images/anachronism/us_americans/benjamin_franklin.jpg b/src/assets/images/anachronism/us_americans/benjamin_franklin.jpg new file mode 100644 index 0000000..f6c4709 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/benjamin_franklin.jpg differ diff --git a/src/assets/images/anachronism/us_americans/billy_the_kid.jpg b/src/assets/images/anachronism/us_americans/billy_the_kid.jpg new file mode 100644 index 0000000..d751c14 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/billy_the_kid.jpg differ diff --git a/src/assets/images/anachronism/us_americans/cavalry_sabre.jpg b/src/assets/images/anachronism/us_americans/cavalry_sabre.jpg new file mode 100644 index 0000000..8268c31 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/cavalry_sabre.jpg differ diff --git a/src/assets/images/anachronism/us_americans/colonial_tricorne.jpg b/src/assets/images/anachronism/us_americans/colonial_tricorne.jpg new file mode 100644 index 0000000..e8cedf2 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/colonial_tricorne.jpg differ diff --git a/src/assets/images/anachronism/us_americans/colt_45_single_action.jpg b/src/assets/images/anachronism/us_americans/colt_45_single_action.jpg new file mode 100644 index 0000000..8e55489 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/colt_45_single_action.jpg differ diff --git a/src/assets/images/anachronism/us_americans/confederate_grey.jpg b/src/assets/images/anachronism/us_americans/confederate_grey.jpg new file mode 100644 index 0000000..46bea93 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/confederate_grey.jpg differ diff --git a/src/assets/images/anachronism/us_americans/deputization.jpg b/src/assets/images/anachronism/us_americans/deputization.jpg new file mode 100644 index 0000000..a774468 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/deputization.jpg differ diff --git a/src/assets/images/anachronism/us_americans/earp_vendetta_ride.jpg b/src/assets/images/anachronism/us_americans/earp_vendetta_ride.jpg new file mode 100644 index 0000000..208c101 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/earp_vendetta_ride.jpg differ diff --git a/src/assets/images/anachronism/us_americans/george_washington.jpg b/src/assets/images/anachronism/us_americans/george_washington.jpg new file mode 100644 index 0000000..5074522 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/george_washington.jpg differ diff --git a/src/assets/images/anachronism/us_americans/jefferson_davis.jpg b/src/assets/images/anachronism/us_americans/jefferson_davis.jpg new file mode 100644 index 0000000..eaef5fb Binary files /dev/null and b/src/assets/images/anachronism/us_americans/jefferson_davis.jpg differ diff --git a/src/assets/images/anachronism/us_americans/john_henry_doc_holliday.jpg b/src/assets/images/anachronism/us_americans/john_henry_doc_holliday.jpg new file mode 100644 index 0000000..709a42c Binary files /dev/null and b/src/assets/images/anachronism/us_americans/john_henry_doc_holliday.jpg differ diff --git a/src/assets/images/anachronism/us_americans/lincoln_county_regulators.jpg b/src/assets/images/anachronism/us_americans/lincoln_county_regulators.jpg new file mode 100644 index 0000000..28c0877 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/lincoln_county_regulators.jpg differ diff --git a/src/assets/images/anachronism/us_americans/robert_e_lee.jpg b/src/assets/images/anachronism/us_americans/robert_e_lee.jpg new file mode 100644 index 0000000..46612b2 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/robert_e_lee.jpg differ diff --git a/src/assets/images/anachronism/us_americans/springfield_musket.jpg b/src/assets/images/anachronism/us_americans/springfield_musket.jpg new file mode 100644 index 0000000..85b48f7 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/springfield_musket.jpg differ diff --git a/src/assets/images/anachronism/us_americans/states_rights.jpg b/src/assets/images/anachronism/us_americans/states_rights.jpg new file mode 100644 index 0000000..6f4adb8 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/states_rights.jpg differ diff --git a/src/assets/images/anachronism/us_americans/stetson_hat.jpg b/src/assets/images/anachronism/us_americans/stetson_hat.jpg new file mode 100644 index 0000000..d0c9fcd Binary files /dev/null and b/src/assets/images/anachronism/us_americans/stetson_hat.jpg differ diff --git a/src/assets/images/anachronism/us_americans/the_dictator.jpg b/src/assets/images/anachronism/us_americans/the_dictator.jpg new file mode 100644 index 0000000..a7c1946 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/the_dictator.jpg differ diff --git a/src/assets/images/anachronism/us_americans/the_us_constitution.jpg b/src/assets/images/anachronism/us_americans/the_us_constitution.jpg new file mode 100644 index 0000000..ec103b6 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/the_us_constitution.jpg differ diff --git a/src/assets/images/anachronism/us_americans/ulysses_s_grant.jpg b/src/assets/images/anachronism/us_americans/ulysses_s_grant.jpg new file mode 100644 index 0000000..d18f519 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/ulysses_s_grant.jpg differ diff --git a/src/assets/images/anachronism/us_americans/union_blue.jpg b/src/assets/images/anachronism/us_americans/union_blue.jpg new file mode 100644 index 0000000..cfe7524 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/union_blue.jpg differ diff --git a/src/assets/images/anachronism/us_americans/wanted_man.jpg b/src/assets/images/anachronism/us_americans/wanted_man.jpg new file mode 100644 index 0000000..b869c6d Binary files /dev/null and b/src/assets/images/anachronism/us_americans/wanted_man.jpg differ diff --git a/src/assets/images/anachronism/us_americans/west_point.jpg b/src/assets/images/anachronism/us_americans/west_point.jpg new file mode 100644 index 0000000..caad52b Binary files /dev/null and b/src/assets/images/anachronism/us_americans/west_point.jpg differ diff --git a/src/assets/images/anachronism/us_americans/winchester_model_1873_rifle.jpg b/src/assets/images/anachronism/us_americans/winchester_model_1873_rifle.jpg new file mode 100644 index 0000000..b4fc43e Binary files /dev/null and b/src/assets/images/anachronism/us_americans/winchester_model_1873_rifle.jpg differ diff --git a/src/assets/images/anachronism/us_americans/wyatt_earp.jpg b/src/assets/images/anachronism/us_americans/wyatt_earp.jpg new file mode 100644 index 0000000..ee4dfc8 Binary files /dev/null and b/src/assets/images/anachronism/us_americans/wyatt_earp.jpg differ diff --git a/src/assets/images/code-bg.jpg b/src/assets/images/code-bg.jpg new file mode 100644 index 0000000..3098d43 Binary files /dev/null and b/src/assets/images/code-bg.jpg differ diff --git a/src/assets/images/eric-8bit.gif b/src/assets/images/eric-8bit.gif new file mode 100644 index 0000000..9f60f30 Binary files /dev/null and b/src/assets/images/eric-8bit.gif differ diff --git a/src/assets/images/favicons/android-icon-144x144.png b/src/assets/images/favicons/android-icon-144x144.png new file mode 100644 index 0000000..ca66e27 Binary files /dev/null and b/src/assets/images/favicons/android-icon-144x144.png differ diff --git a/src/assets/images/favicons/android-icon-192x192.png b/src/assets/images/favicons/android-icon-192x192.png new file mode 100644 index 0000000..afd52f1 Binary files /dev/null and b/src/assets/images/favicons/android-icon-192x192.png differ diff --git a/src/assets/images/favicons/android-icon-36x36.png b/src/assets/images/favicons/android-icon-36x36.png new file mode 100644 index 0000000..f146451 Binary files /dev/null and b/src/assets/images/favicons/android-icon-36x36.png differ diff --git a/src/assets/images/favicons/android-icon-48x48.png b/src/assets/images/favicons/android-icon-48x48.png new file mode 100644 index 0000000..9ef4111 Binary files /dev/null and b/src/assets/images/favicons/android-icon-48x48.png differ diff --git a/src/assets/images/favicons/android-icon-72x72.png b/src/assets/images/favicons/android-icon-72x72.png new file mode 100644 index 0000000..bd5dec5 Binary files /dev/null and b/src/assets/images/favicons/android-icon-72x72.png differ diff --git a/src/assets/images/favicons/android-icon-96x96.png b/src/assets/images/favicons/android-icon-96x96.png new file mode 100644 index 0000000..4de3aef Binary files /dev/null and b/src/assets/images/favicons/android-icon-96x96.png differ diff --git a/src/assets/images/favicons/apple-icon-114x114.png b/src/assets/images/favicons/apple-icon-114x114.png new file mode 100644 index 0000000..7334212 Binary files /dev/null and b/src/assets/images/favicons/apple-icon-114x114.png differ diff --git a/src/assets/images/favicons/apple-icon-120x120.png b/src/assets/images/favicons/apple-icon-120x120.png new file mode 100644 index 0000000..4d6e989 Binary files /dev/null and b/src/assets/images/favicons/apple-icon-120x120.png differ diff --git a/src/assets/images/favicons/apple-icon-144x144.png b/src/assets/images/favicons/apple-icon-144x144.png new file mode 100644 index 0000000..ca66e27 Binary files /dev/null and b/src/assets/images/favicons/apple-icon-144x144.png differ diff --git a/src/assets/images/favicons/apple-icon-152x152.png b/src/assets/images/favicons/apple-icon-152x152.png new file mode 100644 index 0000000..3f437ad Binary files /dev/null and b/src/assets/images/favicons/apple-icon-152x152.png differ diff --git a/src/assets/images/favicons/apple-icon-180x180.png b/src/assets/images/favicons/apple-icon-180x180.png new file mode 100644 index 0000000..1649c4b Binary files /dev/null and b/src/assets/images/favicons/apple-icon-180x180.png differ diff --git a/src/assets/images/favicons/apple-icon-57x57.png b/src/assets/images/favicons/apple-icon-57x57.png new file mode 100644 index 0000000..45cf0fd Binary files /dev/null and b/src/assets/images/favicons/apple-icon-57x57.png differ diff --git a/src/assets/images/favicons/apple-icon-60x60.png b/src/assets/images/favicons/apple-icon-60x60.png new file mode 100644 index 0000000..f14bdce Binary files /dev/null and b/src/assets/images/favicons/apple-icon-60x60.png differ diff --git a/src/assets/images/favicons/apple-icon-72x72.png b/src/assets/images/favicons/apple-icon-72x72.png new file mode 100644 index 0000000..bd5dec5 Binary files /dev/null and b/src/assets/images/favicons/apple-icon-72x72.png differ diff --git a/src/assets/images/favicons/apple-icon-76x76.png b/src/assets/images/favicons/apple-icon-76x76.png new file mode 100644 index 0000000..2ad500b Binary files /dev/null and b/src/assets/images/favicons/apple-icon-76x76.png differ diff --git a/src/assets/images/favicons/apple-icon-precomposed.png b/src/assets/images/favicons/apple-icon-precomposed.png new file mode 100644 index 0000000..bd7b484 Binary files /dev/null and b/src/assets/images/favicons/apple-icon-precomposed.png differ diff --git a/src/assets/images/favicons/apple-icon.png b/src/assets/images/favicons/apple-icon.png new file mode 100644 index 0000000..bd7b484 Binary files /dev/null and b/src/assets/images/favicons/apple-icon.png differ diff --git a/src/assets/images/favicons/favicon-32x32.png b/src/assets/images/favicons/favicon-32x32.png new file mode 100644 index 0000000..69d3259 Binary files /dev/null and b/src/assets/images/favicons/favicon-32x32.png differ diff --git a/src/assets/images/favicons/favicon-96x96.png b/src/assets/images/favicons/favicon-96x96.png new file mode 100644 index 0000000..4de3aef Binary files /dev/null and b/src/assets/images/favicons/favicon-96x96.png differ diff --git a/src/assets/images/favicons/favicon.ico b/src/assets/images/favicons/favicon.ico new file mode 100644 index 0000000..d9f98df Binary files /dev/null and b/src/assets/images/favicons/favicon.ico differ diff --git a/src/assets/images/favicons/favicon.png b/src/assets/images/favicons/favicon.png new file mode 100644 index 0000000..8626f74 Binary files /dev/null and b/src/assets/images/favicons/favicon.png differ diff --git a/src/assets/images/favicons/ms-icon-144x144.png b/src/assets/images/favicons/ms-icon-144x144.png new file mode 100644 index 0000000..ca66e27 Binary files /dev/null and b/src/assets/images/favicons/ms-icon-144x144.png differ diff --git a/src/assets/images/favicons/ms-icon-150x150.png b/src/assets/images/favicons/ms-icon-150x150.png new file mode 100644 index 0000000..7bbc031 Binary files /dev/null and b/src/assets/images/favicons/ms-icon-150x150.png differ diff --git a/src/assets/images/favicons/ms-icon-310x310.png b/src/assets/images/favicons/ms-icon-310x310.png new file mode 100644 index 0000000..df6a674 Binary files /dev/null and b/src/assets/images/favicons/ms-icon-310x310.png differ diff --git a/src/assets/images/favicons/ms-icon-70x70.png b/src/assets/images/favicons/ms-icon-70x70.png new file mode 100644 index 0000000..d926644 Binary files /dev/null and b/src/assets/images/favicons/ms-icon-70x70.png differ diff --git a/src/assets/images/illuminati/aanwo.jpg b/src/assets/images/illuminati/aanwo.jpg new file mode 100644 index 0000000..a8cd4df Binary files /dev/null and b/src/assets/images/illuminati/aanwo.jpg differ diff --git a/src/assets/images/illuminati/cobra.jpg b/src/assets/images/illuminati/cobra.jpg new file mode 100644 index 0000000..b3b404d Binary files /dev/null and b/src/assets/images/illuminati/cobra.jpg differ diff --git a/src/assets/images/illuminati/evil-inc.jpg b/src/assets/images/illuminati/evil-inc.jpg new file mode 100644 index 0000000..b830b6d Binary files /dev/null and b/src/assets/images/illuminati/evil-inc.jpg differ diff --git a/src/assets/images/illuminati/league.jpg b/src/assets/images/illuminati/league.jpg new file mode 100644 index 0000000..46ca9da Binary files /dev/null and b/src/assets/images/illuminati/league.jpg differ diff --git a/src/assets/images/illuminati/satanic.jpg b/src/assets/images/illuminati/satanic.jpg new file mode 100644 index 0000000..46fb285 Binary files /dev/null and b/src/assets/images/illuminati/satanic.jpg differ diff --git a/src/assets/images/illuminati/umbrella.jpg b/src/assets/images/illuminati/umbrella.jpg new file mode 100644 index 0000000..30d66d0 Binary files /dev/null and b/src/assets/images/illuminati/umbrella.jpg differ diff --git a/src/assets/images/illuminati/umn.jpg b/src/assets/images/illuminati/umn.jpg new file mode 100644 index 0000000..9aa3857 Binary files /dev/null and b/src/assets/images/illuminati/umn.jpg differ diff --git a/src/assets/images/illuminati/vatican.jpg b/src/assets/images/illuminati/vatican.jpg new file mode 100644 index 0000000..abbe18b Binary files /dev/null and b/src/assets/images/illuminati/vatican.jpg differ diff --git a/src/assets/images/magic/arafell/ander.jpg b/src/assets/images/magic/arafell/ander.jpg new file mode 100644 index 0000000..a63765f Binary files /dev/null and b/src/assets/images/magic/arafell/ander.jpg differ diff --git a/src/assets/images/magic/arafell/damascus.jpg b/src/assets/images/magic/arafell/damascus.jpg new file mode 100644 index 0000000..c363875 Binary files /dev/null and b/src/assets/images/magic/arafell/damascus.jpg differ diff --git a/src/assets/images/magic/arafell/jolene.jpg b/src/assets/images/magic/arafell/jolene.jpg new file mode 100644 index 0000000..eb55685 Binary files /dev/null and b/src/assets/images/magic/arafell/jolene.jpg differ diff --git a/src/assets/images/magic/arafell/lafflas.jpg b/src/assets/images/magic/arafell/lafflas.jpg new file mode 100644 index 0000000..d409be9 Binary files /dev/null and b/src/assets/images/magic/arafell/lafflas.jpg differ diff --git a/src/assets/images/magic/commanders/edgar-markov.png b/src/assets/images/magic/commanders/edgar-markov.png new file mode 100644 index 0000000..71318b9 Binary files /dev/null and b/src/assets/images/magic/commanders/edgar-markov.png differ diff --git a/src/assets/images/magic/commanders/estrid-the-masked.png b/src/assets/images/magic/commanders/estrid-the-masked.png new file mode 100644 index 0000000..204518d Binary files /dev/null and b/src/assets/images/magic/commanders/estrid-the-masked.png differ diff --git a/src/assets/images/magic/commanders/heartless-hidetsugu.jpg b/src/assets/images/magic/commanders/heartless-hidetsugu.jpg new file mode 100644 index 0000000..cd72429 Binary files /dev/null and b/src/assets/images/magic/commanders/heartless-hidetsugu.jpg differ diff --git a/src/assets/images/magic/commanders/saheeli-the-gifted.png b/src/assets/images/magic/commanders/saheeli-the-gifted.png new file mode 100644 index 0000000..8b4d83d Binary files /dev/null and b/src/assets/images/magic/commanders/saheeli-the-gifted.png differ diff --git a/src/assets/images/magic/commanders/slimefoot-the-stowaway.png b/src/assets/images/magic/commanders/slimefoot-the-stowaway.png new file mode 100644 index 0000000..8c623ba Binary files /dev/null and b/src/assets/images/magic/commanders/slimefoot-the-stowaway.png differ diff --git a/src/assets/images/magic/commanders/syr-gwyn-hero-of-ashvale.png b/src/assets/images/magic/commanders/syr-gwyn-hero-of-ashvale.png new file mode 100644 index 0000000..4cdbb21 Binary files /dev/null and b/src/assets/images/magic/commanders/syr-gwyn-hero-of-ashvale.png differ diff --git a/src/assets/images/magic/commanders/temmet-vizier-of-naktamun.png b/src/assets/images/magic/commanders/temmet-vizier-of-naktamun.png new file mode 100644 index 0000000..8895d7b Binary files /dev/null and b/src/assets/images/magic/commanders/temmet-vizier-of-naktamun.png differ diff --git a/src/assets/images/magic/commanders/ur-dragon.png b/src/assets/images/magic/commanders/ur-dragon.png new file mode 100644 index 0000000..2437029 Binary files /dev/null and b/src/assets/images/magic/commanders/ur-dragon.png differ diff --git a/src/assets/images/magic/commanders/wrexial-the-risen-deep.png b/src/assets/images/magic/commanders/wrexial-the-risen-deep.png new file mode 100644 index 0000000..6c95a2e Binary files /dev/null and b/src/assets/images/magic/commanders/wrexial-the-risen-deep.png differ diff --git a/src/assets/images/magic/fun/token-angel-barnaby.png b/src/assets/images/magic/fun/token-angel-barnaby.png new file mode 100644 index 0000000..671df57 Binary files /dev/null and b/src/assets/images/magic/fun/token-angel-barnaby.png differ diff --git a/src/assets/images/magic/fun/token-angel-metatron.png b/src/assets/images/magic/fun/token-angel-metatron.png new file mode 100644 index 0000000..cee3932 Binary files /dev/null and b/src/assets/images/magic/fun/token-angel-metatron.png differ diff --git a/src/assets/images/magic/fun/token-demon-azrael-regular.png b/src/assets/images/magic/fun/token-demon-azrael-regular.png new file mode 100644 index 0000000..e7c90bf Binary files /dev/null and b/src/assets/images/magic/fun/token-demon-azrael-regular.png differ diff --git a/src/assets/images/magic/fun/token-demon-azrael.png b/src/assets/images/magic/fun/token-demon-azrael.png new file mode 100644 index 0000000..24bfc42 Binary files /dev/null and b/src/assets/images/magic/fun/token-demon-azrael.png differ diff --git a/src/assets/images/magic/fun/token-thrull-dogma-1.png b/src/assets/images/magic/fun/token-thrull-dogma-1.png new file mode 100644 index 0000000..3bc1d08 Binary files /dev/null and b/src/assets/images/magic/fun/token-thrull-dogma-1.png differ diff --git a/src/assets/images/magic/fun/token-thrull-dogma-2.png b/src/assets/images/magic/fun/token-thrull-dogma-2.png new file mode 100644 index 0000000..a3c62c4 Binary files /dev/null and b/src/assets/images/magic/fun/token-thrull-dogma-2.png differ diff --git a/src/assets/images/magic/fun/token-thrull-dogma-3.png b/src/assets/images/magic/fun/token-thrull-dogma-3.png new file mode 100644 index 0000000..6a2725f Binary files /dev/null and b/src/assets/images/magic/fun/token-thrull-dogma-3.png differ diff --git a/src/assets/images/magic/malakyre/mad-baron.jpg b/src/assets/images/magic/malakyre/mad-baron.jpg new file mode 100644 index 0000000..5a5a179 Binary files /dev/null and b/src/assets/images/magic/malakyre/mad-baron.jpg differ diff --git a/src/assets/images/magic/malakyre/mind-gorger.jpg b/src/assets/images/magic/malakyre/mind-gorger.jpg new file mode 100644 index 0000000..f9ee177 Binary files /dev/null and b/src/assets/images/magic/malakyre/mind-gorger.jpg differ diff --git a/src/assets/images/magic/malakyre/unseen-infiltrator.jpg b/src/assets/images/magic/malakyre/unseen-infiltrator.jpg new file mode 100644 index 0000000..a730fc1 Binary files /dev/null and b/src/assets/images/magic/malakyre/unseen-infiltrator.jpg differ diff --git a/src/assets/images/magic/malakyre/whispering-warlock.jpg b/src/assets/images/magic/malakyre/whispering-warlock.jpg new file mode 100644 index 0000000..2092785 Binary files /dev/null and b/src/assets/images/magic/malakyre/whispering-warlock.jpg differ diff --git a/src/assets/images/magic/mythicwars/horror.jpg b/src/assets/images/magic/mythicwars/horror.jpg new file mode 100644 index 0000000..8aef768 Binary files /dev/null and b/src/assets/images/magic/mythicwars/horror.jpg differ diff --git a/src/assets/images/magic/mythicwars/hydra.jpg b/src/assets/images/magic/mythicwars/hydra.jpg new file mode 100644 index 0000000..ef6e3c4 Binary files /dev/null and b/src/assets/images/magic/mythicwars/hydra.jpg differ diff --git a/src/assets/images/magic/mythicwars/sphinx.jpg b/src/assets/images/magic/mythicwars/sphinx.jpg new file mode 100644 index 0000000..1b5ef17 Binary files /dev/null and b/src/assets/images/magic/mythicwars/sphinx.jpg differ diff --git a/src/assets/images/magic/mythicwars/spirit.jpg b/src/assets/images/magic/mythicwars/spirit.jpg new file mode 100644 index 0000000..6303efa Binary files /dev/null and b/src/assets/images/magic/mythicwars/spirit.jpg differ diff --git a/src/assets/images/magic/planeswalkers/set01/anora.jpg b/src/assets/images/magic/planeswalkers/set01/anora.jpg new file mode 100644 index 0000000..49327bb Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set01/anora.jpg differ diff --git a/src/assets/images/magic/planeswalkers/set01/arzachai.jpg b/src/assets/images/magic/planeswalkers/set01/arzachai.jpg new file mode 100644 index 0000000..6345487 Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set01/arzachai.jpg differ diff --git a/src/assets/images/magic/planeswalkers/set01/freyjef.jpg b/src/assets/images/magic/planeswalkers/set01/freyjef.jpg new file mode 100644 index 0000000..0fb41ad Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set01/freyjef.jpg differ diff --git a/src/assets/images/magic/planeswalkers/set01/hojn.jpg b/src/assets/images/magic/planeswalkers/set01/hojn.jpg new file mode 100644 index 0000000..9fe0fe4 Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set01/hojn.jpg differ diff --git a/src/assets/images/magic/planeswalkers/set01/ktor.jpg b/src/assets/images/magic/planeswalkers/set01/ktor.jpg new file mode 100644 index 0000000..7d16c42 Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set01/ktor.jpg differ diff --git a/src/assets/images/magic/planeswalkers/set01/mawhett.jpg b/src/assets/images/magic/planeswalkers/set01/mawhett.jpg new file mode 100644 index 0000000..6e659cb Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set01/mawhett.jpg differ diff --git a/src/assets/images/magic/planeswalkers/set01/momyt.jpg b/src/assets/images/magic/planeswalkers/set01/momyt.jpg new file mode 100644 index 0000000..578d265 Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set01/momyt.jpg differ diff --git a/src/assets/images/magic/planeswalkers/set01/nasoj.jpg b/src/assets/images/magic/planeswalkers/set01/nasoj.jpg new file mode 100644 index 0000000..a13f74e Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set01/nasoj.jpg differ diff --git a/src/assets/images/magic/planeswalkers/set01/riec.jpg b/src/assets/images/magic/planeswalkers/set01/riec.jpg new file mode 100644 index 0000000..6fc0124 Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set01/riec.jpg differ diff --git a/src/assets/images/magic/planeswalkers/set01/sahyel.jpg b/src/assets/images/magic/planeswalkers/set01/sahyel.jpg new file mode 100644 index 0000000..86dff12 Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set01/sahyel.jpg differ diff --git a/src/assets/images/magic/planeswalkers/set02/anora.png b/src/assets/images/magic/planeswalkers/set02/anora.png new file mode 100644 index 0000000..6b5832e Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set02/anora.png differ diff --git a/src/assets/images/magic/planeswalkers/set02/freyjef.png b/src/assets/images/magic/planeswalkers/set02/freyjef.png new file mode 100644 index 0000000..921a64b Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set02/freyjef.png differ diff --git a/src/assets/images/magic/planeswalkers/set02/hojn.png b/src/assets/images/magic/planeswalkers/set02/hojn.png new file mode 100644 index 0000000..32a5ede Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set02/hojn.png differ diff --git a/src/assets/images/magic/planeswalkers/set02/mawhett.png b/src/assets/images/magic/planeswalkers/set02/mawhett.png new file mode 100644 index 0000000..7d9164b Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set02/mawhett.png differ diff --git a/src/assets/images/magic/planeswalkers/set02/riec.png b/src/assets/images/magic/planeswalkers/set02/riec.png new file mode 100644 index 0000000..5abd7ed Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set02/riec.png differ diff --git a/src/assets/images/magic/planeswalkers/set02/sahyel.png b/src/assets/images/magic/planeswalkers/set02/sahyel.png new file mode 100644 index 0000000..c0675aa Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set02/sahyel.png differ diff --git a/src/assets/images/magic/planeswalkers/set02/tesh.png b/src/assets/images/magic/planeswalkers/set02/tesh.png new file mode 100644 index 0000000..61dcc11 Binary files /dev/null and b/src/assets/images/magic/planeswalkers/set02/tesh.png differ diff --git a/src/assets/images/updates/fakebook.jpg b/src/assets/images/updates/fakebook.jpg new file mode 100644 index 0000000..83e0974 Binary files /dev/null and b/src/assets/images/updates/fakebook.jpg differ diff --git a/src/assets/images/updates/mw-scotts.jpg b/src/assets/images/updates/mw-scotts.jpg new file mode 100644 index 0000000..99579d0 Binary files /dev/null and b/src/assets/images/updates/mw-scotts.jpg differ diff --git a/src/assets/images/updates/obit.jpg b/src/assets/images/updates/obit.jpg new file mode 100644 index 0000000..0ea8542 Binary files /dev/null and b/src/assets/images/updates/obit.jpg differ diff --git a/src/assets/images/updates/swamp4.png b/src/assets/images/updates/swamp4.png new file mode 100644 index 0000000..d99f986 Binary files /dev/null and b/src/assets/images/updates/swamp4.png differ diff --git a/src/assets/images/updates/syncthing.gif b/src/assets/images/updates/syncthing.gif new file mode 100644 index 0000000..d57a9b5 Binary files /dev/null and b/src/assets/images/updates/syncthing.gif differ diff --git a/src/assets/images/updates/wave-original.jpg b/src/assets/images/updates/wave-original.jpg new file mode 100644 index 0000000..9f0bccc Binary files /dev/null and b/src/assets/images/updates/wave-original.jpg differ diff --git a/src/assets/scripts/1-docready.min.js b/src/assets/scripts/1-docready.min.js new file mode 100644 index 0000000..7225311 --- /dev/null +++ b/src/assets/scripts/1-docready.min.js @@ -0,0 +1,9 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT +/* + docready.js + https://github.com/jfriend00/docReady + The MIT License (MIT) + Copyright (c) 2014 John Friend +*/ +!(function(t,e){"use strict";function n(){if(!a){a=!0;for(var t=0;t= -r&&n.top-window.innerHeight= -r&&n.left-window.innerWidthparseInt(a[1],10))):(F=!1));return F}function M(a){null===H&&(H=!!a.document.fonts);return H}function N(a,c){var b=a.style,g=a.weight;if(null===G){var e=document.createElement("div");try{e.style.font="condensed 100px sans-serif"}catch(q){}G=""!==e.style.font}return[b,g,G?a.stretch:"","100px",c].join(" ")}D.prototype.load=function(a,c){var b=this,g=a||"BESbswy",e=0,q=c||3e3,J=new Date().getTime();return new Promise(function(K,L){if(M(b.context)&&!I(b.context)){var O=new Promise(function(r,t){function h(){new Date().getTime()-J>=q?t(Error(""+q+"ms timeout exceeded")):b.context.document.fonts.load(N(b,'"'+b.family+'"'),g).then(function(n){1<=n.length?r():setTimeout(h,25)},t)}h()}),P=new Promise(function(r,t){e=setTimeout(function(){t(Error(""+q+"ms timeout exceeded"))},q)});Promise.race([P,O]).then(function(){clearTimeout(e);K(b)},L)}else{u(function(){function r(){var d;if((d=(-1!=k&&-1!=l)||(-1!=k&&-1!=m)||(-1!=l&&-1!=m))){(d=k!=l&&k!=m&&l!=m)||(null===E&&((d=/AppleWebKit\/([0-9]+)(?:\.([0-9]+))/.exec(window.navigator.userAgent)),(E=!!d&&(536>parseInt(d[1],10)||(536===parseInt(d[1],10)&&11>=parseInt(d[2],10))))),(d=E&&((k==y&&l==y&&m==y)||(k==z&&l==z&&m==z)||(k==A&&l==A&&m==A)))),(d=!d)}d&&(null!==f.parentNode&&f.parentNode.removeChild(f),clearTimeout(e),K(b))}function t(){if(new Date().getTime()-J>=q){null!==f.parentNode&&f.parentNode.removeChild(f),L(Error(""+q+"ms timeout exceeded"))}else{var d=b.context.document.hidden;if(!0===d||void 0===d){(k=h.g.offsetWidth),(l=n.g.offsetWidth),(m=v.g.offsetWidth),r()}e=setTimeout(t,50)}}var h=new w(g),n=new w(g),v=new w(g),k=-1,l=-1,m=-1,y=-1,z=-1,A=-1,f=document.createElement("div");f.dir="ltr";x(h,N(b,"sans-serif"));x(n,N(b,"serif"));x(v,N(b,"monospace"));f.appendChild(h.g);f.appendChild(n.g);f.appendChild(v.g);b.context.document.body.appendChild(f);y=h.g.offsetWidth;z=n.g.offsetWidth;A=v.g.offsetWidth;t();C(h,function(d){k=d;r()});x(h,N(b,'"'+b.family+'",sans-serif'));C(n,function(d){l=d;r()});x(n,N(b,'"'+b.family+'",serif'));C(v,function(d){m=d;r()});x(v,N(b,'"'+b.family+'",monospace'))})}})};"object"===typeof module?(module.exports=D):((window.FontFaceObserver=D),(window.FontFaceObserver.prototype.load=D.prototype.load))})(); +// @license-end diff --git a/src/assets/scripts/6-classlist.min.js b/src/assets/scripts/6-classlist.min.js new file mode 100644 index 0000000..1af33f4 --- /dev/null +++ b/src/assets/scripts/6-classlist.min.js @@ -0,0 +1,9 @@ +// @license magnet:?xt=urn:btih:e95b018ef3580986a04669f1b5879592219e2a7a&dn=public-domain.txt Unlicense +/* + classList.js v1.2.20171210 + https://github.com/eligrey/classList.js + The Unlicense +*/ +"document"in self&&(("classList"in document.createElement("_")&&(!document.createElementNS||"classList"in document.createElementNS("http://www.w3.org/2000/svg","g")))||!(function(t){"use strict";if("Element"in t){var e="classList",n="prototype",i=t.Element[n],s=Object,r=String[n].trim||function(){return this.replace(/^\s+|\s+$/g,"")},o=Array[n].indexOf||function(t){for(var e=0,n=this.length;n>e;e+=1){if(e in this&&this[e]===t){return e}}return -1},c=function(t,e){(this.name=t),(this.code=DOMException[t]),(this.message=e)},a=function(t,e){if(""===e){throw new c("SYNTAX_ERR","The token must not be empty.")}if(/\s/.test(e)){throw new c("INVALID_CHARACTER_ERR","The token must not contain space characters.")}return o.call(t,e)},l=function(t){for(var e=r.call(t.getAttribute("class")||""),n=e?e.split(/\s+/):[],i=0,s=n.length;s>i;i+=1){this.push(n[i])}this._updateClassName=function(){t.setAttribute("class",this.toString())}},u=(l[n]=[]),h=function(){return new l(this)};if(((c[n]=Error[n]),(u.item=function(t){return this[t]||null}),(u.contains=function(t){return~a(this,t+"")}),(u.add=function(){var t,e=arguments,n=0,i=e.length,s=!1;do{(t=e[n]+""),~a(this,t)||(this.push(t),(s=!0))}while(++nn;n+=1){(t=arguments[n]),e.call(this,t)};;};e("add"),e("remove")}if((t.classList.toggle("c3",!1),t.classList.contains("c3"))){var n=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(t,e){return 1 in arguments&&!this.contains(t)==!e?e:n.call(this,t)}}"replace"in document.createElement("_").classList||(DOMTokenList.prototype.replace=function(t,e){var n=this.toString().split(" "),i=n.indexOf(t+"");~i&&((n=n.slice(i)),this.remove.apply(this,n),this.add(e),this.add.apply(this,n.slice(1)))}),(t=null)})()); + +// @license-end diff --git a/src/assets/scripts/7-dayjs.min.js b/src/assets/scripts/7-dayjs.min.js new file mode 100644 index 0000000..b9935bc --- /dev/null +++ b/src/assets/scripts/7-dayjs.min.js @@ -0,0 +1,10 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT +/* + dayjs v1.11.5 + https://github.com/iamkun/dayjs + The MIT License (MIT) + Copyright (c) 2018-present, iamkun +*/ +!(function(t,e){"object"==typeof exports&&"undefined"!=typeof module?(module.exports=e()):"function"==typeof define&&define.amd?define(e):((t="undefined"!=typeof globalThis?globalThis:t||self).dayjs=e())})(this,function(){"use strict";var t=1e3,e=6e4,n=36e5,r="millisecond",i="second",s="minute",u="hour",a="day",o="week",f="month",h="quarter",c="year",d="date",$="Invalid Date",l=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,y=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,M={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_")},m=function(t,e,n){var r=String(t);return!r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},g={s:m,z:function(t){var e= -t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return(e<=0?"+":"-")+m(r,2,"0")+":"+m(i,2,"0")},m:function t(e,n){if(e.date()1){return t(u[0])}}else{var a=e.name;(D[a]=e),(i=a)}return!r&&i&&(v=i),i||(!r&&v)},w=function(t,e){if(p(t)){return t.clone()}var n="object"==typeof e?e:{};return(n.date=t),(n.args=arguments),new _(n)},O=g;(O.l=S),(O.i=p),(O.w=function(t,e){return w(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})});var _=(function(){function M(t){(this.$L=S(t.locale,null,!0)),this.parse(t)}var m=M.prototype;return((m.parse=function(t){(this.$d=(function(t){var e=t.date,n=t.utc;if(null===e){return new Date(NaN)}if(O.u(e)){return new Date()}if(e instanceof Date){return new Date(e)}if("string"==typeof e&&!/Z$/i.test(e)){var r=e.match(l);if(r){var i=r[2]-1||0,s=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)})(t)),(this.$x=t.x||{}),this.init()}),(m.init=function(){var t=this.$d;(this.$y=t.getFullYear()),(this.$M=t.getMonth()),(this.$D=t.getDate()),(this.$W=t.getDay()),(this.$H=t.getHours()),(this.$m=t.getMinutes()),(this.$s=t.getSeconds()),(this.$ms=t.getMilliseconds())}),(m.$utils=function(){return O}),(m.isValid=function(){return!(this.$d.toString()===$)}),(m.isSame=function(t,e){var n=w(t);return this.startOf(e)<=n&&n<=this.endOf(e)}),(m.isAfter=function(t,e){return w(t)0),p<=y.r||!y.r)){p<=1&&c>0&&(y=h[c-1]);var v=l[y.l];u&&(p=u(""+p)),(a="string"==typeof v?v.replace("%d",p):v(p,n,y.l,s));break}}if(n){return a}var M=s?l.future:l.past;return "function"==typeof M?M(a):M.replace("%s",a)}),(n.to=function(r,e){return i(r,e,this,!0)}),(n.from=function(r,e){return i(r,e,this)});var d=function(r){return r.$u?t.utc():t()};(n.toNow=function(r){return this.to(d(this),r)}),(n.fromNow=function(r){return this.from(d(this),r)})}}); +// @license-end diff --git a/src/assets/scripts/scripts.js b/src/assets/scripts/scripts.js new file mode 100644 index 0000000..2c8888c --- /dev/null +++ b/src/assets/scripts/scripts.js @@ -0,0 +1,80 @@ +// @license magnet:?xt=urn:btih:90dc5c0be029de84e523b9b3922520e79e0e6f08&dn=cc0.txt CC0-1.0 +/**************************************************************************** + * It's Eric Woodward's Site + * + * Copyright 2014-2022 Eric Woodward + * Source released under CC0 Public Domain License v1.0 + * http://creativecommons.org/publicdomain/zero/1.0/ + ****************************************************************************/ +(function () { + "use strict"; + + // Checking if browser "cuts the mustard" - https://gomakethings.com/ditching-jquery/ + if (!(!!document.querySelector && !!window.addEventListener)) return; + + if (window.dayjs) dayjs.extend(window.dayjs_plugin_relativeTime); + + // Indicate JS is loaded + document.documentElement.className = + document.documentElement.className.replace("no-js", "js"); + + // Enable cached fonts ASAP + if (window.Cookies && !!Cookies.get("fonts_loaded")) { + document.documentElement.className += " js-hasFontsLoaded"; + } + + docReady(function () { + setTimeout(function () { + if (!window.Cookies || !window.FontFaceObserver) return; + + // Handle Fonts + const font_ls = new FontFaceObserver("liberation_serif"), + font_msc = new FontFaceObserver("marcellus_sc"); + Promise.all([font_ls.load(), font_msc.load()]).then(function () { + if ( + document.documentElement.className.indexOf( + "js-hasFontsLoaded" + ) == -1 + ) { + document.documentElement.className += " js-hasFontsLoaded"; + } + Cookies.set("fonts_loaded", true); + }); + + // Lazy-Load Media + if (typeof loadMedia === "function") { + loadMedia(".js-lazyLoader", null, true); + } + + // Add relative dates via dayjs + if (window.dayjs) { + const times = document.getElementsByTagName("time"); + + [].forEach.call(times, function (the_time) { + let pub_time = the_time.getAttribute("datetime"); + if (the_time.className.indexOf("js-noRelativeTime") === -1) + the_time.innerHTML += + ' (' + + dayjs(pub_time).from(dayjs()) + + ")"; + the_time.classList.add("isDone"); + }); + } + + if (document.documentElement.className.indexOf("is404") > -1) { + document.getElementById("searchQuery").value = + window.location.pathname + .replace(/\\.html?$/, "") + .replace(/\//g, " "); + } + + document + .getElementById("searchForm") + .addEventListener("submit", function (e) { + document.getElementById("searchQuery").value += + " site:" + window.location.hostname; + }); + }, 1); + }); +})(); +// @license-end diff --git a/src/assets/styles/fonts.css b/src/assets/styles/fonts.css new file mode 100644 index 0000000..f1035bc --- /dev/null +++ b/src/assets/styles/fonts.css @@ -0,0 +1,43 @@ +@font-face { + font-family: 'exo_2'; + src: url('/files/fonts/Exo2-Regular-webfont.eot'); + src: url('/files/fonts/Exo2-Regular-webfont.eot?#iefix') format('embedded-opentype'), + url('/files/fonts/Exo2-Regular-webfont.woff') format('woff'), + url('/files/fonts/Exo2-Regular-webfont.ttf') format('truetype'), + url('/files/fonts/Exo2-Regular-webfont.svg#exo_2') format('svg'); + font-weight: 400; + font-style: normal; +} + +@font-face { + font-family: 'exo_2'; + src: url('/files/fonts/Exo2-Italic-webfont.eot'); + src: url('/files/fonts/Exo2-Italic-webfont.eot?#iefix') format('embedded-opentype'), + url('/files/fonts/Exo2-Italic-webfont.woff') format('woff'), + url('/files/fonts/Exo2-Italic-webfont.ttf') format('truetype'), + url('/files/fonts/Exo2-Italic-webfont.svg#exo_2') format('svg'); + font-weight: 400; + font-style: italic; +} + +@font-face { + font-family: 'exo_2'; + src: url('Exo2-Bold-webfont.eot'); + src: url('Exo2-Bold-webfont.eot?#iefix') format('embedded-opentype'), + url('Exo2-Bold-webfont.woff') format('woff'), + url('Exo2-Bold-webfont.ttf') format('truetype'), + url('Exo2-Bold-webfont.svg#exo_2') format('svg'); + font-weight: 600; + font-style: normal; +} + +@font-face { + font-family: 'exo_2'; + src: url('Exo2-BoldItalic-webfont.eot'); + src: url('Exo2-BoldItalic-webfont.eot?#iefix') format('embedded-opentype'), + url('Exo2-BoldItalic-webfont.woff') format('woff'), + url('Exo2-BoldItalic-webfont.ttf') format('truetype'), + url('Exo2-BoldItalic-webfont.svg#exo_2') format('svg'); + font-weight: 600; + font-style: italic; +} diff --git a/src/assets/styles/imports.css b/src/assets/styles/imports.css new file mode 100644 index 0000000..46709b5 --- /dev/null +++ b/src/assets/styles/imports.css @@ -0,0 +1,297 @@ +/**************************************************************************** + * It's Eric Woodward (dotcom) + * + * Copyright 2015-2018 Eric Woodward + * Source released under CC0 Public Domain License v1.0 + * http://creativecommons.org/publicdomain/zero/1.0/ + ****************************************************************************/ + + /*! normalize.css v5.0.0 | MIT License | github.com/necolas/normalize.css */ + html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:0.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace, monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:inherit}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace, monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,html [type="button"],[type="reset"],[type="submit"]{-webkit-appearance:button}button::-moz-focus-inner,[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring{outline:1px dotted ButtonText}fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-cancel-button,[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}template{display:none}[hidden]{display:none} + + /**************************************************************************** + * Default settings + ****************************************************************************/ + + /* set options */ + @charset "UTF-8"; + @-ms-viewport { + width: device-width; + } + + @viewport { + width: device-width; + } + + /* apply a natural box layout model to all elements */ + *, *:before, *:after { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + } + + abbr[title] { + border-bottom: none; + } + + html { + font-size: 16px; + } + + /* Fix 300ms Delay */ + a, button { + -ms-touch-action: manipulation; /* IE10 */ + touch-action: manipulation; /* IE11+ */ + } + + /**************************************************************************** + * Grid settings (http://www.responsivegridsystem.com/) + ****************************************************************************/ + + .section { + clear: both; + margin: 0px; + padding: 0px; + } + + .group:before, + .group:after { + content:""; + display:table; + } + .group:after { + clear:both; + } + .group { + zoom:1; /* For IE 6/7 (trigger hasLayout) */ + } + + .col { + display: block; + float:left; + margin: 1% 0 1% 0%; + } + + .col:first-child { margin-left: 0; } /* all browsers except IE6 and lower */ + + @media only screen and (min-width: 30em) { + .col { + margin: 1% 0 1% 1.6%; + } + } + + .span_6_of_6 { + width: 100%; + } + .span_5_of_6 { + width: 100%; + } + .span_4_of_6 { + width: 100%; + } + .span_3_of_6 { + width: 100%; + } + .span_2_of_6 { + width: 100%; + } + .span_1_of_6 { + width: 100%; + } + + @media only screen and (min-width: 30em) { + .span_6_of_6 { + width: 100%; + } + + .span_5_of_6 { + width: 83.06%; + } + + .span_4_of_6 { + width: 66.13%; + } + + .span_3_of_6 { + width: 49.2%; + } + + .span_2_of_6 { + width: 32.26%; + } + + .span_1_of_6 { + width: 15.33%; + } + } + + .span_5_of_5 { + width: 100%; + } + .span_4_of_5 { + width: 100%; + } + .span_3_of_5 { + width: 100%; + } + .span_2_of_5 { + width: 100%; + } + .span_1_of_5 { + width: 100%; + } + + @media only screen and (min-width: 30em) { + .span_5_of_5 { + width: 100%; + } + + .span_4_of_5 { + width: 79.68%; + } + + .span_3_of_5 { + width: 59.36%; + } + + .span_2_of_5 { + width: 39.04%; + } + + .span_1_of_5 { + width: 18.72%; + } + } + + .span_4_of_4 { + width: 100%; + } + .span_3_of_4 { + width: 100%; + } + .span_2_of_4 { + width: 100%; + } + .span_1_of_4 { + width: 100%; + } + + @media only screen and (min-width: 30em) { + .span_4_of_4 { + width: 100%; + } + + .span_3_of_4 { + width: 74.6%; + } + + .span_2_of_4 { + width: 49.2%; + } + + .span_1_of_4 { + width: 23.8%; + } + } + + /**************************************************************************** + * Helper classes + ****************************************************************************/ + + .clearfix:before, + .clearfix:after { + content: " "; + display: table; + } + + .clearfix:after { + clear: both; + } + + .clearfix { + *zoom: 1; + } + + .pullRight{ + float: right; + } + + code, kbd, pre, samp { + font-size: .8em; + } + + /**************************************************************************** + * Print styles + ****************************************************************************/ + + @media print { + * { + text-shadow: none !important; + color: #000 !important; + background: transparent !important; + box-shadow: none !important; + } + a, + a:visited { + text-decoration: underline; + } + a[href]:after { + content: " (" attr(href) ")"; + } + abbr[title]:after { + content: " (" attr(title) ")"; + } + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + thead { + display: table-header-group; + } + tr, + img { + page-break-inside: avoid; + } + img { + max-width: 100% !important; + } + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + h2, + h3 { + page-break-after: avoid; + } + select { + background: #FFFDD7 !important; + } + .navbar { + display: none; + } + .table td, + .table th { + background-color: #FFFDD7 !important; + } + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + .label { + border: 1px solid #000; + } + .table { + border-collapse: collapse !important; + } + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } + } diff --git a/src/assets/styles/styles.css b/src/assets/styles/styles.css new file mode 100644 index 0000000..9c36767 --- /dev/null +++ b/src/assets/styles/styles.css @@ -0,0 +1,1262 @@ +/**************************************************************************** + * It's Eric Woodward (dotcom) + * + * Copyright 2015-2018 Eric Woodward + * Source released under CC0 Public Domain License v1.0 + * http://creativecommons.org/publicdomain/zero/1.0/ + ****************************************************************************/ + +/* + Palette + color: #9aa8bc + bg: #0d1852 + link: 049c74 + border: 25baba + big-font: 25baba + black: 040308 + other: 094192 + +*/ + +body { + background: #0d1852; /* Old browsers */ + background: url("/images/code-bg.jpg") top fixed; + color: #9aa8bc; + font-family: sans-serif; + font-size: 100%; + line-height: 1.5em; +} + +a { + border: 1px solid transparent; + border-bottom: 1px dashed #25baba; + color: #049c74; + font-weight: bold; + padding: 0 0.2rem; + text-decoration: none; + -webkit-transition: 0.3s background-color, 0.3s color, 0.3s border-radius; + transition: 0.3s background-color, 0.3s color, 0.3s border-radius; +} + +a[target="_blank"]::after { + content: " \29C9"; + font-weight: normal; +} + +a:hover { + border: 1px solid #25baba; + background-color: #25baba; + border-radius: 0.3rem; + color: #040308; + text-decoration: none; +} + +a:hover:visited { + color: #040308; +} + +a:visited { + color: #094192; + color: #1e6e58; +} + +article img { + max-width: 100%; +} + +blockquote { + border-left: 2px solid #04778f; + font-style: italic; + margin: 1em 0; + padding: 0 1em; +} + +code, +kbd { + background-color: #0d1852; + background-color: rgba(13, 24, 82, 0.5); + color: #ccc; + font-size: 0.9em; + padding: 0.25em; +} + +figcaption { + font-size: 0.9em; +} + +figure { + margin: 1em auto; + display: block; + text-align: center; +} + +h1 { + color: #25baba; + font-size: 2em; + line-height: 1.2em; +} + +h2 { + color: #25baba; + font-size: 1.5em; + line-height: 1.2em; +} + +h3 { + color: #25baba; + font-size: 1.22em; + line-height: 1.2em; +} + +h4 { + color: #25baba; + font-size: 1.12em; + line-height: 1.2em; +} + +h5 { + color: #25baba; + font-size: 1.06em; + line-height: 1.2em; +} + +h6 { + color: #25baba; + font-size: 1em; +} + +iframe { + max-width: 100%; +} + +li { + margin-bottom: 0.6em; +} + +li ul { + margin-top: 0.6em; +} + +main { + font-size: 0.95em; +} + +main img { + max-width: 100%; +} + +ol, +ul { + padding-left: 1.2em; +} + +pre { + background-color: #0d1852; + background-color: rgba(13, 24, 82, 0.5); + color: #ccc; + font-size: 0.9em; + overflow: auto; + padding: 0.25em; +} + +pre code, +pre kbd { + background-color: transparent; +} + +samp { + font-size: 0.9em; +} + +.anaCardImg { + height: auto; + margin: 0; + vertical-align: middle; + width: 100%; +} + +.anaCardLink { + display: block; + margin: 0 auto; + max-width: 15em; + padding: 0.5em; +} + +.anaLink-billy { + background: url("/images/anachronism/links/billy_the_kid.jpg") no-repeat + center; + background-size: cover; +} + +.anaLink-constitution { + background: url("/images/anachronism/links/the_us_constitution.jpg") + no-repeat center; + background-size: cover; +} + +.anaLink-dictator { + background: url("/images/anachronism/links/the_dictator.jpg") no-repeat + center; + background-size: cover; +} + +.anaLink-earp { + background: url("/images/anachronism/links/wyatt_earp.jpg") no-repeat center; + background-size: cover; +} + +.anaLink-grant { + background: url("/images/anachronism/links/ulysses_s_grant.jpg") no-repeat + center; + background-size: cover; +} + +.anaLink-lee { + background: url("/images/anachronism/links/robert_e_lee.jpg") no-repeat + center; + background-size: cover; +} + +.anaLink-lincoln { + background: url("/images/anachronism/links/abraham_lincoln.jpg") no-repeat + center; + background-size: cover; +} + +.anaLink-stetson { + background: url("/images/anachronism/links/stetson_hat.jpg") no-repeat + center; + background-size: cover; +} + +.anaLink-washington { + background: url("/images/anachronism/links/george_washington.jpg") no-repeat + center; + background-size: cover; +} + +.anaLogo { + display: block; + margin: 0 auto 1em; + width: 100%; +} + +.asideBio { + line-height: 1.35em; + padding: 0.5em; + text-align: center; +} + +.asideBio-div { + display: none; + margin: 0.5em auto; + text-align: center; +} + +.asideBio-div-img { + max-width: 7.5em; +} + +.asideBio-div-imgLink { + border: 1px solid transparent; + display: inline-block; + padding: 0.5em 0.5em 0.3em; + -webkit-transition: 0.3s background-color, 0.3s color, 0.3s border-radius; + transition: 0.3s background-color, 0.3s color, 0.3s border-radius; +} + +.asideBio-div-link { + white-space: nowrap; +} + +.asideBio-div-textLink { + display: none; +} + +.asideContent { + border-top: 1px dotted #04778f; +} + +.asideMenu-divider { + border: 1px dashed #25baba; + color: #25baba; + width: 80%; +} + +.asideMenu-item { + align-self: auto; + display: inline-block; + flex: none; + margin: 0.5em; +} + +.asideMenu-link { + border: 1px solid #726f6a; + border-radius: 0.3em; + display: inline-block; + padding: 0.25em; +} + +.asideMenu-list { + align-content: center; + align-items: center; /* or stretch */ + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + list-style: none; + margin: 0; + padding: 0; + text-align: center; +} + +.asideMenu-subtitle { + font-size: 1.1em; + margin: 1.3em auto; + text-align: center; +} + +.asideMenu-subtitle-link { + border: 1px solid transparent; + display: inline-block; +} + +.asideMenu-title { + font-size: 1.3em; + margin: 1.5em auto; + text-align: center; +} + +.asideMenu-title-link { + border: 1px solid transparent; + display: inline-block; +} + +.asideRight { + padding: 0 1em 1em; +} + +.authorHidden { + display: none; +} + +.backLink { + clear: both; + font-size: 0.8em; + margin: 1em auto; + text-align: center; +} + +.backLink-link { + border: 1px solid #25baba; + color: #25baba; + display: inline-block; + padding: 0.25em 0.5em; +} + +.boxLink { + border: 1px solid #726f6a; + border-radius: 0.3em; + display: inline-block; + padding: 0.25em; +} + +.boxLink.isCurrent { + background-color: #049c74; + background-color: rgba(4, 156, 116, 0.8); + color: #040308; + text-decoration: none; +} + +.boxLink.isCurrent:hover { + background-color: #25baba; +} + +.dataTable td { + border-left: 1px solid #9aa8bc; + border-right: 1px solid #9aa8bc; + padding: 0.1em 0.2em; + text-align: center; +} + +.dataTable th { + border: 1px solid #9aa8bc; + color: #25baba; + padding: 0.2em 0.4em; + text-align: center; +} + +.dataTable thead tr { + background-color: #0d1852; +} + +.dataTable tr { + border-bottom: 1px solid transparent; + border-top: 1px solid transparent; +} + +.dataTable tbody tr:last-child { + border-bottom: 1px solid #9aa8bc; +} + +.dataTable tbody:nth-child(even) tr:nth-child(even) { + background-color: #0d1852; +} + +.dataTable tr:hover td { + border-bottom: 1px solid #25baba; + border-top: 1px solid #25baba; + color: #25baba; +} + +.dirList { + padding: 0; +} + +.dirList-item { + display: inline-block; + margin: 0.5em; +} + +.embed { + display: block; + margin: 1em auto; + width: 30em; + max-width: 100%; +} + +.embedLink { + padding: 0.2rem; +} + +.embedImg { + width: 100%; +} + +.embedSwitch { + text-align: right; + margin-bottom: 1em; +} + +.embedTwitter { + width: 100%; +} + +.embedVimeo { + height: 15em; + max-height: 50vw; +} + +.embedYoutube { + min-height: 21em; + width: 100%; +} + +.entry-content { + display: block; + min-height: 2.6em; + padding-top: 0.2em; +} + +.entry-reacji { + cursor: default; + float: left; + font-size: 2.2em; + margin-right: 0.2em; + vertical-align: middle; +} + +.entry-reply { + display: block; +} + +.feedLine { + border-color: #25baba; + border-color: rgba(37, 171, 171, 0.3); + clear: both; + margin: 2.5em auto; + width: 80%; +} + +.feedLine:last-child { + display: none; +} + +.footnote { + font-size: 0.8em; +} + +.gameCardImg { + border-radius: 1rem; + max-width: 100%; +} + +.gameCardImgLand { + border-radius: 2rem; + max-width: 100%; +} + +.heroImage { + display: block; + clear: both; + margin: auto; + max-width: 100%; +} + +.icon { + display: inline-block; + font-size: 2em; + font-style: normal; + text-transform: none; + vertical-align: middle; +} + +.imgAttrib { + font-size: 0.8em; +} + +.js-momentTime { + display: inline-block; +} + +.licenseImg { + vertical-align: middle; +} + +.licenseLink { + display: inline-block; + border: 1px solid transparent; + border-bottom: 1px solid transparent; + vertical-align: baseline; +} + +.linkButton { + margin: 1em auto; + text-align: center; +} + +.linkButton-link { + border: 1px solid #25baba; + color: #25baba; + display: inline-block; + padding: 0.25em 0.5em; +} + +.magic-commander-img { + border-radius: 0.75em; + max-width: 100%; + width: 15em; +} + +.mainBio-div-img { + height: auto; + margin: 0; + vertical-align: middle; + width: 100%; +} + +.mainBio-div-imgLink { + border: 1px solid transparent; + display: block; + margin: 0 auto; + max-width: 15em; + padding: 0.5em; + -webkit-transition: 0.3s background-color, 0.3s color, 0.3s border-radius, + 0.3s border-width; + transition: 0.3s background-color, 0.3s color, 0.3s border-radius, + 0.3s border-width; +} + +.mainBio-div-imgLink:hover { + border-width: 3px; +} + +.mainBio-div-textLink { + display: none; +} + +.menubar { + background: #282c32; + display: static; +} + +.navMenu { + line-height: 2em; + padding: 0 0 0.5em; + text-align: center; +} + +.navMenu-list { + list-style: none; + padding: 0; + margin: 0; +} + +.navMenu-list-link { + border: 1px solid transparent; + text-decoration: none; +} + +.navMenu-list-link:visited { + color: #25baba; +} + +.navMenu-list-link.isCurrentSection { + background-color: #049c74; + border: 1px solid #25baba; + border-radius: 0.3rem; + color: #040308; + text-decoration: none; +} + +.navMenu-list-link.isCurrentSection:hover { + background-color: #25baba; +} + +.navMenu-list-item { + display: inline-block; + line-height: 2em; + margin: 0 0.25em; + text-align: center; +} + +.navMenu-search-fieldset { + border: none; + font-size: 0.8em; + padding: 0; +} + +.page { + background: #040308; + background: rgba(4, 3, 8, 0.9); + border: 1px solid #9aa8bc; + border-top: none; + border-bottom: none; + display: block; + margin: 0 auto; + max-width: 40em; + min-height: 100vh; + padding: 0; + position: relative; +} + +.pageFooter { + border-top: 1px solid #04778f; + margin: 0 auto; + padding: 0.5em 1em; + width: 100%; +} + +.pageFooter a { + text-decoration: none; +} + +.pageFooter-inner { + font-size: 0.8em; + text-align: center; + width: 100%; +} + +.pageFooter-inner p { + text-align: left; +} + +.pageHeader { + width: 100%; +} + +.pageHeader-titleBlock { + width: 100%; +} + +.pageMain { + min-height: 28em; + padding: 1em; +} + +.pageMenu { + clear: both; + margin: 0 auto 2.5em; + max-width: 25em; + padding: 0px; + text-align: center; +} + +.pageMenu-anaCardLink { + border: 1px solid transparent; + display: inline-block; + margin: 0 auto; + padding: 0.5em; +} + +.pageMenu-anaCards { + align-items: center; + display: flex; + flex-direction: column; + max-width: 100%; +} + +.pageMenu-caption { + left: 0; + bottom: 0.5em; + position: absolute; + right: 0; +} +.pageMenu-gameCards { + align-items: center; + display: flex; + flex-direction: column; + justify-content: center; +} + +.pageMenu-gameCardLink { + border: 1px solid transparent; + display: flex; + margin: 0 auto; + max-width: 24em; + padding: 0.5em; +} + +.pageMenu-item { + align-items: center; + border: 2px solid transparent; + border-radius: 0.3rem; + display: flex; + justify-content: center; + margin-left: 0; + max-width: 340px; + text-align: center; + text-decoration: none; + -webkit-transition: 0.3s background-color, 0.3s border-color, 0.3s color; + transition: 0.3s background-color, 0.3s border-color, 0.3s color; +} + +.pageMenu-item:hover { + border-color: #25baba; +} + +.pageMenu-link { + display: block; + height: 6.8em; + position: relative; + width: 6.8em; +} + +.pageMenu-link:hover .pageMenu-text { + background-color: #25baba; + background-color: rgba(150, 150, 150, 0.8); + color: #040308; + text-decoration: none; + width: 100%; +} + +.pageMenu-text { + background: rgba(50, 50, 50, 0.8); + display: inline-block; + margin: 0 auto; + -webkit-transition: 0.3s background-color, 0.3s color; + transition: 0.3s background-color, 0.3s color; + width: 100%; +} + +.pageSection { + word-wrap: break-word; +} + +.postsByYear { + clear: both; + display: block; + float: right; +} + +.postsByYear { + clear: both; + font-size: 0.8em; + margin: 1em auto; + text-align: center; +} + +.postsByYear-list { + display: inline; + margin: 0; + max-width: 25em; + padding: 0px; +} + +.postsByYear-list li { + border-radius: 0.3rem; +} + +.postMenu { + max-height: 0; + overflow: hidden; +} +.postMenu-item { + align-self: auto; + display: inline-block; + flex: none; + margin: 0.5em; +} + +.postMenu-link { + border: 1px solid #726f6a; + border-radius: 0.3em; + display: inline-block; + padding: 0.25em; +} + +.postMenu-list { + align-content: center; + align-items: center; + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: center; + list-style: none; + margin: 0; + padding: 0; + text-align: center; +} + +.postMenu-title { + font-size: 1.3em; + margin: 1.5em auto; + text-align: center; +} + +.postMenu-title-link { + border: 1px solid transparent; + display: inline-block; +} + +.pubDate { + font-size: 0.9em; + visibility: hidden; +} + +.raceTable-name { + font-weight: bold; + text-align: left; +} + +.readTime { + font-size: 0.9em; + font-style: italic; + text-align: right; + text-transform: capitalize; +} + +.replyTo { + margin: 0 1.25em; +} + +.replyTo-arrow { + font-size: 1.75em; +} + +.searchBox-query { + background-color: #049c74; + border-radius: 0.3rem; + color: #000; + width: 10em; +} + +.siteTitle { + text-align: center; + width: 100%; +} + +.siteTitle-link { + border: 1px solid transparent; + color: #25baba; + border-radius: 1rem; + display: inline-block; + font-style: normal; + padding: 0.2em; + position: relative; + text-decoration: none; + text-shadow: 0px 2px 2px rgba(16, 16, 16, 0.6); + -webkit-transition: 0.3s border-color, 0.3s color, 0.3s text-shadow, + 0.3s border-radius; + transition: 0.3s border-color, 0.3s color, 0.3s text-shadow, + 0.3s border-radius; +} + +.siteTitle-link:visited { + color: #25baba; +} + +.spellTable { + margin-left: -1em; +} + +.spellTable td { + border: 1px solid #094192; +} + +.spellTable tbody:nth-child(even) { + background-color: #0d1852; +} + +.tagPage-counts { + font-size: 0.9em; + font-style: italic; +} + +.tagPage-list { + padding-left: 0; +} + +.tagPage-listItem { + display: inline; + list-style: none; + padding: 0.3em 0.5em; +} + +.teaseLink { + clear: both; + font-size: 0.8em; + margin: 1em auto; + text-align: center; +} + +.teaseLink-link { + color: #25baba; + display: inline-block; + padding: 0.25em 0.5em; +} + +.titleLink { + border-bottom: none; +} + +.titleLink:active, +.titleLink:hover { + border: 1px solid #25baba; +} + +/* toggleSwitch & overrides */ +/* +.toggleSwitch:empty +{ + margin-left: -999px; +} + +.toggleSwitch:empty ~ label .toggleSwitch-info, +.toggleSwitch:checked ~ label .toggleSwitch-info { + visibility: hidden; +} + +.toggleSwitch:empty ~ label +{ + position: relative; + float: left; + line-height: 1.6em; + text-indent: 4em; + margin: 0.2em 0; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.toggleSwitch:empty ~ label:before, +.toggleSwitch:empty ~ label:after +{ + position: absolute; + display: block; + top: 0; + bottom: 0; + left: 0; + content: ' '; + width: 3.6em; + background-color: #c33; + border-radius: 0.3em; + box-shadow: inset 0 0.2em 0 rgba(0,0,0,0.3); + -webkit-transition: all 100ms ease-in; + transition: all 100ms ease-in; +} + +.toggleSwitch:empty ~ label:before +{ + content: "Disable Embeds"; +} + +.toggleSwitch:empty ~ label:after +{ + background-color: #fff; + border-radius: 0.15em; + bottom: 0.1em; + box-shadow: inset 0 -0.2em 0 rgba(0,0,0,0.2); + margin-left: 0.1em; + top: 0.1em; + width: 1.4em; +} + +.toggleSwitch:checked ~ label:before +{ + content: "Enable Embeds"; + background-color: #393; +} + +.toggleSwitch:checked ~ label:after +{ + margin-left: 2em; +} +*/ + +.topAnchor { + border: none; + height: 0; + margin: 0; + padding: 0; +} + +.topLink { + border: 1px solid #726f6a; + border-radius: 0.3em; + display: inline-block; + margin: 1em auto; + padding: 0.25em; + text-align: center; +} + +.twitter-tweet { + margin: 0; +} + +.update-citation { + display: block; + text-align: right; +} + +.update-footer { + align-items: start; + color: #423f4d; + display: flex; + flex-direction: column; + font-size: 0.9em; + font-style: italic; + margin-top: 1em; +} + +.update-footer-author { + display: none; +} + +.update-footer-time { + margin-left: auto; +} + +.update-nav { + border-top: 1px dotted; + display: flex; + margin-top: 1em; + padding-top: 1em; + width: 100%; +} + +.update-nav-link { + border: 1px dashed #726f6a; + border-radius: 0.3em; + display: block; + padding: 0.5em; +} + +.update-nav-linkWrapper { + max-width: 45%; +} + +.update-nav-pubDate { + font-size: 0.8em; +} + +.update-nav-nextWrapper { + margin-left: auto; + text-align: right; +} + +.update-tags { + align-items: center; + display: flex; + flex-wrap: wrap; + margin-top: 1em; + text-align: left; +} + +.update-tags > .boxLink { + margin: 0.5em; +} + +/**************************************************************************** + * State Overrides + ****************************************************************************/ + +.asideBio.hideBio { + display: none; +} + +.asideBio-div.showPhoto { + display: inline-block; +} + +.asideMenu-link.isCurrent { + background-color: #049c74; + background-color: rgba(4, 156, 116, 0.8); + color: #040308; + text-decoration: none; +} + +.asideMenu-link.isCurrent:hover { + background-color: #25baba; +} + +.asideUpdates .update-citation { + display: none; +} + +.asideUpdates .update-footer-time { + margin: 1em 0 2em; +} + +.asideUpdates .js-momentTime { + display: none; +} + +.asideUpdates .reacji { + float: left; +} + +.feature hr { + border: 1px 0 0 0; + border-color: #0d1852; + border-style: solid; + color: #0d1852; + max-width: 90%; +} + +.js-hasFontsLoaded body { + font-family: "Exo 2", sans-serif; +} + +.pageMenu-link.isCurrent .pageMenu-text { + background-color: #049c74; + background-color: rgba(4, 156, 116, 0.8); + color: #040308; + text-decoration: none; +} + +.pageMenu-link.isCurrent:hover .pageMenu-text { + background-color: #25baba; +} + +.textMenu-link.isCurrent { + background-color: #049c74; + background-color: rgba(4, 156, 116, 0.8); + color: #040308; + text-decoration: none; +} + +.textMenu-link.isCurrent:hover { + background-color: #25baba; +} + +.update.isDraft { + background-color: #282c32; +} + +.update.isEmbargoed { + background-color: #151222; +} + +/**************************************************************************** + * JS Overrides + ****************************************************************************/ + +.js .pubDate.isDone { + -webkit-transition: 0.3s visibility; + transition: 0.3s visibility; + visibility: visible; +} + +.no-js .pubDate { + visibility: visible; +} + +/**************************************************************************** + * Media Queries + ****************************************************************************/ + +@media all and (min-width: 38em) { + .navMenu { + padding: 0; + } + + .navMenu-list { + float: left; + text-align: left; + } + + .navMenu-list-item { + margin-left: 0.75em; + } + + .searchBox { + float: right; + margin-right: 0.75em; + } +} + +@media all and (min-width: 34em) { + .magic-commander-img { + float: right; + } +} + +@media all and (min-width: 52em) { + body { + font-size: 1.1em; + } +} + +@media all and (min-width: 70em) { + .asideContent { + background: #040308; + background: rgba(4, 3, 8, 0.9); + border: 1px solid #9aa8bc; + font-size: 0.8em; + position: absolute; + top: 5em; + } + + .asideLeft { + left: -14em; + width: 14em; + } + + .asideMenu-divider { + display: none; + } + + .asideRight { + right: -15em; + width: 15em; + } + + .asideRight .asideMenu-link { + max-width: 13em; + } + + .postMainIndex .feedLine:last-child { + display: block; + } + + .postMenu { + max-height: none; + } + + .socialList-item { + display: inherit; + } +} diff --git a/src/layouts/default.ejs b/src/layouts/default.ejs new file mode 100644 index 0000000..ec1c1e2 --- /dev/null +++ b/src/layouts/default.ejs @@ -0,0 +1,66 @@ + + + +<%- include('partials/top') %> +<% var titleLink = (site && site.base_uri) ? site.base_uri : '/'; -%> + + +
+ + +
+
+ + <%- include('partials/embed_switch') %> + + <% if (page.content_type) { -%> + + <%- (include('partials/content_types/' + page.content_type) || '').trim() %> + + <% } else { -%> + + <%- include('functions') -%> + + <% if (page.title && (page.render_opts || '').indexOf('no_title') == -1) { -%> + +

+ <%= page.title %> +

+ <% } -%> + + <%- content %> + + <% } -%> + +
+
+ + <%- include('partials/menusub') %> + + <%/* + if ("index" === top_dir) { + loadPartial(top_dir, 'latest') + } + */%> + + <%- include('partials/bio') %> + + <%- include('partials/footer') %> + +
+ +<%- include('partials/bottom') %> + + diff --git a/src/layouts/functions.ejs b/src/layouts/functions.ejs new file mode 100644 index 0000000..f488750 --- /dev/null +++ b/src/layouts/functions.ejs @@ -0,0 +1,103 @@ +<% + htmlize = (text) => { + return (text || '').replace(/&/g, '&').replace(//g, '>'); + }; + + prettyDate = (date) => { + // January 20, 2017 at 20:26 + const + month_names = [ + 'January', 'February', 'March', 'April', 'May', 'June', + 'July', 'August', 'September', 'October', 'November', 'December' + ]; + let + d = new Date(date), + has_time = d && !(d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0), + dArr = []; + if (d) { + dArr = [ + month_names[d.getMonth()], + ' ', + (d.getDate() < 10 ? '0' : ''), + d.getDate(), + ', ', + d.getFullYear() + ]; + if (has_time) { + dArr = dArr + .concat([ + ' at ', + (d.getHours() < 10 ? '0' : ''), + d.getHours(), + ':', + (d.getMinutes() < 10 ? '0' : ''), + d.getMinutes() + ]); + } + } + + return dArr.join(''); + + }; + + shortDate = (date) => { + // 2021-06-20 20:26 + const + d = new Date(date), + has_time = d && !(d.getHours() === 0 && d.getMinutes() === 0 && d.getSeconds() === 0); + let dArr = []; + + if (d) { + dArr = [ + d.getFullYear(), + '-', + (d.getMonth() < 9 ? '0' : ''), + (d.getMonth() + 1), + '-', + (d.getDate() < 10 ? '0' : ''), + d.getDate() + ]; + if (has_time) { + dArr = dArr + .concat([ + ' @ ', + (d.getHours() < 10 ? '0' : ''), + d.getHours(), + ':', + (d.getMinutes() < 10 ? '0' : ''), + d.getMinutes() + ]); + } + + return dArr.join(''); + + } + }; + + + snakeCase = (val) => { + return val.trim().toLowerCase().replace(/\W/g, '_'); + }; + + sortByPath = (p1, p2) => { + if (p1.path < p2.path) return -1; + if (p1.path > p2.path) return 1; + return 0; + }; + + reverseSortByDate = (p1, p2) => { + if (p1.date_pub && p2.date_pub) { + let + p1_dt = (new Date(p1.date_pub)).getTime(), + p2_dt = (new Date(p2.date_pub)).getTime(); + if (p1_dt < p2_dt) { + return 1; + } + if (p2_dt < p1_dt) { + return -1; + } + return 0; + } + }; + +-%> diff --git a/src/layouts/journal-year.ejs b/src/layouts/journal-year.ejs new file mode 100644 index 0000000..fd5cad5 --- /dev/null +++ b/src/layouts/journal-year.ejs @@ -0,0 +1,170 @@ + +<% + const titleLink = (site?.base_uri) ? site.base_uri : '/'; + const { entriesToList = [], pageCount, pageNum, year = '' } = page; +-%> + +<%- include('partials/top') %> + + + +
+ + +
+
+ + <%- include('partials/embed_switch') %> + + <%- include('functions') -%> + + <% if (page?.title && (page.render_opts || '').indexOf('no_title') == -1) { -%> + +

+ Journal Entries By Year: + <%= year %> +

+ <% if (pageCount > 1) { -%> +

+ (Page <%= pageNum %> of <%= pageCount %>) +

+ <% } -%> +

+ Assorted journal entries from <%= year %>. +

+ +
+ +

+ + <% } -%> + + <% if (entriesToList && year) { -%> + <% entriesToList.forEach((entry) => { -%> + <% if (entry?.content_type === 'journal') { -%> + <% + const { + author = {}, + content = '', + date_pub = '', + description = '', + path = '', + readTime = '', + tags = [], + title = '', + tldr = '' + } = entry; + -%> +

+ +
+ + <% if (author?.site && author?.name) { -%> + + <% if (author?.photo) { -%> + + <% } -%> + + + + <% } else if (site?.author?.site && site?.author?.name) { -%> + + <% if (site?.author?.photo) { -%> + + <% } -%> + + + + <% } -%> + +
+ +

+ <%= title %> +

+ + <% if (tldr || description) { -%> +

TL;DR — <%- tldr || description %>

+ <% } -%> + + <% if (readTime) { -%> +

+ 👓 <%= readTime %> +

+ <% } -%> + + <% if (content) { -%> +
+ <%- content %> +
+ <% } -%> + + + +
+ + +
+ + <% } -%> + <% }); -%> + <% } -%> + + <%- include('partials/pageMenu') %> + +
+
+ + <%- include('partials/journal/menusub') %> + + <%- include('partials/bio') %> + + <%- include('partials/footer') %> + +
+ +<%- include('partials/bottom') %> diff --git a/src/layouts/partials/anachronism/menusub.ejs b/src/layouts/partials/anachronism/menusub.ejs new file mode 100644 index 0000000..8ab9668 --- /dev/null +++ b/src/layouts/partials/anachronism/menusub.ejs @@ -0,0 +1,75 @@ + diff --git a/src/layouts/partials/bio.ejs b/src/layouts/partials/bio.ejs new file mode 100644 index 0000000..c168f3e --- /dev/null +++ b/src/layouts/partials/bio.ejs @@ -0,0 +1,76 @@ + + + +<% + var + show_bio = !(page.name === 'about' && page.path.indexOf('about') === 0), + photo_class = (page.name === 'index' && page.path === '' || page.path.indexOf('index') === 0 ? ' showPhoto' : ''); + + if (show_bio) { +%> + + + +<% } %> + + diff --git a/src/layouts/partials/bottom.ejs b/src/layouts/partials/bottom.ejs new file mode 100644 index 0000000..4a6f143 --- /dev/null +++ b/src/layouts/partials/bottom.ejs @@ -0,0 +1,16 @@ + + + +
+ + + + + + + + + + + + diff --git a/src/layouts/partials/content_types/feature.ejs b/src/layouts/partials/content_types/feature.ejs new file mode 100644 index 0000000..5010e7a --- /dev/null +++ b/src/layouts/partials/content_types/feature.ejs @@ -0,0 +1,14 @@ +<%- include('../../functions') -%> + +<% if (page.title && (page.render_opts || '').indexOf('no_title') == -1) { -%> + +

+ <%= page.title %> +

+<% } -%> +<%- content %> diff --git a/src/layouts/partials/content_types/journal.ejs b/src/layouts/partials/content_types/journal.ejs new file mode 100644 index 0000000..26b5456 --- /dev/null +++ b/src/layouts/partials/content_types/journal.ejs @@ -0,0 +1,108 @@ +<%- include('../../functions') -%> +<% + var + journals = site.pages.filter(thePage => thePage.content_type === 'journal'), + curr = journals.filter(journal => journal.filePath === page.filePath), + currIndex = journals.map(journal => journal.filePath).indexOf(page.filePath), + prev = currIndex < (journals.length - 1) ? journals[currIndex + 1] : null, + next = currIndex > 0 ? journals[currIndex - 1] : null; +%> + +<% if (page.title) { -%> + +

+ <%= page.title %> +

+ +<% } -%> + +<% if (page.readTime) { -%> + +

+ 👓 <%= page.readTime %> +

+ +<% } -%> + + +<% if (page.tldr || page.description) { -%> +

TL;DR — <%- page.tldr || page.description %>

+<% } -%> + +
+ <%- content %> +
+ + \ No newline at end of file diff --git a/src/layouts/partials/content_types/magic-deck.ejs b/src/layouts/partials/content_types/magic-deck.ejs new file mode 100644 index 0000000..2bfc678 --- /dev/null +++ b/src/layouts/partials/content_types/magic-deck.ejs @@ -0,0 +1,99 @@ +<%- include('../../functions') -%> + +<% + var + card_url = "http://gatherer.wizards.com/Pages/Search/Default.aspx?name=+[%22CARD-NAME%22]", + detail_url = "http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=", + image_url = "/images/magic/commanders/", + deck = page.deck || {}, + info = deck.info || {}, + cards = deck.cards || [], + lands = deck.lands || [], + changes = deck.changes || [], + starting_lands = info.starting_lands || [], + + commander = info.commander && info.commander_id ? + "
  • " + info.commander + + " (Commander)
  • " : + "", + commander_img = info.commander && info.commander_img ? + "" + info.commander + " card": + "" + ; +-%> + +

    + + <%= page.title %> + +

    + +

    + Below is my <%= info.name %> deck for Magic: the Gathering + (<%= info.format %> format). + It was last updated on <%= info.date_upd %>. +

    + +

    + Each card listed below is linked to its entry on The Gatherer + (the official MtG card database) and should open in a new window or tab in + your browser. +

    + +

    Decklist

    + +<%- commander_img %> + +
      + <%- commander %> + <% cards.forEach(function(card) { %> +
    • <%= card %>
    • + <% }) %> + <% lands.forEach(function(land) { %> +
    • <%= land.type %> (x<%=land.count%>)
    • + <% }) %> +
    + +<% if (starting_lands && starting_lands.length > 0) { %> +

    Starting Lands

    +

    + In order to speed our games along, my gaming group allows everyone to start with 3 basic lands. + The lands listed below are included in the counts above.

    +
      + <% starting_lands.forEach(function(land) { %> + <% if (typeof land === 'string') { %> +
    • <%= land %>
    • + <% } else {%> +
    • + <%= land.type %> (x<%=land.count%>) +
    • + <% } %> + <% }) %> +
    +<% } %> + +<% if (changes && changes.length > 0) { %> +

    Changes from Previous Versions

    + +
      + <% changes.forEach(function(change) { %> +
    • + Implemented <%= change.date_upd %>: +
        + <% if (change.adds) { %> + <% change.adds.forEach(function(add) { %> +
      • <%= add %> (added)
      • + <% }) %> + <% } %> + <% if (change.dels) { %> + <% change.dels.forEach(function(del) { %> +
      • <%= del %> (removed)
      • + <% }) %> + <% } %> +
      +
    • + <% }) %> +
    +<% } %> + +<%- content %> diff --git a/src/layouts/partials/embed_switch.ejs b/src/layouts/partials/embed_switch.ejs new file mode 100644 index 0000000..973cc2b --- /dev/null +++ b/src/layouts/partials/embed_switch.ejs @@ -0,0 +1,15 @@ + + + +<% + if (page.path && page.path.indexOf('/updates') === 0) { +-%> +
    +
    + + +
    +
    +<% } -%> + + diff --git a/src/layouts/partials/footer.ejs b/src/layouts/partials/footer.ejs new file mode 100644 index 0000000..826c2ba --- /dev/null +++ b/src/layouts/partials/footer.ejs @@ -0,0 +1,51 @@ + + + + + + diff --git a/src/layouts/partials/header.ejs b/src/layouts/partials/header.ejs new file mode 100644 index 0000000..09ecae5 --- /dev/null +++ b/src/layouts/partials/header.ejs @@ -0,0 +1,30 @@ + + + + + + diff --git a/src/layouts/partials/journal/menusub.ejs b/src/layouts/partials/journal/menusub.ejs new file mode 100644 index 0000000..426b06c --- /dev/null +++ b/src/layouts/partials/journal/menusub.ejs @@ -0,0 +1,60 @@ + \ No newline at end of file diff --git a/src/layouts/partials/linklists/menusub.ejs b/src/layouts/partials/linklists/menusub.ejs new file mode 100644 index 0000000..e7b4bdb --- /dev/null +++ b/src/layouts/partials/linklists/menusub.ejs @@ -0,0 +1,43 @@ + diff --git a/src/layouts/partials/magic-cards/menusub.ejs b/src/layouts/partials/magic-cards/menusub.ejs new file mode 100644 index 0000000..e69010c --- /dev/null +++ b/src/layouts/partials/magic-cards/menusub.ejs @@ -0,0 +1,36 @@ + diff --git a/src/layouts/partials/magic-decks/menusub.ejs b/src/layouts/partials/magic-decks/menusub.ejs new file mode 100644 index 0000000..644bbfe --- /dev/null +++ b/src/layouts/partials/magic-decks/menusub.ejs @@ -0,0 +1,62 @@ + diff --git a/src/layouts/partials/menusub.ejs b/src/layouts/partials/menusub.ejs new file mode 100644 index 0000000..52d4f88 --- /dev/null +++ b/src/layouts/partials/menusub.ejs @@ -0,0 +1,21 @@ + + +<% if (page.section && page.subsection && page.section === 'games') { %> + <% if (page.subsection === 'anachronism') { %> + <%- include('anachronism/menusub') %> + <% } else if (page.subsection === 'magic-cards' && page.name !== 'index') { %> + <%- include('magic-cards/menusub') %> + <% } else if (page.subsection === 'magic-decks' && page.name !== 'index') { %> + <%- include('magic-decks/menusub') %> + <% } else if (page.subsection === 'thur' && page.name !== 'index') { %> + <%- include('thur/menusub') %> + <% } %> +<% } else if (page.section && page.subsection && page.section === 'web') { %> + <% if (page.subsection === 'linklists' && page.name !== 'index') { %> + <%- include('linklists/menusub') %> + <% } %> +<% } else if (page.content_type === 'journal') { %> + <%- include('journal/menusub') %> +<% } %> + + diff --git a/src/layouts/partials/navmain.ejs b/src/layouts/partials/navmain.ejs new file mode 100644 index 0000000..afd8d32 --- /dev/null +++ b/src/layouts/partials/navmain.ejs @@ -0,0 +1,40 @@ + + + + + + diff --git a/src/layouts/partials/pageMenu.ejs b/src/layouts/partials/pageMenu.ejs new file mode 100644 index 0000000..cac5679 --- /dev/null +++ b/src/layouts/partials/pageMenu.ejs @@ -0,0 +1,17 @@ +<% const { pageCount, pageNum } = page; -%> + +<% if (pageNum && pageCount > 1) { -%> + +<% } -%> diff --git a/src/layouts/partials/thur/menusub.ejs b/src/layouts/partials/thur/menusub.ejs new file mode 100644 index 0000000..51c1988 --- /dev/null +++ b/src/layouts/partials/thur/menusub.ejs @@ -0,0 +1,43 @@ + diff --git a/src/layouts/partials/toolbar.ejs b/src/layouts/partials/toolbar.ejs new file mode 100644 index 0000000..3ce4733 --- /dev/null +++ b/src/layouts/partials/toolbar.ejs @@ -0,0 +1,11 @@ + + + +
    + + + + Menu +
    + + diff --git a/src/layouts/partials/top.ejs b/src/layouts/partials/top.ejs new file mode 100644 index 0000000..1c9c59d --- /dev/null +++ b/src/layouts/partials/top.ejs @@ -0,0 +1,88 @@ + + +<% + const + getPageField = (field_name) => { + return page[field_name] || site[field_name] || ''; + }, + getUrl = () => site.base_uri + (site.base_uri.endsWith('/') ? '' : '/') + page.path; +-%> + + + + + + + + + + + + + <%= page.title ? page.title + ' | ' : ''%><%= page.sub_title ? page.sub_title + ' | ' : ''%><%= site.title %> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<% if (page.image) { %> + +<% } %> +<% if (page.description) { %> + +<% } %> + + +<% if (page.image) { %> + +<% } else { %> + +<% } %> + + + + +<% if (page.author && page.author.twitter) { %> + +<% } else if (site.author && site.author.twitter) { %> + +<% } %> + + + + + + + + + + + diff --git a/src/layouts/partials/topLink.ejs b/src/layouts/partials/topLink.ejs new file mode 100644 index 0000000..e69de29 diff --git a/src/layouts/tag.ejs b/src/layouts/tag.ejs new file mode 100644 index 0000000..381eada --- /dev/null +++ b/src/layouts/tag.ejs @@ -0,0 +1,161 @@ + +<% + var cwd = (process && process.cwd) ? process.cwd() : ''; + var titleLink = (site && site.base_uri) ? site.base_uri : '/'; + const { entriesToList, pageCount, pageNum, tag } = page; +-%> + +<%- include('partials/top') %> + + + + + +
    + + +
    +
    + + <%- include('partials/embed_switch') -%> + + <%- include('functions') -%> + + <% if (page.title && (page.render_opts || '').indexOf('no_title') == -1) { -%> + +

    + Journal Entries By Tag: #<%= tag -%> +

    + + <% if (pageCount > 1) { -%> +

    + (Page <%= pageNum %> of <%= pageCount %>) +

    + <% } -%> + +

    + Assorted journal entries with the tag #<%= tag %>. +

    + +
    + +

    + <% } -%> + + <% if (content && Array.isArray(entriesToList)) { -%> + <% entriesToList.forEach((page) => { -%> +

    + +
    + + <% if (page.author && page.author.site && page.author.name) { -%> + + <% if (page.author.photo) { -%> + + <% } -%> + + + + <% } else if (site.author && site.author.site && site.author.name) { -%> + + <% if (site.author.photo) { -%> + + <% } -%> + + + + <% } -%> + +
    + +

    + <%= page.title %> +

    + + <% if (page.tldr || page.description) { -%> +

    TL;DR — <%- page.tldr || page.description %>

    + <% } -%> + + <% if (page.readTime) { -%> +

    + 👓 <%= page.readTime %> +

    + <% } -%> + + <% if (page.content) { -%> +
    + <%- page.content %> +
    + <% } -%> + + + +
    + + +
    + + <% }) -%> + + <% } -%> + + <%- include('partials/pageMenu') %> + + + +
    +
    + +<%- include('partials/journal/menusub') %> + +<%- include('partials/bio') %> + +<%- include('partials/footer') %> + +
    + +<%- include('partials/bottom') %> diff --git a/src/pages/about.ejs b/src/pages/about.ejs new file mode 100644 index 0000000..c506caf --- /dev/null +++ b/src/pages/about.ejs @@ -0,0 +1,111 @@ +--- +{ + "title": "About", + "description": "Information about both Eric and the site.", + "date_pub": "2015-11-10T07:18:00-05:00", + "date_upd": "2021-06-21T23:58:00-04:00", + "section" : "about", + "content_type": "feature", + "short_code": "ma", + "render_opts": "no_title" +} +--- +
    + + +

    About Me

    + +
      +
    • My name is Eric Woodward and this is my website.
    • + +
    • + I am a geek, + coder, + gamer, + tinkerer, + husband, + father, + server admin, + web developer, + and American + cyborg, + though not necessarily in that order. +
    • + +
    • I spend most of my waking hours staring at screens, usually either coding, gaming, or web surfing (or some combination thereof).
    • + +
    • I live with my wife, two kids, four cats, and a dog in a house outside Charlotte, North Carolina.
    • + +
    • + I've been programming since I was 8, first on an Apple IIe, then on an Atari 130XE, followed by various + x86 PCs, and finally the World Wide Web itself. Along the way, I've used (and abused) various forms of + BASIC, C++, LISP, x86 Assembly, PL-SQL, Perl, PHP, Java, and shell scripting, before ultimately settling on + my current day-to-day usage of JavaScript and HTML. +
    • + +
    • In January, 2016, my first officially published tabletop game, + Mythic Wars, was released by + Excalibre Games. +
    • + +
    • + Since 2018, I've gotten back into RPGs in a big way, running (and playing in) several + weekly games over the course of the pandemic. Most recently, I started an + AstralJamming campaign using the + [advanced Old-School Essentials rules](https://necroticgnome.com/collections/rules). +
    • + +
    • + I prefer to be reached via e-mail at + Email. + + Alternatively, you can grab my + vCard and add me to your address book. +
    • +
    • + I host a collection of + git repos + (where I keep my code). +
    • +
    • + I am sporadically active on various corporate social media silos, and have accounts on + LinkedIn, + GitHub, and + BoardGameGeek. +
    • +
    + + Back to Top + +

    About This Site

    + +

    + This site is powered by Node, + nginx, + VSCodium, + this image from EMIL Ivanov at PEXELS, + the Exo 2 font, + a Raspberry Pi 4, and + a truly massive ego. +

    + + Back to Top + +
    diff --git a/src/pages/anachronism/armors.md b/src/pages/anachronism/armors.md new file mode 100644 index 0000000..b94f886 --- /dev/null +++ b/src/pages/anachronism/armors.md @@ -0,0 +1,52 @@ +--- +title: U.S. American Armor Cards +sub_title: Custom Anachronism Cards +description: Eric's custom armor cards for the game Anachronism. +date_pub: 2014-04-27T20:58:00-05:00 +date_upd: 2018-08-18T13:19:00-04:00 +license: CC0 +section: games +subsection: anachronism +content_type: feature +--- +If you like these cards, please feel free to save them, print them, and share them. As stated on the cards, they are as far as I'm concerned. Links open in a new window. + + + +Back to Top diff --git a/src/pages/anachronism/index.md b/src/pages/anachronism/index.md new file mode 100644 index 0000000..fe4c98e --- /dev/null +++ b/src/pages/anachronism/index.md @@ -0,0 +1,57 @@ +--- +title: Custom Anachronism Cards +description: Eric's custom cards for the game Anachronism. +date_pub: 2014-03-09T22:49:00-05:00 +date_upd: 2018-08-18T13:19:00-04:00 +license: CC0 +section: games +subsection: anachronism +content_type: feature +render_opts: no_title +--- + + +## Intro +Welcome to my custom card collection for the game *Anachronism*. It should be noted up front that I am not and have not ever been directly involved with Triking Games or [The History Channel](http://www.history.com/), except as a Judge during several organized play tournaments of *Anachronism*. + +**Disclaimer: I do not own any copyrights to the game or its logos, nor am I attempting to claim the copyright of anything associated with it - all copyrights used herein are the property of their respective owners, whomever they may currently be.** + +Now, with that out of the way, let me say a few words about the game itself. + +Back to Top + +## The Game + +Way back in 2005, a company called Triking Games, in conjuction with The History Channel, published a different kind of collectable card game: *Anachronism - The Greatest Game in History*. + +I'll leave it to the Great Oracle of All Knowledge +to describe it: + +> The game is a contest of arms between two warriors from numerous historical periods. Each game lasts a maximum of five rounds. The game is unusual for a card game in that it does not use shuffling as a randomization technique. Anachronism "decks" consist of five cards, and players do not draw cards or have a "hand" of cards. Despite the relatively small number of cards used in each game, card interactions and strategy can become surprisingly intricate, especially in the later rounds. Each player places his chosen warrior card on the playmat and his four support cards, face down, in slots corresponding to the first four rounds. The support cards may be any combination of inspiration, weapon, armor, or special cards. Each player flips his leftmost face-down support card at the beginning of each round. Initiative numbers on the support cards determine which player goes first in each round. The warrior cards may move and be turned (faced) as in a miniatures game. Support cards represent a variety of historical weapons, armor, items, deities, people, places or concepts such as the Norse sverd or Japanese book Go Rin No Sho. The game's name is derived from the ability to mix the various support cards such that the ancient Greek Leonidas wearing a kimono may fight a Japanese ninja who is wielding a gladius. Dice are used by both the attacker and defender to determine the outcome of battles. + +And unlike almost every other CCG, Anachronism packs were not blind boosters, so when you bought a [Genghis Khan](http://en.wikipedia.org/wiki/Genghis_Khan) pack, for example, you knew what 4 other cards were in the pack. And even though each player only needed 1 deck to play, the best combinations usually involved mixing cards from 2 or more packs together, so most of my friends would buy complete (or mostly complete) sets of the decks, just to maximize playability. And my friends and I played it alot, both when hanging out together, and at organized tournaments. In fact, I got into it big enough that I started running weekly, Triking-sponsored tournaments at our FLGS, even hosting the state's only *regional qualifying* tournament for 2006 (to qualify for the World Tournament at Gencon). + +Unfortunately, a run of (IMHO) less-appealing cards hit the game, and enthusiasm died down. Before long, the company closed, and Anachronism was just another footnote in gaming history. But that shouldn't mean the end of the game. And with *Anachronism*, it wasn't. + +A group of determined former judges and players got together, and before long actually released a print-and-play card set containing cards which Triking had designed prior to their closing, along with an additional set based on the judges own ideas'. It is in the spirit of these "homebrew" sets that I present my own submission to the greater *Anachronism* fan community. + +Back to Top + +## My Cards + +I've created a fair number of cards, and hope to have them all listed here before too long, but for the time being, I've only managed to build pages for my custom US American cards + +Back to Top + +## Credits + +Many thanks to those who supported this project, intentionally or otherwise. Most especially, thanks to: + ++ Triking Games and the History Channel, for publishing the game (and the prize support); ++ Ballistic Comics, for carrying the game and hosting the official tournaments (you will be missed); ++ My old play group, for all the good times; ++ Devin Heard for the [Encyclopedia Anachronistica](http://dystemporalia.org/encyclopaedia/) his fantastic interactive card reference (which was immensely helpful in designing the cards); ++ Twan van Laarhoven for [Magic Set Editor](http://magicseteditor.sourceforge.net/) and artfreakwiu for his [Anachronism templates](http://msetemps.sourceforge.net/phpBB3/viewtopic.php?t=144), without which these cards would look alot crappier; and ++ My family (especially my son, KDub) for their playtesting and continued support. + +Back to Top diff --git a/src/pages/anachronism/inspirations.md b/src/pages/anachronism/inspirations.md new file mode 100644 index 0000000..b99654f --- /dev/null +++ b/src/pages/anachronism/inspirations.md @@ -0,0 +1,52 @@ +--- +title: U.S. American Inspiration Cards +sub_title: Custom Anachronism Cards +description: Eric's custom inspiration cards for the game Anachronism. +date_pub: 2014-04-27T20:57:00-05:00 +date_upd: 2018-08-18T13:19:00-04:00 +license: CC0 +section: games +subsection: anachronism +content_type: feature +--- +If you like these cards, please feel free to save them, print them, and share them. As stated on the cards, they are as far as I'm concerned. Links open in a new window. + + + +Back to Top diff --git a/src/pages/anachronism/specials.md b/src/pages/anachronism/specials.md new file mode 100644 index 0000000..604c751 --- /dev/null +++ b/src/pages/anachronism/specials.md @@ -0,0 +1,52 @@ +--- +title: U.S. American Special Cards +sub_title: Custom Anachronism Cards +description: Eric's custom special cards for the game Anachronism. +date_pub: 2014-04-27T20:56:00-05:00 +date_upd: 2018-08-18T13:19:00-04:00 +license: CC0 +section: games +subsection: anachronism +content_type: feature +--- +If you like these cards, please feel free to save them, print them, and share them. As stated on the cards, they are as far as I'm concerned. Links open in a new window. + + + +Back to Top diff --git a/src/pages/anachronism/us_americans/billy_the_kid.md b/src/pages/anachronism/us_americans/billy_the_kid.md new file mode 100644 index 0000000..dbc8a38 --- /dev/null +++ b/src/pages/anachronism/us_americans/billy_the_kid.md @@ -0,0 +1,54 @@ +--- +{ + "title": "Billy \"The Kid\" Warrior Pack", + "sub_title": "Custom Anachronism Cards", + "description": "A set of custom cards designed by Eric Woodward for the defunct Anachronism CCG", + "date_pub": "2014-03-23T22:43:00-05:00", + "date_upd": "2018-08-18T13:17:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "anachronism", + "content_type": "feature" +} +--- +Even though modern historians have raised doubts about his actual prowress as a criminal, Billy's notoriety as an outlaw in the American "Old West" made him the perfect addition to this set. + +If you like these cards, please feel free to save them, print them, and share them. As stated on the cards, they are as far as I'm concerned. Links open in a new window. + + diff --git a/src/pages/anachronism/us_americans/george_washington.md b/src/pages/anachronism/us_americans/george_washington.md new file mode 100644 index 0000000..662b62b --- /dev/null +++ b/src/pages/anachronism/us_americans/george_washington.md @@ -0,0 +1,56 @@ +--- +{ + "title": "George Washington Warrior Pack", + "sub_title": "Custom Anachronism Cards", + "description": "A set of custom cards designed by Eric Woodward for the defunct Anachronism CCG", + "date_pub": "2014-04-27T20:27:00-05:00", + "date_upd": "2018-08-18T13:17:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "anachronism", + "content_type": "feature" +} +--- +It's safe to say that I have wanted a George Washington deck almost from the very first time I saw **Anachronism**. I'm not entirely sure why, but as the years went on, my enthusiasm never waned. So, once I started putting this culture together, his was the first deck I finished, and became the format by which the others were built (specifically, a firearm for a weapon, and an ally for a Special). + +If you like these cards, please feel free to save them, print them, and share them. As stated on the cards, they are as far as I'm concerned. Links open in a new window. + + + +Back to Top diff --git a/src/pages/anachronism/us_americans/index.md b/src/pages/anachronism/us_americans/index.md new file mode 100644 index 0000000..2c1c23c --- /dev/null +++ b/src/pages/anachronism/us_americans/index.md @@ -0,0 +1,25 @@ +--- +{ + "title": "US Americans Set", + "sub_title": "Custom Anachronism Cards", + "description": "A list of custom warrior packs designed by Eric Woodward for the defunct Anachronism CCG.", + "date_pub": "2014-04-27T20:58:00-05:00", + "date_upd": "2018-08-18T13:17:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "anachronism", + "content_type": "feature", + "short_code": "a1" +} +--- + + Warrior - George Washington + + +I always felt that the US should have had its culture pack. I mean, sure, there was a Native American pack (a good set, at that), and a Frontier American pack (?!), but where was the culture that included [George Washington](/anachronism/us_americans/george_washington), or [Billy the Kid](/anachronism/us_americans/billy_the_kid)? Where was [Wyatt Earp](/anachronism/us_americans/wyatt_earp), or [Ulysses S. Grant](/anachronism/us_americans/ulysses_s_grant), or [Robert E. Lee](/anachronism/us_americans/robert_e_lee)? And so it was that I sought to fill this gap with my custom-made **Anachronism US American Culture Pack**, featuring five of the greatest warriors ever to have called themselves Americans. + +I have tried to use only sourced, public domain or otherwise material to build these cards. If you discover that I am in error or somehow in violation of a copyright, please let me know at , and I will take every measure possible to correct the mistake. + +Back to Top diff --git a/src/pages/anachronism/us_americans/robert_e_lee.md b/src/pages/anachronism/us_americans/robert_e_lee.md new file mode 100644 index 0000000..0e53670 --- /dev/null +++ b/src/pages/anachronism/us_americans/robert_e_lee.md @@ -0,0 +1,56 @@ +--- +{ + "title": "Robert E. Lee Warrior Pack", + "sub_title": "Custom Anachronism Cards", + "description": "A set of custom cards designed by Eric Woodward for the defunct Anachronism CCG", + "date_pub": "2014-04-27T23:32:00-05:00", + "date_upd": "2018-08-18T13:17:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "anachronism", + "content_type": "feature" +} +--- +Considered by many to be one of the greatest military leaders in U.S. history, General Robert E. Lee commanded the Army of Northern Virginia (and, eventually, all of the Confederate forces) during the Civil War. + +If you like these cards, please feel free to save them, print them, and share them. As stated on the cards, they are as far as I'm concerned. Links open in a new window. + + + +Back to Top diff --git a/src/pages/anachronism/us_americans/ulysses_s_grant.md b/src/pages/anachronism/us_americans/ulysses_s_grant.md new file mode 100644 index 0000000..0dff78a --- /dev/null +++ b/src/pages/anachronism/us_americans/ulysses_s_grant.md @@ -0,0 +1,54 @@ +--- +{ + "title": "Ulysses S. Grant Warrior Pack", + "sub_title": "Custom Anachronism Cards", + "description": "A set of custom cards designed by Eric Woodward for the defunct Anachronism CCG", + "date_pub": "2014-04-27T20:44:00-05:00", + "date_upd": "2018-08-18T13:17:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "anachronism", + "content_type": "feature" +} +--- +If you like these cards, please feel free to save them, print them, and share them. As stated on the cards, they are as far as I'm concerned. Links open in a new window. + + + +Back to Top diff --git a/src/pages/anachronism/us_americans/wyatt_earp.md b/src/pages/anachronism/us_americans/wyatt_earp.md new file mode 100644 index 0000000..62d01ba --- /dev/null +++ b/src/pages/anachronism/us_americans/wyatt_earp.md @@ -0,0 +1,54 @@ +--- +{ + "title": "Wyatt Earp Warrior Pack", + "sub_title": "Custom Anachronism Cards", + "description": "A set of custom cards designed by Eric Woodward for the defunct Anachronism CCG", + "date_pub": "2014-03-23T22:43:00-05:00", + "date_upd": "2018-08-18T13:17:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "anachronism", + "content_type": "feature" +} +--- +If you like these cards, please feel free to save them, print them, and share them. As stated on the cards, they are as far as I'm concerned. Links open in a new window. + + + +Back to Top diff --git a/src/pages/anachronism/warriors.md b/src/pages/anachronism/warriors.md new file mode 100644 index 0000000..3d423bb --- /dev/null +++ b/src/pages/anachronism/warriors.md @@ -0,0 +1,52 @@ +--- +title: U.S. American Warrior Cards +sub_title: Custom Anachronism Cards +description: Eric's custom warrior cards for the game Anachronism. +date_pub: 2014-04-27T20:55:00-05:00 +date_upd: 2018-08-18T13:19:00-04:00 +license: CC0 +section: games +subsection: anachronism +content_type: feature +--- +If you like these cards, please feel free to save them, print them, and share them. As stated on the cards, they are as far as I'm concerned. Links open in a new window. + + + +Back to Top diff --git a/src/pages/anachronism/weapons.md b/src/pages/anachronism/weapons.md new file mode 100644 index 0000000..f650775 --- /dev/null +++ b/src/pages/anachronism/weapons.md @@ -0,0 +1,52 @@ +--- +title: U.S. American Weapon Cards +sub_title: Custom Anachronism Cards +description: Eric's custom weapon cards for the game Anachronism. +date_pub: 2014-04-27T20:59:00-05:00 +date_upd: 2018-08-18T13:19:00-04:00 +license: CC0 +section: games +subsection: anachronism +content_type: feature +--- +If you like these cards, please feel free to save them, print them, and share them. As stated on the cards, they are as far as I'm concerned. Links open in a new window. + + + +Back to Top diff --git a/src/pages/chim/index.md b/src/pages/chim/index.md new file mode 100644 index 0000000..865c92d --- /dev/null +++ b/src/pages/chim/index.md @@ -0,0 +1,86 @@ +--- +title: Camp Happy Island Massacre +description: Eric's first (and only) computer game, a comedy-horror text game for the DOS operating system. +date_pub: 2018-10-10T19:07:00-04:00 +license: CC0 +section: games +subsection: chim +content_type: feature +--- + + +In 1997, I released my first (and, so far, only) computer game, **Camp Happy Island Massacre**, a comedy-horror text game for the DOS operating system. Originally written while I was still in college, the game is about a cursed summer camp and the 3 surviving counselors who try to stop a horrific force before it claims them. + +If you have a functional DOS machine (or an emulator, like [DOSBox](https://www.dosbox.com/)), you can download the game in a [ZIP file](/files/chim/chim.zip), which contains the following files: + ++ [`CHIM.EXE`](/files/chim/chim.exe) *(the main executable file)* ++ [`CHIM.FAQ`](/files/chim/chim.faq) *(list of frequently asked questions)* ++ [`FILE_ID.DIZ`](/files/chim/file_id.diz) *(ZIP file descriptor)* ++ [`INTRO.TXT`](/files/chim/intro.txt) *(the intro screen)* ++ [`LICENSE.TXT`](/files/chim/license.txt) *(the distribution license)* ++ [`MAP.TXT`](/files/chim/map.txt) *(a text map of the island)* + +And now, thanks to [DOSBox](https://www.dosbox.com/), [Emscripten](http://emscripten.org/), and their unholy lovechild, [JS-DOS](https://js-dos.com/), you can play **Camp Happy Island Massacre** in your browser: + +
    + + + + diff --git a/src/pages/games/illuminati.md b/src/pages/games/illuminati.md new file mode 100644 index 0000000..3263379 --- /dev/null +++ b/src/pages/games/illuminati.md @@ -0,0 +1,86 @@ +--- +title: Illuminati +description: Eric's custom conspiracy cards for Illuminati. +date_pub: 2022-08-18T01:35:00-04:00 +license: CC0 +section: games +subsection: illuminati +content_type: feature +--- + +A few years ago, I got heavy into Steve Jackson's incredible conspiracy-focused game, [Illuminati](http://www.sjgames.com/illuminati/), and made a handful of cards inspired by some of my favorite conspiracies, which you can find below: + + diff --git a/src/pages/games/index.md b/src/pages/games/index.md new file mode 100644 index 0000000..e562ff5 --- /dev/null +++ b/src/pages/games/index.md @@ -0,0 +1,31 @@ +--- +{ + "title": "Games", + "description": "Some of Eric's gaming-related projects.", + "date_pub": "2018-08-18T13:39:00-04:00", + "date_upd": "2022-08-22T11:15:00-04:00", + "section": "games", + "content_type": "feature", + "short_code": "mg", +} +--- + +One of my biggest hobbies / time-sinks over the last 20+ years of my life has been gaming in its various forms. As such, below you'll find a small collection of my gaming-related projects. + +### My Games + +- [Camp Happy Island Massacre](/chim) - My first (and only) computer game, a comedy-horror text game for the DOS operating system that you can now play online. +- [Mythic Wars](https://mythicwarsgame.com/) - My tabletop (card and dice) game, where the gods and goddesses themselves battle for ultimate supremacy! Published by [Excalibre Games](http://excalibregames.com/). + + + +### Other People's Games + +- [Anachronism](/anachronism) - My unofficial custom cards for the awesome (but defunct) [Anachronism card game](). +- [Illuminati Custom Groups](./illuminati.html) - My unofficial custom Illuminati cards for Steve Jackson's hilariously-fun [Illuminati card game](http://www.sjgames.com/illuminati/). +- Magic: the Gathering - Stuff for the [undisputed king of CCGs](https://magic.wizards.com/en). + - [Custom Cards](/magic-cards) - My unofficial cards, featuring friends, fun, and shameles cross-promotion! + - [Decks](/magic-decks) - Some of the decks I've built for Saturday Night Magic. diff --git a/src/pages/index.md b/src/pages/index.md new file mode 100644 index 0000000..c844318 --- /dev/null +++ b/src/pages/index.md @@ -0,0 +1,16 @@ +--- +title: Greetings! +description: Welcome to It's Eric Woodward (dotcom). +date_pub: 2015-11-10T07:18:00-05:00 +date_upd: 2021-06-21T23:15:00-04:00 +section: main +content_type: feature +short_code: m1 +--- +As it says [elsewhere](/about.html), my name is Eric Woodward, and this is my website. + +Mostly, I use it as a repository for some of the stuff that my brain has dumped out through the years, such as the [games](games.html) and [web](web.html) projects that I occasionally work on, the odd [journal entry](/journal/), and what I'm working on right [now](/now.html). + +I also host [my own git repos](https://git.itsericwoodward.com/), in case you want to see what I've been working on. + +Thanks for stopping by! diff --git a/src/pages/linklists/blogroll.md b/src/pages/linklists/blogroll.md new file mode 100644 index 0000000..35e416b --- /dev/null +++ b/src/pages/linklists/blogroll.md @@ -0,0 +1,80 @@ +--- +title: Blogroll +sub_title: LinkLists +description: A list of the blogs I read with (some) regularity +date_pub: 2022-07-21T00:54:00-04:00 +date_upd: 2022-09-16T23:43:00-04:00 +content_type: feature +section: web +subsection: linklists +--- + +_Compiled 2022-07-21 / Updated 2022-09-17_ + +Below are links to some of the blogs that I read, updated as of September 17, 2022. + +### General + +- [Aaron Parecki](https://aaronparecki.com/) +- [Adactio (Jeremy Keith)](https://adactio.com/) +- [Alex Shroeder](https://alexschroeder.ch/wiki/Diary) +- [Andrew Roach](http://ajroach42.com/) +- [Aral Balkan](https://ar.al/) +- [Baldur Bjarnason](https://www.baldurbjarnason.com/) (and [his notes](https://notes.baldurbjarnason.com/)) +- [blog.lmorchard.com](https://blog.lmorchard.com/) +- [The Boston Diaries](http://boston.conman.org//) +- [Brad Frost](https://bradfrost.com/blog/) +- [Chris Aldrich](https://boffosocko.com/blog/) +- [Coding Horror](https://blog.codinghorror.com/) +- [Jim Nielsen](https://blog.jim-nielsen.com/) +- [jwz](https://jwz.com/blog/) +- [Shtetl-Optimized (Scott Aaronson)](https://scottaaronson.blog/) +- [Tantek Γ‡elik](http://tantek.com/) + +### Technology + +- [Stratechery](https://stratechery.com/) +- [Cyberdeck Cafe](https://cyberdeck.cafe/) +- [Mozilla Hacks](https://hacks.mozilla.org/) +- [HACKADAY](https://hackaday.com/) +- [N-O-D-E.net](https://n-o-d-e.net/) + +### Tabletop Gaming + +- [The Alexandrian](https://thealexandrian.net/) +- [The Blog of Holding](http://blogofholding.com/) +- [Eldritch Fields](http://eldritchfields.blogspot.com/) +- [Goblin Punch](https://goblinpunch.blogspot.com/) +- [Grognardia](https://grognardia.blogspot.com/) +- [Silverarm](https://silverarmpress.com/) +- [Sly Flourish](https://slyflourish.com/) +- [Strange Magic](http://strangemagic.robertsongames.com/) +- [The Tao of D&D](https://tao-dnd.blogspot.com/) +- [Traverse Fantasy](https://traversefantasy.blogspot.com/) +- [Welcome to the Deathtrap](https://deathtrap-games.blogspot.com/) + +### YouTube Channels / Vlogs + +- [The 8-Bit Guy](https://www.youtube.com/c/The8BitGuy) +- [Bandit's Keep](https://www.youtube.com/channel/UC0-gfEp3GDT0wT7bdU-CeSw) +- [Cinema Wins](https://www.youtube.com/channel/UCL8h3ri2WN_-IbviBlWtUcQ) +- [The Coridor Crew](https://www.youtube.com/user/samandniko) +- [Dungeon Craft](https://www.youtube.com/channel/UCD6ERRdXrF2IZ0R888G8PQg) +- [Dungeon Masterpiece](https://www.youtube.com/channel/UC5l5MjE1H1NP7Gh6VOZNfsQ) +- [Friday Night Arcade](https://www.youtube.com/user/MediaGlitchHD) +- [Hak5](https://www.youtube.com/user/Hak5Darren) +- [History Buffs](https://www.youtube.com/channel/UCggHoXaj8BQHIiPmOxezeWA) +- [Indigo Gaming](https://www.youtube.com/channel/UCTRohxutThBffdcP3H6O0Zg) +- [Jeff Geerling](https://www.youtube.com/user/geerlingguy) +- [Master the Dungeon](https://www.youtube.com/channel/UCrPmuq5_AJ_DvZ9OXQrFEFw) +- [Matthew Colville](https://www.youtube.com/user/mcolville) +- [Oliver Harper's Reviews and Retrospectives](https://www.youtube.com/user/ollyh82) +- [Questing Beast](https://www.youtube.com/c/QuestingBeast) +- [Rhystic Studies](https://www.youtube.com/user/themagicmansam33) +- [RPG Retro Reviews](https://www.youtube.com/user/captcorajus) +- [Seth Skorkowsky](https://www.youtube.com/channel/UCQs8-UJ7IHsrzhQ-OQOYBmg) +- [TheCrafsMan SteadyCraftin](https://www.youtube.com/channel/UCzsjHlc0WRwZYwlinsmtM4w) +- [Techmoan](https://www.youtube.com/user/Techmoan) +- [Tolarian Community College](https://www.youtube.com/c/tolariancommunity) +- [Toy Galaxy](https://www.youtube.com/c/ToyGalaxyTV) +- [Voidstar Labs (Zack Freedman)](https://www.youtube.com/user/ZackFreedman) diff --git a/src/pages/linklists/free_gamedev.md b/src/pages/linklists/free_gamedev.md new file mode 100644 index 0000000..a551401 --- /dev/null +++ b/src/pages/linklists/free_gamedev.md @@ -0,0 +1,30 @@ +--- +title: Free Game Development Resources +sub_title: LinkLists +description: A list of free assets (images and such) that one can use for developing a game. +date_pub: 2014-03-10T20:53:00-05:00 +date_upd: 2022-09-17T00:51:00-04:00 +content_type: feature +section: web +subsection: linklists +--- + +_Compiled 2014-03-10 / Updated 2022-09-17_ + +[As noted elsewhere](/linklists/pd_comics.html), my total inability to draw has often hindered my creative processes, forcing me to rely on overlong text descriptions or poorly-drawn sketches. While researching other possible graphic sources, I came across several sites brimming with resources for game developers like myself, who wish to use CC and PD art to make new games. + +Below are links to some of the sources I've been using, compiled as of March 10, 2014. The links were last verified (and one was updated) on September 17, 2022. + +### Links + +- [Art Assets for Game Developers](http://letsmakegames.org/resources/art-assets-for-game-developers/) - The name says it all. Part of [LetsMakeGames](http://letsmakegames.org/), a Australian non-profit that supports game development. + +- [OpenGameArt.org](https://opengameart.org/) - Also listed on the site above, this site includes free sprites, tiles, sounds, and other useful bits. + +- [Game-icons.net](http://game-icons.net/) - A collection of SVG-based game-related icons that can be used in most any digital (or paper) games. + +- [Ambrosine's Game Creation Resources](http://www.ambrosine.com/resource.php) - A searchable database of game engines and resources, plus lots of info about classic games. + +- [Pixabay](https://pixabay.com/) - A searchable database of over a million public domain images. + +- [Wikimedia Commons](https://commons.wikimedia.org/wiki/Main_Page) - Boasting of 46 million media items, this is the media collecting arm of the Wikimedia Foundation (the keepers of the [Great Oracle of All Knowledge](https://www.wikipedia.org)). diff --git a/src/pages/linklists/index.md b/src/pages/linklists/index.md new file mode 100644 index 0000000..98df499 --- /dev/null +++ b/src/pages/linklists/index.md @@ -0,0 +1,22 @@ +--- +title: LinkLists +description: Lists of recently verified links to to useful resources on the internet. +date_pub: 2015-11-11T14:17:00-05:00 +date_upd: 2022-09-17T01:14:00-04:00 +content_type: feature +section: web +subsection: linklists +--- + +_All Links Last Verified: 2022-09-17_ + +As a self-professed serial enthusiast, I often go on tangents of research about very specific topics. When the topic is somewhat obscure or "retro", I usually find myself wading through pages and pages of search results that go to dead links, inactive sites or, even worse, straight-out bad information. When that happens, I'll often collect a page of the good links, tack a date on the top (indicating when I last checked the links), and file them away as LinkLists. + +Some of the ones I've posted here: + +- [Blogroll](/linklists/blogroll.html) - Blogs I like to read. +- [Free Game Development Resources](/linklists/free_gamedev.html) - A collection of free assets to use while designing games (digital or analog). +- [MUCK Resources](/linklists/muck_stuff.html) - I briefly got into multi-user text gaming, and compiled these links while I was attempting to figure it out. +- [Public Domain Comic Book Resources](/linklists/pd_comics.html) - Recently, I've discovered a treasure-trove of fantastic, completely-free images, hidden in the comic books of the 40s and 50s. +- [Tabletop Role-Playing Game Resources](/linklists/tabletop_rpg.html) - A bunch of great, _free_ resources for starting and running role-playing game campaigns. +- [Web and JavaScript Game Design Tutorials](/linklists/web_game_tuts.html) - Inspired by a request from my nephew, who wished to learn the dark arts of coding. diff --git a/src/pages/linklists/muck_stuff.md b/src/pages/linklists/muck_stuff.md new file mode 100644 index 0000000..34e50be --- /dev/null +++ b/src/pages/linklists/muck_stuff.md @@ -0,0 +1,28 @@ +--- +title: MUCK Resources +sub_title: LinkLists +description: A list of free assets (images and such) that one can use for developing a game. +date_pub: 2011-09-15T21:43:00-04:00 +date_upd: 2021-06-20T19:14:00-04:00 +content_type: feature +section: web +subsection: linklists +--- + +_Compiled 2011-09-15 / Verified 2022-09-17_ + +A good friend and myself worked for a while on building up a MUCK, running Fuzzball 6.0. + +Unfortunately, we were a little late to the party, and it proved difficult to find good actively-maintained online resources. To that end, I created this list of active MUCK-related sites, as of September 15th, 2011. The links were last verified on September 17, 2022. + +I hope it serves someone well. + +_Update 2015-11-11 - Since it's been 4 years since I first wrote this list, I should mention that I actually wound up becoming frustrated with the limitations of the MUCK software, and abandoned it for the much better-documented [LambdaMOO](http://www.moo.mud.org/), before ultimately losing interest in the whole endeavour._ + +### Links + +- [The official Fuzzball site](http://www.fuzzball.org/) - Links to the official repos and docs, presented via a (fake?) telnet session. - _OFFLINE as of 2018-05-20_ + +- [Ginger's MUCK Help Page](http://www.soappuppy.com/muck/) - Scripts, documentation, and other “Useful Stuff”. + +- [The Mink MUCK Manual](http://www.rdwarf.com/users/mink/muckman/toc.html) - Good material, but unfortunately most of the rest of the links on this site aren't good. diff --git a/src/pages/linklists/pd_comics.md b/src/pages/linklists/pd_comics.md new file mode 100644 index 0000000..2917881 --- /dev/null +++ b/src/pages/linklists/pd_comics.md @@ -0,0 +1,30 @@ +--- +title: Public Domain Comic Book Resources +sub_title: LinkLists +description: A list of sites housing scans from a bunch of public domain comic books from the 40s and 50s. +date_pub: 2013-10-13T18:12:00-04:00 +date_upd: 2021-06-20T19:17:00-04:00 +content_type: feature +section: web +subsection: linklists +--- + +_Compiled 2013-10-13 / Verified 2022-09-17_ + +My total inability to draw has often hindered my creative processes, forcing me to rely on overlong text descriptions or poorly-drawn sketches. Recently, I've discovered a treasure-trove of fantastic, completely-free images, hidden in the comic books of the 40s and 50s. + +Below are links to some of the sources I've been using, compiled as of October 13th, 2013. The links were last verified on September 17, 2022. + +### Links + +- [Digital Comic Museum](https://digitalcomicmuseum.com/) - The BEST source I've found for full comic scans (even if they aren't allegedly all public domain). + +- [Public Domain Super Heroes](https://pdsh.wikia.com/wiki/Public_Domain_Super_Heroes) - A wonderful resource for PD / Open Source superhero characters (including some modern ones). + +- [Golden-Age Comic Book Superheroes & Villains Encyclopedia](http://www.herogoggles.com/) - Just what the name says, a large list of comic book heroes and villains from the Golden Age. + +- [Copyrights and Comics of 1940s](http://www.herogoggles.com/copyright1.html) - A great article detailing the results of the author's search for the copyrights and renewals of specific titles from the 1940s. Also does a good job of describing the general process of renewal, pre-1978. + +- [The Online Books Page: Copyright Registration and Renewal Records](http://onlinebooks.library.upenn.edu/cce/index.html) - Links to copyright / renewal info by year for 1891 - 1978. + +- [US Copyright Office](https://www.copyright.gov/records/) - Copyrights and renewals since 1978 (including renewals for items copyright after 1950 or so). diff --git a/src/pages/linklists/tabletop_rpg.md b/src/pages/linklists/tabletop_rpg.md new file mode 100644 index 0000000..c89cf21 --- /dev/null +++ b/src/pages/linklists/tabletop_rpg.md @@ -0,0 +1,26 @@ +--- +title: Tabletop Role-Playing Game Resources +sub_title: LinkLists +description: A list of free rules, tables, and other role-playing game resources. +date_pub: 2022-09-17T00:07:00-04:00 +content_type: feature +section: web +subsection: linklists +--- + +_Compiled 2022-09-16_ + +I've been an RPG enthusiast for 30+ years, and after a long hiatus, I've been lucky enough to spend the past few years playing (and running) regular games. Thanks to the explosion of content from the OSR (a ["play style movement"](https://en.wikipedia.org/wiki/Old_School_Renaissance) inspired by the early days of RPGs), there are a number of great, _free_ resources for starting and running campaigns. + +Below are links to some of the sites I've been using for my own games, compiled as of September 17, 2022. + +### Links + +- [DnD Speak](https://www.dndspeak.com/) - Excellent collection of tools, tables, and lists to inspire your games. +- [Dyson's Dodecahedron](https://dysonlogos.blog/) - Some of the best maps on the interwebs. +- [Fantasy Name Generators](https://www.fantasynamegenerators.com/) - An endless variety of names for all kinds of things. +- [The Frugal GM](https://www.frugalgm.com/) - Tons of free gaming resources. +- [A Knight at the Opera](https://knightattheopera.blogspot.com/) - "OSR Gaming for Tools & Reviews for GMs". +- [Kosmic Dungeon](https://kosmicdungeon.com/) - An excellent collection of free maps. +- [Old-School Essentials System Reference Document](https://oldschoolessentials.necroticgnome.com/srd/) - Like classic D&D, but easier to read, and available for free. +- [tenfootpole.org](https://tenfootpole.org/ironspike/) - Lots and lots of module reviews. diff --git a/src/pages/linklists/web_game_tuts.md b/src/pages/linklists/web_game_tuts.md new file mode 100644 index 0000000..3a18f99 --- /dev/null +++ b/src/pages/linklists/web_game_tuts.md @@ -0,0 +1,40 @@ +--- +title: Web and JavaScript Game Design Tutorials +sub_title: LinkLists +description: A list of sites housing scans from a bunch of public domain comic books, mostly from the 40s and 50s. +date_pub: 2013-10-13T18:12:00-04:00 +date_upd: 2022-09-17T01:21:00-04:00 +content_type: feature +section: web +subsection: linklists +--- + +_Compiled 2012-07-23 / Verified 2022-09-17_ + +The other day (_over a decade ago, as of last update_), my nephew asked me for some advice on learning how to code. Having been a code monkey myself since 3rd grade, I can appreciate the desire to learn coding in general, and game development (his preferred specialty) in particular. + +But, things have change alot in the 25 30+ years since I first learned, and I suspect that learning BASIC on an Apple IIe is no longer the preferred starting method (or even terribly useful). So, after some brief thought, I suggested he learn the art of JavaScript (and the HTML that surrounds it), which I prefer for several reasons: + +1. it's simple (or, at least, can be, with the right libraries), +2. it's powerful, thanks to the modern JS engines in Chrome and Firefox, and +3. it's relevant in this modern, interconnected world. + +So, in order to simplify the transfer of knowledge for him, I present the Web and JavaScript Game Design Tutorials LinkList, as compiled July 23rd, 2012. The links were last verified on September 17, 2022. + +### Links + +- [W3Schools.com](https://www.w3schools.com/) - I've been a fan of this site for years, and found them to be an invaluable resource as I honed my own JavaScript skills. They have basic and advanced tutorials in both [HTML](https://www.w3schools.com/html/) and [JavaScript](https://www.w3schools.com/js/), as well as lots of examples and references. + +- [Tizag](http://www.tizag.com/) - Well I'm not particularly familiar with this site, they look like they have some good from-the-ground-up tutorials on everything from [HTML](http://www.tizag.com/beginnerT/) and [JavaScript](http://www.tizag.com/javascriptT/) to [Perl](http://www.tizag.com/perlT/) and [Flash](http://www.tizag.com/flashTutorial/) (and lots of stuff in between). + +- [Developing HTML5 Canvas Games for Facebook with JavaScript](http://manuel.kiessling.net/2012/04/02/tutorial-developing-html5-canvas-games-for-facebook-with-javascript-part-1/) - A more specific tutorial, written by a developer who wanted to teach his 5-year-old son about video games. Steps through the building of a simple space-shooting game. + +- [Codeacademy](https://www.codecademy.com/) - A relatively new tutorial site, with a social bend. Sign in via Facebook, and earn badges and achievments while you learn. Looks like it might be a great way to learn, as it seems to start right out with an interactive JavaScript command line. + +- [Eloquent JavaScript](https://eloquentjavascript.net/) - A free ((Creative Commons 3.0 Attribution, for those that care about such things.)) ebook designed to be a "modern introduction to programming" by way of the JavaScript language. + +- _The Very Simple Tic-Tac-Toe Tutorial Using HTML5, CSS3, and JavaScript_ (formerly at http://www.dreamincode.net/forums/topic/247361-simple-tic-tac-toe-using-html5-css3-and-javascript/) - The name says it all. A single page tutorial posted to the dreamincode.net forums, covering the step-by-step process of developing a simple game. Link down as of 2022-09-17\_ + +- [HTML5 Games 101 - An introductory tutorial to HTML5 Games](https://www.codeproject.com/Articles/230794/HTML5-Games-101-An-introductory-tutorial-to-HTML5) - Another step-by-step tutorial, this one demonstrating how to build a simple snake game. + +- [MDN - Learn Web Development](https://developer.mozilla.org/en-US/docs/Learn) _(New)_ - The Mozilla Developer's Network is a treasure trove of information, with tutorials and reference material for all levels of developer. diff --git a/src/pages/magic-cards/dnd.md b/src/pages/magic-cards/dnd.md new file mode 100644 index 0000000..14c935f --- /dev/null +++ b/src/pages/magic-cards/dnd.md @@ -0,0 +1,80 @@ +--- +title: D&D-Inspired Custom Magic Cards +description: Custom creature cards, based on various D&D characters I've run (as a player or DM). +date_pub: 2022-08-20T23:56:00-04:00 +content_type: feature +section: games +subsection: magic-cards +--- + +Below you'll find some custom (unoffocial) creature cards I made, based on various D&D characters I've run (as a player or DM). + +As with [my other custom Magic cards](/magic-cards), these were created with the help of the excellent [MTG Cardsmith](https://mtgcardsmith.com/). + +Here's some inspired by my (ever-evolving) character from my Friday night D&D game, Malakyre: + + + +And here's some based on the other party members: + + + +Back to Top diff --git a/src/pages/magic-cards/index.md b/src/pages/magic-cards/index.md new file mode 100644 index 0000000..709df7c --- /dev/null +++ b/src/pages/magic-cards/index.md @@ -0,0 +1,14 @@ +--- +title: Custom Magic Cards +description: Custom Magic cards I've created using MTG Cardsmith +date_pub: 2022-08-21T13:41:00-04:00 +content_type: feature +section: games +subsection: magic-cards +--- + +Below, you'll find links to some of the custom (unofficial) magic cards I created with the help of the excellent [MTG Cardsmith](https://mtgcardsmith.com/). + +- [Planeswalkers](snm-planeswalkers.html) - Based on the goofballs I play with [every week](/magic-decks). +- [D&D](dnd.html) - Creatures based on my (and others') D&D characters +- [Tokens](tokens.html) - Some inspired by [Mythic Wars](https://mythicwarsgame.com/), some based on my favorite movies diff --git a/src/pages/magic-cards/snm-planeswalkers.md b/src/pages/magic-cards/snm-planeswalkers.md new file mode 100644 index 0000000..ab92dfd --- /dev/null +++ b/src/pages/magic-cards/snm-planeswalkers.md @@ -0,0 +1,141 @@ +--- +title: The Custom Planeswalker Cards of Saturday Night Magic +description: Custom planeswalker cards, based on the friends that I play with during our weekly Saturday Night Magic games. +date_pub: 2022-08-21T15:07:00-04:00 +content_type: feature +section: games +subsection: magic-cards +--- + +Inspired by the (now outdated?) notion that [each Magic player is actually a planeswalker](https://magic.wizards.com/en/articles/archive/feature/you-are-planeswalker-2008-07-25), I designed these custom (unofficial) planeswalker cards based on the friends that I play with during our [weekly Saturday Night Magic games](/magic-decks) and their preferred play styles and decks. + +As with [my other custom Magic cards](/magic-cards), these were created with the help of the excellent [MTG Cardsmith](https://mtgcardsmith.com/). + + + +Back to Top + +A couple of years later, I made a second round of these, based on our updated player roster. + + diff --git a/src/pages/magic-cards/tokens.md b/src/pages/magic-cards/tokens.md new file mode 100644 index 0000000..7fcb45a --- /dev/null +++ b/src/pages/magic-cards/tokens.md @@ -0,0 +1,99 @@ +--- +title: Custom Magic Tokens +description: Custom token cards, based on other games and movies +date_pub: 2022-08-21T15:04:00-04:00 +content_type: feature +section: games +subsection: magic-cards +--- + +Enjoy these custom tokens I made, based on other games and movies. + +As with [my other custom Magic cards](/magic-cards), these were created with the help of the excellent [MTG Cardsmith](https://mtgcardsmith.com/). + +This first set uses art from my game, [Mythic Wars](https://mythicwarsgame.com/): + + + +This set was made at the request of a friend for a Demons deck he was building, and was inspired by the movie [Dogma](): + + diff --git a/src/pages/magic-decks/arcades.md b/src/pages/magic-decks/arcades.md new file mode 100644 index 0000000..6d2caec --- /dev/null +++ b/src/pages/magic-decks/arcades.md @@ -0,0 +1,44 @@ +--- +{ + "title": "Defenders of the Mirth (Commander)", + "sub_title": "Magic Decks", + "description": "", + "date_pub": "2020-04-02T00:07:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "magic-decks", + "content_type": "magic-deck", + "deck": { + "info": { + "name": "Defenders of the Mirth", + "format": "Commander", + "based_on": "", + "commander": "Arcades, the Strategist", + "commander_id": 447348, + "starting_lands": [ + "Forest", + "Island", + "Plain" + ], + "date_upd": "2020-04-02" + }, + "cards": [ + ], + "lands" : [ + { + "type": "Forest", + "count": 10 + }, + { + "type": "Island", + "count": 10 + }, + { + "type": "Plain", + "count": 10 + } + ], + "changes" : [] + } +} +--- diff --git a/src/pages/magic-decks/edgar.md b/src/pages/magic-decks/edgar.md new file mode 100644 index 0000000..24b80b6 --- /dev/null +++ b/src/pages/magic-decks/edgar.md @@ -0,0 +1,126 @@ +--- +{ + "title": "Edgar-World (Commander)", + "sub_title": "Magic Decks", + "description": "", + "date_pub": "2018-08-18T13:08:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "magic-decks", + "content_type": "magic-deck", + "deck": + { + "info": + { + "name": "Edgar-World", + "format": "Commander", + "based_on": "Commander 2017 Vampires Deck", + "commander": "Edgar Markov", + "commander_id": 433277, + "commander_img": "edgar-markov.png", + "starting_lands": ["Mountain", "Plains", "Swamp"], + "date_upd": "2018-08-16", + }, + "cards": + [ + "Akoum Refuge", + "Anowon, the Ruin Sage", + "Archetype of Aggression", + "Arvad the Cursed", + "Bishop of Binding", + "Bishop of the Bloodstained", + "Blade of the Bloodchief", + "Blind Obedience", + "Blood Artist", + "Blood Seeker", + "Blood Tribute", + "Bloodfell Caves", + "Bloodline Necromancer", + "Bloodlord of Vaasgoth", + "Bojuka Bog", + "Boros Garrison", + "Boros Guildgate", + "Boros Signet", + "Butcher of Malakir", + "Call to the Feast", + "Canyon Slough", + "Captivating Vampire", + "Cinder Barrens", + "Cliffhaven Vampire", + "Command Tower", + "Consuming Vapors", + "Crackling Doom", + "Cradle of Vitality", + "Dark Imposter", + "Dawn Charm", + "Deset of the True", + "Disrupt Decorum", + "Door of Destinies", + "Drana's Emissary", + "Elenda, the Dusk Rose", + "Endless Sands", + "Evolving Wilds", + "Falkenrath Noble", + "Final Reward", + "Gifted Aetherborn", + "Guul Draz Overseer", + "Indulgent Aristocrat", + "Inspiring Vantage", + "Intimidation", + "Kabira Crossroads", + "Kazarov, Sengir Pureblood", + "Kheru Mind-Eater", + "Kindred Boon", + "Kindred Charge", + "Krovikan Vampire", + "Legion Lieutenant", + "Malakir Bloodwitch", + "Mathas, Fiend Seeker", + "Mavren Fein, Dusk Apostle", + "Merciless Eviction", + "Mortify", + "New Blood", + "Nomad Outpost", + "Opal Palace", + "Orzhov Basilica", + "Orzhov Guildgate", + "Orzhov Signet", + "Orzhova, the Church of Deals", + "Path of Ancestry", + "Patron of the Vein", + "Quag Vampires", + "Radkos Carnarium", + "Radkos Guildgate", + "Radkos Signet", + "Rakish Heir", + "Rootborn Defenses", + "Sanguine Blood", + "Scoured Barrens", + "Sol Ring", + "Soul Collector", + "Sorin, Lord of Innistrad", + "Stensia Masquerade", + "Stone Quarry", + "Stromkirk Captain", + "Tainted Field", + "Teferi's Protection", + "Terramorphic Expanse", + "Tithe Drinker", + "Unmake", + "Urge to Feed", + "Vampire Nighthawk", + "Vizkopa Guildmage", + "Wander in Death", + "Well of Lost Dreams", + "Wind-Scarred Crag", + ], + "lands": + [ + { "type": "Mountain", "count": 3 }, + { "type": "Plains", "count": 3 }, + { "type": "Swamp", "count": 3 }, + ], + "changes": [], + }, +} +--- diff --git a/src/pages/magic-decks/estrid.md b/src/pages/magic-decks/estrid.md new file mode 100644 index 0000000..bcf67bf --- /dev/null +++ b/src/pages/magic-decks/estrid.md @@ -0,0 +1,198 @@ +--- +{ + "title": "Estrid's Masks of Fate", + "sub_title": "Magic Decks", + "description": "", + "date_pub": "2019-02-23T15:44:00-05:00", + "license": "CC0", + "section": "games", + "subsection": "magic-decks", + "content_type": "magic-deck", + "deck": + { + "info": + { + "name": "Estrid's Masks of Fate", + "format": "Commander", + "based_on": "", + "commander": "Estrid, the Masked", + "commander_id": 450641, + "commander_img": "estrid-the-masked.png", + "starting_lands": ["Forest", "island", "Plains"], + }, + "cards": + [ + "Ajani Unyielding", + "Ajani's Chosen", + "Archetype of Imagination", + "Archon of Sun's Grace", + "Azorious Chancery", + "Bant Charm", + "Bear Umbra", + "Blessed Light", + "Blossoming Sands", + "Bronzehide Lion", + "Bruna, Light of Alabaster", + "Captivating Unicorn", + "Celestial Archon", + "Cleansing Nova", + "Clone", + "Command Tower", + "Creeping Renaissance", + "Danitha Capashen, Paragon", + "Dawn's Reflection", + "Dictate of Kruphix", + "Eel Umbra", + "Eidolon of Blossoms", + "Enchantress's Presence", + "Enigmatic Incarnation", + "Epic Proportions", + "Estrid's Invocation", + "Ever-Watching Threshold", + "Evolving Wilds", + "Finest Hour", + "Forge of Heroes", + "Fortified Village", + "Frogify", + "Fumigate", + "Genesis Storm", + "Ground Seal", + "Grove of the Guardian", + "Heavenly Blademaster", + "Herald of the Pantheon", + "Hydra Omnivore", + "Hyena Umbra", + "Inspire Awe", + "Kestia, the Cultivator", + "Krosan Verge", + "Loyal Drake", + "Loyal Unicorn", + "Lumbering Falls", + "Meandering River", + "Mosswort Bridge", + "Nessian Wanderer", + "Nomad Mythmaker", + "Nylea's Colossus", + "Octopus Umbra", + "Overgrowth", + "Phyrexian Rebirth", + "Primal Empathy", + "Reason // Believe", + "Reliquary Tower", + "Righteous Authority", + "Sage's Reverie", + "Seaside Citadel", + "Sejiri Refuge", + "Selesnya Guildgate", + "Selesnya Sanctuary", + "Shoal Kraken", + "Sigarda, Heron's Grace", + "Sigil of the Empty Throne", + "Silent Sentinel", + "Simic Growth Chamber", + "Siona, Captain of the Pyleas", + "Snake Umbra", + "Sol Ring", + "Soul Snare", + "Spider Umbra", + "Terramorphic Expanse", + "Thornwood Falls", + "Three Dreams", + "Tranquil Cove", + "Tranquil Expanse", + "Transcendent Envoy", + "Tuvasa the Sunlit", + "Unquestioned Authority", + "Whitewater Naiads", + "Wild Growth", + "Winds of Rath", + "Woodland Stream", + "Yavimaya Enchantress", + ], + "lands": + [ + { "type": "Forest", "count": 5 }, + { "type": "Island", "count": 4 }, + { "type": "Plains", "count": 4 }, + ], + "changes": + [ + { + "date_upd": "2019-01-19", + "dels": + [ + "Bow of Nylea", + "Elderwood Scion", + "Fleetfeather Cockatrice", + "Ravenous Slime", + "Shapers of Nature", + "Skyship Plunderer", + ], + "adds": + [ + "Blessed Light", + "Cleansing Nova", + "Fumigate", + "Oracle's Vault", + "Reason // Believe", + "Reliquary Tower", + "Spider Umbra", + ], + }, + { + "date_upd": "2020-02-02", + "dels": + [ + "Arixmethes, Slumbering Isle", + "Kiora, the Crashing Wave", + "Loyal Guardian", + "Myth Unbound", + "Oracle's Vault", + ], + "adds": + [ + "Captivating Unicorn", + "Favored of Iroas", + "Frogify", + "Inspire Awe", + "Trancendent Envoy", + ], + }, + { + "date_upd": "2020-03-21", + "dels": ["Kruphix's Insight", "Unflinching Courage"], + "adds": + [ + "Sigarda, Heron's Grace", + "Siona, Captain of the Pyleas", + ], + }, + { + "date_upd": "2020-06-06", + "dels": + [ + "Boon Satyr", + "Daxos of Meletis", + "Favored of Iroas", + "Fertile Ground", + "Prophet of Kruphix", + "Spawning Grounds", + "Vow of Flight", + "Vow of Wildness", + ], + "adds": + [ + "Archon of Sun's Grace", + "Bronzehide Lion", + "Enigmatic Incarnation", + "Hyena Umbra", + "Nessian Wanderer", + "Primal Empathy", + "Shoal Kraken", + "Three Dreams", + ], + }, + ], + }, +} +--- diff --git a/src/pages/magic-decks/hidetsugu.md b/src/pages/magic-decks/hidetsugu.md new file mode 100644 index 0000000..bdb52d6 --- /dev/null +++ b/src/pages/magic-decks/hidetsugu.md @@ -0,0 +1,124 @@ +--- +{ + "title": "Tap-Bomb (Commander)", + "sub_title": "Magic Decks", + "description": "", + "date_pub": "2018-08-18T13:08:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "magic-decks", + "content_type": "magic-deck", + "deck": + { + "info": + { + "name": "Tap-Bomb", + "format": "Commander", + "based_on": "", + "commander": "Heartless Hidetsugu", + "commander_id": 382282, + "commander_img": "heartless-hidetsugu.jpg", + "starting_lands": [{ "type": "Mountain", "count": 3 }], + "date_upd": "2018-07-21", + }, + "cards": + [ + "Akroan Conscriptor", + "Annihilating Fire", + "Arcbond", + "Bloodlust Inciter", + "Bloodsworn Steward", + "Boiling Earth", + "Browbeat", + "Cartouche of Zeal", + "Cathartic Reunion", + "Chain Reaction", + "Chandra, Bold Pyromancer", + "Chandra's Outburst", + "Chandra's Pyrohelix", + "Cobbled Wings", + "Cyclops of Eternal Fury", + "Disintegrate", + "Fated Conflagration", + "Fiery Temper", + "Firedrinker Satyr", + "Flame Lash", + "The Flame of Keld", + "Fleetfeather Sandals", + "Flurry of Horns", + "Geth's Grimoire", + "Ghitu Fire", + "Goblin War Paint", + "Hammer of Ruin", + "Hijack", + "Inner-Flame Acolyte", + "Insolence", + "Kari Zev's Expertise", + "Lava Axe", + "Leyline of Lightning", + "Lightning Greaves", + "Mad Prophet", + "Mana Geyser", + "Obsidian Battle-Axe", + "Outpost Siege", + "Paragon of Fierce Defiance", + "Portent of Betrayal", + "Prophetic Ravings", + "Puncturing Blow", + "Punishing Fire", + "Pyroclasm", + "Reckless Bushwhacker", + "Reroute", + "Sarkhan's Dragonfire", + "Scouring Sands", + "Seething Song", + "Seismic Strike", + "Spitting Earth", + "Shatter", + "Shock", + "Soulbright Flamekin", + "Strider Harness", + "Swashbuckling", + "Sword of Vengeance", + "Talon of Pain", + "Tormenting Voice", + "Traitorous Blood", + "Traitorous Instinct", + "Unnatural Speed", + "Wall of Fire", + "Wild Ricochet", + "Word of Seizing", + "Yamabushi's Flame", + ], + "lands": [{ "type": "Mountain", "count": 33 }], + "changes": + [ + { + "date_upd": "2018-07-21", + "dels": + [ + "Act of Treason", + "Archetype of Aggression", + "Brute Strength", + "Infectious Bloodlust", + "Sulfuric Vortex", + "Tibalt, the Fiend Blooded", + "Trumpet Blast", + "Whispersilk Cloak", + ], + "adds": + [ + "Chandra, Bold Pyromancer", + "Chandra's Outburst", + "The Flame of Keld", + "Kari Zev's Expertise", + "Lightning Greaves", + "Punishing Fire", + "Sarkhan's Dragonfire", + "Mountain", + ], + }, + ], + }, +} +--- diff --git a/src/pages/magic-decks/index.md b/src/pages/magic-decks/index.md new file mode 100644 index 0000000..53b99db --- /dev/null +++ b/src/pages/magic-decks/index.md @@ -0,0 +1,24 @@ +--- +title: Magic Decks +description: +date_pub: 2019-02-23T16:28:00-05:00 +content_type: feature +section: games +subsection: magic-decks +--- +I'm a huge fan of [Magic: the Gathering](https://magic.wizards.com/), personally believing it to be one of the greatest +tabletop games ever designed. I've been playing it for the past 18 years or so, and frequently join my friends in their weekly casual games (which have been running for over a decade). + +Initially, we played regular, 60-card Magic (aka [Legacy format](https://magic.wizards.com/en/game-info/gameplay/formats/legacy)), but have shifted over the last few years to playing EDH (aka [Commander format](https://magic.wizards.com/en/content/commander-format)) fairly exclusively. As I've been rebuilding my decks to work with the new format, I decided to start documenting them (or, at least, the ones that actually win work). + +Click on a deck name below to see its full list of cards. + ++ [Edgar-World](edgar.html) - A red-white-black vampire-tribal deck headed by [Edgar Markov](http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=433277) (because I ♥ Eminence). ++ [Estrid's Masks of Fate](estrid.html) - A green-white-blue deck with a heavy focus on enchantments (especially Totem Armor) commanded by the Planeswalker [Estrid, the Masked](http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=450641). ++ [The Fight of Dragons](ur-dragon.html) - A five-color dragon-tribal deck headed by [The Ur-Dragon](http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=433289) (because I *really* ♥ Eminence). ++ [A Hard Day's Knight](knights.html) - A red-white-black knight-tribal deck with lots of equipment, commanded [by Syr Gwyn, Hero of Ashvale](http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=476048). ++ [Saheeli-Thopters](saheeli.html) - A blue-red deck based around (and commanded by) the Planeswalker [Saheeli, the Gifted](http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=450645). ++ [Slimefoot's Sapsuckers](slimefoot.html) - A black-green deck designed to generate and then sacrifice Saprolings, all to trigger Commander [Slimefoot, the Stoweaway](http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=443093)'s damage-inflicting ability. ++ [Tap-Bomb](hidetsugu.html) - A mono-red deck built solely to enable the ability of its Commander, the tap-bomb himself, [Heartless Hidetsugu](http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=382282). Stupidly evil. ++ [Temmet's Invisi-Tokens](temmet.html) - A white-blue deck full of token-creature-generating spells, just so Commander [Temmet, Vizier of Naktamun](http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=426909) can make them unblockable. ++ [Wrexial Rising](wrexial.html) - My first commander deck, a blue-black horror-themed deck headed by the Cthulhu-esque [Wrexial, the Risen Deep](http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=446907). diff --git a/src/pages/magic-decks/knights.md b/src/pages/magic-decks/knights.md new file mode 100644 index 0000000..0ff923e --- /dev/null +++ b/src/pages/magic-decks/knights.md @@ -0,0 +1,183 @@ +--- +{ + "title": "A Hard Day's Knight", + "sub_title": "Magic Decks", + "description": "", + "date_pub": "2020-06-04T22:17:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "magic-decks", + "content_type": "magic-deck", + "deck": + { + "info": + { + "name": "A Hard Day's Knight", + "format": "Commander", + "based_on": "", + "commander": "Syr Gwyn, Hero of Ashvale", + "commander_id": 476048, + "commander_img": "syr-gwyn-hero-of-ashvale.png", + "starting_lands": ["Mountain", "Plains", "Swamp"], + "date_upd": "2019-02-23", + }, + "cards": + [ + "Acclaimed Contender", + "All That Glitters", + "Angelic Armaments", + "Arcane Signet", + "Aryel, Knight of Windgrace", + "Bloodfell Caves", + "Blood-Cursed Knight", + "Bond of Discipline", + "Bonehoard", + "Boros Guildgate", + "Blinding Powder", + "Command Tower", + "Chariot of Victory", + "Corpse Knight", + "Colossus Hammer", + "Cabal Paladin", + "Daitha Capashen, Paragon", + "Dwarven Mine", + "Evolving Wilds", + "Explorer's Scope", + "Fleetfeather Sandals", + "Fireshrieker", + "Gideon, Martial Paragon", + "Godless Shrine", + "Heirloom Blade", + "Holy Day", + "Hot Soup", + "Icon of Ancestry", + "Idyllic Grange", + "Inspiring Veteran", + "Kinsbaile Cavalier", + "Knight Exemplar", + "Knight of Glory", + "Knight of Infamy", + "Knight of Sursi", + "Knight of the Ebon Legion", + "Knight's Charge", + "Kwende, Pride of Femeref", + "Lena, Slefless Champion", + "Lone Rider // It That Rides as One", + "Loxodon Warhammer", + "Mace of the Valiant", + "Marauding Knight", + "Marshal's Anthem", + "Midnight Reaper", + "Moonsilver Spear", + "Ob Nixilis's Cruelty", + "Odric, Lunarch Marshal", + "Orzhov Guildgate", + "Orzhov Signet", + "Paladin of Atonement", + "Prying Blade", + "Rally the Righteous", + "Rakdos Guildgate", + "Rakdos Locket", + "Response // Resurgence", + "Ring of Valkas", + "Scoured Barrens", + "Scytheclaw", + "Shining Armor", + "Sigil of Valor", + "Silverblade Paladin", + "Silverflame Ritual", + "Silverwing Squadron", + "Single Combat", + "Skyknight Vanguard", + "Smitten Swordmaster", + "Surestrike Trident", + "Sword of Vengeance", + "Syr Konrad, the Grim", + "Temple of Triumph", + "Thalia's Lancers", + "Tiana, Ship's Caretaker", + "Tournament Grounds", + "Umbral Mantle", + "Valiant Knight", + "Whispersilk Cloak", + "Wind-Scarred Crag", + "Worthy Knight", + ], + "lands": + [ + { "type": "Mountain", "count": 6 }, + { "type": "Plains", "count": 6 }, + { "type": "Swamp", "count": 6 }, + ], + "changes": + [ + { + "date_upd": "2019-02-23", + "dels": + [ + "Day of the Dragons", + "Fractured Identity", + "Sram's Expertise", + ], + "adds": + [ + "Azorious Guildgate", + "Vivid Creek", + "Whispersilk Cloak", + ], + }, + { + "date_upd": "2019-01-19", + "dels": + [ + "Control Magic", + "Pentavus", + "Sinuous Striker", + "Urbis Protector", + "Wall of Denial", + "Whirlermaker", + ], + "adds": + [ + "Call of the Cavalry", + "Fractured Identity", + "History of Benalia", + "Raff Capashen, Ship's Mage", + "Resplendent Angel", + "Triumph of Gerrard", + ], + }, + { + "date_upd": "2018-07-28", + "dels": + [ + "Hoofprints of the Stag", + "Jace, Architect of Thought", + "Sigil of Valor", + ], + "adds": + [ + "Niambi, Fathful Healer", + "Tetsuko Umezawa, Fugitive", + "Teferi, Timebender", + ], + }, + { + "date_upd": "2020-04-01", + "dels": ["Desert of the True"], + "adds": ["Prairie Stream"], + }, + { + "date_upd": "2020-06-03", + "dels": ["Daxos of Meletis"], + "adds": ["Scion of Vitu-Ghazi"], + }, + { + "date_upd": "2020-07-02", + "dels": ["Brawler's Plate"], + "adds": ["Blinding Powder"], + }, + ], + }, +} +--- diff --git a/src/pages/magic-decks/saheeli.md b/src/pages/magic-decks/saheeli.md new file mode 100644 index 0000000..3a47d7d --- /dev/null +++ b/src/pages/magic-decks/saheeli.md @@ -0,0 +1,162 @@ +--- +{ + "title": "Saheeli-Thopters (Commander)", + "sub_title": "Magic Decks", + "description": "", + "date_pub": "2018-08-18T13:08:00-04:00", + "date_upd": "2019-02-23T16:29:00-05:00", + "license": "CC0", + "section": "games", + "subsection": "magic-decks", + "content_type": "magic-deck", + "deck": + { + "info": + { + "name": "Saheeli-Thopters", + "format": "Commander", + "based_on": "Commander 2018 Artifacts Deck", + "commander": "Saheeli, the Gifted", + "commander_id": 450645, + "commander_img": "saheeli-the-gifted.png", + "starting_lands": + [{ "type": "Island", "count": 2 }, "Mountain"], + "date_upd": "2019-02-16", + }, + "cards": + [ + "Aether Gale", + "Ancient Stone Idol", + "Animation Module", + "Anticipate", + "The Antiquities War", + "Blasphemous Act", + "Blinkmoth Urn", + "Brudiclad, Telchor Engineer", + "Buried Ruin", + "Cancel", + "Chief Engineer", + "Chief of the Foundry", + "Command Tower", + "Commander's Sphere", + "Contagion Clasp", + "Creepy Doll", + "Daring Archaeologist", + "Darksteel Citadel", + "Darksteel Juggernaut", + "Darksteel Reactor", + "Diamond Mare", + "Duplicant", + "Echo Storm", + "Endless Atlas", + "Etherium Sculptor", + "Forebear's Blade", + "Forge of Heroes", + "Geode Golem", + "Great Furnace", + "Guardians of Koilos", + "Hangarback Walker", + "Hedron Archive", + "Hellkite Igniter", + "Highland Lake", + "Inkwell Leviathan", + "Insidious Will", + "Into the Roil", + "Inventor's Fair", + "Izzet Boilerworks", + "Izzet Guildgate", + "Izzet Signet", + "Karn's Temporal Sundering", + "Loyal Apprentice", + "Loyal Drake", + "Manalith", + "Metallurgic Summonings", + "Mind Stone", + "Mirrorworks", + "Needlebug", + "One with the Machine", + "Padeem, Consul of Innovation", + "Prismatic Lens", + "Prototype Portal", + "Rupture Spire", + "Retrofitter Foundry", + "Reverse Engineer", + "Saheeli's Artistry", + "Saheeli's Directive", + "Sai, Master Thopterist", + "Scuttling Doom Engine", + "Seat of the Synod", + "Sharding Sphinx", + "Shield of the Avatar", + "Sol Ring", + "Soul of New Phyrexia", + "Steel Hellkite", + "Sulfur Falls", + "Suspicious Bookcase", + "Swiftfoot Boots", + "Swiftwater Cliffs", + "Syncopate", + "Tawnos, Urza's Apprentice", + "Tezzeret, Cruel Machinist", + "Tezzeret's Gatebreaker", + "Thopter Assembly", + "Thopter Engineer", + "Thopter Spy Network", + "Treasure Nabber", + "Ugin's Nexus", + "Unstable Obelisk", + "Unwinding Clock", + "Vedalken Humiliator", + "Vedalken Orrery", + "Whirler Rogue", + "Zahid, Djinn of the Lamp", + ], + "lands": + [ + { "type": "Island", "count": 7 }, + { "type": "Mountain", "count": 7 }, + ], + "changes": + [ + { + "date_upd": "2019-02-16", + "dels": ["Relic Runner"], + "adds": ["Sai, Master Thopterist"], + }, + { + "date_upd": "2018-08-25", + "dels": + [ + "Bosh, Iron Golem", + "Magnifying Glass", + "Pilgrim's Eye", + "Rescue", + "Vessel of Endless Rest", + ], + "adds": + [ + "Contagion Clasp", + "Creepy Doll", + "Metallurgic Summonings", + "Needlebug", + "Ugin's Nexus", + ], + }, + { + "date_upd": "2020-03-26", + "dels": ["Jhoira's Familiar"], + "adds": ["Padeem, Consul of Innovation"], + }, + { + "date_upd": "2020-04-01", + "dels": ["Thirst for Knowledge"], + "adds": ["Vedalken Orrery"], + }, + ], + }, +} +--- + +### Notes + +This deck is still quite new, with the official Saheeli deck having just been released in August, 2018. It's my first (and, so far, only) Planeswalker Commander deck, mostly because I don't typically like using mono-colored Commanders, which all of the previous Commander-capable Planeswalkers were. diff --git a/src/pages/magic-decks/slimefoot.md b/src/pages/magic-decks/slimefoot.md new file mode 100644 index 0000000..3226b36 --- /dev/null +++ b/src/pages/magic-decks/slimefoot.md @@ -0,0 +1,122 @@ +--- +{ + "title": "Slimefoot's Sapsuckers (Commander)", + "sub_title": "Magic Decks", + "description": "", + "date_pub": "2018-08-18T13:08:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "magic-decks", + "content_type": "magic-deck", + "deck": + { + "info": + { + "name": "Slimefoot's Sapsuckers", + "format": "Commander", + "based_on": "", + "commander": "Slimefoot, the Stoweaway", + "commander_id": 443093, + "commander_img": "slimefoot-the-stowaway.png", + "starting_lands": + [{ "type": "Forest", "count": 2 }, "Swamp"], + "date_upd": "2018-07-28", + }, + "cards": + [ + "Aid from the Cowl", + "Altar's Reap", + "Archetype of Finality", + "Blood Artist", + "Bolas's Citadel", + "Bonds of Mortality", + "Borderland Ranger", + "Caravan Vigil", + "Commencement of Festivities", + "Corrosive Ooze", + "Death Mutation", + "Doom Blade", + "Doomgape", + "Dreampool Druid", + "Embodiment of Insight", + "Fendeep Summoner", + "Fertile Imagination", + "Fists of Ironwood", + "Fog", + "Fungal Infection", + "Fungal Sprouting", + "Gift of Strength", + "Golgari Cluestone", + "Golgari Germination", + "Golgari Guildgate", + "Golgari Guildmage", + "Golgari Keyrune", + "Golgari Rot Farm", + "Golgari Rotwurm", + "Golgari Signet", + "Greener Pastures", + "Grow from the Ashes", + "Jade Mage", + "Jungle Hollow", + "Korozda Guildmage", + "Lampad of Death's Vigil", + "Lethal Sting", + "Life and Limb", + "Life Goes On", + "Morbid Bloom", + "Mycoloth", + "Nezumi Bone-Reader", + "Night Soil", + "Necrogenesis", + "Overgrown Armasaur", + "Psychotrope Thallid", + "Putrefy", + "Recover", + "Respite", + "Saproling infestation", + "Saproling Symbiosis", + "Scatter the Seeds", + "Search for Tomorrow", + "Skullclamp", + "Spidersilk Armor", + "Spontaneous Generation", + "Sporemound", + "Sporesower Thallid", + "Sporoloth Ancient", + "Svogthos, the Restless Tomb", + "Tainted Wood", + "Thallid Germinator", + "Tragic Slip", + "Traveler's Amulet", + "Tukatongue Thallid", + "Vampire Nighthawk", + "Verdant Embrace", + "Verdant Force", + "Verdeloth the Ancient", + "Vhati il-Dal", + "Vitaspore Thallid", + "Whisper, Blood Liturgist", + "Woebringer Demon", + "Wrap in vigor", + ], + "lands": + [ + { "type": "Forest", "count": 16 }, + { "type": "Swamp", "count": 9 }, + ], + "changes": + [ + { + "date_upd": "2020-04-01", + "dels": ["Deathbloom Thallid"], + "adds": ["Bolas's Citadel"], + }, + { + "date_upd": "2020-05-27", + "dels": ["Ebony Treefolk", "Sylvan Ranger"], + "adds": ["Greener Pastures", "Lampad of Death's Vigil"], + }, + ], + }, +} +--- diff --git a/src/pages/magic-decks/temmet.md b/src/pages/magic-decks/temmet.md new file mode 100644 index 0000000..43a6285 --- /dev/null +++ b/src/pages/magic-decks/temmet.md @@ -0,0 +1,177 @@ +--- +{ + "title": "Temmet's Invisi-Tokens", + "sub_title": "Magic Decks", + "description": "", + "date_pub": "2018-08-18T13:08:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "magic-decks", + "content_type": "magic-deck", + "deck": + { + "info": + { + "name": "Temmet's Invisi-Tokens", + "format": "Commander", + "based_on": "", + "commander": "Temmet, Vizier of Naktamun", + "commander_id": 426909, + "commander_img": "temmet-vizier-of-naktamun.png", + "starting_lands": + [{ "type": "Island", "count": 2 }, "Plains"], + "date_upd": "2018-07-28", + }, + "cards": + [ + "Absorb", + "Anointer Priest", + "Aven Wind Guide", + "Azorius Chancery", + "Azorius Cluestone", + "Azorious Guildgate", + "Back from the Brink", + "Baral, Chief of Compliance", + "Bonehoard", + "Cackling Counterpart", + "Call of the Cavalry", + "Cellar Door", + "Claustrophobia", + "Clone Legion", + "Crush of Tentacles", + "Dance of Many", + "Decree of Justice", + "Desolation Twin", + "Enlightened Maniac", + "Fated Infatuation", + "Feudkiller's Verdict", + "Fieldmist Borderpost", + "Flood Plain", + "Followed Footsteps", + "Griffin Guide", + "Grip of Phyresis", + "Halimar Depths", + "Havengul Runebinder", + "Healer of the Pride", + "Hero's Blade", + "History of Benalia", + "Hour of Eternity", + "Hour of Need", + "Increasing Devotion", + "Intangible Virtue", + "Meandering River", + "Moonsilver Spear", + "New Benalia", + "Niambi, Fathful Healer", + "Open into wonder", + "Overrule", + "Phantom General", + "Phyrexian Rebirth", + "Prairie Stream", + "Raff Capashen, Ship's Mage", + "Rakshasa's Disdain", + "Reefworm", + "Relic Seeker", + "Resplendent Angel", + "Ring of Thune", + "Rootborn Defenses", + "Saheeli's Artistry", + "Scion of Vitu-Ghazi", + "Sejiri Refuge", + "Skinwing", + "Soaring Seacliff", + "Spell Burst", + "Star Compass", + "Steadfast Sentinel", + "Stolen Identity", + "Sunscourge Champion", + "Supplant Form", + "Teferi, Timebender", + "Tempt with Reflections", + "Tenacity", + "Terramorphic Expanse", + "Tetsuko Umezawa, Fugitive", + "Tranquil Cove", + "Triumph of Gerrard", + "Trostani's Judgment", + "Ur-Golem's Eye", + "Venser, the Sojourner", + "Vivid Creek", + "Vizier of Many Face", + "Wake the Reflections", + "Wanderer's Twig", + "Whispersilk Cloak", + "Wonder", + ], + "lands": + [ + { "type": "Island", "count": 11 }, + { "type": "Plains", "count": 10 }, + ], + "changes": + [ + { + "date_upd": "2019-02-23", + "dels": + [ + "Day of the Dragons", + "Fractured Identity", + "Sram's Expertise", + ], + "adds": + [ + "Azorious Guildgate", + "Vivid Creek", + "Whispersilk Cloak", + ], + }, + { + "date_upd": "2019-01-19", + "dels": + [ + "Control Magic", + "Pentavus", + "Sinuous Striker", + "Urbis Protector", + "Wall of Denial", + "Whirlermaker", + ], + "adds": + [ + "Call of the Cavalry", + "Fractured Identity", + "History of Benalia", + "Raff Capashen, Ship's Mage", + "Resplendent Angel", + "Triumph of Gerrard", + ], + }, + { + "date_upd": "2018-07-28", + "dels": + [ + "Hoofprints of the Stag", + "Jace, Architect of Thought", + "Sigil of Valor", + ], + "adds": + [ + "Niambi, Fathful Healer", + "Tetsuko Umezawa, Fugitive", + "Teferi, Timebender", + ], + }, + { + "date_upd": "2020-04-01", + "dels": ["Desert of the True"], + "adds": ["Prairie Stream"], + }, + { + "date_upd": "2020-06-03", + "dels": ["Daxos of Meletis"], + "adds": ["Scion of Vitu-Ghazi"], + }, + ], + }, +} +--- diff --git a/src/pages/magic-decks/ur-dragon.md b/src/pages/magic-decks/ur-dragon.md new file mode 100644 index 0000000..dfd59e9 --- /dev/null +++ b/src/pages/magic-decks/ur-dragon.md @@ -0,0 +1,147 @@ +--- +{ + "title": "The Fight of Dragons (Commander)", + "sub_title": "Magic Decks", + "description": "", + "date_pub": "2018-08-18T13:08:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "magic-decks", + "content_type": "magic-deck", + "deck": + { + "info": + { + "name": "The Fight of Dragons", + "format": "Commander", + "based_on": "Commander 2017 Dragons Deck", + "commander": "The Ur-Dragon", + "commander_id": 433289, + "commander_img": "ur-dragon.png", + "starting_lands": ["Island", "Mountain", "Plains"], + "date_upd": "2018-07-21", + }, + "cards": + [ + "Arcane Sanctum", + "Armillary Sphere", + "Atarka, World Renderer", + "Bladewing, the Risen", + "Bogardan Hellkite", + "Boneyard Scourge", + "Broodmate Dragon", + "Command Tower", + "Commander's Sphere", + "Crosis, the Purger", + "Crucible of Fire", + "Crucible of the Spirit Dragon", + "Crumbling Necropolis", + "Crux of Fate", + "Deathbringer Regent", + "Darigaaz Reincarnated", + "Darksteel Ingot", + "Dragon Tempest", + "Dragonlord's Servant", + "Dragon's Claw", + "Dragonspeaker Shaman", + "Dreamstone Hedron", + "Dromoka, the Eternal", + "Earthquake", + "Eerie Ultimatum", + "Elemental Bond", + "Evolving Wilds", + "Farseek", + "Fist of Suns", + "Frontier Bivouac", + "Frontier Siege", + "Gilded Lotus", + "Haven of the Spirit Dragon", + "Hellkite Charger", + "Herald's Horn", + "Intet, the Dreamer", + "Jungle Shrine", + "Kessig Wolf Run", + "Kilnmouth Dragon", + "Kindred Discovery", + "Kolaghan, the Storm's Fury", + "Mirror of the Forebears", + "Monastery Siege", + "Mordant Dragons", + "Mystic Monastery", + "Niv-Mizzet, Dracogenius", + "Nomad Outpost", + "Ojutai, Soul of Winter", + "Opulent Palace", + "Palace Siege", + "Path of Ancestry", + "Pristine Skywise", + "Rain of Thorns", + "Ramos, Dragon Engine", + "Ryusei, the Falling Star", + "Sandsteppe Citadel", + "Sarkhan, Dragonsoul", + "Savage Lands", + "Savage Ventmaw", + "Scalelord Reckoner", + "Scion of the Ur-Dragon", + "Scourge of Valkas", + "Seaside Citadel", + "Shivan Hellkite", + "Silumgar, the Drifting Death", + "Sol Ring", + "Spellbound Dragon", + "Spinerock Knoll", + "Steel Hellkite", + "Stormwing Dragon", + "Sunscorch Regent", + "Talgam, Ojutai Master", + "Tek", + "Teneb, the Harvester", + "Territorial Hellkite", + "Tyrant's Familiar", + "Utvara Hellkite", + "Vivid Crag", + "Wasitora, Nekoru Queen", + "Wayfarer's Bauble", + "Whispersilk Cloak", + ], + "lands": + [ + { "type": "Forest", "count": 3 }, + { "type": "Island", "count": 3 }, + { "type": "Mountain", "count": 6 }, + { "type": "Plains", "count": 3 }, + { "type": "Swamp", "count": 3 }, + ], + "changes": + [ + { + "date_upd": "2018-07-21", + "dels": + [ + "Curse of Bounty", + "Lightning Greaves", + "Painful Truths", + "Punishing Fire", + ], + "adds": + [ + "Darigaaz Reincarnated", + "Gilded Lotus", + "Kamahl's Druidic Vow", + "Sarkhan, Dragonsoul", + ], + }, + { + "date_upd": "2018-07-21", + "dels": + [ + "Kamahl's Druidic Vow", + "O-Kagachi, Vengeful Kami", + ], + "adds": ["Eerie Ultimatum", "Tek"], + }, + ], + }, +} +--- diff --git a/src/pages/magic-decks/wrexial.md b/src/pages/magic-decks/wrexial.md new file mode 100644 index 0000000..433aeb6 --- /dev/null +++ b/src/pages/magic-decks/wrexial.md @@ -0,0 +1,130 @@ +--- +{ + "title": "Wrexial Rising (Commander)", + "sub_title": "Magic Decks", + "description": "", + "date_pub": "2018-08-18T13:09:00-04:00", + "license": "CC0", + "section": "games", + "subsection": "magic-decks", + "content_type": "magic-deck", + "deck": + { + "info": + { + "name": "Wrexial Rising", + "format": "Commander", + "commander": "Wrexial, the Risen Deep", + "commander_id": 446907, + "commander_img": "wrexial-the-risen-deep.png", + "starting_lands": + [{ "type": "Island", "count": 2 }, "Swamp"], + "date_upd": "2018-07-21", + }, + "cards": + [ + "Arcane Melee", + "Bident of Thassa", + "Black Market", + "Blanket of Night", + "Body Double", + "Bonehoard", + "Butcher of Malakir", + "Butcher's Glee", + "Chimeric Egg", + "Clone", + "Consuming Aberration", + "Contagion Clasp", + "Crypt Angel", + "Darksteel Citadel", + "Deep-Sea Kraken", + "Dimir Guildgate", + "Disallow", + "Dismal Backwater", + "Disruptor Pitmage", + "Djinn of Wishes", + "Dreadship Reef", + "Dreamborn Muse", + "Drifting Shade", + "Footbottom Feast", + "Gyruda, Doom of Depths", + "Halimar Depths", + "Hidden Strings", + "Indulgent Tormentor", + "Infiltrator il-Kor", + "Jace's Mindseeker", + "Kraken's Eye", + "Marauding Knight", + "Mephitic Ooze", + "Mind Control", + "Mindwrack Demon", + "Mirko Vosk, Mind Drinker", + "Monastery Siege", + "Mortuary Mine", + "Negate", + "Nightmare", + "Nihilith", + "Paranoid Delusions", + "Phyrexian Infiltrator", + "Pilfered Plans", + "Possessed Skaab", + "Power Sink", + "Profane Command", + "Psychic Intrusion", + "Rapid Hybridization", + "Rona, Disciple of Gix", + "Salt Marsh", + "Scourge of Fleets", + "Scuttling Doom Engine", + "Skinwing", + "Soul Seizer // Ghastly Haunting", + "Spectral Flight", + "Strandwalker", + "Stuffy Doll", + "Szadek, Lord of Secrets", + "Triton Shorestalker", + "Uninvited Geist // Unimpeded Trespasser", + "Vault of Whispers", + "Vedalken Orrery", + "Viscerid Deepwalker", + "Viscid Lemures", + "Vraska, Scheming Gorgon", + "Vraska's Scorn", + "Westvale Abbey", + ], + "lands": + [ + { "type": "Island", "count": 19 }, + { "type": "Swamp", "count": 12 }, + ], + "changes": + [ + { + "date_upd": "2018-07-21", + "dels": ["Last Thoughts", "Mahamoti Djinn"], + "adds": ["Djinn of Wishes", "Rona, Disciple of Gix"], + }, + { + "date_upd": "2020-03-26", + "dels": ["Clockspinning"], + "adds": ["Blanket of Night"], + }, + { + "date_upd": "2020-06-05", + "dels": + [ + "Evolving Wilds", + "Plea for Power", + "Servant of Tymaret", + ], + "adds": + [ + "Gyruda, Doom of Depths", + "Paranoid Delusions", + "Szadek, Lord of Secrets", + ], + }, + ], + }, +} +--- diff --git a/src/pages/now.md b/src/pages/now.md new file mode 100644 index 0000000..8328289 --- /dev/null +++ b/src/pages/now.md @@ -0,0 +1,16 @@ +--- +title: Now +description: A short list of the things that I'm (probably) working on right now. +date_pub: 2021-06-21T23:15:00-04:00 +date_upd: 2022-07-21T00:52:00-04:00 +section: main +content_type: feature +short_code: mn +--- + +Between the hours of roughly 9AM and 12AM (`America/New_York` time, give or take an hour or two), you'll most likely find me working on any or all of the following: + +- work stuff, +- this website, +- some crazy side project (probably involving a game and/or a Raspberry Pi), or +- my Monday night [Old School Essentials](https://necroticgnome.com/collections/old-school-essentials) campaign. diff --git a/src/pages/projects.md b/src/pages/projects.md new file mode 100644 index 0000000..faebc26 --- /dev/null +++ b/src/pages/projects.md @@ -0,0 +1,19 @@ +--- +{ + "title": "Projects", + "description": "Some of Eric's projects.", + "date_pub": "2015-11-26T23:44:00-05:00", + "date_upd": "2018-11-04T00:08:00-04:00", + "section": "projects", + "content_type": "feature", + "short_code": "mp" +} +--- +As of the update on August 18, 2018, this page is no longer linked from anywhere, and has been deprecated. + +However, since [cool URLs don't change](https://www.w3.org/Provider/Style/URI.html), this page has been left up, with links to the pages that replaced it. + +You're welcome. &x1F607; + ++ [Games](games.html) - A small collection of my gaming-related projects. ++ [Web](web.html) - My attempts at [developing the web](https://blog.itsericwoodward.com/2015/developing-the-web). diff --git a/src/pages/web.md b/src/pages/web.md new file mode 100644 index 0000000..6f51e21 --- /dev/null +++ b/src/pages/web.md @@ -0,0 +1,23 @@ +--- +{ + "title": "Web Stuff", + "description": "Some of Eric's web-related projects.", + "date_pub": "2018-08-18T17:50:00-04:00", + "date_upd": "2022-07-21T00:57:00-04:00", + "section": "web", + "content_type": "feature", + "short_code": "mw" +} +--- +The web is, IMHO, the most revolutionary invention in information sharing since [Gutenberg's](https://www.gutenberg.org/) printing press. As such, I spend an inordinate amount of time thinking about the web, and I do what I can to help [develop it](https://blog.itsericwoodward.com/2015/developing-the-web). + +### Here + ++ [LinkLists](/linklists) - Lists of links (natch) to various web sites, resources, and/or [blogs](/linklists/blogroll.html), typically organized around a particular subject. Like bookmarking, but not. Updated (occasionally). + +### Elsewhere + ++ [Mythic Wars](https://mythicwarsgame.com/) - The site for my tabletop card-and-dice game, where the gods and goddesses themselves battle for ultimate supremacy! Features a free print-and-play demo, lots of free wallpapers, and the comprehensive rules, among other things. ++ [The Codex Mythica](https://codex.mythicwarsgame.com/) - An [open-source](https:/git.itsericwoodward.com/eric/codex-mythica/) web application I wrote which functions as a card database for Mythic Wars. ++ [My Blog](https://blog.itsericwoodward.com) - A retired instance of the [Known blogging software](https://withknown.com/) where I used to collect my various day-to-day musings. ++ [My Code Repos](https://git.itsericwoodward.com/) - A private [Gitea](https://gitea.io/) instance hosting some of my Git repositories. diff --git a/src/sitePosts/journal/2015/03-18-developing-the-web.md b/src/sitePosts/journal/2015/03-18-developing-the-web.md new file mode 100644 index 0000000..ba7a8e6 --- /dev/null +++ b/src/sitePosts/journal/2015/03-18-developing-the-web.md @@ -0,0 +1,26 @@ +--- +title: Developing the Web +date_pub: 2015-03-18T00:00:00-04:00 +date_upd: 2018-12-01T14:39:00-05:00 +description: A "Web Developer" should "develop the web" by building their projects in accordance with their own vision of how the web should be. For me, that means using open source software to build standards-compliant, accessible, and secure sites and apps. +content_type: journal +tags: code internet js web WebDev +--- + +The great Remy Sharp ([@rem](https://twitter.com/rem)) wrote a [piece](https://remysharp.com/2015/02/26/i-am-web-developer) about what it means to be a web developer, as opposed to an engineer, and the difference a title does (or doesn't) make. In the end, he settles on the title of "web developer": + +> I don't know why I thought it was uncool to be a "web developer". Perhaps because it's utterly vague. +> +> What "web developer" does mean to me though, is this: +> +> Someone who writes code for browsers. Likely from the school of view source, is comfortable with drop-in libraries, understands standards and best practice techniques. But mostly, a tinkerer. + +I like his definition (especially the part about tinkering), but I think that it's incomplete, being merely functional. + +I suggest that the term "web developer", by its definition, carries a philosophical imperative: to **develop** the **web**. That is to say, a web developer should visualize how they would like the web to be (as a whole), and build their own projects in a way that reflects that vision. + +This is something I've tried to do myself, both in my professional and personal projects (albeit with varying degrees of success). To me, being a web developer means that I should use [responsive design principles](https://en.wikipedia.org/wiki/Responsive_web_design), [ensure accessibility](http://www.w3.org/WAI/intro/aria), and [follow the standards](http://www.w3.org/TR/pointerevents/) wherever possible. It also means using only open source software, be it [in the server stack](https://en.wikipedia.org/wiki/LAMP_%28software_bundle%29), the [service layer](http://philecms.com/), or even as a [client browser](https://www.mozilla.org/en-US/firefox/). + +As a web developer, I want to participate in a decentralized web, and would rather use a self-hosted, fully-open [social media platform](http://withknown.com) than a corporate data silo. Likewise, I support the use of standards-based communication protocols (IRC, e-mail, etc.) over proprietary solutions. Finally, as a web developer, I believe in a more secure web, and support initiatives like [HTTPS everywhere](https://www.eff.org/https-everywhere). + +All in all, I think this definition adds an air of legitimacy to the "web developer" title. As I noted in a [comment](https://remysharp.com/2015/02/26/i-am-web-developer#comment-1876942490): based on this criteria, one could say that Sir Tim Berners-Lee is the definitive Web Developer (a title he himself uses, as Remy pointed out), and that's not bad company to be in. In fact, I think I'm going to go get some business cards with "Web Developer" on them. diff --git a/src/sitePosts/journal/2015/04-22-the-people-vs-john-deere.md b/src/sitePosts/journal/2015/04-22-the-people-vs-john-deere.md new file mode 100644 index 0000000..f2e28e3 --- /dev/null +++ b/src/sitePosts/journal/2015/04-22-the-people-vs-john-deere.md @@ -0,0 +1,18 @@ +--- +title: The People vs. John Deere +date_pub: 2015-04-22T00:00:00-04:00 +date_upd: 2018-12-01T14:39:00-05:00 +description: John Deere argues that farmers don't own their tractors, and this does not bode well for our IoT future. +content_type: journal +tags: code hacking politics privacy +--- + +Over at Wired, [iFixit's](https://www.ifixit.com/) Kyle Wiens ([@kwiens](https://twitter.com/kwiens)) points out that #DMCA abuse extends well beyond preventing you from [jailbreaking your PS3](http://arstechnica.com/gaming/2015/04/us-government-takes-on-legal-fight-over-console-jailbreaking-once-more/) and into the world of... [farm machinery](http://www.wired.com/2015/04/dmca-ownership-john-deere/)? + +> In a particularly spectacular display of corporate delusion, John Deereβ€”the world’s largest agricultural machinery maker β€”told the Copyright Office that farmers don’t own their tractors. Because computer code snakes through the DNA of modern tractors, farmers receive β€œan implied license for the life of the vehicle to operate the vehicle.” +> +> It’s John Deere’s tractor, folks. You’re just driving it. + +I find this particularly worrisome with regards to the #InternetOfThings, and the possibility of forced vendor lock-in on even the most trivial of items ("I'm sorry, sir, you'll have to call a certified Moen plumber to fix your leak.") + +Welcome to the future. [Fight to make it better.](http://www.digitalrighttorepair.org/) diff --git a/src/sitePosts/journal/2015/05-04-ethics-in-shilling-videogames.md b/src/sitePosts/journal/2015/05-04-ethics-in-shilling-videogames.md new file mode 100644 index 0000000..9f51405 --- /dev/null +++ b/src/sitePosts/journal/2015/05-04-ethics-in-shilling-videogames.md @@ -0,0 +1,23 @@ +--- +title: Ethics in Shilling Videogames +content_type: journal +date_pub: 2015-05-04T00:00:00-04:00 +date_upd: 2018-11-04T14:37:00-05:00 +tags: games internet politics +--- + +[David Wolinsky](https://twitter.com/davidwolinsky) has a [great article](http://www.unwinnable.com/2015/05/11/actually-its-about-ethics-in-shilling-videogames/#.VVR9luRXbrc) on [Unwinnable](http://www.unwinnable.com) capturing his thoughts on the whole "ethics in game journalism" / #GamerGate thing. + +> It’s time we retire the term β€œvideogame journalist.” +> +> Most writers in the field need to accept that they, too, are marketers unless their approach or something else in the landscape shifts and changes. + +Part of the problem, as he sees it, is that videogame companies aren't driven to do PR with journalists that might give them serious criticism (a.k.a. bad reviews). As a result, traditional "videogame journalists" have to choose between being a PR puppet for the game companies, or not being at all. + +Part of the reason for this all-or-nothing attitude are the YouTube streamers, whose undeniable popularity means that they are getting courted more and more often by the game companies in lieu of print / online journalists. For example, look at [Pewdiepie](https://www.youtube.com/user/PewDiePie), and his 36-million followers: + +> Thirty-six million subscribers means roughly anything he puts online is more popular than Nirvana’s Nevermind (somewhere around 30 million sales) or Michael Jackson’s Bad (also around 30 million). +> +> Think about it. An audience that size, bigger than the population of Canada (a country), and they are all paying attention to one person’s opinions about videogames. That is staggering on a basic human level. + +He hits on a lot of different notes, and it does tend to run long, but it's an overall great read for anyone that wants to move beyond the black-and-white #GamerGate in-group / out-group fighting and into a serious discussion about marketing vs. journalism, and what ethics in gaming can (and should) be. diff --git a/src/sitePosts/journal/2015/05-22-the-web-is-dead.md b/src/sitePosts/journal/2015/05-22-the-web-is-dead.md new file mode 100644 index 0000000..b4589a6 --- /dev/null +++ b/src/sitePosts/journal/2015/05-22-the-web-is-dead.md @@ -0,0 +1,46 @@ +--- +title: The Web is Dead! Long Live the Web! +date_pub: 2015-05-22T00:00:00-04:00 +date_upd: 2018-11-04T14:40:00-05:00 +content_type: journal +tags: code web WebDev +--- + +In browsing through some of the fallout from the arrival of [Facebook's Instant Articles](http://instantarticles.fb.com/), I stumbled across a couple of great pieces by Baldur Bjarnason ([@fakebaldur](https://twitter.com/fakebaldur)) that go a long way to explain how we got into [the situation we're in](http://www.newser.com/story/206784/facebook-instant-articles-a-tectonic-shift-in-news.html), and why it's us [web developers](http://blog.itsericwoodward.com/2015/developing-the-web) who are responsible. + +In the first, he takes on [the ongoing debate about apps vs. the web](https://www.baldurbjarnason.com/notes/media-websites-vs-facebook/), and makes the assertion that it isn't "the web" that's broken, it's how (we) web developers are using it that's broken (emphasis his): + +> Here’s an absolute fact that all of these reporters, columnists, and media pundits need to get into their heads: +> +> The web doesn’t suck. Your websites suck. +> +> _All of your websites suck._ +> +> You destroy basic usability by hijacking the scrollbar. You take native functionality (scrolling, selection, links, loading) that is fast and efficient and you rewrite it with β€˜cutting edge’ javascript toolkits and frameworks so that it is slow and buggy and broken. You balloon your websites with megabytes of cruft. You ignore best practices. You take something that works and is complementary to your business and turn it into a liability. +> +> The lousy performance of your websites becomes a defensive moat around Facebook. + +In other words, if the [mobile web is dead](http://www.zdnet.com/article/the-mobile-web-is-dead-long-live-the-app/), it's because we developers killed it. + +On a side note, I wonder if this isn't alot of the reason that millennials have increasingly [preferred using apps to browsers](https://www.siliconrepublic.com/play/2010/11/24/mobile-ads-shock-millennials-prefer-apps-gen-x-browsers) - because mobile browsing is, for many, a needlessly painful experience. + +In the [second piece](https://www.baldurbjarnason.com/notes/new-age-of-html/), he even goes so far as to explain why people can't seem to get on the same page about how "the web" should be: Because they're all talking about different versions of it: + +> Instead of viewing the web as a single platform, it’s more productive to consider it to be a group of competing platforms with competing needs. The mix is becoming messy. +> +> 1. Services (e.g. forms and ecommerce, requires accessibility, reach, and security) +> 2. Web Publishing (requires typography, responsive design, and reach) +> 3. Media (requires rich design, involved interactivity, and DRM) +> 4. Apps (requires modularity in design, code, and data as well as heavy OS integration) + +Just to drive this point home, he makes reference to the Apple Pointer issue from [earlier this year](http://studiotendra.com/2015/03/01/the-web-has-covered-the-basics): + +> This is just one facet of the core problem with the web as an application platform: we will never have a unified web app platform. +> +> What Apple, Google, Microsoft, and Mozilla want from web applications is simply too divergent for them to settle on one unified platform. That’s the reason why we’re always going to get Google apps that only work in Chrome, Apple Touch APIs that are modelled on iOS’s native touch model, and Microsoft Pointer APIs that reflect their need to support both touch and mouse events on a single device at the same time. There really isn’t an easy way to solve this because standardisation hinges on a common set of needs and use cases which these organisations just don’t share. + +A more conspiracy-minded individual might even believe most of the major vendors would be better off if the standards never really do work out, since it would prevent "native-esque" web apps from cutting into their bottom-lines in their respective app stores. But I digress. + +Speaking for myself, I know that I had never really considered this point when talking / ranting about "the web". What's more, I wonder if half of our inability to come to agreement on some of these issues is simply a matter of terminology getting in the way of having meaningful conversations. I mean, apps aren't "better" than "the web", because they are essentially part of (one form of) it: they use the same web protocols (HTTP / HTML) as the rest of the "browsable" web, they just use them on the back-end before glossing it over with a pretty "native" front end. + +In fact, one might argue that this is the reason that the one area of web standards that has actually seen some progress in the past few months is the [HTTP2 spec](https://http2.github.io/) - an update to how data is transmitted on-the-wire, which should bring notable speed and security improvements to anyone that uses HTTP (including all of those native apps I mentioned earlier). After all, improving this part of "the web" is the one thing that all of the players involved can agree on. diff --git a/src/sitePosts/journal/2015/06-03-an-act-of-freedom.md b/src/sitePosts/journal/2015/06-03-an-act-of-freedom.md new file mode 100644 index 0000000..3597ae2 --- /dev/null +++ b/src/sitePosts/journal/2015/06-03-an-act-of-freedom.md @@ -0,0 +1,27 @@ +--- +title: An Act of Freedom, But For Whom? +date_pub: 2015-06-03T00:00:00-04:00 +date_upd: 2018-11-04T14:43:00-05:00 +content_type: journal +tags: politics privacy surveillance +--- + +On this most auspicious day, when the [USA FREEDOM Act](https://en.wikipedia.org/wiki/USA_Freedom_Act) passed through the Senate on it's way to president's desk, I spent the afternoon listening to some of law professors [Eben Moglen's](https://en.wikipedia.org/wiki/Eben_Moglen) excellent talks about [Snowden and the Future](http://snowdenandthefuture.info/index.html). + +One of the things that I noticed he mentioned, which I don't recall hearing anywhere else, is our (the US citizenry) continued complacency about spying, as long as they aren't spying on Americans. + +> Military control ensured absolute command deference with respect to the fundamental principle which made it all "all right," which was: "No Listening Here." The boundary between home and away was the boundary between absolutely permissible and absolutely impermissibleβ€”between the world in which those whose job it is to kill people and break things instead stole signals and broke codes, and the constitutional system of ordered liberty. + +Of course, we all know how that turned out: + +> Not only had circumstances destroyed the simplicity of "no listening inside," not only had fudging with the Foreign Intelligence Surveillance Act carried them into the land where law no longer provided them with useful landmarks, but they wanted to do itβ€”let's be frank, they wanted to do it. Their view of the nature of human power was Augustan if not august. They wanted what it is forbidden to wise people to take unto themselves. And so they fell, and we fell with them. + +Nearly every time that the USA PATRIOT Act is demonized in the press (even the leftist press), it seems to only be because the NSA dared to spy on _us_. But, shouldn't we be questioning why they have to have such a large net at all, irrespective of the national boundaries? + +Or, as professor Moglen so succinctly put it (emphasis mine): + +> The empire of the United States, the one that secured itself by listening to everything, was the empire of exported liberty. What we had to offer all around the world was freedomβ€”after colonization, after European theft, after the forms of twentieth-century horror we haven't even talked about yetβ€”we offered liberty; we offered freedom. +> ... +> It is, of course, utterly inconsistent with the American ideal to attempt to fasten the procedures of totalitarianism on American constitutional self-governance... Partly, as I shall suggest next time, because freedom is merely privilege extended unless enjoyed by one and all. But primarily because _there is an even deeper inconsistency between American ideals and the subjection of every other society on earth to the procedures of totalitarianism_. + +Something to think about the next time someone talks about "freedom". diff --git a/src/sitePosts/journal/2015/06-18-the-art-of-authorship.md b/src/sitePosts/journal/2015/06-18-the-art-of-authorship.md new file mode 100644 index 0000000..2658cf8 --- /dev/null +++ b/src/sitePosts/journal/2015/06-18-the-art-of-authorship.md @@ -0,0 +1,13 @@ +--- +title: The Art of Authorship and Appropriation +date_pub: 2015-06-18T00:00:00-04:00 +date_upd: 2018-11-04T14:49:00-05:00 +content_type: journal +tags: art copyright web +--- + +Christopher Sprigman [takes another look](http://www.bloomberg.com/news/articles/2015-06-17/richard-prince-instagram-and-authorship-in-a-digital-world) at Richard Prince's Instagram Exhibit, and makes some bold conclusions: + +> Prince’s body of appropriation art is provoking a reassessment of the meaning of authorship at a time when ownership of creative works in our digital world is tenuous. Anyone with access to the Internet can take something made by others, copy it, change it, and distribute it at the click of a mouse. In this context, we can see that authorship is not a stable concept, but rather that it shifts as technology weakens the link between an β€œoriginator” and his work. You may like that or hate that; Prince is pointing it out, in the direct way that only art can. + +As a would-be artist whose done some "appropriation art" myself (as well as a longtime fan of perpetual copyright-trolls, [Negativland](http://negativland.com)), I find this whole discussion fascinating. However, I have to admit that I'm more than a bit surprised at the sums he's been able to get for his "re"-work, and the implication that one man's copyright infringement is another man's high-brow art. diff --git a/src/sitePosts/journal/2015/06-30-two-hard-things.md b/src/sitePosts/journal/2015/06-30-two-hard-things.md new file mode 100644 index 0000000..083361e --- /dev/null +++ b/src/sitePosts/journal/2015/06-30-two-hard-things.md @@ -0,0 +1,19 @@ +--- +title: Two Hard Things +date_pub: 2015-06-30T00:00:00-04:00 +date_upd: 2018-11-04T14:51:00-05:00 +content_type: journal +tags: code computers humor +--- + +Came across this little ditty today, via [Martin Fowler](http://martinfowler.com/bliki/TwoHardThings.html): + +> There are only two hard things in Computer Science: cache invalidation and naming things. +> +> -- Phil Karlton + +Personally, though, I prefer the corollary: + +> There are only two hard things in Computer Science: cache invalidation, naming things, and off-by-one errors. + +Too true. diff --git a/src/sitePosts/journal/2015/07-10-smartphone-cryptogeddon.md b/src/sitePosts/journal/2015/07-10-smartphone-cryptogeddon.md new file mode 100644 index 0000000..9a43af9 --- /dev/null +++ b/src/sitePosts/journal/2015/07-10-smartphone-cryptogeddon.md @@ -0,0 +1,23 @@ +--- +title: Smartphone Cryptogeddon +date_pub: 2015-07-10T00:00:00-04:00 +date_upd: 2018-11-04T14:57:00-05:00 +content_type: journal +tags: code fear internet politics privacy +--- + +After yesterday's Senate committee hearing on encryption, wherein both [FBI Director James Comey](http://arstechnica.com/tech-policy/2015/07/fbi-chief-tells-senate-committee-were-doomed-without-crypto-backdoors/) and [New York County District Attorney Cyrus Vance Jr.](http://arstechnica.com/tech-policy/2015/07/this-is-the-most-outrageous-government-tirade-against-ios-8-encryption/) made some pretty nasty comments about strong encryption on smartphones and the apocolyptic-problems it could bring, I thought it might be a good idea to remind everyone of what [Representative Ted Lieu of California said back in April](http://arstechnica.com/tech-policy/2015/04/irate-congressman-gives-cops-easy-rule-just-follow-the-damn-constitution/) about why some users wanted smartphone encryption in the first place: + +> Why do you think Apple and Google are doing this? It's because the public is demanding it. People like me: privacy advocates. A public does not want an out-of-control surveillance state. It is the public that is asking for this. Apple and Google didn't do this because they thought they would make less money. This is a private sector response to government overreach. +> +> ... +> +> [T]o me it's very simple to draw a privacy balance when it comes to law enforcement and privacy: just follow the damn Constitution. +> +> And because the NSA didn't do that and other law enforcement agencies didn't do that, you're seeing a vast public reaction to this. Because the NSA, your colleagues, have essentially violated the Fourth Amendment rights of every American citizen for years by seizing all of our phone records, by collecting our Internet traffic, that is now spilling over to other aspects of law enforcement. And if you want to get this fixed, I suggest you write to NSA: the FBI should tell the NSA, stop violating our rights. And then maybe you might have much more of the public on the side of supporting what law enforcement is asking for. +> +> Then let me just conclude by saying I do agree with law enforcement that we live in a dangerous world. And that's why our founders put in the Constitution of the United Statesβ€”that's why they put in the Fourth Amendment. Because they understand that an Orwellian overreaching federal government is one of the most dangerous things that this world can have. + +It might be worth point out that Rep. Lieu is one of four House members with computer science degrees, is a Lieutenant Colonel in the United States Air Force Reserves, _and_ served for four years as a member of the Judge Advocate General’s Corps, making him (IMHO) someone knowledgeable in this area. + +And it just so happens that [fourteen of the world's top computer security experts](http://dspace.mit.edu/bitstream/handle/1721.1/97690/MIT-CSAIL-TR-2015-026.pdf) agree with him, but who's counting. diff --git a/src/sitePosts/journal/2015/07-15-on-william-gibson.md b/src/sitePosts/journal/2015/07-15-on-william-gibson.md new file mode 100644 index 0000000..b37b374 --- /dev/null +++ b/src/sitePosts/journal/2015/07-15-on-william-gibson.md @@ -0,0 +1,19 @@ +--- +title: On William Gibson and Cyberspace +date_pub: 2015-07-15T00:00:00-04:00 +date_upd: 2018-11-04T14:59:00-05:00 +content_type: journal +tags: computers cyberpunk philosophy +--- + +I've been on vacation for the last couple of days, and have used some of the time to finish reading William Gibson's excellent "Sprawl" series. + +I actually read the first book in the series, _Neuromancer_, some 14 years ago, and always meant to get back to it, but just never did. Then, about 2 years ago, I re-read _Neuromancer_ and dove straight into the second book, _Count Zero_, before again losing momentum and abandoning the series. While packing for our vacation, I happened across my copy of the third and final book in the series, _Mona Lisa Overdrive_, and I made the decision to use this vacation as an opportunity to finally finish reading the series, a feat that I accomplished just yesterday. + +First, I have to say that I loved the book. You can tell that Gibson's style got more focused as the series went on, making each book better than the last. Also, the series fits his style well -- he has a habit of creating apparently unrelated strands of storytelling, featuring characters that don't seem to have anything to do with each other, and bringing them together in the climax. In that way, _Mona Lisa Overdrive_ serves as the climax of the series itself, bringing apparently unrelated characters and story elements from the first two books together (along with some new ones) into an explosive ending. + +Much of what I like about the series are the background elements, like the way he describes the sprawl and the histories of his characters. But, most of all, I love the idea of [cyberspace](https://en.wikipedia.org/wiki/Cyberspace): + +> Cyberspace. A consensual hallucination experienced daily by billions of legitimate operators, in every nation, by children being taught mathematical concepts... A graphic representation of data abstracted from the banks of every computer in the human system. Unthinkable complexity. Lines of light ranged in the nonspace of the mind, clusters and constellations of data. Like city lights, receding. + +As a computer nerd whose been into networking information and virtual worlds since the days of BBSing (and through into MUDs, the web, and even [OpenSimulator](http://opensimulator.org), for a little while), the notion of connecting to digital realms directly via ones own mind has always appealed to me. In fact, one of the most depressing things about the books, to me, is that in the nearly 30 years since they were published, very little of that technology [has come to pass](https://en.wikipedia.org/wiki/Brain%E2%80%93computer_interface). diff --git a/src/sitePosts/journal/2015/07-21-rss-atom-comeback.md b/src/sitePosts/journal/2015/07-21-rss-atom-comeback.md new file mode 100644 index 0000000..134d2a8 --- /dev/null +++ b/src/sitePosts/journal/2015/07-21-rss-atom-comeback.md @@ -0,0 +1,15 @@ +--- +title: RSS & Atom Making a Comeback? +date_pub: 2015-07-21T00:00:00-04:00 +date_upd: 2018-11-04T15:01:00-05:00 +content_type: journal +tags: internet js rss web +--- + +[Baldur Bjarnason thinks he knows](https://www.baldurbjarnason.com/notes/the-rules-have-changed-for-rss/) why RSS and Atom have come back into vogue, powering both Apple News and Facebook Instant Articles after years of disuse: + +> There’s one thing that’s very different this time around for RSS and Atom and it’s the reason why this time it might be different. Back then β€˜just the HTML, no CSS, JS, or Flash’ meant nothing more than rich text with images. +> +> Now, β€˜just the HTML’ means rich text, video, audio, SVG, and more. While at the same time β€˜HTML with CSS and JS’ has come to mean slow loading websites full of annoying ads and broken functionality (i.e. scroll-jacking). + +It's that last point (again) that's the most important, IMHO, but it's also the one that seems to be [falling on deaf ears](https://blog.itsericwoodward.com/2015/self-fulfilling-prophecymicahgodboltstatus623180750142058496). diff --git a/src/sitePosts/journal/2015/07-22-fatigue-and-mastery.md b/src/sitePosts/journal/2015/07-22-fatigue-and-mastery.md new file mode 100644 index 0000000..822b231 --- /dev/null +++ b/src/sitePosts/journal/2015/07-22-fatigue-and-mastery.md @@ -0,0 +1,13 @@ +--- +title: Fatigue and Mastery +date_pub: 2015-07-22T00:00:00-04:00 +date_upd: 2018-11-04T15:21:00-05:00 +content_type: journal +tags: code js philosophy +--- + +Tero Parviainen has a nice piece about [Overcoming Javascript Framework Fatigue](http://teropa.info/blog/2015/07/15/overcoming-javascript-framework-fatigue.html), but don't let the title fool you - much of the advice can be applied those who work (and live) in most any rapidly-evolving field. Plus, it contains [one of the best quotes](https://gist.github.com/prakhar1989/1b0a2c9849b2e1e912fb) from Rich Hickey (the creator of [Clojure](http://clojure.org/)) about what skills a developer really needs to have (and those skills have nothing to do with preferred language or framework): + +> Programming mastery has little to do with languages, paradigms, platforms, building blocks, open source, conferences etc. These things change all the time and are not fundamental. Knowledge acquisition skills allow you to grok them as needed. I'd take a developer (or even non-developer!) with deep knowledge acquisition and problem solving skills over a programmer with a smorgasbord of shallow experiences any day. + +Via [JavaScript Weekly](http://javascriptweekly.com/issues/241) diff --git a/src/sitePosts/journal/2015/07-29-anti-gmo-scaremongering.md b/src/sitePosts/journal/2015/07-29-anti-gmo-scaremongering.md new file mode 100644 index 0000000..3760bf6 --- /dev/null +++ b/src/sitePosts/journal/2015/07-29-anti-gmo-scaremongering.md @@ -0,0 +1,11 @@ +--- +title: Anti-GMO Scaremongering +date_pub: 2015-07-29T00:00:00-04:00 +date_upd: 2018-11-04T15:25:00-05:00 +content_type: journal +tags: fear gmo politics science +--- + +> The people who push GMO labels and GMO-free shopping aren’t informing you or protecting you. They’re using you. They tell food manufacturers, grocery stores, and restaurants to segregate GMOs, and ultimately not to sell them, because people like you won’t buy them. They tell politicians and regulators to label and restrict GMOs because people like you don’t trust the technology. They use your anxiety to justify GMO labels, and then they use GMO labels to justify your anxiety. Keeping you scared is the key to their political and business strategy. And companies like Chipotle, with their non-GMO marketing campaigns, are playing along. + +[Unhealthy Fixation](http://www.slate.com/articles/health_and_science/science/2015/07/are_gmos_safe_yes_the_case_against_them_is_full_of_fraud_lies_and_errors.html), William Saletan diff --git a/src/sitePosts/journal/2015/09-18-commercial-web-dying.md b/src/sitePosts/journal/2015/09-18-commercial-web-dying.md new file mode 100644 index 0000000..52f16ca --- /dev/null +++ b/src/sitePosts/journal/2015/09-18-commercial-web-dying.md @@ -0,0 +1,21 @@ +--- +title: The (Commercial) Web is Dying? So What? +content_type: journal +date_pub: 2015-09-18T00:00:00-04:00 +date_upd: 2021-07-10T23:44:00-04:00 +description: In defense of ad-blockers and a demonetizied web. +tags: web money blogging +--- +Lately, there seems to have been a up-tick in the [never](http://www.tomsguide.com/us/ad-blocking-is-stealing,news-20962.html)-[ending](https://www.techdirt.com/articles/20100306/1649198451.shtml) [debate](http://www.theverge.com/2015/9/17/9338963/welcome-to-hell-apple-vs-google-vs-facebook-and-the-slow-death-of-the-web) about the web, advertising, and content-blocking. While Apple's recent [introduction of content-blockers in iOS9](https://developer.apple.com/library/prerelease/ios/releasenotes/General/WhatsNewInSafari/Articles/Safari_9.html#//apple_ref/doc/uid/TP40014305-CH9-SW8) is the most proximate reason for this discussion, it isn't a new battle, and has been raging for [quite some time](http://arstechnica.com/business/2010/03/why-ad-blocking-is-devastating-to-the-sites-you-love/). The basic argument is that many sites rely on advertising revenue to cover not just their costs, but also to turn a profit. And these web-based companies are (justifiably) concerned that ad-blocking could reduce (or destroy) that revenue stream, which might force them to shutdown. + +To which I say, "so what?" + +I'm not trying to be mean, but the fact is that [lots](https://en.wikipedia.org/wiki/List_of_defunct_retailers_of_the_United_States) and [lots](http://www.statisticbrain.com/startup-failure-by-industry/) of businesses are forced to close every year, and many (most?) of them close because they have what some might call a "flawed business model". Like [some others](http://entreproducer.com/online-advertising/), I believe that's exactly what the "web advertising" model is, because if it wasn't, no one would be blocking the ads, there would be no heated discussion about it, and blog posts like this one would never exist. I mean, some may liken ad-blocking to stealing, but others see it for what it actually is - [disruption](http://www.ideafaktory.com/technology/ad-blocking-web-of-lies/). + +Look, I've been online long enough to remember the early attempts at monetizing the web: first came the embedded banner ads, which paid-per-view, but were easily ignored by end users; then came the pop-up (and pop-under) ads, which were still pay-per-view, but which couldn't be ignored (unless you turned them off, since they relied on JavaScript); then came embedded banners with a "pay-per-click" model, which didn't work because nobody wanted to actually click the links. And as each one rose to prominence, there were always those crying for people to engage with their ads ("If you don't click on one of my ads, I'll be forced to shut my site down!"). But the web remains. + +And that's part of why I titled this the way I did. Even if the commercial web went away (which, let's be honest, it probably won't), it wouldn't be the end of the world: many sites which rely on [donations](https://wikipedia.org) or [subscriptions](http://ft.com/) would remain, as would [storefronts](https://amazon.com/) and sites that support [physical](https://samsung.com) [things](http://hasbro.com). Plus, there are still many sites which are run more-or-less as hobbies, paid for by the people [who run them](https://itsericwoodward.com/). And, despite what the anti-blockers would say, there are [other successful revenue models out there](https://medium.com/on-blendle/blendle-a-radical-experiment-with-micropayments-in-journalism-365-days-later-f3b799022edc). + +So, if you are a blogger or news site who is concerned about how this change will affect your bottom line, you have my sympathy: not because I block your ads (which I do), but because you put your faith in a fundamentally flawed business model (and believe me, [you aren't the only one](http://the-digital-reader.com/2015/06/03/no-readers-have-no-obligation-to-support-a-publishers-flawed-model-or-bad-decisions/)). If, however, you think I'm wrong, then I encourage you to take the next obvious step and start blocking (or [Comic Sans-ing](https://twitter.com/howtogeek/status/638861518575173632)) users who run ad blockers. If your content is worth viewing ads for, then people who run blockers will turn them off just so they can see it. But be prepared for the horrifying truth: when people have to actually pay for something (either with their eyeballs and "unblock" buttons, or with cold-hard cash), your site may not be good/interesting/original enough to actually generate revenue. Again, you have my sympathy... but not my cooperation. + +[It has recently been asked](http://oleb.net/blog/2015/08/is-it-immoral-to-not-block-ads/) what the web might have looked like if the ad-based model had never taken off. Since we can't rewind the clock, we can't know for sure what course history may have taken in that instance. But if we keep running ad-blockers long enough, we may yet find out. diff --git a/src/sitePosts/journal/2016/06-16-hello-world.md b/src/sitePosts/journal/2016/06-16-hello-world.md new file mode 100644 index 0000000..2979971 --- /dev/null +++ b/src/sitePosts/journal/2016/06-16-hello-world.md @@ -0,0 +1,27 @@ +--- +{ + "title": "Hello, World!", + "description": "The obligatory introductory post for my new web site.", + "content_type": "journal", + "is_draft": false, + "was_pushed": true, + "date_pub": "2016-06-16T13:54:45.000Z", + "date_upd": "2018-12-01T14:31:00-05:00", + "short_code": "1f5f0", + "tags": "blogging" +} +--- + +So, after a few years of on-again, off-again [blogging](https://blog.itsericwoodward.com/) (in both [original](https://blog.itsericwoodward.com/2015/on-william-gibson-and-cyberspace) and [micro](https://blog.itsericwoodward.com/2016/cherish-your-impostor-syndrome-dont-trust-people-who-dont-have) flavors), coupled with staring at (and maintaining) a [half-completed projects site](https://site.itsericwoodward.com/), I got tired of having a split web personality and decided to squish it all together. This site is the result of that unholy union. + +I plan on doing a write-up later explaining the gory details of how (and why) I built it the way I +did1, but let me at least give you the quick, jargon-laden version: the site is built with [Node](https://nodejs.org/) (specifically an as-of-yet-unreleased custom library & CLI wrapped around [HarpJS](https://harpjs.com/)), which creates static pages out of [Markdown](http://commonmark.org/) and [EJS](http://ejs.co/) (templated to conform to [IndieWeb](https://indiewebcamp.com/) / [microformats2](http://microformats.org/) specifications), which is then compressed via various [Gulp](http://gulpjs.com/) plugins, and is ultimately served up through [nginx](https://nginx.org/) running on a [DigitalOcean](https://m.do.co/c/99e02989735d) droplet. And, lest I forget, lots and lots of emojis. + +It's all still very much a work-in-progress, but I'm pleased as punch with the results so far, and look forward to finishing both it and my 237 other projects (just probably not this week, month, or year). + +In the meantime, feel free to take a look around and check it out, and if you have any questions (or want to heap praise on me), hit me up [on social media or via email](/about.html). + +---------- +

    +1 - Especially since I've been publishing here for [over a month](/updates/2016/5/8/update.html) and am just now getting around to writing my "introductory" post. +

    diff --git a/src/sitePosts/journal/2016/08-23-obituary.md b/src/sitePosts/journal/2016/08-23-obituary.md new file mode 100644 index 0000000..2f59652 --- /dev/null +++ b/src/sitePosts/journal/2016/08-23-obituary.md @@ -0,0 +1,34 @@ +--- +{ + "title": "Obituary for Dennis Jon Woodward (My Father)", + "description": "My father, Dennis Jon Woodward, passed away May 23, 2016. This is his obituary.", + "tags": "memorial", + "is_draft": false, + "date_pub": "2016-08-23T02:23:47.697Z", + "date_upd": "2021-07-11T22:06:00-04:00", + "content_type": "journal", + "was_pushed": true, + "short_code": "1f7n0" +} +--- +My father, Dennis Jon Woodward, passed away May 23, 2016. + + + +I debated whether to even write about this here, but as the months have gone on, I can't help but notice the effect his passing has had on my thoughts. Initially, I was overwhelmed with sadness, my mind unable to grasp the concept of him not existing anymore. As the time has gone on, it's become more about specific thoughts or experiences triggering specific memories, followed by a wave of sadness at never being able to have those experiences with him again. Even now, as I write this nearly 3 months on, I find myself tearing up at the thought of never seeing him again. I know these things take time, and I'm sure that someday, once I'm "used" to not being with him anymore, my memories of him will bring joy. But not yet. + +The downside of being a nauralist / materialist is that I don't believe in any magical place where I'll get to see him again, nor do I believe that he can come visit me as a ghost or spirit. I mean, it'd be nice if either of these true, but I can't believe in them because there's no evidence for them. And since he's the one who started me on my love of science (and, tangentially, my road to naturalism), I have to stay true to that, no matter what my wishes are. But it's hard. + +Writing the obituary has been, for me, part of the grieving process - trying to consolidate the major events / moments / details of his life down to a few short sentences. But it's also been difficult to complete; almost as if, by not publishing it, I was somehow hanging on to him. I dreaded writing it (to say nothing of trying to find the right picture), but I did, and as of yesterday, it was published in the paper. But nothing changed. He's still gone. + +This is the other reason I debated writing about this here - not just because it's difficult, but because I feel like I don't have anything useful to say. Maybe later, but not now. + +--------- + +Dennis Jon Woodward, formerly of Concord, passed away unexpectedly but peacefully in his home Monday, May 23, 2016, at the age of 64. +He was born January 16, 1952, in Syracuse, N.Y., the son of the late Leonard and Vera Woodward, and was raised in upstate New York. +He retired from Pass & Seymour / Legrande in Concord in 2012 after 40 years with the company. + +He is survived by his wife, Sherry Woodward, of Ellenboro; sisters, Eileen Joy and Brenda Myslevecek, of Redfield, N.Y.; brother, Donald Woodward and wife, Pat, of Augusta, Ga.; son Eric Woodward and wife, Stacie, of Concord; son, Jeffrey Woodward and wife, Candace, also of Concord; daughter Sarah Horton and husband, Jason, of Mount Pleasant; stepson, Keith McDaniel and wife, Lisa, of Ellenboro; stepson Kirk McDaniel, of Concord; and 13 grandchildren. A private family service was held at his home. In lieu of flowers, the family is asking that donations be made to the [Leukemia & Lymphoma Society](http://www.lls.org/). + +Posted at: http://www.independenttribune.com/obituaries/woodward-dennis/article_015cf7ba-3000-5081-8719-9b5536174451.html diff --git a/src/sitePosts/journal/2016/12-12-failing-me-softly.md b/src/sitePosts/journal/2016/12-12-failing-me-softly.md new file mode 100644 index 0000000..19f3df3 --- /dev/null +++ b/src/sitePosts/journal/2016/12-12-failing-me-softly.md @@ -0,0 +1,70 @@ +--- +{ + "title": "Failing Me Softly with SPF", + "description": "The joys of the Sender Policy Framework and the (apparent) difficulties of implementing it correctly.", + "tags": "spf dns internet email", + "is_draft": false, + "date_pub": "2016-12-12T16:51:12.171Z", + "date_upd": "2018-12-01T14:34:00-05:00", + "content_type": "journal", + "was_pushed": true, + "short_code": "1fbb0" +} +--- +About a year ago, I started receiving some fairly odd email messages: some originating from my own domain (itsericwoodward.com), and many originating from my own email address! + + + +Most of these emails were obvious spam (or were themselves the product of spam, such as failure messages from external domains where the spam had been sent), and I started panicking: had I been hacked? + +As I dug into the issue, I discovered that no, I hadn't been hacked, but that my domain was just blindly accepting requests to send email. That's when I first learned about [SPF (Sender Policy Framework)](http://www.openspf.org/), "an open standard specifying a technical method to prevent sender address forgery." Basically, to use SPF, I (as the domain owner) simply had to add a single TXT record to my domain information that indicated what servers could actually send email from my domain, and all others would be rejected. So, after fiddling around with [the format](http://www.openspf.org/SPF_Record_Syntax) for a while, I found my hosts's recommended record (name changed to protect the innocent): + + v=spf1 a mx include:mail.example.com ~all + +Needless to say, I added it to my domain record, and bam -- overnight, nearly all of the spam stopped flowing. + +So, I went about my merry way, figuring I had solved the issue. I even added this record to the other domains that I own, since it had worked so well with the first one. + +But it turns out that I was wrong. + +Although I stopped receiving messages the messages from myself, every now and then I'd get a failure notice about an email coming from one of my domains being unsendable. When I'd get these, I'd think, "huh, I thought I fixed that," and then I'd forget about it and move on to [something else](https://mythicwarsgame.com/). + +Then, just the other day, I received an email from me, to (another) me, telling me that I had a voicemail from an international number (it even helpfully suggested that "You might want to check it when you get a chance."). And I thought, "wait a minute, didn't I already fix this?". + +So, this time, rather than forgetting about it, I actually took a moment to look at the header, and that's when I saw this (again, name changed): + + softfail (mail.example.com: domain of transitioning xxxxxx@example.com + does not designate 192.0.2.1 as permitted sender) + +So, I went back to the SPF site again, and that's when I learned that the server could not only reply with "pass" and "fail", but a whole cornucopia of messages: + + Received-SPF: softfail (mybox.example.org: domain of transitioning + myname@example.com does not designate 192.0.2.1 as permitted sender) + + Received-SPF: neutral (mybox.example.org: 192.0.2.1 is neither permitted + nor denied by domain of myname@example.com) + + Received-SPF: none (mybox.example.org: domain of myname@example.com does + not designate permitted sender hosts) + + Received-SPF: permerror -extension:foo (mybox.example.org: domain of + myname@example.com uses mechanism not recognized by this client) + + Received-SPF: temperror (mybox.example.org: error in processing during + lookup of myname@example.com: DNS timeout) + +The next obvious question is "why?" (well, that and "what the hell does transitioning mean?"). + +It turns out that my host either misinterpreted [the SPF spec](https://www.ietf.org/rfc/rfc4408.txt), or tried to protect their users from themselves. Apparently, the presence of the tilde ("~") in a record indicates that the domain is in transition to SPF - it's designed for large email providers and corporations to let them start transitioning to SPF without forcing hard failures on every email that originates from an unlisted server (the idea is that the email owner would collect these softfails, verify the IPs are valid, and then add them to the SPF record). Oops. + +Fortunately, I now knew what to do to fix the problem: replace the tilde with a dash ("-"): + + v=spf1 a mx include:mail.example.com -all + +A few hours later, problem solved, and no more spam from my domain (so far). + +Based on my reading, [I'm not the only one that made this mistake](https://nick.groenen.me/posts/2013/03/20/spf-records-youre-doing-them-wrong/), and since SPF has been around for a few years (and is implemented, in some for or another, on most corporate domains), I can only imagine how many other domains using an incomplete / incorrect implementation of it (based on the number of F*-buddy requests and Canadian pharmaceutical offers I still get, I'd imagine that number to be fairly high). + +So, if you own one or more domains, please do everyone a favor and implement SPF for your email. And if you aren't using a ton of different mail servers (wherein you might not be able to list them all in your TXT record), skip the tilde and go straight for the dash. + +The internet will thank you for it. diff --git a/src/sitePosts/journal/2016/12-14-star-trekkin.md b/src/sitePosts/journal/2016/12-14-star-trekkin.md new file mode 100644 index 0000000..2f65d42 --- /dev/null +++ b/src/sitePosts/journal/2016/12-14-star-trekkin.md @@ -0,0 +1,62 @@ +--- +{ + "title": "Star Trekkin'", + "description": "An amusing take on how the humans in Star Trek relate to their technology (and how other aliens relate to them).", + "tags": "scifi funny tv StarTrek", + "is_draft": false, + "date_pub": "2016-12-14T15:26:55.596Z", + "date_upd": "2018-12-01T14:34:00-05:00", + "content_type": "journal", + "was_pushed": true, + "short_code": "1fbd0" +} +--- +Today, in the "I never thought of it like that" file: + +> Random Headcanon: That Federation vessels in _Star Trek_ seem to experience bizarre malfunctions with such overwhelming frequency isn’t just an artefact of the television serial format. Rather, it’s because the Federation as a culture are a bunch of deranged hyper-neophiles, tooling around in ships packed full of beyond-cutting-edge tech they don’t really understand... All those rampant holograms and warp core malfunctions and accidentally-traveling-back-in-time incidents? That doesn’t actually happen to anyone else; it’s literally **just** Federation vessels that go off the rails like that. And they do so on a fairly regular basis. + + + +But apparently, others **have** thought of that, and its implications: + +> So to everyone else in the galaxy, all humans are basically Doc Brown... Aliens who have seen the _Back to the Future_ movies literally don’t realise that Doc Brown is meant to be funny. They’re just like β€œyes, that is exactly what all human scientists are like in my experience”. + +... + +> THE ONLY REASON SCOTTY IS CHIEF ENGINEER INSTEAD OF SOMEONE FROM A SPECIES WITH A HIGHER TECHNOLOGICAL APTITUDE IS BECAUSE EVERYONE FROM THOSE SPECIES TOOK ONE LOOK AT THE ENTERPRISE’S ENGINE ROOM AND RAN AWAY SCREAMING + +... + +> klingons: okay we don’t get it +> +> vulcan science academy: get what +> +> klingons: you vulcans are a bunch of stuffy prisses but you’re also tougher, stronger, and smarter than humans in every single way +> +> klingons: why do you let them run your federation +> +> vulcan science academy: look +> +> vulcan science academy: this is a species where if you give them two warp cores they don’t do experiments on one and save the other for if the first one blows up +> +> vulcan science academy: this is a species where if you give them two warp cores, they will ask for a third one, immediately plug all three into each other, punch a hole into an alternate universe where humans subscribe to an even more destructive ideological system, fight everyone in it because they’re offended by that, steal their warp cores, plug those together, punch their way back here, then try to turn a nearby sun into a torus because that was what their initial scientific experiment was for and they didn’t want to waste a trip. +> +> vulcan science academy: they did that last week. we have the write-up right here. it’s getting published in about six hundred scientific journals across two hundred different disciplines because of how many established theories their ridiculous little expedition has just called into question. also, they did turn that sun into a torus, and no one actually knows how. +> +> vulcan science academy: this is why we let them do whatever the hell they want. +> +> klingons: ... can we be a part of your federation + +... + +> you know what the best evidence for this is? Deep Space 9 almost never broke down. minor malfunctions that irritated O’Brien to hell and back, sure, but almost none of the truly weird shit that befell Voyager and all the starships Enterprise. what was the weirdest malfunction DS9 ever had? the senior staff getting trapped as holosuite characters in Our Man Bashir, and that was because a human decided to just dump the transporter buffer into the station’s core memory and hope everything would work out somehow, which is a bit like swapping your computer’s hard drive out for a memory card from a PlayStation 2 and expecting to be able to play a game of Spyro the Dragon with your keyboard and mouse. + +... + +> There is no phrase in Vulcan for β€œthe particular moment when you understand that the true way to serenity is to embrace chaos as much as logic.” +> +> Vulcans that work for Starfleet though, have a particular look that passes between them when sharing war stories featuring human shenanigans that might mean the same thing. + +From http://beka-tiddalik.tumblr.com/post/150425828285/roachpatrol-deadcatwithaflamethrower / HT [jwz.org](https://www.jwz.org/blog/2016/11/star-trek-mad-science/) + +<rant>I loathe the way Tumblr shows replies. It's like the worst aspects of a single-page mailing list dump, but for the "social media age" (so, an excess of needless indenting that screws up both the text and the embedded images).</rant> diff --git a/src/sitePosts/journal/2018/02-18-mythic-wars-have-begun.md b/src/sitePosts/journal/2018/02-18-mythic-wars-have-begun.md new file mode 100644 index 0000000..acf0a5e --- /dev/null +++ b/src/sitePosts/journal/2018/02-18-mythic-wars-have-begun.md @@ -0,0 +1,36 @@ +--- +title: The Mythic Wars Have Begun! +description: My new card game has been published, so I wrote a card database for it. +tags: code MythicWars CodexMythica games +is_draft: false +date_pub: 2018-02-18T22:47:06.239Z +section: updates +content_type: journal +was_pushed: false +--- + +TL;DR - I made a [game](https://mythicwarsgame.com/) and got it [published](https://www.kickstarter.com/projects/603868199/mythic-wars-clash-of-the-gods-and-cthulhu-rises/posts/2095980), so I made an [app](https://codex.mythicwarsgame.com/) to help people play the game, and [published](https://github.com/ItsEricWoodward/codex-mythica) that, too. + +ICYMI, [the card game I designed](https://mythicwarsgame.com/) and [ran a Kickstarter for](https://www.kickstarter.com/projects/603868199/mythic-wars-clash-of-the-gods-and-cthulhu-rises/) was [finally published a few months ago](https://www.kickstarter.com/projects/603868199/mythic-wars-clash-of-the-gods-and-cthulhu-rises/posts/2095980). + +<gratuitous-plug> It's called [Mythic Wars: Clash of the Gods](https://mythicwarsgame.com/), and it's available now at many fine gaming stores, or directly from either [the Excalibre Games website](http://excalibregames.com/) or [Amazon](https://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords=mythic+wars+clash+of+the+gods)! </gratuitous-plug> + +I had alot of fun designing and playtesting the game, and I'm quite pleased with the finished product. While I admit that I found the entire Kickstarting and publishing process to be somewhat less fun (and quite eye-opening), overall, the fact that I can now hold my game in my hands (and see it for sale at [my friendly local game store](https://www.facebook.com/pages/Scotts-Collectibles/190794444295850)) makes me enormously happy. + +
    + +
    My game, on a shelf, AT A STORE!
    +
    + +Since I am [a code monkey by trade](https://itsericwoodward.com/about.html) (and [a web developer by choice](https://blog.itsericwoodward.com/2015/developing-the-web)), I wanted to complement the game's publication with the release of a simple, searchable database of all of the cards available for it. Taking inspiration from [the Gatherer, the official database for Magic: the Gathering cards](http://gatherer.wizards.com/) (the best example of such an application that I'm aware of), I mocked up something over the course of weekend, tweaked it over the course of a couple more weekends, and soon, [The Codex Mythica](https://codex.mythicwarsgame.com/) was born. + +It's my first publicly-available [Node](https://nodejs.org/) / [Express](http://expressjs.com/) application, so the code's kinda ugly, but I think it has some neat features, like a responsive layout designed to work well on different screens and devices, and a category-based searching / filtering system for sorting and selecting cards (along with the obligatory word search functionality). Plus, each card has links to both its art and to the [Wikipedia](https://wikipedia.org/) entry for the its subject (or the [Lovecraft wiki](http://lovecraft.wikia.com/wiki/Main_Page) entry, in the case of some of [the Outer Gods and their minions](https://codex.mythicwarsgame.com/cards/s01r)). + +It also (finally) gave me an excuse to share something on GitHub! You can find it at https://github.com/ItsEricWoodward/codex-mythica + +<gratuitous-plug> So, if you like games about gatherings of mages, ascended beings, or worlds where war is crafted, check out [Mythic Wars: Clash of the Gods](https://mythicwarsgame.com/), available now at many fine gaming stores, or directly from either [the Excalibre Games website](http://excalibregames.com/) or [Amazon](https://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Daps&field-keywords=mythic+wars+clash+of+the+gods)! </gratuitous-plug> + +(Sorry, I'm contractually obligated to get in one more of those.) + +Anyways, if you have any suggestions for The Codex Mythica, feel free to [open an issue on GitHub](https://github.com/ItsEricWoodward/codex-mythica/issues) or +drop me a line (I can't guarantee I'll implement it, but I always appreciate the suggestions). diff --git a/src/sitePosts/journal/2018/05-15-fixing-gedit.md b/src/sitePosts/journal/2018/05-15-fixing-gedit.md new file mode 100644 index 0000000..a6ade10 --- /dev/null +++ b/src/sitePosts/journal/2018/05-15-fixing-gedit.md @@ -0,0 +1,25 @@ +--- +title: Fixing Gedit +date_pub: 2018-05-15T00:00:00-04:00 +date_upd: 2018-12-01T14:43:00-05:00 +content_type: journal +tags: NoteToMyFutureSelf gedit Ubuntu +description: Notes about some of the settings that I recommend for gedit. +--- +I tend to use [Atom](https://atom.io/) when I'm working on code, but given the choice, I prefer to use more basic text editors when I'm just making / re-reading notes (something I do alot). + +In my laptop's previous life, it had a runaway memory issue with #gedit that made it impossible to use, but since upgrading to #Ubuntu 18.04, I haven't had any troubles with it, so it's been my default text editor once again. + +Unfortunately, one issue I've continued to run into is that, no matter how many times I adjust the editor settings in the GUI (for tab size, auto-indent, and [use-spaces-for-tabs-goddammit](https://www.jwz.org/doc/tabs-vs-spaces.html)), those changes are lost on reboot. + +So, this time, rather than making the same futile changes in the application, I decided to use (what I think are) the commands to permanently change those settings. + +If you're having the same problems, type this in your shell of choice (ENTER after each one): + +```shell +> gsettings set org.gnome.gedit.preferences.editor tabs-size 2 +> gsettings set org.gnome.gedit.preferences.editor auto-indent true +> gsettings set org.gnome.gedit.preferences.editor insert-spaces true +``` + +I've rebooted the machine since I put these commands in, and so far, so good. Of course, this may change by the next LTS release, but these settings should keep my happy for the next couple of years, at least (and I'm posting it here primarily as a #NoteToMyFutureSelf). diff --git a/src/sitePosts/journal/2018/06-26-loose-ideas-for-next-social-web.md b/src/sitePosts/journal/2018/06-26-loose-ideas-for-next-social-web.md new file mode 100644 index 0000000..79ff059 --- /dev/null +++ b/src/sitePosts/journal/2018/06-26-loose-ideas-for-next-social-web.md @@ -0,0 +1,22 @@ +--- +title: Loose Ideas for the Next Social Web +date_pub: 2018-06-26T00:00:00-04:00 +date_upd: 2018-12-01T14:42:00-05:00 +content_type: journal +tags: SocialMedia web offline fediverse WebDev +description: Some thoughts about what I would like to see next in the social media / web space. +--- +Inspired by both [this toot](https://octodon.social/@kensanata/100270464515352834) and my recent dabblings in [the Fediverse](https://wonderdome.net/), I just wanted to take a moment and collect some thoughts about what I would like to see next in the #SocialMedia / #web space. + ++ I like the idea of using a hub-and-spoke model, where each actual edge device (phone / tablet / etc.) connects to some kind of always-on server (either a cheap virtual machine or a home-based server), which would be run by a tech-enabling friend, like BBSes used to be. ++ All content creation and such would occur on the edge device, probably via a [progressive web app](https://adactio.com/journal/13884) hosted on the hub (to enable #offline creating), and which would connect to its hub when convenient to upload any newly created content. + + Here, "content" means basically anything that you can create on a social media site - text, photos, replies, whatnot. ++ The content would be marked up with [IndieWeb](https://indieweb.org/) [microformats-2](http://microformats.org/) tags, enabling easy consumption / sharing. ++ Since the content creation / editing would occur on the spoke devices, the hub would be used primarily for caching and speedy connectivity (to prevent issues with asymmetric connection speeds that would prevent direct sharing between the edge devices). ++ The hub would collect incoming messages for the user and cache them until the user's device can connect to the hub to pull them down into their edge device(s). ++ The hub would also support [webmentions](http://webmention.org/) (both in and out), [webfinger](https://webfinger.net/), and any other useful protocols ([ActivityPub](https://www.w3.org/TR/activitypub/), to enable more clients?). ++ Ideally, each user of this kind of system would have a subdomain of their own (https://eric.example.com), which has their public info, profile pic, and public posts, and which could serve as a [Web sign-in](https://indieweb.org/How_to_set_up_web_sign-in_on_your_own_domain) endpoint via the presence of an [h-card](http://microformats.org/wiki/h-card) (listing their OAuth2-compatible accounts). + +I freely admit that this idea still has some issues, since it is both incredibly hand-wavy and would still require tech-smart gatekeepers to run the hubs, but eventually even that second issue could be mitigated somewhat by turning the software into a single-click install option for a Pi or similar device (or pre-installed on such a device, with a plug-and-play setup of some kind, or pre-built images for VPS hosting). + +I'm open to thoughts / suggestions / comments. diff --git a/src/sitePosts/journal/2018/07-23-career-20.md b/src/sitePosts/journal/2018/07-23-career-20.md new file mode 100644 index 0000000..8243925 --- /dev/null +++ b/src/sitePosts/journal/2018/07-23-career-20.md @@ -0,0 +1,15 @@ +--- +title: Career 2.0 +content_type: journal +date_pub: 2018-07-23T00:00:00-04:00 +date_upd: 2021-07-10T23:32:00-04:00 +tags: career meatspace +tldr: Announcing my upcoming change in employment status. +--- +In case you hadn't heard by now, I've decided to leave AT&T. After nearly 18 years with the company, July 30 will be my last day. + +I have my reasons for leaving, and I may go into them once I am no longer bound by the company's Social Media policy, but for the time being, I'll have to remain mum about it (unless you know me in #meatspace, in which case, contact me elsewhere for details). + +Due to the (relatively) generous severance and benefits package I'll be receiving, I shouldn't have to scramble to find a replacement job career too quickly. As such, I plan on taking a couple of weeks' "sabbatical" during which I can spend some quality time with my family and (hopefully) get some of my side projects finished. + +All that to say: When I woke up this morning, I was struck by how surreal it is that, after nearly 18 years working for the same company, at the same location, and seeing many of the same people every day, I only have a week left. diff --git a/src/sitePosts/journal/2018/08-19-my-blogging-problem.md b/src/sitePosts/journal/2018/08-19-my-blogging-problem.md new file mode 100644 index 0000000..3edcf63 --- /dev/null +++ b/src/sitePosts/journal/2018/08-19-my-blogging-problem.md @@ -0,0 +1,23 @@ +--- +title: My Blogging Problem +date_pub: 2018-08-19T00:00:00-04:00 +date_upd: 2018-12-01T12:17:00-05:00 +content_type: journal +tldr: Social media navel gazing about my love/hate relationship with blogging, all because I'm launching a new journal (not blog) at www.itsericwoodward.com/journal/. +tags: SocialMedia blogging +--- +I have a problem with #blogging. + +For a long time, I assumed that it was a time issue - I felt like I either didn't have the time to do anything cool (which would give me something to blog about), or I felt like I didn't have the time to blog about the few cool things that I did accomplish. + +Then, when I did have some time, there would always be other reasons that I couldn't write: I'd have issues with my blogging software (and wind up spend time either diagnosing it, fixing it, or looking for a replacement), or I'd get distracted updating the servers, or by a family issue, or any number of 100 other things. + +But what makes it worse is my other problem: every few weeks, I'll go on a tear where I get hyper-focused on a single topic or idea, and spend a large amount of my free time either researching it, attempting my hand at it, or both. And then, after a few weeks, I'll inevitably move on to some other topic (something [Les Orchard](https://lmorchard.com/) calls ["Serial Enthusiasm"](https://blog.lmorchard.com/2006/05/26/confessions-of-a-serial-enthusiast/)), and I won't take the time to document what I learned / accomplished during said tear. + +But... no more. + +This post represents the first in (what I hope will be) a series of journal entries about the various things that I've done and/or learned about in the few months/years/lives, in hopes of doing my own small part to [develop the web](/journal/2015/03-18-developing-the-web.html). In addition to posting new items here, I also plan to (eventually) import most of my entries from my on-again-off-again [Known instance](https://blog.itsericwoodward.com/) (aka just in case something bad happens to it). I've got a few other ideas, too, but we'll see how industrious I am. + +And, in order to break my blogging curse, this will not be called a blog, but rather [a journal](https://botsin.space/@selfcare/101008122586734747), and it will live at [ItsEricWoodward.com/journal/](https://www.itsericwoodward.com/journal/). + +So, I hope you enjoy my new journal, and if you're already here, I say "Thanks for stopping by, feel free to take a look around, but please don't let the cats out." ☺ diff --git a/src/sitePosts/journal/2018/08-25-things-i-couldnt-say.md b/src/sitePosts/journal/2018/08-25-things-i-couldnt-say.md new file mode 100644 index 0000000..74d76d3 --- /dev/null +++ b/src/sitePosts/journal/2018/08-25-things-i-couldnt-say.md @@ -0,0 +1,19 @@ +--- +title: Things I Couldn't Say +content_type: journal +date_pub: 2018-08-25T21:19:00-04:00 +date_upd: 2018-12-01T12:17:00-05:00 +tldr: My previous employer's policies prevented me from voicing my opinions on certain topics. As I am no longer employed by them, these are those opinions. +tags: SocialMedia NetNeutrality advertising politics +--- +As I mentioned before, [I have recently ended my employment relationship](/journal/2018/07-23-carrer-20.html) with a certain telecommunications entertainment company, and while I don't want to be seen as someone who bad mouths their former employer, the truth is that they had some policies in place that prevented me from voicing my opinions on certain topics while I was working for them. This is not me complaining so much as explaining why I feel the need to make the following statements now, as opposed to when they were somewhat more relevant to current events. + ++ **Net Neutrality is a good thing, and it needs to be re-instated ASAP** - the major ISPs in the US have proven [time](https://www.eff.org/deeplinks/2007/10/eff-tests-agree-ap-comcast-forging-packets-to-interfere) [and](https://www.washingtonpost.com/blogs/post-tech/post/fcc-fines-verizon-125m-for-blocking-tethering-apps/2012/07/31/gJQAXjRLNX_blog.html) [again](https://www.theguardian.com/technology/2015/jun/22/major-internet-providers-slowing-traffic-speeds) that they can't be trusted, and that they will use every opportunity to try and take advantage of their customers. IMHO, this is a result of the total lack of competition outside of the top 30-50 markets (and sometimes, even within them, meaning that most customers in the US only have one or maybe two competing ISPs available (and who knows how many are in the same position I am, where only one offers *actual* high-speed internet, with the other limited to offering DSL). This is why we need #NetNeutrality. + ++ **Targeted #advertising is not a good thing** - I'm not a huge fan of [surveillance capitalism](https://en.wikipedia.org/wiki/Surveillance_capitalism) in general, but I have a particular distaste for targetted advertising, mostly because of the (unintended?) side effects that we see all around us (filter bubbles, fake news, weaponized misinformation, etc.). That having been said, I do still have a number of Google products in my house, primarily because they are useful devices to have, and (IMHO) that usefulness justifies the data that Google can scrape about me from them. However, to suggest that targetted advertising itself is so useful that we should allow advertisers to collect data about us is, to me, not only the height of arrogance (assuming that these offers are *so good* that we'll *beg* them to take our information), but (because those ads track you further) become something of a circular argument: we need to collect this data, so we can show you better ads, which will track you further, so we can collect more data, so we can show you better ads, which will track you further.... + ++ **Media conglomeration is not a good thing** - there was a time when various arms of the federal government would actually move in order to stop dangerous potential monopolies from forming, but with a few exceptions, that hasn't happened much lately (even though it should). IMHO, telecommunication companies, as gateways to content, should be barred from owning entertainment companies that produce said content (or, if not barred, at least forced to operate those companies at [arm's length](https://en.wikipedia.org/wiki/Arm%27s_length_principle)) in order to help guarantee competition. + ++ **Donald Trump is an unhinged, narcissistic ass-clown who is incapable of telling the truth, and who will go down as one of the worst (but hopefully not last) US presidents in history** - I don't think I need to elaborate on this one. + +I may have more to add to these someday soon, but for now, the above statements will have to do. diff --git a/src/sitePosts/journal/2018/09-18-syncthing-ionice.md b/src/sitePosts/journal/2018/09-18-syncthing-ionice.md new file mode 100644 index 0000000..273eb00 --- /dev/null +++ b/src/sitePosts/journal/2018/09-18-syncthing-ionice.md @@ -0,0 +1,80 @@ +--- +title: Making SyncThing Play (IO)Nice +date_pub: 2018-09-18T16:29:00-04:00 +date_upd: 2018-12-01T12:21:00-05:00 +tldr: My SyncThing instance was using too much CPU, and CPU Limit didn't help reign it in, so I wound up using IO Nice. +content_type: journal +tags: SyncThing Ubuntu +--- +Every now and then, my laptop (running #Ubuntu 18.04) would freeze up: all the screens would lock, and although my mouse cursor was still on the screen, it was completely unable to interact with anything. After 30-40 seconds, everything would start moving again and return to normal. + +The very first thing that I usually did when I get control of my system back was to run the `top` command, and what I frequently saw was [SyncThing](https://syncthing.net/), an open source application that I use for backups, pegging 100% or higher on my CPU usage: + +A screenshot showing SyncThing using too much CPU. + +Now, I knew that this wasn't supposed to happen, and until I could figure out what was triggering the sudden jump in utilization, I decided to try and limit SyncThing's consumption via some other way. + + +## Fix #1 - CPU Limit ## + +First, I tried [CPU Limit](https://github.com/opsengine/cpulimit), a utility designed to put a hard limit on the CPU usage for a process, which I installed and used as outlined [here](https://inside-out.xyz/technology/limiting-to-50-of-a-cpu-core-for-syncthing.html): + +```shell +# Install CPU Limit +> sudo apt install cpulimit +``` + ++ I edited the `syncthing.service` file to make my `ExecStart` directive look like this: + +```shell +# Limit SyncThing to no more than 50% of the available processor +ExecStart=/usr/bin/cpulimit -v -l 50 /usr/bin/syncthing -- -no-browser -no-restart -logflags=0 +``` + ++ Finally, I restarted the SyncThing service: + +```shell +# Reload the service files +> systemctl daemon-reload +# or use `systemctl --user daemon-reload` for user-specific services + +# Restart the SyncThing service +> systemctl restart syncthing.service +# or use `systemctl --user restart syncthing.service` for user-specific services +``` + +This worked for a while, but apparently broke after I updated SyncThing from v0.14.43 to v0.14.50 (the service file kept crashing out). + +And that's when I switched to... + +## Fix #2 - IO Nice ## + +The [IO Nice](https://manpages.debian.org/testing/util-linux/ionice.1.en.html) utility (part of the `util-linux` package in Debian and Ubuntu) allows system users / admins to adjust the scheduling class for an application, which indicates when the process should run: in real-time, as a best-effort (but giving way real-time applications), or only when the system is otherwise idle. + +```shell +# Install util-linux +> sudo apt install util-linux +``` + ++ again, I edited the `syncthing.service` file, but this time, I made my `ExecStart` directive look like this: + +```shell +# We want syncthing to be run as a "best-effort" application +ExecStart=/usr/bin/ionice -c 2 /usr/bin/syncthing -no-browser -no-restart -logflags=0 +``` + ++ Finally, I restarted the SyncThing service (aain): + +```shell +# Reload the service files +> systemctl daemon-reload +# or use `systemctl --user daemon-reload` for user-specific services + +# Restart the SyncThing service +> systemctl restart syncthing.service +# or use `systemctl --user restart syncthing.service` for user-specific services +``` + +It's been a little over a month since I made this change, and I haven't experienced a laptop freeze-up since. I did have a similar problem with SyncThing on the machine that I'm backing up to, and wound up implementing the IO Nice limit on that box, too (with the same result). + +I'll update this post (again) if I run into any other issues with SyncThing. diff --git a/src/sitePosts/journal/2018/10-11-dats-incredible.md b/src/sitePosts/journal/2018/10-11-dats-incredible.md new file mode 100644 index 0000000..23a37e4 --- /dev/null +++ b/src/sitePosts/journal/2018/10-11-dats-incredible.md @@ -0,0 +1,119 @@ +--- +title: Dat's Incredible! +content_type: journal +date_pub: 2018-10-11T12:03:00-04:00 +date_upd: 2018-12-01T12:23:00-05:00 +tldr: I decided to try out the Dat protocol, and now have a copy of this site running on it. +tags: dat archive WebDev +--- + +Recently, I was inspired by [Aral Balkan's concept of Web+](https://ar.al/2018/06/26/web+/) and [his work with dats](https://ar.al/2018/06/25/demonstrating-web-plus-dat/) to add [Dat protocol support](https://datproject.org/) to my own site(s). Since my experiences might be useful to others, I thought I'd share them here. + +A #dat, or Dat #archive (as I understand it) is a sort-of cross between a [Git](https://en.wikipedia.org/wiki/Git) repository and [BitTorrent](https://en.wikipedia.org/wiki/BitTorrent) file share. It was initially developed for storing and sharing data in a decentralized way, and so makes for a great way to share an archive of static content (like a website). + +To create and share a Dat archive, I needed to install the Dat protocol. Since it uses [NodeJS](https://nodejs.org/), this is done via the [Node Package Manager](http://npmjs.com/): + +```shell +sudo npm install -g dat +``` + +I already had a directory in mind to share (the directory that holds the static files of my website), so sharing the dat was as simple as: going into that directory and typing the following commands: + +```shell +# Enter the directory with the static files +> cd www + +# Create the dat +> dat create + +Welcome to dat program! +You can turn any folder on your computer into a Dat. +A Dat is a folder with some magic. + +Your dat is ready! +We will walk you through creating a 'dat.json' file. +(You can skip dat.json and get started now.) + +Learn more about dat.json: https://github.com/datprotocol/dat.json + +Ctrl+C to exit at any time +Title: It's Eric Woodward (dotcom) +Description: Dat for the site running at https://www.itsericwoodward.com/. +Created empty Dat in /home/eric/www/.dat + +Now you can add files and share: +* Run dat share to create metadata and sync. +* Copy the unique dat link and securely share it. + +dat://3dccd6e62ea8e2864fb66598ee38a6b4f4471137eebc23ddff8d81fc0df8dbbc + +# Share the newly-created dat +> dat share +``` + +And that's it. :) + +To verify that I was sharing it, I pointed my web browser to https://datbase.org/, entered my DAT URL in the search box at the top-left of screen, pressed ENTER, and, lo and behold, my website came up. + +Another way to verify that a DAT URL is being actively shared is to view it through the [Beaker Browser](https://beakerbrowser.com/), a special web-browser-like application used for viewing dats. To get it, I went to https://beakerbrowser.com/install/, and downloaded the [AppImage](https://appimage.org/) file for Linux (no link provided here because the Beaker Browser still in pre-release, and any image that I point to from here will probably be old by the time anyone reads this). + +Then, I launched it: + +```shell +# Make it executable + +> chmod a+x beaker-browser-0.8.0-prerelease.7-x86_64.AppImage + +# Launch the AppImage + +> ./beaker-browser-0.8.0-prerelease.7-x86_64.AppImage +``` + +After a few moments, the application came up, at which point I entered my dat URL into the Beaker Browser's address bar, hit the ENTER key, and just like that, my website came up. + +Unfortunately, unless your data is wildly popular (and thus located across multiple hosts in the [swarm](https://docs.datproject.org/hyperdiscovery)), it is only shared for as long as the `dat share` command is running on your machine. So, to make the files permanently available via Dat, I had to create a service file that would run the `dat share` automatically. To do this, I created file in `/etc/systemd/system` called `dat-share-web.service`, which looked like this: + +```shell +[Unit] +Description=DAT Share for It's Eric Woodward (dotcom) +After=network.target + +[Service] +User=eric +Type=simple +WorkingDirectory=/home/eric/www +Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +ExecStart=/usr/bin/node /usr/local/lib/node_modules/dat/bin/cli.js share +Restart=always + +# Output to syslog +StandardOutput=syslog +StandardError=syslog +SyslogIdentifier=dat-share-www + +[Install] +WantedBy=multi-user.target +``` + +After I turned-off my existing DAT share, I started the new service, like this: + +```shell +# Start the service +> sudo systemctl start dat-share-www + +# Enable the service +> sudo systemctl enable dat-share-www +``` + +Now, my Dat archive will be served 24x7, even after I restart the server. + +Everything worked great, but there was one more thing that I wanted to try: I had noticed that, in addition to Aral's site being available at a usual DAT address (`dat://` plus a 64-charactercode), it was also available at his own domain name (dat://ar.al/). After a quick search, I found that what I was looking for was [DAT over DNS](https://www.datprotocol.com/deps/0005-dns/), which can be implemented one of two ways: either via [DNS TXT records](https://github.com/beakerbrowser/beaker/wiki/Dat-DNS-TXT-records-with-optional-DNS-over-HTTPS) or by [placing a file with a link to the DAT at a specific "well known" location](https://github.com/beakerbrowser/beaker/wiki/Authenticated-Dat-URLs-and-HTTPS-to-Dat-Discovery). Since the second option is the one that the DAT project seems to recommend (and it was dead simple to add), [that's what I did](/.well-known/dat). So now, if you launch the Beaker Browser and open the site `dat://www.itsericwoodward.com/`, it will take you to the DAT version of my site. Neat! + +The DAT protocol is a simple but powerful way to share static content, and can help add a layer of redundancy to a website. Hopefully, your experiences in using it will be as positive as mine. + +References: + ++ https://docs.datproject.org/install ++ https://docs.datproject.org/tutorial ++ http://awesome.datproject.org/ ++ https://forum.ind.ie/t/running-a-dat-share-as-a-service-with-systemctl-ubuntu-etc/2181 diff --git a/src/sitePosts/journal/2018/10-29-chim.md b/src/sitePosts/journal/2018/10-29-chim.md new file mode 100644 index 0000000..ac8aead --- /dev/null +++ b/src/sitePosts/journal/2018/10-29-chim.md @@ -0,0 +1,34 @@ +--- +{ + "title": "Now Playing: \"Camp Happy Island Massacre\" for DOS", + "date_pub": "2018-10-29T12:03:00-04:00", + "date_upd": "2018-12-03T19:29:00-05:00", + "tldr": "I wrote a simple computer game in 1997 called Camp Happy Island Massacre which I now have running online here.", + "content_type": "journal", + "tags": "DOSBox chim games js WebDev" +} +--- + +Way back in 1997, I released my first (and, so far, only) computer game, **Camp Happy Island Massacre** (hereafter referred to as #CHIM), a comedy-horror text game for the DOS operating system. Originally written while I was still in college, the game is about a cursed summer camp and the 3 surviving counselors who try to stop a horrific force before it claims them. I put it out for free (more-or-less) on the [internet of 1997](https://www.youtube.com/watch?v=A81IwlDeV6c), and though it was never a huge success, I've always been proud of it. + +Fast forward to 2018: although I've known about the [Internet Archive's MS-DOS Software Library](https://archive.org/details/softwarelibrary_msdos_games) for some time, I'd never really thought about the specifics of how it works until I read [an article](https://news.ycombinator.com/item?id=10977424) which talked about the [Em-DOSBox project](https://github.com/dreamlayers/em-dosbox/). Em-DOSBox is a port of [DOSBox emulator](https://www.dosbox.com/) which runs in the browser via the [Emscripten JavaScript library](http://emscripten.org/). As I was reading the article, a thought struck me: could I get *CHIM* running in the browser? + +I decided it was at least worth a shot, so I began with step 1, [building Emscripten from source](https://kripken.github.io/emscripten-site/docs/getting_started/downloads.html). That went off without an issue, so I moved on to the next step, building the DOSBox JS files, and that's where I ran into my first snag: the only way I was able to get it to build was by disabling the "emterpreter sync" function (`emconfigure --disable-sync ./configure`). It complained about the lack of empterpreter sync, but it built, and that lead me to the next step, packaging the `dosbox.js` file for use in a browser via the `./packager.py` command. Even though this seemed to work great, there was obviously something wrong with my resulting files, as the JavaScript engine in my browser kept throwing an error ("missing function in Module"). After toying around with it for a while, I found that, if I used `./repackager.py` (the Emscripten-less version of the packager) to package my files, I could get an empty DOSBox window to come up, but it still wouldn't load the actual EXE. + +By this point, I was flummoxed, and was about to give up. And that's when I found the answer: [js-dos](https://js-dos.com/)! + +After 30 minutes with [this tutorial](https://js-dos.com/getting-started/) (and some source viewing on a couple of js-dos [game](https://js-dos.com/games/pac-man.exe.html) [pages](https://js-dos.com/games/doom.exe.html)), I was able to get *CHIM* working. + +But my work wasn't finished yet. Even though I'd kept nearly all of the files for *CHIM* for the last 21 years (with the exception of the game's original C++ source files, which were lost in a hard drive crash shortly after it was released), I hadn't really messed with them much in the last decade, so there was some cleaning up to be done. I updated some of the questions (and answers) in the FAQ, replaced the license, and generally tried to clean up the supporting text files. And that's when I ran into one last unexpected issue: text encoding. + +You see, I had forgotten that, when I first wrote the game and the supporting files, I had used some primitive ANSI graphic characters in an attempt to enhance the look of it. And now, when I tried to view those files on my Linux laptop, those graphics came out... weird. + +The fix was to convert the files from the "IBM-862" format to the modern UTF-8 format: + +```shell +> iconv -f IBM862 -t UTF8 INTRO.TXT -o INTRO.UTF.TXT +``` + +This allowed me to edit the files in Mousepad (and serve them up with Nginx), while still keeping the graphics intact. Finally, I added the Unicode Byte Order Mark, which makes it display correctly in the browser, even when served from a `file://` URL (you can add the BOM via Mousepad, under "Document -> Write Unicode BOM"). + +So, if you'd like to try the game out, [check it out here](/chim/index.html), and good luck - you're gonna need it! diff --git a/src/sitePosts/journal/2018/12-03-hacked.md b/src/sitePosts/journal/2018/12-03-hacked.md new file mode 100644 index 0000000..b8dae7d --- /dev/null +++ b/src/sitePosts/journal/2018/12-03-hacked.md @@ -0,0 +1,140 @@ +--- +title: Hacked!? +content_type: journal +date_pub: "2018-12-03T19:07:00-05:00" +date_upd: "2018-12-03T19:07:00-05:00" +tldr: I recently received an email telling me that I've been hacked. Since I don't believe it, I thought I'd make fun of it instead. +tags: hackers hacking email spf internet spam +--- + +A couple of weeks ago, I was lucky enough to receive an #email telling me how one of my email accounts (and the devices associated with it) had been hacked. What's more, this email appeared to be "From" the hacked accounts, a feat designed to help me understand just how serious of a threat this hacker is. + +And I do understand - they're a joke. + +Now, I am not disrespecting "real" #hackers, the kind who are perfectly capable of destroying my bank account, doxxing my children, and generally ruining my life, so please, don't take this as some kind of a challenge. Instead, I'm disrespecting a "script kiddie", someone who can't actually hack, and instead spends their time trying to fake it by scaring people who don't understand the shiny magic boxes we commonly call computers (or, more generally, "devices"). + +
    + +
    If you really wanna be a fake hacker, this book will tell you how!
    +
    + +Unfortunately for this lamer, I do understand these magic boxes enough to call their bluff, and have decided to post their weak-sauce attempt at extortion here (along with some commentary of my own). Although I've redacted the addresses that I received these messages from, I've kept most of the actual text of the messages intact, in hopes that someone searching for this text may come across this post and save themselves a truly unnecessary extortion payment. + +#### The Email + + +> From: [redacted-address]
    +> To: [redacted-address]
    +> Subject: [redacted-address] - this account has been hacked! Change all your passwords! +> +> Hello! + +Hi! + +> I have bad news for you.
    + +Uh-oh. + +> 19/07/2018 - on this day I hacked your operating system and got full access to your account [redacted-address] + +Oh, noes! You hacked my operating system to get access to my email address? + +Wait, how does **that** work? + +> It is useless to change the password, my malware intercepts it every time. + +Wow, that's some magical malware. + +> How it was:
    +> In the software of the router to which you were connected that day, there was a vulnerability.
    +> I first hacked this router and placed my malicious code on it.
    +> When you entered in the Internet, my trojan was installed on the operating system of your device. +> +> After that, I made a full dump of your disk (I have all your address book, history of viewing sites, all files, phone numbers and addresses of all your contacts). + +I've always wondered how it was, so thanks for telling me. + +By the way, I like how you use the generic term "device" - that must make it easier to mass-send bogus emails like this. I mean, which device associated with this email did you hack? + +I only ask because... well, let's not ruin the fun yet. 😉 + +> A month ago, I wanted to lock your device and ask for a small amount of money to unlock.
    +> But I looked at the sites that you regularly visit, and came to the big delight of your favorite resources.
    +> I'm talking about sites for adults. +> +> I want to say - you are a big, big pervert. You have unbridled fantasy!!! + +You know, I used to play bass for Unbridled Fantasy back in high school. + +> After that, an idea came to my mind.
    +> I made a screenshot of the intimate website where you have fun (you know what it is about, right?).
    +> After that, I made a screenshot of your joys (using the camera of your device) and joined all together.
    +> It turned out beautifully, do not doubt. + +Both my favorite intimate website and my "joys", together in one picture? I gotta see this! + +By the way, thanks for telling me how beautiful my "joys" look, it's not often that I get a complement like that. + +> I am strongly belive that you would not like to show these pictures to your relatives, friends or colleagues. + +And I am strongly belive that you're not much of a writer. Or a hacker. + +> I think $741 is a very small amount for my silence.
    +> Besides, I spent a lot of time on you! + +OK, this just got weird. + +> I accept money only in Bitcoins.
    +> My BTC wallet: 1H9bS7Zb6LEANLkM8yiF8EsoGEtMEeLFvC + +But, what if I don't know to replenish a Bitcoin wallet? + +> You do not know how to replenish a Bitcoin wallet?
    +> In any search engine write "how to send money to btc wallet".
    +> It's easier than send money to a credit card! + +I don't know, send money to a credit card is pretty easy. + +> For payment you have a little more than two days (exactly 50 hours).
    +> Do not worry, the timer will start at the moment when you open this letter. Yes, yes .. it has already started! +> +> After payment, my virus and dirty photos with you self-destruct automatically.
    +> Narrative, if I do not receive the specified amount from you, then your device will be blocked, and all your contacts will receive a photos with your "joys". + +Well, it's been over a week since I opened the "letter" (approximately 168 hours, by my math), and so far, no "joys". + +> I want you to be prudent.
    +> - Do not try to find and destroy my virus! (All your data is already uploaded to a remote server)
    +> - Do not try to contact me (this is not feasible, I sent you an email from your account)
    +> - Various security services will not help you; formatting a disk or destroying a device will not help either, since your data is already on a remote server. + +Yeah, here's the thing about the email you "sent": you didn't actually send it, you just tried to send it (and you didn't even bother to hide the source IP!), but my [email handling rules](/journal/2016/12-12-failing-me-softly.html) caught it, flagged it, and dumped it into my #spam folder, which is why it took me over a week to notice it. + +> P.S. I guarantee you that I will not disturb you again after payment, as you are not my single victim.
    +> This is a hacker code of honor. + +Well, you sure seem trustworthy, so I'm sure I can believe your "guarantee". And your haxx0r "code of honor". + +> From now on, I advise you to use good antiviruses and update them regularly (several times a day)! +> +> Don't be mad at me, everyone has their own work. + +Sure, if by "work" you mean "scaring technophobes from your parents' basement". + +> Farewell. + +Bite me, lamer. + +#### The Truth + +Now, you may be asking yourself, "how does he know that his devices haven't actually been hacked?" Well, in addition to all of the reasons raised above, there is one more I neglected to mention: the email account that this master haxx0r allegedly compromised **isn't even associated with any devices**. It's just a email address, plain and simple, and isn't used for logging into any application or device anywhere on the #internet. What's more, I've been sending out and posting resumes with this address for a few weeks now, and suspect that this is how this wannabe got their hands on it. + +So, in the end, how can one try and minimize their exposure to hacking threats (especially fake ones)? Well, IANAHOSE, but these are some of the ways that I do it: + ++ For years, I've tried to diversify my accounts, using different emails for different sites, and keeping those email addresses separate from the accounts I use on actual devices. + + To make this work, I had to buy a domain name (which costs about $10 / year) and setup a [catch-all (or "wildcard") address](https://www.namecheap.com/support/knowledgebase/article.aspx/310/2214/how-to-set-up-a-catchall-wildcard-email-address). That way, I can use anything I want for the "local-part" of the [email address](https://en.wikipedia.org/wiki/Email_address) (aka the portion before the "@" symbol), and I'll still get it at my main address (which I don't typically share). ++ Likewise, I diversify my passwords, using a different password for each site / device. The easiest way to do this is with a [good password manager](https://www.pcmag.com/article2/0,2817,2407168,00.asp). ++ I also try to keep good backups, so if my devices do get hacked, I can wipe and restore them (relatively) easily. ++ Finally, as alluded to above, I have [Sender Policy Framework (SPF)](http://www.openspf.org/) rules [setup to work with my domain](/journal/2016/12-12-failing-me-softly.html), which helps to prevent others from sending unauthorized emails from an account I own. + +Always try to remember: No matter how scary an email may look, **don't believe everything that you read**. Many (if not most) are from fakers just like this one, and are nothing more than poorly-weaponized spam. And, just like with regular spam, the only proper (and safe) way to react is to ignore it completely. diff --git a/src/sitePosts/journal/2019/03-13-wave-of-the-future.md b/src/sitePosts/journal/2019/03-13-wave-of-the-future.md new file mode 100644 index 0000000..dd4b764 --- /dev/null +++ b/src/sitePosts/journal/2019/03-13-wave-of-the-future.md @@ -0,0 +1,23 @@ +--- +title: The Wave of the Future +content_type: journal +date_pub: 2019-03-13T19:54:00-04:00 +tldr: A brief history of "The Wave of the Future". +tags: wallpaper images computers + +--- + +While watching [Weird Science](https://en.wikipedia.org/wiki/Weird_Science_(film)) for the hundredth time today, I noticed this amazing image hanging on Wyatt's wall: + +
    + +
    Catch the Wave!
    +
    + +I don't know how I've missed it all these years (although I suspect it was because I'd never watched a high-def version before). I've long been a fan of the original [Great Wave off Kanagawa](https://en.wikipedia.org/wiki/The_Great_Wave_off_Kanagawa) woodblock print, and have enjoyed the many images that [parody](https://www.reddit.com/r/GODZILLA/comments/xzi07/godzilla_in_the_great_wave_off_kanagawa/) and/or [were inspired by](http://gatherer.wizards.com/Pages/Card/Details.aspx?multiverseid=426620) it, but I'd never seen one with such a great "digital" look to it, and I was curious to find out how it came to be. + +Apparently, it was made by a design agency called [Grafik](https://grafik.agency/insight/waveofthefuture/) in 1981 for a computer trade show. The amazing thing is that, despite its appearance (and intended use), it wasn't actually computer-generated at all, and was instead created by meticulously coloring each square by hand... *with pencils*. + +"The Wave of the Future", indeed. + +Fortunately, I was able to find a larger version of it, and now, thanks to the power of the internet (and, in particular, reddit user [acoolrocket](https://www.reddit.com/user/acoolrocket)), I'm happy to have this image on my laptop as my [wallpaper](https://www.reddit.com/r/outrun/comments/agjn07/wave_of_the_future/). Too cool! diff --git a/src/sitePosts/journal/2019/11-27-hacked-again.md b/src/sitePosts/journal/2019/11-27-hacked-again.md new file mode 100644 index 0000000..bff7f74 --- /dev/null +++ b/src/sitePosts/journal/2019/11-27-hacked-again.md @@ -0,0 +1,80 @@ +--- +title: Hacked!? Again!? +content_type: journal +date_pub: 2019-11-27T18:57:00-05:00 +date_upd: 2021-07-11T22:29:00-04:00 +tldr: I've received some more emails telling me that I've been hacked. Since I still don't believe them, I thought I'd make fun of another one instead. +tags: hackers, hacking, email, internet, spam +--- + +Since my last post about [script-kiddies using spam to try and commit fake extortion](/journal/2018/12-03-hacked), I've recevived plenty of other threatenting emails from lamers, so here's another one from the (spam) vault: + +> From: [redacted-address]
    +> To: [redacted-address]
    +> Subject: Security Warning. Third party accessed to [redacted-address]. +> +> Hello! +> +> I'm is very good coder. + +Just not much of a writer, apparently. + +> I am known by my nickname finn29. + +Look, man - I've known [The Finn](http://williamgibson.wikia.com/wiki/The_Finn) since 1984. And you, sir, are not The Finn. + +> I hacked this mailbox more than six months ago,
    +> through it I infected your operating system with a virus (trojan) created by me and have been spying for you a very long time. + +Somehow, I find this hard to believe. + +> I understand it is hard to believe, but you can check it yourself.
    +> I'm sent this e-mail from your account. Try it yourself. + +No, "you're" didn't send this email from my account. In fact, if I had to guess, you tried to send it from your parents' basement (which I have the IP for, by the way), but my [SPF rules](/journal/2016/12-12-failing-me-softly.html) caught it, flagged it, and dumped it into my spam folder. As they should have. + +> Even if you changed the password after that - it does not matter, my virus intercepted all the caching data on your computer
    +> and automatically saved access for me. + +I think you've been watching too much **CSI: Cyber**. + +> I have access to all your accounts, social networks, email, browsing history.
    +> Accordingly, I have the data of all your contacts, files from your computer, photos and videos. + +Oh noes, all of the contacts stored on my computer? What is this, 1998? + +> I was most struck by the intimate content sites that you occasionally visit.
    +> You have a very wild imagination, I tell you! + +I do, actually, but not in the way you want. + +> During your pastime and entertainment there, I took screenshot through the camera of your device, synchronizing with what you are watching.
    +> Oh my god! You are so funny and excited! + +I don't even know what to say to that. + +> I think that you do not want all your contacts to get these files, right?
    +> If you are of the same opinion, then I think that $643 is quite a fair price to destroy the dirt I created. + +$600 to erase the pictures and videos you don't have? What a bargain! + +> Send the above amount on my BTC wallet (bitcoin): 19kXyFbvetft819v4QV5g9vzrjwNqRtvgA
    +> As soon as the above amount is received, I guarantee that the data will be deleted, I do not need it. + +Well, you seem trustworthy, so I'm sure I can believe your "guarantee". + +> Otherwise, these files and history of visiting sites will get all your contacts from your device.
    +> Also, I'll send to everyone your contact access to your email and access logs, I have carefully saved it! + +I've spent the last 10 minutes trying to figure out what he's saying here, but I just can't make sense of it. + +> Since reading this letter you have 48 hours!
    +> After your reading this message, I'll receive an automatic notification that you have seen the letter. + +Doubtful, since it's now been 96 hours since you sent the message, and my contacts still haven't received anything from you. I mean, me. Whatever. + +> I hope I taught you a good lesson.
    +> Do not be so nonchalant, please visit only to proven resources, and don't enter your passwords anywhere!
    +> Good luck! + +Indeed, you have taught me a lesson: how not to extort money from someone. diff --git a/src/sitePosts/journal/2021/07-10-hacked-wall-of-shame.md b/src/sitePosts/journal/2021/07-10-hacked-wall-of-shame.md new file mode 100644 index 0000000..c044c32 --- /dev/null +++ b/src/sitePosts/journal/2021/07-10-hacked-wall-of-shame.md @@ -0,0 +1,91 @@ +--- +title: Hacked - Extortion Wall of Shame +content_type: journal +date_pub: 2021-07-10T23:13:00-04:00 +date_upd: 2022-01-18T01:07:00-05:00 +tldr: I've received even more emails telling me that I've been hacked. Since I still don't believe their empty threats, I'm posting their bitcoin addresses. +tags: hackers, hacking, email, internet, spam +--- + +Since my last few posts about script-kiddies and the [fake extortions](/journal/2018/12-03-hacked) [they try to commit](/journal/2019/11-27-hacked-again), I've received upwards of 50 such emails, each with a different bitcoin address, and many with slight differences in text, style, or form, but all basically the same: an email from myself (*gasp*) claiming that I have been hacked, that some non-descript OS or "device" I own has some magical virus installed on it, and that, if I don't pay the hacker a ransom in bitcoin, my life will be *ruined*. + +However, I know from past experience that these messages are little more than spam, sent out en masse in hopes that they can rope in some poor sucker who falls for this. I know most of these are bogus from the beginning because the email I use for my phone is completely unrelated to the ones that keep receiving these messages. Other times, the email will make vague references to programs I don't even have installed, again betraying their carboon-copied nature. In truth, I have never paid ransom, even though I've personally received dozens of these messages, and my life has yet to be ruined by these *lamers*. + +So, as a public service, I have included the bitcoin addresses for these fakers, in hopes that some other would-be victim finds this page (possibly through a web search), and they learn that they can ignore this BS as well: + +``` + +====== BEGIN WALL OF SHAME ====== +====== UPDATED: 2022-03-17 ====== + +1GjZSJnpU4AfTS8vmre6rx7eQgeMUq8VYr +18eBGkYam1wjz1S77jz3VmADuYYFzhA3vB +376XVFQ2GDHow9kBDJ49Q3vRW7TC35L2Hx +142e8SgyTLnkvwkDkNNon9jMtKY4UDvQqr +14aFMWfDdBW9FpWxu8myFsXY7Pfy9fBp5C +17qQSJatXXj5DnjMLjNGXx9BT7NUhqimRx +1JRfE57ZF8Eaqa7DktHmVCoAneA8q4fpP2 +17hMTFUWqa1oHKj7PHA361qjpZoBaChTWY +15tGbgpiksnzBY1tef2LgUbJ9pZvoDjCbs +1HUHBgNHYCz9Djy9z615adkgd2NYQNMVUd +1C242L8qAXRxudv6KBAahi81GHS5wpc8cF +1GRHyZf18sQ65CdG66YCYs7vhrzUEV1HVs +1LAWGnA2K5njVSshERU9bcUSrW2YWwtXs1 +1MZsUfERBoQp6PJW4Gcx9PvgH2S6WcLiyv +1PLfzxybxkTKbcxRwhRw23TxcYDJ9wsphS +13rkwLUVuWeLtnB1JdxJGo4vin15V2poS5 +1Hxkqd6fib8ZrXyYj2iqQVfDxw8vjrc1aA +14qpWY7GxcimEVbPe7x6vnbV6qDaALr7Nb +1Cboy74YFQy1pLJTRrnibYfqiVo3FXv9fe +1QEkESQ8xR13P54vt8QKBHvhKjkrCBybzk +163qcNngcPxk7njkBGU3GGtxdhi74ycqzk +1GoWy5yMzh3XXBiYxLU9tKCBMgibpznGio +1Je9xULKJK191a1JV68QuMiPgHJduSpYf6 +34ZQ4zk5ep53LdTdsikrKBVn2egPa7N1NA +3MmuobsivmP6SBwdX9b2X4vs8SKBrLvRFt +14DvFghvkzQujf5Kd5AL2VKjxaYm5KidxR +14tfS3yWL2cABhXVJZ97XRhuDXC69aWH6Y +1FzjogU6vMPcJAsTgc7Fw7tMu7nmwom6QD +1CHXVoouz5b8YykXr6T1t5y4rv6enPLKjS +16j8quu5c51swAN6QUdeMEcSidxD4JdtoS +19Vok4UYuig3XC9ixoASteqXUvB378qAUR +1DEjEBAsw7rLaKnKj2mthpwPDXy6f6rXMh +15iiic5PmfGvE3TyMP1JyYh1W9KxQLGQL6 +1DDRvdiUZMeF9c4zjMLHWvacJYhPcbzumf +15pY2U8WBZBJRVxGhh8WRXsdkXQbMKD8k9 +1FQBA6LYwjFYfSgrHTwizV6aLPUuG3cMBa +1KiY2X9tww3zDgZmuoFRvZ7ssWx1b4moC9 +1H1K8MfLEJgjCCfDEkTJmv9GJjD3XzEFGR +163qcNngcPxk7njkBGU3GGtxdhi74ycqzk +3616S7LW7c4rPpoS44eAb74gVvcY1nHo2w +18js3UK28bD11rwP1RJPjZUT93z3s3s77k +1K5gLeGFrhbsKXBQQK23TPGfqrAwgqgPkC +ο»Ώ3Npm2ipM11TYyMymJhMW3jhmMVR91fNaod +14LYbckmC9gKJ6LR1JAWaKSsCojZfURbzH +1KE1EqyKLPzLWQ3BhRz2g1MHh5nws2TRk (sic) +36QKFL786hVNqEfkPHqvu47ZvzkXrokPSK +3KAjh4JnH2eWo7yXkMMXz5Nnf4mr13RNpr +1Ji2K8EVzxDRnpuXts1kKAjMwTrV2LTnRS +18i5utJSShwVTGdtSrmi2M3XpyRBfnpdPw +3JRHity7zbykme4uriFnroxWj0VhML780lhIC9taBjdmYd5LcVIy9N1P8UeSn1F9pAYfKV59ET0RyoiJgxWucM +MBV4M5vH2W519JEJ9T4yvqVhNaaYECxaTS +35xURRetkiCKCZNjWtlJ21sm3dWxmV48cKtIV1ygfJU7thXjc1r +1KVX9hCnQ9MfSoEFyxqAXGFXdTFNyzD22n +1KJ3ZrhrkXBVjGyAU635sapjLpLSFgpqYe +342yJ6g29rQQVehf1nbPX5UDquKUSKw4ev +19p63VSjmRLPNP34ASWPEixUDYhvGQxTFK +17z8ACS2tJouyxuoqEBoDDmaEZzFTzQg1Z +17cPvTgQ4vsG9D6iZqTL3JChjd8ApFYTPA +12ELWfXgRgqhtt8KenQbAfuBbAb1Rd3GJ7 +19PRxthVN1P9hsXcStqc2Kp8Yy4hXyXVau +1BwDYXp1YCa2NLfGiF5Gfnkmgf61MqupHb +15KquhG7RGkyXvEVT1aXLgPt4qgBEVe8rN +bc1qznsh6ahq9h05pgekemygh7mdvc4egkvfvf3ltc +19Ya5oeV6zqsHa9TSyurpeF1LpYJqm84Yv +15DMMwLTqV4RmYpJZDoNUZvzNikX1m6j4R +bc1q4s9vnxa7a008rxcuus0fqk94dyc0r2z88cs6c4 + +======= END WALL OF SHAME ======= + +``` +Again, if you received an ominous email about your device being hacked and it uses one of these bitcoin addresses, just know that I received one of those messages, too, and I never paid. Since I'm still here, posting this, obviously none of their doomsday prophecies came to pass - no mass email to my contacts, no embarassing footage, no ruined life... and no hacked device. diff --git a/src/sitePosts/journal/2022/07-21-hello-again.md b/src/sitePosts/journal/2022/07-21-hello-again.md new file mode 100644 index 0000000..091b674 --- /dev/null +++ b/src/sitePosts/journal/2022/07-21-hello-again.md @@ -0,0 +1,39 @@ +--- +title: Web Site Re-Re-Re-Relaunch! +content_type: journal +date_pub: 2022-07-21T00:59:00-04:00 +description: Website maintenance navel-gazing. +tags: blogging web meta +--- + +Greetings, and welcome the bi-annual tri-annual periodic relaunch of my website! + +Yes, after a few years of neglect, I finally got around to updating it again. + +Like the last few versions, it's mostly a static site generated by Javascript. The biggest change with this iteration is the lack of a central library for doing all of the heavy-lifting. No more [harp](https://harpjs.com/) or [gulp](https://gulpjs.com/) - instead, I'm using a hodge-podge of different, smaller libraries (like [ejs](https://github.com/mde/ejs) and [front-matter](https://github.com/jxson/front-matter)) which I string together via a series of fairly short js files, (mostly) all using modern `async` and `await` code to do things in the right order. + +The end result is that it's _bad fast_, taking the build time down from 10+ seconds to under 2 (although that may not be a fair comparison, as it doesn't do _everything_ the gulp version did... yet). + +Some of the biggest changes under the hood: + +- I replaced [marked](https://marked.js.org/) and [commonmark.js](https://github.com/commonmark/commonmark.js) with the better fit (for me) [markdown-it](https://github.com/markdown-it/markdown-it#readme), +- I simplified many of my templates, purging a number of unneeded partials, +- I made each journal entry link to the two chronologically-nearest entires, +- I upgraded most of my config files to use [json5](https://github.com/json5/json5) (the self-proclaimed "JSON for Humans"), and +- I added a [now page](/now.html) (inspired by [nownownow.com](https://nownownow.com/about)). + +Once I get the source code cleaned up a bit more, I'll post it in a public git repo. + +I've got some more ideas for what to do next, like adding in-browser file editing, a homespun blogging engine, and expanded IndieWeb support (most likely via the IndieKit project) with an eye towards IndieAuth, MicroPub, and WebSub. + +It's all part of my (continuing) attempt to rest control back of my social-media-life from the corporate silos. + +Along the way, I hope to grow the content-side of this web presence as well, so keep on the lookout for more new stuff, like: + +- notes from my various RPG campaigns, +- homebrew for D&D and OSR games, +- my custom Magic cards, +- some hardware stuff I've been playing with, +- and a whole lot more! + +Thanks for stopping by! diff --git a/src/sitePosts/journal/2022/08-18-killing-thur.md b/src/sitePosts/journal/2022/08-18-killing-thur.md new file mode 100644 index 0000000..f636c10 --- /dev/null +++ b/src/sitePosts/journal/2022/08-18-killing-thur.md @@ -0,0 +1,25 @@ +--- +title: Killing Thur +content_type: journal +date_pub: 2022-08-18T00:49:00-04:00 +description: I've removed the "Thur" section of the website because I'm ashamed of some parts of it. +tags: blogging web meta +--- + +After hosting it here for the better part of a decade, I've decided to remove my RPG, **Thur**, from this site. + +**Thur** was an RPG that I ran while I was in college, a custom system set on a world of my own design, full of all of the stuff that I thought was cool at the time (and still do, for the most part): Fremen, ninjas, Gunslingers, psychics, wizards, aliens, mutants, technomages, tears in the space-time continuum, a global economy (and shared culture) based on huge teleportation gates - all kinds of gonzo stuff. + +I ran several adventures as 1-on-1 games with a former friend of mine, and ran a couple of sessions other friends, but eventually the demands of full-time work and parenting didn't leave me with much RPG time, so I shelved it. I pulled it out about a decade ago when a friend was getting into Pathfinder. We played a couple of sessions, and that was when I published it here. However, since the rules were never really fully fleshed-out (and thanks to some bad writing on my part), the game fell kinda flat, and so was shelved again, where it's remained since. + +So, what changed? A few things. + +As I said before, the rules were a hot mess, with the magic system in particular in shambles. Incomplete as it was, I probably should never have published it here in the first place. + +Additionally, my thinking on rules has evolved over the years. I'm now much more interested in simpler systems that don't systematize flavor (thus leaving more of room for roleplaying). I'm also more into tweaking existing rulesets over building entirely new ones, since it's easier to introduce new players (and bring back old ones). + +But honestly, the main reason I took it down is because I'm genuinely ashamed of some of what's there. The version of me that wrote most of that was younger, dumber, and had a far-simpler (and naively incorrect) conception of the world at large. He was also far more casually racist, and for that, I am truly sorry. + +So, I took it down. + +It may come back, it may not. If it does, it'll probably be in a very different format from what it was before, like an online zine for OSE (so others can play), but that won't happen until after I've made it into something I can be proud of. diff --git a/src/sitePosts/journal/2022/09-18-magical-updates.md b/src/sitePosts/journal/2022/09-18-magical-updates.md new file mode 100644 index 0000000..72af606 --- /dev/null +++ b/src/sitePosts/journal/2022/09-18-magical-updates.md @@ -0,0 +1,22 @@ +--- +title: Site Updates - Now with More Magic and LibreJS Validation! +content_type: journal +date_pub: 2022-09-18T11:48:00-04:00 +description: I added some new content (including custom Magic and Illuminati cards, and an expanded blogroll) and did some JS housecleaning. +tags: blogging FreeSoftwareWin meta web +--- + +A couple of website updates to announce: + +- I added a bunch of [custom (unofficial) cards I've made](/magic-cards/index.html) over the years for my personal paper-crack, [Magic: the Gathering](https://magic.wizards.com/en). +- I also added some [custom Illuminati groups that I designed](/games/illuminati/index.html) a few years ago. +- I added a new [LinkList for Tabletop Role-Playing Game Resources](/linklists/tabletop_rpg). +- I expanded the [blogroll](/linklists/blogroll/index.html) to include more sites I like to read (plus some vlogs). +- I updated the tags throughout the site to be links. +- Finally, I fixed the JS on the client side, so that things like relative timestamps and reading time _should_ work again. + +While I was fixing the client code, I went and disabled my (already broken) concatentation and minification script, opting instead to serve up all 8(!) JS library files individually (and, thanks to [HTTP/2](https://en.wikipedia.org/wiki/HTTP/2), concurrently) + +I mean, I'm using minification for the libraries I'm importing (I'm not a monster), but I don't use it for the (small) bit of code that ties those libraries together and makes the site work. This way, anyone can see how (and why) the site works the way it does, [as it should be](/journal/2015/03-18-developing-the-web.html), and all without the added complexity of generating source maps or similar unnecessary complications. + +And for those minified libraries, I've provided a link to each library's repo and added automated license info, so the [LibreJS validator](https://www.gnu.org/software/librejs/) gives this site a ✅. #FreeSoftwareWin! diff --git a/src/support/_sitemap.ejs.broken b/src/support/_sitemap.ejs.broken new file mode 100644 index 0000000..40c60fc --- /dev/null +++ b/src/support/_sitemap.ejs.broken @@ -0,0 +1,83 @@ +<% + /* + Not sure it's worth the effort for this ATM. + */ + + var + generateSitemapList = function(the_head, the_tail) { + var + sortForIndex = function(a,b) { + if (a === 'index.html' || ab) { + return 1; + } + return 0; + }, + filter = /(\.html$)/, + replace = /(\.html$)|(^index\.html$)/, + tree = function (head, tail) { + var + output = '', + tree_output = '', + data, content; + for (var key in head) { + var + val = head[key]; + if (key !== '.git') { + if (key == '_data') { + data = val; + } else if (key == '_contents') { + content = val; + } else { + tree_output += tree(val, tail + key + "/"); + } + } + } + + if (content && data) { + content + .sort(sortForIndex) + .forEach (function(file) { + var + slug = file.replace(filter, ""), + file_data = data && data[slug] ? data[slug] : {}, + now = new Date(), + show_item = false, + title, date; + if (filter.test(file)) { + show_item = true; + if (file_data) { + var + is_draft = file_data.is_draft || false, + is_sys_file = file_data.is_sys_file || false, + title = (file_data.title || '').trim(); + if (is_draft || is_sys_file || title === '') { + show_item = false; + } else { + date = file_data.date_last_mod ? new Date(file_data.date_last_mod) : ''; + date = date !== '' && file_data.date_pub ? new Date(file_data.date_pub) : ''; + if ((date && date.getTime() > now.getTime())) { + show_item = false; + } + } + } + } + if (show_item) { + output += + (file === 'index.html' ? '\n'; + } + return output + tree_output; + }; + return tree(the_head, the_tail); + }; +%> +

    Site Map

    +
      + <%- generateSitemapList(public, "/") %> +
    diff --git a/src/support/browserconfig.xml.ejs b/src/support/browserconfig.xml.ejs new file mode 100644 index 0000000..794ae8d --- /dev/null +++ b/src/support/browserconfig.xml.ejs @@ -0,0 +1,2 @@ + +#9aa8bc diff --git a/src/support/errors/404.html.ejs b/src/support/errors/404.html.ejs new file mode 100644 index 0000000..1ff9991 --- /dev/null +++ b/src/support/errors/404.html.ejs @@ -0,0 +1,84 @@ + + + + + It's Eric Woodward! (dotcom) | Page Not Found + + + +
    +

    Page Not Found

    +

    Sorry, but the page you were trying to view does not exist.

    +

    It looks like this was the result of either:

    + +

    You can go back and try again, or just start over at It's Eric Woodward's front page.

    +
    + + + + + + + + +

    Powered by DuckDuckGo

    +
    +
    + + diff --git a/src/support/errors/offline.ejs.off b/src/support/errors/offline.ejs.off new file mode 100644 index 0000000..198c72c --- /dev/null +++ b/src/support/errors/offline.ejs.off @@ -0,0 +1,9 @@ +<% + var + title = "Offline", + text = [ + '

    Sorry, but you are currently offline, and don't have that page in your cache.

    ', + '

    You should still be able to go to any page you've already visited (just not this one, apparently).

    ' + ].join('\n'); +-%> +<%- partial("_error_page", {title: title, text: text, show_search: false}) %> diff --git a/src/support/feed.json.ejs b/src/support/feed.json.ejs new file mode 100644 index 0000000..630d785 --- /dev/null +++ b/src/support/feed.json.ejs @@ -0,0 +1,68 @@ +<% + // There's an issue here with trailing commas. + // A better solution would probably be to pull the data in I need, build an object, and then dump it via JSON.stringify() + // reference: https://jsonfeed.org/version/1.1 + + const + + prependSlash = (pagePath) => `${pagePath.indexOf('/') === 0 ? '' : '/'}${pagePath}`, + + { author, copyright, language, tags } = site, + + feedData = { + version: 'https://jsonfeed.org/version/1.1', + title: site.title, + home_page_url: `${site.uri}`, + feed_url: `${site.uri}/feed.json`, + authors: [], + items: [], + }; + + if (author) { + + const { name, email, photo, site: aSite } = author || {}; + const newAuthor = {}; + + if (email) newAuthor.email = email; + if (name) newAuthor.name = name; + if (photo) newAuthor.photo = `${site.uri}${photo}`; + if (aSite) newAuthor.site = aSite; + + feedData.authors.push(newAuthor); + + } + + if (Array.isArray(site?.pages)) { + + feedData.items.push(...site.pages + .sort((p1, p2) => { + + const p1Date = new Date(p1.date_upd || p1.date_pub); + const p2Date = new Date(p2.date_upd || p2.date_pub); + + return p2Date - p1Date; + + }) + .map((page) => { + + const { body, content, date_pub, date_upd, description, path, tags } = page || {}; + const p = { + id: `${site.uri}${prependSlash(path)}`, + url: `${site.uri}${prependSlash(path)}`, + }; + + if (body) p.content_text = body; + if (content) p.content_html = content; + if (date_pub) p.date_published = date_pub; + if (date_upd) p.date_modified = date_upd; + if (description) p.summary = description; + if (Array.isArray(tags)) p.tags = tags; + + return { ...p }; + + }) + ); + + } +-%> +<%- JSON.stringify(feedData, null, 2) -%> \ No newline at end of file diff --git a/src/support/feed.xml.ejs b/src/support/feed.xml.ejs new file mode 100644 index 0000000..59a1a03 --- /dev/null +++ b/src/support/feed.xml.ejs @@ -0,0 +1,73 @@ + + +<%- include('../layouts/functions') -%> +<% + // validator: https://validator.w3.org/feed/#validate_by_input + const { author, copyright, language, tags } = site; +-%> + + + + <%- site.title %> + + <%- (new Date()).toJSON() -%> + <%- site.uri %> + + + <% if (author.name) { -%> + <%- author.name %> + <% } -%> + <% if (author.email) { -%> + <%- author.email %> + <% } -%> + <% if (author.site) { -%> + <%- author.site %> + <% } -%> + + + + <% if (copyright) { -%> + <%= copyright %> + <% } -%> + <% if (author.photo) { -%> + <%= author.photo %> + <% } -%> + ItsEricWoodward.com + + <% + if (typeof tags === 'string') { + const keywords = tags.split(/\W+/); + for (var i=0; i < keywords.length; i++) { + if (keywords[i]) { + -%> + <%= keywords[i] %> + <% + } + } + } + -%> + + <% if (site && Array.isArray(site.pages)) { + site.pages + .sort((p1, p2) => { + const p1Date = new Date(p1.date_upd || p1.date_pub); + const p2Date = new Date(p2.date_upd || p2.date_pub); + return p2Date - p1Date; + }) + .forEach((page) => { -%> + + + <%= page.title %> + <%- site.uri %><%- page.path %> + + <%= (new Date(page.date_upd || page.date_pub)).toJSON() %> + <% if (page.description) { -%> + <%= page.description %> + <% } -%> + + + <% }); + } -%> + + + diff --git a/src/support/journal/index.html.ejs b/src/support/journal/index.html.ejs new file mode 100644 index 0000000..dfd206b --- /dev/null +++ b/src/support/journal/index.html.ejs @@ -0,0 +1,192 @@ +--- +title: Eric's Journal +path: /journal/index.html +--- +<% const MAX_POSTS = 6; -%> +<% const cwd = (process && process.cwd) ? process.cwd() : ''; -%> +<% const titleLink = (site && site.base_uri) ? site.base_uri : '/'; -%> +<%- include('../../layouts/partials/top') %> + + +
    + + +
    +
    + + <%- include('../../layouts/partials/embed_switch') %> + + <%- include('../../layouts/functions') %> + + <% if (page?.title && (page?.render_opts || '').indexOf('no_title') == -1) { -%> + +

    + <%= page.title %> +

    + +

    + Below you'll find some of my most recent Journal entries. +

    + +
    + +

    + + <% } -%> + <% if (site && site.pages) { -%> + <% + let + curr_post_num = 0, + pages = site.pages.sort((a, b) => { + if (a.date_pub && b.date_pub) { + let + a_dt = (new Date(a.date_pub)).getTime(), + b_dt = (new Date(b.date_pub)).getTime(); + if (a_dt < b_dt) { + return 1; + } + if (b_dt < a_dt) { + return -1; + } + return 0; + } + }); + -%> + + <% pages.forEach(function(page) { -%> + <% if (page.content_type && page.content_type === 'journal' && curr_post_num < MAX_POSTS) { -%> + <% curr_post_num++; -%> +

    +
    + <% if (page.author && page.author.site && page.author.name) { %> + <% if (page.author.photo) { %> + + <% } %> + + <% } else if (site.author && site.author.site && site.author.name) { %> + <% if (site.author.photo) { %> + + <% } %> + + <% } %> +
    + +

    + <%= page.title %> +

    + + <% if (page.tldr || page.description) { -%> +

    TL;DR — <%- page.tldr || page.description %>

    + <% } -%> + + <% if (page.readTime) { -%> +

    + 👓 <%= page.readTime %> +

    + <% } -%> + + <% if (page.content) { -%> +
    + <%- page.content %> +
    + <% } -%> + +
    + + <% if (Array.isArray(page?.tags) && page.tags.length) { -%> + +
    + + 📁 + + <% page.tags.forEach((tag, index) => { -%> + <%= tag %><%= (index < (page.tags.length - 1)) ? ', ' : '' %> + <% }) -%> + +
    + + <% } -%> + + + + + + + +
    + +
    + + +
    + + <% } -%> + <% }); -%> + <% } -%> +
    + +
    +

    + All Entries By Year +

    +
      + <% + if (site && site.pages) { + let + years = []; + site.pages.forEach(function(page) { + if (page.content_type && page.content_type === 'journal' && page.date_pub) { + let the_year = (new Date(page.date_pub)).getFullYear(); + if (years.indexOf(the_year) === -1) { + years.push(the_year); + } + } + }); + years = years.sort().reverse(); + years.forEach((year) => { + -%> +
    • + + <%= year %> + +
    • + + <% + }) + } + -%> + +
    +
    +
    + + <%- include('../../layouts/partials/journal/menusub') %> + + <%- include('../../layouts/partials/bio') %> + + <%- include('../../layouts/partials/footer') %> + +
    + +<%- include('../../layouts/partials/bottom') %> diff --git a/src/support/manifest.json.ejs b/src/support/manifest.json.ejs new file mode 100644 index 0000000..9d001ad --- /dev/null +++ b/src/support/manifest.json.ejs @@ -0,0 +1,41 @@ +{ + "name": "App", + "icons": [ + { + "src": "\/images\/favicons\/android-icon-36x36.png", + "sizes": "36x36", + "type": "image\/png", + "density": "0.75" + }, + { + "src": "\/images\/favicons\/android-icon-48x48.png", + "sizes": "48x48", + "type": "image\/png", + "density": "1.0" + }, + { + "src": "\/images\/favicons\/android-icon-72x72.png", + "sizes": "72x72", + "type": "image\/png", + "density": "1.5" + }, + { + "src": "\/images\/favicons\/android-icon-96x96.png", + "sizes": "96x96", + "type": "image\/png", + "density": "2.0" + }, + { + "src": "\/images\/favicons\/android-icon-144x144.png", + "sizes": "144x144", + "type": "image\/png", + "density": "3.0" + }, + { + "src": "\/images\/favicons\/android-icon-192x192.png", + "sizes": "192x192", + "type": "image\/png", + "density": "4.0" + } + ] +} diff --git a/src/support/opensearch.xml.ejs b/src/support/opensearch.xml.ejs new file mode 100644 index 0000000..bdedef8 --- /dev/null +++ b/src/support/opensearch.xml.ejs @@ -0,0 +1,13 @@ +<% + var + uri = (site.base_uri || '').replace(/^https?:\/\//, ''); +-%> + + + itsericwoodward.com + Search itsericwoodward.com + UTF-8 + + diff --git a/src/support/robots.txt.ejs b/src/support/robots.txt.ejs new file mode 100644 index 0000000..93abf99 --- /dev/null +++ b/src/support/robots.txt.ejs @@ -0,0 +1,2 @@ +User-agent: * +Disallow: /.well-known/ diff --git a/src/support/root/index.html.ejs b/src/support/root/index.html.ejs new file mode 100644 index 0000000..501dbbe --- /dev/null +++ b/src/support/root/index.html.ejs @@ -0,0 +1,306 @@ + + + + + + + + + + + + + <%= site.title %> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + +
    + +

    + My name is Eric Woodward, and I am a + geek, + coder, + gamer, + tinkerer, + husband, + father, + server admin, + web developer, + and American + cyborg, + though not necessarily in that order. +

    + +

    You can find out more + about me by + checking out + my website + or perusing + my code. + If you want to reach me, you can send me an Email, + + or you can find me on + LinkedIn, + GitHub, or + BoardGameGeek. + Alternatively, you can grab my + vCard and add me to your address book. +

    +

    + ← + An IndieWeb Webring πŸ•ΈπŸ’ + β†’ +

    +
    +
    + + diff --git a/src/support/sitemap-v2.xml.ejs.broken b/src/support/sitemap-v2.xml.ejs.broken new file mode 100644 index 0000000..5f3b5fa --- /dev/null +++ b/src/support/sitemap-v2.xml.ejs.broken @@ -0,0 +1,77 @@ +<% + /* + This is broken too, adds an unnecessary "undefine" to output. + */ + + var + generateSitemapXML = function(the_head, the_tail, the_base) { + var + filter = /(\.html$)/, + replace = /(\.html$)|(^index\.html$)/, + tree = function (head, tail, base) { + var + output = '', + tree_output = '', + data, content; + for (var key in head) { + var + val = head[key]; + if (key && val && key !== '.git') { + if (key == '_data') { + data = val; + } else if (key == '_contents') { + content = val; + } else { + tree_output += tree(val, tail + key + "/", base); + } + } + } + + if (content) { + for (var i in content) { + var + file = content[i], + slug = file.replace(filter, ""), + file_data = data && data[slug] ? data[slug] : {}, + now = new Date(), + show_item = false, + upd_date; + if (filter.test(file)) { + show_item = true; + if (file_data) { + var + is_draft = file_data.is_draft || false, + is_sys_file = file_data.is_sys_file || false, + title = (file_data.title || '').trim(); + if (is_draft || is_sys_file || title === '') { + show_item = false; + } else { + upd_date = file_data.date_last_mod ? new Date(file_data.date_last_mod) : ''; + upd_date = upd_date !== '' && file_data.date_pub ? new Date(file_data.date_pub) : ''; + if ((upd_date && upd_date.getTime() > now.getTime())) { + show_item = false; + } + } + } else { + show_item = false; + } + } + if (show_item) { + output += + '\n\n ' + the_base + tail + file + '\n' + + (upd_date ? '\n ' + upd_date.toUTCString() + '' : '') + '\n'; + } + } + return output + (['','undefined'].indexOf(tree_output.trim()) == -1 ? tree_output : ''); + } + }; + return tree(the_head, the_tail, the_base) + .replace('undefined', ''); // hack, not sure where the extra "undefined" is coming from. TODO: Fix this + } +-%> + + + <%- generateSitemapXML(public, "/", site.uri.production) %> + diff --git a/src/support/sitemap.html.ejs.off b/src/support/sitemap.html.ejs.off new file mode 100644 index 0000000..b0c72f3 --- /dev/null +++ b/src/support/sitemap.html.ejs.off @@ -0,0 +1,62 @@ +<% + var + generateSitemapList = function(the_head, the_tail) { + var + filter = /(\.html$)/, + replace = /(\.html$)|(^index\.html$)/, + tree = function (head, tail) { + var + output = '', + tree_output = '', + data, content; + for (var key in head) { + var + val = head[key]; + if (key !== '.git') { + if (key == '_data') { + data = val; + } else if (key == '_contents') { + content = val; + } else { + tree_output += tree(val, tail + key + "/"); + } + } + } + + if (content && data) { + for (var i in content) { + var + file = content[i], + slug = file.replace(replace, ""), + file_data = data && data[slug] ? data[slug] : {}, + now = new Date(), + show_item = false, + title, date; + if (filter.test(file) && !(/^404\.html/).test(file)) { + show_item = true; + if (file_data) { + var is_draft = file_data.is_draft || false; + date = file_data.date_pub ? new Date(file_data.date_pub) : ''; + title = file_data.title || ''; + if (is_draft || title === '' || (date && date.getTime() > now.getTime())) { + show_item = false; + } + } + } + if (show_item) { +// file = file.replace(replace, ""); + output += + '\n
  • ' + title + '
  • \n'; + } + } + } + return output + tree_output; + }; + return tree(the_head, the_tail); + }; +%> + + + <%- generateSitemapList(public, "/") %> + + diff --git a/src/support/sitemap.xml.ejs b/src/support/sitemap.xml.ejs new file mode 100644 index 0000000..374dd9d --- /dev/null +++ b/src/support/sitemap.xml.ejs @@ -0,0 +1,16 @@ + +<%- include('../layouts/functions') -%> + + + <% if (site && Array.isArray(site.pages)) { + site.pages + .sort(sortByPath) + .forEach((page) => { -%> + + <%= page.path %> + <%= (new Date(page.date_upd || page.date_pub)).toJSON() %> + + <% }); + } -%> + +