|
1 | | -{ /* global Node NodeList HTMLInputElement HTMLTextAreaElement Text */ |
| 1 | +{ |
2 | 2 | const infinify = (fn, reflect = false) => new Proxy(fn, { |
3 | 3 | get: (fn, key) => |
4 | | - (reflect && key in fn && Reflect.get(fn, key)) || fn.bind(undefined, key) |
| 4 | + typeof key !== 'symbol' && ((reflect && key in fn && Reflect.get(fn, key)) || fn.bind(undefined, key)) |
5 | 5 | }) |
6 | 6 |
|
7 | 7 | const emitter = (host = {}, listeners = new Map()) => Object.assign(host, { |
|
41 | 41 | }) |
42 | 42 | }) |
43 | 43 |
|
| 44 | + const NodeENV = typeof global === 'object' |
| 45 | + const root = NodeENV ? global : window |
| 46 | + const antiSemiotics = o => typeof o === 'symbol' ? o.toString() : o |
| 47 | + |
| 48 | + if (NodeENV) { |
| 49 | + var Text = class Text { constructor (txt) { this.textContent = txt } } |
| 50 | + } |
| 51 | + |
44 | 52 | const isArr = Array.isArray |
45 | 53 | const isDef = o => o !== undefined && o !== null |
46 | 54 | const isNil = o => o === undefined || o === null |
47 | 55 | const isObj = o => o && o.constructor === Object |
48 | 56 | const isStr = o => typeof o === 'string' |
49 | | - const isInput = o => o instanceof HTMLInputElement || o instanceof HTMLTextAreaElement |
50 | | - const isArrlike = o => isArr(o) || o instanceof NodeList || (isDef(o) && !(o instanceof Function || o instanceof Node) && o.length % 1 === 0) |
| 57 | + const isInput = o => !NodeENV && (o instanceof root.HTMLInputElement || o instanceof root.HTMLTextAreaElement) |
| 58 | + const isArrlike = o => isArr(o) || (!NodeENV && o instanceof root.NodeList) || (isDef(o) && !(o instanceof Function || (!NodeENV && o instanceof root.Node)) && o.length % 1 === 0) |
51 | 59 | const isPromise = o => typeof o === 'object' && isFunc(o.then) |
52 | 60 | const isRegExp = o => o instanceof RegExp |
53 | 61 | const isFunc = o => o instanceof Function |
|
79 | 87 | } |
80 | 88 |
|
81 | 89 | // simple global variable but you could export here |
82 | | - var SuperModel = (data, mitter = emitter(), store = new Map()) => { |
| 90 | + const SuperModel = (data, mitter = emitter(), store = new Map()) => { |
83 | 91 | let Model |
84 | 92 | const {emit, emitAsync, on, once} = mitter |
85 | 93 |
|
|
128 | 136 |
|
129 | 137 | const syncs = new Map() |
130 | 138 | const sync = new Proxy(function (obj, key, prop = key) { |
| 139 | + key = antiSemiotics(key) |
| 140 | + prop = antiSemiotics(prop) |
131 | 141 | if (isArr(obj)) { |
132 | 142 | const args = Array.from(arguments).slice(1) |
133 | 143 | if (args.every(isStr)) return sync.template(obj, ...args) |
|
183 | 193 | return obj |
184 | 194 | }, { |
185 | 195 | get (fn, prop) { |
186 | | - if (Reflect.has(fn, prop)) { |
187 | | - return Reflect.get(fn, prop) |
188 | | - } else { |
| 196 | + if (Reflect.has(fn, prop)) return Reflect.get(fn, prop) |
| 197 | + else { |
189 | 198 | return (obj, key) => { |
190 | 199 | if (isNil(obj)) return sync.text(prop) |
191 | 200 | if (isNil(key)) key = prop |
|
211 | 220 |
|
212 | 221 | sync.text = new Proxy( |
213 | 222 | prop => sync(new Text(), 'textContent', prop), |
214 | | - {get: (fn, prop) => fn(prop)} |
| 223 | + {get: (fn, prop) => fn(antiSemiotics(prop))} |
215 | 224 | ) |
216 | 225 |
|
217 | 226 | sync.template = (strings, ...keys) => flatten( |
|
225 | 234 |
|
226 | 235 | const Async = new Proxy((key, fn) => has(key) ? fn(store.get(key)) : once('set:' + key, fn), { |
227 | 236 | get: (_, key) => new Promise(resolve => { |
| 237 | + key = antiSemiotics(key) |
228 | 238 | has(key) ? resolve(store.get(key)) : once('set:' + key, resolve) |
229 | 239 | }), |
230 | 240 | set: (_, key, val) => val.then(mut.bind(undefined, key)) |
231 | 241 | }) |
232 | 242 |
|
233 | 243 | const validators = new Map() |
234 | 244 | const validateProp = key => { |
| 245 | + key = antiSemiotics(key) |
235 | 246 | const valid = store.has(key) && validators.has(key) && validators.get(key)(store.get(key)) |
236 | 247 | emit('validate:' + key, valid) |
237 | 248 | emit('validate', key, valid) |
|
240 | 251 |
|
241 | 252 | const Validation = new Proxy((key, validator) => { |
242 | 253 | if (isNil(validator)) return validateProp(key) |
| 254 | + key = antiSemiotics(key) |
243 | 255 | if (isRegExp(validator)) { |
244 | 256 | const regexp = validator |
245 | 257 | validator = val => isStr(val) && regexp.test(val) |
|
252 | 264 | } |
253 | 265 | }, { |
254 | 266 | get: (_, key) => validateProp(key), |
255 | | - set: (vd, key, val) => vd(key, val) |
| 267 | + set: (validate, key, val) => validate(key, val) |
256 | 268 | }) |
257 | 269 |
|
258 | 270 | const computed = new Map() |
259 | 271 | const compute = new Proxy(function (key, computation) { |
| 272 | + key = antiSemiotics(key) |
260 | 273 | if (isFunc(computation)) computed.set(key, computation) |
261 | 274 | else if (isStr(computation)) { |
262 | 275 | if (allare(arguments, isStr)) { |
|
345 | 358 | return Model |
346 | 359 | } |
347 | 360 | SuperModel.emitter = emitter |
| 361 | + |
| 362 | + isFunc(root.define) && root.define.amd ? root.define([], () => SuperModel) : typeof module === 'object' && module.exports ? module.exports = SuperModel : root.SuperModel = SuperModel |
348 | 363 | } |
0 commit comments