als-layout 3.0.0 → 4.0.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/0-change-log.md +8 -0
- package/docs/1-basic-usage.md +0 -1
- package/docs/4-render.md +22 -17
- package/index.js +163 -1
- package/package.json +6 -9
- package/readme.md +30 -18
- package/tests/constructor.test.js +2 -14
- package/tests/description.test.js +33 -0
- package/tests/favicon.test.js +36 -0
- package/tests/image.test.js +42 -0
- package/tests/{layout.test.js → integrative.test.js} +1 -2
- package/tests/keywords.test.js +47 -0
- package/tests/link.test.js +83 -0
- package/tests/render/counter/App.js +8 -0
- package/tests/render/counter/Counter.js +9 -0
- package/tests/render/counter/build.js +12 -0
- package/tests/render.test.js +8 -15
- package/tests/script.test.js +57 -0
- package/tests/style.test.js +41 -0
- package/tests/url.test.js +50 -0
- package/tests/viewport.test.js +41 -0
- package/lib/elements/add-meta.js +0 -11
- package/lib/elements/charset.js +0 -8
- package/lib/elements/description.js +0 -9
- package/lib/elements/favicon.js +0 -10
- package/lib/elements/image.js +0 -11
- package/lib/elements/index.js +0 -15
- package/lib/elements/keywords.js +0 -20
- package/lib/elements/link.js +0 -13
- package/lib/elements/script.js +0 -18
- package/lib/elements/style.js +0 -30
- package/lib/elements/title.js +0 -11
- package/lib/elements/url.js +0 -17
- package/lib/elements/viewport.js +0 -8
- package/lib/layout.js +0 -30
- package/lib/onload.js +0 -9
- package/lib/render.js +0 -12
- package/tests/counter/App.js +0 -6
- package/tests/counter/build.js +0 -14
- package/tests/counter/counter.js +0 -14
- package/tests/elements.test.js +0 -437
- /package/tests/render/{App.js → render/App.js} +0 -0
- /package/tests/render/{Some.js → render/Some.js} +0 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const Layout = require('../../../index')
|
|
3
|
+
|
|
4
|
+
// Create and configure the layout
|
|
5
|
+
const layout = new Layout('','',false).title('Counter')
|
|
6
|
+
const time1 = performance.now()
|
|
7
|
+
layout.$('body').render('./App')
|
|
8
|
+
const time2 = performance.now()
|
|
9
|
+
console.log(`${time2 - time1}ms`) // e.g., 1.0649ms
|
|
10
|
+
|
|
11
|
+
// Write the output to a file
|
|
12
|
+
fs.writeFileSync('counter.html', layout.rawHtml, 'utf-8')
|
package/tests/render.test.js
CHANGED
|
@@ -1,31 +1,24 @@
|
|
|
1
1
|
const assert = require('assert');
|
|
2
2
|
const { describe, it,beforeEach } = require('node:test')
|
|
3
|
-
const Layout = require('../
|
|
3
|
+
const Layout = require('../index')
|
|
4
4
|
|
|
5
5
|
describe('Basic tests', () => {
|
|
6
6
|
let layout
|
|
7
7
|
beforeEach(() => layout = new Layout())
|
|
8
8
|
it('Should render without bundle',() => {
|
|
9
|
-
|
|
9
|
+
layout.$('body').render('./render/render/App',{},false)
|
|
10
10
|
const expected =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
' Hello From Some!\n' +
|
|
15
|
-
' </div>\n' +
|
|
16
|
-
' </div></body></html>'
|
|
17
|
-
|
|
18
|
-
assert(rawHtml === expected)
|
|
11
|
+
'<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title></title></head><body><div component="App"><div>Hello from App!</div>\n' +
|
|
12
|
+
' <div component="Some">Hello From Some!</div></div></body></html>'
|
|
13
|
+
assert(layout.rawHtml === expected)
|
|
19
14
|
})
|
|
20
15
|
|
|
21
16
|
it('Should render with bundle',() => {
|
|
22
|
-
|
|
23
|
-
assert(rawHtml.includes('<script>'))
|
|
17
|
+
layout.$('body').render('./render/render/App')
|
|
18
|
+
assert(layout.rawHtml.includes('<script>'))
|
|
24
19
|
})
|
|
25
20
|
|
|
26
21
|
it('Should do nothing if element not exists',() => {
|
|
27
|
-
|
|
28
|
-
const expected = '<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title></title></head><body></body></html>'
|
|
29
|
-
assert(rawHtml === expected)
|
|
22
|
+
assert.throws(() => layout.$('main').render('./render/render/App'))
|
|
30
23
|
})
|
|
31
24
|
})
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const { describe, it, beforeEach } = require('node:test')
|
|
3
|
+
const Layout = require('../index');
|
|
4
|
+
|
|
5
|
+
describe('Scripts', () => {
|
|
6
|
+
let layout;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => layout = new Layout());
|
|
9
|
+
|
|
10
|
+
it('should not add script if attributes are not an object', () => {
|
|
11
|
+
layout.script("not-an-object");
|
|
12
|
+
assert.strictEqual(layout.root.$('script'), null, 'Script should not be added when attributes are not an object');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should not add script if src already exists', () => {
|
|
16
|
+
layout.script({ src: 'existingscript.js' }, 'console.log("test");');
|
|
17
|
+
layout.script({ src: 'existingscript.js' }, 'console.log("duplicate");');
|
|
18
|
+
assert.strictEqual(layout.root.$$(`script[src="existingscript.js"]`).length, 1, 'Duplicate script should not be added');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should handle empty innerHTML correctly', () => {
|
|
22
|
+
layout.script({ src: 'test.js' }, '');
|
|
23
|
+
assert.strictEqual(layout.root.$('script').innerHTML, '', 'Script innerHTML should be empty');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should add script correctly', () => {
|
|
27
|
+
const scriptContent = 'console.log("Hello, world!");';
|
|
28
|
+
layout.script({}, scriptContent);
|
|
29
|
+
assert.strictEqual(layout.root.$('script').innerHTML, scriptContent, 'Script content not set correctly');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should add version to script src', () => {
|
|
33
|
+
const src = 'script.js';
|
|
34
|
+
const version = '1.0';
|
|
35
|
+
layout.script({ src }, '', true, version);
|
|
36
|
+
assert.strictEqual(layout.root.$('script').getAttribute('src'), `${src}?v=${version}`, 'Script src should include version');
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should not add script if no attributes and no innerHTML', () => {
|
|
40
|
+
layout.script({}, '');
|
|
41
|
+
assert.strictEqual(layout.root.$('script'), null, 'Script should not be added if there are no attributes and no innerHTML');
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should add script after body when head is false', () => {
|
|
45
|
+
const scriptContent = 'console.log("Script in body");';
|
|
46
|
+
layout.script({ src: 'scriptbody.js' }, scriptContent, false);
|
|
47
|
+
assert.strictEqual(layout.body.next.innerHTML, scriptContent, 'Script should be added to body');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should append version parameter correctly when src already has parameters', () => {
|
|
51
|
+
const srcWithParams = 'script.js?existing=param';
|
|
52
|
+
const version = '1.0';
|
|
53
|
+
layout.script({ src: srcWithParams }, '', true, version);
|
|
54
|
+
assert.strictEqual(layout.root.$('script').getAttribute('src'), `${srcWithParams}&v=${version}`, 'Version parameter should be appended with &');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const { describe, it, beforeEach } = require('node:test')
|
|
3
|
+
const Layout = require('../index');
|
|
4
|
+
const uglifycss = require('uglifycss');
|
|
5
|
+
describe('Styles', () => {
|
|
6
|
+
let layout;
|
|
7
|
+
beforeEach(() => layout = new Layout());
|
|
8
|
+
|
|
9
|
+
it('should not add style if styles are invalid', () => {
|
|
10
|
+
assert.throws(() => layout.style(123))
|
|
11
|
+
// layout.style(123);
|
|
12
|
+
// assert.strictEqual(layout.root.$('style'), null, 'Style should not be added when styles are invalid');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should add style correctly', () => {
|
|
16
|
+
const styles = 'body { background-color: black; }';
|
|
17
|
+
layout.style(styles);
|
|
18
|
+
assert(layout.root.$('style').innerHTML.includes(styles), 'Styles not set correctly');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('should add styles to existing style tag', () => {
|
|
22
|
+
assert(layout.root.$$('style').length === 0)
|
|
23
|
+
const styles1 = 'body { background-color: black; }';
|
|
24
|
+
const styles2 = 'body { margin: 0; }';
|
|
25
|
+
layout.style(styles1);
|
|
26
|
+
assert(layout.root.$$('style').length === 1)
|
|
27
|
+
layout.style(styles2);
|
|
28
|
+
assert(layout.root.$$('style').length === 1)
|
|
29
|
+
const inner = layout.root.$('style').innerHTML
|
|
30
|
+
assert(inner.includes(styles1));
|
|
31
|
+
assert(inner.includes(styles2));
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should add minified style', () => {
|
|
35
|
+
const styles = 'body { color: blue; } div { font-size: 12px; }';
|
|
36
|
+
const uglified = uglifycss.processString(styles);
|
|
37
|
+
layout.style(styles,true);
|
|
38
|
+
assert(layout.root.$('style').innerHTML === uglified, 'Styles should be minified');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
})
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const { describe, it, beforeEach } = require('node:test')
|
|
3
|
+
const Layout = require('../index');
|
|
4
|
+
|
|
5
|
+
describe('Url', () => {
|
|
6
|
+
let layout;
|
|
7
|
+
beforeEach(() => layout = new Layout());
|
|
8
|
+
|
|
9
|
+
it('should not add canonical URL if URL is invalid', () => {
|
|
10
|
+
layout.url('not-a-url', 'aa');
|
|
11
|
+
assert.strictEqual(layout.root.$('link[rel="canonical"]'), null, 'Canonical URL should not be added for invalid URLs');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should add url correctly', () => {
|
|
15
|
+
const url = 'http://localhost';
|
|
16
|
+
layout.url(url);
|
|
17
|
+
assert(layout.root.$('link[rel="canonical"]').getAttribute('href') === url, 'Canonical URL not set correctly');
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should add og:url meta correctly', () => {
|
|
21
|
+
const url = 'http://example.com';
|
|
22
|
+
const host = 'http://example.com';
|
|
23
|
+
layout.url(url, host);
|
|
24
|
+
assert.strictEqual(layout.root.$('meta[property="og:url"]').getAttribute('content'), url, 'og:url meta not set correctly');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should add canonical link if not already present', () => {
|
|
28
|
+
const url = 'http://example.com';
|
|
29
|
+
const host = 'http://example.com';
|
|
30
|
+
layout.url(url, host);
|
|
31
|
+
assert.strictEqual(layout.root.$('link[rel="canonical"]').getAttribute('href'), url, 'Canonical link should be added if not present');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should update existing canonical link', () => {
|
|
35
|
+
const initialUrl = 'http://example.com/initial';
|
|
36
|
+
const newUrl = 'http://example.com/new';
|
|
37
|
+
const host = 'http://example.com';
|
|
38
|
+
layout.url(initialUrl, host);
|
|
39
|
+
layout.url(newUrl, host);
|
|
40
|
+
assert.strictEqual(layout.root.$('link[rel="canonical"]').getAttribute('href'), newUrl, 'Canonical link should be updated with new URL');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should handle invalid URL with valid host', () => {
|
|
44
|
+
layout.url('http://', 'http://example.com');
|
|
45
|
+
assert.strictEqual(layout.root.$('meta[property="og:url"]'), null, 'Meta og:url should not be added for invalid URL');
|
|
46
|
+
assert.strictEqual(layout.root.$('link[rel="canonical"]'), null, 'Canonical link should not be added for invalid URL');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
const assert = require('assert');
|
|
2
|
+
const { describe, it, beforeEach } = require('node:test')
|
|
3
|
+
const Layout = require('../index');
|
|
4
|
+
|
|
5
|
+
describe('layout.viewport',() => {
|
|
6
|
+
let layout;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => layout = new Layout());
|
|
9
|
+
|
|
10
|
+
it('should update existing viewport meta correctly', () => {
|
|
11
|
+
// Добавляем изначальный viewport
|
|
12
|
+
const initialContent = 'width=device-width, initial-scale=1.0';
|
|
13
|
+
layout.viewport(initialContent);
|
|
14
|
+
|
|
15
|
+
// Обновляем viewport
|
|
16
|
+
const updatedContent = 'width=device-width, initial-scale=2.0';
|
|
17
|
+
layout.viewport(updatedContent);
|
|
18
|
+
|
|
19
|
+
// Проверяем, что содержимое meta обновлено
|
|
20
|
+
assert.strictEqual(layout.root.$('meta[name="viewport"]').getAttribute('content'), updatedContent, 'Existing viewport meta content should be updated');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should not add a second viewport meta if one already exists', () => {
|
|
24
|
+
// Добавляем изначальный viewport
|
|
25
|
+
const initialContent = 'width=device-width, initial-scale=1.0';
|
|
26
|
+
layout.viewport(initialContent);
|
|
27
|
+
|
|
28
|
+
// Пытаемся добавить ещё один
|
|
29
|
+
const secondContent = 'width=device-width, initial-scale=2.0';
|
|
30
|
+
layout.viewport(secondContent);
|
|
31
|
+
|
|
32
|
+
// Проверяем, что в документе только один элемент meta viewport
|
|
33
|
+
assert.strictEqual(layout.root.$$(`meta[name="viewport"]`).length, 1, 'Only one viewport meta should exist');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should add viewport correctly', () => {
|
|
37
|
+
const viewportContent = 'width=device-width, initial-scale=1.0';
|
|
38
|
+
layout.viewport(viewportContent);
|
|
39
|
+
assert.strictEqual(layout.root.$('meta[name="viewport"]').getAttribute('content'), viewportContent, 'Viewport not set correctly');
|
|
40
|
+
});
|
|
41
|
+
})
|
package/lib/elements/add-meta.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
const { SingleNode } = require('als-document')
|
|
2
|
-
function addMeta(props, layout) {
|
|
3
|
-
const entries = Object.entries(props)
|
|
4
|
-
const [name, value] = entries[0]
|
|
5
|
-
const selector = `meta[${name}="${value}"]`
|
|
6
|
-
const metaElement = layout.root.$(selector)
|
|
7
|
-
if (metaElement) entries.forEach(([name, v]) => metaElement.setAttribute(name, props[name]))
|
|
8
|
-
else layout.head.insert(2, new SingleNode('meta', props))
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
module.exports = addMeta
|
package/lib/elements/charset.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
const { SingleNode } = require('als-document')
|
|
2
|
-
|
|
3
|
-
module.exports = function (charset = 'UTF-8', layout) {
|
|
4
|
-
const charsetElement = layout.head.$('meta[charset]')
|
|
5
|
-
if (charsetElement) charsetElement.setAttribute('charset', charset)
|
|
6
|
-
else layout.head.insert(2, new SingleNode('meta', { charset }))
|
|
7
|
-
return layout
|
|
8
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
const addMeta = require('./add-meta')
|
|
2
|
-
|
|
3
|
-
function addDescription(description, layout) {
|
|
4
|
-
addMeta({ name: 'description', content: description }, layout)
|
|
5
|
-
addMeta({ property: 'og:description', content: description }, layout)
|
|
6
|
-
addMeta({ property: 'twitter:description', content: description }, layout)
|
|
7
|
-
return layout
|
|
8
|
-
}
|
|
9
|
-
module.exports = addDescription
|
package/lib/elements/favicon.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
const { SingleNode } = require('als-document')
|
|
2
|
-
|
|
3
|
-
function addFavicon(href,layout) {
|
|
4
|
-
const faviconElement = layout.root.$('link[rel=icon][type=image/x-icon]')
|
|
5
|
-
if(faviconElement) faviconElement.setAttribute('href',href)
|
|
6
|
-
else layout.head.insert(2,new SingleNode('link',{rel:'icon',href,type:'image/x-icon'}))
|
|
7
|
-
return layout
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
module.exports = addFavicon
|
package/lib/elements/image.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
const addMeta = require('./add-meta')
|
|
2
|
-
function addImage(image,version, layout) {
|
|
3
|
-
if (image && version) image += (image.includes('?') ? '&' : '?') + `v=${version}`
|
|
4
|
-
|
|
5
|
-
addMeta({property:'og:image',content:image},layout)
|
|
6
|
-
addMeta({name:'twitter:image',content:image},layout)
|
|
7
|
-
addMeta({name:'twitter:card',content:'summary_large_image'},layout)
|
|
8
|
-
return layout
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
module.exports = addImage
|
package/lib/elements/index.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
const addKeywords = require('./keywords')
|
|
2
|
-
const addStyle = require('./style')
|
|
3
|
-
const addDescription = require('./description')
|
|
4
|
-
const addTitle = require('./title')
|
|
5
|
-
const addImage = require('./image')
|
|
6
|
-
const addUrl = require('./url')
|
|
7
|
-
const addFavicon = require('./favicon')
|
|
8
|
-
const addScript = require('./script')
|
|
9
|
-
const addLink = require('./link')
|
|
10
|
-
const charset = require('./charset')
|
|
11
|
-
const viewport = require('./viewport')
|
|
12
|
-
module.exports = {
|
|
13
|
-
addKeywords, addStyle, addDescription, addTitle, addImage,
|
|
14
|
-
addUrl, addFavicon, addScript,addLink,charset,viewport
|
|
15
|
-
}
|
package/lib/elements/keywords.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
const { SingleNode } = require('als-document')
|
|
2
|
-
|
|
3
|
-
function keywords(keywords = [], layout) {
|
|
4
|
-
const { root } = layout
|
|
5
|
-
let keywordsElement = root.$('meta[name=keywords]')
|
|
6
|
-
if (!keywordsElement) keywordsElement = new SingleNode('meta', { name: 'keywords' })
|
|
7
|
-
const content = keywordsElement.getAttribute('content')
|
|
8
|
-
const existingKeywords = content ? content.split(',') : []
|
|
9
|
-
keywords.forEach(keyword => {
|
|
10
|
-
keyword = keyword.trim()
|
|
11
|
-
if (!existingKeywords.includes(keyword)) existingKeywords.push(keyword)
|
|
12
|
-
});
|
|
13
|
-
if(existingKeywords.length) {
|
|
14
|
-
keywordsElement.setAttribute('content', existingKeywords.join())
|
|
15
|
-
layout.head.insert(2, keywordsElement)
|
|
16
|
-
}
|
|
17
|
-
return layout
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
module.exports = keywords
|
package/lib/elements/link.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
const { SingleNode } = require('als-document')
|
|
2
|
-
function addLink(href, version, layout) {
|
|
3
|
-
if(!href || typeof href !== 'string') return layout
|
|
4
|
-
if (href && version) href += (href.includes('?') ? '&' : '?') + `v=${version}`
|
|
5
|
-
const selector = `link[rel=stylesheet][href^="${href}"]`
|
|
6
|
-
let linkElement = layout.root.$(selector)
|
|
7
|
-
if (linkElement) return
|
|
8
|
-
linkElement = new SingleNode('link', { rel: 'stylesheet', href })
|
|
9
|
-
layout.head.insert(2, linkElement)
|
|
10
|
-
return layout
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
module.exports = addLink
|
package/lib/elements/script.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
const { Node } = require('als-document')
|
|
2
|
-
function addScript(attrs = {}, innerHTML = '', head = true, version, layout) {
|
|
3
|
-
if(typeof attrs !== 'object' || attrs === null || Array.isArray(attrs)) attrs = {}
|
|
4
|
-
if(attrs.src) {
|
|
5
|
-
const selector = `script[src="${attrs.src}"]`
|
|
6
|
-
if (attrs.src && layout.root.$(selector)) return layout
|
|
7
|
-
if (attrs.src && version) attrs.src += (attrs.src.includes('?') ? '&' : '?') + `v=${version}`
|
|
8
|
-
}
|
|
9
|
-
if(Object.keys(attrs).length || innerHTML) {
|
|
10
|
-
const script = new Node('script', attrs)
|
|
11
|
-
if(innerHTML) script.innerHTML = innerHTML
|
|
12
|
-
if (head) layout.head.insert(2, script)
|
|
13
|
-
else layout.body.insert(3, script)
|
|
14
|
-
}
|
|
15
|
-
return layout
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
module.exports = addScript
|
package/lib/elements/style.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
const CssParser = require('als-css-parser');
|
|
2
|
-
const Simple = require('als-simple-css')
|
|
3
|
-
const { Node } = require('als-document')
|
|
4
|
-
function checkStyles(styles, minified) {
|
|
5
|
-
if (Array.isArray(styles)) styles = new Simple(styles).stylesheet(minified)
|
|
6
|
-
else if(typeof styles === 'string') {
|
|
7
|
-
styles = styles.trim()
|
|
8
|
-
if (minified) {
|
|
9
|
-
const cssParser = new CssParser(styles);
|
|
10
|
-
styles = cssParser.minified()
|
|
11
|
-
}
|
|
12
|
-
} else return null
|
|
13
|
-
return styles
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function addStyle(styles, minified=false,layout) {
|
|
17
|
-
styles = checkStyles(styles,minified)
|
|
18
|
-
if(!styles) return layout
|
|
19
|
-
let styleElement = layout.root.$('style')
|
|
20
|
-
if(!styleElement) {
|
|
21
|
-
styleElement = new Node('style')
|
|
22
|
-
styleElement.innerHTML = styles
|
|
23
|
-
layout.head.insert(2, styleElement)
|
|
24
|
-
} else {
|
|
25
|
-
styleElement.innerHTML = styleElement.innerHTML + '\n' + styles
|
|
26
|
-
}
|
|
27
|
-
return layout
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
module.exports = addStyle
|
package/lib/elements/title.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
const addMeta = require('./add-meta')
|
|
2
|
-
|
|
3
|
-
function addTitle(title,layout) {
|
|
4
|
-
const element = layout.root.$('title')
|
|
5
|
-
if(element) element.innerHTML = title
|
|
6
|
-
else layout.head.insert(2,/*html*/`<title>${title}</title>`)
|
|
7
|
-
addMeta({property:'og:title',content:title},layout)
|
|
8
|
-
return layout
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
module.exports = addTitle
|
package/lib/elements/url.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
const addMeta = require('./add-meta')
|
|
2
|
-
const { SingleNode } = require('als-document')
|
|
3
|
-
|
|
4
|
-
function getUrl(url, host, layout) {
|
|
5
|
-
try {
|
|
6
|
-
url = new URL(url, host).href.replace(/\/$/, '')
|
|
7
|
-
addMeta({ property: 'og:url', content: url }, layout)
|
|
8
|
-
const canonicalElement = layout.root.$('link[rel="canonical"]')
|
|
9
|
-
if (canonicalElement) canonicalElement.setAttribute('href', url)
|
|
10
|
-
else layout.head.insert(2, new SingleNode('link', { rel: 'canonical', href: url }))
|
|
11
|
-
} catch (error) {
|
|
12
|
-
console.log(`url ${url} with host ${host} is not valid url`)
|
|
13
|
-
}
|
|
14
|
-
return layout
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module.exports = getUrl
|
package/lib/elements/viewport.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
const { SingleNode } = require('als-document')
|
|
2
|
-
|
|
3
|
-
module.exports = function (viewport, layout) {
|
|
4
|
-
const element = layout.root.$('meta[name="viewport"]')
|
|
5
|
-
if (element) element.setAttribute('content', viewport)
|
|
6
|
-
else layout.head.insert(2, new SingleNode('meta', { name: 'viewport', content: viewport }))
|
|
7
|
-
return layout
|
|
8
|
-
}
|
package/lib/layout.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
const { Document } = require('als-document')
|
|
2
|
-
const onload = require('./onload')
|
|
3
|
-
const render = require('./render')
|
|
4
|
-
const {
|
|
5
|
-
addKeywords, addStyle, addDescription, addTitle, addImage,
|
|
6
|
-
addUrl, addFavicon, addScript, addLink, charset, viewport
|
|
7
|
-
} = require('./elements/index')
|
|
8
|
-
|
|
9
|
-
class Layout extends Document {
|
|
10
|
-
constructor(html, url) {super(html, url); this.root = this.html}
|
|
11
|
-
onload() { this.script({}, onload); return this }
|
|
12
|
-
lang(lang) { this.html.setAttribute('lang', lang); return this }
|
|
13
|
-
version(v) { this.v = v; return this; }
|
|
14
|
-
charset(newCharset = 'UTF-8') { return charset(newCharset, this) }
|
|
15
|
-
keywords(keywords = []) { return addKeywords(keywords, this) }
|
|
16
|
-
description(description) { return addDescription(description, this) }
|
|
17
|
-
title(title) { return addTitle(title, this) }
|
|
18
|
-
style(styles, minified) { return addStyle(styles, minified, this) }
|
|
19
|
-
image(image, v = this.v) { return addImage(image, v, this) }
|
|
20
|
-
url(url, host = this.URL) { return addUrl(url, host, this) }
|
|
21
|
-
favicon(href) { return addFavicon(href, this) }
|
|
22
|
-
script(attributes, innerHTML, head = true, v = this.v) { return addScript(attributes, innerHTML, head, v, this) }
|
|
23
|
-
link(href, v = this.v) { return addLink(href, v, this) }
|
|
24
|
-
viewport(newViewport = 'width=device-width, initial-scale=1.0') { return viewport(newViewport, this) }
|
|
25
|
-
get rawHtml() { return this.innerHTML }
|
|
26
|
-
get clone() { return new Layout(new Document(this), this.URL) }
|
|
27
|
-
render(path, selector, makeBundle) {return render(path, selector, makeBundle,this)}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
module.exports = Layout
|
package/lib/onload.js
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
module.exports = `document.addEventListener('DOMContentLoaded', function() {
|
|
2
|
-
const elements = document.querySelectorAll('[onload]');
|
|
3
|
-
elements.forEach(element => {
|
|
4
|
-
const onloadCode = element.getAttribute('onload');
|
|
5
|
-
const func = Function('"use strict"; return function() { ' + onloadCode + ' }');
|
|
6
|
-
func().call(element);
|
|
7
|
-
element.removeAttribute('onload');
|
|
8
|
-
});
|
|
9
|
-
});`
|
package/lib/render.js
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
const render = require('als-render')
|
|
2
|
-
module.exports = function (path, selector, makeBundle, layout) {
|
|
3
|
-
const element = layout.$(selector)
|
|
4
|
-
if (!element) return layout
|
|
5
|
-
const { rawHtml, bundle } = render(path)
|
|
6
|
-
element.innerHTML = rawHtml
|
|
7
|
-
if (typeof makeBundle === 'object') {
|
|
8
|
-
const { update = true, minified = true } = makeBundle
|
|
9
|
-
layout.script({}, bundle(selector, update, minified), false)
|
|
10
|
-
}
|
|
11
|
-
return layout
|
|
12
|
-
}
|
package/tests/counter/App.js
DELETED
package/tests/counter/build.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const Layout = require('../../lib/layout')
|
|
3
|
-
|
|
4
|
-
// Create and configure the layout
|
|
5
|
-
const layout = new Layout().title('Counter')
|
|
6
|
-
|
|
7
|
-
// Measure render time and generate HTML
|
|
8
|
-
const time1 = performance.now()
|
|
9
|
-
const { rawHtml } = layout.render('./App', 'body', {minified:true})
|
|
10
|
-
const time2 = performance.now()
|
|
11
|
-
console.log(`${time2 - time1}ms`) // e.g., 1.0649ms
|
|
12
|
-
|
|
13
|
-
// Write the output to a file
|
|
14
|
-
fs.writeFileSync('counter.html', rawHtml, 'utf-8')
|
package/tests/counter/counter.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
function Counter() {
|
|
2
|
-
function change(m=1) {
|
|
3
|
-
context.count += 1*m
|
|
4
|
-
Counter.update()
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
return (<div>
|
|
8
|
-
<button onclick={() => change(1)}>Increase</button>
|
|
9
|
-
<span component="counter">{context.count}</span>
|
|
10
|
-
<button onclick={() => change(-1)}>Decrease</button>
|
|
11
|
-
</div>)
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
module.exports = Counter
|