be-hive 0.1.14 → 0.1.15
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 +184 -0
- package/be-hive.js +4 -4
- package/findAdjacentElement.js +30 -30
- package/package.json +1 -1
- package/parsers/parse-grouped-capture-statements.js +10 -10
- package/parsers/parse-pattern-statements.js +11 -10
- package/parsers/parse-pattern-statements.ts +4 -3
package/README.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# be-hive
|
|
2
|
+
|
|
3
|
+
[](https://www.webcomponents.org/element/bahrus/be-hive)
|
|
4
|
+
[](https://bundlephobia.com/result?p=be-hive)
|
|
5
|
+
<img src="http://img.badgesize.io/https://cdn.jsdelivr.net/npm/be-hive?compression=gzip">
|
|
6
|
+
[](http://badge.fury.io/js/be-hive)
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
[be-hive](https://www.youtube.com/watch?v=SQoOwosJWns) lets it [snow in August](https://www.youtube.com/watch?v=m3dmnOtqrV0).
|
|
11
|
+
|
|
12
|
+
be-hive is the coordination layer for the [family of HTML enhancements](https://github.com/bahrus/may-it-be) that follow the "be-enhanced" pattern. It extends the [mount-observer](https://github.com/nicknisi/mount-observer) `Synthesizer` class, providing a declarative custom element (`<be-hive>`) for registering and managing element enhancements within Shadow DOM scopes.
|
|
13
|
+
|
|
14
|
+
In the modern architecture, `be-hive` serves as:
|
|
15
|
+
|
|
16
|
+
1. A **custom element** (`<be-hive>`) that acts as a registry point inside a Shadow DOM realm
|
|
17
|
+
2. A **host for EMC (Enhancement Mount Configuration) scripts** that declare which enhancements are active
|
|
18
|
+
3. A **parser host** for registering attribute parsers used by enhancements
|
|
19
|
+
4. A **utility provider** (e.g. `findAdjacentElement`) for enhancement implementations
|
|
20
|
+
|
|
21
|
+
## How It Works
|
|
22
|
+
|
|
23
|
+
The `BeHive` class extends `Synthesizer` from `mount-observer`:
|
|
24
|
+
|
|
25
|
+
```TypeScript
|
|
26
|
+
import {Synthesizer} from 'mount-observer/Synthesizer.js';
|
|
27
|
+
|
|
28
|
+
export class BeHive extends Synthesizer{}
|
|
29
|
+
|
|
30
|
+
customElements.define('be-hive', BeHive);
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
When placed inside a Shadow DOM realm, `<be-hive>` processes its child `<script>` elements to configure which enhancements are active in that scope.
|
|
34
|
+
|
|
35
|
+
## Registering Enhancements
|
|
36
|
+
|
|
37
|
+
Enhancements are registered declaratively using `<script type=emc>` tags inside `<be-hive>`:
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<be-hive>
|
|
41
|
+
<script type=emc src="be-clonable/emc.json"></script>
|
|
42
|
+
<script type=emc src="be-committed/emc.json"></script>
|
|
43
|
+
</be-hive>
|
|
44
|
+
<script type=module>
|
|
45
|
+
import 'be-hive/be-hive.js';
|
|
46
|
+
</script>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Each `<script type=emc>` points to a JSON configuration file (generated from an `emc.mjs` build script) that tells `be-hive` how to observe, parse, and spawn the enhancement.
|
|
50
|
+
|
|
51
|
+
## The EMC (Enhancement Mount Configuration)
|
|
52
|
+
|
|
53
|
+
Each enhancement project provides an EMC that defines:
|
|
54
|
+
|
|
55
|
+
- **enhKey**: The unique identifier / attribute name for the enhancement
|
|
56
|
+
- **spawn**: The module path to lazily import the enhancement class
|
|
57
|
+
- **withAttrs**: How to map HTML attributes to enhancement properties
|
|
58
|
+
|
|
59
|
+
Example `emc.mjs`:
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
export const emc = {
|
|
63
|
+
enhConfig: {
|
|
64
|
+
enhKey: 'BeClonable',
|
|
65
|
+
spawn: 'be-clonable/be-clonable.js',
|
|
66
|
+
withAttrs: {
|
|
67
|
+
base: 'be-clonable',
|
|
68
|
+
triggerInsertPosition: '${base}-trigger-insert-position',
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
customData: {
|
|
72
|
+
weakRef: {
|
|
73
|
+
properties: ['enhancedElement']
|
|
74
|
+
},
|
|
75
|
+
actions: {
|
|
76
|
+
addCloneBtn: { ifAllOf: ['triggerInsertPosition', 'enhancedElement'] }
|
|
77
|
+
},
|
|
78
|
+
defaultPropVals: {
|
|
79
|
+
triggerInsertPosition: 'beforebegin'
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export function render(){
|
|
85
|
+
return JSON.stringify(emc, null, 4);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
console.log(render());
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Running `node emc.mjs > emc.json` generates the static JSON configuration that `<be-hive>` loads at runtime.
|
|
92
|
+
|
|
93
|
+
## Custom Parsers
|
|
94
|
+
|
|
95
|
+
For enhancements with complex attribute syntax, be-hive provides built-in parser wrappers that integrate with the [nested-regex-groups](https://github.com/bahrus/nested-regex-groups) library:
|
|
96
|
+
|
|
97
|
+
- `be-hive/parsers/parse-pattern-statements.js` — for nested object structures using dot notation in capture groups
|
|
98
|
+
- `be-hive/parsers/parse-grouped-capture-statements.js` — for flat objects parsed from multiple statements
|
|
99
|
+
|
|
100
|
+
Register parsers in HTML before loading EMC scripts that depend on them:
|
|
101
|
+
|
|
102
|
+
```html
|
|
103
|
+
<be-hive>
|
|
104
|
+
<script type=emc-parser
|
|
105
|
+
src="be-hive/parsers/parse-pattern-statements.js"
|
|
106
|
+
parser-name=parse-pattern-statements></script>
|
|
107
|
+
<script type=emc
|
|
108
|
+
src="do-invoke/emc.json"
|
|
109
|
+
wait-for-parsers=parse-pattern-statements></script>
|
|
110
|
+
</be-hive>
|
|
111
|
+
<script type=module>
|
|
112
|
+
import 'be-hive/be-hive.js';
|
|
113
|
+
</script>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Emoji Shorthand
|
|
117
|
+
|
|
118
|
+
Many enhancements support both a full name and an emoji shorthand (e.g. `be-clonable` / `⿻`). A separate `.mjs` file generates a variant JSON that overrides the `enhKey` and `base` attribute:
|
|
119
|
+
|
|
120
|
+
```html
|
|
121
|
+
<!-- Full name -->
|
|
122
|
+
<div be-clonable>...</div>
|
|
123
|
+
|
|
124
|
+
<!-- Emoji shorthand -->
|
|
125
|
+
<div ⿻>...</div>
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Both resolve to the same enhancement class; only the observed attribute name differs.
|
|
129
|
+
|
|
130
|
+
## Utilities
|
|
131
|
+
|
|
132
|
+
be-hive also provides utilities used by enhancement implementations:
|
|
133
|
+
|
|
134
|
+
### findAdjacentElement
|
|
135
|
+
|
|
136
|
+
Finds an element adjacent to a given element based on an `InsertPosition` and CSS selector:
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
import {findAdjacentElement} from 'be-hive/findAdjacentElement.js';
|
|
140
|
+
|
|
141
|
+
const trigger = findAdjacentElement('beforebegin', element, '.my-trigger');
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Exports
|
|
145
|
+
|
|
146
|
+
| Path | Description |
|
|
147
|
+
|------|-------------|
|
|
148
|
+
| `be-hive/be-hive.js` | The `BeHive` custom element (extends Synthesizer) |
|
|
149
|
+
| `be-hive/findAdjacentElement.js` | Adjacent element lookup utility |
|
|
150
|
+
| `be-hive/parsers/parse-pattern-statements.js` | Parser for nested object structures |
|
|
151
|
+
| `be-hive/parsers/parse-grouped-capture-statements.js` | Parser for flat object structures |
|
|
152
|
+
|
|
153
|
+
## Dependencies
|
|
154
|
+
|
|
155
|
+
- [mount-observer](https://github.com/nicknisi/mount-observer) — Provides the `Synthesizer` base class and the `MountObserver` infrastructure for watching DOM mutations and spawning enhancements
|
|
156
|
+
- [nested-regex-groups](https://github.com/bahrus/nested-regex-groups) — Regex-based attribute parsing library used by the built-in parsers
|
|
157
|
+
|
|
158
|
+
## Related Projects
|
|
159
|
+
|
|
160
|
+
Key packages in the enhancement ecosystem:
|
|
161
|
+
|
|
162
|
+
- [mount-observer](https://github.com/nicknisi/mount-observer) — Core observation engine
|
|
163
|
+
- [roundabout-lib](https://github.com/bahrus/roundabout-lib) — Reactive property management for enhancements
|
|
164
|
+
- [assign-gingerly](https://github.com/bahrus/assign-gingerly) — Safe property assignment and enhancement gateway
|
|
165
|
+
- [inferencer](https://github.com/bahrus/inferencer) — Element property/event inference
|
|
166
|
+
- [nested-regex-groups](https://github.com/bahrus/nested-regex-groups) — Attribute value parsing
|
|
167
|
+
|
|
168
|
+
Example enhancements built on this architecture:
|
|
169
|
+
|
|
170
|
+
- [be-clonable](https://github.com/bahrus/be-clonable) — Reference implementation
|
|
171
|
+
- [do-invoke](https://github.com/bahrus/do-invoke) — Custom parser reference
|
|
172
|
+
- [be-committed](https://github.com/bahrus/be-committed)
|
|
173
|
+
- [be-bound](https://github.com/bahrus/be-bound) — Two-way data binding
|
|
174
|
+
|
|
175
|
+
## Viewing Locally
|
|
176
|
+
|
|
177
|
+
1. Install git
|
|
178
|
+
2. Fork/clone this repo
|
|
179
|
+
3. Install node.js
|
|
180
|
+
4. Open command window to folder where you cloned this repo
|
|
181
|
+
5. `> git submodule update --init --recursive`
|
|
182
|
+
6. `> npm install`
|
|
183
|
+
7. `> npm run serve` (requires a static file server with SSI support)
|
|
184
|
+
8. Open http://localhost:8000/demo/ in a modern browser (Chrome 146+ recommended for JSON import assertions)
|
package/be-hive.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Synthesizer } from 'mount-observer/Synthesizer.js';
|
|
2
|
-
export class BeHive extends Synthesizer {
|
|
3
|
-
}
|
|
4
|
-
customElements.define('be-hive', BeHive);
|
|
1
|
+
import { Synthesizer } from 'mount-observer/Synthesizer.js';
|
|
2
|
+
export class BeHive extends Synthesizer {
|
|
3
|
+
}
|
|
4
|
+
customElements.define('be-hive', BeHive);
|
package/findAdjacentElement.js
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
export function findAdjacentElement(insertPosition, element, selector) {
|
|
2
|
-
switch (insertPosition) {
|
|
3
|
-
case 'afterbegin':
|
|
4
|
-
case 'beforeend':
|
|
5
|
-
return element.querySelector(selector);
|
|
6
|
-
break;
|
|
7
|
-
case 'beforebegin':
|
|
8
|
-
{
|
|
9
|
-
let trigger = element.previousElementSibling;
|
|
10
|
-
while (trigger !== null) {
|
|
11
|
-
if (trigger.matches(selector)) {
|
|
12
|
-
return trigger;
|
|
13
|
-
}
|
|
14
|
-
trigger = trigger.previousElementSibling;
|
|
15
|
-
}
|
|
16
|
-
return null;
|
|
17
|
-
}
|
|
18
|
-
case 'afterend':
|
|
19
|
-
{
|
|
20
|
-
let trigger = element.nextElementSibling;
|
|
21
|
-
while (trigger !== null) {
|
|
22
|
-
if (trigger.matches(selector)) {
|
|
23
|
-
return trigger;
|
|
24
|
-
}
|
|
25
|
-
trigger = trigger.nextElementSibling;
|
|
26
|
-
}
|
|
27
|
-
return null;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
1
|
+
export function findAdjacentElement(insertPosition, element, selector) {
|
|
2
|
+
switch (insertPosition) {
|
|
3
|
+
case 'afterbegin':
|
|
4
|
+
case 'beforeend':
|
|
5
|
+
return element.querySelector(selector);
|
|
6
|
+
break;
|
|
7
|
+
case 'beforebegin':
|
|
8
|
+
{
|
|
9
|
+
let trigger = element.previousElementSibling;
|
|
10
|
+
while (trigger !== null) {
|
|
11
|
+
if (trigger.matches(selector)) {
|
|
12
|
+
return trigger;
|
|
13
|
+
}
|
|
14
|
+
trigger = trigger.previousElementSibling;
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
case 'afterend':
|
|
19
|
+
{
|
|
20
|
+
let trigger = element.nextElementSibling;
|
|
21
|
+
while (trigger !== null) {
|
|
22
|
+
if (trigger.matches(selector)) {
|
|
23
|
+
return trigger;
|
|
24
|
+
}
|
|
25
|
+
trigger = trigger.nextElementSibling;
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { parseGroupedCaptureStatements as pgcs } from 'nested-regex-groups/parse-grouped-capture-statements.js';
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
* @param {string} value
|
|
5
|
-
* @param {*} context
|
|
6
|
-
*/
|
|
7
|
-
export default function parseGroupedCaptureStatements(value, context) {
|
|
8
|
-
const result = pgcs(value, context.attrConfig.parserConfig);
|
|
9
|
-
return result;
|
|
10
|
-
}
|
|
1
|
+
import { parseGroupedCaptureStatements as pgcs } from 'nested-regex-groups/parse-grouped-capture-statements.js';
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param {string} value
|
|
5
|
+
* @param {*} context
|
|
6
|
+
*/
|
|
7
|
+
export default function parseGroupedCaptureStatements(value, context) {
|
|
8
|
+
const result = pgcs(value, context.attrConfig.parserConfig);
|
|
9
|
+
return result;
|
|
10
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { parsePatternStatements as pps } from 'nested-regex-groups/parse-pattern-statements.js';
|
|
2
|
-
/**
|
|
3
|
-
*
|
|
4
|
-
* @param {string} value
|
|
5
|
-
* @param {*} context
|
|
6
|
-
*/
|
|
7
|
-
export default function parsePatternStatements(value, context) {
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
import { parsePatternStatements as pps } from 'nested-regex-groups/parse-pattern-statements.js';
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
* @param {string} value
|
|
5
|
+
* @param {*} context
|
|
6
|
+
*/
|
|
7
|
+
export default function parsePatternStatements(value, context) {
|
|
8
|
+
const parserOptions = context.attrConfig.parserOptions;
|
|
9
|
+
const result = pps(value, context.attrConfig.parserConfig, parserOptions);
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {parsePatternStatements as pps} from 'nested-regex-groups/parse-pattern-statements.js';
|
|
2
2
|
import { ParserContext } from '../types/assign-gingerly/types.d.js';
|
|
3
|
-
import { PatternConfig } from '../types/nested-regex-groups/types.js';
|
|
3
|
+
import { PatternConfig, ParserOptions } from '../types/nested-regex-groups/types.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
*
|
|
@@ -8,6 +8,7 @@ import { PatternConfig } from '../types/nested-regex-groups/types.js';
|
|
|
8
8
|
* @param {*} context
|
|
9
9
|
*/
|
|
10
10
|
export default function parsePatternStatements(value: string, context: ParserContext){
|
|
11
|
-
const
|
|
11
|
+
const parserOptions = context.attrConfig.parserOptions as ParserOptions | undefined;
|
|
12
|
+
const result = pps(value, context.attrConfig.parserConfig as PatternConfig[], parserOptions);
|
|
12
13
|
return result;
|
|
13
|
-
}
|
|
14
|
+
}
|