jsx-parser icon indicating copy to clipboard operation
jsx-parser copied to clipboard

genCode

Open RubyLouvre opened this issue 8 years ago • 2 comments

function avalon() {
}
//单例HTML标签,多例自定义标签
var aslice = Array.prototype.slice
avalon.createElement = function (type, props, children) {
    var obj = {
        type: type,
        props: props,
        children: aslice.call(arguments, 2)
    }
    if (obj.children[2] == null) {
        if (props && Array.isArray(props.children)) {
            obj.children = props.children
        }
    }
    return obj
}

function genCode(array) {
    this.nodes = this.genChildren(array)
}

var pp = genCode.prototype

pp.genFn = function () {
    console.log(this.nodes)
    return new Function('return ' + this.nodes)
}
//如果一个元素没有JSX,那么它
pp.genTag = function (el) {
    var children = this.genChildren(el.children, el)
    return 'avalon.createElement(' + JSON.stringify(el.type) +
            ',' + this.genProps(el.props, el) +
            ',' + children + ')'
}

pp.genChildren = function (children, obj, join) {
    if (obj) {
        if (obj.isVoidTag||!obj.children.length){
             obj.static = true
            return 'null'
        }
    }
    obj.static = true
    var static = true
    var ret = []
    for (var i = 0, el; el = children[i++]; ) {
        if (el.type === '#js') {
            static = false
            if (Array.isArray(el.nodeValue)) {
                ret[ret.length] = this.genChildren(el.nodeValue, null, ' ')
            } else {
                ret[ret.length] = el.nodeValue
            }
        } else if (el.type === '#text') {
            ret[ret.length] = JSON.stringify(el.nodeValue)
        } else if (el) {
            ret[ret.length] = this.genTag(el)
            if(!el.static){
                static = false
            }
        }
    }
    if(static === false)
       delete obj.static
    return ret.join(join || ',')
}
var staticID = 0
function getStaticID(){
    return '$'+(++staticID)
}
pp.genProps = function (props, el) {
    if (!props) {
        if(el.static)
           el.static = true
        return '{$staticID:"'+ getStaticID() +'"}'
    }
    var peg = {index: 0}
    var ret = '{'
    for (var i in props) {
        ret += JSON.stringify(i) + ':' + this.genPropValue(props[i], peg) + ',\n'
    }
    if(!peg.index && el.static){
         el.static = true
        ret += '$staticID' + ':' + getStaticID() + ',\n'
    } else{
        delete el.static
    }
     
    
     return ret.replace(/\,\n$/, '') + '}'
    
}

pp.genPropValue = function (val, peg) {
    if (typeof val === 'string') {
        return JSON.stringify(val)
    }
    if (val) {
        ++peg.index
        if (Array.isArray(val.nodeValue)) {
            return this.genChildren(val.nodeValue)
        }
        if (val) {
            return val.nodeValue
        }
    }
}

//return <div ><span></span></div>
        
        
    //    React.createElement('div', {$staicID: "$3434"})

RubyLouvre avatar Mar 05 '17 17:03 RubyLouvre


//单例HTML标签,多例自定义标签


function genCode(str, config) {
    config = config || {}
    config.ns = config.ns || 'anu'
    config.type = config.type || 'eval'
    this.ns = config.ns
    this.type = config.type
    if (typeof JSXParser === 'function') {
        var array = (new JSXParser(str)).parse()
        var evalCode = this.genChildren(array)
        return evalCode
    }
}

var pp = genCode.prototype

var rComponent = /^(this|[A-Z])/
    //如果一个元素没有JSX,那么它
pp.genTag = function(el) {
    var children = this.genChildren(el.children, el)
    var ns = this.ns
    var type = rComponent.test(el.type) ? el.type : JSON.stringify(el.type)
    return ns + '.createElement(' + type +
        ',' + this.genProps(el.props, el) +
        ',' + children + ')'
}

pp.genChildren = function(children, obj, join) {
    if (obj) {
        if (obj.isVoidTag || !obj.children.length) {
            return 'null'
        }
    }

    var ret = []
    for (var i = 0, el; el = children[i++];) {
        if (el.type === '#jsx') {
            static = false
            if (Array.isArray(el.nodeValue)) {
                ret[ret.length] = this.genChildren(el.nodeValue, null, ' ')
            } else {
                ret[ret.length] = el.nodeValue
            }
        } else if (el.type === '#text') {
            ret[ret.length] = JSON.stringify(el.nodeValue)
        } else if (el) {
            ret[ret.length] = this.genTag(el)
        }
    }
    return ret.join(join || ',')
}

pp.genProps = function(props, el) {
    if (!props) {
        return 'null'
    }

    var ret = '{'
    for (var i in props) {
        ret += JSON.stringify(i) + ':' + this.genPropValue(props[i]) + ',\n'
    }

    return ret.replace(/\,\n$/, '') + '}'

}

pp.genPropValue = function(val) {
    if (typeof val === 'string') {
        return JSON.stringify(val)
    }
    if (val) {
        if (Array.isArray(val.nodeValue)) {
            return this.genChildren(val.nodeValue)
        }
        if (val) {
            return val.nodeValue
        }
    }
}

RubyLouvre avatar Mar 05 '17 17:03 RubyLouvre

function parseCode(string) { // <div id={ function(){<div/>} }>
    var word = '', //用于匹配前面的单词
        braceIndex = 1,
        codeIndex = 0,
        nodes = [],
        quote
    for (var i = 0, n = string.length; i < n; i++) {
        var c = string[i]
        if (quote) {
            if (c === quote) {
                quote = ''
            }
        } else {
            if (c === '"' || c === "'") {
                word = ''
                quote = c
            } else if (c === '{') {
                word = ''
                braceIndex++
            } else if (c === '}') {
                word = ''
                braceIndex--
                if (braceIndex === 0) {
                    var nodeValue = string.slice(codeIndex, i)
                    if (/\S/.test(nodeValue)) { //将{前面的东西放进去
                        nodes.push({
                            type: '#jsx',
                            nodeValue: nodeValue
                        })
                    }
                    return [string.slice(0, i), nodes]
                }
            } else if (c === '[' || c === ']' || c === '(' || c === ')' || c === ',') {
                word = ''
            } else if (c === '<') {
                var chunkString = string.slice(i)
                if ((word === '' || word === 'return' || word.slice(-2) == '=>') && /\<\w/.test(chunkString)) {
                    var nodeValue = string.slice(codeIndex, i)
                    if (/\S/.test(nodeValue)) { //将{前面的东西放进去
                        nodes.push({
                            type: '#jsx',
                            nodeValue: nodeValue
                        })
                    }
                    var chunk = lexer(chunkString, true)
                    nodes.push(chunk[1])
                    i += (chunk[0].length - 1) //因为已经包含了<, 需要减1
                    codeIndex = i + 1
                }
                word = ''
            } else if (c !== ' ') { //非空字符
                word += c
            } //空字符
        }
    }
}

RubyLouvre avatar Apr 14 '17 09:04 RubyLouvre