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