Skip to content

Commit 4f1d747

Browse files
Merge branch 'master' into re-adopt
2 parents 36769a2 + c689e81 commit 4f1d747

24 files changed

+522
-6646
lines changed

CHANGELOG.md

+13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
# hyper(html) Changelog
22

3+
### v2.6.0
4+
* declarative hyper.Component via `Component.for(context, uid?)` - #202
5+
* hyperHTML TypeScript information - #201
6+
7+
### v2.5.12
8+
* fixed #200: textarea/style with initial undefined value
9+
10+
### v2.5.11
11+
* fixed #198: connected/disconnected events for nested components
12+
13+
### v2.5.10
14+
* more rigid / explicit RegExp to avoid glitches with self-closing tags
15+
316
### v2.5.8
417
* improved `VOID_ELEMENTS` regular expression (aligned with the _viperHTML_ one)
518

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ You can verify directly through the following links:
8787
* [100% code coverage](https://webreflection.github.io/hyperHTML/test/) for browsers natively compatible with string literals
8888
* [100% code coverage](https://webreflection.github.io/hyperHTML/test/ie/) for IE9+ and browsers that need transpiled code
8989

90+
## HTML Syntax Highlight
91+
92+
If you are using Visual Studio Code you can install `literally-html` to highlight all literals handled by `hyperHTML` and others.
93+
94+
![literally-html example](https://viperhtml.js.org/hyperhtml/documentation/img/literally-html.png)
95+
9096
## Questions ?
9197

9298
Please ask anything you'd like to know in [StackOverflow](https://stackoverflow.com) using the tag [`hyperhtml`](https://stackoverflow.com/questions/tagged/hyperhtml) so that others can benefit from answers and examples.

cjs/classes/Component.js

+45-2
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,58 @@
11
'use strict';
2+
const { WeakMap } = require('../shared/poorlyfills.js');
3+
24
// hyperHTML.Component is a very basic class
35
// able to create Custom Elements like components
46
// including the ability to listen to connect/disconnect
57
// events via onconnect/ondisconnect attributes
8+
// Components can be created imperatively or declaratively.
9+
// The main difference is that declared components
10+
// will not automatically render on setState(...)
11+
// to simplify state handling on render.
612
function Component() {}
713
Object.defineProperty(exports, '__esModule', {value: true}).default = Component
814

915
// components will lazily define html or svg properties
1016
// as soon as these are invoked within the .render() method
1117
// Such render() method is not provided by the base class
1218
// but it must be available through the Component extend.
19+
// Declared components could implement a
20+
// render(props) method too and use props as needed.
1321
function setup(content) {
22+
const children = new WeakMap;
23+
const create = Object.create;
24+
const createEntry = (wm, id, component) => {
25+
wm.set(id, component);
26+
return component;
27+
};
28+
const get = (Class, info, id) => {
29+
switch (typeof id) {
30+
case 'object':
31+
case 'function':
32+
const wm = info.w || (info.w = new WeakMap);
33+
return wm.get(id) || createEntry(wm, id, new Class);
34+
default:
35+
const sm = info.p || (info.p = create(null));
36+
return sm[id] || (sm[id] = new Class);
37+
}
38+
};
39+
const set = context => {
40+
const info = {w: null, p: null};
41+
children.set(context, info);
42+
return info;
43+
};
44+
Object.defineProperties(
45+
Component,
46+
{
47+
for: {
48+
configurable: true,
49+
value(context, id) {
50+
const info = children.get(context) || set(context);
51+
return get(this, info, id == null ? 'default' : id);
52+
}
53+
}
54+
}
55+
);
1456
Object.defineProperties(
1557
Component.prototype,
1658
{
@@ -25,11 +67,12 @@ function setup(content) {
2567
svg: lazyGetter('svg', content),
2668
state: lazyGetter('state', function () { return this.defaultState; }),
2769
defaultState: {get() { return {}; }},
28-
setState: {value(state) {
70+
setState: {value(state, render) {
2971
const target = this.state;
3072
const source = typeof state === 'function' ? state.call(this, target) : state;
3173
for (const key in source) target[key] = source[key];
32-
this.render();
74+
if (render !== false) this.render();
75+
return this;
3376
}}
3477
}
3578
);

cjs/index.d.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import hyper from "..";
2+
export * from '..';
3+
export default hyper;

cjs/objects/Updates.js

+8-7
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,8 @@ const setAttribute = (node, name, original, adopt) => {
474474
// different from text there but it's worth checking
475475
// for possible defined intents.
476476
const setTextContent = node => {
477-
let oldValue;
477+
// avoid hyper comments inside textarea/style when value is undefined
478+
let oldValue = '';
478479
const textContent = value => {
479480
if (oldValue !== value) {
480481
oldValue = value;
@@ -533,12 +534,12 @@ function observe() {
533534
const dispatchTarget = (node, event) => {
534535
if (components.has(node)) {
535536
node.dispatchEvent(event);
536-
} else {
537-
const children = node.children;
538-
const length = children.length;
539-
for (let i = 0; i < length; i++) {
540-
dispatchTarget(children[i], event);
541-
}
537+
}
538+
539+
const children = node.children;
540+
const length = children.length;
541+
for (let i = 0; i < length; i++) {
542+
dispatchTarget(children[i], event);
542543
}
543544
}
544545

cjs/shared/re.js

+9-8
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@
22
// TODO: I'd love to code-cover RegExp too here
33
// these are fundamental for this library
44

5-
const almostEverything = '[^ \\f\\n\\r\\t\\/>"\'=]+';
6-
const attrName = '[^\\S]+' + almostEverything;
7-
const tagName = '<([a-z]+[a-z0-9:_-]*)((?:';
8-
const attrPartials = '(?:=(?:\'.*?\'|".*?"|<.+?>|' + almostEverything + '))?)';
5+
const spaces = ' \\f\\n\\r\\t';
6+
const almostEverything = '[^ ' + spaces + '\\/>"\'=]+';
7+
const attrName = '[ ' + spaces + ']+' + almostEverything;
8+
const tagName = '<([A-Za-z]+[A-Za-z0-9:_-]*)((?:';
9+
const attrPartials = '(?:=(?:\'[^\']*?\'|"[^"]*?"|<[^>]*?>|' + almostEverything + '))?)';
910

1011
const attrSeeker = new RegExp(
11-
tagName + attrName + attrPartials + '+)([^\\S]*/?>)',
12-
'gi'
12+
tagName + attrName + attrPartials + '+)([ ' + spaces + ']*/?>)',
13+
'g'
1314
);
1415

1516
const selfClosing = new RegExp(
16-
tagName + attrName + attrPartials + '*)([^\\S]*/>)',
17-
'gi'
17+
tagName + attrName + attrPartials + '*)([ ' + spaces + ']*/>)',
18+
'g'
1819
);
1920

2021
exports.attrName = attrName;

coverage/coverage.json

+1-1
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)