@dinoreic/fez 0.3.2 → 0.4.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/README.md +5 -5
- package/dist/fez.js +44 -21
- package/dist/fez.js.map +4 -4
- package/package.json +2 -2
- package/src/fez/compile.js +4 -7
- package/src/fez/connect.js +50 -77
- package/src/fez/instance.js +59 -10
- package/src/fez/root.js +11 -174
- package/src/fez/utility.js +198 -2
- package/src/fez/utils/css_mixin.js +25 -0
- package/src/fez/utils/dump.js +44 -15
- package/src/fez/utils/highlight_all.js +98 -0
- package/src/svelte-cde-adapter.coffee +122 -0
package/package.json
CHANGED
package/src/fez/compile.js
CHANGED
|
@@ -70,10 +70,7 @@ const compileToClass = (html) => {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
if (String(result.style).includes(':')) {
|
|
73
|
-
|
|
74
|
-
result.style = result.style.replaceAll(`:${key} `, `${val} `)
|
|
75
|
-
})
|
|
76
|
-
|
|
73
|
+
result.style = Fez.cssMixin(result.style)
|
|
77
74
|
result.style = result.style.includes(':fez') || /(?:^|\s)body\s*\{/.test(result.style) ? result.style : `:fez {\n${result.style}\n}`
|
|
78
75
|
klass = klass.replace(/\}\s*$/, `\n CSS = \`${result.style}\`\n}`)
|
|
79
76
|
}
|
|
@@ -105,8 +102,8 @@ function compile_bulk(data) {
|
|
|
105
102
|
if (fezName && !fezName.includes('-')) {
|
|
106
103
|
console.error(`Fez: Invalid custom element name "${fezName}". Custom element names must contain a dash (e.g., 'my-element', 'ui-button').`)
|
|
107
104
|
}
|
|
108
|
-
|
|
109
|
-
return
|
|
105
|
+
compile(fezName, node.innerHTML)
|
|
106
|
+
return
|
|
110
107
|
}
|
|
111
108
|
}
|
|
112
109
|
else {
|
|
@@ -195,7 +192,7 @@ function compile(tagName, html) {
|
|
|
195
192
|
if (klass.includes('import ')) {
|
|
196
193
|
Fez.head({script: klass})
|
|
197
194
|
|
|
198
|
-
// best we can do it inform that node did not compile, so we assume there is
|
|
195
|
+
// best we can do it inform that node did not compile, so we assume there is an error
|
|
199
196
|
setTimeout(()=>{
|
|
200
197
|
if (!Fez.classes[tagName]) {
|
|
201
198
|
Fez.error(`Template "${tagName}" possible compile error. (can be a false positive, it imports are not loaded)`)
|
package/src/fez/connect.js
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
import createTemplate from './lib/template.js'
|
|
2
2
|
import FezBase from './instance.js'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Global mutation observer for reactive attribute changes
|
|
6
|
+
* Watches for attribute changes and triggers component updates
|
|
7
|
+
*/
|
|
8
|
+
const observer = new MutationObserver((mutationsList, _) => {
|
|
9
|
+
for (const mutation of mutationsList) {
|
|
10
|
+
if (mutation.type === 'attributes') {
|
|
11
|
+
const fez = mutation.target.fez
|
|
12
|
+
const name = mutation.attributeName
|
|
13
|
+
const value = mutation.target.getAttribute(name)
|
|
14
|
+
|
|
15
|
+
if (fez) {
|
|
16
|
+
fez.props[name] = value
|
|
17
|
+
fez.onPropsChange(name, value)
|
|
18
|
+
// console.log(`The [${name}] attribute was modified to [${value}].`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
4
24
|
/**
|
|
5
25
|
* Registers a new custom element with Fez framework
|
|
6
26
|
* @param {string} name - Custom element name (must contain a dash)
|
|
@@ -31,22 +51,17 @@ export default function connect(name, klass) {
|
|
|
31
51
|
props.forEach(prop => newKlass.prototype[prop] = klassObj[prop])
|
|
32
52
|
|
|
33
53
|
// Map component configuration properties
|
|
34
|
-
if (klassObj.
|
|
35
|
-
if (klassObj.
|
|
54
|
+
if (klassObj.FAST) { newKlass.FAST = klassObj.FAST } // Global instance reference
|
|
55
|
+
if (klassObj.GLOBAL) { newKlass.GLOBAL = klassObj.GLOBAL } // Global instance reference
|
|
56
|
+
if (klassObj.CSS) { newKlass.css = klassObj.CSS } // Component styles
|
|
36
57
|
if (klassObj.HTML) {
|
|
37
|
-
newKlass.html = closeCustomTags(klassObj.HTML)
|
|
58
|
+
newKlass.html = closeCustomTags(klassObj.HTML) // Component template
|
|
38
59
|
}
|
|
39
|
-
if (klassObj.NAME) { newKlass.nodeName = klassObj.NAME }
|
|
60
|
+
if (klassObj.NAME) { newKlass.nodeName = klassObj.NAME } // Custom DOM node name
|
|
40
61
|
|
|
41
62
|
// Auto-mount global components to body
|
|
42
63
|
if (klassObj.GLOBAL) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (document.readyState === 'loading') {
|
|
46
|
-
document.addEventListener('DOMContentLoaded', mountGlobalComponent);
|
|
47
|
-
} else {
|
|
48
|
-
mountGlobalComponent()
|
|
49
|
-
}
|
|
64
|
+
document.body.appendChild(document.createElement(name))
|
|
50
65
|
}
|
|
51
66
|
|
|
52
67
|
klass = newKlass
|
|
@@ -59,11 +74,11 @@ export default function connect(name, klass) {
|
|
|
59
74
|
|
|
60
75
|
// Process component template
|
|
61
76
|
if (klass.html) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
77
|
+
let slotTag = klass.SLOT || 'div'
|
|
78
|
+
|
|
79
|
+
klass.html = klass.html
|
|
80
|
+
.replace('<slot', `<${slotTag} class="fez-slot" fez-keep="default-slot"`)
|
|
81
|
+
.replace('</slot>', `</${slotTag}>`)
|
|
67
82
|
|
|
68
83
|
// Compile template function
|
|
69
84
|
klass.fezHtmlFunc = createTemplate(klass.html)
|
|
@@ -76,47 +91,16 @@ export default function connect(name, klass) {
|
|
|
76
91
|
|
|
77
92
|
Fez.classes[name] = klass
|
|
78
93
|
|
|
79
|
-
connectCustomElement(name, klass)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Registers the custom element with the browser
|
|
84
|
-
* Sets up batched rendering for optimal performance
|
|
85
|
-
*/
|
|
86
|
-
function connectCustomElement(name, klass) {
|
|
87
|
-
const Fez = globalThis.window?.Fez || globalThis.Fez;
|
|
88
|
-
|
|
89
94
|
if (!customElements.get(name)) {
|
|
90
95
|
customElements.define(name, class extends HTMLElement {
|
|
91
96
|
connectedCallback() {
|
|
92
|
-
//
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
if (!Fez._batchScheduled) {
|
|
101
|
-
Fez._batchScheduled = true
|
|
102
|
-
Promise.resolve().then(() => {
|
|
103
|
-
const connections = Fez._pendingConnections.slice()
|
|
104
|
-
// console.error(`Batch processing ${connections.length} components:`, connections.map(c => c.name))
|
|
105
|
-
Fez._pendingConnections = []
|
|
106
|
-
Fez._batchScheduled = false
|
|
107
|
-
|
|
108
|
-
// Sort by DOM order to ensure parent nodes are processed before children
|
|
109
|
-
connections.sort((a, b) => {
|
|
110
|
-
if (a.node.contains(b.node)) return -1
|
|
111
|
-
if (b.node.contains(a.node)) return 1
|
|
112
|
-
return 0
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
connections.forEach(({ name, node }) => {
|
|
116
|
-
if (node.isConnected && node.parentNode) {
|
|
117
|
-
connectNode(name, node)
|
|
118
|
-
}
|
|
119
|
-
})
|
|
97
|
+
// Fez.onReady(()=>{connectNode(name, this)})
|
|
98
|
+
// connectNode(name, this)
|
|
99
|
+
if (useFastRender(this, klass)) {
|
|
100
|
+
connectNode(name, this)
|
|
101
|
+
} else {
|
|
102
|
+
requestAnimationFrame(()=>{
|
|
103
|
+
connectNode(name, this)
|
|
120
104
|
})
|
|
121
105
|
}
|
|
122
106
|
}
|
|
@@ -124,6 +108,16 @@ function connectCustomElement(name, klass) {
|
|
|
124
108
|
}
|
|
125
109
|
}
|
|
126
110
|
|
|
111
|
+
function useFastRender(node, klass) {
|
|
112
|
+
const fezFast = node.getAttribute('fez-fast')
|
|
113
|
+
var isFast = typeof klass.FAST === 'function' ? klass.FAST(node) : klass.FAST
|
|
114
|
+
if (fezFast == 'false') {
|
|
115
|
+
return false
|
|
116
|
+
} else {
|
|
117
|
+
return fezFast || isFast
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
127
121
|
/**
|
|
128
122
|
* Converts self-closing custom tags to full open/close format
|
|
129
123
|
* Required for proper HTML parsing of custom elements
|
|
@@ -138,7 +132,6 @@ function closeCustomTags(html) {
|
|
|
138
132
|
})
|
|
139
133
|
}
|
|
140
134
|
|
|
141
|
-
|
|
142
135
|
/**
|
|
143
136
|
* Initializes a Fez component instance from a DOM node
|
|
144
137
|
* Replaces the custom element with the component's rendered content
|
|
@@ -172,8 +165,8 @@ function connectNode(name, node) {
|
|
|
172
165
|
|
|
173
166
|
newNode.fez = fez
|
|
174
167
|
|
|
175
|
-
if (klass.
|
|
176
|
-
window[klass.
|
|
168
|
+
if (klass.GLOBAL && klass.GLOBAL != true) {
|
|
169
|
+
window[klass.GLOBAL] = fez
|
|
177
170
|
}
|
|
178
171
|
|
|
179
172
|
if (window.$) {
|
|
@@ -216,23 +209,3 @@ function connectNode(name, node) {
|
|
|
216
209
|
}
|
|
217
210
|
}
|
|
218
211
|
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Global mutation observer for reactive attribute changes
|
|
222
|
-
* Watches for attribute changes and triggers component updates
|
|
223
|
-
*/
|
|
224
|
-
const observer = new MutationObserver((mutationsList, _) => {
|
|
225
|
-
for (const mutation of mutationsList) {
|
|
226
|
-
if (mutation.type === 'attributes') {
|
|
227
|
-
const fez = mutation.target.fez
|
|
228
|
-
const name = mutation.attributeName
|
|
229
|
-
const value = mutation.target.getAttribute(name)
|
|
230
|
-
|
|
231
|
-
if (fez) {
|
|
232
|
-
fez.props[name] = value
|
|
233
|
-
fez.onPropsChange(name, value)
|
|
234
|
-
// console.log(`The [${name}] attribute was modified to [${value}].`);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
});
|
package/src/fez/instance.js
CHANGED
|
@@ -390,11 +390,24 @@ export default class FezBase {
|
|
|
390
390
|
|
|
391
391
|
// <button fez-use="animate" -> this.animate(node]
|
|
392
392
|
fetchAttr('fez-use', (value, n) => {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
}
|
|
397
|
-
|
|
393
|
+
if (value.includes('=>')) {
|
|
394
|
+
// fez-use="el => el.focus()"
|
|
395
|
+
Fez.getFunction(value)(n)
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
if (value.includes('.')) {
|
|
399
|
+
// fez-use="this.focus()"
|
|
400
|
+
Fez.getFunction(value).bind(n)()
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
// fez-use="animate"
|
|
404
|
+
const target = this[value]
|
|
405
|
+
if (typeof target == 'function') {
|
|
406
|
+
target(n)
|
|
407
|
+
} else {
|
|
408
|
+
console.error(`Fez error: "${value}" is not a function in ${this.fezName}`)
|
|
409
|
+
}
|
|
410
|
+
}
|
|
398
411
|
}
|
|
399
412
|
})
|
|
400
413
|
|
|
@@ -406,7 +419,7 @@ export default class FezBase {
|
|
|
406
419
|
if (lastClass) {
|
|
407
420
|
setTimeout(()=>{
|
|
408
421
|
n.classList.add(lastClass)
|
|
409
|
-
},
|
|
422
|
+
}, 1)
|
|
410
423
|
}
|
|
411
424
|
})
|
|
412
425
|
|
|
@@ -442,8 +455,28 @@ export default class FezBase {
|
|
|
442
455
|
// Keep the old element in place of the new one
|
|
443
456
|
newEl.parentNode.replaceChild(oldEl, newEl)
|
|
444
457
|
} else if (key === 'default-slot') {
|
|
445
|
-
|
|
446
|
-
|
|
458
|
+
if (newEl.getAttribute('hide')) {
|
|
459
|
+
// You cant use state any more
|
|
460
|
+
this.state = null
|
|
461
|
+
|
|
462
|
+
const parent = newEl.parentNode
|
|
463
|
+
|
|
464
|
+
// Insert all root children before the slot's next sibling
|
|
465
|
+
Array.from(this.root.childNodes).forEach(child => {
|
|
466
|
+
parent.insertBefore(child, newEl)
|
|
467
|
+
})
|
|
468
|
+
|
|
469
|
+
// Remove the slot element
|
|
470
|
+
newEl.remove()
|
|
471
|
+
}
|
|
472
|
+
else {
|
|
473
|
+
// First render - populate the slot with current root children
|
|
474
|
+
Array.from(this.root.childNodes).forEach(
|
|
475
|
+
child => {
|
|
476
|
+
newEl.appendChild(child)
|
|
477
|
+
}
|
|
478
|
+
)
|
|
479
|
+
}
|
|
447
480
|
}
|
|
448
481
|
})
|
|
449
482
|
}
|
|
@@ -606,7 +639,18 @@ export default class FezBase {
|
|
|
606
639
|
methods.forEach(method => this[method] = this[method].bind(this))
|
|
607
640
|
}
|
|
608
641
|
|
|
609
|
-
|
|
642
|
+
// dissolve into parent, if you want to promote first child or given node with this.root
|
|
643
|
+
dissolve(inNode) {
|
|
644
|
+
if (inNode) {
|
|
645
|
+
inNode.classList.add('fez')
|
|
646
|
+
inNode.classList.add(`fez-${this.fezName}`)
|
|
647
|
+
inNode.fez = this
|
|
648
|
+
if (this.attr('id')) inNode.setAttribute('id', this.attr('id'))
|
|
649
|
+
|
|
650
|
+
this.root.innerHTML = ''
|
|
651
|
+
this.root.appendChild(inNode)
|
|
652
|
+
}
|
|
653
|
+
|
|
610
654
|
const node = this.root
|
|
611
655
|
const nodes = this.childNodes()
|
|
612
656
|
const parent = this.root.parentNode
|
|
@@ -614,7 +658,12 @@ export default class FezBase {
|
|
|
614
658
|
nodes.reverse().forEach(el => parent.insertBefore(el, node.nextSibling))
|
|
615
659
|
|
|
616
660
|
this.root.remove()
|
|
617
|
-
this.root =
|
|
661
|
+
this.root = undefined
|
|
662
|
+
|
|
663
|
+
if (inNode) {
|
|
664
|
+
this.root = inNode
|
|
665
|
+
}
|
|
666
|
+
|
|
618
667
|
return nodes
|
|
619
668
|
}
|
|
620
669
|
|
package/src/fez/root.js
CHANGED
|
@@ -5,6 +5,7 @@ import Gobber from './vendor/gobber.js'
|
|
|
5
5
|
import { Idiomorph } from './vendor/idiomorph.js'
|
|
6
6
|
|
|
7
7
|
import objectDump from './utils/dump.js'
|
|
8
|
+
import highlightAll from './utils/highlight_all.js'
|
|
8
9
|
import connect from './connect.js'
|
|
9
10
|
import compile from './compile.js'
|
|
10
11
|
import state from './lib/global-state.js'
|
|
@@ -106,13 +107,9 @@ Fez.globalCss = (cssClass, opts = {}) => {
|
|
|
106
107
|
cssClass = Fez.cssClass(text)
|
|
107
108
|
}
|
|
108
109
|
|
|
109
|
-
|
|
110
|
+
Fez.onReady(() => {
|
|
110
111
|
document.body.parentElement.classList.add(cssClass)
|
|
111
|
-
}
|
|
112
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
113
|
-
document.body.parentElement.classList.add(cssClass)
|
|
114
|
-
})
|
|
115
|
-
}
|
|
112
|
+
})
|
|
116
113
|
|
|
117
114
|
return cssClass
|
|
118
115
|
}
|
|
@@ -145,27 +142,6 @@ Fez.publish = (channel, ...args) => {
|
|
|
145
142
|
})
|
|
146
143
|
}
|
|
147
144
|
|
|
148
|
-
// get unique id from string
|
|
149
|
-
Fez.fnv1 = (str) => {
|
|
150
|
-
var FNV_OFFSET_BASIS, FNV_PRIME, hash, i, j, ref;
|
|
151
|
-
FNV_OFFSET_BASIS = 2166136261;
|
|
152
|
-
FNV_PRIME = 16777619;
|
|
153
|
-
hash = FNV_OFFSET_BASIS;
|
|
154
|
-
for (i = j = 0, ref = str.length - 1; (0 <= ref ? j <= ref : j >= ref); i = 0 <= ref ? ++j : --j) {
|
|
155
|
-
hash ^= str.charCodeAt(i);
|
|
156
|
-
hash *= FNV_PRIME;
|
|
157
|
-
}
|
|
158
|
-
return hash.toString(36).replaceAll('-', '');
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
Fez.tag = (tag, opts = {}, html = '') => {
|
|
162
|
-
const json = encodeURIComponent(JSON.stringify(opts))
|
|
163
|
-
return `<${tag} data-props="${json}">${html}</${tag}>`
|
|
164
|
-
// const json = JSON.stringify(opts, null, 2)
|
|
165
|
-
// const data = `<script type="text/template">${json}</script><${tag} data-json-template="true">${html}</${tag}>`
|
|
166
|
-
// return data
|
|
167
|
-
};
|
|
168
|
-
|
|
169
145
|
Fez.error = (text, show) => {
|
|
170
146
|
text = `Fez: ${text}`
|
|
171
147
|
console.error(text)
|
|
@@ -173,151 +149,13 @@ Fez.error = (text, show) => {
|
|
|
173
149
|
return `<span style="border: 1px solid red; font-size: 14px; padding: 3px 7px; background: #fee; border-radius: 4px;">${text}</span>`
|
|
174
150
|
}
|
|
175
151
|
}
|
|
152
|
+
|
|
176
153
|
Fez.log = (text) => {
|
|
177
154
|
if (Fez.LOG === true) {
|
|
178
155
|
text = String(text).substring(0, 180)
|
|
179
156
|
console.log(`Fez: ${text}`)
|
|
180
157
|
}
|
|
181
158
|
}
|
|
182
|
-
document.addEventListener('DOMContentLoaded', () => {
|
|
183
|
-
Fez.log('Fez.LOG === true, logging enabled.')
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
// execute function until it returns true
|
|
187
|
-
Fez.untilTrue = (func, pingRate) => {
|
|
188
|
-
pingRate ||= 200
|
|
189
|
-
|
|
190
|
-
if (!func()) {
|
|
191
|
-
setTimeout(()=>{
|
|
192
|
-
Fez.untilTrue(func, pingRate)
|
|
193
|
-
} ,pingRate)
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// throttle function calls
|
|
198
|
-
Fez.throttle = (func, delay = 200) => {
|
|
199
|
-
let lastRun = 0;
|
|
200
|
-
let timeout;
|
|
201
|
-
|
|
202
|
-
return function(...args) {
|
|
203
|
-
const now = Date.now();
|
|
204
|
-
|
|
205
|
-
if (now - lastRun >= delay) {
|
|
206
|
-
func.apply(this, args);
|
|
207
|
-
lastRun = now;
|
|
208
|
-
} else {
|
|
209
|
-
clearTimeout(timeout);
|
|
210
|
-
timeout = setTimeout(() => {
|
|
211
|
-
func.apply(this, args);
|
|
212
|
-
lastRun = Date.now();
|
|
213
|
-
}, delay - (now - lastRun));
|
|
214
|
-
}
|
|
215
|
-
};
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Fetch wrapper with automatic caching and data handling
|
|
219
|
-
// Usage:
|
|
220
|
-
// Fez.fetch(url) - GET request (default)
|
|
221
|
-
// Fez.fetch(url, callback) - GET with callback
|
|
222
|
-
// Fez.fetch(url, data) - GET with query params (?foo=bar&baz=qux)
|
|
223
|
-
// Fez.fetch(url, data, callback) - GET with query params and callback
|
|
224
|
-
// Fez.fetch('POST', url, data) - POST with FormData body (multipart/form-data)
|
|
225
|
-
// Fez.fetch('POST', url, data, callback) - POST with FormData and callback
|
|
226
|
-
// Data object is automatically converted:
|
|
227
|
-
// - GET: appended as URL query parameters
|
|
228
|
-
// - POST: sent as FormData (multipart/form-data) without custom headers
|
|
229
|
-
Fez.fetch = function(...args) {
|
|
230
|
-
// Initialize cache if not exists
|
|
231
|
-
Fez._fetchCache ||= {};
|
|
232
|
-
|
|
233
|
-
let method = 'GET';
|
|
234
|
-
let url;
|
|
235
|
-
let callback;
|
|
236
|
-
|
|
237
|
-
// Check if first arg is HTTP method (uppercase letters)
|
|
238
|
-
if (typeof args[0] === 'string' && /^[A-Z]+$/.test(args[0])) {
|
|
239
|
-
method = args.shift();
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// URL is required
|
|
243
|
-
url = args.shift();
|
|
244
|
-
|
|
245
|
-
// Check for data/options object
|
|
246
|
-
let opts = {};
|
|
247
|
-
let data = null;
|
|
248
|
-
if (typeof args[0] === 'object') {
|
|
249
|
-
data = args.shift();
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// Check for callback function
|
|
253
|
-
if (typeof args[0] === 'function') {
|
|
254
|
-
callback = args.shift();
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Handle data based on method
|
|
258
|
-
if (data) {
|
|
259
|
-
if (method === 'GET') {
|
|
260
|
-
// For GET, append data as query parameters
|
|
261
|
-
const params = new URLSearchParams(data);
|
|
262
|
-
url += (url.includes('?') ? '&' : '?') + params.toString();
|
|
263
|
-
} else if (method === 'POST') {
|
|
264
|
-
// For POST, convert to FormData
|
|
265
|
-
const formData = new FormData();
|
|
266
|
-
for (const [key, value] of Object.entries(data)) {
|
|
267
|
-
formData.append(key, value);
|
|
268
|
-
}
|
|
269
|
-
opts.body = formData;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Set method
|
|
274
|
-
opts.method = method;
|
|
275
|
-
|
|
276
|
-
// Create cache key from method, url, and stringified opts
|
|
277
|
-
const cacheKey = `${method}:${url}:${JSON.stringify(opts)}`;
|
|
278
|
-
|
|
279
|
-
// Check cache first
|
|
280
|
-
if (Fez._fetchCache[cacheKey]) {
|
|
281
|
-
const cachedData = Fez._fetchCache[cacheKey];
|
|
282
|
-
Fez.log(`fetch cache hit: ${method} ${url}`);
|
|
283
|
-
if (callback) {
|
|
284
|
-
callback(cachedData);
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
return Promise.resolve(cachedData);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// Log live fetch
|
|
291
|
-
Fez.log(`fetch live: ${method} ${url}`);
|
|
292
|
-
|
|
293
|
-
// Helper to process and cache response
|
|
294
|
-
const processResponse = (response) => {
|
|
295
|
-
if (response.headers.get('content-type')?.includes('application/json')) {
|
|
296
|
-
return response.json();
|
|
297
|
-
}
|
|
298
|
-
return response.text();
|
|
299
|
-
};
|
|
300
|
-
|
|
301
|
-
// If callback provided, execute and handle
|
|
302
|
-
if (callback) {
|
|
303
|
-
fetch(url, opts)
|
|
304
|
-
.then(processResponse)
|
|
305
|
-
.then(data => {
|
|
306
|
-
Fez._fetchCache[cacheKey] = data;
|
|
307
|
-
callback(data);
|
|
308
|
-
})
|
|
309
|
-
.catch(error => Fez.onError('fetch', error));
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
// Return promise with automatic JSON parsing
|
|
314
|
-
return fetch(url, opts)
|
|
315
|
-
.then(processResponse)
|
|
316
|
-
.then(data => {
|
|
317
|
-
Fez._fetchCache[cacheKey] = data;
|
|
318
|
-
return data;
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
159
|
|
|
322
160
|
Fez.onError = (kind, message) => {
|
|
323
161
|
// Ensure kind is always a string
|
|
@@ -328,14 +166,6 @@ Fez.onError = (kind, message) => {
|
|
|
328
166
|
console.error(`${kind}: ${message.toString()}`);
|
|
329
167
|
}
|
|
330
168
|
|
|
331
|
-
// define custom style macro
|
|
332
|
-
// Fez.styleMacro('mobile', '@media (max-width: 768px)')
|
|
333
|
-
// :mobile { ... } -> @media (max-width: 768px) { ... }
|
|
334
|
-
Fez._styleMacros = {}
|
|
335
|
-
Fez.styleMacro = (name, content) => {
|
|
336
|
-
Fez._styleMacros[name] = content
|
|
337
|
-
}
|
|
338
|
-
|
|
339
169
|
// work with tmp store
|
|
340
170
|
Fez.store = {
|
|
341
171
|
store: new Map(),
|
|
@@ -360,10 +190,17 @@ Fez.store = {
|
|
|
360
190
|
|
|
361
191
|
// Load utility functions
|
|
362
192
|
import addUtilities from './utility.js'
|
|
193
|
+
import cssMixin from './utils/css_mixin.js'
|
|
363
194
|
addUtilities(Fez)
|
|
195
|
+
cssMixin(Fez)
|
|
364
196
|
|
|
365
197
|
Fez.compile = compile
|
|
366
198
|
Fez.state = state
|
|
367
199
|
Fez.dump = objectDump
|
|
200
|
+
Fez.dump = highlightAll
|
|
201
|
+
|
|
202
|
+
Fez.onReady(() => {
|
|
203
|
+
Fez.log('Fez.LOG === true, logging enabled.')
|
|
204
|
+
})
|
|
368
205
|
|
|
369
206
|
export default Fez
|