source: node_modules/hastscript/factory.js@ 65b6638

main
Last change on this file since 65b6638 was d24f17c, checked in by Aleksandar Panovski <apano77@…>, 15 months ago

Initial commit

  • Property mode set to 100644
File size: 4.6 KB
Line 
1'use strict'
2
3var find = require('property-information/find')
4var normalize = require('property-information/normalize')
5var parseSelector = require('hast-util-parse-selector')
6var spaces = require('space-separated-tokens').parse
7var commas = require('comma-separated-tokens').parse
8
9module.exports = factory
10
11var own = {}.hasOwnProperty
12
13function factory(schema, defaultTagName, caseSensitive) {
14 var adjust = caseSensitive ? createAdjustMap(caseSensitive) : null
15
16 return h
17
18 // Hyperscript compatible DSL for creating virtual hast trees.
19 function h(selector, properties) {
20 var node = parseSelector(selector, defaultTagName)
21 var children = Array.prototype.slice.call(arguments, 2)
22 var name = node.tagName.toLowerCase()
23 var property
24
25 node.tagName = adjust && own.call(adjust, name) ? adjust[name] : name
26
27 if (properties && isChildren(properties, node)) {
28 children.unshift(properties)
29 properties = null
30 }
31
32 if (properties) {
33 for (property in properties) {
34 addProperty(node.properties, property, properties[property])
35 }
36 }
37
38 addChild(node.children, children)
39
40 if (node.tagName === 'template') {
41 node.content = {type: 'root', children: node.children}
42 node.children = []
43 }
44
45 return node
46 }
47
48 function addProperty(properties, key, value) {
49 var info
50 var property
51 var result
52
53 // Ignore nullish and NaN values.
54 if (value === null || value === undefined || value !== value) {
55 return
56 }
57
58 info = find(schema, key)
59 property = info.property
60 result = value
61
62 // Handle list values.
63 if (typeof result === 'string') {
64 if (info.spaceSeparated) {
65 result = spaces(result)
66 } else if (info.commaSeparated) {
67 result = commas(result)
68 } else if (info.commaOrSpaceSeparated) {
69 result = spaces(commas(result).join(' '))
70 }
71 }
72
73 // Accept `object` on style.
74 if (property === 'style' && typeof value !== 'string') {
75 result = style(result)
76 }
77
78 // Class-names (which can be added both on the `selector` and here).
79 if (property === 'className' && properties.className) {
80 result = properties.className.concat(result)
81 }
82
83 properties[property] = parsePrimitives(info, property, result)
84 }
85}
86
87function isChildren(value, node) {
88 return (
89 typeof value === 'string' ||
90 'length' in value ||
91 isNode(node.tagName, value)
92 )
93}
94
95function isNode(tagName, value) {
96 var type = value.type
97
98 if (tagName === 'input' || !type || typeof type !== 'string') {
99 return false
100 }
101
102 if (typeof value.children === 'object' && 'length' in value.children) {
103 return true
104 }
105
106 type = type.toLowerCase()
107
108 if (tagName === 'button') {
109 return (
110 type !== 'menu' &&
111 type !== 'submit' &&
112 type !== 'reset' &&
113 type !== 'button'
114 )
115 }
116
117 return 'value' in value
118}
119
120function addChild(nodes, value) {
121 var index
122 var length
123
124 if (typeof value === 'string' || typeof value === 'number') {
125 nodes.push({type: 'text', value: String(value)})
126 return
127 }
128
129 if (typeof value === 'object' && 'length' in value) {
130 index = -1
131 length = value.length
132
133 while (++index < length) {
134 addChild(nodes, value[index])
135 }
136
137 return
138 }
139
140 if (typeof value !== 'object' || !('type' in value)) {
141 throw new Error('Expected node, nodes, or string, got `' + value + '`')
142 }
143
144 nodes.push(value)
145}
146
147// Parse a (list of) primitives.
148function parsePrimitives(info, name, value) {
149 var index
150 var length
151 var result
152
153 if (typeof value !== 'object' || !('length' in value)) {
154 return parsePrimitive(info, name, value)
155 }
156
157 length = value.length
158 index = -1
159 result = []
160
161 while (++index < length) {
162 result[index] = parsePrimitive(info, name, value[index])
163 }
164
165 return result
166}
167
168// Parse a single primitives.
169function parsePrimitive(info, name, value) {
170 var result = value
171
172 if (info.number || info.positiveNumber) {
173 if (!isNaN(result) && result !== '') {
174 result = Number(result)
175 }
176 } else if (info.boolean || info.overloadedBoolean) {
177 // Accept `boolean` and `string`.
178 if (
179 typeof result === 'string' &&
180 (result === '' || normalize(value) === normalize(name))
181 ) {
182 result = true
183 }
184 }
185
186 return result
187}
188
189function style(value) {
190 var result = []
191 var key
192
193 for (key in value) {
194 result.push([key, value[key]].join(': '))
195 }
196
197 return result.join('; ')
198}
199
200function createAdjustMap(values) {
201 var length = values.length
202 var index = -1
203 var result = {}
204 var value
205
206 while (++index < length) {
207 value = values[index]
208 result[value.toLowerCase()] = value
209 }
210
211 return result
212}
Note: See TracBrowser for help on using the repository browser.