• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1
2var util = require('./util')
3var OHOS_THEME_PROP_GROUPS = require('../../theme/ohosStyles');
4
5// http://www.w3.org/TR/css3-color/#html4
6var BASIC_COLOR_KEYWORDS = {
7  black: '#000000',
8  silver: '#C0C0C0',
9  gray: '#808080',
10  white: '#FFFFFF',
11  maroon: '#800000',
12  red: '#FF0000',
13  purple: '#800080',
14  fuchsia: '#FF00FF',
15  green: '#008000',
16  lime: '#00FF00',
17  olive: '#808000',
18  yellow: '#FFFF00',
19  navy: '#000080',
20  blue: '#0000FF',
21  teal: '#008080',
22  aqua: '#00FFFF'
23}
24
25// http://www.w3.org/TR/css3-color/#svg-color
26var EXTENDED_COLOR_KEYWORDS = {
27  aliceblue: '#F0F8FF',
28  antiquewhite: '#FAEBD7',
29  aqua: '#00FFFF',
30  aquamarine: '#7FFFD4',
31  azure: '#F0FFFF',
32  beige: '#F5F5DC',
33  bisque: '#FFE4C4',
34  black: '#000000',
35  blanchedalmond: '#FFEBCD',
36  blue: '#0000FF',
37  blueviolet: '#8A2BE2',
38  brown: '#A52A2A',
39  burlywood: '#DEB887',
40  cadetblue: '#5F9EA0',
41  chartreuse: '#7FFF00',
42  chocolate: '#D2691E',
43  coral: '#FF7F50',
44  cornflowerblue: '#6495ED',
45  cornsilk: '#FFF8DC',
46  crimson: '#DC143C',
47  cyan: '#00FFFF',
48  darkblue: '#00008B',
49  darkcyan: '#008B8B',
50  darkgoldenrod: '#B8860B',
51  darkgray: '#A9A9A9',
52  darkgreen: '#006400',
53  darkgrey: '#A9A9A9',
54  darkkhaki: '#BDB76B',
55  darkmagenta: '#8B008B',
56  darkolivegreen: '#556B2F',
57  darkorange: '#FF8C00',
58  darkorchid: '#9932CC',
59  darkred: '#8B0000',
60  darksalmon: '#E9967A',
61  darkseagreen: '#8FBC8F',
62  darkslateblue: '#483D8B',
63  darkslategray: '#2F4F4F',
64  darkslategrey: '#2F4F4F',
65  darkturquoise: '#00CED1',
66  darkviolet: '#9400D3',
67  deeppink: '#FF1493',
68  deepskyblue: '#00BFFF',
69  dimgray: '#696969',
70  dimgrey: '#696969',
71  dodgerblue: '#1E90FF',
72  firebrick: '#B22222',
73  floralwhite: '#FFFAF0',
74  forestgreen: '#228B22',
75  fuchsia: '#FF00FF',
76  gainsboro: '#DCDCDC',
77  ghostwhite: '#F8F8FF',
78  gold: '#FFD700',
79  goldenrod: '#DAA520',
80  gray: '#808080',
81  green: '#008000',
82  greenyellow: '#ADFF2F',
83  grey: '#808080',
84  honeydew: '#F0FFF0',
85  hotpink: '#FF69B4',
86  indianred: '#CD5C5C',
87  indigo: '#4B0082',
88  ivory: '#FFFFF0',
89  khaki: '#F0E68C',
90  lavender: '#E6E6FA',
91  lavenderblush: '#FFF0F5',
92  lawngreen: '#7CFC00',
93  lemonchiffon: '#FFFACD',
94  lightblue: '#ADD8E6',
95  lightcoral: '#F08080',
96  lightcyan: '#E0FFFF',
97  lightgoldenrodyellow: '#FAFAD2',
98  lightgray: '#D3D3D3',
99  lightgreen: '#90EE90',
100  lightgrey: '#D3D3D3',
101  lightpink: '#FFB6C1',
102  lightsalmon: '#FFA07A',
103  lightseagreen: '#20B2AA',
104  lightskyblue: '#87CEFA',
105  lightslategray: '#778899',
106  lightslategrey: '#778899',
107  lightsteelblue: '#B0C4DE',
108  lightyellow: '#FFFFE0',
109  lime: '#00FF00',
110  limegreen: '#32CD32',
111  linen: '#FAF0E6',
112  magenta: '#FF00FF',
113  maroon: '#800000',
114  mediumaquamarine: '#66CDAA',
115  mediumblue: '#0000CD',
116  mediumorchid: '#BA55D3',
117  mediumpurple: '#9370DB',
118  mediumseagreen: '#3CB371',
119  mediumslateblue: '#7B68EE',
120  mediumspringgreen: '#00FA9A',
121  mediumturquoise: '#48D1CC',
122  mediumvioletred: '#C71585',
123  midnightblue: '#191970',
124  mintcream: '#F5FFFA',
125  mistyrose: '#FFE4E1',
126  moccasin: '#FFE4B5',
127  navajowhite: '#FFDEAD',
128  navy: '#000080',
129  oldlace: '#FDF5E6',
130  olive: '#808000',
131  olivedrab: '#6B8E23',
132  orange: '#FFA500',
133  orangered: '#FF4500',
134  orchid: '#DA70D6',
135  palegoldenrod: '#EEE8AA',
136  palegreen: '#98FB98',
137  paleturquoise: '#AFEEEE',
138  palevioletred: '#DB7093',
139  papayawhip: '#FFEFD5',
140  peachpuff: '#FFDAB9',
141  peru: '#CD853F',
142  pink: '#FFC0CB',
143  plum: '#DDA0DD',
144  powderblue: '#B0E0E6',
145  purple: '#800080',
146  red: '#FF0000',
147  rosybrown: '#BC8F8F',
148  royalblue: '#4169E1',
149  rebeccapurple: '#663399',
150  saddlebrown: '#8B4513',
151  salmon: '#FA8072',
152  sandybrown: '#F4A460',
153  seagreen: '#2E8B57',
154  seashell: '#FFF5EE',
155  sienna: '#A0522D',
156  silver: '#C0C0C0',
157  skyblue: '#87CEEB',
158  slateblue: '#6A5ACD',
159  slategray: '#708090',
160  slategrey: '#708090',
161  snow: '#FFFAFA',
162  springgreen: '#00FF7F',
163  steelblue: '#4682B4',
164  tan: '#D2B48C',
165  teal: '#008080',
166  thistle: '#D8BFD8',
167  tomato: '#FF6347',
168  turquoise: '#40E0D0',
169  violet: '#EE82EE',
170  wheat: '#F5DEB3',
171  white: '#FFFFFF',
172  whitesmoke: '#F5F5F5',
173  yellow: '#FFFF00',
174  yellowgreen: '#9ACD32'
175}
176
177var DEFAULT_ANIMATION = {
178    animationDuration : "0ms",
179    animationDelay : "0ms",
180    animationDirection : 'normal',
181    animationTimingFunction : 'ease',
182    animationPlayState : 'running',
183    animationIterationCount : 1,
184    animationFillMode : 'none'
185}
186
187var LENGTH_REGEXP = /^[-+]?\d*\.?\d+(\S*)$/
188var LINE_GRADIENT_ITEM_REGEXP = /^([0-9a-zA-Z-]+)\((.*)\)/
189var LINE_GRADIENT_DIRECTION_REGEXP = /^\s*(to|bottom|right|left|top)|[-+]?[0-9]*\.?[0-9]+(.*)/
190var LINE_GRADIENT_TO_DIRECTION_REGEXP = /(to|bottom|right|left|top)/
191var ANGLE_REGEXP = /^[-+]?[0-9]*\.?[0-9]+(.*)/
192var ARRAY_COLOR_STOP_REGEXP = /(rgba|rgb)\([0-9,.\spx%vpfp]+\)\s?[0-9-+px%vpfp]*|[#]?\w+\s?[0-9+-\spx%vpfp]*/gi
193var URL_REGEXP = /^url\(\s*['"]?\s*([^()]+?)\s*['"]?\s*\)$/
194var NAME_REGEXP = /^[a-zA-Z_]+[a-zA-Z0-9-]*$/
195var INT_REGEXP = /^[-+]?[0-9]+$/
196var ID_REGEXP = /^\"@id\d+\"$/
197var DATE_REGEXP = /(^([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((1[02]|0?[13578])-([12][0-9]|3[01]|0?[1-9]))|((11|0?[469])-(30|[12][0-9]|0?[1-9]))|(0?2-(1[0-9]|2[0-8]|0?[1-9])))$)|(^(([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[13579][26])00))-(0?)2-29$)/
198var TRANSFORM_REGEXP = /[0-9a-zA-Z]+\s*\(\s*[0-9(a-zA-Z-|%)\.]+\s*(,\s*[0-9(a-zA-Z-|%)\.]+)*\)/g
199var TRANSFORM_ITEM_REGEXP = /^([0-9a-zA-Z]+)\s*\((.*)\)$/
200var FILTER_REGEXP = /^blur\(([1-9]\d*|0)(px|fp|vp)\)$/
201var FILTER_PERCENTAGE_REGEXP = /^blur\(([1-9]?\d|100)%\)$/
202var FILTER_STYLE_REGEXP = /^blur\(([1-9]?\d|100)%\)\s+[A-Za-z_]+$/
203var SUPPORT_CSS_UNIT = ['px', 'pt', 'wx', 'vp', 'fp']
204var SUPPORT_CSS_TIME_UNIT = ['ms', 's']
205var SUPPORT_CSS_PERCENTAGE_UNIT = ['px', '%', 'vp', 'fp']
206var SUPPORT_CSS_GRID_UNIT = ['px', '%', 'fr', 'vp', 'fp']
207var SUPPORT_CSS_TEXT_INDENT_UNIT = ['px', 'cm', '%', 'em', 'vp', 'fp']
208var SUPPORT_CSS_ANGLE_UNIT = ["deg", "rad", "grad", "turn"]
209var logTypes = ["NOTE", "WARNING", "ERROR"]
210
211var ANYTHING_VALIDATOR = function ANYTHING_VALIDATOR(v) {
212  v = (v || '').toString().trim()
213  return { value: v }
214}
215
216/**
217 * the values below is valid
218 * - number
219 * - number + 'px'|'%'|'vp'| 'fp'
220 *
221 * @param {string} v
222 * @return {function} a function to return
223 * - value: number|null
224 * - reason(k, v, result)
225 */
226var PERCENTAGE_LENGTH_VALIDATOR = function PERCENTAGE_LENGTH_VALIDATOR(v) {
227  v = (v || '').toString().trim()
228  if (v.match(ID_REGEXP)) {
229    return { value: v }
230  } else {
231    return LENGTH(v, SUPPORT_CSS_PERCENTAGE_UNIT)
232  }
233}
234
235/**
236 * the values below is valid
237 * - number
238 * - number + 'px'
239 *
240 * @param {string} v
241 * @return {function} a function to return
242 * - value: number|null
243 * - reason(k, v, result)
244 */
245var LENGTH_VALIDATOR = function LENGTH_VALIDATOR(v) {
246  v = (v || '').toString().trim()
247
248  if (v.match(ID_REGEXP)) {
249    return { value: v }
250  } else {
251    return LENGTH(v, SUPPORT_CSS_UNIT)
252  }
253}
254
255var LENGTH = function LENGTH(v, SUPPORT_UNIT) {
256  v = (v || '').toString().trim()
257  var match = v.match(LENGTH_REGEXP)
258
259  if (match) {
260    var unit = match[1]
261    if (!unit) {
262      return v === '0' ? { value: parseFloat(v) + SUPPORT_UNIT[0] } :
263        {
264          value: parseFloat(v) + SUPPORT_UNIT[0],
265          reason: function(k, v) {
266            return 'WARNING: No unit is specified for the `'+util.camelCaseToHyphened(k)+'` attribute. The default unit is ' + SUPPORT_UNIT[0]
267          }
268        }
269    } else if (SUPPORT_UNIT.indexOf(unit) > -1) {
270      return { value: v }
271    } else {
272      return {
273        value: parseFloat(v) + SUPPORT_UNIT[0],
274        reason: function reason(k, v, result) {
275          return 'ERROR: The `' + k + '` attribute does not support `' + unit + '`. The default unit is ' + SUPPORT_UNIT[0]
276        }
277      }
278    }
279  }
280
281  if (v.indexOf('@') >= 0) {
282    let result
283    // target format "@sys.float.id_sys_length" or '@sys.float.id_sys_length'
284    let SysResourceTypeRefReg = /['"]\s*@sys\.float\.(?<resName>\w+)\s*['"]/
285    result = SysResourceTypeRefReg.exec(v)
286    if (result) {
287      const resourceName = result.groups['resName']
288      if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) {
289        return { value: "@sys.float." + OHOS_THEME_PROP_GROUPS[resourceName] }
290      }
291    }
292    // target format "@app.float.developer_defined_length" or '@app.float.developer_defined_length'
293    let AppResourceTypeRefReg = /['"]\s*@app\.float\.(?<resName>\w+)\s*['"]/
294    result = AppResourceTypeRefReg.exec(v)
295    if (result) {
296      const resourceName = result.groups['resName']
297      if (resourceName) {
298        return { value: "@app.float." + resourceName}
299      }
300    }
301    // target format "@id_sys_length" or '@id_sys_length' or @id_sys_length
302    let ResourceRefReg = /['"]?\s*@(?<resName>\w+)\s*['"]?/
303    result = ResourceRefReg.exec(v)
304    if (result) {
305      const resourceName = result.groups['resName']
306      if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) {
307        return { value: "@ohos_id_" + OHOS_THEME_PROP_GROUPS[resourceName] }
308      }
309    }
310  }
311
312  return {
313    value: null,
314    reason: function reason(k, v, result) {
315      return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support the `' + v + '` value (only numbers are supported).'
316    }
317  }
318}
319
320var TEXT_INDENT_VALIDATOR = function TEXT_INDENT_VALIDATOR(v) {
321  return LENGTH(v, SUPPORT_CSS_TEXT_INDENT_UNIT)
322}
323
324/**
325 * the values below is valid
326 * - number
327 * - number + 'ms'|'s'
328 *
329 * @param {string} v
330 * @return {function} a function to return
331 * - value: number|null
332 * - reason(k, v, result)
333 */
334var TIME_VALIDATOR = function TIME_VALIDATOR(v) {
335  return LENGTH(v, SUPPORT_CSS_TIME_UNIT)
336}
337
338/**
339 * the values below is valid
340 * - number {1,4}
341 * - number + 'px' {1,4}
342 *
343 * @param {string} v
344 * @return {function} a function to return
345 * - value: number|null
346 * - reason(k, v, result)
347 */
348var SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR = function SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR(v) {
349  v = (v || '').toString().trim()
350  let rule = PERCENTAGE_LENGTH_VALIDATOR
351  return SHORTHAND_VALIDATOR(v, rule)
352}
353
354var SHORTHAND_LENGTH_VALIDATOR = function SHORTHAND_LENGTH_VALIDATOR(v) {
355  v = (v || '').toString().trim()
356  let rule = LENGTH_VALIDATOR
357  return SHORTHAND_VALIDATOR(v, rule)
358}
359
360var ARRAY_LENGTH_VALIDATOR = function ARRAY_LENGTH_VALIDATOR(v) {
361  v = (v || '').toString().trim().replace(/,/g, ' ')
362  var isArray = true
363  return SHORTHAND_VALIDATOR(v, LENGTH_VALIDATOR, isArray)
364}
365
366/**
367 * the values below is valid
368 * - hex color value (#xxxxxx or #xxx)
369 * - basic and extended color keywords in CSS spec
370 *
371 * @param {string} v
372 * @return {function} a function to return
373 * - value: string|null
374 * - reason(k, v, result)
375 */
376var COLOR_VALIDATOR = function COLOR_VALIDATOR(v) {
377  v = (v || '').toString().trim()
378
379  if (v.indexOf('linear-gradient') >= 0) {
380    let result = {
381      values: []
382    }
383    let temp = LINEAR_GRADIENT_VALIDATOR(v)
384    if (util.isValidValue(temp.value)) {
385      let tempValue = JSON.parse(temp.value)
386      result.values.push(tempValue)
387      return { value: JSON.stringify(result) }
388    } else {
389      return temp
390    }
391  }
392
393  if (v.match(ID_REGEXP)) {
394    return { value: v }
395  }
396
397  if (v.indexOf('@') >= 0) {
398    let result
399    // target format "@sys.color.id_color_background" or '@sys.color.id_color_background'
400    let SysResourceTypeRefReg = /['"]\s*@sys\.color\.(?<resName>\w+)\s*['"]/
401    result = SysResourceTypeRefReg.exec(v)
402    if (result) {
403      const resourceName = result.groups['resName']
404      if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) {
405        return { value: "@sys.color." + OHOS_THEME_PROP_GROUPS[resourceName] }
406      }
407    }
408    // target format "@app.color.developer_defined_color" or '@app.color.developer_defined_color'
409    let AppResourceTypeRefReg = /['"]\s*@app\.color\.(?<resName>\w+)\s*['"]/
410    result = AppResourceTypeRefReg.exec(v)
411    if (result) {
412      const resourceName = result.groups['resName']
413      if (resourceName) {
414        return { value: "@app.color." + resourceName}
415      }
416    }
417    // target format "@id_color_background" or '@id_color_background' or @id_color_background
418    let ResourceRefReg = /['"]?\s*@(?<resName>\w+)\s*['"]?/
419    result = ResourceRefReg.exec(v)
420    if (result) {
421      const resourceName = result.groups['resName']
422      if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) {
423        return { value: "@ohos_id_" + OHOS_THEME_PROP_GROUPS[resourceName] }
424      }
425    }
426  }
427
428  if (v.match(/^#([0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/)) {
429    return { value: v }
430  }
431
432  if (v.match(/^#[0-9a-fA-F]{3}$/)) {
433    return {
434      value: '#' + v[1] + v[1] + v[2] + v[2] + v[3] + v[3],
435      reason: function reason(k, v, result) {
436        return 'NOTE: Attribute value `' + v + '` is automatically fixed to `' + result + '`.'
437      }
438    }
439  }
440
441  if (EXTENDED_COLOR_KEYWORDS[v]) {
442    return {
443      value: EXTENDED_COLOR_KEYWORDS[v],
444      reason: function reason(k, v, result) {
445        return 'NOTE: Attribute value `' + v + '` is automatically fixed to `' + result + '`.'
446      }
447    }
448  }
449
450  if (v === 'transparent' || v === 'none') {
451    return { value: 'rgba(0,0,0,0)' }
452  }
453
454  const returnColorReg = COLOR_REG(v)
455  if (returnColorReg.value !== null) {
456    return returnColorReg
457  }
458
459  return {
460    value: null,
461    reason: function reason(k, v, result) {
462      return 'ERROR: Value `' + v + '` is invalid for the `' + util.camelCaseToHyphened(k) + '` attribute.'
463    }
464  }
465}
466
467var COLOR_REG = function COLOR_REG(v) {
468  let arrColor, r, g, b, a
469  const RGB_REGEXP = /^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/gi
470  const RGBA_REGEXP = /^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d*\.?\d+)\s*\)$/gi
471  const HSL_REGEXP = /^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)$/gi
472  const HSLA_REGEXP = /^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d*\.?\d+)\s*\)$/gi
473  if (arrColor = RGB_REGEXP.exec(v)) {
474    r = parseInt(arrColor[1])
475    g = parseInt(arrColor[2])
476    b = parseInt(arrColor[3])
477    if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) {
478      return { value: 'rgb(' + [r, g, b].join(',') + ')' }
479    }
480  }
481  if (arrColor = RGBA_REGEXP.exec(v)) {
482    r = parseInt(arrColor[1])
483    g = parseInt(arrColor[2])
484    b = parseInt(arrColor[3])
485    a = parseFloat(arrColor[4])
486    if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && a >= 0 && a <= 1) {
487      return { value: 'rgba(' + [r, g, b, a].join(',') + ')' }
488    }
489  }
490  if (arrColor = HSL_REGEXP.exec(v)) {
491    r = arrColor[1]
492    g = arrColor[2]
493    b = arrColor[3]
494    if (r >= 0 && r <= 360 && g >= 0 && g <= 100 && b >= 0 && b <= 100) {
495      return { value: 'hsl(' + [r, g+'%', b+'%'].join(',') + ')' }
496    }
497  }
498  if (arrColor = HSLA_REGEXP.exec(v)) {
499    r = arrColor[1]
500    g = arrColor[2]
501    b = arrColor[3]
502    a = arrColor[4]
503    if (r >= 0 && r <= 360 && g >= 0 && g <= 100 && b >= 0 && b <= 100 && a >= 0 && a <= 1) {
504      return { value: 'hsla(' + [r, g+'%', b+'%', a].join(',') + ')' }
505    }
506  }
507
508  return { value: null }
509}
510
511/**
512 * the values below is valid
513 * - color {1,4}
514 *
515 * @param {string} v
516 * @return {function} a function to return
517 * - value: color|null
518 * - reason(k, v, result)
519 */
520var SHORTHAND_COLOR_VALIDATOR = function SHORTHAND_COLOR_VALIDATOR(v) {
521  v = (v || '').toString().trim()
522  v = v.replace(/\s*,\s+/g, ',')
523  return SHORTHAND_VALIDATOR(v, COLOR_VALIDATOR)
524}
525
526var ARRAY_COLOR_VALIDATOR = function ARRAY_COLOR_VALIDATOR(v) {
527  v = (v || '').toString().trim()
528  var isArray = true
529  return SHORTHAND_VALIDATOR(v.replace(/,/g, ' '), COLOR_VALIDATOR, isArray)
530}
531
532var SHORTHAND_STYLE_VALIDATOR = function SHORTHAND_STYLE_VALIDATOR(v) {
533  v = (v || '').toString().trim()
534  return SHORTHAND_VALIDATOR(v, STYLE_VALIDATOR)
535}
536
537var STYLE_VALIDATOR = function STYLE_VALIDATOR(v) {
538  const styleList = ["solid", "dashed", "dotted"]
539  v = (v || '').toString().trim()
540  if (styleList.includes(v)) {
541    return { value:v }
542  } else {
543    return {
544      value: null,
545      reason: function (k,v) {
546        return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + v + '` (the support value is `' + styleList.join('`|`') + '`).'
547      }
548    }
549  }
550}
551
552var SHORTHAND_VALIDATOR = function SHORTHAND_VALIDATOR(v, validateFunction, isArray) {
553  v = (v || '').toString().trim()
554  let value = []
555  let reason = []
556  let results = v.split(/\s+/).map(validateFunction)
557  for (let i = 0; i < results.length; ++i) {
558    let res = results[i]
559    if (!res.value) {
560      value = null
561      reason = res.reason
562      break
563    }
564    value.push(res.value)
565    if (res.reason) {
566      reason.push(res.reason)
567    }
568  }
569
570  if (!value) {
571    return {
572      value: value,
573      reason: reason
574    }
575  }
576  else {
577    return {
578      value: isArray ? value.join(',') : value.join(' '),
579      reason: reason.length > 0 ? function (k, v, result) {
580        return reason.map(function (res) {
581          if (typeof res === 'function') {
582            return res(k, v, result)
583          }
584        }).join('\n')
585      } : null
586    }
587  }
588}
589
590var BORDER_VALIDATOR = function BORDER_VALIDATOR (value, name) {
591  value = (value || '').toString().trim()
592  const values = value.split(/\s+/)
593  const res = []
594  let hasError = false
595  const reasons = []
596  let index = 0
597  const order = []
598  let validatorResult
599  const rules = [
600    {
601      match (item) { return LENGTH_VALIDATOR(item).value },
602      action (item) {
603        validatorResult = LENGTH_VALIDATOR(item)
604        order.push(0)
605        res.push({
606          value: validatorResult.value,
607          type: 'Width'
608        })
609      }
610    },
611    {
612      match (item) { return validate('borderStyle', item).value },
613      action (item) {
614        validatorResult = validate('borderStyle', item)
615        order.push(1)
616        res.push({
617          value: validatorResult.value,
618          type: 'Style'
619        })
620      }
621    },
622    {
623      match (item) { return COLOR_VALIDATOR(item).value },
624      action (item) {
625        validatorResult = COLOR_VALIDATOR(item)
626        order.push(2)
627        res.push({
628          value: validatorResult.value,
629          type: 'Color'
630        })
631      }
632    },
633    {
634      match () { return true },
635      action () {
636        hasError = true
637      }
638    }
639  ]
640  if (values && values.length <= 3) {
641    for (let i = 0; i < values.length; i++) {
642      const item = values[i]
643      for (let i = 0; i < rules.length; i++) {
644        if (rules[i].match(item)) {
645          rules[i].action(item)
646          break
647        }
648      }
649      // style width color pass verification, but did not write in order, such as "1px red solid", should be error
650      let orderIndex = -1
651      order.forEach((item) => {
652        orderIndex < item ? orderIndex = item : hasError = true
653      })
654      // get all warning and note log
655      logUtil(validatorResult, name, item, reasons, index)
656    }
657    // print warning and note
658    if (!hasError) {
659      return {
660        value: res,
661        reason: reasons.length > 0 ? function (k, v) {
662          return (
663            logTypes[index] + ': There are some problems with value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute. \n ' + reasons.join(' \n'))
664        } : null
665      }
666    }
667  }
668  // print error
669  return {
670    value: null,
671    reason: function reason (k, v, result) {
672      return 'ERROR: The `' + util.camelCaseToHyphened(k) +
673      '` attribute does not support value `' + v + '` (this value does not meet the inspection standards for the width, style, and color).'
674    }
675  }
676}
677
678function logUtil (validatorResult, name, item, reasons, index) {
679  if (validatorResult.reason) {
680    let str = validatorResult.reason(name, item, validatorResult.value)
681    const mesg = str.match(/^([A-Z]+):/)
682    // When both warning and note information are included, a high severity sign is output
683    const num = logTypes.indexOf(mesg[1])
684    if (index < num) {
685      index = num
686    }
687    str = str.replace(mesg[0], '')
688    reasons.push(str)
689  }
690}
691
692var BOX_SHADOW_VALIDATOR = function BOX_SHADOW_VALIDATOR(value, name) {
693  value = (value || '').toString().trim()
694  const values = value.split(/\s+/)
695  let validatorResult
696  const res = []
697  const order = []
698  const reasons = []
699  let index = 0
700  let ruleIndex = 0
701  let hasError = false
702  const rules = [
703    {
704      match (item) { return validate('boxShadowH', item).value },
705      action (item) {
706        validatorResult = validate('boxShadowH', item)
707        order.push(0)
708        res.push({
709          value: validatorResult.value,
710          type: 'H'
711        })
712      }
713    },
714    {
715      match (item) { return validate('boxShadowV', item).value },
716      action (item) {
717        validatorResult = validate('boxShadowV', item)
718        order.push(1)
719        res.push({
720          value: validatorResult.value,
721          type: 'V'
722        })
723      }
724    },
725    {
726      match (item) { return validate('boxShadowBlur', item).value },
727      action (item) {
728        validatorResult = validate('boxShadowBlur', item)
729        order.push(2)
730        res.push({
731          value: validatorResult.value,
732          type: 'Blur'
733        })
734      }
735    },
736    {
737      match (item) { return validate('boxShadowSpread', item).value },
738      action (item) {
739        validatorResult = validate('boxShadowSpread', item)
740        order.push(3)
741        res.push({
742          value: validatorResult.value,
743          type: 'Spread'
744        })
745      }
746    },
747    {
748      match (item) { return COLOR_VALIDATOR(item).value },
749      action (item) {
750        validatorResult = COLOR_VALIDATOR(item)
751        order.push(4)
752        res.push({
753          value: validatorResult.value,
754          type: 'Color'
755        })
756      }
757    }
758  ]
759  const length = values.length
760  const flag = (length <= 6 && length >= 2) && values[0].match(LENGTH_REGEXP) && values[1].match(LENGTH_REGEXP)
761  if (values && flag) {
762    for (let i = 0; i < values.length; i++) {
763      const item = values[i]
764      for (let j = ruleIndex; j < rules.length; j++) {
765        if (rules[j].match(item)) {
766          ruleIndex++
767          rules[j].action(item)
768          break
769        }
770      }
771      let orderIndex = -1
772      order.forEach((item) => {
773        orderIndex < item ? orderIndex = item : hasError = true
774      })
775      // get all warning and note log
776      logUtil(validatorResult, name, item, reasons, index)
777    }
778    if (!hasError) {
779      return {
780        value: res,
781        reason: reasons.length > 0 ? function (k, v) {
782          return (
783            logTypes[index] + ': There are some problems with value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute. \n ' + reasons.join(' \n'))
784        } : null
785      }
786    }
787  }
788  return {
789    value: null,
790    reason: function reason (k, v, result) {
791      return 'ERROR: The `' + util.camelCaseToHyphened(k) +
792      '` attribute does not support value `' + v + '` (this value does not meet the inspection standards).'
793    }
794  }
795}
796
797/**
798 * only integer or float value is valid
799 *
800 * @param {string} v
801 * @return {function} a function to return
802 * - value: number|null
803 * - reason(k, v, result)
804 */
805var NUMBER_VALIDATOR = function NUMBER_VALIDATOR(v, isInt) {
806  v = (v || '').toString().trim()
807
808  if (v.match(ID_REGEXP)) {
809    return { value: v }
810  }
811
812  var match = v.match(LENGTH_REGEXP)
813
814  if (match && !match[1]) {
815    return { value: isInt === true ? parseInt(v, 10) : parseFloat(v) }
816  }
817
818  if (v.indexOf('@') >= 0) {
819    let result
820    // target format "@sys.float.id_sys_number" or '@sys.float.id_sys_number'
821    let SysResourceTypeRefReg = /['"]\s*@sys\.float\.(?<resName>\w+)\s*['"]/
822    result = SysResourceTypeRefReg.exec(v)
823    if (result) {
824      const resourceName = result.groups['resName']
825      if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) {
826        return { value: "@sys.float." + OHOS_THEME_PROP_GROUPS[resourceName] }
827      }
828    }
829    // target format "@app.float.developer_defined_number" or '@app.float.developer_defined_number'
830    let AppResourceTypeRefReg = /['"]\s*@app\.float\.(?<resName>\w+)\s*['"]/
831    result = AppResourceTypeRefReg.exec(v)
832    if (result) {
833      const resourceName = result.groups['resName']
834      if (resourceName) {
835        return { value: "@app.float." + resourceName}
836      }
837    }
838    // target format "@id_sys_number" or '@id_sys_number' or @id_sys_number
839    let ResourceRefReg = /['"]?\s*@(?<resName>\w+)\s*['"]?/
840    result = ResourceRefReg.exec(v)
841    if (result) {
842      const resourceName = result.groups['resName']
843      if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) {
844        return { value: "@ohos_id_" + OHOS_THEME_PROP_GROUPS[resourceName] }
845      }
846    }
847  }
848
849  return {
850    value: null,
851    reason: function reason(k, v, result) {
852      return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + v + '` (only numbers are supported).'
853    }
854  }
855}
856
857var ARRAY_NUMBER_VALIDATOR = function ARRAY_NUMBER_VALIDATOR(v) {
858  v = (v || '').toString().trim().replace(/,/g, ' ')
859  var isArray = true
860  return SHORTHAND_VALIDATOR(v, NUMBER_VALIDATOR, isArray)
861}
862
863/**
864 * only integer value is valid
865 *
866 * @param {string} v
867 * @return {function} a function to return
868 * - value: number|null
869 * - reason(k, v, result)
870 */
871var INTEGER_VALIDATOR = function INTEGER_VALIDATOR(v) {
872  return NUMBER_VALIDATOR(v, true)
873}
874
875/**
876 * transition-property: only css property is valid
877 *
878 * @param {string} v
879 * @return {function} a function to return
880 * - value: string|null
881 * - reason(k, v, result)
882 */
883var TRANSITION_PROPERTY_VALIDATOR = function TRANSITION_PROPERTY_VALIDATOR(v) {
884  v = (v || '').toString()
885  v = v.split(/\s*,\s*/).map(util.hyphenedToCamelCase).join(',')
886
887  if (v.split(/\s*,\s*/).every(p => !!validatorMap[p])) {
888    return {value: v}
889  }
890
891  return {
892    value: null,
893    reason: function reason(k, v, result) {
894      return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + v + '` (only CSS attributes support this value).'
895    }
896  }
897}
898
899/**
900 * transition-duration & transition-delay: only number of seconds or milliseconds is valid
901 *
902 * @param {string} v
903 * @return {function} a function to return
904 * - value: number|null
905 * - reason(k, v, result)
906 */
907var TRANSITION_INTERVAL_VALIDATOR = function TRANSITION_INTERVAL_VALIDATOR(v) {
908  v = (v || 0).toString()
909  var match, num, ret
910
911  if (match = v.match(/^\d*\.?\d+(ms|s)?$/)) {
912    num = parseFloat(match[0])
913    if (!match[1]) {
914      ret = {value: parseInt(num)}
915    }
916    else {
917      if (match[1] === 's') {
918        num *= 1000
919      }
920      ret = {
921        value: parseInt(num),
922        reason: function reason(k, v, result) {
923          return 'NOTE: Attribute value `' + v + '` is automatically fixed to `' + result + '`.'
924        }
925      }
926    }
927    return ret
928  }
929
930  return {
931    value: null,
932    reason: function reason(k, v, result) {
933      return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + v + '` (only seconds and milliseconds are supported).'
934    }
935  }
936}
937
938/**
939 * transition-timing-function: only linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier(n,n,n,n) is valid
940 *
941 * @param {string} v
942 * @return {function} a function to return
943 * - value: linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier(n,n,n,n)|null
944 * - reason(k, v, result)
945 */
946var TRANSITION_TIMING_FUNCTION_VALIDATOR = function TRANSITION_TIMING_FUNCTION_VALIDATOR(v) {
947  v = (v || '').toString()
948
949  if (v.match(/^linear|ease|ease-in|ease-out|ease-in-out|fast-out-slow-in|linear-out-slow-in$/) ||
950    v.match(/^fast-out-linear-in|friction|extreme-deceleration|sharp|rhythm|smooth$/)) {
951    return {value: v}
952  }
953
954  let match, ret
955  let NUM_REGEXP = /^[-]?\d*\.?\d+$/
956  if (match = v.match(/^cubic-bezier\(\s*(.*)\s*,\s*(.*)\s*,\s*(.*)\s*,\s*(.*)\s*\)$/)) {
957    /* istanbul ignore else */
958    if (match[1].match(NUM_REGEXP) && match[2].match(NUM_REGEXP) && match[3].match(NUM_REGEXP) && match[4].match(NUM_REGEXP)) {
959      ret = [parseFloat(match[1]), parseFloat(match[2]), parseFloat(match[3]), parseFloat(match[4])].join(',')
960      return {value: 'cubic-bezier(' + ret + ')'}
961    }
962  }
963
964  // check steps
965  if (match = v.match(/^steps\(\s*([\d]*)\s*(,\s*(start|end)\s*){0,1}\)$/)) {
966    var stepCnt = parseFloat(match[1]);
967    if (stepCnt > 0) {
968      if (match[3] === undefined) {
969        ret = stepCnt;
970      } else {
971        ret = [stepCnt, match[3]].join(',')
972      }
973      return {value: 'steps(' + ret + ')'}
974    }
975  }
976
977  return {
978    value: null,
979    reason: function reason(k, v, result) {
980      return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + v +
981             '` (supported values include `linear`, `ease`, `ease-in`, `ease-out`, `ease-in-out`, `cubic-bezier(n,n,n,n)` and `steps(n[, start|end])`).'
982    }
983  }
984}
985
986function parseAnimationOption(key, option, style)
987{
988   var subResult = validate(key, option)
989   if (subResult.value) {
990       style[key] = subResult.value
991       return true
992   }
993    return false
994}
995
996function parseSimpleAnimation(style, animation) {
997    // init default animation brief value
998    Object.assign(style, DEFAULT_ANIMATION)
999    let options = animation.trim().replace(/,\s+/g, ",").split(/\s+/)
1000    let durationIdx = NaN
1001    let delayIdx = NaN
1002    let directionIdx = NaN
1003    let timingIdx = NaN
1004    let playStateIdx = NaN
1005    let iterationIdx = NaN
1006    let fillModeIdx = NaN
1007    for (let idx in options) {
1008        const option = options[idx]
1009        if (isNaN(timingIdx) && parseAnimationOption('animationTimingFunction', option, style)) {
1010            timingIdx = idx
1011            continue
1012        }
1013        if (isNaN(directionIdx) && parseAnimationOption('animationDirection', option, style)) {
1014            directionIdx = idx
1015            continue
1016        }
1017        if (isNaN(playStateIdx) && parseAnimationOption('animationPlayState', option, style)) {
1018            playStateIdx = idx
1019            continue
1020        }
1021        if (isNaN(iterationIdx) && parseAnimationOption('animationIterationCount', option, style)) {
1022            iterationIdx = idx
1023            continue
1024        }
1025        if (isNaN(fillModeIdx) && parseAnimationOption('animationFillMode', option, style)) {
1026            fillModeIdx = idx
1027            continue
1028        }
1029        if (isNaN(durationIdx) && parseAnimationOption('animationDuration', option, style)) {
1030            durationIdx = idx
1031            continue
1032        }
1033        if (isNaN(delayIdx) && parseAnimationOption('animationDelay', option, style)) {
1034            delayIdx = idx
1035            continue
1036        }
1037    }
1038    delete options[durationIdx]
1039    delete options[delayIdx]
1040    delete options[directionIdx]
1041    delete options[timingIdx]
1042    delete options[playStateIdx]
1043    delete options[iterationIdx]
1044    delete options[fillModeIdx]
1045    options = options.filter(res => { return !(res === 'undefined') })
1046    if (options.length === 1) {
1047       if (!parseAnimationOption('animationName', options[0], style)) {
1048           return false
1049       }
1050       return true
1051    } else if (options.length > 1) {
1052        return false
1053    } else {
1054        // use default.
1055        return true
1056    }
1057}
1058
1059var ANIMATION_VALIDATOR = function ANIMATION_VALIDATOR(v) {
1060    var style = {}
1061    if (parseSimpleAnimation(style, v)) {
1062        return {value: style}
1063    } else {
1064        return {
1065            value: null,
1066            reason: function reason(k, v, result) {
1067                return 'ERROR: animation is invalid'
1068            }
1069        }
1070    }
1071}
1072
1073var TRANSFORM_VALIDATOR = function TRANSFORM_VALIDATOR(v) {
1074  v = (v || '').toString().trim()
1075  if (v.match(/^none$/)) {
1076    return { value: JSON.stringify({}) }
1077  }
1078  const values = []
1079  TRANSFORM_REGEXP.lastIndex = 0
1080  while (true) {
1081    let matchValue = TRANSFORM_REGEXP.exec(v)
1082    if (!matchValue) {
1083      break
1084    }
1085    values.push(v.slice(matchValue.index, TRANSFORM_REGEXP.lastIndex))
1086  }
1087  if (!values.length) {
1088    return {
1089      value: null,
1090      reason: function reason(k, v) {
1091        return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + v + '`.'
1092      }
1093    }
1094  }
1095  let result = {}
1096  let reasonMaps = []
1097  let allLength = 0
1098  values.forEach(function(v) {
1099    let length = 0
1100    let match = v.match(TRANSFORM_ITEM_REGEXP)
1101    if (match) {
1102      let firstValue = match[1]
1103      let secondValue = match[2]
1104      let checkFuntion = transformValidatorMap[firstValue]
1105      if (typeof checkFuntion == 'function') {
1106        var checkResult = checkFuntion(secondValue)
1107        if (typeof checkResult.value == 'number' || typeof checkResult.value == 'string') {
1108          result[firstValue] = checkResult.value
1109        }
1110        let check = checkReason(checkResult, firstValue, secondValue, length)
1111        length = check.length
1112        if (check.realReason) {
1113          reasonMaps.push(check.realReason)
1114        }
1115      } else {
1116        length = 2
1117        reasonMaps.push('property `' + firstValue + '` is invalid.')
1118      }
1119    } else {
1120      length = 2
1121      reasonMaps.push('property value `' + v + '` is invalid.')
1122    }
1123    if (allLength < length) {
1124      allLength = length
1125    }
1126  })
1127  return {
1128    value: result ? JSON.stringify(result) : null,
1129    reason: reasonMaps.length > 0 ?
1130      function(k, v) {
1131        return logTypes[allLength] + ': Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect. \n ' + reasonMaps.join(' \n ')
1132      } : null
1133  }
1134}
1135
1136var MULTIPLE_PERCENTAGE_LENGTH_VALIDATOR = function MULTIPLE_PERCENTAGE_LENGTH_VALIDATOR(v) {
1137  v = (v || '').toString().trim()
1138  return MULTIPLE_POSITION_VALIDATOR(v, PERCENTAGE_LENGTH_VALIDATOR)
1139}
1140
1141var MULTIPLE_NUMBER_VALIDATOR = function MULTIPLE_NUMBER_VALIDATOR(v) {
1142  v = (v || '').toString().trim()
1143  return MULTIPLE_POSITION_VALIDATOR(v, NUMBER_VALIDATOR)
1144}
1145
1146var MUTIPLE_ANGLE_VALIDATOR = function MUTIPLE_ANGLE_VALIDATOR(v) {
1147  v = (v || '').toString().trim()
1148  return MULTIPLE_POSITION_VALIDATOR(v, ANGLE_VALIDATOR)
1149}
1150
1151var ROTATE3D_VALIDATOR = function ROTATE3D_VALIDATOR(v) {
1152  v = (v || '').toString().trim()
1153  let values = v.split(/,/g)
1154  if (values && values.length > 0) {
1155    let resultValues = []
1156    let childResult = void 0
1157    let reasonMaps = []
1158    let length = 0
1159    if (values.length != 4) {
1160      length = 2
1161      reasonMaps.push('The number of properties is 4, value ' + values + ' is incorrect.')
1162    } else {
1163      values.forEach(function (value, index) {
1164        if (index < 3) {
1165          childResult = NUMBER_VALIDATOR(value)
1166        } else {
1167          childResult = ANGLE_VALIDATOR(value)
1168        }
1169        if (typeof childResult.value == 'number' || typeof childResult.value == 'string') {
1170          resultValues.push(childResult.value)
1171        }
1172        let check = checkReason(childResult, index.toString(), value, length)
1173        length = check.length
1174        if (check.realReason !== null) {
1175          reasonMaps.push(check.realReason)
1176        }
1177      })
1178    }
1179
1180    return {
1181      value: length < 2 ? resultValues.join(' ') : null,
1182      reason: reasonMaps.length > 0 ?
1183        function (k, v) {
1184          return logTypes[length] + ': Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect. \n ' + reasonMaps.join(' \n ')
1185        } : null
1186    }
1187  }
1188}
1189
1190var MULTIPLE_POSITION_VALIDATOR = function MULTIPLE_POSITION_VALIDATOR(v, validateFunction) {
1191  v = (v || '').toString().trim()
1192  let values = v.split(/,/g)
1193  if (values && values.length > 0) {
1194    let resultValues = []
1195    let childResult = void 0
1196    let reasonMaps = []
1197    let length = 0
1198    if (values.length > 16) {
1199      length = 2
1200      reasonMaps.push('The maximum number of properties is 16, value ' + values + ' is incorrect.')
1201    }
1202    values.forEach(function (value, index) {
1203      childResult = validateFunction(value)
1204      if (typeof childResult.value == 'number' || typeof childResult.value == 'string') {
1205        resultValues.push(childResult.value)
1206      }
1207      let check = checkReason(childResult, index.toString(), value, length)
1208      length = check.length
1209      if (check.realReason !== null) {
1210        reasonMaps.push(check.realReason)
1211      }
1212    })
1213    return {
1214      value: length < 2 ? resultValues.join(' ') : null,
1215      reason: reasonMaps.length > 0 ?
1216        function (k, v) {
1217          return logTypes[length] + ': Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect. \n ' + reasonMaps.join(' \n ')
1218        } : null
1219    }
1220  }
1221}
1222
1223/**
1224 * generate a function to check whether a value is in `list`
1225 * - first value: default, could be removed
1226 * - not in `list`: incorrect
1227 *
1228 * @param  {Array} list
1229 * @return {function} a function(v) which returns a function to return
1230 * - value: string|null
1231 * - reason(k, v, result)
1232 */
1233function genEnumValidator(list) {
1234  return function ENUM_VALIDATOR(v, name) {
1235    v = (v || '').toString().trim()
1236    if (v.match(ID_REGEXP)) {
1237      return {value: v}
1238    }
1239
1240    var index = list.indexOf(v)
1241    if (index > 0) {
1242      return {value: v}
1243    }
1244    if (index === 0) {
1245      return {
1246        value: v,
1247        reason: name !== 'objectFit' ?
1248          function reason(k, v, result) {
1249            return 'NOTE: Value `' + v + '` is the default value of the `' + util.camelCaseToHyphened(k) + '` attribute (the value can be removed).'
1250          } : null
1251      }
1252    }
1253    else {
1254      return {
1255        value: null,
1256        reason: function reason(k, v, result) {
1257          return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + v + '` (the supported value is `' + list.join('`|`') + '`).'
1258        }
1259      }
1260    }
1261  }
1262}
1263
1264var MASK_VALIDATOR = function MASK_VALIDATOR(v) {
1265  if (v.indexOf('url') >= 0) {
1266      return URL_VALIDATOR(v)
1267  } else {
1268      return BACKGROUND_VALIDATOR(v)
1269  }
1270}
1271
1272var BACKGROUND_VALIDATOR = function BACKGROUND_VALIDATOR(v) {
1273  v = (v || '').toString().trim()
1274  if (v.indexOf('-gradient') > 0) {
1275    let valueMatch = v.match(/(repeating-linear|linear).*?(?=\s*(repeating|linear)|$)/g)
1276    let resultValues = {
1277      values: []
1278    }
1279    if (valueMatch && valueMatch.length) {
1280      let reasonMaps = []
1281      let length = 0
1282      valueMatch.forEach(function (realValue) {
1283        let temp, gradientValidator
1284        if(realValue.indexOf("-gradient") >= 0){
1285          temp = realValue.indexOf("repeating") >= 0 ? "repeatingLinearGradient": "linearGradient"
1286          gradientValidator = backgroundValidatorMap[temp]
1287        }
1288        if (typeof gradientValidator == 'function') {
1289          let validateResult = gradientValidator(realValue)
1290          if (util.isValidValue(validateResult.value)) {
1291            let jsonValue = JSON.parse(validateResult.value)
1292            resultValues.values.push(jsonValue)
1293          }
1294          let check = checkReason(validateResult, temp, realValue, length)
1295          length = check.length
1296          if (check.realReason !== null) {
1297            reasonMaps.push(check.realReason)
1298          }
1299        } else {
1300          length = 2
1301          reasonMaps.push("background type '" + realValue + "' is not supported.")
1302        }
1303      })
1304      return {
1305        value: length < 2 ? JSON.stringify(resultValues) : null,
1306        reason: reasonMaps.length > 0 ?
1307          function (k, v) {
1308            return logTypes[length] + ': Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect. \n ' + reasonMaps.join(' \n ')
1309          } : null
1310      }
1311    }
1312  }
1313  return {
1314    value: null,
1315    reason: function (k, v) {
1316      return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect.'
1317    }
1318  }
1319}
1320
1321var LINEAR_GRADIENT_VALIDATOR = function LINEAR_GRADIENT_VALIDATOR(v) {
1322  v = (v || "").toString().trim()
1323  let result = {
1324    type: "",
1325    directions: ["to", "bottom"],
1326    values: []
1327  }
1328  let valueMatch = v.match(LINE_GRADIENT_ITEM_REGEXP)
1329  if (valueMatch) {
1330    let tempResult = {}
1331    let reasonMaps = []
1332    let length = 0
1333    let typeName = util.hyphenedToCamelCase(valueMatch[1])
1334    result.type = typeName
1335    let matchValues = valueMatch[2].split(/,/)
1336    if (LINE_GRADIENT_DIRECTION_REGEXP.test(matchValues[0])) {
1337      let directionValidator
1338      if (LINE_GRADIENT_TO_DIRECTION_REGEXP.test(matchValues[0])) {
1339        directionValidator = backgroundValidatorMap.linearGradientDirection
1340      } else if (matchValues[0].match(ANGLE_REGEXP)) {
1341        directionValidator = backgroundValidatorMap.linearGradientAngle
1342      }
1343      if (typeof directionValidator == "function") {
1344        tempResult = directionValidator(matchValues[0])
1345        if (util.isValidValue(tempResult.value)) {
1346          result.directions = tempResult.value.split(/\s+/)
1347        }
1348        let check = checkReason(tempResult, typeName, matchValues[0], length)
1349        length = check.length
1350        if (check.realReason !== null) {
1351          reasonMaps.push(check.realReason)
1352        }
1353        matchValues.splice(0, 1)
1354      }
1355    }
1356    if (matchValues.length > 0) {
1357      let colorStopResult = {}
1358      colorStopResult = backgroundValidatorMap.linearGradientColor(matchValues)
1359      if (util.isValidValue(colorStopResult.value)) {
1360        result.values = JSON.parse(colorStopResult.value)
1361      }
1362      let check = checkReason(colorStopResult, typeName, matchValues, length)
1363        length = check.length
1364        if (check.realReason !== null) {
1365          reasonMaps.push(check.realReason)
1366        }
1367    } else {
1368      length = 2
1369      reasonMaps.push("parameter '" + v + "' missing transition colors.")
1370    }
1371    return {
1372      value: length < 2 ? JSON.stringify(result) : null,
1373      reason: reasonMaps.length > 0 ?
1374        function (k, v) {
1375          return logTypes[length] + ': Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect. \n  ' + reasonMaps.join('\n  ')
1376        }: null
1377    }
1378  }
1379  return {
1380    value: null,
1381    reason: function (k, v) {
1382      return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect.'
1383    }
1384  }
1385}
1386
1387var ARRAY_COLOR_STOP_VALIDATOR = function ARRAY_COLOR_STOP_VALIDATOR(v) {
1388  v = (v || '').toString().trim()
1389  let values = v.match(ARRAY_COLOR_STOP_REGEXP)
1390  if (values && values.length > 1) {
1391    let resultValues = []
1392    let reasonMaps = []
1393    let length = 0
1394    values.forEach(function (value, n) {
1395      let widthMatch = value.match(/[\s]+[-+0-9]+(px|%|vp|fp)?$/)
1396      let tempValues = []
1397      if (widthMatch) {
1398        let matchResult = PERCENTAGE_LENGTH_VALIDATOR(widthMatch[0])
1399        let index = value.indexOf(widthMatch[0])
1400        value = value.substring(0, index)
1401        if (util.isValidValue(matchResult.value)) {
1402          tempValues.push(matchResult.value)
1403        }
1404        let check = checkReason(matchResult, n.toString(), widthMatch[0], length)
1405        length = check.length
1406        if (check.realReason !== null) {
1407          reasonMaps.push(check.realReason)
1408        }
1409      }
1410      if (value) {
1411        let colorResult = COLOR_VALIDATOR(value)
1412        if (util.isValidValue(colorResult.value)) {
1413          tempValues.unshift(colorResult.value)
1414        }
1415        resultValues.push(tempValues.join(' '))
1416        let check = checkReason(colorResult, n.toString(), value, length)
1417        length = check.length
1418        if (check.realReason !== null) {
1419          reasonMaps.push(check.realReason)
1420        }
1421      } else {
1422        length = 2
1423        reasonMaps.push("parameter '" + v + "' is incorrect format.")
1424      }
1425    })
1426    return {
1427      value: length < 2 ? JSON.stringify(resultValues) : null,
1428      reason: reasonMaps.length > 0 ?
1429        function (k, v) {
1430          return logTypes[length] + ': Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect. \n  ' + reasonMaps.join('\n  ')
1431        } : null
1432    }
1433  }
1434  return {
1435    value: null,
1436    reason: function (k, v) {
1437      return 'ERROR: The format of value `' + v + '` of the `'+ util.camelCaseToHyphened(k) + '` attribute is incorrect. Please specify at least two colors.'
1438    }
1439  }
1440}
1441
1442function checkReason(result, k, v, length) {
1443  let reason
1444  if (result.reason) {
1445    reason = result.reason(k, v, result.value)
1446    if (reason) {
1447      let reasonType = reason.match(/^([A-Z]+):/)
1448      let index
1449      if (reasonType) {
1450        index = logTypes.indexOf(reasonType[1])
1451        if (logTypes.indexOf(reasonType[1]) > length) {
1452          length = index
1453        }
1454        reason = reason.replace(reasonType[0], '').trim()
1455      }
1456    }
1457  }
1458  return {
1459    length: length,
1460    realReason: reason ? reason : null
1461  }
1462}
1463
1464var ANGLE_VALIDATOR = function ANGLE_VALIDATOR(v) {
1465  v = (v || '').toString().trim()
1466  let match = v.match(ANGLE_REGEXP)
1467  if (match) {
1468    let unit = match[1]
1469    if (unit) {
1470      let angle = parseFloat(v)
1471      if (unit.toLowerCase() === 'rad') {
1472        return {
1473          value: Math.round(180 * angle / Math.PI) + SUPPORT_CSS_ANGLE_UNIT[0]
1474        }
1475      } else {
1476        if (SUPPORT_CSS_ANGLE_UNIT.indexOf(unit.toLowerCase()) >= 0) {
1477          return { value: v }
1478        } else {
1479          return {
1480            value: angle + SUPPORT_CSS_ANGLE_UNIT[0],
1481            reason: function(k, v) {
1482              return 'ERROR: The `' + util.camelCaseToHyphened(k) +
1483              '` attribute does not support `' + unit + '`. It only supports `' + JSON.stringify(SUPPORT_CSS_ANGLE_UNIT) + '`.'
1484            }
1485          }
1486        }
1487      }
1488    } else {
1489      return {
1490        value: parseFloat(v) + SUPPORT_CSS_ANGLE_UNIT[0],
1491        reason: function(k, v) {
1492          return 'WARNING: No unit is specified for the value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute. The default unit is `' + SUPPORT_CSS_ANGLE_UNIT[0] + '`.'
1493        }
1494      }
1495    }
1496  }
1497  return {
1498    value: null,
1499    reason: function(k, v) {
1500      return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + v + '` (only numbers are supported).'
1501    }
1502  }
1503}
1504
1505var GRADIENT_DIRECTION_VALIDATOR = function GRADIENT_DIRECTION_VALIDATOR(v) {
1506  v = (v || "").toString().trim()
1507  let values = v.split(/\s+/)
1508  let invalid = false
1509  let scaleY = ['top','bottom']
1510  let scaleX = ['left','right']
1511  let valueOrder = []
1512
1513  values.forEach(function (value) {
1514    if (value === 'to') {
1515      valueOrder.push(0)
1516    } else if (scaleY.includes(value)) {
1517      valueOrder.push(1)
1518    } else if (scaleX.includes(value)) {
1519      valueOrder.push(2)
1520    } else {
1521      invalid = true
1522    }
1523  })
1524  if (!invalid) {
1525    if (valueOrder[0] === 0 && valueOrder.length > 1 && valueOrder.length < 4 && valueOrder[1] !== 0) {
1526      if (valueOrder[2] && valueOrder[1] + valueOrder[2] !== 3) {
1527        invalid = true
1528      }
1529    }
1530  }
1531
1532  return {
1533    value: invalid ? null : v,
1534    reason: invalid ?
1535      function (k, v) {
1536        return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect.'
1537      } : null
1538  }
1539}
1540
1541var URL_VALIDATOR = function URL_VALIDATOR(v) {
1542  v = (v || "").toString().trim()
1543  if (v.match(/^none$/i)) {
1544    return { value: "none" }
1545  }
1546  if (v.indexOf('@') >= 0) {
1547    let result
1548    // target format "@sys.media.sys_background_image" or '@sys.media.sys_background_image'
1549    let SysResourceTypeRefReg = /['"]\s*@sys\.media\.(?<resName>\w+)\s*['"]/
1550    result = SysResourceTypeRefReg.exec(v)
1551    if (result) {
1552      const resourceName = result.groups['resName']
1553      if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) {
1554        return { value: "@sys.media." + OHOS_THEME_PROP_GROUPS[resourceName] }
1555      }
1556    }
1557    // target format "@app.media.customized_background_image" or '@app.media.customized_background_image'
1558    let AppResourceTypeRefReg = /['"]\s*@app\.media\.(?<resName>\w+)\s*['"]/
1559    result = AppResourceTypeRefReg.exec(v)
1560    if (result) {
1561      const resourceName = result.groups['resName']
1562      if (resourceName) {
1563        return { value: "@app.media." + resourceName}
1564      }
1565    }
1566  }
1567
1568  let matchValues = URL_REGEXP.exec(v)
1569  if (matchValues) {
1570    if(isLiteDevice){
1571      return { value: matchValues[0] }
1572    }else{
1573      if (matchValues[1].match(/^\.\.\/|^\.\//)) {
1574        return {
1575          value: matchValues[1],
1576          isRelative: true
1577        }
1578      }
1579      else {
1580        return { value: matchValues[1] }
1581      }
1582    }
1583  }
1584  else {
1585    return {
1586      value: null,
1587      reason: function (k, v) {
1588          return 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute must be none or url(...).'
1589      }
1590    }
1591  }
1592}
1593
1594var NAME_VALIDATOR = function NAME_VALIDATOR(v) {
1595  v = (v || "").toString().trim()
1596  if (v.match(NAME_REGEXP)) {
1597    return  { value: v }
1598  } else {
1599    return {
1600      value: null,
1601      reason: function(k, v) {
1602        return 'ERROR: The format of value `' + v + '` of the `' +  util.camelCaseToHyphened(k) + '` attribute is incorrect.'
1603      }
1604    }
1605  }
1606}
1607
1608var ITERATIONCOUNT_VALIDATOR = function ITERATIONCOUNT_VALIDATOR(v) {
1609  v = (v || "").toString().trim()
1610  if (v.match(INT_REGEXP)) {
1611    return {
1612      value: parseInt(v, 10)
1613    }
1614  } else if (v.match(/^infinite$/)) {
1615    return { value: -1 }
1616  } else {
1617    return {
1618      value: null,
1619      reason: function(k, v) {
1620          return 'ERROR: The format of value `' + v + '` of the `' +  util.camelCaseToHyphened(k) + '` attribute is incorrect (only integers and infinity are supported).'
1621      }
1622    }
1623  }
1624}
1625
1626var BACKGROUND_SIZE_VALIDATOR = function BACKGROUND_SIZE_VALIDATOR(v) {
1627  v = (v || "").toString().trim()
1628  let values = v.split(/\s+/)
1629  const sizeReg = /auto|contain|cover/g
1630  if (values.length === 1) {
1631    if (/^(auto|contain|cover)$/.test(v)) {
1632      return { value: v }
1633    } else {
1634      return PERCENTAGE_LENGTH_VALIDATOR(v)
1635    }
1636  }
1637  if (values.length === 2 && !sizeReg.test(v)) {
1638    return SHORTHAND_VALIDATOR(v, PERCENTAGE_LENGTH_VALIDATOR)
1639  }
1640  return {
1641    value: null,
1642    reason: function(k, v) {
1643      return 'ERROR: Value `' + v + '` of the `' +  util.camelCaseToHyphened(k) + '` attribute is incorrect.'
1644    }
1645  }
1646}
1647
1648var BACKGROUND_POSITION_VALIDATOR = function BACKGROUND_POSITION_VALIDATOR(v) {
1649  v = (v || '').toString().trim()
1650  let values = v.split(/\s+/)
1651  const positionReg = /left|right|top|bottom|center/g
1652  if (values.length === 1) {
1653    if (/^(left|right|top|bottom|center)$/.test(v)) {
1654      return { value: v }
1655    } else {
1656      return PERCENTAGE_LENGTH_VALIDATOR(v)
1657    }
1658  }
1659  if (values.length === 2) {
1660    if (!positionReg.test(v)) {
1661      return SHORTHAND_VALIDATOR(v, PERCENTAGE_LENGTH_VALIDATOR)
1662    } else {
1663      return CHECK_BACKGROUND_POSITION(v)
1664    }
1665  }
1666  return {
1667    value: null,
1668    reason: function(k, v) {
1669      return 'ERROR: Value `' + v + '` of the `' +  util.camelCaseToHyphened(k) + '` attribute is incorrect.'
1670    }
1671  }
1672}
1673
1674var CHECK_BACKGROUND_POSITION = function CHECK_BACKGROUND_POSITION(v) {
1675  let values = v.split(/\s+/)
1676  let result = []
1677  let reasons = []
1678  let directions = []
1679  values.forEach(function(value, index) {
1680    if (/^(left|right|top|bottom|center)$/.test(value)) {
1681      result.push(value)
1682      if (checkDirection(value)) {
1683        directions.push(checkDirection(value))
1684      }
1685    } else {
1686      let tempResult = PERCENTAGE_LENGTH_VALIDATOR(value)
1687      if (tempResult.value) {
1688        result.push(value)
1689        if(index === 0){
1690          directions.push('horizon')
1691        } else {
1692          directions.push('vertical')
1693        }
1694      }
1695      if (tempResult.reason) {
1696        reasons.push(tempResult.reason)
1697      }
1698    }
1699  })
1700  if (directions.length === 2 && directions[0] === directions[1]) {
1701    reasons.push(function(k, v) {
1702      return 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect.'
1703    })
1704  }
1705  return {
1706    value: result.length > 0 ? result.join(' ') : null,
1707    reason: reasons.length > 0 ?
1708      function(k, v) {
1709        return reasons.map(function(res) {
1710          if (typeof res === 'function') {
1711            return res(k, v)
1712          }
1713        }).join('\n')
1714      }: null
1715  }
1716}
1717
1718function checkDirection(v) {
1719  const scaleXReg = /^(left|right)$/
1720  const scaleYReg = /^(top|bottom)$/
1721  if (scaleXReg.test(v)) {
1722    return 'horizon'
1723  }
1724  if (scaleYReg.test(v)) {
1725    return 'vertical'
1726  }
1727  return null
1728}
1729
1730var MYLOCATION_VALIDATOR = function MYLOCATION_VALIDATOR(v) {
1731  v = (v || "").toString().trim()
1732  let values = v.match(/\((.+?)\)/g) || []
1733  let replaceValue = null
1734  if (values.length) {
1735    for (let index = 0; index < values.length; index++) {
1736      replaceValue = values[index].replace(/\s*/g, "")
1737      v = v.replace(values[index], replaceValue);
1738    }
1739  }
1740  let realValues = v.split(/\s+/)
1741  let resultValues = []
1742  let valuesOrder = []
1743  let reason = null
1744  if (realValues && realValues.length <= 3) {
1745    realValues.forEach(function(realValue) {
1746      if (typeof COLOR_VALIDATOR(realValue).value == 'string') {
1747        resultValues.push(COLOR_VALIDATOR(realValue).value)
1748        valuesOrder.push(0)
1749      } else if (typeof URL_VALIDATOR(realValue).value == 'string') {
1750        resultValues.push(URL_VALIDATOR(realValue).value)
1751        valuesOrder.push(1)
1752      } else {
1753        reason = 'value'
1754      }
1755    })
1756    let n = -1
1757    valuesOrder.forEach(function(order) {
1758      if (order >= n) {
1759        n = order
1760      } else {
1761        if (!reason) {
1762          reason = 'order'
1763        }
1764      }
1765    })
1766    if (reason) {
1767      return {
1768        value : null,
1769        reason: function(k, v) {
1770          return reason == 'value' ?
1771            'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute does not meet the inspection standards for the color or url.' :
1772            'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute must be set in order(color color url).'
1773        }
1774      }
1775    }
1776    return {
1777      value: resultValues.join(" ")
1778    }
1779  }
1780  return {
1781    value: null,
1782    reason: function(k, v) {
1783      return 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is invalid.'
1784    }
1785  }
1786}
1787
1788var TRANSFORM_ORIGIN_VALIDATOR = function TRANSFORM_ORIGIN_VALIDATOR(v) {
1789  v = (v || "").toString().trim()
1790  let values = v.split(/\s+/)
1791  const positionReg = /left|right|top|bottom|center/g
1792  if (values.length == 1) {
1793    if (/^(left|right|top|bottom|center)$/.test(v)) {
1794      return { value: v }
1795    } else {
1796      return PERCENTAGE_LENGTH_VALIDATOR(v);
1797    }
1798  }
1799  if (values.length == 2) {
1800    if (!positionReg.test(v)) {
1801      return SHORTHAND_VALIDATOR(v, PERCENTAGE_LENGTH_VALIDATOR)
1802    } else {
1803      return CHECK_TRANSFORM_ORIGIN(values)
1804    }
1805  }
1806  return {
1807    value: null,
1808    reason: function (k, v) {
1809      return 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is invalid. such as left 100px or 50% bottom.'
1810    }
1811  }
1812}
1813
1814var CHECK_TRANSFORM_ORIGIN = function CHECK_TRANSFORM_ORIGIN(values) {
1815  let result = []
1816  let reasons = []
1817  let directions = []
1818  values.forEach(function (value, index) {
1819    if (/^(left|right|top|bottom|center)$/.test(value)) {
1820      result.push(value)
1821      directions.push(checkDirection(value))
1822    } else {
1823      let tempResult = PERCENTAGE_LENGTH_VALIDATOR(value)
1824      if (tempResult.value) {
1825        result.push(value)
1826        if (index === 0) {
1827          directions.push('horizon')
1828        } else {
1829          directions.push('vertical')
1830        }
1831      }
1832      if (tempResult.reason) {
1833        reasons.push(tempResult.reason)
1834      }
1835    }
1836  })
1837  if (directions.length != 2 || directions.length === 2 && (directions[0] === 'vertical' || directions[1] === 'horizon')) {
1838    reasons.push(function (k, v) {
1839      return 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect.'
1840    })
1841  }
1842  return {
1843    value: result.length > 0 ? result.join(' ') : null,
1844    reason: reasons.length > 0 ?
1845      function (k, v) {
1846        return reasons.map(function (res) {
1847          if (typeof res === 'function') {
1848            return res(k, v)
1849          }
1850        }).join('\n')
1851      } : null
1852  }
1853}
1854
1855var GRID_VALIDATOR = function GRID_VALIDATOR(v) {
1856  v = (v || '').toString().trim()
1857  if (v == 'auto' || v == 'auto-fill') {
1858    return { value: v }
1859  } else {
1860    return LENGTH(v, SUPPORT_CSS_GRID_UNIT)
1861  }
1862}
1863
1864var GRID_TEMPLATE_VALIDATOR = function GRID_TEMPLATE_VALIDATOR(v) {
1865  v = (v || '').toString().trim()
1866  if (v.match(/^repeat/)) {
1867    let str = []
1868    if (v.match(/auto-fill/)) {
1869      let match = v.match(/^repeat\((.+),(.+)\)/)
1870      str.push(match[1].trim(), match[2].trim())
1871      return GRID_TEMPLATE_VALIDATOR(str.join(' '))
1872    } else {
1873      let match = v.match(/^repeat\((\d+),(.+)\)/)
1874      if (match[1] && match[2]) {
1875        let n = match[1]
1876          while (n > 0) {
1877            str.push(match[2].trim())
1878            n--
1879          }
1880        return GRID_TEMPLATE_VALIDATOR(str.join(' '))
1881      }
1882      else {
1883        return {
1884          value: null,
1885          reason: function reason(k, v, result) {
1886            return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + v + '`.'
1887          }
1888        }
1889      }
1890    }
1891  }
1892  else {
1893    let value = []
1894    let reason = []
1895    let results = v.split(/\s+/).map(GRID_VALIDATOR)
1896    for (let i = 0; i < results.length; ++i) {
1897      let res = results[i]
1898      if (!res.value) {
1899        value = null
1900        reason = res.reason
1901        break
1902      }
1903      value.push(res.value)
1904      if (res.reason) {
1905        reason.push(res.reason)
1906      }
1907    }
1908
1909    if (!value) {
1910      return {
1911        value: value,
1912        reason: reason
1913      }
1914    } else {
1915      return {
1916        value: value.join(' '),
1917        reason: reason.length > 0 ? function(k, v, result) {
1918          return reason.map(function (res) {
1919            if (typeof res === 'function') {
1920              return res(k, v, result)
1921            }
1922          }).join('\n')
1923        } : null
1924      }
1925    }
1926  }
1927}
1928
1929var DATE_VALIDATOR = function DATE_VALIDATOR(v) {
1930  v = (v || '').toString().trim()
1931  if (DATE_REGEXP.test(v)) {
1932    return { value: v }
1933  } else {
1934    return {
1935      value: null,
1936      reason:function (k, v, result) {
1937        return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect.'
1938      }
1939    }
1940  }
1941}
1942
1943var FILTER_VALIDATOR = function FILTER_VALIDATOR(v) {
1944  v = (v || '').toString().trim().replace(/\s*/g, '')
1945  if (FILTER_REGEXP.test(v)) {
1946    return { value: v }
1947  } else {
1948    return {
1949      value: null,
1950      reason:function (k, v, result) {
1951        return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect.'
1952      }
1953    }
1954  }
1955}
1956
1957var FILTER_PERCENTAGE_VALIDATOR = function FILTER_PERCENTAGE_VALIDATOR(v) {
1958  v = (v || '').toString().trim().replace(/\s*,\s*/g, " ")
1959  if (FILTER_PERCENTAGE_REGEXP.test(v)) {
1960    return { value: v }
1961  }
1962  if (FILTER_STYLE_REGEXP.test(v)) {
1963    const values = v.trim().split(/\s+/)
1964    if(values[1] && values.length === 2){
1965      const blurStyleValidator = genEnumValidator(['small_light', 'medium_light', 'large_light', 'xlarge_light', 'small_dark', 'medium_dark', 'large_dark', 'xlarge_dark'])
1966      const blurStyleResult = blurStyleValidator(values[1])
1967      if(util.isValidValue(blurStyleResult.value)){
1968        return { value: v }
1969      }
1970      let reasonMaps = [];
1971      let length = 0;
1972      let check = checkReason(blurStyleResult, 'window-filter', values[1], length)
1973      if(check.realReason !== null) {
1974        reasonMaps.push(check.realReason)
1975      }
1976      return {
1977        value: check.length < 2 ? JSON.stringify(blurStyleResult.value) : null,
1978        reason: function(k, v) {
1979          return 'ERROR: ' + reasonMaps
1980        }
1981      }
1982    }
1983  }
1984  return {
1985    value: null,
1986    reason:function (k, v, result) {
1987      return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect.'
1988    }
1989  }
1990}
1991
1992var BORDER_IMAGE_VALIDATOR = function BORDER_IMAGE_VALIDATOR(v) {
1993  var regexp = /(repeating-linear|linear).*?(?=\s*(repeating|linear)|$)/g;
1994  if (regexp.test(v)) {
1995    return BORDER_IMAGE_GRADIENT_VALIDATOR(v);
1996  } else {
1997    return BORDER_IMAGE_URL_VALIDATOR(v);
1998  }
1999}
2000
2001var BORDER_IMAGE_URL_VALIDATOR = function BORDER_IMAGE_URL_VALIDATOR(v) {
2002  let base = {
2003    values: []
2004  };
2005  let value = {
2006    url: "",
2007    slice: [],
2008    width: [],
2009    outset: [],
2010    repeat: ""
2011  };
2012  var URL_REGEXP = /^url\(\s*['"]?\s*([^()]+?)\s*['"]?\s*\)(.*)(stretch|round|repeat)$/;
2013  let result = URL_REGEXP.exec(v);
2014  value.url = result[1];
2015  let num = result[2].split(/\//);
2016  switch (num.length) {
2017    case 1:
2018    value.slice = BORDER_IMAGE_SPLIT(num[0]);
2019    break;
2020    case 2:
2021    value.slice = BORDER_IMAGE_SPLIT(num[0]);
2022    value.width = BORDER_IMAGE_SPLIT(num[1]);
2023    break;
2024    case 3:
2025    value.slice = BORDER_IMAGE_SPLIT(num[0]);
2026    value.width = BORDER_IMAGE_SPLIT(num[1]);
2027    value.outset = BORDER_IMAGE_SPLIT(num[2]);
2028    break;
2029  }
2030  value.repeat = result[3];
2031  base.values.push(value);
2032  return {
2033    value: JSON.stringify(base)
2034  };
2035}
2036
2037var BORDER_IMAGE_SPLIT = function BORDER_IMAGE_SPLIT(v) {
2038  const NUM_REGEXP = SHORTHAND_LENGTH_VALIDATOR(v);
2039  let result = [];
2040  const value = NUM_REGEXP.value.split(/\s/);
2041  value.forEach(element => {
2042    result.push(element);
2043  });
2044  return result;
2045}
2046
2047var BORDER_IMAGE_GRADIENT_VALIDATOR = function BORDER_IMAGE_GRADIENT_VALIDATOR(v) {
2048  v = (v || "").toString().trim()
2049  var BORDER_IMAGE_GRADIENT_ITEM_REGEXP = /^([0-9a-zA-Z-]+)\((.*)\)\s(.*)/;
2050  let base = {
2051    values: []
2052  }
2053  let valueMatch = v.match(BORDER_IMAGE_GRADIENT_ITEM_REGEXP)
2054  if (valueMatch) {
2055    const gradientStr = valueMatch[1].toString() + '(' + valueMatch[2].toString() + ')';
2056    const gradient = LINEAR_GRADIENT_VALIDATOR(gradientStr);
2057    let value = {};
2058    if (util.isValidValue(gradient.value)) {
2059      value = JSON.parse(gradient.value)
2060    }
2061    value.slice = BORDER_IMAGE_SPLIT(valueMatch[3]);
2062    base.values.push(value);
2063    return {
2064      value: JSON.stringify(base),
2065      reason: gradient.reason
2066    }
2067  }
2068  return {
2069    value: null,
2070    reason: function(k, v) {
2071      return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k)
2072        + '` attribute is incorrect.'
2073    }
2074  }
2075}
2076
2077var RICH_PROP_NAME_GROUPS = {
2078  boxModel: {
2079    width: PERCENTAGE_LENGTH_VALIDATOR,
2080    height: PERCENTAGE_LENGTH_VALIDATOR,
2081    overflow: genEnumValidator(['auto', 'hidden','scroll','visible']),
2082    padding: SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR,
2083    paddingLeft: PERCENTAGE_LENGTH_VALIDATOR,
2084    paddingRight: PERCENTAGE_LENGTH_VALIDATOR,
2085    paddingTop: PERCENTAGE_LENGTH_VALIDATOR,
2086    paddingBottom: PERCENTAGE_LENGTH_VALIDATOR,
2087    paddingStart: PERCENTAGE_LENGTH_VALIDATOR,
2088    paddingEnd: PERCENTAGE_LENGTH_VALIDATOR,
2089    margin: SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR,
2090    marginLeft: PERCENTAGE_LENGTH_VALIDATOR,
2091    marginRight: PERCENTAGE_LENGTH_VALIDATOR,
2092    marginTop: PERCENTAGE_LENGTH_VALIDATOR,
2093    marginBottom: PERCENTAGE_LENGTH_VALIDATOR,
2094    marginStart: PERCENTAGE_LENGTH_VALIDATOR,
2095    marginEnd: PERCENTAGE_LENGTH_VALIDATOR,
2096    placeholderColor: COLOR_VALIDATOR,
2097    selectedColor: COLOR_VALIDATOR,
2098    caretColor: COLOR_VALIDATOR,
2099    strokeWidth: LENGTH_VALIDATOR,
2100    progressColor: COLOR_VALIDATOR,
2101    slideWidth: LENGTH_VALIDATOR,
2102    slideMargin: LENGTH_VALIDATOR,
2103    resizeMode: genEnumValidator(['cover', 'contain', 'stretch', 'center']),
2104    columns: NUMBER_VALIDATOR,
2105    columnSpan: NUMBER_VALIDATOR,
2106    maskColor: COLOR_VALIDATOR,
2107    mylocation: MYLOCATION_VALIDATOR,
2108    mylocationFillColor: COLOR_VALIDATOR,
2109    mylocationStrokeColor: COLOR_VALIDATOR,
2110    mylocationIconPath: URL_VALIDATOR,
2111    displayIndex: NUMBER_VALIDATOR,
2112    aspectRatio: NUMBER_VALIDATOR,
2113    minWidth: PERCENTAGE_LENGTH_VALIDATOR,
2114    minHeight: PERCENTAGE_LENGTH_VALIDATOR,
2115    maxWidth: PERCENTAGE_LENGTH_VALIDATOR,
2116    maxHeight: PERCENTAGE_LENGTH_VALIDATOR,
2117    flexWeight: NUMBER_VALIDATOR,
2118    boxShadow: BOX_SHADOW_VALIDATOR,
2119    boxShadowH: LENGTH_VALIDATOR,
2120    boxShadowV: LENGTH_VALIDATOR,
2121    boxShadowBlur: LENGTH_VALIDATOR,
2122    boxShadowSpread: LENGTH_VALIDATOR,
2123    boxShadowColor: COLOR_VALIDATOR,
2124    filter: FILTER_VALIDATOR,
2125    backdropFilter: FILTER_VALIDATOR,
2126    windowFilter: FILTER_PERCENTAGE_VALIDATOR,
2127    transitionEffect: genEnumValidator(['unfold', 'none'])
2128  },
2129  div: {
2130    gridTemplateColumns: GRID_TEMPLATE_VALIDATOR,
2131    gridTemplateRows: GRID_TEMPLATE_VALIDATOR,
2132    gridGap: LENGTH_VALIDATOR,
2133    gridColumnsGap: LENGTH_VALIDATOR,
2134    gridRowsGap: LENGTH_VALIDATOR,
2135    gridRowStart: NUMBER_VALIDATOR,
2136    gridRowEnd: NUMBER_VALIDATOR,
2137    gridColumnStart: NUMBER_VALIDATOR,
2138    gridColumnEnd: NUMBER_VALIDATOR,
2139    gridAutoFlow: genEnumValidator(['row', 'column'])
2140  },
2141  border: {
2142    border: BORDER_VALIDATOR,
2143    borderWidth: SHORTHAND_LENGTH_VALIDATOR,
2144    borderLeftWidth: LENGTH_VALIDATOR,
2145    borderTopWidth: LENGTH_VALIDATOR,
2146    borderRightWidth: LENGTH_VALIDATOR,
2147    borderBottomWidth: LENGTH_VALIDATOR,
2148    borderColor: SHORTHAND_COLOR_VALIDATOR,
2149    borderLeftColor: COLOR_VALIDATOR,
2150    borderTopColor: COLOR_VALIDATOR,
2151    borderRightColor: COLOR_VALIDATOR,
2152    borderBottomColor: COLOR_VALIDATOR,
2153    borderStyle: SHORTHAND_STYLE_VALIDATOR,
2154    borderTopStyle: STYLE_VALIDATOR,
2155    borderRightStyle: STYLE_VALIDATOR,
2156    borderBottomStyle: STYLE_VALIDATOR,
2157    borderLeftStyle: STYLE_VALIDATOR,
2158    borderRadius: SHORTHAND_LENGTH_VALIDATOR,
2159    borderBottomLeftRadius: LENGTH_VALIDATOR,
2160    borderBottomRightRadius: LENGTH_VALIDATOR,
2161    borderTopLeftRadius: LENGTH_VALIDATOR,
2162    borderTopRightRadius: LENGTH_VALIDATOR,
2163    borderLeft: BORDER_VALIDATOR,
2164    borderRight: BORDER_VALIDATOR,
2165    borderTop: BORDER_VALIDATOR,
2166    borderBottom: BORDER_VALIDATOR,
2167    borderImage: BORDER_IMAGE_VALIDATOR,
2168    borderImageSource: URL_VALIDATOR,
2169    borderImageSlice: SHORTHAND_LENGTH_VALIDATOR,
2170    borderImageWidth: SHORTHAND_LENGTH_VALIDATOR,
2171    borderImageOutset: SHORTHAND_LENGTH_VALIDATOR,
2172    borderImageRepeat: genEnumValidator(['stretch', 'round', 'repeat'])
2173  },
2174  indicator: {
2175    indicatorSize: LENGTH_VALIDATOR,
2176    indicatorTop: PERCENTAGE_LENGTH_VALIDATOR,
2177    indicatorRight: PERCENTAGE_LENGTH_VALIDATOR,
2178    indicatorBottom: PERCENTAGE_LENGTH_VALIDATOR,
2179    indicatorLeft: PERCENTAGE_LENGTH_VALIDATOR,
2180    indicatorColor: COLOR_VALIDATOR,
2181    indicatorSelectedColor: COLOR_VALIDATOR
2182  },
2183  animation: {
2184    animationDuration: TIME_VALIDATOR,
2185    animationDelay: TIME_VALIDATOR,
2186    animationName: NAME_VALIDATOR,
2187    animationTimingFunction: TRANSITION_TIMING_FUNCTION_VALIDATOR,
2188    animationIterationCount: ITERATIONCOUNT_VALIDATOR,
2189    animationFillMode: genEnumValidator(['none', 'forwards', 'backwards', 'both']),
2190    animationPlayState: genEnumValidator(['running', 'paused']),
2191    animationDirection: genEnumValidator(['normal', 'reverse', 'alternate', 'alternate-reverse']),
2192    animation: ANIMATION_VALIDATOR,
2193  },
2194  flexbox: {
2195    flex: genEnumValidator(['none', 'auto', 'initial']),
2196    flexWrap: genEnumValidator(['nowrap', 'wrap']),
2197    flexGrow: NUMBER_VALIDATOR,
2198    flexShrink: NUMBER_VALIDATOR,
2199    flexBasis: LENGTH_VALIDATOR,
2200    flexDirection: genEnumValidator(['row', 'column', 'column-reverse', 'row-reverse']),
2201    justifyContent: genEnumValidator(['flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'space-evenly']),
2202    alignItems: genEnumValidator(['stretch', 'flex-start', 'flex-end', 'center', 'baseline']),
2203    alignContent: genEnumValidator(['stretch', 'flex-start', 'flex-end', 'center', 'space-between', 'space-around']),
2204    alignSelf: genEnumValidator(["auto", "flex-start", "flex-end", "center", "baseline", "stretch"])
2205  },
2206  position: {
2207    position: genEnumValidator(['relative', 'fixed', 'absolute']),
2208    top: PERCENTAGE_LENGTH_VALIDATOR,
2209    bottom: PERCENTAGE_LENGTH_VALIDATOR,
2210    left: PERCENTAGE_LENGTH_VALIDATOR,
2211    right: PERCENTAGE_LENGTH_VALIDATOR,
2212    zIndex: INTEGER_VALIDATOR
2213  },
2214  common: {
2215    opacity: NUMBER_VALIDATOR,
2216    background: BACKGROUND_VALIDATOR,
2217    backgroundColor: COLOR_VALIDATOR,
2218    backgroundImage: URL_VALIDATOR,
2219    backgroundRepeat: genEnumValidator(['repeat', 'no-repeat', 'repeat-x', 'repeat-y']),
2220    visibility: genEnumValidator(['visible', 'hidden']),
2221    objectFit: genEnumValidator(['cover', 'fill', 'contain', 'none', 'scale-down']),
2222    backgroundSize: BACKGROUND_SIZE_VALIDATOR,
2223    backgroundPosition: BACKGROUND_POSITION_VALIDATOR,
2224    display: genEnumValidator(['flex', 'none', 'grid']),
2225    imageFill: COLOR_VALIDATOR,
2226    maskImage: MASK_VALIDATOR,
2227    maskPosition: BACKGROUND_POSITION_VALIDATOR,
2228    maskSize: BACKGROUND_SIZE_VALIDATOR
2229  },
2230  text: {
2231    lines: INTEGER_VALIDATOR,
2232    color: COLOR_VALIDATOR,
2233    fontSize: LENGTH_VALIDATOR,
2234    fontStyle: genEnumValidator(['normal', 'italic']),
2235    fontFamily: ANYTHING_VALIDATOR,
2236    fontWeight: genEnumValidator(['normal', 'lighter', 'bold', 'bolder', "medium", "regular", '100', '200', '300', '400', '500', '600', '700', '800', '900']),
2237    textDecoration: genEnumValidator(['none', 'underline', 'line-through']),
2238    textAlign: genEnumValidator(['start', 'end', 'left', 'center', 'right']),
2239    textOverflow: genEnumValidator(['clip', 'ellipsis']),
2240    textIndent: TEXT_INDENT_VALIDATOR,
2241    lineHeight: LENGTH_VALIDATOR,
2242    letterSpacing: LENGTH_VALIDATOR,
2243    minLines: NUMBER_VALIDATOR,
2244    maxLines: ANYTHING_VALIDATOR,
2245    minFontSize: LENGTH_VALIDATOR,
2246    maxFontSize: LENGTH_VALIDATOR,
2247    fontSizeStep: LENGTH_VALIDATOR,
2248    preferFontSizes: ARRAY_LENGTH_VALIDATOR,
2249    adaptHeight: genEnumValidator(['true', 'false']),
2250    allowScale: genEnumValidator(['true', 'false']),
2251    fontVariant: ANYTHING_VALIDATOR,
2252    id: ANYTHING_VALIDATOR,
2253    x: PERCENTAGE_LENGTH_VALIDATOR,
2254    y: PERCENTAGE_LENGTH_VALIDATOR,
2255    dx: PERCENTAGE_LENGTH_VALIDATOR,
2256    dy: PERCENTAGE_LENGTH_VALIDATOR,
2257    rotate: NUMBER_VALIDATOR,
2258    fill: COLOR_VALIDATOR,
2259    fillOpacity: NUMBER_VALIDATOR,
2260    stroke: COLOR_VALIDATOR,
2261    strokeOpacity: NUMBER_VALIDATOR,
2262    strokeWidth: LENGTH_VALIDATOR,
2263    fontFeatureSettings: ANYTHING_VALIDATOR
2264  },
2265  calendar: {
2266    boundaryColOffset: LENGTH_VALIDATOR,
2267    boundaryRowOffset: LENGTH_VALIDATOR,
2268    colSpace: LENGTH_VALIDATOR,
2269    dailyFiveRowSpace: LENGTH_VALIDATOR,
2270    dayColor: COLOR_VALIDATOR,
2271    dayFontSize: LENGTH_VALIDATOR,
2272    dayHeight: LENGTH_VALIDATOR,
2273    dayWidth: LENGTH_VALIDATOR,
2274    focusedAreaBackgroundColor: COLOR_VALIDATOR,
2275    focusedAreaRadius: LENGTH_VALIDATOR,
2276    focusedDayColor: COLOR_VALIDATOR,
2277    focusedLunarColor: COLOR_VALIDATOR,
2278    gregorianCalendarHeight: LENGTH_VALIDATOR,
2279    lunarColor: COLOR_VALIDATOR,
2280    lunarDayFontSize: LENGTH_VALIDATOR,
2281    lunarDayYAxisOffset: LENGTH_VALIDATOR,
2282    lunarHeight: LENGTH_VALIDATOR,
2283    markLunarColor: COLOR_VALIDATOR,
2284    nonCurrentMonthDayColor: COLOR_VALIDATOR,
2285    nonCurrentMonthLunarColor: COLOR_VALIDATOR,
2286    nonCurrentMonthOffDayMarkColor: COLOR_VALIDATOR,
2287    nonCurrentMonthWorkDayMarkColor: COLOR_VALIDATOR,
2288    offDayMarkColor: COLOR_VALIDATOR,
2289    offDayMarkSize: LENGTH_VALIDATOR,
2290    scheduleMarkerRadius: LENGTH_VALIDATOR,
2291    scheduleMarkerXAxisOffset: LENGTH_VALIDATOR,
2292    scheduleMarkerYAxisOffset: LENGTH_VALIDATOR,
2293    underscoreLength: LENGTH_VALIDATOR,
2294    underscoreWidth: LENGTH_VALIDATOR,
2295    underscoreXAxisOffset: LENGTH_VALIDATOR,
2296    underscoreYAxisOffset: LENGTH_VALIDATOR,
2297    weekAndDayRowSpace: LENGTH_VALIDATOR,
2298    weekColor: COLOR_VALIDATOR,
2299    weekFontSize: LENGTH_VALIDATOR,
2300    weekHeight: LENGTH_VALIDATOR,
2301    weekWidth: LENGTH_VALIDATOR,
2302    weekendDayColor: COLOR_VALIDATOR,
2303    weekendLunarColor: COLOR_VALIDATOR,
2304    workDayMarkColor: COLOR_VALIDATOR,
2305    workDayMarkSize: LENGTH_VALIDATOR,
2306    workStateHorizontalMovingDistance: LENGTH_VALIDATOR,
2307    workStateVerticalMovingDistance: LENGTH_VALIDATOR,
2308    workStateWidth: LENGTH_VALIDATOR
2309  },
2310  rating: {
2311    starBackground: URL_VALIDATOR,
2312    starForeground: URL_VALIDATOR,
2313    starSecondary: URL_VALIDATOR,
2314    rtlFlip: genEnumValidator(['true', 'false'])
2315  },
2316  transition: {
2317    transitionProperty: TRANSITION_PROPERTY_VALIDATOR,
2318    transitionDuration: TRANSITION_INTERVAL_VALIDATOR,
2319    transitionDelay: TRANSITION_INTERVAL_VALIDATOR,
2320    transitionEnter: NAME_VALIDATOR,
2321    transitionExit: NAME_VALIDATOR,
2322    transitionDuration: TIME_VALIDATOR,
2323    transitionTimingFunction: TRANSITION_TIMING_FUNCTION_VALIDATOR
2324  },
2325  transform: {
2326    transform: TRANSFORM_VALIDATOR,
2327    transformOrigin: TRANSFORM_ORIGIN_VALIDATOR
2328  },
2329  customized: {
2330    itemSize: LENGTH_VALIDATOR,
2331    itemColor: COLOR_VALIDATOR,
2332    itemSelectedColor: COLOR_VALIDATOR,
2333    textColor: COLOR_VALIDATOR,
2334    timeColor: COLOR_VALIDATOR,
2335    textHighlightColor: COLOR_VALIDATOR
2336  },
2337  list: {
2338    itemExtent: PERCENTAGE_LENGTH_VALIDATOR,
2339    fadeColor: COLOR_VALIDATOR,
2340    dividerColor: COLOR_VALIDATOR,
2341    dividerHeight: LENGTH_VALIDATOR,
2342    dividerLength: LENGTH_VALIDATOR,
2343    dividerOrigin: LENGTH_VALIDATOR
2344  },
2345  progress: {
2346    secondaryColor: COLOR_VALIDATOR,
2347    scaleWidth: LENGTH_VALIDATOR,
2348    scaleNumber: NUMBER_VALIDATOR,
2349    startAngle: ANGLE_VALIDATOR,
2350    totalAngle: ANGLE_VALIDATOR,
2351    centerX: LENGTH_VALIDATOR,
2352    centerY: LENGTH_VALIDATOR,
2353    radius: LENGTH_VALIDATOR,
2354    direction: genEnumValidator(['start-to-end', 'end-to-start']),
2355    sections: NAME_VALIDATOR,
2356    colors: ARRAY_COLOR_VALIDATOR,
2357    weights: ARRAY_NUMBER_VALIDATOR
2358  },
2359  navigation: {
2360    titleColor: COLOR_VALIDATOR,
2361    subtitleColor: COLOR_VALIDATOR
2362  },
2363  button: {
2364    iconWidth: LENGTH_VALIDATOR,
2365    iconHeight: LENGTH_VALIDATOR
2366  },
2367  switch: {
2368    textonColor: COLOR_VALIDATOR,
2369    textoffColor: COLOR_VALIDATOR,
2370    textPadding: LENGTH_VALIDATOR
2371  },
2372  share: {
2373    sharedTransitionEffect: genEnumValidator(['exchange', 'static']),
2374    sharedTransitionName: NAME_VALIDATOR,
2375    sharedTransitionTimingFunction: TRANSITION_TIMING_FUNCTION_VALIDATOR
2376  },
2377  image: {
2378    matchTextDirection: genEnumValidator(['false', 'true']),
2379    fitOriginalSize: genEnumValidator(['false', 'true']),
2380  },
2381  divider: {
2382    lineCap: genEnumValidator(['butt', 'square', 'round'])
2383  },
2384  picker: {
2385    columnHeight: LENGTH_VALIDATOR
2386  },
2387  pickerView: {
2388    selectedFontSize: LENGTH_VALIDATOR,
2389    selectedFontFamily: ANYTHING_VALIDATOR,
2390    focusColor: COLOR_VALIDATOR,
2391    focusFontSize: LENGTH_VALIDATOR,
2392    focusFontFamily: ANYTHING_VALIDATOR,
2393    disappearFontSize: LENGTH_VALIDATOR,
2394    disappearColor: COLOR_VALIDATOR
2395  },
2396  slider: {
2397    blockColor: COLOR_VALIDATOR,
2398  },
2399  badge: {
2400    badgeColor: COLOR_VALIDATOR,
2401    badgeSize: LENGTH_VALIDATOR
2402  },
2403  ellipse: {
2404    fill: COLOR_VALIDATOR,
2405    fillOpacity: NUMBER_VALIDATOR,
2406    fillRule: genEnumValidator(['nonzero', 'evenodd']),
2407    opacity: NUMBER_VALIDATOR,
2408    stroke: COLOR_VALIDATOR,
2409    strokeDasharray: ANYTHING_VALIDATOR,
2410    strokeDashoffset: LENGTH_VALIDATOR,
2411    strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']),
2412    strokeLinecap: genEnumValidator(['butt', 'round', 'square']),
2413    strokeMiterlimit: NUMBER_VALIDATOR,
2414    strokeOpacity: NUMBER_VALIDATOR,
2415    strokeWidth: LENGTH_VALIDATOR,
2416    transform: TRANSFORM_VALIDATOR,
2417    id: ANYTHING_VALIDATOR,
2418    cx: PERCENTAGE_LENGTH_VALIDATOR,
2419    cy: PERCENTAGE_LENGTH_VALIDATOR,
2420    rx: PERCENTAGE_LENGTH_VALIDATOR,
2421    ry: PERCENTAGE_LENGTH_VALIDATOR
2422  },
2423  rect: {
2424    id: ANYTHING_VALIDATOR,
2425    fill: COLOR_VALIDATOR,
2426    fillOpacity: NUMBER_VALIDATOR,
2427    fillRule: genEnumValidator(['nonzero', 'evenodd']),
2428    opacity: NUMBER_VALIDATOR,
2429    strokeDasharray: ANYTHING_VALIDATOR,
2430    strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']),
2431    strokeLinecap: genEnumValidator(['butt', 'round', 'square']),
2432    strokeMiterlimit: NUMBER_VALIDATOR,
2433    strokeOpacity: NUMBER_VALIDATOR,
2434    strokeWidth: LENGTH_VALIDATOR,
2435    transform: TRANSFORM_VALIDATOR,
2436    width: PERCENTAGE_LENGTH_VALIDATOR,
2437    height: PERCENTAGE_LENGTH_VALIDATOR,
2438    x: PERCENTAGE_LENGTH_VALIDATOR,
2439    y: PERCENTAGE_LENGTH_VALIDATOR,
2440    rx: PERCENTAGE_LENGTH_VALIDATOR,
2441    ry: PERCENTAGE_LENGTH_VALIDATOR,
2442    stroke: COLOR_VALIDATOR,
2443    strokeDashoffset: LENGTH_VALIDATOR
2444  },
2445  circle: {
2446    fill: COLOR_VALIDATOR,
2447    fillOpacity: NUMBER_VALIDATOR,
2448    fillRule: genEnumValidator(['nonzero', 'evenodd']),
2449    opacity: NUMBER_VALIDATOR,
2450    stroke: COLOR_VALIDATOR,
2451    strokeDasharray: ANYTHING_VALIDATOR,
2452    strokeDashoffset: LENGTH_VALIDATOR,
2453    strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']),
2454    strokeLinecap: genEnumValidator(['butt', 'round', 'square']),
2455    strokeMiterlimit: NUMBER_VALIDATOR,
2456    strokeOpacity: NUMBER_VALIDATOR,
2457    strokeWidth: LENGTH_VALIDATOR,
2458    transform: TRANSFORM_VALIDATOR,
2459    id: ANYTHING_VALIDATOR,
2460    cx: PERCENTAGE_LENGTH_VALIDATOR,
2461    cy: PERCENTAGE_LENGTH_VALIDATOR,
2462    r: PERCENTAGE_LENGTH_VALIDATOR
2463  },
2464  path: {
2465    fillOpacity: NUMBER_VALIDATOR,
2466    fillRule: genEnumValidator(['nonzero', 'evenodd']),
2467    opacity: NUMBER_VALIDATOR,
2468    strokeDashoffset: LENGTH_VALIDATOR,
2469    strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']),
2470    strokeLinecap: genEnumValidator(['butt', 'round', 'square']),
2471    strokeMiterlimit: NUMBER_VALIDATOR,
2472    strokeOpacity: NUMBER_VALIDATOR,
2473    strokeWidth: LENGTH_VALIDATOR,
2474    transform: TRANSFORM_VALIDATOR,
2475    id: ANYTHING_VALIDATOR,
2476    d: ANYTHING_VALIDATOR,
2477    fill: COLOR_VALIDATOR,
2478    strokeDasharray: ANYTHING_VALIDATOR,
2479    stroke: COLOR_VALIDATOR
2480  },
2481  svg: {
2482    fill: COLOR_VALIDATOR,
2483    fillOpacity: NUMBER_VALIDATOR,
2484    fillRule: genEnumValidator(['nonzero', 'evenodd']),
2485    opacity: NUMBER_VALIDATOR,
2486    stroke: COLOR_VALIDATOR,
2487    strokeDasharray: ANYTHING_VALIDATOR,
2488    strokeDashoffset: LENGTH_VALIDATOR,
2489    strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']),
2490    strokeLinecap: genEnumValidator(['butt', 'round', 'square']),
2491    strokeMiterlimit: NUMBER_VALIDATOR,
2492    strokeOpacity: NUMBER_VALIDATOR,
2493    strokeWidth: LENGTH_VALIDATOR,
2494    transform: TRANSFORM_VALIDATOR,
2495    id: ANYTHING_VALIDATOR,
2496    width: PERCENTAGE_LENGTH_VALIDATOR,
2497    height: PERCENTAGE_LENGTH_VALIDATOR,
2498    x: PERCENTAGE_LENGTH_VALIDATOR,
2499    y: PERCENTAGE_LENGTH_VALIDATOR,
2500    viewbox: ANYTHING_VALIDATOR
2501  },
2502  polygon: {
2503    fill: COLOR_VALIDATOR,
2504    fillOpacity: NUMBER_VALIDATOR,
2505    opacity: NUMBER_VALIDATOR,
2506    stroke: COLOR_VALIDATOR,
2507    strokeDasharray: ANYTHING_VALIDATOR,
2508    strokeDashoffset: LENGTH_VALIDATOR,
2509    strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']),
2510    strokeLinecap: genEnumValidator(['butt', 'round', 'square']),
2511    strokeMiterlimit: NUMBER_VALIDATOR,
2512    strokeOpacity: NUMBER_VALIDATOR,
2513    strokeWidth: LENGTH_VALIDATOR,
2514    transform: TRANSFORM_VALIDATOR,
2515    id: ANYTHING_VALIDATOR,
2516    points: ANYTHING_VALIDATOR,
2517    fillRule: genEnumValidator(['nonzero', 'evenodd'])
2518  },
2519  polyline: {
2520    fill: COLOR_VALIDATOR,
2521    fillOpacity: NUMBER_VALIDATOR,
2522    opacity: NUMBER_VALIDATOR,
2523    stroke: COLOR_VALIDATOR,
2524    strokeDasharray: ANYTHING_VALIDATOR,
2525    strokeDashoffset: LENGTH_VALIDATOR,
2526    strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']),
2527    strokeLinecap: genEnumValidator(['butt', 'round', 'square']),
2528    strokeMiterlimit: NUMBER_VALIDATOR,
2529    strokeOpacity: NUMBER_VALIDATOR,
2530    strokeWidth: LENGTH_VALIDATOR,
2531    transform: TRANSFORM_VALIDATOR,
2532    id: ANYTHING_VALIDATOR,
2533    points: ANYTHING_VALIDATOR,
2534    fillRule: genEnumValidator(['nonzero', 'evenodd'])
2535  },
2536  tspan: {
2537    id: ANYTHING_VALIDATOR,
2538    x: PERCENTAGE_LENGTH_VALIDATOR,
2539    y: PERCENTAGE_LENGTH_VALIDATOR,
2540    dx: PERCENTAGE_LENGTH_VALIDATOR,
2541    dy: PERCENTAGE_LENGTH_VALIDATOR,
2542    rotate: NUMBER_VALIDATOR,
2543    fontSize: LENGTH_VALIDATOR,
2544    fill: COLOR_VALIDATOR,
2545    fillOpacity: NUMBER_VALIDATOR,
2546    stroke: COLOR_VALIDATOR,
2547    strokeOpacity: NUMBER_VALIDATOR,
2548    strokeWidth: LENGTH_VALIDATOR
2549  },
2550  textPath: {
2551    id: ANYTHING_VALIDATOR,
2552    path: ANYTHING_VALIDATOR,
2553    startOffset: PERCENTAGE_LENGTH_VALIDATOR,
2554    fontSize: LENGTH_VALIDATOR,
2555    fill: COLOR_VALIDATOR,
2556    fillOpacity: NUMBER_VALIDATOR,
2557    stroke: COLOR_VALIDATOR,
2558    strokeOpacity: NUMBER_VALIDATOR,
2559    strokeWidth: LENGTH_VALIDATOR
2560  },
2561  animate: {
2562    id: ANYTHING_VALIDATOR,
2563    attributeName: ANYTHING_VALIDATOR,
2564    begin: ANYTHING_VALIDATOR,
2565    dur: ANYTHING_VALIDATOR,
2566    end: ANYTHING_VALIDATOR,
2567    repeatCount: ANYTHING_VALIDATOR,
2568    fill: genEnumValidator(['freeze', 'remove']),
2569    calcMode: genEnumValidator(['discrete', 'linear', 'paced', 'spline']),
2570    keyTimes: ANYTHING_VALIDATOR,
2571    keySplines: ANYTHING_VALIDATOR,
2572    from: ANYTHING_VALIDATOR,
2573    to: ANYTHING_VALIDATOR,
2574    values: ANYTHING_VALIDATOR
2575  },
2576  animateMotion: {
2577    id: ANYTHING_VALIDATOR,
2578    attributeName: ANYTHING_VALIDATOR,
2579    begin: ANYTHING_VALIDATOR,
2580    dur: ANYTHING_VALIDATOR,
2581    end: ANYTHING_VALIDATOR,
2582    repeatCount: ANYTHING_VALIDATOR,
2583    fill: genEnumValidator(['freeze', 'remove']),
2584    calcMode: genEnumValidator(['discrete', 'linear', 'paced', 'spline']),
2585    keyTimes: ANYTHING_VALIDATOR,
2586    keySplines: ANYTHING_VALIDATOR,
2587    from: ANYTHING_VALIDATOR,
2588    to: ANYTHING_VALIDATOR,
2589    keyPoints: ANYTHING_VALIDATOR,
2590    path: ANYTHING_VALIDATOR,
2591    rotate: ANYTHING_VALIDATOR
2592  },
2593  animateTransform: {
2594    id: ANYTHING_VALIDATOR,
2595    attributeName: ANYTHING_VALIDATOR,
2596    begin: ANYTHING_VALIDATOR,
2597    dur: ANYTHING_VALIDATOR,
2598    end: ANYTHING_VALIDATOR,
2599    repeatCount: ANYTHING_VALIDATOR,
2600    fill: genEnumValidator(['freeze', 'remove']),
2601    calcMode: genEnumValidator(['discrete', 'linear', 'paced', 'spline']),
2602    from: ANYTHING_VALIDATOR,
2603    to: ANYTHING_VALIDATOR,
2604    type: genEnumValidator(['translate', 'scale', 'skewX', 'skewY'])
2605  },
2606  line: {
2607    fill: COLOR_VALIDATOR,
2608    fillOpacity: NUMBER_VALIDATOR,
2609    opacity: NUMBER_VALIDATOR,
2610    stroke: COLOR_VALIDATOR,
2611    strokeDasharray: ANYTHING_VALIDATOR,
2612    strokeDashoffset: LENGTH_VALIDATOR,
2613    strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']),
2614    strokeLinecap: genEnumValidator(['butt', 'round', 'square']),
2615    strokeMiterlimit: NUMBER_VALIDATOR,
2616    strokeOpacity: NUMBER_VALIDATOR,
2617    strokeWidth: LENGTH_VALIDATOR,
2618    fillRule: genEnumValidator(['nonzero', 'evenodd']),
2619    transform: TRANSFORM_VALIDATOR,
2620    id: ANYTHING_VALIDATOR,
2621    x1: PERCENTAGE_LENGTH_VALIDATOR,
2622    y1: PERCENTAGE_LENGTH_VALIDATOR,
2623    x2: PERCENTAGE_LENGTH_VALIDATOR,
2624    y2: PERCENTAGE_LENGTH_VALIDATOR
2625  }
2626}
2627
2628var LITE_PROP_NAME_GROUPS = {
2629  boxModel: {
2630    width: PERCENTAGE_LENGTH_VALIDATOR,
2631    height: PERCENTAGE_LENGTH_VALIDATOR,
2632    padding: SHORTHAND_LENGTH_VALIDATOR,
2633    paddingLeft: LENGTH_VALIDATOR,
2634    paddingRight: LENGTH_VALIDATOR,
2635    paddingTop: LENGTH_VALIDATOR,
2636    paddingBottom: LENGTH_VALIDATOR,
2637    margin:SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR,
2638    marginLeft: PERCENTAGE_LENGTH_VALIDATOR,
2639    marginRight: PERCENTAGE_LENGTH_VALIDATOR,
2640    marginTop: PERCENTAGE_LENGTH_VALIDATOR,
2641    marginBottom: PERCENTAGE_LENGTH_VALIDATOR,
2642    strokeWidth: LENGTH_VALIDATOR,
2643  },
2644  border:{
2645    borderWidth: SHORTHAND_LENGTH_VALIDATOR,
2646    borderColor: SHORTHAND_COLOR_VALIDATOR,
2647    borderRadius: LENGTH_VALIDATOR,
2648  },
2649  animation:{
2650    animationDuration: TIME_VALIDATOR,
2651    animationDelay: TIME_VALIDATOR,
2652    animationName: NAME_VALIDATOR,
2653    animationTimingFunction: genEnumValidator(['linear', 'ease-in', 'ease-out', 'ease-in-out']),
2654    animationIterationCount: ITERATIONCOUNT_VALIDATOR,
2655    animationFillMode: genEnumValidator(['none', 'forwards'])
2656  },
2657  flexbox: {
2658    flexDirection: genEnumValidator(['row', 'column']),
2659    flexWrap: genEnumValidator(['nowrap', 'wrap']),
2660    justifyContent: genEnumValidator(['flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'space-evenly']),
2661    alignItems: genEnumValidator(['stretch', 'flex-start', 'flex-end', 'center']),
2662  },
2663  position: {
2664    top: PERCENTAGE_LENGTH_VALIDATOR,
2665    left: PERCENTAGE_LENGTH_VALIDATOR,
2666  },
2667  common: {
2668    opacity: NUMBER_VALIDATOR,
2669    backgroundColor: COLOR_VALIDATOR,
2670    backgroundImage: URL_VALIDATOR,
2671    display: genEnumValidator(['flex', 'none']),
2672  },
2673  text: {
2674    color: COLOR_VALIDATOR,
2675    fontSize: LENGTH_VALIDATOR,
2676    fontFamily: genEnumValidator(['HYQiHei-65S']),
2677    letterSpacing: LENGTH_VALIDATOR,
2678    textAlign: genEnumValidator(['left', 'center', 'right']),
2679    textOverflow: genEnumValidator(['clip', 'ellipsis']),
2680  },
2681  slider: {
2682    selectedColor: COLOR_VALIDATOR,
2683    selectedFontSize: LENGTH_VALIDATOR,
2684    selectedFontFamily: genEnumValidator(['HYQiHei-65S']),
2685    blockColor: COLOR_VALIDATOR,
2686  },
2687  transform: {
2688    transform: TRANSFORM_VALIDATOR,
2689  },
2690  progress: {
2691    centerX: LENGTH_VALIDATOR,
2692    centerY: LENGTH_VALIDATOR,
2693    radius: LENGTH_VALIDATOR,
2694    startAngle: ANGLE_VALIDATOR,
2695    totalAngle: ANGLE_VALIDATOR
2696  }
2697}
2698
2699var CARD_PROP_NAME_GROUPS = {
2700  boxModel: {
2701    width: PERCENTAGE_LENGTH_VALIDATOR,
2702    height: PERCENTAGE_LENGTH_VALIDATOR,
2703    overflow: genEnumValidator(['auto', 'hidden','scroll','visible']),
2704    padding: SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR,
2705    paddingLeft: PERCENTAGE_LENGTH_VALIDATOR,
2706    paddingRight: PERCENTAGE_LENGTH_VALIDATOR,
2707    paddingTop: PERCENTAGE_LENGTH_VALIDATOR,
2708    paddingBottom: PERCENTAGE_LENGTH_VALIDATOR,
2709    paddingStart: PERCENTAGE_LENGTH_VALIDATOR,
2710    paddingEnd: PERCENTAGE_LENGTH_VALIDATOR,
2711    margin: SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR,
2712    marginLeft: PERCENTAGE_LENGTH_VALIDATOR,
2713    marginRight: PERCENTAGE_LENGTH_VALIDATOR,
2714    marginTop: PERCENTAGE_LENGTH_VALIDATOR,
2715    marginBottom: PERCENTAGE_LENGTH_VALIDATOR,
2716    marginStart: PERCENTAGE_LENGTH_VALIDATOR,
2717    marginEnd: PERCENTAGE_LENGTH_VALIDATOR,
2718    columns: NUMBER_VALIDATOR,
2719    displayIndex: NUMBER_VALIDATOR,
2720    aspectRatio: NUMBER_VALIDATOR,
2721    minWidth: PERCENTAGE_LENGTH_VALIDATOR,
2722    minHeight: PERCENTAGE_LENGTH_VALIDATOR,
2723    maxWidth: PERCENTAGE_LENGTH_VALIDATOR,
2724    maxHeight: PERCENTAGE_LENGTH_VALIDATOR,
2725    flexWeight: NUMBER_VALIDATOR,
2726    boxShadow: BOX_SHADOW_VALIDATOR,
2727    boxShadowH: LENGTH_VALIDATOR,
2728    boxShadowV: LENGTH_VALIDATOR,
2729    boxShadowBlur: LENGTH_VALIDATOR,
2730    boxShadowSpread: LENGTH_VALIDATOR,
2731    boxShadowColor: COLOR_VALIDATOR,
2732    filter: FILTER_VALIDATOR,
2733    backdropFilter: FILTER_VALIDATOR,
2734    windowFilter: FILTER_PERCENTAGE_VALIDATOR
2735  },
2736  div: {
2737    gridTemplateColumns: GRID_TEMPLATE_VALIDATOR,
2738    gridTemplateRows: GRID_TEMPLATE_VALIDATOR,
2739    gridGap: LENGTH_VALIDATOR,
2740    gridColumnsGap: LENGTH_VALIDATOR,
2741    gridRowsGap: LENGTH_VALIDATOR,
2742    gridRowStart: NUMBER_VALIDATOR,
2743    gridRowEnd: NUMBER_VALIDATOR,
2744    gridColumnStart: NUMBER_VALIDATOR,
2745    gridColumnEnd: NUMBER_VALIDATOR
2746  },
2747  border: {
2748    border: BORDER_VALIDATOR,
2749    borderWidth: SHORTHAND_LENGTH_VALIDATOR,
2750    borderLeftWidth: LENGTH_VALIDATOR,
2751    borderTopWidth: LENGTH_VALIDATOR,
2752    borderRightWidth: LENGTH_VALIDATOR,
2753    borderBottomWidth: LENGTH_VALIDATOR,
2754    borderColor: SHORTHAND_COLOR_VALIDATOR,
2755    borderLeftColor: COLOR_VALIDATOR,
2756    borderTopColor: COLOR_VALIDATOR,
2757    borderRightColor: COLOR_VALIDATOR,
2758    borderBottomColor: COLOR_VALIDATOR,
2759    borderStyle: genEnumValidator(['solid', 'dashed', 'dotted']),
2760    borderTopStyle: genEnumValidator(['solid', 'dashed', 'dotted']),
2761    borderRightStyle: genEnumValidator(['solid', 'dashed', 'dotted']),
2762    borderBottomStyle: genEnumValidator(['solid', 'dashed', 'dotted']),
2763    borderLeftStyle: genEnumValidator(['solid', 'dashed', 'dotted']),
2764    borderRadius: LENGTH_VALIDATOR,
2765    borderBottomLeftRadius: LENGTH_VALIDATOR,
2766    borderBottomRightRadius: LENGTH_VALIDATOR,
2767    borderTopLeftRadius: LENGTH_VALIDATOR,
2768    borderTopRightRadius: LENGTH_VALIDATOR,
2769    borderLeft: BORDER_VALIDATOR,
2770    borderRight: BORDER_VALIDATOR,
2771    borderTop: BORDER_VALIDATOR,
2772    borderBottom: BORDER_VALIDATOR
2773  },
2774  flexbox: {
2775    flex: genEnumValidator(['none', 'auto', 'initial']),
2776    flexWrap: genEnumValidator(['nowrap', 'wrap']),
2777    flexGrow: NUMBER_VALIDATOR,
2778    flexShrink: NUMBER_VALIDATOR,
2779    flexBasis: LENGTH_VALIDATOR,
2780    flexDirection: genEnumValidator(['row', 'column', 'column-reverse', 'row-reverse']),
2781    justifyContent: genEnumValidator(['flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'space-evenly']),
2782    alignItems: genEnumValidator(['stretch', 'flex-start', 'flex-end', 'center', 'baseline']),
2783    alignContent: genEnumValidator(['stretch', 'flex-start', 'flex-end', 'center', 'space-between', 'space-around']),
2784  },
2785  position: {
2786    position: genEnumValidator(['relative', 'fixed', 'absolute']),
2787    top: PERCENTAGE_LENGTH_VALIDATOR,
2788    bottom: PERCENTAGE_LENGTH_VALIDATOR,
2789    left: PERCENTAGE_LENGTH_VALIDATOR,
2790    right: PERCENTAGE_LENGTH_VALIDATOR,
2791    zIndex: INTEGER_VALIDATOR
2792  },
2793  common: {
2794    background: BACKGROUND_VALIDATOR,
2795    backgroundColor: COLOR_VALIDATOR,
2796    backgroundImage: URL_VALIDATOR,
2797    backgroundSize: BACKGROUND_SIZE_VALIDATOR,
2798    backgroundRepeat: genEnumValidator(['repeat', 'no-repeat', 'repeat-x', 'repeat-y']),
2799    backgroundPosition: BACKGROUND_POSITION_VALIDATOR,
2800    opacity: NUMBER_VALIDATOR,
2801    appearingDuration: NUMBER_VALIDATOR,
2802    visibility: genEnumValidator(['visible', 'hidden']),
2803    display: genEnumValidator(['flex', 'none', 'grid']),
2804    imageFill: COLOR_VALIDATOR,
2805    maskImage: MASK_VALIDATOR,
2806    maskPosition: BACKGROUND_POSITION_VALIDATOR,
2807    maskSize: BACKGROUND_SIZE_VALIDATOR
2808  },
2809  text: {
2810    color: COLOR_VALIDATOR,
2811    fontSize: LENGTH_VALIDATOR,
2812    allowScale: genEnumValidator(['true', 'false']),
2813    letterSpacing: LENGTH_VALIDATOR,
2814    fontStyle: genEnumValidator(['normal', 'italic']),
2815    fontFamily: ANYTHING_VALIDATOR,
2816    fontWeight: genEnumValidator(['normal', 'lighter', 'bold', 'bolder', "medium", "regular", '100', '200', '300', '400', '500', '600', '700', '800', '900']),
2817    textDecoration: genEnumValidator(['none', 'underline', 'line-through']),
2818    textAlign: genEnumValidator(['start', 'end', 'left', 'center', 'right']),
2819    textOverflow: genEnumValidator(['clip', 'ellipsis']),
2820    textIndent: TEXT_INDENT_VALIDATOR,
2821    lineHeight: LENGTH_VALIDATOR,
2822    maxLines: ANYTHING_VALIDATOR,
2823    minFontSize: LENGTH_VALIDATOR,
2824    maxFontSize: LENGTH_VALIDATOR,
2825    fontSizeStep: LENGTH_VALIDATOR,
2826    preferFontSizes: ARRAY_LENGTH_VALIDATOR,
2827    adaptHeight: genEnumValidator(['true', 'false'])
2828  },
2829  progress: {
2830    secondaryColor: COLOR_VALIDATOR,
2831    scaleWidth: LENGTH_VALIDATOR,
2832    scaleNumber: NUMBER_VALIDATOR,
2833    startAngle: ANGLE_VALIDATOR,
2834    totalAngle: ANGLE_VALIDATOR,
2835    centerX: LENGTH_VALIDATOR,
2836    centerY: LENGTH_VALIDATOR,
2837    radius: LENGTH_VALIDATOR,
2838    direction: genEnumValidator(['start-to-end', 'end-to-start']),
2839    sections: NAME_VALIDATOR,
2840    colors: ARRAY_COLOR_VALIDATOR,
2841    weights: ARRAY_NUMBER_VALIDATOR
2842  },
2843  chart: {
2844    strokeWidth: LENGTH_VALIDATOR,
2845  },
2846  button: {
2847    textColor: COLOR_VALIDATOR,
2848    iconWidth: LENGTH_VALIDATOR,
2849    iconHeight: LENGTH_VALIDATOR
2850  },
2851  image: {
2852    objectFit: genEnumValidator(['cover', 'fill', 'contain', 'none', 'scale-down']),
2853    matchTextDirection: genEnumValidator(['false', 'true']),
2854    fitOriginalSize: genEnumValidator(['false', 'true']),
2855  },
2856  list: {
2857    itemExtent: PERCENTAGE_LENGTH_VALIDATOR,
2858    fadeColor: COLOR_VALIDATOR,
2859    dividerColor: COLOR_VALIDATOR,
2860    dividerHeight: LENGTH_VALIDATOR,
2861    dividerLength: LENGTH_VALIDATOR,
2862    dividerOrigin: LENGTH_VALIDATOR
2863  }
2864}
2865
2866var backgroundValidatorMap = {
2867  linearGradient: LINEAR_GRADIENT_VALIDATOR,
2868  repeatingLinearGradient: LINEAR_GRADIENT_VALIDATOR,
2869  linearGradientColor: ARRAY_COLOR_STOP_VALIDATOR,
2870  linearGradientAngle: ANGLE_VALIDATOR,
2871  linearGradientDirection: GRADIENT_DIRECTION_VALIDATOR
2872}
2873
2874var transformValidatorMap = {
2875  translate: MULTIPLE_PERCENTAGE_LENGTH_VALIDATOR,
2876  translate3d: MULTIPLE_PERCENTAGE_LENGTH_VALIDATOR,
2877  translateX: PERCENTAGE_LENGTH_VALIDATOR,
2878  translateY: PERCENTAGE_LENGTH_VALIDATOR,
2879  translateZ: PERCENTAGE_LENGTH_VALIDATOR,
2880  scale: MULTIPLE_NUMBER_VALIDATOR,
2881  scale3d: MULTIPLE_NUMBER_VALIDATOR,
2882  scaleX: NUMBER_VALIDATOR,
2883  scaleY: NUMBER_VALIDATOR,
2884  scaleZ: NUMBER_VALIDATOR,
2885  rotate: MUTIPLE_ANGLE_VALIDATOR,
2886  rotate3d: ROTATE3D_VALIDATOR,
2887  rotateX: ANGLE_VALIDATOR,
2888  rotateY: ANGLE_VALIDATOR,
2889  rotateZ: ANGLE_VALIDATOR,
2890  skew: MUTIPLE_ANGLE_VALIDATOR,
2891  skewX: ANGLE_VALIDATOR,
2892  skewY: ANGLE_VALIDATOR,
2893  matrix: MULTIPLE_NUMBER_VALIDATOR,
2894  matrix3d: MULTIPLE_NUMBER_VALIDATOR,
2895  perspective: PERCENTAGE_LENGTH_VALIDATOR,
2896}
2897
2898var SUGGESTED_PROP_NAME_GROUP = {}
2899
2900var validatorMap = {}
2901
2902const card = process.env.DEVICE_LEVEL === 'card'
2903var isLiteDevice = process.env.DEVICE_LEVEL === 'lite'
2904
2905var PROP_NAME_GROUPS = process.env.DEVICE_LEVEL === 'lite' ? LITE_PROP_NAME_GROUPS :
2906  card ? CARD_PROP_NAME_GROUPS : RICH_PROP_NAME_GROUPS
2907
2908/**
2909 * flatten `PROP_NAME_GROUPS` to `validatorMap`
2910 */
2911function genValidatorMap() {
2912  var groupName, group, name
2913  for (groupName in PROP_NAME_GROUPS) {
2914    group = PROP_NAME_GROUPS[groupName]
2915    for (name in group) {
2916      validatorMap[name] = group[name]
2917    }
2918  }
2919}
2920
2921genValidatorMap()
2922
2923/**
2924 * validate a CSS name/value pair
2925 *
2926 * @param  {string} name   camel cased
2927 * @param  {string} value
2928 * @return {object}
2929 * - value:string or null
2930 * - log:{reason:string} or undefined
2931 */
2932function validate(name, value) {
2933  var result, log
2934  var validator = validatorMap[name]
2935
2936  if (typeof validator === 'function') {
2937    const flag = /{{{(.+?)}}}|{{(.+?)}}/.test(value) && card
2938    if (typeof value !== 'function' &&  !flag) {
2939      result = validator(value, name)
2940    }
2941    /* istanbul ignore else */
2942    else {
2943      result = {value: value}
2944    }
2945    if (result.reason) {
2946      log = {reason: result.reason(name, value, result.value)}
2947    }
2948  }
2949  else {
2950    // ensure number type, no `px`
2951    /* istanbul ignore else */
2952    if (typeof value !== 'function') {
2953      var match = value.match(LENGTH_REGEXP)
2954      if (match && (!match[1] || SUPPORT_CSS_UNIT.indexOf(match[1]) === -1)) {
2955        value = parseFloat(value)
2956      }
2957    }
2958    result = {value: value}
2959    var suggestedName = SUGGESTED_PROP_NAME_GROUP[name]
2960    var suggested = suggestedName ? ', suggest `' + util.camelCaseToHyphened(suggestedName) + '`' : ''
2961    log = {reason: 'WARNING: `' + util.camelCaseToHyphened(name) + '` is not a standard attribute name and may not be supported' + suggested}
2962  }
2963  return {
2964    value: result.value,
2965    log: log
2966  }
2967}
2968
2969var validateFuncMap = {
2970  length: LENGTH_VALIDATOR,
2971  number: NUMBER_VALIDATOR,
2972  date: DATE_VALIDATOR
2973}
2974
2975module.exports = {
2976  BASIC_COLOR_KEYWORDS: BASIC_COLOR_KEYWORDS,
2977  EXTENDED_COLOR_KEYWORDS: EXTENDED_COLOR_KEYWORDS,
2978
2979  LENGTH_VALIDATOR: LENGTH_VALIDATOR,
2980  COLOR_VALIDATOR: COLOR_VALIDATOR,
2981  NUMBER_VALIDATOR: NUMBER_VALIDATOR,
2982  INTEGER_VALIDATOR: INTEGER_VALIDATOR,
2983  genEnumValidator: genEnumValidator,
2984
2985  TRANSITION_PROPERTY_VALIDATOR: TRANSITION_PROPERTY_VALIDATOR,
2986  TRANSITION_DURATION_VALIDATOR: TRANSITION_INTERVAL_VALIDATOR,
2987  TRANSITION_DELAY_VALIDATOR: TRANSITION_INTERVAL_VALIDATOR,
2988  TRANSITION_TIMING_FUNCTION_VALIDATOR: TRANSITION_TIMING_FUNCTION_VALIDATOR,
2989
2990  PROP_NAME_GROUPS: PROP_NAME_GROUPS,
2991  validateFuncMap: validateFuncMap,
2992
2993  map: validatorMap,
2994  validate: validate
2995}
2996