123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- module.exports = self =
- convert: (obj) ->
- self._arrayToChildren obj
- _arrayToChildren: (a, parent = null) ->
- children = []
- prev = null
- for v in a
- if typeof v is 'string'
- node = self._getTextNodeFor v
- else
- node = self._objectToNode v, parent
- node.prev = null
- node.next = null
- node.parent = parent
- if prev?
- node.prev = prev
- prev.next = node
- prev = node
- children.push node
- children
- _objectToNode: (o) ->
- i = 0
- for own k, v of o
- if i > 0
- throw Error "_objectToNode() only accepts an object with one key/value"
- key = k
- val = v
- i++
- node = {}
- if typeof key isnt 'string'
- throw Error "_objectToNode()'s key must be a string of tag name and classes"
- if typeof val is 'string'
- children = [self._getTextNodeFor(val)]
- else if Array.isArray val
- children = self._arrayToChildren val, node
- else
- inspect o
- throw Error "_objectToNode()'s key's value must only be a string or an array"
- node.type = 'tag'
- {name, attribs} = self._parseTag key
- node.name = name
- node.attribs = attribs
- node.children = children
- node
- _getTextNodeFor: (s) ->
- {type: 'text', data: s}
- _nameRx: /^[a-zA-Z\-\_]{1}[a-zA-Z0-9\-\_]*$/
- _parseTag: (k) ->
- # validate
- if not k.match(/^[a-zA-Z0-9\#\-\_\.\[\]\"\'\=\,\s]+$/) or k.match(/^[0-9]+/)
- throw Error "cannot parse tag `#{k}`"
- attribs = {}
- parts =
- name: ''
- attribs: attribs
- # tag name
- if m = k.match /^([^\.#]+)/
- name = m[1]
- unless name.match self._nameRx
- throw Error "tag name `#{name}` is not valid"
- parts.name = name
- k = k.substr name.length, k.length
- # tag id
- if m = k.match /^#([a-zA-Z0-9\-]+)/
- id = m[1]
- unless id.match self._nameRx
- throw Error "tag id `#{id}` is not valid"
- attribs.id = id
- k = k.substr id.length + 1, k.length
- classes = []
- # the class attrib
- while m = k.match /\.([a-zA-Z0-9\-\_]+)/
- cls = m[1]
- unless cls.match self._nameRx
- throw Error "tag class `#{cls}` is not valid"
- classes.push cls
- k = k.replace '.' + cls, ''
- if classes.length
- attribs.class = classes.join " "
- # TODO: match attributes like [a=b]
- parts
|