Jump To …

extend_parser.js

zen-coding dom版本 开始

这里由于使用到了很多nes中的规则定义, 所以我们直接clone nes的parser

为什么不直接添加新规则到nes.parser中? 因为例如(li.class)*2 的group或者 repeat都是 nes中不需要的 拖缓了速度 还增加了冲突的可能(冲突可通过order来规避, 这个parser可以用来生成 命令行参数解析等简单任务 但是复杂的parse还是不建议这样来实现,应该通过手写或者bison这种成熟解析生成)

  var parser2 = nes.parser.clone()

其中pesudos,分隔符也是不需要

    .off(["pesudos","split"])

添加zen-coding中需要的匹配

    .on({
      "group": {
        reg:/\(([^\)]*)\)/,
        action:function(all, capture){
          this.current().group = capture
        },
        order:9
      },
      "repeat":{
        reg:/\*([1-9]\d*)/,
        action:function(all, num){
          this.current().repeat = parseInt(num)
        },
        order:8
      }
    })

根据data生成节点

  var createNode = function(option){
    var tag = option.tag,
      group = option.group,
      creater
    if(group){
      node =  create(group)
    }
    else{
      node = document.createElement(tag == "*"? "div":option.tag)
    }
    for(var i in option){
      if(creater = ExpandCreater[i]){
        creater(node, option[i])
      }
    }
    if(option.repeat){//如果重复数
      var parent = document.createDocumentFragment()
      for(var len = option.repeat;len--;){
        parent.appendChild(len ==0?node: node.cloneNode(true))
      }
      return parent
    }
    return node
  }
  var ExpandCreater = {

group与tag特殊

    id:function(node, id){
      node.id = id
    },
    classList: function(node, classList){
      node.className = classList.join(" ")
    },
    attributes:function(node, attributes){
      var len = attributes.length, attribute
      for(;len--;){
        attribute = attributes[len]
        node.setAttribute(attribute.key, typeof attribute.value == "undefined"? true : attribute.value)
      }
    }
  }
  var comboFilter = function(prev, node, combo){
    if(combo!==">" && combo!=="+"){
      throw Error("节点创建不能传入非>或+连接符")
    }else{
      if(combo === ">"){
        var parent = prev
        parent.appendChild(node)
      }else{
        parent = prev.parentNode
        if(!parent){
          parent = document.createDocumentFragment()
          parent.appendChild(prev)
        }
        parent.appendChild(node)
      }
      return parent
    }
  }

这里是暴露的api: create 传入选择器,生成dom节点(与一般的zen-coding生成字符串不同) 如果顶层节点不是一个,则返回一个documentFragment 如果是group 则进行二次create (group中有group以此类推)

  var create = function(sl){
    sl = sl.replace(/\s+/,"")
    var data = parser2.parse(sl)[0],
      len = data.length,
      datum, parent, current, prev
    for(var i = 0; i < len; i++){
      datum = data[i]
      prev = current
      current = createNode(datum)
      if(i!==0){
        var node = comboFilter(prev, current, data[i-1].combo) //匹配出真正的parent节点
        if(parent === prev) parent = node
      }
      if(!parent) parent = current
    }
    return parent
  }
  var node = create("p>div#cnt+header#id.m-hd.m-md>ul>(li#nm[rel=hah].name1+li.nm2*5)*10")
  if(console&&console.log){
    console.log("-----------------zen-coding输出--------------")

这里检查节点,如果信息不全,可以将这个节点

    nes.one("body").appendChild(node)
    console.log(node)
    console.log("-----------------zen-coding输出结束--------------")
  }