als-layout 2.1.0 → 2.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/build-readme.js +8 -0
- package/docs/#.md +27 -0
- package/docs/0-change-log.md +23 -0
- package/docs/1-basic-usage.md +49 -0
- package/docs/2-cloning.md +19 -0
- package/docs/3-advanced-usage.md +43 -0
- package/docs/4-render.md +71 -0
- package/lib/layout.js +28 -63
- package/lib/render/build-app.js +4 -3
- package/lib/render/component-hierarchy.js +7 -7
- package/lib/render/update.js +19 -0
- package/package.json +2 -2
- package/readme.md +154 -63
- package/tests/build-app.test.js +2 -2
- package/tests/component-hierarchy.test.js +1 -1
- package/tests/constructor.test.js +5 -12
- package/tests/elements.test.js +11 -4
- package/tests/layout.test.js +10 -15
- package/lib/build-root.js +0 -16
- package/lib/data/languages.js +0 -2
- package/tests/build-root.test.js +0 -45
package/readme.md
CHANGED
|
@@ -1,24 +1,69 @@
|
|
|
1
|
-
#
|
|
1
|
+
# als-layout Documentation
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Library Description
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
### What is it?
|
|
6
|
+
`als-layout` is a JavaScript library designed to simplify and enhance the process of constructing and managing web page layouts. It provides a comprehensive API for modifying HTML documents dynamically, allowing developers to add, update, and manipulate various elements such as meta tags, styles, scripts, and more.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
* onload() method
|
|
10
|
-
* bugs fixed
|
|
8
|
+
### Why is it needed?
|
|
9
|
+
Managing HTML document structures and their contents can often become repetitive and error-prone when done manually. `als-modular` offers a structured and reusable approach, reducing development time and improving code maintainability.
|
|
11
10
|
|
|
12
|
-
|
|
11
|
+
### What can you do with it and where can it be used?
|
|
12
|
+
The `als-layout` library is versatile, suitable for:
|
|
13
|
+
- Building dynamic web pages that require frequent updates to their metadata, styles, or scripts.
|
|
14
|
+
- Creating templating systems where multiple page layouts share similar structures but differ in content or styling.
|
|
15
|
+
- Developing web applications that need to dynamically adjust their UI based on user interactions or data changes.
|
|
16
|
+
This library is particularly useful in environments where rapid development and modular design are prioritized.
|
|
17
|
+
|
|
18
|
+
## Installation and Adding
|
|
19
|
+
To use the `als-layout` library in your project, you can install it via npm and then include it in your JavaScript files:
|
|
13
20
|
|
|
14
21
|
```bash
|
|
15
22
|
npm i als-layout
|
|
16
23
|
```
|
|
17
24
|
|
|
25
|
+
```js
|
|
26
|
+
const Layout = require('als-layout')
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Change Log
|
|
30
|
+
* V2.3.0
|
|
31
|
+
* Default, component will not be included in $App, if not [publish] attribute
|
|
32
|
+
* When cloning, components and other staff cloned too
|
|
33
|
+
* Reference does not change
|
|
34
|
+
|
|
35
|
+
* V2.2.0
|
|
36
|
+
* fixed empty update function if no components for $App
|
|
37
|
+
* if component function return string, it will element.innerHTML = string
|
|
38
|
+
* Now each Layout extends Document (als-document)
|
|
39
|
+
* layout.$ and layout.$$
|
|
40
|
+
* Also $App.$ and $App.$$ on backend too
|
|
41
|
+
* no langs validation any more
|
|
42
|
+
* lang method instead
|
|
43
|
+
* no layout.cached
|
|
44
|
+
* charset meta tag allready exists by default
|
|
45
|
+
|
|
46
|
+
* V2.1.0
|
|
47
|
+
* updated als-document version
|
|
48
|
+
* [part] attribute for static components
|
|
49
|
+
* onload() method
|
|
50
|
+
* bugs fixed
|
|
51
|
+
|
|
52
|
+
|
|
18
53
|
## Basic Usage
|
|
19
54
|
|
|
55
|
+
### Initialization
|
|
56
|
+
To start using `als-layout`, you first need to create a new instance of `Layout`. This instance will serve as the foundation for building and modifying your web page.
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
const Layout = require('als-layout');
|
|
60
|
+
const layout = new Layout();
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Adding Different Elements
|
|
64
|
+
Once you have your `Layout` instance, you can easily add or modify various elements of your web page. Here are some examples of how you can use the library to customize your layout:
|
|
65
|
+
|
|
20
66
|
```js
|
|
21
|
-
const Layout = require('als-layout')
|
|
22
67
|
const layout = new Layout()
|
|
23
68
|
.charset() // default UTF-8
|
|
24
69
|
.viewport() // default width=device-width, initial-scale=1.0
|
|
@@ -38,108 +83,154 @@ const layout = new Layout()
|
|
|
38
83
|
// Accessors for document parts
|
|
39
84
|
layout.body // getter for body element (if not exists, created)
|
|
40
85
|
layout.head // getter for head element (if not exists, created)
|
|
41
|
-
layout.html // getter for html
|
|
86
|
+
layout.html // getter for html Element (if not exists, created)
|
|
42
87
|
|
|
43
88
|
// Outputs
|
|
44
|
-
layout.rawHtml // raw
|
|
45
|
-
layout.
|
|
46
|
-
layout.clone // new layout object clone for current object
|
|
89
|
+
layout.rawHtml // raw HTML of the document
|
|
90
|
+
layout.clone // creates a new layout object clone for current object
|
|
47
91
|
```
|
|
48
92
|
|
|
93
|
+
### onload
|
|
94
|
+
|
|
95
|
+
By adding onload attribute, you can run scripts for each element after dom content has loaded.
|
|
96
|
+
|
|
97
|
+
Example how it works:
|
|
98
|
+
```js
|
|
99
|
+
const layout = new Layout().charset().viewport().title('On load').onload()
|
|
100
|
+
layout.body.innerHTML = /*html*/`<div onload="this.innerHTML = 'new content'">original content</div>`
|
|
101
|
+
```
|
|
102
|
+
## Cloning Functionality
|
|
103
|
+
|
|
104
|
+
### What is Cloning and Why is it Necessary?
|
|
105
|
+
Cloning in the `als-layout` library refers to creating a complete, independent copy of the existing `Layout` instance. This functionality is crucial when you need to generate multiple pages or versions of a page from a single base layout without affecting the original setup.
|
|
106
|
+
|
|
107
|
+
### How to Use Cloning
|
|
108
|
+
To clone a `Layout` instance, simply use the `clone` method. This method creates a new `Layout` instance with the same properties and settings as the original, allowing for independent modifications without interference.
|
|
109
|
+
|
|
110
|
+
```js
|
|
111
|
+
const newLayout = layout.clone;
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Benefits of Cloning
|
|
115
|
+
- **Efficiency:** Cloning is highly efficient, especially for creating pages with similar structures but different content or styles. It avoids the overhead of reinitializing and reconfiguring a new `Layout` instance from scratch.
|
|
116
|
+
- **Speed:** Cloning is fast, typically taking less than 20ms even for large pages. This makes it ideal for high-performance web applications that need to dynamically generate content.
|
|
117
|
+
- **Isolation:** Changes made to a cloned `Layout` do not affect the original, ensuring that each instance can be modified independently based on specific requirements.
|
|
118
|
+
|
|
119
|
+
Cloning is particularly useful in scenarios where templates or base layouts are used repeatedly with slight variations, providing a robust and scalable solution for web page generation.
|
|
120
|
+
|
|
121
|
+
|
|
49
122
|
## Advanced Usage
|
|
50
123
|
|
|
124
|
+
The `als-layout` library allows for sophisticated manipulation of web page layouts, providing robust tools for creating dynamic and complex web pages. Below is an advanced example demonstrating various capabilities of the library:
|
|
125
|
+
|
|
51
126
|
```js
|
|
52
|
-
const Layout = require('
|
|
127
|
+
const Layout = require('als-layout')
|
|
53
128
|
|
|
129
|
+
// Starting with a basic HTML template and specifying the host for URL methods
|
|
54
130
|
const raw = /*html*/`<html></html>`
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
lang:'fr' // for <html lang="fr"></html>
|
|
58
|
-
}
|
|
59
|
-
const layout = new Layout(raw, options)
|
|
131
|
+
const host = 'http://example.com';
|
|
132
|
+
const layout = new Layout(raw, host).lang('fr')
|
|
60
133
|
console.log(layout.rawHtml)
|
|
61
|
-
// <!DOCTYPE html><html lang="fr"><head></head><body></body></html>
|
|
134
|
+
// <!DOCTYPE html><html lang="fr"><head></p></head><body></body></html>
|
|
62
135
|
|
|
136
|
+
// Cloning the initial layout to create a specialized page
|
|
63
137
|
const homePage = layout.clone
|
|
138
|
+
homeAutoReload = layout.clone
|
|
64
139
|
homePage.title('Home page')
|
|
65
140
|
homePage.body.innerHTML = /*html*/`<h1>Home page</h1>`
|
|
66
141
|
console.log(homePage.rawHtml)
|
|
67
142
|
// <!DOCTYPE html><html lang="fr"><head><title>Home page</title><meta property="og:title" content="Home page"></head><body><h1>Home page</h1></body></html>
|
|
143
|
+
|
|
144
|
+
// Adding script that reloads the page every minute
|
|
145
|
+
homeAutoReload.script({}, 'setTimeout(function() { window.location.reload(); }, 60000);', false)
|
|
146
|
+
console.log(homeAutoReload.rawHtml)
|
|
147
|
+
// <!DOCTYPE html><html lang="fr"><head><title>Automatic Reload Page</title><meta property="og:title" content="Automatic Reload Page"></head><body><script>setTimeout(function() { window.location.reload(); }, 60000);</script></body></html>
|
|
148
|
+
|
|
149
|
+
// Demonstrating dynamic stylesheet linkage with versioning
|
|
150
|
+
const styleVersion = '1.1';
|
|
151
|
+
homePage.link('/css/main.css', styleVersion)
|
|
152
|
+
console.log(homePage.rawHtml)
|
|
153
|
+
// Includes link to the stylesheet with version parameter to ensure fresh cache
|
|
68
154
|
```
|
|
69
155
|
|
|
156
|
+
In this example:
|
|
157
|
+
- We start with a basic HTML template and use the `lang` method to set the language.
|
|
158
|
+
- We use the `clone` method to create two versions of the base layout: one for the home page and another that automatically reloads every minute.
|
|
159
|
+
- We manipulate the `body` of the `homePage` to include custom HTML.
|
|
160
|
+
- We add a script to `homeAutoReload` that sets up an automatic page reload, showcasing how to insert JavaScript dynamically.
|
|
161
|
+
- We dynamically add a versioned link to a stylesheet in the `homePage`, demonstrating control over caching and resource management.
|
|
162
|
+
|
|
163
|
+
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.
|
|
164
|
+
|
|
165
|
+
|
|
70
166
|
## Rendering
|
|
71
167
|
|
|
72
|
-
Each
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
layout
|
|
76
|
-
layout.utils
|
|
77
|
-
layout.actions
|
|
78
|
-
```
|
|
168
|
+
Each instance of `Layout` comes equipped with a `render` method that compiles the HTML structure and embeds a JavaScript object to manage the page dynamically. This object, known as `window.$App`, allows for real-time interaction and updates within the page.
|
|
169
|
+
|
|
170
|
+
### Structure
|
|
171
|
+
The layout object houses several key properties that facilitate dynamic content management:
|
|
79
172
|
|
|
80
|
-
|
|
173
|
+
- `layout.data`: Stores the data that can be used across the page, such as state variables or configuration settings.
|
|
174
|
+
- `layout.components`: Holds functions that define the behavior and rendering logic for components identified by specific attributes in the HTML.
|
|
175
|
+
- `layout.utils`: Contains utility functions that can be used throughout the page for common tasks.
|
|
176
|
+
- `layout.actions`: Methods that can be triggered by user interaction, often modifying `layout.data` and updating the page accordingly.
|
|
177
|
+
|
|
178
|
+
### The Render Method
|
|
179
|
+
The `render` method processes all elements with a `component` attribute, dynamically generating their content and behavior based on the defined components. After rendering, the page includes the `window.$App` JavaScript object, which provides methods and properties to interact with the page elements and data:
|
|
81
180
|
|
|
82
181
|
```js
|
|
83
182
|
window.$App = {
|
|
84
|
-
data,
|
|
85
|
-
components,
|
|
86
|
-
utils,
|
|
87
|
-
actions,
|
|
88
|
-
$(selector, parent=document),
|
|
89
|
-
$$(selector, parent=document),
|
|
90
|
-
update(element)
|
|
183
|
+
data, // Access to the layout data object
|
|
184
|
+
components, // Access to components functions
|
|
185
|
+
utils, // Access to utility functions
|
|
186
|
+
actions, // Access to action functions
|
|
187
|
+
$(selector, parent = document), // Equivalent to querySelector
|
|
188
|
+
$$(selector, parent = document), // Equivalent to querySelectorAll
|
|
189
|
+
update(element) { // Updates the element if it has a component attribute
|
|
190
|
+
// Update logic here
|
|
191
|
+
}
|
|
91
192
|
}
|
|
92
193
|
```
|
|
93
194
|
|
|
94
|
-
|
|
95
|
-
|
|
195
|
+
### Counter Example
|
|
196
|
+
To demonstrate dynamic interaction, consider a counter that can be increased or decreased through user input:
|
|
96
197
|
|
|
97
198
|
```js
|
|
98
199
|
const fs = require('fs')
|
|
99
200
|
const Layout = require('als-layout')
|
|
100
201
|
|
|
101
|
-
|
|
102
|
-
layout
|
|
202
|
+
// Create and configure the layout
|
|
203
|
+
const layout = new Layout().title('Counter')
|
|
204
|
+
layout.data.counter = 0 // Initialize counter data
|
|
205
|
+
|
|
206
|
+
// Define a component for displaying the counter
|
|
103
207
|
layout.components.counter = function(element, $App) {
|
|
104
208
|
element.innerHTML = `${$App.data.counter}`
|
|
105
209
|
}
|
|
106
210
|
|
|
211
|
+
// Define actions for increasing and decreasing the counter
|
|
107
212
|
layout.actions = {
|
|
108
|
-
increase: () => { $App.data.counter++; $App.update($App.$('[component=counter]')) },
|
|
109
|
-
decrease: () => { $
|
|
213
|
+
increase: () => { $App.data.counter++; $App.update($App.$('[component=counter]')); },
|
|
214
|
+
decrease: () => { $We render the html page to measure and write to a document.app.data.counter--; $Page updates are shown in real-time on the rendered HTML.$App.update($App.$('[component=counter]')); }
|
|
110
215
|
}
|
|
111
216
|
|
|
217
|
+
// Add buttons and the counter display to the body
|
|
112
218
|
layout.body.innerHTML = /*html*/`
|
|
113
219
|
<button onclick="$App.actions.increase()">Increase</button>
|
|
114
|
-
<span component="counter"></span>
|
|
220
|
+
<span component="counter" publish></span>
|
|
115
221
|
<button onclick="$App.actions.decrease()">Decrease</button>
|
|
116
222
|
`
|
|
223
|
+
|
|
224
|
+
// Measure render time and generate HTML
|
|
117
225
|
const time1 = performance.now()
|
|
118
226
|
const rawHtml = layout.render()
|
|
119
227
|
const time2 = performance.now()
|
|
120
228
|
console.log(`${time2 - time1}ms`) // e.g., 1.0649ms
|
|
121
229
|
|
|
230
|
+
// Write the output to a file
|
|
122
231
|
fs.writeFileSync('counter.html', rawHtml, 'utf-8')
|
|
123
232
|
```
|
|
124
233
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
### parts
|
|
132
|
-
|
|
133
|
-
By default render method adds all used components to `$App.components`.
|
|
134
|
-
By adding `part` attribute component will not be added, except cases, the component is part of another component.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
## onload
|
|
138
|
-
|
|
139
|
-
By adding onload attribute, you can run scripts for each element after dom content has loaded.
|
|
140
|
-
|
|
141
|
-
Example how it works:
|
|
142
|
-
```js
|
|
143
|
-
const layout = new Layout().charset().viewport().title('On load').onload()
|
|
144
|
-
layout.body.innerHTML = /*html*/`<div onload="this.innerHTML = 'new content'">original content</div>`
|
|
145
|
-
```
|
|
234
|
+
### Advanced Rendering Details
|
|
235
|
+
- **Component Indexing:** Each component is assigned a `componentIndex` during rendering, providing a unique index within its parent component.
|
|
236
|
+
- **Publish Attribute:** Using the `publish` attribute in a component make it being added to `$App.components`, unless it is nested within another component.
|
package/tests/build-app.test.js
CHANGED
|
@@ -17,13 +17,13 @@ describe('build-$App Functionality', () => {
|
|
|
17
17
|
const called = []
|
|
18
18
|
const done = [
|
|
19
19
|
{
|
|
20
|
-
getAttribute: (attr) => attr === 'component' ? 'comp1' : null,
|
|
20
|
+
getAttribute: (attr) => attr === 'component' ? 'comp1' : attr === 'publish' ? '' : null,
|
|
21
21
|
removeAttribute(att) {called.push(att)},
|
|
22
22
|
$$(){return []},
|
|
23
23
|
ancestors:2
|
|
24
24
|
},
|
|
25
25
|
{
|
|
26
|
-
getAttribute: (attr) => attr === 'component' ? 'comp2' : null,
|
|
26
|
+
getAttribute: (attr) => attr === 'component' ? 'comp2' : attr === 'publish' ? '' : null,
|
|
27
27
|
removeAttribute(att) {called.push(att)},
|
|
28
28
|
$$(){return []},
|
|
29
29
|
ancestors:2
|
|
@@ -13,7 +13,7 @@ function shuffleArray(array) {
|
|
|
13
13
|
|
|
14
14
|
describe('Basic tests', () => {
|
|
15
15
|
it('should build correct hierarchy', () => {
|
|
16
|
-
const root = parseHTML(/*html*/`<div component="some">
|
|
16
|
+
const root = parseHTML(/*html*/`<div component="some" publish>
|
|
17
17
|
<div>
|
|
18
18
|
<div component="some1"></div>
|
|
19
19
|
<div>
|
|
@@ -17,7 +17,8 @@ describe('Layout Initialization', () => {
|
|
|
17
17
|
it('should allow setting a custom language', () => {
|
|
18
18
|
const customLang = 'fr';
|
|
19
19
|
const layout = new Layout(undefined, { lang: customLang });
|
|
20
|
-
|
|
20
|
+
layout.lang(customLang)
|
|
21
|
+
assert(layout.html.getAttribute('lang') === customLang, `language is not set to ${customLang}`);
|
|
21
22
|
});
|
|
22
23
|
|
|
23
24
|
it('should initialize development mode as undefined or false', () => {
|
|
@@ -32,16 +33,8 @@ describe('Layout Initialization', () => {
|
|
|
32
33
|
|
|
33
34
|
it('should allow setting a custom host', () => {
|
|
34
35
|
const customHost = 'http://localhost';
|
|
35
|
-
const layout = new Layout(undefined,
|
|
36
|
-
|
|
36
|
+
const layout = new Layout(undefined,customHost);
|
|
37
|
+
console.log(layout.URL)
|
|
38
|
+
assert.strictEqual(layout.URL, customHost, `host is not set to ${customHost}`);
|
|
37
39
|
});
|
|
38
|
-
|
|
39
|
-
it('check method',() => {
|
|
40
|
-
const cached = cacheDoc(new Root())
|
|
41
|
-
const layout = new Layout(cached)
|
|
42
|
-
const root = layout.root
|
|
43
|
-
assert(root.$('html') !== null)
|
|
44
|
-
assert(root.$('head') !== null)
|
|
45
|
-
assert(root.$('body') !== null)
|
|
46
|
-
})
|
|
47
40
|
});
|
package/tests/elements.test.js
CHANGED
|
@@ -20,7 +20,7 @@ describe('Charset tests', () => {
|
|
|
20
20
|
it('should insert charset at second position if not present', () => {
|
|
21
21
|
const charset = 'UTF-8';
|
|
22
22
|
layout.charset(charset);
|
|
23
|
-
assert.strictEqual(layout.head.childNodes[0].tagName, '
|
|
23
|
+
assert.strictEqual(layout.head.childNodes[0].tagName, 'META', 'Meta should be at second position');
|
|
24
24
|
assert.strictEqual(layout.head.childNodes[0].getAttribute('charset'), charset, 'Charset not set correctly');
|
|
25
25
|
});
|
|
26
26
|
|
|
@@ -50,7 +50,7 @@ describe('Favicon tests', () => {
|
|
|
50
50
|
it('should insert favicon at second position if not present', () => {
|
|
51
51
|
const faviconHref = 'favicon.ico';
|
|
52
52
|
layout.favicon(faviconHref);
|
|
53
|
-
assert.strictEqual(layout.head.childNodes[0].tagName, '
|
|
53
|
+
assert.strictEqual(layout.head.childNodes[0].tagName, 'LINK', 'Favicon link should be at second position');
|
|
54
54
|
assert.strictEqual(layout.head.childNodes[0].getAttribute('href'), faviconHref, 'Favicon href not set correctly');
|
|
55
55
|
});
|
|
56
56
|
|
|
@@ -265,7 +265,7 @@ describe('Scripts', () => {
|
|
|
265
265
|
it('should add script after body when head is false', () => {
|
|
266
266
|
const scriptContent = 'console.log("Script in body");';
|
|
267
267
|
layout.script({ src: 'scriptbody.js' }, scriptContent, false);
|
|
268
|
-
assert.strictEqual(layout.body.next
|
|
268
|
+
assert.strictEqual(layout.body.next.innerHTML, scriptContent, 'Script should be added to body');
|
|
269
269
|
});
|
|
270
270
|
|
|
271
271
|
it('should append version parameter correctly when src already has parameters', () => {
|
|
@@ -328,7 +328,6 @@ describe('Url', () => {
|
|
|
328
328
|
layout.url('not-a-url', 'aa');
|
|
329
329
|
assert.strictEqual(layout.root.$('link[rel="canonical"]'), null, 'Canonical URL should not be added for invalid URLs');
|
|
330
330
|
});
|
|
331
|
-
|
|
332
331
|
|
|
333
332
|
it('should add url correctly', () => {
|
|
334
333
|
const url = 'http://localhost';
|
|
@@ -426,4 +425,12 @@ describe('description and title', () => {
|
|
|
426
425
|
assert(layout.root.$('[property="og:title"]').getAttribute('content') === title, 'Title not set correctly');
|
|
427
426
|
});
|
|
428
427
|
|
|
428
|
+
it('should add title if no title tag', () => {
|
|
429
|
+
layout.$('title').remove()
|
|
430
|
+
const title = 'Test Title';
|
|
431
|
+
layout.title(title);
|
|
432
|
+
assert(layout.root.$('title').innerHTML === title, 'Title not set correctly');
|
|
433
|
+
assert(layout.root.$('[property="og:title"]').getAttribute('content') === title, 'Title not set correctly');
|
|
434
|
+
});
|
|
435
|
+
|
|
429
436
|
});
|
package/tests/layout.test.js
CHANGED
|
@@ -47,7 +47,7 @@ describe('HTML Structure Initialization', () => {
|
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
it('should initialize html element correctly', () => {
|
|
50
|
-
assert.strictEqual(layout.html.tagName, '
|
|
50
|
+
assert.strictEqual(layout.html.tagName, 'HTML', 'HTML element should be initialized');
|
|
51
51
|
});
|
|
52
52
|
|
|
53
53
|
it('should not recreate html element if it already exists', () => {
|
|
@@ -56,7 +56,7 @@ describe('HTML Structure Initialization', () => {
|
|
|
56
56
|
});
|
|
57
57
|
|
|
58
58
|
it('should initialize body element correctly', () => {
|
|
59
|
-
assert.strictEqual(layout.body.tagName, '
|
|
59
|
+
assert.strictEqual(layout.body.tagName, 'BODY', 'Body element should be initialized');
|
|
60
60
|
});
|
|
61
61
|
|
|
62
62
|
it('should not recreate body element if it already exists', () => {
|
|
@@ -65,7 +65,7 @@ describe('HTML Structure Initialization', () => {
|
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
it('should initialize head element correctly', () => {
|
|
68
|
-
assert.strictEqual(layout.head.tagName, '
|
|
68
|
+
assert.strictEqual(layout.head.tagName, 'HEAD', 'Head element should be initialized');
|
|
69
69
|
});
|
|
70
70
|
|
|
71
71
|
it('should not recreate head element if it already exists', () => {
|
|
@@ -111,7 +111,7 @@ describe('Component Updating', () => {
|
|
|
111
111
|
element.insert(2, 'test1 success')
|
|
112
112
|
}
|
|
113
113
|
layout.data.test = 'hello'
|
|
114
|
-
layout.body.innerHTML = /*html*/`<div component="test1">
|
|
114
|
+
layout.body.innerHTML = /*html*/`<div component="test1" publish>
|
|
115
115
|
<div component="test2">failed</div>
|
|
116
116
|
</div>`
|
|
117
117
|
|
|
@@ -132,8 +132,8 @@ describe('Component Updating', () => {
|
|
|
132
132
|
|
|
133
133
|
it('should add part to $App if it is component`s descendant', () => {
|
|
134
134
|
layout.body.innerHTML = /*html*/`
|
|
135
|
-
<div component="parent">
|
|
136
|
-
<div component="child"
|
|
135
|
+
<div component="parent" publish>
|
|
136
|
+
<div component="child"></div>
|
|
137
137
|
</div>`;
|
|
138
138
|
layout.components.parent = (element, $App) => {};
|
|
139
139
|
layout.components.child = (element, $App) => {};
|
|
@@ -151,8 +151,8 @@ describe('Component Updating', () => {
|
|
|
151
151
|
|
|
152
152
|
it('should not add part to $App if it has no component ancestor', () => {
|
|
153
153
|
layout.body.innerHTML = /*html*/`
|
|
154
|
-
<div component="comp1"></div>
|
|
155
|
-
<div component="comp2"
|
|
154
|
+
<div component="comp1" publish></div>
|
|
155
|
+
<div component="comp2"></div>
|
|
156
156
|
`;
|
|
157
157
|
layout.components.comp1 = (element, $App) => {};
|
|
158
158
|
layout.components.comp2 = (element, $App) => {};
|
|
@@ -175,20 +175,15 @@ describe('Component Updating', () => {
|
|
|
175
175
|
|
|
176
176
|
});
|
|
177
177
|
|
|
178
|
-
describe('
|
|
178
|
+
describe('Clone Testing', () => {
|
|
179
179
|
let layout;
|
|
180
180
|
beforeEach(() => {
|
|
181
181
|
layout = new Layout();
|
|
182
182
|
});
|
|
183
183
|
|
|
184
|
-
it('should retrieve cached version of the layout', () => {
|
|
185
|
-
const cachedVersion = layout.cached;
|
|
186
|
-
assert.doesNotThrow(() => JSON.stringify(cachedVersion)) // should be object without recursions
|
|
187
|
-
assert(buildFromCache(cachedVersion).innerHTML === layout.rawHtml)
|
|
188
|
-
});
|
|
189
|
-
|
|
190
184
|
it('should clone the layout correctly', () => {
|
|
191
185
|
const clone = layout.clone;
|
|
186
|
+
console.log(clone.constructor.name)
|
|
192
187
|
assert(clone instanceof Layout, 'Clone should be an instance of Layout');
|
|
193
188
|
assert.notStrictEqual(clone, layout, 'Clone should not be the same instance as the original');
|
|
194
189
|
});
|
package/lib/build-root.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
const { buildFromCache, Root, parseHTML, cacheDoc, Document } = require('als-document')
|
|
2
|
-
|
|
3
|
-
function buildRoot(item) {
|
|
4
|
-
const root =
|
|
5
|
-
(item instanceof Root) ? buildFromCache(cacheDoc(item))
|
|
6
|
-
: (typeof item === 'string') ? parseHTML(item)
|
|
7
|
-
: (typeof item === 'object' && item.tagName) ? buildFromCache(item)
|
|
8
|
-
: new Root()
|
|
9
|
-
|
|
10
|
-
const firstNode = root.childNodes[0]
|
|
11
|
-
if(!firstNode || firstNode.tagName !== '!DOCTYPE') {root.insert(1,/*html*/`<!DOCTYPE html>`)}
|
|
12
|
-
|
|
13
|
-
return root
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
module.exports = buildRoot
|