@webqit/oohtml 2.1.60 → 2.1.61

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 CHANGED
@@ -7,19 +7,15 @@
7
7
 
8
8
  **[Overview](#overview) • [Modular HTML](#modular-html) • [HTML Imports](#html-imports) • [Reactive HTML](#reactive-html) • [Polyfill](#polyfill) • [Examples](#examples) • [License](#license)**
9
9
 
10
- Object-Oriented HTML (OOHTML) is a set of language features for authoring modular, reusable markup, and for translating that to functional DOM-level objects! Everything comes together as a delightful holistic component architecture for the modern UI!
11
-
12
- OOHTML is an upcoming proposal!
10
+ Object-Oriented HTML (OOHTML) is a set of language features for authoring modular, reusable and reactive markup which brings us to a whole new authoring experience on the modern UI!
13
11
 
14
12
  ## Motivation
15
13
 
16
14
  <details><summary>Show</summary>
17
15
 
18
- The web has generally outgrown the idea of a monolith architecture on the UI! But enter HTML; the current authoring experience is one where an author is trying to think out one thing but forced to work out everything, in how the language for the job poses one global scope as the unit of abstraction for styles, scripts and element identifiers enforcing many global dependencies; inflicting much global thinking!
19
-
20
- Think too of how authors often have to do half of the work in HTML and half in JS just to have reusable markup!
16
+ Vanilla HTML is increasingly becoming a more attractive option for web developers! But the current authoring experience still leaves much to be desired in how the language lacks modularity, reusability, and data binding! Authors still have to rely on tools - or, to say the least, do half of the work in HTML and half in JS - to get even basic things working!
21
17
 
22
- This project is a proposal for a new standards work that revisits much of the oldish monolith-oriented constraints in HTML that inhibit the idea of a *component* architecture in HTML!
18
+ This project pursues an object-oriented approach to HTML and implicitly revisits much of what inhibits the idea of a *component* architecture for HTML!
23
19
 
24
20
  └ [See more in the introductory blog post](https://dev.to/oxharris/the-web-native-equations-1m1p-temp-slug-6661657?preview=ba70ad2c17f05b5761bc74516dbde8c9eff8b581a0420d87334fd9ef6bab9d6e6d3ab6aaf3fe02542bb9e7250d0a88a6df91dae40919aabcc9a07320)<sup>draft</sup>
25
21
 
@@ -27,20 +23,27 @@ This project is a proposal for a new standards work that revisits much of the ol
27
23
 
28
24
  ## Overview
29
25
 
30
- OOHTML comes in three sets of features, and the following is an overview. A more detailed documentation for OOHTML is underway in the [project wiki](https://github.com/webqit/oohtml/wiki).
26
+ Here we extend standard HTML and the DOM to normalise certain fundamental concepts and paradigms that the ecosystem has explored over the years!
27
+
28
+ We go in three main focus areas:
31
29
 
32
30
  + [Modular HTML](#modular-html)
33
31
  + [HTML Imports](#html-imports)
34
- + [Reactive HTML](#reactive-html)
32
+ + [Data Binding](#data-binding)
33
+ + [Data Binding](#data-binding)
35
34
  + [Put Together](#put-together)
36
35
 
37
36
  > **Note** This is documentation for `OOHTML@2.x`. (Looking for [`OOHTML@1.x`](https://github.com/webqit/oohtml/tree/v1.10.4)?)
38
37
 
39
38
  ## Modular HTML
40
39
 
41
- The first set of features covers authoring objects with self-contained structure, styling and *scripting*! This simply gets identifiers, style sheets and scripts to serve *at the object level* exactly as they do *at the document (object) level*.
40
+ Modular HTML is a markup pattern that lets us write markup as self-contained objects - with each *encapsulating* its own structure, styling and logic - as against the regular idea of having everything converge and conflict on one global scope!
41
+
42
+ OOHTML makes this possible in just simple conventions - via two new attributes: `namespace` and `scoped`!
42
43
 
43
- *Namespaced IDs for modelling structure*:
44
+ ### Namespacing
45
+
46
+ └ The `namespace` attribute for designating an element as own naming context for identifiers - i.e. the `id` and `name` attributes:
44
47
 
45
48
  ```html
46
49
  <div id="user" namespace>
@@ -51,6 +54,8 @@ The first set of features covers authoring objects with self-contained structure
51
54
  </div>
52
55
  ```
53
56
 
57
+ *which translates really well to an object model*:
58
+
54
59
  ```html
55
60
  user
56
61
  ├── url
@@ -58,16 +63,58 @@ user
58
63
  └── email
59
64
  ```
60
65
 
66
+ *with a corresponding API that exposes said structure to JavaScript applications*:
67
+
61
68
  ```js
62
- // The namespace API
69
+ // The document.namespace API
63
70
  let { user } = document.namespace;
71
+ // The Element.prototype.namespace API
64
72
  let { url, name, email } = user.namespace;
65
73
  ```
66
74
 
67
- *Scoped styles and scripts for styling and functionality*:
75
+ <details><summary>Learn more</summary>
76
+
77
+ You want to see how IDs are otherwise exposed as global variables:
78
+
79
+ ```html
80
+ <div id="foo"><div>
81
+ ```
82
+
83
+ ```js
84
+ console.log(window.foo); // div
85
+ ```
86
+
87
+ [Read more](https://stackoverflow.com/questions/6381425/is-there-a-spec-that-the-id-of-elements-should-be-made-global-variable)
88
+
89
+ </details>
90
+
91
+ └ *A Namespace API that reflects the real-DOM&trade; in real-time*:
92
+
93
+ ```js
94
+ // Observing the addition or removal of elements with an ID
95
+ Observer.observe(document.namespace, changeCallback);
96
+
97
+ const paragraph = document.createElement('p');
98
+ paragraph.setAttribute('id', 'bar');
99
+ document.body.appendChild(paragraph); // Reported synchronously
100
+ ```
101
+
102
+ ```js
103
+ // Observing the addition or removal of elements with an ID
104
+ paragraph.toggleAttribute('namespace', true);
105
+ Observer.observe(paragraph.namespace, changeCallback);
106
+
107
+ const span = document.createElement('span');
108
+ span.setAttribute('id', 'baz');
109
+ paragraph.appendChild(span); // Reported synchronously
110
+ ```
111
+
112
+ ### Style and Script Scoping
113
+
114
+ └ The `scoped` attribute for *scoping* element-specific stylesheets and scripts:
68
115
 
69
116
  ```html
70
- <div id="user">
117
+ <div>
71
118
 
72
119
  <style scoped>
73
120
  :scope { color: red }
@@ -80,17 +127,23 @@ let { url, name, email } = user.namespace;
80
127
  </div>
81
128
  ```
82
129
 
130
+ *with a corresponding API that exposes said assets to JavaScript applications*:
131
+
83
132
  ```js
84
133
  let { styleSheets, scripts } = user; // APIs that are analogous to the document.styleSheets, document.scripts properties
85
134
  ```
86
135
 
87
- └ [Modular HTML concepts](#)
136
+ └ [Modular HTML examples](#modular-html-examples)
88
137
 
89
138
  ## HTML Imports
90
139
 
91
- The next set of features covers *templating and reusing objects* - in both *declarative* and *programmatic* terms! It extends the language with the *module identifier* attribute `def`, and introduces a complementary new `<import>` element, and has everything working together as a real-time module system.
140
+ HTML Imports is a realtime module system for *templating and reusing* HTML in HTML, and optionally in JavaScript! Something like it is the [`<defs>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs) and [`<use>`](https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use) system in SVG.
92
141
 
93
- *The `def` attribute for reusable "module" and "fragment" definitions*:
142
+ OOHTML makes this possible in just simple conventions - via a new `def` attribute and a complementary new `<import>` element!
143
+
144
+ ### Module Definition
145
+
146
+ └ The `def` attribute for defining reusable markup - either as whole *module* or as *fragment*:
94
147
 
95
148
  ```html
96
149
  <head>
@@ -104,7 +157,7 @@ The next set of features covers *templating and reusing objects* - in both *decl
104
157
  </head>
105
158
  ```
106
159
 
107
- *Module nesting for code organization*:
160
+ └ Module nesting for code organization:
108
161
 
109
162
  ```html
110
163
  <head>
@@ -120,16 +173,20 @@ The next set of features covers *templating and reusing objects* - in both *decl
120
173
  </head>
121
174
  ```
122
175
 
123
- *The `<template src>` element for remote modules*:
176
+ ### Remote Modules
177
+
178
+ └ The `<template src>` element for remote modules:
124
179
 
125
180
  ```html
126
181
  <template def="foo" src="/foo.html"></template>
182
+ <!-- which links to the file below -->
127
183
  ```
128
184
 
129
185
  ```html
130
186
  -- file: /foo.html --
131
187
  <div def="fragment1"></div>
132
188
  <template def="nested" src="/nested.html"></template>
189
+ <!-- which itself links to the file below -->
133
190
  ```
134
191
 
135
192
  ```html
@@ -138,11 +195,16 @@ The next set of features covers *templating and reusing objects* - in both *decl
138
195
  --
139
196
  ```
140
197
 
198
+ *which extends how elements like images already work; terminating with either a `load` or an `error` event*:
199
+
141
200
  ```js
142
- foo.addEventListener('load', loadedCallback);
201
+ foo.addEventListener('load', loadCallback);
202
+ foo.addEventListener('error', errorCallback);
143
203
  ```
144
204
 
145
- *The `<import>` element for declarative module import*:
205
+ ### Declarative Module Imports
206
+
207
+ └ The `<import>` element for declarative module import:
146
208
 
147
209
  ```html
148
210
  <body>
@@ -158,20 +220,140 @@ foo.addEventListener('load', loadedCallback);
158
220
  </body>
159
221
  ```
160
222
 
161
- *The HTMLImports API for programmatic module import*:
223
+ <details><summary>All in Realtime</summary>
224
+
225
+ As a realtime module system, `<import> `elements maintain a live relationship with given module definition `<template def>` elements and are resolved again in the event that:
226
+ + the `<import>` element points to another module — either by `ref` change or by a change in `importscontext` (below).
227
+ + the module definition `<template def>` element has had its contents updated, either programmatically or automatically from having loaded.
228
+
229
+ Conversely, an `<import>` element that has been resolved will self-restore in the event that:
230
+ + the `<import>` element no longer points to a module; or the module has been emptied or removed.
231
+ + the previously slotted contents have been programmatically removed and slot is empty.
232
+
233
+ </details>
234
+
235
+ <details><summary>With SSR Support</summary>
236
+
237
+ On the server, these `<import>` elements would retain their place in the DOM, but this time, serialized into comment nodes, while having their output rendered just above them as siblings.
238
+
239
+ The above resolved imports would thus give us something like:
240
+
241
+ ```html
242
+ <body>
243
+ <div def="fragment1"></div>
244
+ <!--&lt;import ref="/foo#fragment1"&gt;&lt;/import&gt;-->
245
+ <div def="fragment2"></div>
246
+ <!--&lt;import ref="/foo/nested#fragment2"&gt;&lt;/import&gt;-->
247
+ </body>
248
+ ```
249
+
250
+ But they also have to remember the exact imported nodes that they manage so as to be able to re-establish that relationship on getting to the client. This information is automatically encoded as part of the serialised element itself, in something like:
251
+
252
+ ```html
253
+ <!--&lt;import ref="/foo/nested#fragment2" nodecount="1"&gt;&lt;/import&gt;-->
254
+ ```
255
+
256
+ Now that extra bit of information gets decoded and original relationships are formed again on getting to the client and "hydrating" the `<import>` element. But, the `<import>` element itself stays invisible in the DOM while still continuing to kick as above!
257
+
258
+ > Note: We know we're on the server when `window.webqit.env === 'server'`. This flag is automatically set by OOHTML's current SSR engine: [OOHTML-SSR](https://github.com/webqit/oohtml-ssr)
259
+
260
+ </details>
261
+
262
+ ### Programmatic Module Imports
263
+
264
+ └ The *HTMLImports* API for programmatic module import:
265
+
266
+ ```js
267
+ const moduleObject1 = document.import('/foo#fragment1');
268
+ console.log(moduleObject1.value); // divElement
269
+ ```
270
+
271
+ ```js
272
+ const moduleObject2 = document.import('/foo/nested#fragment2');
273
+ console.log(moduleObject2.value); // divElement
274
+ ```
275
+
276
+ *with an observable `moduleObject.value` property for working asynchronously; e.g. awaiting and handling remote modules*:
277
+
278
+ ```js
279
+ Observer.observe(moduleObject2, 'value', e => {
280
+ console.log(e.value); // divElement
281
+ });
282
+ ```
283
+
284
+ *with an equivalent `callback` option on the `import()` method itself*:
285
+
286
+ ```js
287
+ document.import('/foo#fragment1', divElement => {
288
+ console.log(divElement);
289
+ });
290
+ ```
291
+
292
+ └ An optional `live` parameter for staying subscribed to any mutations made to source module elements:
293
+
294
+ ```js
295
+ const moduleObject2 = document.import('/foo/nested#fragment2', true/*live*/);
296
+ console.log(moduleObject2.value);
297
+ Observer.observe(moduleObject2, 'value', e => {
298
+ console.log(e.value);
299
+ });
300
+ ```
301
+
302
+ ```js
303
+ document.import('/foo#fragment1', true/*live*/, divElement => {
304
+ console.log(divElement); // To be received after remote module has been loaded
305
+ });
306
+ ```
307
+
308
+ *both of which would get notified on doing the below*:
309
+
310
+ ```js
311
+ document.querySelector('template[def="foo"]').content.firstElementChild.remove();
312
+ ```
313
+
314
+ └ An optional `AbortSignal` parameter for aborting module mutation events:
315
+
316
+ ```js
317
+ const abortController = new AbortController;
318
+ ```
319
+
320
+ ```js
321
+ const moduleObject2 = document.import('/foo/nested#fragment2', { live: true, signal: abortController.signal });
322
+ ```
162
323
 
163
324
  ```js
164
- const import1 = document.import('/foo#fragment1');
165
- console.log(import1); // { value: div }
325
+ document.import('/foo#fragment1', { live: true, signal: abortController.signal }, divElement => {
326
+ console.log(divElement); // To be received after remote module has been loaded
327
+ });
166
328
  ```
167
329
 
168
330
  ```js
169
- const import2 = document.import('/foo/nested#fragment2');
170
- console.log(import2); // { value: div }
331
+ setTimeout(() => abortController.abort(), 1000);
171
332
  ```
172
333
 
173
- *Scoped templates for object-scoped module system*:
174
- > With an equivalent `Element.prototype.import()` API for accessing scoped modules
334
+ <details><summary>Extended Imports concepts</summary>
335
+
336
+ ### Lazy-Loading Modules
337
+
338
+ └ Remote modules with lazy-loading - which has modules loading on first time access:
339
+
340
+ ```html
341
+ <!-- Loading doesn't happen until the first time this is being accessed -->
342
+ <template def="foo" src="/foo.html" loading="lazy"></template>
343
+ ```
344
+
345
+ ```html
346
+ <body>
347
+ <import ref="/foo#fragment1"></import> <!-- Triggers module loading and resolves on load success -->
348
+ </body>
349
+ ```
350
+ ```js
351
+ const moduleObject2 = document.import('/foo#fragment1'); // Triggers module loading and resolves at moduleObject2.value on load success
352
+ ```
353
+
354
+ ### Scoped Modules
355
+
356
+ └ The `scoped` attribute for an *object-scoped* module system:
175
357
 
176
358
  ```html
177
359
  <section> <!-- object with own modules -->
@@ -188,6 +370,8 @@ console.log(import2); // { value: div }
188
370
  </section>
189
371
  ```
190
372
 
373
+ *with an equivalent `Element.prototype.import()` API for accessing said scoped modules*:
374
+
191
375
  ```js
192
376
  // Using the HTMLImports API
193
377
  const moduleHost = document.querySelector('div');
@@ -202,11 +386,9 @@ const globalImport1 = moduleHost.import('/foo#fragment1'); // the global module:
202
386
  console.log(globalImport1); // { value: div }
203
387
  ```
204
388
 
205
- <details><summary>
206
- Extended Imports concepts
207
- </summary>
389
+ ### Module Inheritance
208
390
 
209
- *Module nesting with inheritance*:
391
+ └ Module nesting with inheritance:
210
392
 
211
393
  ```html
212
394
  <template def="foo">
@@ -250,34 +432,9 @@ Extended Imports concepts
250
432
  </body>
251
433
  ```
252
434
 
253
- *Remote modules with lazy-loading*:
254
-
255
- ```html
256
- <!-- Loading doesn't happen until the first time this is being accessed -->
257
- <template def="foo" src="/foo.html" loading="lazy"></template>
258
- ```
259
-
260
- ```html
261
- <body>
262
- <import ref="/foo#fragment1"></import> <!-- To be resolved after remote module has been loaded -->
263
- </body>
264
- ```
265
-
266
- ```js
267
- document.import('/foo#fragment1', divElement => {
268
- console.log(divElement); // To be received after remote module has been loaded
269
- });
270
- ```
435
+ ### Imports Contexts
271
436
 
272
- ```js
273
- const import1 = document.import('/foo#fragment1', true);
274
- console.log(import1); // { value: undefined }
275
- Observer.observe(import1, 'value', divElement => {
276
- console.log(divElement); // To be received after remote module has been loaded
277
- });
278
- ```
279
-
280
- └ *"Imports Contexts" for context-based imports resolution*:
437
+ └ "Imports Contexts" for context-based *import resolution*:
281
438
 
282
439
  ```html
283
440
  <body importscontext="/foo">
@@ -302,7 +459,7 @@ const globalImport2 = moduleHost.import('#fragment2'); // module:/foo/nested#fra
302
459
  console.log(globalImport2); // { value: div }
303
460
  ```
304
461
 
305
- *"Imports Contexts" with named contexts*:
462
+ └ "Imports Contexts" with named contexts:
306
463
 
307
464
  ```html
308
465
  <body contextname="context1" importscontext="/foo/nested">
@@ -326,7 +483,7 @@ const globalImport2 = moduleHost.import('@context1#fragment2'); // module:/foo/n
326
483
  console.log(globalImport2); // { value: div }
327
484
  ```
328
485
 
329
- *"Imports Contexts" with context inheritance*:
486
+ └ "Imports Contexts" with context inheritance:
330
487
 
331
488
  ```html
332
489
  <body importscontext="/foo">
@@ -340,7 +497,9 @@ console.log(globalImport2); // { value: div }
340
497
  </body>
341
498
  ```
342
499
 
343
- *Object-scoped module system with context inheritance*:
500
+ ### Scoped Modules and Imports Contexts
501
+
502
+ └ Object-scoped module system with context inheritance:
344
503
 
345
504
  ```html
346
505
  <body contextname="context1" importscontext="/bar">
@@ -370,10 +529,148 @@ console.log(localOrGlobalImport2); // { value: div }
370
529
 
371
530
  </details>
372
531
 
373
- └ [HTML Imports concepts](#)
532
+ └ [HTML Imports examples](#html-imports-examples)
533
+
534
+ ## Data Binding
535
+
536
+ Data binding is the concept of declaratively driving the UI with application-level data. It comes as mechanism that sits between the UI and the application itself, ensuring that the relevant parts of the UI are *automatically* updated as application state changes.
537
+
538
+ OOHTML makes this possible in just simple conventions - via a new comment-based data-binding syntax `<?{ }?>` and a complementary new `binding` attribute!
539
+
540
+ ### Comment-Based Data-Binding
541
+
542
+ └ A web-native, comment-based data-binding syntax `<?{ }?>` which works like regular comment but stay "data-charged":
543
+
544
+ ```js
545
+ <html>
546
+ <head>
547
+ <title><?{ app.title }?></title>
548
+ </head>
549
+ <body>
550
+ Hi, I'm <?{ app.name ?? 'Default name' }?>!
551
+ and here's another way to write the same comment: <!--?{ app.cool }?-->
552
+ </body>
553
+ </html>
554
+ ```
555
+
556
+ <details><summary>With SSR Support</summary>
557
+
558
+ On the server, these data-binding tags would retain their place in the DOM while having their output rendered to their right in a text node.
559
+
560
+ The following: `<?{ 'Hello World' }?>` would thus give us: `<?{ 'Hello World' }?>Hello World`.
561
+
562
+ But they also have to remember the exact text node that they manage, so as to be able to re-establish that relationship on getting to the client. That information is automatically encoded as part of the declaration itself, and that brings us to having a typical server-rendered binding look like this:
563
+
564
+ ```html
565
+ <?{ 'Hello World'; [=11] }?>Hello World
566
+ ```
567
+
568
+ Now that extra bit of information gets decoded and original relationships are forned again on getting to the client. But the binding tag itself graciously disappears from the DOM, while the now "hydrated" text node continues to kick!
569
+
570
+ > Note: We know we're on the server when `window.webqit.env === 'server'`. This flag is automatically set by OOHTML's current SSR engine: [OOHTML-SSR](https://github.com/webqit/oohtml-ssr)
571
+
572
+ </details>
573
+
574
+ ### Directives-Based Data-Binding
575
+
576
+ └ The `binding` attribute for a declarative and neat, key/value data-binding syntax:
577
+
578
+ ```html
579
+ <div binding="<type><parameter>: <argument>;"></div>
580
+ ```
581
+
582
+ *where*:
374
583
 
375
- ## Reactive HTML
584
+ + *`<type>` is the binding type, which is always a symbol*
585
+ + *`<directive>` is the binding directive, which could be any of CSS property, class name, attribute name, Structural Directive*
586
+ + *`<argument>` is the bound value or expression*
376
587
 
588
+ *which would give us the following for a CSS property*:
589
+
590
+ ```html
591
+ <div binding="&color: someColor; &backgroundColor: 'red'"></div>
592
+ ```
593
+
594
+ *with enough liberty to separate the binding type from the directive itself*:
595
+
596
+ ```html
597
+ <div binding="& color: someColor; & backgroundColor: 'red'"></div>
598
+ ```
599
+
600
+ *all of which can be seen here*:
601
+
602
+ | Symbol | Meaning | Usage |
603
+ | :---- | :---- | :---- |
604
+ | `&` | CSS Property | `<div binding="&color: someColor;"></div>` |
605
+ | `%` | Class Name | `<div binding="%active: app.isActive;"></div>` |
606
+ | `~` | Attribute Name | `<a binding="~href: person.profileUrl + '#bio';"></a>` |
607
+ | `@` | Structural Directive: | *See next table* |
608
+
609
+ <details><summary>Structural Directives</summary>
610
+
611
+ | Directive | Meaning | Usage |
612
+ | :---- | :---- | :---- |
613
+ | `@text` | For rendering plain text content | `<span binding="@text: firstName + ' ' + lastName;"></span>` |
614
+ | `@html` | For rendering markup content | `<span binding="@html: '<i>' + firstName + '</i>';"></span>` |
615
+ | `@items` | For rendering a list, with argument in the following format:<br>`<declaration> <of\|in> <iterable> / <importRef>` | *See next two tables* |
616
+
617
+ <details><summary>"For ... Of" Loops</summary>
618
+
619
+ | Idea | Usage |
620
+ | :---- | :---- |
621
+ | Loop over an array/iterable | `<ul binding="@items: value of [1,2,3] / 'foo#fragment';"></ul>` |
622
+ | Same as above but with a `key` declaration | `<ul binding="@items: (value, key) of [1,2,3] / 'foo#fragment';"></ul>` |
623
+ | Same as above but with different variable names | `<ul binding="@items: (product, id) of store.products / 'foo#fragment';"></ul>` |
624
+ | Same as above but with a dynamic `importRef` | `<ul binding="@items: (product, id) of store.products / store.importRef;"></ul>` |
625
+
626
+ </details>
627
+
628
+ <details><summary>"For ... In" Loops</summary>
629
+
630
+ | Idea | Usage |
631
+ | :---- | :---- |
632
+ | Loop over an object | `<ul binding="@items: key in { a: 1, b: 2 } / 'foo#fragment';"></ul>` |
633
+ | Same as above but with a `value` and `index` declaration | `<ul binding="@items: (key, value, index) in { a: 1, b: 2 } / 'foo#fragment';"></ul>` |
634
+
635
+ </details>
636
+
637
+ </details>
638
+
639
+ <details><summary>Example</summary>
640
+
641
+ ```html
642
+ <section>
643
+
644
+ <!-- The "items" template -->
645
+ <template def="item" scoped>
646
+ <li binding="@text: key + ': ' + name;"></li>
647
+ </template>
648
+
649
+ <!-- The loop -->
650
+ <ul binding="@items: (name, key) of ['dog','cat','ram'] / 'item';"></ul>
651
+
652
+ </section>
653
+ ```
654
+
655
+ </details>
656
+
657
+ <details><summary>All in Realtime</summary>
658
+
659
+ Lists are rendered in realtime, which means that in-place mutations - additions and removals - on the *iteratee* will be automatically reflected on the UI!
660
+
661
+ </details>
662
+
663
+ <details><summary>With SSR Support</summary>
664
+
665
+ Generated item elements are automatically assigned a corresponding index with a `data-index` attribute! This helps in remapping generated item nodes to their respective entry in *iteratee* - universally.
666
+
667
+ </details>
668
+
669
+ ## Component Plumbing
670
+
671
+ *[TODO]: The Context API and Bindings API*
672
+
673
+ <!--
377
674
  The last set of features covers the concept of "state", "bindings", and "reactivity" for those objects at the DOM level - in the most exciting form of the terms and as an upgrade path! This comes factored into the design as something intrinsic to the problem.
378
675
 
379
676
  └ *The [Observer API](https://github.com/webqit/observer) for general-purpose object observability*:
@@ -397,27 +694,6 @@ Observer.set(obj, 'prop1', 'value1'); // Reported synchronously
397
694
  Observer.deleteProperty(obj, 'prop1'); // Reported synchronously
398
695
  ```
399
696
 
400
- └ *A Namespace API that reflects the real-DOM&trade; in real-time*:
401
-
402
- ```js
403
- // Observing the addition or removal of elements with an ID
404
- Observer.observe(document.namespace, changeCallback);
405
-
406
- const paragraph = document.createElement('p');
407
- paragraph.setAttribute('id', 'bar');
408
- document.body.appendChild(paragraph); // Reported synchronously
409
- ```
410
-
411
- ```js
412
- // Observing the addition or removal of elements with an ID
413
- paragraph.toggleAttribute('namespace', true);
414
- Observer.observe(paragraph.namespace, changeCallback);
415
-
416
- const span = document.createElement('span');
417
- span.setAttribute('id', 'baz');
418
- paragraph.appendChild(span); // Reported synchronously
419
- ```
420
-
421
697
  └ *A Bindings API for binding application-level state to an object*:
422
698
 
423
699
  ```js
@@ -485,6 +761,8 @@ Observer.set(element, 'liveProperty'); // Live expressions rerun
485
761
 
486
762
  └ [Reactive HTML concepts](#)
487
763
 
764
+ -->
765
+
488
766
  ## Polyfill
489
767
 
490
768
  OOHTML is being developed as something to be used today - via a polyfill.