als-layout 4.2.0 → 4.3.0
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/docs/4-view.md +19 -0
- package/index.js +38 -4
- package/package.json +5 -1
- package/readme.md +20 -0
- package/tests/view.test.js +72 -0
- package/tests/views/App.js +5 -0
- package/tests/views/app/Index.js +5 -0
package/docs/4-view.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
## View method
|
|
2
|
+
|
|
3
|
+
**The view method is a pilot. Don't use in production.**
|
|
4
|
+
|
|
5
|
+
```js
|
|
6
|
+
Layout.viewsPath = '../../views'; // relative to layout path
|
|
7
|
+
Layout.publicPath = '../../public'; // public folder path for urls starts with "/" should be relative to root
|
|
8
|
+
Layout.dev = false; // true by default
|
|
9
|
+
|
|
10
|
+
const data = {};
|
|
11
|
+
const includeBundle = false; // true by default
|
|
12
|
+
layout.view('some/Test',data,includeBundle) // viewsPath/some/Test.js
|
|
13
|
+
layout.view('some/test',data,includeBundle) // viewsPath/some/test/Index.js
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
* `includeBundle`
|
|
18
|
+
* in dev mode, will include bundle for rendering inside script tag in html
|
|
19
|
+
* in prod mode, will save context and bundle as files in publicPath/js folder and will add script[src] to html for those files.
|
package/index.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
const { Document, SingleNode, Node } = require('als-document');
|
|
2
2
|
const UglifyJS = require("uglify-js");
|
|
3
3
|
const uglifycss = require('uglifycss');
|
|
4
|
+
const { join, dirname } = require('path')
|
|
5
|
+
const { writeFileSync, mkdirSync } = require('fs')
|
|
6
|
+
const Render = require('als-render')
|
|
4
7
|
|
|
5
8
|
const onloadScript = /*js*/`document.addEventListener('DOMContentLoaded', function() {
|
|
6
9
|
const elements = document.querySelectorAll('[onload]');
|
|
@@ -13,16 +16,20 @@ const onloadScript = /*js*/`document.addEventListener('DOMContentLoaded', functi
|
|
|
13
16
|
});`;
|
|
14
17
|
|
|
15
18
|
class Layout extends Document {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
static bundles = {};
|
|
20
|
+
static viewsPath = '../../views';
|
|
21
|
+
static publicPath = '../../public';
|
|
22
|
+
static dev = true;
|
|
20
23
|
constructor(html, host, minified = false) {
|
|
21
24
|
super(html, host);
|
|
22
25
|
this.minified = minified
|
|
23
26
|
this.root = this.html
|
|
24
27
|
}
|
|
25
28
|
|
|
29
|
+
get rawHtml() { return this.innerHTML }
|
|
30
|
+
get clone() { return new Layout(new Document(this), this.URL, this.minified) }
|
|
31
|
+
lang(lang) { this.html.setAttribute('lang', lang); return this }
|
|
32
|
+
|
|
26
33
|
onload() {
|
|
27
34
|
if (this.onloadAdded) return
|
|
28
35
|
this.script({}, onloadScript);
|
|
@@ -143,6 +150,33 @@ class Layout extends Document {
|
|
|
143
150
|
this.head.insert(2, linkElement)
|
|
144
151
|
return this
|
|
145
152
|
}
|
|
153
|
+
|
|
154
|
+
view(path, data = {}, includeBundle=true) {
|
|
155
|
+
const parts = path.split('/')
|
|
156
|
+
if(parts[parts.length-1][0].toUpperCase() !== parts[parts.length-1][0]) parts.push('Index.js')
|
|
157
|
+
const relativePath = join(Layout.viewsPath, ...parts)
|
|
158
|
+
const { bundle, bundleFn, callBundle, rawHtml, context } = Render.render(relativePath, data, !Layout.dev)
|
|
159
|
+
if (includeBundle) {
|
|
160
|
+
if (Layout.dev) this.script({}, bundle, false)
|
|
161
|
+
else {
|
|
162
|
+
this.write('context', context, true)
|
|
163
|
+
this.write(path, bundleFn, false)
|
|
164
|
+
this.script({}, callBundle, false)
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const element = /*html*/`<content></content>`
|
|
168
|
+
this.body.insertAdjacentHTML('afterbegin', element)
|
|
169
|
+
return this.rawHtml.replace(element, rawHtml)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
write(path, content, head) {
|
|
173
|
+
if (Layout.bundles[path]) return
|
|
174
|
+
const filePath = join(Layout.publicPath, 'js', path + '.js')
|
|
175
|
+
mkdirSync(dirname(filePath), { recursive: true })
|
|
176
|
+
writeFileSync(filePath, content)
|
|
177
|
+
Layout.bundles[path] = path
|
|
178
|
+
this.script({ src: `/js/${path}.js` }, '', head)
|
|
179
|
+
}
|
|
146
180
|
}
|
|
147
181
|
|
|
148
182
|
module.exports = Layout
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "als-layout",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "node --test --experimental-test-coverage",
|
|
@@ -12,7 +12,11 @@
|
|
|
12
12
|
"description": "Html layout constructor",
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"als-document": "^1.4.0",
|
|
15
|
+
"als-render": "^0.9.3",
|
|
15
16
|
"uglify-js": "^3.19.2",
|
|
16
17
|
"uglifycss": "^0.0.29"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"fs-extra": "^11.2.0"
|
|
17
21
|
}
|
|
18
22
|
}
|
package/readme.md
CHANGED
|
@@ -152,3 +152,23 @@ In this example:
|
|
|
152
152
|
- We dynamically add a versioned link to a stylesheet in the `homePage`, demonstrating control over caching and resource management.
|
|
153
153
|
|
|
154
154
|
This advanced example illustrates how `als-layout` can be used to handle complex scenarios and requirements in web development, enhancing the flexibility and power at your disposal.
|
|
155
|
+
|
|
156
|
+
## View method
|
|
157
|
+
|
|
158
|
+
**The view method is a pilot. Don't use in production.**
|
|
159
|
+
|
|
160
|
+
```js
|
|
161
|
+
Layout.viewsPath = '../../views'; // relative to layout path
|
|
162
|
+
Layout.publicPath = '../../public'; // public folder path for urls starts with "/" should be relative to root
|
|
163
|
+
Layout.dev = false; // true by default
|
|
164
|
+
|
|
165
|
+
const data = {};
|
|
166
|
+
const includeBundle = false; // true by default
|
|
167
|
+
layout.view('some/Test',data,includeBundle) // viewsPath/some/Test.js
|
|
168
|
+
layout.view('some/test',data,includeBundle) // viewsPath/some/test/Index.js
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
* `includeBundle`
|
|
173
|
+
* in dev mode, will include bundle for rendering inside script tag in html
|
|
174
|
+
* in prod mode, will save context and bundle as files in publicPath/js folder and will add script[src] to html for those files.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const { describe, it, beforeEach, before, afterEach } = require('node:test')
|
|
3
|
+
const Layout = require('../index');
|
|
4
|
+
const { readdirSync, removeSync, existsSync, rmdirSync } = require('fs-extra')
|
|
5
|
+
const { join } = require('path')
|
|
6
|
+
Layout.viewsPath = 'views';
|
|
7
|
+
Layout.publicPath = join(__dirname,'public')
|
|
8
|
+
|
|
9
|
+
describe('Dev mode', () => {
|
|
10
|
+
let layout
|
|
11
|
+
before(() => {
|
|
12
|
+
Layout.dev = true;
|
|
13
|
+
})
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
layout = new Layout()
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('view path without bundle', () => {
|
|
19
|
+
const html = layout.view('App', { test: 'test' })
|
|
20
|
+
assert(html.includes(/*html*/`<div component="App">Hello test</div>`))
|
|
21
|
+
assert(!html.includes(/*html*/`<content></content>`))
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('view Index path without bundle', () => {
|
|
25
|
+
const html = layout.view('app', { test: 'test' })
|
|
26
|
+
assert(html.includes(/*html*/`<div component="Index">Hello test</div>`))
|
|
27
|
+
assert(!html.includes(/*html*/`<content></content>`))
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('view path with bundle', () => {
|
|
31
|
+
const html = layout.view('App', { test: 'test' }, true)
|
|
32
|
+
assert(html.includes('const Context'))
|
|
33
|
+
assert(html.includes('renderedBundle'))
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
describe('Prod mode', () => {
|
|
39
|
+
let layout
|
|
40
|
+
const publicPath = join(Layout.publicPath,'js')
|
|
41
|
+
before(() => {
|
|
42
|
+
Layout.dev = false;
|
|
43
|
+
})
|
|
44
|
+
beforeEach(() => {
|
|
45
|
+
layout = new Layout()
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
afterEach(() => {
|
|
49
|
+
if(!existsSync(publicPath)) return
|
|
50
|
+
const files = readdirSync(publicPath)
|
|
51
|
+
files.forEach(file => removeSync(join(publicPath,file)))
|
|
52
|
+
if(existsSync(publicPath)) rmdirSync(publicPath)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('view path without bundle', () => {
|
|
56
|
+
const html = layout.view('App', { test: 'test' })
|
|
57
|
+
assert(html.includes(/*html*/`<div component="App">Hello test</div>`))
|
|
58
|
+
assert(!html.includes(/*html*/`<content></content>`))
|
|
59
|
+
assert(existsSync(publicPath) === false)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
it('view path with bundle', () => {
|
|
63
|
+
const html = layout.view('App', { test: 'test' }, true)
|
|
64
|
+
const files = readdirSync(publicPath)
|
|
65
|
+
assert.deepStrictEqual(files,[ 'App.js', 'context.js' ])
|
|
66
|
+
assert(html.includes('/js/App.js'))
|
|
67
|
+
assert(html.includes('renderedBundle'))
|
|
68
|
+
// <script src="/js/App.js"></script><script>renderedBundle({"test":"test"})</script>
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
})
|
|
72
|
+
|