bruh 1.8.1 → 1.10.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/dist/bruh.es.js +358 -1
- package/dist/bruh.es.js.map +1 -1
- package/dist/bruh.umd.js +1 -1
- package/dist/bruh.umd.js.map +1 -1
- package/package.json +5 -13
- package/src/components/optimized-picture/render.mjs +4 -1
- package/src/dom/index.browser.mjs +124 -153
- package/src/dom/index.node.mjs +168 -100
- package/src/dom/live-fragment.mjs +2 -4
- package/src/reactive/index.mjs +2 -2
- package/src/util/index.mjs +0 -14
- package/src/reactive/index.d.ts +0 -31
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"library",
|
|
11
11
|
"modern"
|
|
12
12
|
],
|
|
13
|
-
"version": "1.
|
|
13
|
+
"version": "1.10.0",
|
|
14
14
|
"license": "MIT",
|
|
15
15
|
"author": {
|
|
16
16
|
"name": "Daniel Ethridge",
|
|
@@ -50,18 +50,10 @@
|
|
|
50
50
|
"prepare": "npm run build"
|
|
51
51
|
},
|
|
52
52
|
"optionalDependencies": {
|
|
53
|
-
"cac": "^6.7.
|
|
54
|
-
"sharp": "^0.
|
|
53
|
+
"cac": "^6.7.11",
|
|
54
|
+
"sharp": "^0.29.2"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"vite": "^2.
|
|
58
|
-
}
|
|
59
|
-
"browserslist": [
|
|
60
|
-
"ios_saf >= 12.4",
|
|
61
|
-
"and_chr >= 88",
|
|
62
|
-
"chrome >= 87",
|
|
63
|
-
"safari >= 13.1",
|
|
64
|
-
"edge >= 87",
|
|
65
|
-
"firefox >= 84"
|
|
66
|
-
]
|
|
57
|
+
"vite": "^2.6.10"
|
|
58
|
+
}
|
|
67
59
|
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { e } from "bruh/dom"
|
|
2
|
+
import { functionAsObject } from "bruh/util"
|
|
3
|
+
const { picture, source, img } = functionAsObject(e)
|
|
4
|
+
|
|
2
5
|
import { readFile } from "fs/promises"
|
|
3
6
|
|
|
4
7
|
export default async options => {
|
|
@@ -1,49 +1,49 @@
|
|
|
1
1
|
import { LiveFragment } from "./live-fragment.mjs"
|
|
2
|
-
import { reactiveDo } from "../reactive/index.mjs"
|
|
3
|
-
import { maybeDo } from "../util/index.mjs"
|
|
2
|
+
import { isReactive, reactiveDo } from "../reactive/index.mjs"
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
const isMetaNode = Symbol.for("bruh meta node")
|
|
7
|
-
const isMetaTextNode = Symbol.for("bruh meta text node")
|
|
8
|
-
const isMetaElement = Symbol.for("bruh meta element")
|
|
4
|
+
//#region Bruh child functions e.g. bruhChildrenToNodes()
|
|
9
5
|
|
|
10
|
-
// A basic check for if a value is allowed as a
|
|
6
|
+
// A basic check for if a value is allowed as a child in bruh
|
|
11
7
|
// It's responsible for quickly checking the type, not deep validation
|
|
12
|
-
const
|
|
13
|
-
//
|
|
14
|
-
x?.[isMetaNode] ||
|
|
8
|
+
const isBruhChild = x =>
|
|
9
|
+
// Reactives and DOM nodes
|
|
15
10
|
x?.[isReactive] ||
|
|
16
11
|
x instanceof Node ||
|
|
17
12
|
// Any array, just assume it contains valid children
|
|
18
13
|
Array.isArray(x) ||
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
14
|
+
// Allow nullish
|
|
15
|
+
x == null ||
|
|
16
|
+
// Disallow functions and objects
|
|
17
|
+
!(typeof x === "function" || typeof x === "object")
|
|
18
|
+
// Everything else can be a child when stringified
|
|
19
|
+
|
|
20
|
+
// Coerces input into a DOM node, if it isn't already one
|
|
21
|
+
const toNode = x =>
|
|
22
|
+
x instanceof Node
|
|
23
|
+
? x
|
|
24
|
+
: document.createTextNode(x)
|
|
25
|
+
|
|
26
|
+
// Processes bruh children into an array of DOM nodes
|
|
27
|
+
// Reactive values are automatically replaced, so the output must be placed into a parent node
|
|
28
|
+
// before any top level (after flattening arrays) reactions run
|
|
29
|
+
export const bruhChildrenToNodes = (...children) =>
|
|
33
30
|
children
|
|
34
31
|
.flat(Infinity)
|
|
35
32
|
.flatMap(child => {
|
|
33
|
+
// Non-reactive values are untouched
|
|
36
34
|
if (!child[isReactive])
|
|
37
35
|
return [toNode(child)]
|
|
38
36
|
|
|
37
|
+
// Reactive arrays become live fragments with auto-swapped children
|
|
39
38
|
if (Array.isArray(child.value)) {
|
|
40
39
|
const liveFragment = new LiveFragment()
|
|
41
40
|
child.addReaction(() => {
|
|
42
|
-
liveFragment.replaceChildren(...
|
|
41
|
+
liveFragment.replaceChildren(...bruhChildrenToNodes(...child.value))
|
|
43
42
|
})
|
|
44
|
-
return [liveFragment.startMarker, ...
|
|
43
|
+
return [liveFragment.startMarker, ...bruhChildrenToNodes(...child.value), liveFragment.endMarker]
|
|
45
44
|
}
|
|
46
45
|
|
|
46
|
+
// Reactive values become auto-swapped DOM nodes
|
|
47
47
|
let node = toNode(child.value)
|
|
48
48
|
child.addReaction(() => {
|
|
49
49
|
const oldNode = node
|
|
@@ -53,109 +53,129 @@ export const childrenToNodes = children =>
|
|
|
53
53
|
return [node]
|
|
54
54
|
})
|
|
55
55
|
|
|
56
|
+
//#endregion
|
|
56
57
|
|
|
58
|
+
//#region Reactive-aware element helper functions e.g. applyAttributes()
|
|
57
59
|
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
export
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
})
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
this.node = document.createTextNode(textContent)
|
|
73
|
-
}
|
|
74
|
-
}
|
|
60
|
+
// Style attribute rules from an object with
|
|
61
|
+
// potentially reactive and/or undefined values
|
|
62
|
+
export const applyStyles = (element, styles) => {
|
|
63
|
+
for (const property in styles)
|
|
64
|
+
reactiveDo(styles[property], value => {
|
|
65
|
+
if (value !== undefined)
|
|
66
|
+
element.style.setProperty (property, value)
|
|
67
|
+
else
|
|
68
|
+
element.style.removeProperty(property)
|
|
69
|
+
})
|
|
70
|
+
}
|
|
75
71
|
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
// Class list from an object mapping from
|
|
73
|
+
// class names to potentially reactive booleans
|
|
74
|
+
export const applyClasses = (element, classes) => {
|
|
75
|
+
for (const name in classes)
|
|
76
|
+
reactiveDo(classes[name], value => {
|
|
77
|
+
element.classList.toggle(name, value)
|
|
78
|
+
})
|
|
79
|
+
}
|
|
78
80
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
// Attributes from an object with
|
|
82
|
+
// potentially reactive and/or undefined values
|
|
83
|
+
export const applyAttributes = (element, attributes) => {
|
|
84
|
+
for (const name in attributes)
|
|
85
|
+
reactiveDo(attributes[name], value => {
|
|
86
|
+
if (value !== undefined)
|
|
87
|
+
element.setAttribute (name, value)
|
|
88
|
+
else
|
|
89
|
+
element.removeAttribute(name)
|
|
90
|
+
})
|
|
81
91
|
}
|
|
82
92
|
|
|
83
|
-
|
|
84
|
-
constructor(name, namespace) {
|
|
85
|
-
this[isMetaNode] =
|
|
86
|
-
this[isMetaElement] = true
|
|
93
|
+
//#endregion
|
|
87
94
|
|
|
88
|
-
|
|
89
|
-
namespace
|
|
90
|
-
? document.createElementNS(namespace, name)
|
|
91
|
-
: document.createElement ( name)
|
|
92
|
-
}
|
|
95
|
+
//#region t() for text nodes and e() for element nodes
|
|
93
96
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
97
|
+
// Text nodes
|
|
98
|
+
export const t = textContent => {
|
|
99
|
+
// Non-reactive values are just text nodes
|
|
100
|
+
if (!textContent[isReactive])
|
|
101
|
+
return document.createTextNode(textContent)
|
|
99
102
|
|
|
100
|
-
|
|
101
|
-
|
|
103
|
+
// Reactive values auto-update the node's text content
|
|
104
|
+
const node = document.createTextNode(textContent.value)
|
|
105
|
+
textContent.addReaction(() => {
|
|
106
|
+
node.textContent = textContent.value
|
|
107
|
+
})
|
|
108
|
+
return node
|
|
109
|
+
}
|
|
102
110
|
|
|
103
|
-
|
|
111
|
+
// Elements
|
|
112
|
+
export const e = name => (...variadic) => {
|
|
113
|
+
// If there are no props
|
|
114
|
+
if (isBruhChild(variadic[0])) {
|
|
115
|
+
const element = document.createElement(name)
|
|
116
|
+
element.append(...bruhChildrenToNodes(...variadic))
|
|
117
|
+
return element
|
|
104
118
|
}
|
|
105
119
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
reactiveDo(attributes[name],
|
|
109
|
-
maybeDo(
|
|
110
|
-
value => this.node.setAttribute (name, value),
|
|
111
|
-
() => this.node.removeAttribute(name)
|
|
112
|
-
)
|
|
113
|
-
)
|
|
120
|
+
// If props exist as the first variadic argument
|
|
121
|
+
const [props, ...children] = variadic
|
|
114
122
|
|
|
115
|
-
|
|
116
|
-
}
|
|
123
|
+
// Extract explicit options from the bruh prop
|
|
124
|
+
const { namespace } = props.bruh ?? {}
|
|
125
|
+
delete props.bruh
|
|
117
126
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
() => delete this.node.dataset[name]
|
|
124
|
-
)
|
|
125
|
-
)
|
|
127
|
+
// Make an element with optional namespace
|
|
128
|
+
const element =
|
|
129
|
+
namespace
|
|
130
|
+
? document.createElementNS(namespace, name)
|
|
131
|
+
: document.createElement ( name)
|
|
126
132
|
|
|
127
|
-
|
|
133
|
+
// Apply overloaded props, if possible
|
|
134
|
+
if (typeof props.style === "object") {
|
|
135
|
+
applyStyles(element, props.style)
|
|
136
|
+
delete props.style
|
|
128
137
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
138
|
+
if (typeof props.class === "object") {
|
|
139
|
+
applyClasses(element, props.class)
|
|
140
|
+
delete props.class
|
|
132
141
|
}
|
|
142
|
+
// The rest of the props are attributes
|
|
143
|
+
applyAttributes(element, props)
|
|
133
144
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
145
|
+
// Add the children to the element
|
|
146
|
+
element.append(...bruhChildrenToNodes(...children))
|
|
147
|
+
return element
|
|
148
|
+
}
|
|
137
149
|
|
|
138
|
-
|
|
139
|
-
this.node.append(...childrenToNodes(xs))
|
|
140
|
-
}
|
|
150
|
+
//#endregion
|
|
141
151
|
|
|
142
|
-
|
|
143
|
-
this.node.after(...childrenToNodes(xs))
|
|
144
|
-
}
|
|
152
|
+
//#region JSX integration
|
|
145
153
|
|
|
146
|
-
|
|
147
|
-
|
|
154
|
+
// The function that jsx tags (except fragments) compile to
|
|
155
|
+
export const h = (nameOrComponent, props, ...children) => {
|
|
156
|
+
// If we are making an element, this is just a wrapper of e()
|
|
157
|
+
// This is likely when the JSX tag name begins with a lowercase character
|
|
158
|
+
if (typeof nameOrComponent === "string") {
|
|
159
|
+
const makeElement = e(nameOrComponent)
|
|
160
|
+
return props
|
|
161
|
+
? makeElement(props, ...children)
|
|
162
|
+
: makeElement(...children)
|
|
148
163
|
}
|
|
149
164
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
165
|
+
// It must be a component, then, as bruh components are just functions
|
|
166
|
+
// Due to JSX, this would mean a function with only one parameter - props
|
|
167
|
+
// This object includes the all of the normal props and a "children" key
|
|
168
|
+
return nameOrComponent({ ...props, children })
|
|
153
169
|
}
|
|
154
170
|
|
|
171
|
+
// The JSX fragment is made into a bruh fragment (just an array)
|
|
172
|
+
export const JSXFragment = ({ children }) => children
|
|
173
|
+
|
|
174
|
+
//#endregion
|
|
155
175
|
|
|
156
176
|
|
|
157
|
-
// Convenience functions
|
|
158
177
|
|
|
178
|
+
// Hydration of all bruh-textnode's from prerendered html
|
|
159
179
|
export const hydrateTextNodes = () => {
|
|
160
180
|
const tagged = {}
|
|
161
181
|
const bruhTextNodes = document.getElementsByTagName("bruh-textnode")
|
|
@@ -163,61 +183,12 @@ export const hydrateTextNodes = () => {
|
|
|
163
183
|
for (const bruhTextNode of bruhTextNodes) {
|
|
164
184
|
const textNode = document.createTextNode(bruhTextNode.textContent)
|
|
165
185
|
|
|
166
|
-
|
|
167
|
-
|
|
186
|
+
const tag = bruhTextNode.getAttribute("tag")
|
|
187
|
+
if (tag)
|
|
188
|
+
tagged[tag] = textNode
|
|
168
189
|
|
|
169
190
|
bruhTextNode.replaceWith(textNode)
|
|
170
191
|
}
|
|
171
192
|
|
|
172
193
|
return tagged
|
|
173
194
|
}
|
|
174
|
-
|
|
175
|
-
const createMetaTextNode = textContent =>
|
|
176
|
-
new MetaTextNode(textContent)
|
|
177
|
-
|
|
178
|
-
const createMetaElement = (name, namespace) => (...variadic) => {
|
|
179
|
-
const meta = new MetaElement(name, namespace)
|
|
180
|
-
|
|
181
|
-
// Implement optional attributes as first argument
|
|
182
|
-
if (!isMetaNodeChild(variadic[0])) {
|
|
183
|
-
const [attributes, ...children] = variadic
|
|
184
|
-
meta.addAttributes(attributes)
|
|
185
|
-
meta.append(children)
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
meta.append(variadic)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
return meta
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// JSX integration
|
|
195
|
-
const createMetaElementJSX = (nameOrComponent, attributesOrProps, ...children) => {
|
|
196
|
-
// If we are making a html element
|
|
197
|
-
// This is likely when the jsx tag name begins with a lowercase character
|
|
198
|
-
if (typeof nameOrComponent == "string") {
|
|
199
|
-
const meta = new MetaElement(nameOrComponent)
|
|
200
|
-
|
|
201
|
-
// These are attributes then, but they might be null/undefined
|
|
202
|
-
meta.addAttributes(attributesOrProps || {})
|
|
203
|
-
meta.append(children)
|
|
204
|
-
|
|
205
|
-
return meta
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// It must be a component, then
|
|
209
|
-
// Bruh components are just functions that return meta elements
|
|
210
|
-
// Due to JSX, this would mean a function with only one parameter - a "props" object
|
|
211
|
-
// This object includes the all of the attributes and a "children" key
|
|
212
|
-
return nameOrComponent( Object.assign({}, attributesOrProps, { children }) )
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
// These will be called with short names
|
|
216
|
-
export {
|
|
217
|
-
createMetaTextNode as t,
|
|
218
|
-
createMetaElement as e,
|
|
219
|
-
createMetaElementJSX as h
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// The JSX fragment is made into a bruh fragment (just an array)
|
|
223
|
-
export const JSXFragment = ({ children }) => children
|