html-express-js 2.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -16
- package/package.json +22 -7
- package/src/index.d.ts +48 -0
- package/src/index.js +93 -37
- package/.github/dependabot.yml +0 -6
- package/.github/workflows/dependabot-automerge.yml +0 -17
- package/.husky/pre-commit +0 -4
- package/.nvmrc +0 -1
- package/.prettierignore +0 -8
- package/.prettierrc.cjs +0 -3
- package/.release-it.cjs +0 -13
- package/.travis.yml +0 -8
- package/example/app.js +0 -36
- package/example/public/hello/index.js +0 -17
- package/example/public/includes/head.js +0 -15
- package/example/public/index.js +0 -21
- package/example/public/main.css +0 -3
- package/example/public/not-found.js +0 -15
- package/example/server.js +0 -20
- package/jsconfig.json +0 -9
package/README.md
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- Serves HTML documents using template literals
|
|
10
|
-
- Supports includes in
|
|
10
|
+
- Supports includes in HTML documents
|
|
11
|
+
- Allows shared global state throughout templates
|
|
11
12
|
|
|
12
13
|
## Installation
|
|
13
14
|
|
|
@@ -17,28 +18,32 @@ npm install html-express-js
|
|
|
17
18
|
|
|
18
19
|
## Basic Usage
|
|
19
20
|
|
|
20
|
-
The following
|
|
21
|
+
The following is a high level example of how the package can be used as an Express template engine. See [example](/example) directory for all details of a working implementation.
|
|
21
22
|
|
|
22
23
|
Set up your Express app to use this engine:
|
|
23
24
|
|
|
24
25
|
```js
|
|
25
|
-
import htmlExpress
|
|
26
|
+
import htmlExpress from 'html-express-js';
|
|
26
27
|
|
|
27
28
|
const app = express();
|
|
28
29
|
const __dirname = resolve();
|
|
29
30
|
|
|
31
|
+
const viewsDir = `${__dirname}/public`;
|
|
32
|
+
|
|
33
|
+
const { engine, staticIndexHandler } = htmlExpress({
|
|
34
|
+
viewsDir, // root views directory to serve all index.js files
|
|
35
|
+
includesDir: `${viewsDir}/includes`, // OPTIONAL: where all includes reside
|
|
36
|
+
notFoundView: '404/index', // OPTIONAL: relative to viewsDir above
|
|
37
|
+
});
|
|
38
|
+
|
|
30
39
|
// set up engine
|
|
31
|
-
app.engine(
|
|
32
|
-
|
|
33
|
-
htmlExpress({
|
|
34
|
-
includesDir: 'includes', // where all includes reside
|
|
35
|
-
}),
|
|
36
|
-
);
|
|
40
|
+
app.engine('js', engine);
|
|
41
|
+
|
|
37
42
|
// use engine
|
|
38
43
|
app.set('view engine', 'js');
|
|
39
44
|
|
|
40
45
|
// set directory where all index.js pages are served
|
|
41
|
-
app.set('views',
|
|
46
|
+
app.set('views', viewsDir);
|
|
42
47
|
|
|
43
48
|
// render HTML in public/homepage.js with data
|
|
44
49
|
app.get('/', function (req, res, next) {
|
|
@@ -51,12 +56,7 @@ app.get('/', function (req, res, next) {
|
|
|
51
56
|
// OPTIONALLY: route all GET requests to directories
|
|
52
57
|
// to their associated static index.js views in the public directory
|
|
53
58
|
// and, if not found, route to the 404/index.js view
|
|
54
|
-
app.use(
|
|
55
|
-
staticIndexHandler({
|
|
56
|
-
viewsDir: `${__dirname}/public`, // root views directory to serve all index.js files
|
|
57
|
-
notFoundView: '404/index', // relative to viewsDir above
|
|
58
|
-
}),
|
|
59
|
-
);
|
|
59
|
+
app.use(staticIndexHandler());
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
Then you can create the associated files:
|
|
@@ -93,3 +93,76 @@ export const view = (data, state) => html`
|
|
|
93
93
|
</html>
|
|
94
94
|
`;
|
|
95
95
|
```
|
|
96
|
+
|
|
97
|
+
## Advanced usage
|
|
98
|
+
|
|
99
|
+
### Injecting and using state based on a request
|
|
100
|
+
|
|
101
|
+
The following shows an example of showing a logged out state based on the cookie on a request.
|
|
102
|
+
|
|
103
|
+
```js
|
|
104
|
+
import htmlExpress from 'html-express-js';
|
|
105
|
+
|
|
106
|
+
const app = express();
|
|
107
|
+
const __dirname = resolve();
|
|
108
|
+
|
|
109
|
+
const viewsDir = `${__dirname}/public`;
|
|
110
|
+
|
|
111
|
+
const { engine, staticIndexHandler } = htmlExpress({
|
|
112
|
+
viewsDir,
|
|
113
|
+
/**
|
|
114
|
+
* Inject global state into all views based on cookie
|
|
115
|
+
*/
|
|
116
|
+
buildRequestState: (req) => {
|
|
117
|
+
if (req.cookies['authed']) {
|
|
118
|
+
return {
|
|
119
|
+
loggedIn: true,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
app.engine('js', engine);
|
|
126
|
+
app.set('view engine', 'js');
|
|
127
|
+
app.set('views', viewsDir);
|
|
128
|
+
|
|
129
|
+
app.get('/', function (req, res, next) {
|
|
130
|
+
res.render('homepage');
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
```js
|
|
135
|
+
// public/homepage.js
|
|
136
|
+
import { html } from 'html-express-js';
|
|
137
|
+
|
|
138
|
+
export const view = (data, state) => {
|
|
139
|
+
const { loggedIn } = state;
|
|
140
|
+
|
|
141
|
+
return html`
|
|
142
|
+
<!doctype html>
|
|
143
|
+
<html lang="en">
|
|
144
|
+
<head>
|
|
145
|
+
<title>${data.title}</title>
|
|
146
|
+
</head>
|
|
147
|
+
|
|
148
|
+
<body>
|
|
149
|
+
${loggedIn ? `<a href="/logout">Logout</a>` : 'Not logged in'}
|
|
150
|
+
</body>
|
|
151
|
+
</html>
|
|
152
|
+
`;
|
|
153
|
+
};
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Development
|
|
157
|
+
|
|
158
|
+
Run site in examples directory
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
npm start
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Run tests
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
npm test
|
|
168
|
+
```
|
package/package.json
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "html-express-js",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "An Express template engine to render HTML views using native JavaScript",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
8
8
|
"node": ">=16"
|
|
9
9
|
},
|
|
10
|
+
"files": [
|
|
11
|
+
"src/index.js",
|
|
12
|
+
"src/index.d.ts"
|
|
13
|
+
],
|
|
10
14
|
"scripts": {
|
|
11
|
-
"format": "prettier --write '**/*'",
|
|
12
|
-
"
|
|
15
|
+
"format": "prettier --write '**/*' --log-level=warn",
|
|
16
|
+
"format-check": "prettier --check '**/*' --ignore-unknown",
|
|
17
|
+
"test": "npm run test:src && npm run type-check && npm run format-check",
|
|
18
|
+
"test:src": "mocha src/**/*.tests.js",
|
|
13
19
|
"start": "node ./example/server.js",
|
|
14
|
-
"
|
|
20
|
+
"type-check": "tsc -p tsconfig.json",
|
|
21
|
+
"prepare": "husky install",
|
|
22
|
+
"build": "tsc -p tsconfig.build.json"
|
|
15
23
|
},
|
|
16
24
|
"repository": {
|
|
17
25
|
"type": "git",
|
|
@@ -34,12 +42,19 @@
|
|
|
34
42
|
"glob": "^10.2.2"
|
|
35
43
|
},
|
|
36
44
|
"devDependencies": {
|
|
37
|
-
"@types/
|
|
45
|
+
"@types/chai": "^4.3.13",
|
|
46
|
+
"@types/express": "^4.17.21",
|
|
47
|
+
"@types/mocha": "^10.0.6",
|
|
48
|
+
"@types/sinon": "^17.0.3",
|
|
49
|
+
"chai": "^5.1.0",
|
|
38
50
|
"chokidar": "^3.5.3",
|
|
39
51
|
"express": "^4.18.1",
|
|
40
52
|
"husky": "^9.0.7",
|
|
53
|
+
"mocha": "^10.3.0",
|
|
41
54
|
"prettier": "^3.0.3",
|
|
42
|
-
"release-it": "^17.
|
|
43
|
-
"reload": "^3.2.0"
|
|
55
|
+
"release-it": "^17.1.1",
|
|
56
|
+
"reload": "^3.2.0",
|
|
57
|
+
"sinon": "^17.0.1",
|
|
58
|
+
"typescript": "^5.4.3"
|
|
44
59
|
}
|
|
45
60
|
}
|
package/src/index.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Template literal that supports string
|
|
3
|
+
* interpolating in passed HTML.
|
|
4
|
+
*
|
|
5
|
+
* @param {*} strings
|
|
6
|
+
* @param {...any} data
|
|
7
|
+
* @returns {string} - HTML string
|
|
8
|
+
*/
|
|
9
|
+
export function html(strings: any, ...data: any[]): string;
|
|
10
|
+
/**
|
|
11
|
+
* Returns an object containing both static
|
|
12
|
+
* index handler and the template engine callback.
|
|
13
|
+
*
|
|
14
|
+
* @param {HTMLExpressOptions} [opts]
|
|
15
|
+
* @returns {{
|
|
16
|
+
* staticIndexHandler: HTMLExpressStaticIndexHandler,
|
|
17
|
+
* engine: Parameters<import('express').Application['engine']>[1],
|
|
18
|
+
* }}
|
|
19
|
+
*/
|
|
20
|
+
export default function _default(opts?: HTMLExpressOptions): {
|
|
21
|
+
staticIndexHandler: HTMLExpressStaticIndexHandler;
|
|
22
|
+
engine: [ext: string, fn: (path: string, options: object, callback: (e: any, rendered?: string) => void) => void][1];
|
|
23
|
+
};
|
|
24
|
+
export type HTMLExpressBuildStateHandler = (req: import('express').Request) => Record<string, any>;
|
|
25
|
+
export type HTMLExpressOptions = {
|
|
26
|
+
/**
|
|
27
|
+
* - The directory that houses any potential index files
|
|
28
|
+
*/
|
|
29
|
+
viewsDir: string;
|
|
30
|
+
/**
|
|
31
|
+
* - The directory that houses all of the includes
|
|
32
|
+
* that will be available on the includes property of each static page.
|
|
33
|
+
*/
|
|
34
|
+
includesDir?: string;
|
|
35
|
+
/**
|
|
36
|
+
* - The path of a file relative to the views
|
|
37
|
+
* directory that should be served as 404 when no matching index page exists. Defaults to `404/index`.
|
|
38
|
+
*/
|
|
39
|
+
notFoundView?: string;
|
|
40
|
+
/**
|
|
41
|
+
* - A callback function that allows for
|
|
42
|
+
* building a state object from request information, that will be merged with default state and made available to all views
|
|
43
|
+
*/
|
|
44
|
+
buildRequestState?: HTMLExpressBuildStateHandler;
|
|
45
|
+
};
|
|
46
|
+
export type HTMLExpressStaticIndexHandler = (options?: HTMLExpressOptions) => import('express').RequestHandler;
|
|
47
|
+
declare function staticIndexHandler(options?: HTMLExpressOptions): import('express').RequestHandler;
|
|
48
|
+
export {};
|
package/src/index.js
CHANGED
|
@@ -2,6 +2,23 @@ import { basename, extname } from 'path';
|
|
|
2
2
|
import { glob } from 'glob';
|
|
3
3
|
import { stat } from 'fs/promises';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* @callback HTMLExpressBuildStateHandler
|
|
7
|
+
* @param {import('express').Request} req
|
|
8
|
+
* @returns {Record<string, any>}
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @typedef {object} HTMLExpressOptions
|
|
13
|
+
* @property {string} viewsDir - The directory that houses any potential index files
|
|
14
|
+
* @property {string} [includesDir] - The directory that houses all of the includes
|
|
15
|
+
* that will be available on the includes property of each static page.
|
|
16
|
+
* @property {string} [notFoundView] - The path of a file relative to the views
|
|
17
|
+
* directory that should be served as 404 when no matching index page exists. Defaults to `404/index`.
|
|
18
|
+
* @property {HTMLExpressBuildStateHandler} [buildRequestState] - A callback function that allows for
|
|
19
|
+
* building a state object from request information, that will be merged with default state and made available to all views
|
|
20
|
+
*/
|
|
21
|
+
|
|
5
22
|
/**
|
|
6
23
|
* Renders an HTML template in a file.
|
|
7
24
|
*
|
|
@@ -26,14 +43,15 @@ async function renderHtmlFileTemplate(path, data, state) {
|
|
|
26
43
|
*
|
|
27
44
|
* @param {string} filePath - The path to html file
|
|
28
45
|
* @param {object} data - Data to be made available in view
|
|
29
|
-
* @param {object}
|
|
46
|
+
* @param {object} options - Options passed to original instantiation
|
|
47
|
+
* @param {HTMLExpressOptions['includesDir']} options.includesDir
|
|
48
|
+
* @param {Record<string, any>} [options.state]
|
|
30
49
|
* @returns {Promise<string>} HTML with includes available (appended to state)
|
|
31
50
|
*/
|
|
32
|
-
async function renderHtmlFile(filePath, data = {},
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
};
|
|
36
|
-
const { includesDir } = instanceOptions;
|
|
51
|
+
async function renderHtmlFile(filePath, data = {}, options) {
|
|
52
|
+
const { includesDir } = options || {};
|
|
53
|
+
const state = options.state || {};
|
|
54
|
+
state.includes = {};
|
|
37
55
|
|
|
38
56
|
const includeFilePaths = await glob(`${includesDir}/*.js`);
|
|
39
57
|
for await (const includePath of includeFilePaths) {
|
|
@@ -48,7 +66,9 @@ async function renderHtmlFile(filePath, data = {}, instanceOptions = {}) {
|
|
|
48
66
|
}
|
|
49
67
|
|
|
50
68
|
/**
|
|
51
|
-
* Template literal that supports string
|
|
69
|
+
* Template literal that supports string
|
|
70
|
+
* interpolating in passed HTML.
|
|
71
|
+
*
|
|
52
72
|
* @param {*} strings
|
|
53
73
|
* @param {...any} data
|
|
54
74
|
* @returns {string} - HTML string
|
|
@@ -59,22 +79,23 @@ export function html(strings, ...data) {
|
|
|
59
79
|
const exp = data[i] || '';
|
|
60
80
|
rawHtml += str + exp;
|
|
61
81
|
}
|
|
62
|
-
|
|
63
|
-
return html;
|
|
82
|
+
return rawHtml;
|
|
64
83
|
}
|
|
65
84
|
|
|
85
|
+
/**
|
|
86
|
+
* @callback HTMLExpressStaticIndexHandler
|
|
87
|
+
* @param {HTMLExpressOptions} [options]
|
|
88
|
+
* @returns {import('express').RequestHandler}
|
|
89
|
+
*/
|
|
90
|
+
|
|
66
91
|
/**
|
|
67
92
|
* Attempts to render index.js pages when requesting to
|
|
68
93
|
* directories and fallback to 404/index.js if doesnt exist.
|
|
69
94
|
*
|
|
70
|
-
* @
|
|
71
|
-
* @param {object} options.viewsDir - The directory that houses any potential index files
|
|
72
|
-
* @param {string} [options.notFoundView] - The path of a file relative to the views
|
|
73
|
-
* directory that should be served as 404 when no matching index page exists. Defaults to `404/index`.
|
|
74
|
-
* @returns {import('express').RequestHandler} - Middleware function
|
|
95
|
+
* @type {HTMLExpressStaticIndexHandler}
|
|
75
96
|
*/
|
|
76
|
-
|
|
77
|
-
const notFoundView = options
|
|
97
|
+
function staticIndexHandler(options) {
|
|
98
|
+
const { viewsDir, notFoundView, includesDir, buildRequestState } = options;
|
|
78
99
|
|
|
79
100
|
return async function (req, res, next) {
|
|
80
101
|
const { path: rawPath } = req;
|
|
@@ -82,39 +103,74 @@ export function staticIndexHandler(options) {
|
|
|
82
103
|
if (fileExtension) {
|
|
83
104
|
return next();
|
|
84
105
|
}
|
|
85
|
-
const
|
|
86
|
-
const path =
|
|
106
|
+
const pathWithoutPrecedingSlash = rawPath.replace('/', ''); // remove beginning slash
|
|
107
|
+
const path = pathWithoutPrecedingSlash
|
|
108
|
+
? `${pathWithoutPrecedingSlash}/index`
|
|
109
|
+
: 'index';
|
|
110
|
+
|
|
111
|
+
const requestState = buildRequestState ? buildRequestState(req) : {};
|
|
112
|
+
|
|
113
|
+
const renderOptions = {
|
|
114
|
+
includesDir,
|
|
115
|
+
state: requestState,
|
|
116
|
+
};
|
|
117
|
+
res.setHeader('Content-Type', 'text/html');
|
|
87
118
|
try {
|
|
88
|
-
|
|
89
|
-
|
|
119
|
+
const absoluteFilePath = `${viewsDir}/${path}.js`;
|
|
120
|
+
await stat(absoluteFilePath); // check if file exists
|
|
121
|
+
const html = await renderHtmlFile(absoluteFilePath, {}, renderOptions);
|
|
122
|
+
res.send(html);
|
|
90
123
|
} catch (e) {
|
|
91
124
|
if (e.code !== 'ENOENT') {
|
|
92
125
|
throw e;
|
|
93
126
|
}
|
|
127
|
+
const notFoundViewPath = notFoundView || `404/index`;
|
|
128
|
+
const notFoundAbsoluteFilePath = `${viewsDir}/${notFoundViewPath}.js`;
|
|
129
|
+
const html = await renderHtmlFile(
|
|
130
|
+
notFoundAbsoluteFilePath,
|
|
131
|
+
{},
|
|
132
|
+
renderOptions,
|
|
133
|
+
);
|
|
94
134
|
res.status(404);
|
|
95
|
-
res.
|
|
135
|
+
res.send(html);
|
|
96
136
|
}
|
|
97
137
|
};
|
|
98
138
|
}
|
|
99
139
|
|
|
100
140
|
/**
|
|
101
|
-
* Returns
|
|
141
|
+
* Returns an object containing both static
|
|
142
|
+
* index handler and the template engine callback.
|
|
102
143
|
*
|
|
103
|
-
* @param {
|
|
104
|
-
* @
|
|
105
|
-
*
|
|
144
|
+
* @param {HTMLExpressOptions} [opts]
|
|
145
|
+
* @returns {{
|
|
146
|
+
* staticIndexHandler: HTMLExpressStaticIndexHandler,
|
|
147
|
+
* engine: Parameters<import('express').Application['engine']>[1],
|
|
148
|
+
* }}
|
|
106
149
|
*/
|
|
107
|
-
export default function (opts
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
150
|
+
export default function (opts) {
|
|
151
|
+
const { buildRequestState, notFoundView, viewsDir } = opts;
|
|
152
|
+
const includesDir = opts.includesDir
|
|
153
|
+
? opts.includesDir
|
|
154
|
+
: `${viewsDir}/includes`;
|
|
155
|
+
return {
|
|
156
|
+
staticIndexHandler: (options) => {
|
|
157
|
+
return staticIndexHandler({
|
|
158
|
+
includesDir,
|
|
159
|
+
viewsDir,
|
|
160
|
+
notFoundView,
|
|
161
|
+
buildRequestState,
|
|
162
|
+
...options,
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
engine: async (filePath, data, callback) => {
|
|
166
|
+
const html = await renderHtmlFile(
|
|
167
|
+
filePath,
|
|
168
|
+
{},
|
|
169
|
+
{
|
|
170
|
+
includesDir,
|
|
171
|
+
},
|
|
172
|
+
);
|
|
173
|
+
return callback(null, html);
|
|
174
|
+
},
|
|
119
175
|
};
|
|
120
176
|
}
|
package/.github/dependabot.yml
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
name: Dependabot auto-merge
|
|
2
|
-
on: pull_request
|
|
3
|
-
|
|
4
|
-
permissions:
|
|
5
|
-
pull-requests: write
|
|
6
|
-
contents: write
|
|
7
|
-
|
|
8
|
-
jobs:
|
|
9
|
-
dependabot:
|
|
10
|
-
runs-on: ubuntu-latest
|
|
11
|
-
if: ${{ github.actor == 'dependabot[bot]' }}
|
|
12
|
-
steps:
|
|
13
|
-
- name: Enable auto-merge for Dependabot PRs
|
|
14
|
-
run: gh pr merge --auto --squash "$PR_URL"
|
|
15
|
-
env:
|
|
16
|
-
PR_URL: ${{github.event.pull_request.html_url}}
|
|
17
|
-
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
package/.husky/pre-commit
DELETED
package/.nvmrc
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
16
|
package/.prettierignore
DELETED
package/.prettierrc.cjs
DELETED
package/.release-it.cjs
DELETED
package/.travis.yml
DELETED
package/example/app.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import express from 'express';
|
|
2
|
-
import { resolve } from 'path';
|
|
3
|
-
import htmlExpress, { staticIndexHandler } from '../src/index.js';
|
|
4
|
-
|
|
5
|
-
const __dirname = resolve();
|
|
6
|
-
|
|
7
|
-
const app = express();
|
|
8
|
-
|
|
9
|
-
app.engine(
|
|
10
|
-
'js',
|
|
11
|
-
htmlExpress({
|
|
12
|
-
includesDir: 'includes',
|
|
13
|
-
}),
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
app.set('view engine', 'js');
|
|
17
|
-
app.set('views', `${__dirname}/example/public`);
|
|
18
|
-
|
|
19
|
-
// serve all other static files like CSS, images, etc
|
|
20
|
-
app.use(express.static(`${__dirname}/example/public`));
|
|
21
|
-
|
|
22
|
-
app.get('/hello', async function (req, res) {
|
|
23
|
-
res.render('hello', {
|
|
24
|
-
name: 'world',
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// Automatically serve any index.js file as HTML in the public directory
|
|
29
|
-
app.use(
|
|
30
|
-
staticIndexHandler({
|
|
31
|
-
viewsDir: `${__dirname}/example/public`,
|
|
32
|
-
notFoundView: 'not-found', // OPTIONAL: defaults to `404/index`
|
|
33
|
-
}),
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
export default app;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { html } from '../../../src/index.js';
|
|
2
|
-
|
|
3
|
-
export const view = (data, state) => html`
|
|
4
|
-
<!doctype html>
|
|
5
|
-
<html lang="en">
|
|
6
|
-
<head>
|
|
7
|
-
${state.includes.head}
|
|
8
|
-
<title>Hello!</title>
|
|
9
|
-
</head>
|
|
10
|
-
|
|
11
|
-
<body>
|
|
12
|
-
<h1>Hello, ${data.name}!</h1>
|
|
13
|
-
|
|
14
|
-
<p>Click <a href="/">here</a> to go back to the dashboard.</p>
|
|
15
|
-
</body>
|
|
16
|
-
</html>
|
|
17
|
-
`;
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { html } from '../../../src/index.js';
|
|
2
|
-
|
|
3
|
-
export const view = (/*data, state*/) => html`
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
6
|
-
<meta
|
|
7
|
-
name="viewport"
|
|
8
|
-
content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0"
|
|
9
|
-
/>
|
|
10
|
-
|
|
11
|
-
<link rel="stylesheet" href="/main.css" />
|
|
12
|
-
|
|
13
|
-
<!-- For HMR! -->
|
|
14
|
-
<script src="/reload/reload.js"></script>
|
|
15
|
-
`;
|
package/example/public/index.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { html } from '../../src/index.js';
|
|
2
|
-
|
|
3
|
-
export const view = (data, state) => html`
|
|
4
|
-
<!doctype html>
|
|
5
|
-
<html lang="en">
|
|
6
|
-
<head>
|
|
7
|
-
${state.includes.head}
|
|
8
|
-
<title>Dashboard</title>
|
|
9
|
-
</head>
|
|
10
|
-
|
|
11
|
-
<body>
|
|
12
|
-
<h1>This is the dashboard!</h1>
|
|
13
|
-
|
|
14
|
-
<p>
|
|
15
|
-
This file is served by the <code>staticIndexHandler</code> in app.js
|
|
16
|
-
</p>
|
|
17
|
-
|
|
18
|
-
<p>Click <a href="/hello">here</a> to go hello route.</p>
|
|
19
|
-
</body>
|
|
20
|
-
</html>
|
|
21
|
-
`;
|
package/example/public/main.css
DELETED
package/example/server.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import app from './app.js';
|
|
2
|
-
import reload from 'reload';
|
|
3
|
-
import chokidar from 'chokidar';
|
|
4
|
-
|
|
5
|
-
const port = 2222;
|
|
6
|
-
|
|
7
|
-
// reload browser on file changes
|
|
8
|
-
reload(app, { verbose: true })
|
|
9
|
-
.then(function (reloadReturned) {
|
|
10
|
-
chokidar.watch(['./src', './example']).on('all', (/*event, path*/) => {
|
|
11
|
-
reloadReturned.reload();
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
app.listen(port, function () {
|
|
15
|
-
console.log(`Server started at http://localhost:${port}`);
|
|
16
|
-
});
|
|
17
|
-
})
|
|
18
|
-
.catch(function (err) {
|
|
19
|
-
console.error('Reload could not start, could not start example app', err);
|
|
20
|
-
});
|