-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(global): init project with groundwork
- Loading branch information
Showing
19 changed files
with
1,878 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules/ | ||
dist/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,36 @@ | ||
# error-pages | ||
HTTP Error Pages | ||
## Custom HTTP Error Pages | ||
|
||
Lightweight tool to create own static HTTP Error Pages in minimalistic responsive and accessible design features and customization support including localization. | ||
|
||
# Features | ||
|
||
* Static pages with simple design | ||
* Lightweight and fast running | ||
* Extensibility | ||
* Customization | ||
* Localization (i18n) | ||
* Accessibility (a11y) | ||
* Built-in web-server config generator (Nginx) | ||
|
||
|
||
# How to use | ||
|
||
Requirements: installed Node.js 11+ | ||
|
||
1. Checkout this repository to your local machine | ||
2. Run `npm i` command to install dependencies | ||
3. Run `npm run build` command to compile error pages and config | ||
4. Copy static html-files from `dist` directory to your server | ||
5. Copy and apply config snippet from `dist` to your web-server configuration | ||
|
||
|
||
# How to improve default pages | ||
|
||
* *Extensibility* A new pages can be added by adding new json-files in `scr/<locale>` directory. The page name must follow to format `<HTTP-code>.json` (`<HTTP-code>` is Number, related to specific HTTP status code). You can put any additional data to json-files, that you want to display on a page. In case of common variables, you can use `common.json` file to define them. | ||
* *Customization* By editing default theme you can add anything you want. In case if you want to have own page desing, you can create a new theme and apply it by editing `config.json` file. All assets (images, fonts, etc) must be placed to `assets` directory. By default [mustache.js](https://www.npmjs.com/package/mustache) is used as a template engine and [Tailwind](https://tailwindcss.com/) as a CSS framework. Entry point of Tailwind styles must be located in `themes/<name>/assets/css/main.tcss` file. Custom Tailwind theme settings can be added to `theme.tailwind.config.js` file located in a root of theme directory. Also Tailwind can be disabled by editing `tailwind` option in `config.js`. | ||
* *Localization* If you need to change default text messages, then you can simply edit existing files in`src/<locale>` directory according to your needs. If you want to create your own localization, just simply add new locale directory and create set of source files. After new locale adding, change `locale` property in `config.json` file, located in a root. | ||
|
||
|
||
# Contributing | ||
|
||
You are very welcome to contribute into this project with improvements, localizations, bug fixes and so on. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"tailwind": true, | ||
"theme": "minimalistic", | ||
"locale": "en" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
import { promisify } from 'util'; | ||
import { exec } from 'child_process'; | ||
import { access, cp, readFile, readdir, rm, mkdir, writeFile } from 'fs/promises'; | ||
import { render } from 'mustache'; | ||
|
||
import { DEFAULTS, SRC_CODE_PATTERN, TAILWIND_STYLE } from './lib/constants'; | ||
import { Config, SatusCode, TemplateVariables } from "./lib/interfaces"; | ||
|
||
async function compile(config: Config) { | ||
try { | ||
let vars: TemplateVariables = { | ||
locale: config.locale, | ||
}; | ||
|
||
const template = await readFile(`${DEFAULTS.THEMES}/${config.theme}/template.html`).then(String); | ||
|
||
const codesVars = new Map<SatusCode, TemplateVariables>(); | ||
await readdir(`${DEFAULTS.SRC}/${config.locale}/`) | ||
.then(files => { | ||
return Promise.all( | ||
files.map(async (file) => { | ||
const srcVars: TemplateVariables = await readJson(`${DEFAULTS.SRC}/${config.locale}/${file}`); | ||
const match = file.match(SRC_CODE_PATTERN); | ||
if (match) { | ||
codesVars.set(Number(match[0]), srcVars); | ||
} | ||
else { | ||
vars = {...vars, ...srcVars}; | ||
} | ||
}) | ||
) | ||
}) | ||
|
||
if (codesVars.size > 0) { | ||
await Promise.all( | ||
Array.from(codesVars).map( | ||
([code, codeVars]) => renderPage(template, {...vars, ...codeVars, code}) | ||
) | ||
); | ||
|
||
console.log(`INFO: ${codesVars.size} pages was successfully created`); | ||
} | ||
else { | ||
throw new Error('No source data to render error pages'); | ||
} | ||
} catch (err) { | ||
throw err; | ||
} | ||
} | ||
|
||
async function execTailwind(config: Config) { | ||
try { | ||
if (config.tailwind) { | ||
const input = `${DEFAULTS.THEMES}/${config.theme}/assets/css/${DEFAULTS.TAILWIND_ENTRY}`; | ||
const output = `${DEFAULTS.DIST}/${config.locale}/assets/css/${DEFAULTS.TAILWIND_ENTRY.replace('.tcss', '.css')}`; | ||
const cmd = `INPUT="${input}" OUTPUT="${output}" npm run build:tailwind`; | ||
|
||
console.log(`INFO: build Tailwind CSS styles`); | ||
console.log(`INFO: run '${cmd}'`); | ||
|
||
await promisify(exec)(cmd).then(() => { | ||
console.log(`INFO: Tailwind CSS styles were built`); | ||
}); | ||
} | ||
else { | ||
console.log(`WARN: Tailwind CSS was disabled in config`); | ||
} | ||
} catch (err) { | ||
throw err; | ||
} | ||
} | ||
|
||
async function readJson(path: string) { | ||
try { | ||
return await readFile(path).then(String).then(JSON.parse); | ||
} catch (err) { | ||
throw err; | ||
} | ||
} | ||
|
||
async function renderPage(template: string, vars: TemplateVariables) { | ||
try { | ||
if (!vars.code) { | ||
throw new Error('No code variable to render page'); | ||
} else if (!vars.locale) { | ||
throw new Error('No locale variable to render page'); | ||
} | ||
|
||
const path = `${DEFAULTS.DIST}/${vars.locale}/${vars.code}.html`; | ||
|
||
console.log(`INFO: render '${path}' page`); | ||
await writeFile(path, render(template, vars), { flag: 'w+' }); | ||
|
||
} catch (err) { | ||
throw err; | ||
} | ||
} | ||
|
||
async function readConfig(): Promise<Config> { | ||
try { | ||
const config = await readJson(DEFAULTS.CONFIG); | ||
|
||
if (!config.theme) { | ||
throw new Error(`Please set theme in your configuration: ${DEFAULTS.CONFIG}`); | ||
} else if (!config.locale) { | ||
throw new Error(`Please set locale in your configuration: ${DEFAULTS.CONFIG}`); | ||
} | ||
|
||
return config; | ||
} catch (err) { | ||
throw err; | ||
} | ||
} | ||
|
||
async function prepare(config: Config) { | ||
try { | ||
console.log(`INFO: prepare build directory '${DEFAULTS.DIST}'`); | ||
|
||
await rm(DEFAULTS.DIST, { force: true, recursive: true }); | ||
await mkdir(`${DEFAULTS.DIST}/${config.locale}/`, { recursive: true }); | ||
} catch (err) { | ||
throw err; | ||
} | ||
} | ||
|
||
async function copyAssets(config: Config) { | ||
try { | ||
console.log(`INFO: copying assets to build directory '${DEFAULTS.DIST}'`); | ||
|
||
const path = `${DEFAULTS.THEMES}/${config.theme}/assets`; | ||
|
||
let exists = false; | ||
try { | ||
await access(path); | ||
exists = true; | ||
} catch (_) {} | ||
|
||
if (exists) { | ||
await cp( | ||
path, | ||
`${DEFAULTS.DIST}/${config.locale}/assets`, | ||
{ | ||
recursive: true, | ||
// Skip Tailwind styles to copy | ||
filter: (src) => !TAILWIND_STYLE.test(src) | ||
} | ||
); | ||
} | ||
else { | ||
console.log(`INFO: no assets in '${config.theme}' theme directory`); | ||
} | ||
} catch (err) { | ||
throw err; | ||
} | ||
} | ||
|
||
readConfig() | ||
.then(async (config) => { | ||
await prepare(config); | ||
await compile(config); | ||
await execTailwind(config); | ||
await copyAssets(config); | ||
}) | ||
.catch(err => { | ||
console.error(` | ||
An error happened during compile process. Please, check 'README.md' to get more details about calling this process. | ||
Error Message: | ||
${err.message} | ||
Error Stack: | ||
${err.stack} | ||
`); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
exports.DefaultPaths = { | ||
CONFIG: './config.json', | ||
SRC: './src', | ||
DIST: './dist', | ||
THEMES: './themes', | ||
TAILWIND_ENTRY: 'main.tcss' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { Defaults } from './interfaces.js'; | ||
import { DefaultPaths } from './_constants.js'; | ||
|
||
export const DEFAULTS: Defaults = { | ||
CONFIG: DefaultPaths.CONFIG, | ||
SRC: DefaultPaths.SRC, | ||
DIST: DefaultPaths.DIST, | ||
THEMES: DefaultPaths.THEMES, | ||
TAILWIND_ENTRY: DefaultPaths.TAILWIND_ENTRY, | ||
} | ||
|
||
export const SRC_CODE_PATTERN = /^[0-9]{3}(?=\.json$)/i; | ||
export const TAILWIND_STYLE = /\.tcss$/i; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
export interface Defaults { | ||
CONFIG: string, | ||
SRC: string, | ||
DIST: string, | ||
THEMES: string, | ||
TAILWIND_ENTRY: string, | ||
} | ||
|
||
export interface Config { | ||
tailwind: boolean, | ||
theme: string, | ||
locale: string, | ||
} | ||
|
||
export type SatusCode = number; | ||
|
||
export interface TemplateVariables { | ||
locale: string; | ||
[key: string]: string|number; | ||
} |
Oops, something went wrong.