All files / src pow.safe.js

100% Statements 26/26
100% Branches 16/16
100% Functions 8/8
100% Lines 24/24

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62                              21x 21x 18x 3x 3x   15x         3x 3x   1x           11x 3x 11x 2x 2x 1x 1x         11x 11x 11x 11x 11x 11x   11x         11x      
/**
 * @license MIT
 * @author IFYates <https://github.com/ifyates/pow.js>
 * @description A very small and lightweight templating framework.
 * @version 3.7.3
 */
 
import pow from "./pow.js"
 
/**
 * Provides basic interpolation of values
 * 
 * Supports property walking and 0-argument functions
 */
function _eval(template, data, root) {
    const period = template.indexOf('.')
    if (period < 0) {
        if (template.endsWith('()')) {
            const fn = _eval(template.slice(0, -2), data, root ??= data)
            return typeof fn == 'function' ? fn(root.$data, root) : undefined
        }
        return data?.hasOwnProperty(template) ? data[template]
            : template == 'length' && typeof data == 'object' ? Object.keys(data).length
                : !root ? window[template] : undefined
    }
 
    const value = _eval(template.slice(0, period), data, root ??= data)
    return _eval(template.slice(period + 1), value, root)
}
pow._eval = _eval
 
/**
 * Rebinds event listeners on bound range after each apply
*/
function rebindEvents(element) {
    const attrs = [...element.querySelectorAll('*')].map($ => [...$.attributes]).flat()
        .filter($ => $.name.startsWith('on'))
    for (const { ownerElement, name, value } of attrs) {
        const match = /^(\$pow.+?)\.(.*?)\(/.exec(value)
        if (match) {
            ownerElement.addEventListener(name.slice(2), () => window[match[1]][match[2]](ownerElement))
            ownerElement.removeAttribute(name)
        }
    }
}
function bind(element) {
    const binding = pow.bind(element)
    const apply = binding.apply
    binding.apply = (data) => {
        const result = apply(data)
        rebindEvents(element)
        return result
    }
    return binding
}
 
// pow.safe
export default {
    apply: (element, data) => bind(element).apply(data),
    bind,
    _eval
}