saneObjectToDom.coffee
2.3 KB
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
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