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 NORMAL_REGEXP = /^normal$/ 198var AUTO_REGEXP = /^auto$/ 199var 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$)/ 200var TRANSFORM_REGEXP = /[0-9a-zA-Z]+\s*\(\s*[0-9(a-zA-Z-|%)\.]+\s*(,\s*[0-9(a-zA-Z-|%)\.]+)*\)/g 201var TRANSFORM_ITEM_REGEXP = /^([0-9a-zA-Z]+)\s*\((.*)\)$/ 202var FILTER_REGEXP = /^blur\(([1-9]\d*|0)(px|fp|vp)\)$/ 203var FILTER_PERCENTAGE_REGEXP = /^blur\(([1-9]?\d|100)%\)$/ 204var FILTER_STYLE_REGEXP = /^blur\(([1-9]?\d|100)%\)\s+[A-Za-z_]+$/ 205var SUPPORT_CSS_EXPRESSION = /calc\(|var\(\-\-/ 206var SUPPORT_VAR_EXPRESSION = /var\(\-\-/ 207var SUPPORT_CSS_UNIT = ['px', 'pt', 'wx', 'vp', 'fp'] 208var SUPPORT_CSS_TIME_UNIT = ['ms', 's'] 209var SUPPORT_CSS_PERCENTAGE_UNIT = ['px', '%', 'vp', 'fp'] 210var SUPPORT_CSS_GRID_UNIT = ['px', '%', 'fr', 'vp', 'fp'] 211var SUPPORT_CSS_TEXT_INDENT_UNIT = ['px', 'cm', '%', 'em', 'vp', 'fp'] 212var SUPPORT_CSS_ANGLE_UNIT = ["deg", "rad", "grad", "turn"] 213var logTypes = ["NOTE", "WARNING", "ERROR"] 214 215var ANYTHING_VALIDATOR = function ANYTHING_VALIDATOR(v) { 216 v = (v || '').toString().trim() 217 return { value: v } 218} 219 220/** 221 * the values below is valid 222 * - auto 223 * - number 224 * - number + 'px'|'%'|'vp'| 'fp' 225 * 226 * @param {string} v 227 * @return {function} a function to return 228 * - value: number|null 229 * - reason(k, v, result) 230 */ 231var AUTO_PERCENTAGE_LENGTH_VALIDATOR = function AUTO_PERCENTAGE_LENGTH_VALIDATOR(v) { 232 v = (v || '').toString().trim() 233 if (v.match(AUTO_REGEXP)) { 234 return { value: v } 235 } else if (v.match(ID_REGEXP)) { 236 return { value: v } 237 } else if (v.match(SUPPORT_CSS_EXPRESSION)) { 238 return { value: v } 239 } else { 240 return LENGTH(v, SUPPORT_CSS_PERCENTAGE_UNIT) 241 } 242} 243 244/** 245 * the values below is valid 246 * - number 247 * - number + 'px'|'%'|'vp'| 'fp' 248 * 249 * @param {string} v 250 * @return {function} a function to return 251 * - value: number|null 252 * - reason(k, v, result) 253 */ 254var PERCENTAGE_LENGTH_VALIDATOR = function PERCENTAGE_LENGTH_VALIDATOR(v) { 255 v = (v || '').toString().trim() 256 if (v.match(ID_REGEXP)) { 257 return { value: v } 258 } else if (v.match(SUPPORT_CSS_EXPRESSION)) { 259 return { value: v } 260 } else { 261 return LENGTH(v, SUPPORT_CSS_PERCENTAGE_UNIT) 262 } 263} 264 265/** 266 * the values below is valid 267 * - number 268 * - number + 'px' 269 * 270 * @param {string} v 271 * @return {function} a function to return 272 * - value: number|null 273 * - reason(k, v, result) 274 */ 275var LENGTH_VALIDATOR = function LENGTH_VALIDATOR(v) { 276 v = (v || '').toString().trim() 277 if (v.match(SUPPORT_CSS_EXPRESSION)) { 278 return { value: v } 279 } else if (v.match(ID_REGEXP)) { 280 return { value: v } 281 } else { 282 return LENGTH(v, SUPPORT_CSS_UNIT) 283 } 284} 285 286var LENGTH = function LENGTH(v, SUPPORT_UNIT) { 287 v = (v || '').toString().trim() 288 var match = v.match(LENGTH_REGEXP) 289 290 if (match) { 291 var unit = match[1] 292 if (!unit) { 293 return v === '0' ? { value: parseFloat(v) + SUPPORT_UNIT[0] } : 294 { 295 value: parseFloat(v) + SUPPORT_UNIT[0], 296 reason: function(k, v) { 297 return 'WARNING: No unit is specified for the `' + util.camelCaseToHyphened(k) + 298 '` attribute. The default unit is ' + SUPPORT_UNIT[0] 299 } 300 } 301 } else if (SUPPORT_UNIT.indexOf(unit) > -1) { 302 return { value: v } 303 } else { 304 return { 305 value: parseFloat(v) + SUPPORT_UNIT[0], 306 reason: function reason(k, v, result) { 307 return 'ERROR: The `' + k + '` attribute does not support `' + unit + 308 '`. The default unit is ' + SUPPORT_UNIT[0] 309 } 310 } 311 } 312 } 313 314 if (v.indexOf('@') >= 0) { 315 let result 316 // target format "@sys.float.id_sys_length" or '@sys.float.id_sys_length' 317 let SysResourceTypeRefReg = /['"]\s*@sys\.float\.(?<resName>\w+)\s*['"]/ 318 result = SysResourceTypeRefReg.exec(v) 319 if (result) { 320 const resourceName = result.groups['resName'] 321 if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) { 322 return { value: "@sys.float." + OHOS_THEME_PROP_GROUPS[resourceName] } 323 } 324 } 325 // target format "@app.float.developer_defined_length" or '@app.float.developer_defined_length' 326 let AppResourceTypeRefReg = /['"]\s*@app\.float\.(?<resName>\w+)\s*['"]/ 327 result = AppResourceTypeRefReg.exec(v) 328 if (result) { 329 const resourceName = result.groups['resName'] 330 if (resourceName) { 331 return { value: "@app.float." + resourceName} 332 } 333 } 334 // target format "@id_sys_length" or '@id_sys_length' or @id_sys_length 335 let ResourceRefReg = /['"]?\s*@(?<resName>\w+)\s*['"]?/ 336 result = ResourceRefReg.exec(v) 337 if (result) { 338 const resourceName = result.groups['resName'] 339 if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) { 340 return { value: "@ohos_id_" + OHOS_THEME_PROP_GROUPS[resourceName] } 341 } 342 } 343 } 344 345 return { 346 value: null, 347 reason: function reason(k, v, result) { 348 return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support the `' + 349 v + '` value (only numbers are supported).' 350 } 351 } 352} 353 354var TEXT_INDENT_VALIDATOR = function TEXT_INDENT_VALIDATOR(v) { 355 return LENGTH(v, SUPPORT_CSS_TEXT_INDENT_UNIT) 356} 357 358var TEXT_LINE_HEIGHT_VALIDATOR = function TEXT_LINE_HEIGHT_VALIDATOR(v) { 359 v = (v || '').toString().trim() 360 361 if (v.match(NORMAL_REGEXP)) { 362 return { value: v } 363 } else { 364 return LENGTH_VALIDATOR(v) 365 } 366} 367 368/** 369 * the values below is valid 370 * - number 371 * - number + 'ms'|'s' 372 * 373 * @param {string} v 374 * @return {function} a function to return 375 * - value: number|null 376 * - reason(k, v, result) 377 */ 378var TIME_VALIDATOR = function TIME_VALIDATOR(v) { 379 return LENGTH(v, SUPPORT_CSS_TIME_UNIT) 380} 381 382/** 383 * the values below is valid 384 * - number {1,4} 385 * - number + 'px' {1,4} 386 * 387 * @param {string} v 388 * @return {function} a function to return 389 * - value: number|null 390 * - reason(k, v, result) 391 */ 392var SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR = function SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR(v) { 393 v = (v || '').toString().trim() 394 let rule = PERCENTAGE_LENGTH_VALIDATOR 395 return SHORTHAND_VALIDATOR(v, rule) 396} 397 398var SHORTHAND_AUTO_PERCENTAGE_LENGTH_VALIDATOR = function SHORTHAND_AUTO_PERCENTAGE_LENGTH_VALIDATOR(v) { 399 v = (v || '').toString().trim() 400 let rule = AUTO_PERCENTAGE_LENGTH_VALIDATOR 401 return SHORTHAND_VALIDATOR(v, rule) 402} 403 404var SHORTHAND_LENGTH_VALIDATOR = function SHORTHAND_LENGTH_VALIDATOR(v) { 405 v = (v || '').toString().trim() 406 let rule = LENGTH_VALIDATOR 407 return SHORTHAND_VALIDATOR(v, rule) 408} 409 410var ARRAY_LENGTH_VALIDATOR = function ARRAY_LENGTH_VALIDATOR(v) { 411 v = (v || '').toString().trim().replace(/,/g, ' ') 412 var isArray = true 413 return SHORTHAND_VALIDATOR(v, LENGTH_VALIDATOR, isArray) 414} 415 416/** 417 * the values below is valid 418 * - hex color value (#xxxxxx or #xxx) 419 * - basic and extended color keywords in CSS spec 420 * - expression 421 * 422 * @param {string} v 423 * @return {function} a function to return 424 * - value: string|null 425 * - reason(k, v, result) 426 */ 427var COLOR_VAR_VALIDATOR = function COLOR_VAR_VALIDATOR(v) { 428 v = (v || '').toString().trim() 429 if (v.match(SUPPORT_VAR_EXPRESSION)) { 430 return { value: v } 431 } else { 432 return COLOR_VALIDATOR(v) 433 } 434} 435 436/** 437 * the values below is valid 438 * - hex color value (#xxxxxx or #xxx) 439 * - basic and extended color keywords in CSS spec 440 * 441 * @param {string} v 442 * @return {function} a function to return 443 * - value: string|null 444 * - reason(k, v, result) 445 */ 446var COLOR_VALIDATOR = function COLOR_VALIDATOR(v) { 447 v = (v || '').toString().trim() 448 449 if (v.indexOf('linear-gradient') >= 0) { 450 let result = { 451 values: [] 452 } 453 let temp = LINEAR_GRADIENT_VALIDATOR(v) 454 if (util.isValidValue(temp.value)) { 455 let tempValue = JSON.parse(temp.value) 456 result.values.push(tempValue) 457 return { value: JSON.stringify(result) } 458 } else { 459 return temp 460 } 461 } 462 463 if (v.match(ID_REGEXP)) { 464 return { value: v } 465 } 466 467 if (v.indexOf('@') >= 0) { 468 let result 469 // target format "@sys.color.id_color_background" or '@sys.color.id_color_background' 470 let SysResourceTypeRefReg = /['"]\s*@sys\.color\.(?<resName>\w+)\s*['"]/ 471 result = SysResourceTypeRefReg.exec(v) 472 if (result) { 473 const resourceName = result.groups['resName'] 474 if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) { 475 return { value: "@sys.color." + OHOS_THEME_PROP_GROUPS[resourceName] } 476 } 477 } 478 // target format "@app.color.developer_defined_color" or '@app.color.developer_defined_color' 479 let AppResourceTypeRefReg = /['"]\s*@app\.color\.(?<resName>\w+)\s*['"]/ 480 result = AppResourceTypeRefReg.exec(v) 481 if (result) { 482 const resourceName = result.groups['resName'] 483 if (resourceName) { 484 return { value: "@app.color." + resourceName} 485 } 486 } 487 // target format "@id_color_background" or '@id_color_background' or @id_color_background 488 let ResourceRefReg = /['"]?\s*@(?<resName>\w+)\s*['"]?/ 489 result = ResourceRefReg.exec(v) 490 if (result) { 491 const resourceName = result.groups['resName'] 492 if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) { 493 return { value: "@ohos_id_" + OHOS_THEME_PROP_GROUPS[resourceName] } 494 } 495 } 496 } 497 498 if (v.match(/^#([0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/)) { 499 return { value: v } 500 } 501 502 if (v.match(/^#[0-9a-fA-F]{3}$/)) { 503 return { 504 value: '#' + v[1] + v[1] + v[2] + v[2] + v[3] + v[3], 505 reason: function reason(k, v, result) { 506 return 'NOTE: Attribute value `' + v + '` is automatically fixed to `' + result + '`.' 507 } 508 } 509 } 510 511 if (EXTENDED_COLOR_KEYWORDS[v]) { 512 return { 513 value: EXTENDED_COLOR_KEYWORDS[v], 514 reason: function reason(k, v, result) { 515 return 'NOTE: Attribute value `' + v + '` is automatically fixed to `' + result + '`.' 516 } 517 } 518 } 519 520 if (v === 'transparent' || v === 'none') { 521 return { value: 'rgba(0,0,0,0)' } 522 } 523 524 const returnColorReg = COLOR_REG(v) 525 if (returnColorReg.value !== null) { 526 return returnColorReg 527 } 528 529 return { 530 value: null, 531 reason: function reason(k, v, result) { 532 return 'ERROR: Value `' + v + '` is invalid for the `' + util.camelCaseToHyphened(k) + '` attribute.' 533 } 534 } 535} 536 537var COLOR_REG = function COLOR_REG(v) { 538 let arrColor, r, g, b, a 539 const RGB_REGEXP = /^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/gi 540 const RGBA_REGEXP = /^rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d*\.?\d+)\s*\)$/gi 541 const HSL_REGEXP = /^hsl\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*\)$/gi 542 const HSLA_REGEXP = /^hsla\(\s*(\d+)\s*,\s*(\d+)%\s*,\s*(\d+)%\s*,\s*(\d*\.?\d+)\s*\)$/gi 543 if (arrColor = RGB_REGEXP.exec(v)) { 544 r = parseInt(arrColor[1]) 545 g = parseInt(arrColor[2]) 546 b = parseInt(arrColor[3]) 547 if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255) { 548 return { value: 'rgb(' + [r, g, b].join(',') + ')' } 549 } 550 } 551 if (arrColor = RGBA_REGEXP.exec(v)) { 552 r = parseInt(arrColor[1]) 553 g = parseInt(arrColor[2]) 554 b = parseInt(arrColor[3]) 555 a = parseFloat(arrColor[4]) 556 if (r >= 0 && r <= 255 && g >= 0 && g <= 255 && b >= 0 && b <= 255 && a >= 0 && a <= 1) { 557 return { value: 'rgba(' + [r, g, b, a].join(',') + ')' } 558 } 559 } 560 if (arrColor = HSL_REGEXP.exec(v)) { 561 r = arrColor[1] 562 g = arrColor[2] 563 b = arrColor[3] 564 if (r >= 0 && r <= 360 && g >= 0 && g <= 100 && b >= 0 && b <= 100) { 565 return { value: 'hsl(' + [r, g+'%', b+'%'].join(',') + ')' } 566 } 567 } 568 if (arrColor = HSLA_REGEXP.exec(v)) { 569 r = arrColor[1] 570 g = arrColor[2] 571 b = arrColor[3] 572 a = arrColor[4] 573 if (r >= 0 && r <= 360 && g >= 0 && g <= 100 && b >= 0 && b <= 100 && a >= 0 && a <= 1) { 574 return { value: 'hsla(' + [r, g+'%', b+'%', a].join(',') + ')' } 575 } 576 } 577 578 return { value: null } 579} 580 581/** 582 * the values below is valid 583 * - color {1,4} 584 * 585 * @param {string} v 586 * @return {function} a function to return 587 * - value: color|null 588 * - reason(k, v, result) 589 */ 590var SHORTHAND_COLOR_VALIDATOR = function SHORTHAND_COLOR_VALIDATOR(v) { 591 v = (v || '').toString().trim() 592 v = v.replace(/\s*,\s+/g, ',') 593 return SHORTHAND_VALIDATOR(v, COLOR_VAR_VALIDATOR) 594} 595 596var ARRAY_COLOR_VALIDATOR = function ARRAY_COLOR_VALIDATOR(v) { 597 v = (v || '').toString().trim() 598 var isArray = true 599 return SHORTHAND_VALIDATOR(v.replace(/,/g, ' '), COLOR_VAR_VALIDATOR, isArray) 600} 601 602var SHORTHAND_STYLE_VALIDATOR = function SHORTHAND_STYLE_VALIDATOR(v) { 603 v = (v || '').toString().trim() 604 return SHORTHAND_VALIDATOR(v, STYLE_VALIDATOR) 605} 606 607var STYLE_VALIDATOR = function STYLE_VALIDATOR(v) { 608 const styleList = ["solid", "dashed", "dotted"] 609 v = (v || '').toString().trim() 610 if (styleList.includes(v)) { 611 return { value:v } 612 } else { 613 return { 614 value: null, 615 reason: function (k,v) { 616 return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + 617 v + '` (the support value is `' + styleList.join('`|`') + '`).' 618 } 619 } 620 } 621} 622 623var SHORTHAND_VALIDATOR = function SHORTHAND_VALIDATOR(v, validateFunction, isArray) { 624 v = (v || '').toString().trim() 625 let value = [] 626 let reason = [] 627 let results = v.split(/(?<!\+|\-|\*|\/|\,)\s+(?!\+|\-|\*|\/|\,)/).map(validateFunction) 628 for (let i = 0; i < results.length; ++i) { 629 let res = results[i] 630 if (!res.value) { 631 value = null 632 reason = res.reason 633 break 634 } 635 value.push(res.value) 636 if (res.reason) { 637 reason.push(res.reason) 638 } 639 } 640 641 if (!value) { 642 return { 643 value: value, 644 reason: reason 645 } 646 } 647 else { 648 return { 649 value: isArray ? value.join(',') : value.join(' '), 650 reason: reason.length > 0 ? function (k, v, result) { 651 return reason.map(function (res) { 652 if (typeof res === 'function') { 653 return res(k, v, result) 654 } 655 }).join('\n') 656 } : null 657 } 658 } 659} 660 661var BORDER_VALIDATOR = function BORDER_VALIDATOR (value, name) { 662 value = (value || '').toString().trim(); 663 let values = ''; 664 const colorAttribute = value.match(/\(.*?\)/g); 665 if (colorAttribute && colorAttribute.length === 1) { 666 values = value.replace(colorAttribute[0], colorAttribute[0].replace(/\s+/g, '')).split(/\s+/); 667 } else { 668 values = value.split(/\s+/); 669 } 670 const res = [] 671 let hasError = false 672 const reasons = [] 673 let index = 0 674 const order = [] 675 let validatorResult 676 const rules = [ 677 { 678 match (item) { return LENGTH_VALIDATOR(item).value }, 679 action (item) { 680 validatorResult = LENGTH_VALIDATOR(item) 681 order.push(0) 682 res.push({ 683 value: validatorResult.value, 684 type: 'Width' 685 }) 686 } 687 }, 688 { 689 match (item) { return validate('borderStyle', item).value }, 690 action (item) { 691 validatorResult = validate('borderStyle', item) 692 order.push(1) 693 res.push({ 694 value: validatorResult.value, 695 type: 'Style' 696 }) 697 } 698 }, 699 { 700 match (item) { return COLOR_VAR_VALIDATOR(item).value }, 701 action (item) { 702 validatorResult = COLOR_VAR_VALIDATOR(item) 703 order.push(2) 704 res.push({ 705 value: validatorResult.value, 706 type: 'Color' 707 }) 708 } 709 }, 710 { 711 match () { return true }, 712 action () { 713 hasError = true 714 } 715 } 716 ] 717 if (values && values.length <= 3) { 718 for (let i = 0; i < values.length; i++) { 719 const item = values[i] 720 for (let i = 0; i < rules.length; i++) { 721 if (rules[i].match(item)) { 722 rules[i].action(item) 723 break; 724 } 725 } 726 // style width color pass verification, but did not write in order, such as "1px red solid", should be error 727 let orderIndex = -1 728 order.forEach((item) => { 729 orderIndex < item ? orderIndex = item : hasError = true 730 }) 731 // get all warning and note log 732 logUtil(validatorResult, name, item, reasons, index) 733 } 734 // print warning and note 735 if (!hasError) { 736 return { 737 value: res, 738 reason: reasons.length > 0 ? function (k, v) { 739 return ( 740 logTypes[index] + ': There are some problems with value `' + v + '` of the `' + 741 util.camelCaseToHyphened(k) + '` attribute. \n ' + reasons.join(' \n')) 742 } : null 743 } 744 } 745 } 746 // print error 747 return { 748 value: null, 749 reason: function reason (k, v, result) { 750 return 'ERROR: The `' + util.camelCaseToHyphened(k) + 751 '` attribute does not support value `' + v + 752 '` (this value does not meet the inspection standards for the width, style, and color).' 753 } 754 } 755} 756 757function logUtil (validatorResult, name, item, reasons, index) { 758 if (validatorResult.reason) { 759 let str = validatorResult.reason(name, item, validatorResult.value) 760 const mesg = str.match(/^([A-Z]+):/) 761 // When both warning and note information are included, a high severity sign is output 762 const num = logTypes.indexOf(mesg[1]) 763 if (index < num) { 764 index = num 765 } 766 str = str.replace(mesg[0], '') 767 reasons.push(str) 768 } 769} 770 771var BOX_SHADOW_VALIDATOR = function BOX_SHADOW_VALIDATOR(value, name) { 772 value = (value || '').toString().trim() 773 const values = value.split(/\s+/) 774 let validatorResult 775 const res = [] 776 const order = [] 777 const reasons = [] 778 let index = 0 779 let ruleIndex = 0 780 let hasError = false 781 const rules = [ 782 { 783 match (item) { return validate('boxShadowH', item).value }, 784 action (item) { 785 validatorResult = validate('boxShadowH', item) 786 order.push(0) 787 res.push({ 788 value: validatorResult.value, 789 type: 'H' 790 }) 791 } 792 }, 793 { 794 match (item) { return validate('boxShadowV', item).value }, 795 action (item) { 796 validatorResult = validate('boxShadowV', item) 797 order.push(1) 798 res.push({ 799 value: validatorResult.value, 800 type: 'V' 801 }) 802 } 803 }, 804 { 805 match (item) { return validate('boxShadowBlur', item).value }, 806 action (item) { 807 validatorResult = validate('boxShadowBlur', item) 808 order.push(2) 809 res.push({ 810 value: validatorResult.value, 811 type: 'Blur' 812 }) 813 } 814 }, 815 { 816 match (item) { return validate('boxShadowSpread', item).value }, 817 action (item) { 818 validatorResult = validate('boxShadowSpread', item) 819 order.push(3) 820 res.push({ 821 value: validatorResult.value, 822 type: 'Spread' 823 }) 824 } 825 }, 826 { 827 match (item) { return COLOR_VAR_VALIDATOR(item).value }, 828 action (item) { 829 validatorResult = COLOR_VAR_VALIDATOR(item) 830 order.push(4) 831 res.push({ 832 value: validatorResult.value, 833 type: 'Color' 834 }) 835 } 836 } 837 ] 838 const length = values.length 839 const flag = (length <= 6 && length >= 2) && values[0].match(LENGTH_REGEXP) && values[1].match(LENGTH_REGEXP) 840 if (values && flag) { 841 for (let i = 0; i < values.length; i++) { 842 const item = values[i] 843 for (let j = ruleIndex; j < rules.length; j++) { 844 if (rules[j].match(item)) { 845 ruleIndex++ 846 rules[j].action(item) 847 break 848 } 849 } 850 let orderIndex = -1 851 order.forEach((item) => { 852 orderIndex < item ? orderIndex = item : hasError = true 853 }) 854 // get all warning and note log 855 logUtil(validatorResult, name, item, reasons, index) 856 } 857 if (!hasError) { 858 return { 859 value: res, 860 reason: reasons.length > 0 ? function (k, v) { 861 return ( 862 logTypes[index] + ': There are some problems with value `' + v + 863 '` of the `' + util.camelCaseToHyphened(k) + '` attribute. \n ' + reasons.join(' \n')) 864 } : null 865 } 866 } 867 } 868 return { 869 value: null, 870 reason: function reason (k, v, result) { 871 return 'ERROR: The `' + util.camelCaseToHyphened(k) + 872 '` attribute does not support value `' + v + 873 '` (this value does not meet the inspection standards).' 874 } 875 } 876} 877 878/** 879 * only integer or float value is valid 880 * 881 * @param {string} v 882 * @return {function} a function to return 883 * - value: number|null 884 * - reason(k, v, result) 885 */ 886var NUMBER_VALIDATOR = function NUMBER_VALIDATOR(v, isInt) { 887 v = (v || '').toString().trim() 888 889 if (v.match(ID_REGEXP)) { 890 return { value: v } 891 } 892 893 var match = v.match(LENGTH_REGEXP) 894 895 if (match && !match[1]) { 896 return { value: isInt === true ? parseInt(v, 10) : parseFloat(v) } 897 } 898 899 if (v.indexOf('@') >= 0) { 900 let result 901 // target format "@sys.float.id_sys_number" or '@sys.float.id_sys_number' 902 let SysResourceTypeRefReg = /['"]\s*@sys\.float\.(?<resName>\w+)\s*['"]/ 903 result = SysResourceTypeRefReg.exec(v) 904 if (result) { 905 const resourceName = result.groups['resName'] 906 if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) { 907 return { value: "@sys.float." + OHOS_THEME_PROP_GROUPS[resourceName] } 908 } 909 } 910 // target format "@app.float.developer_defined_number" or '@app.float.developer_defined_number' 911 let AppResourceTypeRefReg = /['"]\s*@app\.float\.(?<resName>\w+)\s*['"]/ 912 result = AppResourceTypeRefReg.exec(v) 913 if (result) { 914 const resourceName = result.groups['resName'] 915 if (resourceName) { 916 return { value: "@app.float." + resourceName} 917 } 918 } 919 // target format "@id_sys_number" or '@id_sys_number' or @id_sys_number 920 let ResourceRefReg = /['"]?\s*@(?<resName>\w+)\s*['"]?/ 921 result = ResourceRefReg.exec(v) 922 if (result) { 923 const resourceName = result.groups['resName'] 924 if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) { 925 return { value: "@ohos_id_" + OHOS_THEME_PROP_GROUPS[resourceName] } 926 } 927 } 928 } 929 930 return { 931 value: null, 932 reason: function reason(k, v, result) { 933 return 'ERROR: The `' + util.camelCaseToHyphened(k) + 934 '` attribute does not support value `' + v + '` (only numbers are supported).' 935 } 936 } 937} 938 939var ARRAY_NUMBER_VALIDATOR = function ARRAY_NUMBER_VALIDATOR(v) { 940 v = (v || '').toString().trim().replace(/,/g, ' ') 941 var isArray = true 942 return SHORTHAND_VALIDATOR(v, NUMBER_VALIDATOR, isArray) 943} 944 945/** 946 * only integer value is valid 947 * 948 * @param {string} v 949 * @return {function} a function to return 950 * - value: number|null 951 * - reason(k, v, result) 952 */ 953var INTEGER_VALIDATOR = function INTEGER_VALIDATOR(v) { 954 return NUMBER_VALIDATOR(v, true) 955} 956 957/** 958 * transition-property: only css property is valid 959 * 960 * @param {string} v 961 * @return {function} a function to return 962 * - value: string|null 963 * - reason(k, v, result) 964 */ 965var TRANSITION_PROPERTY_VALIDATOR = function TRANSITION_PROPERTY_VALIDATOR(v) { 966 v = (v || '').toString() 967 v = v.split(/\s*,\s*/).map(util.hyphenedToCamelCase).join(',') 968 969 if (v.split(/\s*,\s*/).every(p => !!validatorMap[p])) { 970 return {value: v} 971 } 972 973 return { 974 value: null, 975 reason: function reason(k, v, result) { 976 return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + 977 v + '` (only CSS attributes support this value).' 978 } 979 } 980} 981 982/** 983 * transition-duration & transition-delay: only number of seconds or milliseconds is valid 984 * 985 * @param {string} v 986 * @return {function} a function to return 987 * - value: number|null 988 * - reason(k, v, result) 989 */ 990var TRANSITION_INTERVAL_VALIDATOR = function TRANSITION_INTERVAL_VALIDATOR(v) { 991 v = (v || 0).toString() 992 var match, num, ret 993 994 if (match = v.match(/^\d*\.?\d+(ms|s)?$/)) { 995 num = parseFloat(match[0]) 996 if (!match[1]) { 997 ret = {value: parseInt(num)} 998 } 999 else { 1000 if (match[1] === 's') { 1001 num *= 1000 1002 } 1003 ret = { 1004 value: parseInt(num), 1005 reason: function reason(k, v, result) { 1006 return 'NOTE: Attribute value `' + v + '` is automatically fixed to `' + result + '`.' 1007 } 1008 } 1009 } 1010 return ret 1011 } 1012 1013 return { 1014 value: null, 1015 reason: function reason(k, v, result) { 1016 return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + 1017 v + '` (only seconds and milliseconds are supported).' 1018 } 1019 } 1020} 1021 1022/** 1023 * transition-timing-function: only linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier(n,n,n,n) is valid 1024 * 1025 * @param {string} v 1026 * @return {function} a function to return 1027 * - value: linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier(n,n,n,n)|null 1028 * - reason(k, v, result) 1029 */ 1030var TRANSITION_TIMING_FUNCTION_VALIDATOR = function TRANSITION_TIMING_FUNCTION_VALIDATOR(v) { 1031 v = (v || '').toString() 1032 1033 if (v.match(/^linear|ease|ease-in|ease-out|ease-in-out|fast-out-slow-in|linear-out-slow-in$/) || 1034 v.match(/^fast-out-linear-in|friction|extreme-deceleration|sharp|rhythm|smooth$/)) { 1035 return {value: v} 1036 } 1037 1038 let match, ret 1039 let NUM_REGEXP = /^[-]?\d*\.?\d+$/ 1040 if (match = v.match(/^cubic-bezier\(\s*(.*)\s*,\s*(.*)\s*,\s*(.*)\s*,\s*(.*)\s*\)$/)) { 1041 /* istanbul ignore else */ 1042 if (match[1].match(NUM_REGEXP) && match[2].match(NUM_REGEXP) && 1043 match[3].match(NUM_REGEXP) && match[4].match(NUM_REGEXP)) { 1044 ret = [parseFloat(match[1]), parseFloat(match[2]), parseFloat(match[3]), parseFloat(match[4])].join(',') 1045 return {value: 'cubic-bezier(' + ret + ')'} 1046 } 1047 } 1048 1049 // check steps 1050 if (match = v.match(/^steps\(\s*([\d]*)\s*(,\s*(start|end)\s*){0,1}\)$/)) { 1051 var stepCnt = parseFloat(match[1]); 1052 if (stepCnt > 0) { 1053 if (match[3] === undefined) { 1054 ret = stepCnt; 1055 } else { 1056 ret = [stepCnt, match[3]].join(',') 1057 } 1058 return {value: 'steps(' + ret + ')'} 1059 } 1060 } 1061 1062 return { 1063 value: null, 1064 reason: function reason(k, v, result) { 1065 return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + v + 1066 '` (supported values include `linear`, `ease`, `ease-in`, `ease-out`, `ease-in-out`,' + 1067 ' `cubic-bezier(n,n,n,n)` and `steps(n[, start|end])`).' 1068 } 1069 } 1070} 1071 1072function parseAnimationOption(key, option, style) 1073{ 1074 var subResult = validate(key, option) 1075 if (subResult.value) { 1076 style[key] = subResult.value 1077 return true 1078 } 1079 return false 1080} 1081 1082function parseSimpleAnimation(style, animation) { 1083 // init default animation brief value 1084 Object.assign(style, DEFAULT_ANIMATION) 1085 let options = animation.trim().replace(/,\s+/g, ",").split(/\s+/) 1086 let durationIdx = NaN 1087 let delayIdx = NaN 1088 let directionIdx = NaN 1089 let timingIdx = NaN 1090 let playStateIdx = NaN 1091 let iterationIdx = NaN 1092 let fillModeIdx = NaN 1093 for (let idx in options) { 1094 const option = options[idx] 1095 if (isNaN(timingIdx) && parseAnimationOption('animationTimingFunction', option, style)) { 1096 timingIdx = idx 1097 continue 1098 } 1099 if (isNaN(directionIdx) && parseAnimationOption('animationDirection', option, style)) { 1100 directionIdx = idx 1101 continue 1102 } 1103 if (isNaN(playStateIdx) && parseAnimationOption('animationPlayState', option, style)) { 1104 playStateIdx = idx 1105 continue 1106 } 1107 if (isNaN(iterationIdx) && parseAnimationOption('animationIterationCount', option, style)) { 1108 iterationIdx = idx 1109 continue 1110 } 1111 if (isNaN(fillModeIdx) && parseAnimationOption('animationFillMode', option, style)) { 1112 fillModeIdx = idx 1113 continue 1114 } 1115 if (isNaN(durationIdx) && parseAnimationOption('animationDuration', option, style)) { 1116 durationIdx = idx 1117 continue 1118 } 1119 if (isNaN(delayIdx) && parseAnimationOption('animationDelay', option, style)) { 1120 delayIdx = idx 1121 continue 1122 } 1123 } 1124 delete options[durationIdx] 1125 delete options[delayIdx] 1126 delete options[directionIdx] 1127 delete options[timingIdx] 1128 delete options[playStateIdx] 1129 delete options[iterationIdx] 1130 delete options[fillModeIdx] 1131 options = options.filter(res => { return !(res === 'undefined') }) 1132 if (options.length === 1) { 1133 if (!parseAnimationOption('animationName', options[0], style)) { 1134 return false 1135 } 1136 return true 1137 } else if (options.length > 1) { 1138 return false 1139 } else { 1140 // use default. 1141 return true 1142 } 1143} 1144 1145var ANIMATION_VALIDATOR = function ANIMATION_VALIDATOR(v) { 1146 var style = {} 1147 if (parseSimpleAnimation(style, v)) { 1148 return {value: style} 1149 } else { 1150 return { 1151 value: null, 1152 reason: function reason(k, v, result) { 1153 return 'ERROR: animation is invalid' 1154 } 1155 } 1156 } 1157} 1158 1159var TRANSFORM_VALIDATOR = function TRANSFORM_VALIDATOR(v) { 1160 v = (v || '').toString().trim() 1161 if (v.match(/^none$/)) { 1162 return { value: JSON.stringify({}) } 1163 } 1164 const values = [] 1165 TRANSFORM_REGEXP.lastIndex = 0 1166 while (true) { 1167 let matchValue = TRANSFORM_REGEXP.exec(v) 1168 if (!matchValue) { 1169 break 1170 } 1171 values.push(v.slice(matchValue.index, TRANSFORM_REGEXP.lastIndex)) 1172 } 1173 if (!values.length) { 1174 return { 1175 value: null, 1176 reason: function reason(k, v) { 1177 return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + v + '`.' 1178 } 1179 } 1180 } 1181 let result = {} 1182 let reasonMaps = [] 1183 let allLength = 0 1184 values.forEach(function(v) { 1185 let length = 0 1186 let match = v.match(TRANSFORM_ITEM_REGEXP) 1187 if (match) { 1188 let firstValue = match[1] 1189 let secondValue = match[2] 1190 let checkFuntion = transformValidatorMap[firstValue] 1191 if (typeof checkFuntion == 'function') { 1192 var checkResult = checkFuntion(secondValue) 1193 if (typeof checkResult.value == 'number' || typeof checkResult.value == 'string') { 1194 result[firstValue] = checkResult.value 1195 } 1196 let check = checkReason(checkResult, firstValue, secondValue, length) 1197 length = check.length 1198 if (check.realReason) { 1199 reasonMaps.push(check.realReason) 1200 } 1201 } else { 1202 length = 2 1203 reasonMaps.push('property `' + firstValue + '` is invalid.') 1204 } 1205 } else { 1206 length = 2 1207 reasonMaps.push('property value `' + v + '` is invalid.') 1208 } 1209 if (allLength < length) { 1210 allLength = length 1211 } 1212 }) 1213 return { 1214 value: result ? JSON.stringify(result) : null, 1215 reason: reasonMaps.length > 0 ? 1216 function(k, v) { 1217 return logTypes[allLength] + ': Value `' + v + '` of the `' + 1218 util.camelCaseToHyphened(k) + '` attribute is incorrect. \n ' + reasonMaps.join(' \n ') 1219 } : null 1220 } 1221} 1222 1223var MULTIPLE_PERCENTAGE_LENGTH_VALIDATOR = function MULTIPLE_PERCENTAGE_LENGTH_VALIDATOR(v) { 1224 v = (v || '').toString().trim() 1225 return MULTIPLE_POSITION_VALIDATOR(v, PERCENTAGE_LENGTH_VALIDATOR) 1226} 1227 1228var MULTIPLE_NUMBER_VALIDATOR = function MULTIPLE_NUMBER_VALIDATOR(v) { 1229 v = (v || '').toString().trim() 1230 return MULTIPLE_POSITION_VALIDATOR(v, NUMBER_VALIDATOR) 1231} 1232 1233var MUTIPLE_ANGLE_VALIDATOR = function MUTIPLE_ANGLE_VALIDATOR(v) { 1234 v = (v || '').toString().trim() 1235 return MULTIPLE_POSITION_VALIDATOR(v, ANGLE_VALIDATOR) 1236} 1237 1238var ROTATE3D_VALIDATOR = function ROTATE3D_VALIDATOR(v) { 1239 v = (v || '').toString().trim() 1240 let values = v.split(/,/g) 1241 if (values && values.length > 0) { 1242 let resultValues = [] 1243 let childResult = void 0 1244 let reasonMaps = [] 1245 let length = 0 1246 if (values.length != 4) { 1247 length = 2 1248 reasonMaps.push('The number of properties is 4, value ' + values + ' is incorrect.') 1249 } else { 1250 values.forEach(function (value, index) { 1251 if (index < 3) { 1252 childResult = NUMBER_VALIDATOR(value) 1253 } else { 1254 childResult = ANGLE_VALIDATOR(value) 1255 } 1256 if (typeof childResult.value == 'number' || typeof childResult.value == 'string') { 1257 resultValues.push(childResult.value) 1258 } 1259 let check = checkReason(childResult, index.toString(), value, length) 1260 length = check.length 1261 if (check.realReason !== null) { 1262 reasonMaps.push(check.realReason) 1263 } 1264 }) 1265 } 1266 1267 return { 1268 value: length < 2 ? resultValues.join(' ') : null, 1269 reason: reasonMaps.length > 0 ? 1270 function (k, v) { 1271 return logTypes[length] + ': Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 1272 '` attribute is incorrect. \n ' + reasonMaps.join(' \n ') 1273 } : null 1274 } 1275 } 1276} 1277 1278var MULTIPLE_POSITION_VALIDATOR = function MULTIPLE_POSITION_VALIDATOR(v, validateFunction) { 1279 v = (v || '').toString().trim() 1280 let values = v.split(/,/g) 1281 if (values && values.length > 0) { 1282 let resultValues = [] 1283 let childResult = void 0 1284 let reasonMaps = [] 1285 let length = 0 1286 if (values.length > 16) { 1287 length = 2 1288 reasonMaps.push('The maximum number of properties is 16, value ' + values + ' is incorrect.') 1289 } 1290 values.forEach(function (value, index) { 1291 childResult = validateFunction(value) 1292 if (typeof childResult.value == 'number' || typeof childResult.value == 'string') { 1293 resultValues.push(childResult.value) 1294 } 1295 let check = checkReason(childResult, index.toString(), value, length) 1296 length = check.length 1297 if (check.realReason !== null) { 1298 reasonMaps.push(check.realReason) 1299 } 1300 }) 1301 return { 1302 value: length < 2 ? resultValues.join(' ') : null, 1303 reason: reasonMaps.length > 0 ? 1304 function (k, v) { 1305 return logTypes[length] + ': Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 1306 '` attribute is incorrect. \n ' + reasonMaps.join(' \n ') 1307 } : null 1308 } 1309 } 1310} 1311 1312/** 1313 * generate a function to check whether a value is in `list` 1314 * - first value: default, could be removed 1315 * - not in `list`: incorrect 1316 * 1317 * @param {Array} list 1318 * @return {function} a function(v) which returns a function to return 1319 * - value: string|null 1320 * - reason(k, v, result) 1321 */ 1322function genEnumValidator(list) { 1323 return function ENUM_VALIDATOR(v, name) { 1324 v = (v || '').toString().trim() 1325 if (v.match(ID_REGEXP)) { 1326 return {value: v} 1327 } 1328 1329 var index = list.indexOf(v) 1330 if (index > 0) { 1331 return {value: v} 1332 } 1333 if (index === 0) { 1334 return { 1335 value: v, 1336 reason: name !== 'objectFit' ? 1337 function reason(k, v, result) { 1338 return 'NOTE: Value `' + v + '` is the default value of the `' + util.camelCaseToHyphened(k) + 1339 '` attribute (the value can be removed).' 1340 } : null 1341 } 1342 } 1343 else { 1344 return { 1345 value: null, 1346 reason: function reason(k, v, result) { 1347 return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + v + 1348 '` (the supported value is `' + list.join('`|`') + '`).' 1349 } 1350 } 1351 } 1352 } 1353} 1354 1355var MASK_VALIDATOR = function MASK_VALIDATOR(v) { 1356 if (v.indexOf('url') >= 0) { 1357 return URL_VALIDATOR(v) 1358 } else { 1359 return BACKGROUND_VALIDATOR(v) 1360 } 1361} 1362 1363var BACKGROUND_VALIDATOR = function BACKGROUND_VALIDATOR(v) { 1364 v = (v || '').toString().trim() 1365 if (v.indexOf('-gradient') > 0) { 1366 let valueMatch = v.match(/(repeating-linear|linear).*?(?=\s*(repeating|linear)|$)/g) 1367 let resultValues = { 1368 values: [] 1369 } 1370 if (valueMatch && valueMatch.length) { 1371 let reasonMaps = [] 1372 let length = 0 1373 valueMatch.forEach(function (realValue) { 1374 let temp, gradientValidator 1375 if(realValue.indexOf("-gradient") >= 0){ 1376 temp = realValue.indexOf("repeating") >= 0 ? "repeatingLinearGradient": "linearGradient" 1377 gradientValidator = backgroundValidatorMap[temp] 1378 } 1379 if (typeof gradientValidator == 'function') { 1380 let validateResult = gradientValidator(realValue) 1381 if (util.isValidValue(validateResult.value)) { 1382 let jsonValue = JSON.parse(validateResult.value) 1383 resultValues.values.push(jsonValue) 1384 } 1385 let check = checkReason(validateResult, temp, realValue, length) 1386 length = check.length 1387 if (check.realReason !== null) { 1388 reasonMaps.push(check.realReason) 1389 } 1390 } else { 1391 length = 2 1392 reasonMaps.push("background type '" + realValue + "' is not supported.") 1393 } 1394 }) 1395 return { 1396 value: length < 2 ? JSON.stringify(resultValues) : null, 1397 reason: reasonMaps.length > 0 ? 1398 function (k, v) { 1399 return logTypes[length] + ': Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 1400 '` attribute is incorrect. \n ' + reasonMaps.join(' \n ') 1401 } : null 1402 } 1403 } 1404 } 1405 return { 1406 value: null, 1407 reason: function (k, v) { 1408 return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 1409 '` attribute is incorrect.' 1410 } 1411 } 1412} 1413 1414var LINEAR_GRADIENT_VALIDATOR = function LINEAR_GRADIENT_VALIDATOR(v) { 1415 v = (v || "").toString().trim() 1416 let result = { 1417 type: "", 1418 directions: ["to", "bottom"], 1419 values: [] 1420 } 1421 let valueMatch = v.match(LINE_GRADIENT_ITEM_REGEXP) 1422 if (valueMatch) { 1423 let tempResult = {} 1424 let reasonMaps = [] 1425 let length = 0 1426 let typeName = util.hyphenedToCamelCase(valueMatch[1]) 1427 result.type = typeName 1428 let matchValues = valueMatch[2].split(/,/) 1429 if (LINE_GRADIENT_DIRECTION_REGEXP.test(matchValues[0])) { 1430 let directionValidator 1431 if (LINE_GRADIENT_TO_DIRECTION_REGEXP.test(matchValues[0])) { 1432 directionValidator = backgroundValidatorMap.linearGradientDirection 1433 } else if (matchValues[0].match(ANGLE_REGEXP)) { 1434 directionValidator = backgroundValidatorMap.linearGradientAngle 1435 } 1436 if (typeof directionValidator == "function") { 1437 tempResult = directionValidator(matchValues[0]) 1438 if (util.isValidValue(tempResult.value)) { 1439 result.directions = tempResult.value.split(/\s+/) 1440 } 1441 let check = checkReason(tempResult, typeName, matchValues[0], length) 1442 length = check.length 1443 if (check.realReason !== null) { 1444 reasonMaps.push(check.realReason) 1445 } 1446 matchValues.splice(0, 1) 1447 } 1448 } 1449 if (matchValues.length > 0) { 1450 let colorStopResult = {} 1451 colorStopResult = backgroundValidatorMap.linearGradientColor(matchValues) 1452 if (util.isValidValue(colorStopResult.value)) { 1453 result.values = JSON.parse(colorStopResult.value) 1454 } 1455 let check = checkReason(colorStopResult, typeName, matchValues, length) 1456 length = check.length 1457 if (check.realReason !== null) { 1458 reasonMaps.push(check.realReason) 1459 } 1460 } else { 1461 length = 2 1462 reasonMaps.push("parameter '" + v + "' missing transition colors.") 1463 } 1464 return { 1465 value: length < 2 ? JSON.stringify(result) : null, 1466 reason: reasonMaps.length > 0 ? 1467 function (k, v) { 1468 return logTypes[length] + ': Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 1469 '` attribute is incorrect. \n ' + reasonMaps.join('\n ') 1470 }: null 1471 } 1472 } 1473 return { 1474 value: null, 1475 reason: function (k, v) { 1476 return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 1477 '` attribute is incorrect.' 1478 } 1479 } 1480} 1481 1482var ARRAY_COLOR_STOP_VALIDATOR = function ARRAY_COLOR_STOP_VALIDATOR(v) { 1483 v = (v || '').toString().trim() 1484 let values = v.match(ARRAY_COLOR_STOP_REGEXP) 1485 if (values && values.length > 1) { 1486 let resultValues = [] 1487 let reasonMaps = [] 1488 let length = 0 1489 processValueItem(v, values, resultValues, reasonMaps, length) 1490 return { 1491 value: length < 2 ? JSON.stringify(resultValues) : null, 1492 reason: reasonMaps.length > 0 ? 1493 function (k, v) { 1494 return logTypes[length] + ': Value `' + v + '` of the `' + 1495 util.camelCaseToHyphened(k) + '` attribute is incorrect. \n ' + reasonMaps.join('\n ') 1496 } : null 1497 } 1498 } 1499 return { 1500 value: null, 1501 reason: function (k, v) { 1502 return 'ERROR: The format of value `' + v + '` of the `'+ util.camelCaseToHyphened(k) + 1503 '` attribute is incorrect. Please specify at least two colors.' 1504 } 1505 } 1506} 1507 1508function processValueItem(v, values, resultValues, reasonMaps, length) { 1509 values.forEach(function (value, n) { 1510 let widthMatch = value.match(/[\s]+[-+0-9]+(px|%|vp|fp)?$/) 1511 let tempValues = [] 1512 if (widthMatch) { 1513 let matchResult = PERCENTAGE_LENGTH_VALIDATOR(widthMatch[0]) 1514 let index = value.indexOf(widthMatch[0]) 1515 value = value.substring(0, index) 1516 if (util.isValidValue(matchResult.value)) { 1517 tempValues.push(matchResult.value) 1518 } 1519 let check = checkReason(matchResult, n.toString(), widthMatch[0], length) 1520 length = check.length 1521 if (check.realReason !== null) { 1522 reasonMaps.push(check.realReason) 1523 } 1524 } 1525 if (value) { 1526 let colorResult = COLOR_VAR_VALIDATOR(value) 1527 if (util.isValidValue(colorResult.value)) { 1528 tempValues.unshift(colorResult.value) 1529 } 1530 resultValues.push(tempValues.join(' ')) 1531 let check = checkReason(colorResult, n.toString(), value, length) 1532 length = check.length 1533 if (check.realReason !== null) { 1534 reasonMaps.push(check.realReason) 1535 } 1536 } else { 1537 length = 2 1538 reasonMaps.push("parameter '" + v + "' is incorrect format.") 1539 } 1540 }) 1541} 1542 1543function checkReason(result, k, v, length) { 1544 let reason 1545 if (result.reason) { 1546 reason = result.reason(k, v, result.value) 1547 if (reason) { 1548 let reasonType = reason.match(/^([A-Z]+):/) 1549 let index 1550 if (reasonType) { 1551 index = logTypes.indexOf(reasonType[1]) 1552 if (logTypes.indexOf(reasonType[1]) > length) { 1553 length = index 1554 } 1555 reason = reason.replace(reasonType[0], '').trim() 1556 } 1557 } 1558 } 1559 return { 1560 length: length, 1561 realReason: reason ? reason : null 1562 } 1563} 1564 1565var ANGLE_VALIDATOR = function ANGLE_VALIDATOR(v) { 1566 v = (v || '').toString().trim() 1567 let match = v.match(ANGLE_REGEXP) 1568 if (match) { 1569 let unit = match[1] 1570 if (unit) { 1571 let angle = parseFloat(v) 1572 if (unit.toLowerCase() === 'rad') { 1573 return { 1574 value: Math.round(180 * angle / Math.PI) + SUPPORT_CSS_ANGLE_UNIT[0] 1575 } 1576 } else { 1577 if (SUPPORT_CSS_ANGLE_UNIT.indexOf(unit.toLowerCase()) >= 0) { 1578 return { value: v } 1579 } else { 1580 return { 1581 value: angle + SUPPORT_CSS_ANGLE_UNIT[0], 1582 reason: function(k, v) { 1583 return 'ERROR: The `' + util.camelCaseToHyphened(k) + 1584 '` attribute does not support `' + unit + '`. It only supports `' + 1585 JSON.stringify(SUPPORT_CSS_ANGLE_UNIT) + '`.' 1586 } 1587 } 1588 } 1589 } 1590 } else { 1591 return { 1592 value: parseFloat(v) + SUPPORT_CSS_ANGLE_UNIT[0], 1593 reason: function(k, v) { 1594 return 'WARNING: No unit is specified for the value `' + v + 1595 '` of the `' + util.camelCaseToHyphened(k) + '` attribute. The default unit is `' + 1596 SUPPORT_CSS_ANGLE_UNIT[0] + '`.' 1597 } 1598 } 1599 } 1600 } 1601 return { 1602 value: null, 1603 reason: function(k, v) { 1604 return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' 1605 + v + '` (only numbers are supported).' 1606 } 1607 } 1608} 1609 1610var GRADIENT_DIRECTION_VALIDATOR = function GRADIENT_DIRECTION_VALIDATOR(v) { 1611 v = (v || "").toString().trim() 1612 let values = v.split(/\s+/) 1613 let invalid = false 1614 let scaleY = ['top','bottom'] 1615 let scaleX = ['left','right'] 1616 let valueOrder = [] 1617 1618 values.forEach(function (value) { 1619 if (value === 'to') { 1620 valueOrder.push(0) 1621 } else if (scaleY.includes(value)) { 1622 valueOrder.push(1) 1623 } else if (scaleX.includes(value)) { 1624 valueOrder.push(2) 1625 } else { 1626 invalid = true 1627 } 1628 }) 1629 if (!invalid) { 1630 if (valueOrder[0] === 0 && valueOrder.length > 1 && valueOrder.length < 4 && valueOrder[1] !== 0) { 1631 if (valueOrder[2] && valueOrder[1] + valueOrder[2] !== 3) { 1632 invalid = true 1633 } 1634 } 1635 } 1636 1637 return { 1638 value: invalid ? null : v, 1639 reason: invalid ? 1640 function (k, v) { 1641 return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 1642 '` attribute is incorrect.' 1643 } : null 1644 } 1645} 1646 1647var URL_VALIDATOR = function URL_VALIDATOR(v) { 1648 v = (v || "").toString().trim() 1649 if (v.match(/^none$/i)) { 1650 return { value: "none" } 1651 } 1652 if (v.indexOf('@') >= 0) { 1653 let result 1654 // target format "@sys.media.sys_background_image" or '@sys.media.sys_background_image' 1655 let SysResourceTypeRefReg = /['"]\s*@sys\.media\.(?<resName>\w+)\s*['"]/ 1656 result = SysResourceTypeRefReg.exec(v) 1657 if (result) { 1658 const resourceName = result.groups['resName'] 1659 if (resourceName && OHOS_THEME_PROP_GROUPS[resourceName]) { 1660 return { value: "@sys.media." + OHOS_THEME_PROP_GROUPS[resourceName] } 1661 } 1662 } 1663 // target format "@app.media.customized_background_image" or '@app.media.customized_background_image' 1664 let AppResourceTypeRefReg = /['"]\s*@app\.media\.(?<resName>\w+)\s*['"]/ 1665 result = AppResourceTypeRefReg.exec(v) 1666 if (result) { 1667 const resourceName = result.groups['resName'] 1668 if (resourceName) { 1669 return { value: "@app.media." + resourceName} 1670 } 1671 } 1672 } 1673 1674 let matchValues = URL_REGEXP.exec(v) 1675 if (matchValues) { 1676 if(isLiteDevice){ 1677 return { value: matchValues[0] } 1678 }else{ 1679 if (matchValues[1].match(/^\.\.\/|^\.\//)) { 1680 return { 1681 value: matchValues[1], 1682 isRelative: true 1683 } 1684 } 1685 else { 1686 return { value: matchValues[1] } 1687 } 1688 } 1689 } 1690 else { 1691 return { 1692 value: null, 1693 reason: function (k, v) { 1694 return 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 1695 '` attribute must be none or url(...).' 1696 } 1697 } 1698 } 1699} 1700 1701var NAME_VALIDATOR = function NAME_VALIDATOR(v) { 1702 v = (v || "").toString().trim() 1703 if (v.match(NAME_REGEXP)) { 1704 return { value: v } 1705 } else { 1706 return { 1707 value: null, 1708 reason: function(k, v) { 1709 return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 1710 '` attribute is incorrect.' 1711 } 1712 } 1713 } 1714} 1715 1716var ITERATIONCOUNT_VALIDATOR = function ITERATIONCOUNT_VALIDATOR(v) { 1717 v = (v || "").toString().trim() 1718 if (v.match(INT_REGEXP)) { 1719 return { 1720 value: parseInt(v, 10) 1721 } 1722 } else if (v.match(/^infinite$/)) { 1723 return { value: -1 } 1724 } else { 1725 return { 1726 value: null, 1727 reason: function(k, v) { 1728 return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 1729 '` attribute is incorrect (only integers and infinity are supported).' 1730 } 1731 } 1732 } 1733} 1734 1735var BACKGROUND_SIZE_VALIDATOR = function BACKGROUND_SIZE_VALIDATOR(v) { 1736 v = (v || "").toString().trim() 1737 let values = v.split(/\s+/) 1738 const sizeReg = /auto|contain|cover/g 1739 if (values.length === 1) { 1740 if (/^(auto|contain|cover)$/.test(v)) { 1741 return { value: v } 1742 } else { 1743 return PERCENTAGE_LENGTH_VALIDATOR(v) 1744 } 1745 } 1746 if (values.length === 2 && !sizeReg.test(v)) { 1747 return SHORTHAND_VALIDATOR(v, PERCENTAGE_LENGTH_VALIDATOR) 1748 } 1749 return { 1750 value: null, 1751 reason: function(k, v) { 1752 return 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect.' 1753 } 1754 } 1755} 1756 1757var BACKGROUND_POSITION_VALIDATOR = function BACKGROUND_POSITION_VALIDATOR(v) { 1758 v = (v || '').toString().trim() 1759 let values = v.split(/\s+/) 1760 const positionReg = /left|right|top|bottom|center/g 1761 if (values.length === 1) { 1762 if (/^(left|right|top|bottom|center)$/.test(v)) { 1763 return { value: v } 1764 } else { 1765 return PERCENTAGE_LENGTH_VALIDATOR(v) 1766 } 1767 } 1768 if (values.length === 2) { 1769 if (!positionReg.test(v)) { 1770 return SHORTHAND_VALIDATOR(v, PERCENTAGE_LENGTH_VALIDATOR) 1771 } else { 1772 return CHECK_BACKGROUND_POSITION(v) 1773 } 1774 } 1775 return { 1776 value: null, 1777 reason: function(k, v) { 1778 return 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect.' 1779 } 1780 } 1781} 1782 1783var CHECK_BACKGROUND_POSITION = function CHECK_BACKGROUND_POSITION(v) { 1784 let values = v.split(/\s+/) 1785 let result = [] 1786 let reasons = [] 1787 let directions = [] 1788 values.forEach(function(value, index) { 1789 if (/^(left|right|top|bottom|center)$/.test(value)) { 1790 result.push(value) 1791 if (checkDirection(value)) { 1792 directions.push(checkDirection(value)) 1793 } 1794 } else { 1795 let tempResult = PERCENTAGE_LENGTH_VALIDATOR(value) 1796 if (tempResult.value) { 1797 result.push(value) 1798 if(index === 0){ 1799 directions.push('horizon') 1800 } else { 1801 directions.push('vertical') 1802 } 1803 } 1804 if (tempResult.reason) { 1805 reasons.push(tempResult.reason) 1806 } 1807 } 1808 }) 1809 if (directions.length === 2 && directions[0] === directions[1]) { 1810 reasons.push(function(k, v) { 1811 return 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect.' 1812 }) 1813 } 1814 return { 1815 value: result.length > 0 ? result.join(' ') : null, 1816 reason: reasons.length > 0 ? 1817 function(k, v) { 1818 return reasons.map(function(res) { 1819 if (typeof res === 'function') { 1820 return res(k, v) 1821 } 1822 }).join('\n') 1823 }: null 1824 } 1825} 1826 1827function checkDirection(v) { 1828 const scaleXReg = /^(left|right)$/ 1829 const scaleYReg = /^(top|bottom)$/ 1830 if (scaleXReg.test(v)) { 1831 return 'horizon' 1832 } 1833 if (scaleYReg.test(v)) { 1834 return 'vertical' 1835 } 1836 return null 1837} 1838 1839var MYLOCATION_VALIDATOR = function MYLOCATION_VALIDATOR(v) { 1840 v = (v || "").toString().trim() 1841 let values = v.match(/\((.+?)\)/g) || [] 1842 let replaceValue = null 1843 if (values.length) { 1844 for (let index = 0; index < values.length; index++) { 1845 replaceValue = values[index].replace(/\s*/g, "") 1846 v = v.replace(values[index], replaceValue); 1847 } 1848 } 1849 let realValues = v.split(/\s+/) 1850 let resultValues = [] 1851 let valuesOrder = [] 1852 let reason = null 1853 if (realValues && realValues.length <= 3) { 1854 realValues.forEach(function(realValue) { 1855 if (typeof COLOR_VAR_VALIDATOR(realValue).value == 'string') { 1856 resultValues.push(COLOR_VAR_VALIDATOR(realValue).value) 1857 valuesOrder.push(0) 1858 } else if (typeof URL_VALIDATOR(realValue).value == 'string') { 1859 resultValues.push(URL_VALIDATOR(realValue).value) 1860 valuesOrder.push(1) 1861 } else { 1862 reason = 'value' 1863 } 1864 }) 1865 let n = -1 1866 valuesOrder.forEach(function(order) { 1867 if (order >= n) { 1868 n = order 1869 } else { 1870 if (!reason) { 1871 reason = 'order' 1872 } 1873 } 1874 }) 1875 if (reason) { 1876 return { 1877 value : null, 1878 reason: function(k, v) { 1879 return reason == 'value' ? 1880 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 1881 '` attribute does not meet the inspection standards for the color or url.' : 1882 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 1883 '` attribute must be set in order(color color url).' 1884 } 1885 } 1886 } 1887 return { 1888 value: resultValues.join(" ") 1889 } 1890 } 1891 return { 1892 value: null, 1893 reason: function(k, v) { 1894 return 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is invalid.' 1895 } 1896 } 1897} 1898 1899var TRANSFORM_ORIGIN_VALIDATOR = function TRANSFORM_ORIGIN_VALIDATOR(v) { 1900 v = (v || "").toString().trim() 1901 let values = v.split(/\s+/) 1902 const positionReg = /left|right|top|bottom|center/g 1903 if (values.length == 1) { 1904 if (/^(left|right|top|bottom|center)$/.test(v)) { 1905 return { value: v } 1906 } else { 1907 return PERCENTAGE_LENGTH_VALIDATOR(v); 1908 } 1909 } 1910 if (values.length == 2) { 1911 if (!positionReg.test(v)) { 1912 return SHORTHAND_VALIDATOR(v, PERCENTAGE_LENGTH_VALIDATOR) 1913 } else { 1914 return CHECK_TRANSFORM_ORIGIN(values) 1915 } 1916 } 1917 return { 1918 value: null, 1919 reason: function (k, v) { 1920 return 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 1921 '` attribute is invalid. such as left 100px or 50% bottom.' 1922 } 1923 } 1924} 1925 1926var CHECK_TRANSFORM_ORIGIN = function CHECK_TRANSFORM_ORIGIN(values) { 1927 let result = [] 1928 let reasons = [] 1929 let directions = [] 1930 values.forEach(function (value, index) { 1931 if (/^(left|right|top|bottom|center)$/.test(value)) { 1932 result.push(value) 1933 directions.push(checkDirection(value)) 1934 } else { 1935 let tempResult = PERCENTAGE_LENGTH_VALIDATOR(value) 1936 if (tempResult.value) { 1937 result.push(value) 1938 if (index === 0) { 1939 directions.push('horizon') 1940 } else { 1941 directions.push('vertical') 1942 } 1943 } 1944 if (tempResult.reason) { 1945 reasons.push(tempResult.reason) 1946 } 1947 } 1948 }) 1949 if (directions.length != 2 || directions.length === 2 && 1950 (directions[0] === 'vertical' || directions[1] === 'horizon')) { 1951 reasons.push(function (k, v) { 1952 return 'ERROR: Value `' + v + '` of the `' + util.camelCaseToHyphened(k) + '` attribute is incorrect.' 1953 }) 1954 } 1955 return { 1956 value: result.length > 0 ? result.join(' ') : null, 1957 reason: reasons.length > 0 ? 1958 function (k, v) { 1959 return reasons.map(function (res) { 1960 if (typeof res === 'function') { 1961 return res(k, v) 1962 } 1963 }).join('\n') 1964 } : null 1965 } 1966} 1967 1968var GRID_VALIDATOR = function GRID_VALIDATOR(v) { 1969 v = (v || '').toString().trim() 1970 if (v == 'auto' || v == 'auto-fill') { 1971 return { value: v } 1972 } else { 1973 return LENGTH(v, SUPPORT_CSS_GRID_UNIT) 1974 } 1975} 1976 1977var GRID_TEMPLATE_VALIDATOR = function GRID_TEMPLATE_VALIDATOR(v) { 1978 v = (v || '').toString().trim() 1979 if (v.match(/^repeat/)) { 1980 let str = [] 1981 if (v.match(/auto-fill/)) { 1982 let match = v.match(/^repeat\((.+),(.+)\)/) 1983 str.push(match[1].trim(), match[2].trim()) 1984 return GRID_TEMPLATE_VALIDATOR(str.join(' ')) 1985 } else { 1986 let match = v.match(/^repeat\((\d+),(.+)\)/) 1987 if (match[1] && match[2]) { 1988 let n = match[1] 1989 while (n > 0) { 1990 str.push(match[2].trim()) 1991 n-- 1992 } 1993 return GRID_TEMPLATE_VALIDATOR(str.join(' ')) 1994 } 1995 else { 1996 return { 1997 value: null, 1998 reason: function reason(k, v, result) { 1999 return 'ERROR: The `' + util.camelCaseToHyphened(k) + '` attribute does not support value `' + v + '`.' 2000 } 2001 } 2002 } 2003 } 2004 } 2005 else { 2006 let value = [] 2007 let reason = [] 2008 let results = v.split(/\s+/).map(GRID_VALIDATOR) 2009 for (let i = 0; i < results.length; ++i) { 2010 let res = results[i] 2011 if (!res.value) { 2012 value = null 2013 reason = res.reason 2014 break 2015 } 2016 value.push(res.value) 2017 if (res.reason) { 2018 reason.push(res.reason) 2019 } 2020 } 2021 2022 if (!value) { 2023 return { 2024 value: value, 2025 reason: reason 2026 } 2027 } else { 2028 return { 2029 value: value.join(' '), 2030 reason: reason.length > 0 ? function(k, v, result) { 2031 return reason.map(function (res) { 2032 if (typeof res === 'function') { 2033 return res(k, v, result) 2034 } 2035 }).join('\n') 2036 } : null 2037 } 2038 } 2039 } 2040} 2041 2042var DATE_VALIDATOR = function DATE_VALIDATOR(v) { 2043 v = (v || '').toString().trim() 2044 if (DATE_REGEXP.test(v)) { 2045 return { value: v } 2046 } else { 2047 return { 2048 value: null, 2049 reason:function (k, v, result) { 2050 return 'ERROR: The format of value `' + v + '` of the `' + 2051 util.camelCaseToHyphened(k) + '` attribute is incorrect.' 2052 } 2053 } 2054 } 2055} 2056 2057var FILTER_VALIDATOR = function FILTER_VALIDATOR(v) { 2058 v = (v || '').toString().trim().replace(/\s*/g, '') 2059 if (FILTER_REGEXP.test(v)) { 2060 return { value: v } 2061 } else { 2062 return { 2063 value: null, 2064 reason:function (k, v, result) { 2065 return 'ERROR: The format of value `' + v + '` of the `' + 2066 util.camelCaseToHyphened(k) + '` attribute is incorrect.' 2067 } 2068 } 2069 } 2070} 2071 2072var FILTER_PERCENTAGE_VALIDATOR = function FILTER_PERCENTAGE_VALIDATOR(v) { 2073 v = (v || '').toString().trim().replace(/\s*,\s*/g, " ") 2074 if (FILTER_PERCENTAGE_REGEXP.test(v)) { 2075 return { value: v } 2076 } 2077 if (FILTER_STYLE_REGEXP.test(v)) { 2078 const values = v.trim().split(/\s+/) 2079 if(values[1] && values.length === 2){ 2080 const blurStyleValidator = genEnumValidator(['small_light', 'medium_light', 'large_light', 2081 'xlarge_light', 'small_dark', 'medium_dark', 'large_dark', 'xlarge_dark']) 2082 const blurStyleResult = blurStyleValidator(values[1]) 2083 if(util.isValidValue(blurStyleResult.value)){ 2084 return { value: v } 2085 } 2086 let reasonMaps = []; 2087 let length = 0; 2088 let check = checkReason(blurStyleResult, 'window-filter', values[1], length) 2089 if(check.realReason !== null) { 2090 reasonMaps.push(check.realReason) 2091 } 2092 return { 2093 value: check.length < 2 ? JSON.stringify(blurStyleResult.value) : null, 2094 reason: function(k, v) { 2095 return 'ERROR: ' + reasonMaps 2096 } 2097 } 2098 } 2099 } 2100 return { 2101 value: null, 2102 reason:function (k, v, result) { 2103 return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k) + 2104 '` attribute is incorrect.' 2105 } 2106 } 2107} 2108 2109var BORDER_IMAGE_VALIDATOR = function BORDER_IMAGE_VALIDATOR(v) { 2110 var regexp = /(repeating-linear|linear).*?(?=\s*(repeating|linear)|$)/g; 2111 if (regexp.test(v)) { 2112 return BORDER_IMAGE_GRADIENT_VALIDATOR(v); 2113 } else { 2114 return BORDER_IMAGE_URL_VALIDATOR(v); 2115 } 2116} 2117 2118var BORDER_IMAGE_URL_VALIDATOR = function BORDER_IMAGE_URL_VALIDATOR(v) { 2119 let base = { 2120 values: [] 2121 }; 2122 let value = { 2123 url: "", 2124 repeat: "" 2125 }; 2126 var URL_REGEXP_FIRST = /^url\(\s*['"]?\s*([^()]+?)\s*['"]?\s*\)(.*)/; 2127 var regexpFirst = /(stretch|round|repeat|space)$/; 2128 var URL_REGEXP_SECOND = /^(.*)(stretch|round|repeat|space)$/; 2129 let result; 2130 result = URL_REGEXP_FIRST.exec(v); 2131 if (regexpFirst.test(result[2])) { 2132 let res = URL_REGEXP_SECOND.exec(result[2]); 2133 value = BORDER_IMAGE_NOL(res[1]); 2134 value.repeat = res[2]; 2135 } else { 2136 var reg = /px|%/; 2137 if (reg.test(result[2])) { 2138 value = BORDER_IMAGE_NOL(result[2]); 2139 } 2140 } 2141 value.url = result[1]; 2142 base.values.push(value); 2143 return { 2144 value: JSON.stringify(base) 2145 }; 2146} 2147 2148var BORDER_IMAGE_NOL = function BORDER_IMAGE_NOL(v) { 2149 let value = { 2150 url: "", 2151 repeat: "" 2152 }; 2153 var reg = /px|%/; 2154 if (!reg.test(v)) { 2155 return value; 2156 } 2157 let num = v.split(/\//); 2158 switch (num.length) { 2159 case 1: 2160 value.slice = BORDER_IMAGE_SPLIT(num[0]); 2161 break; 2162 case 2: 2163 value.slice = BORDER_IMAGE_SPLIT(num[0]); 2164 value.width = BORDER_IMAGE_SPLIT(num[1]); 2165 break; 2166 case 3: 2167 value.slice = BORDER_IMAGE_SPLIT(num[0]); 2168 value.width = BORDER_IMAGE_SPLIT(num[1]); 2169 value.outset = BORDER_IMAGE_SPLIT(num[2]); 2170 break; 2171 } 2172 return value; 2173} 2174 2175var BORDER_IMAGE_SPLIT = function BORDER_IMAGE_SPLIT(v) { 2176 const NUM_REGEXP = SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR(v); 2177 let result = []; 2178 const value = NUM_REGEXP.value.split(/\s/); 2179 value.forEach(element => { 2180 result.push(element); 2181 }); 2182 return result; 2183} 2184 2185var BORDER_IMAGE_GRADIENT_VALIDATOR = function BORDER_IMAGE_GRADIENT_VALIDATOR(v) { 2186 v = (v || "").toString().trim() 2187 var BORDER_IMAGE_GRADIENT_ITEM_REGEXP = /^([0-9a-zA-Z-]+)\((.*)\)(.*)/; 2188 let base = { 2189 values: [] 2190 } 2191 let valueMatch = v.match(BORDER_IMAGE_GRADIENT_ITEM_REGEXP) 2192 if (valueMatch) { 2193 const gradientStr = valueMatch[1].toString() + '(' + valueMatch[2].toString() + ')'; 2194 const gradient = LINEAR_GRADIENT_VALIDATOR(gradientStr); 2195 let value = {}; 2196 if (util.isValidValue(gradient.value)) { 2197 value = JSON.parse(gradient.value) 2198 } 2199 var reg = /px|%/; 2200 if (valueMatch[3].match(reg)) { 2201 value.slice = BORDER_IMAGE_SPLIT(valueMatch[3]); 2202 } 2203 base.values.push(value); 2204 return { 2205 value: JSON.stringify(base), 2206 reason: gradient.reason 2207 } 2208 } 2209 return { 2210 value: null, 2211 reason: function(k, v) { 2212 return 'ERROR: The format of value `' + v + '` of the `' + util.camelCaseToHyphened(k) 2213 + '` attribute is incorrect.' 2214 } 2215 } 2216} 2217 2218var Color_Picker_VALIDATOR = function Color_Picker_VALIDATOR(v) { 2219 v = (v || "").toString().trim() 2220 let num = v.split(/\//); 2221 let base = { 2222 cValues: [] 2223 } 2224 num.forEach(element => { 2225 base.cValues.push(COLOR_VAR_VALIDATOR(element).value); 2226 }); 2227 return { 2228 value: JSON.stringify(base) 2229 } 2230} 2231 2232var RICH_PROP_NAME_GROUPS = { 2233 boxModel: { 2234 width: PERCENTAGE_LENGTH_VALIDATOR, 2235 height: PERCENTAGE_LENGTH_VALIDATOR, 2236 overflow: genEnumValidator(['auto', 'hidden','scroll','visible']), 2237 padding: SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR, 2238 paddingLeft: PERCENTAGE_LENGTH_VALIDATOR, 2239 paddingRight: PERCENTAGE_LENGTH_VALIDATOR, 2240 paddingTop: PERCENTAGE_LENGTH_VALIDATOR, 2241 paddingBottom: PERCENTAGE_LENGTH_VALIDATOR, 2242 paddingStart: PERCENTAGE_LENGTH_VALIDATOR, 2243 paddingEnd: PERCENTAGE_LENGTH_VALIDATOR, 2244 margin: SHORTHAND_AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2245 marginLeft: AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2246 marginRight: AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2247 marginTop: AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2248 marginBottom: AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2249 marginStart: PERCENTAGE_LENGTH_VALIDATOR, 2250 marginEnd: PERCENTAGE_LENGTH_VALIDATOR, 2251 placeholderColor: COLOR_VAR_VALIDATOR, 2252 selectedColor: COLOR_VAR_VALIDATOR, 2253 caretColor: COLOR_VAR_VALIDATOR, 2254 strokeWidth: LENGTH_VALIDATOR, 2255 progressColor: COLOR_VAR_VALIDATOR, 2256 slideWidth: LENGTH_VALIDATOR, 2257 slideMargin: LENGTH_VALIDATOR, 2258 resizeMode: genEnumValidator(['cover', 'contain', 'stretch', 'center']), 2259 columns: NUMBER_VALIDATOR, 2260 columnSpan: NUMBER_VALIDATOR, 2261 maskColor: COLOR_VAR_VALIDATOR, 2262 mylocation: MYLOCATION_VALIDATOR, 2263 mylocationFillColor: COLOR_VAR_VALIDATOR, 2264 mylocationStrokeColor: COLOR_VAR_VALIDATOR, 2265 mylocationIconPath: URL_VALIDATOR, 2266 displayIndex: NUMBER_VALIDATOR, 2267 aspectRatio: NUMBER_VALIDATOR, 2268 minWidth: PERCENTAGE_LENGTH_VALIDATOR, 2269 minHeight: PERCENTAGE_LENGTH_VALIDATOR, 2270 maxWidth: PERCENTAGE_LENGTH_VALIDATOR, 2271 maxHeight: PERCENTAGE_LENGTH_VALIDATOR, 2272 flexWeight: NUMBER_VALIDATOR, 2273 boxShadow: BOX_SHADOW_VALIDATOR, 2274 boxShadowH: LENGTH_VALIDATOR, 2275 boxShadowV: LENGTH_VALIDATOR, 2276 boxShadowBlur: LENGTH_VALIDATOR, 2277 boxShadowSpread: LENGTH_VALIDATOR, 2278 boxShadowColor: COLOR_VAR_VALIDATOR, 2279 filter: FILTER_VALIDATOR, 2280 backdropFilter: FILTER_VALIDATOR, 2281 windowFilter: FILTER_PERCENTAGE_VALIDATOR, 2282 transitionEffect: genEnumValidator(['unfold', 'none']) 2283 }, 2284 div: { 2285 gridTemplateColumns: GRID_TEMPLATE_VALIDATOR, 2286 gridTemplateRows: GRID_TEMPLATE_VALIDATOR, 2287 gridGap: LENGTH_VALIDATOR, 2288 gridColumnsGap: LENGTH_VALIDATOR, 2289 gridRowsGap: LENGTH_VALIDATOR, 2290 gridRowStart: NUMBER_VALIDATOR, 2291 gridRowEnd: NUMBER_VALIDATOR, 2292 gridColumnStart: NUMBER_VALIDATOR, 2293 gridColumnEnd: NUMBER_VALIDATOR, 2294 gridAutoFlow: genEnumValidator(['row', 'column']) 2295 }, 2296 border: { 2297 border: BORDER_VALIDATOR, 2298 borderWidth: SHORTHAND_LENGTH_VALIDATOR, 2299 borderLeftWidth: LENGTH_VALIDATOR, 2300 borderTopWidth: LENGTH_VALIDATOR, 2301 borderRightWidth: LENGTH_VALIDATOR, 2302 borderBottomWidth: LENGTH_VALIDATOR, 2303 borderColor: SHORTHAND_COLOR_VALIDATOR, 2304 borderLeftColor: COLOR_VAR_VALIDATOR, 2305 borderTopColor: COLOR_VAR_VALIDATOR, 2306 borderRightColor: COLOR_VAR_VALIDATOR, 2307 borderBottomColor: COLOR_VAR_VALIDATOR, 2308 borderStyle: SHORTHAND_STYLE_VALIDATOR, 2309 borderTopStyle: STYLE_VALIDATOR, 2310 borderRightStyle: STYLE_VALIDATOR, 2311 borderBottomStyle: STYLE_VALIDATOR, 2312 borderLeftStyle: STYLE_VALIDATOR, 2313 borderRadius: PERCENTAGE_LENGTH_VALIDATOR, 2314 borderBottomLeftRadius: PERCENTAGE_LENGTH_VALIDATOR, 2315 borderBottomRightRadius: PERCENTAGE_LENGTH_VALIDATOR, 2316 borderTopLeftRadius: PERCENTAGE_LENGTH_VALIDATOR, 2317 borderTopRightRadius: PERCENTAGE_LENGTH_VALIDATOR, 2318 borderLeft: BORDER_VALIDATOR, 2319 borderRight: BORDER_VALIDATOR, 2320 borderTop: BORDER_VALIDATOR, 2321 borderBottom: BORDER_VALIDATOR, 2322 borderImage: BORDER_IMAGE_VALIDATOR, 2323 borderImageSource: URL_VALIDATOR, 2324 borderImageOutset: SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR, 2325 borderImageSlice: SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR, 2326 borderImageWidth: SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR, 2327 borderImageRepeat: genEnumValidator(['stretch', 'round', 'repeat', 'space']) 2328 }, 2329 indicator: { 2330 indicatorSize: LENGTH_VALIDATOR, 2331 indicatorTop: PERCENTAGE_LENGTH_VALIDATOR, 2332 indicatorRight: PERCENTAGE_LENGTH_VALIDATOR, 2333 indicatorBottom: PERCENTAGE_LENGTH_VALIDATOR, 2334 indicatorLeft: PERCENTAGE_LENGTH_VALIDATOR, 2335 indicatorColor: COLOR_VAR_VALIDATOR, 2336 indicatorSelectedColor: COLOR_VAR_VALIDATOR 2337 }, 2338 animation: { 2339 animationDuration: TIME_VALIDATOR, 2340 animationDelay: TIME_VALIDATOR, 2341 animationName: NAME_VALIDATOR, 2342 animationTimingFunction: TRANSITION_TIMING_FUNCTION_VALIDATOR, 2343 animationIterationCount: ITERATIONCOUNT_VALIDATOR, 2344 animationFillMode: genEnumValidator(['none', 'forwards', 'backwards', 'both']), 2345 animationPlayState: genEnumValidator(['running', 'paused']), 2346 animationDirection: genEnumValidator(['normal', 'reverse', 'alternate', 'alternate-reverse']), 2347 animation: ANIMATION_VALIDATOR, 2348 }, 2349 flexbox: { 2350 flex: genEnumValidator(['none', 'auto', 'initial']), 2351 flexWrap: genEnumValidator(['nowrap', 'wrap']), 2352 flexGrow: NUMBER_VALIDATOR, 2353 flexShrink: NUMBER_VALIDATOR, 2354 flexBasis: LENGTH_VALIDATOR, 2355 flexDirection: genEnumValidator(['row', 'column']), 2356 justifyContent: genEnumValidator(['flex-start', 'flex-end', 'center', 'space-between', 2357 'space-around', 'space-evenly']), 2358 alignItems: genEnumValidator(['stretch', 'flex-start', 'flex-end', 'center', 'baseline']), 2359 alignContent: genEnumValidator(['stretch', 'flex-start', 'flex-end', 'center', 'space-between', 'space-around']), 2360 alignSelf: genEnumValidator(["auto", "flex-start", "flex-end", "center", "baseline", "stretch"]) 2361 }, 2362 position: { 2363 position: genEnumValidator(['relative', 'fixed', 'absolute']), 2364 top: PERCENTAGE_LENGTH_VALIDATOR, 2365 bottom: PERCENTAGE_LENGTH_VALIDATOR, 2366 left: PERCENTAGE_LENGTH_VALIDATOR, 2367 right: PERCENTAGE_LENGTH_VALIDATOR, 2368 zIndex: INTEGER_VALIDATOR 2369 }, 2370 common: { 2371 opacity: NUMBER_VALIDATOR, 2372 background: BACKGROUND_VALIDATOR, 2373 backgroundColor: COLOR_VAR_VALIDATOR, 2374 backgroundImage: URL_VALIDATOR, 2375 backgroundRepeat: genEnumValidator(['repeat', 'no-repeat', 'repeat-x', 'repeat-y']), 2376 visibility: genEnumValidator(['visible', 'hidden']), 2377 objectFit: genEnumValidator(['cover', 'fill', 'contain', 'none', 'scale-down']), 2378 backgroundSize: BACKGROUND_SIZE_VALIDATOR, 2379 backgroundPosition: BACKGROUND_POSITION_VALIDATOR, 2380 display: genEnumValidator(['flex', 'none', 'grid']), 2381 imageFill: COLOR_VAR_VALIDATOR, 2382 maskImage: MASK_VALIDATOR, 2383 maskPosition: BACKGROUND_POSITION_VALIDATOR, 2384 maskSize: BACKGROUND_SIZE_VALIDATOR 2385 }, 2386 text: { 2387 lines: INTEGER_VALIDATOR, 2388 color: COLOR_VAR_VALIDATOR, 2389 fontSize: LENGTH_VALIDATOR, 2390 fontStyle: genEnumValidator(['normal', 'italic']), 2391 fontFamily: ANYTHING_VALIDATOR, 2392 fontWeight: genEnumValidator(['normal', 'lighter', 'bold', 'bolder', "medium", "regular", 2393 '100', '200', '300', '400', '500', '600', '700', '800', '900']), 2394 textDecoration: genEnumValidator(['none', 'underline', 'line-through']), 2395 textAlign: genEnumValidator(['start', 'end', 'left', 'center', 'right']), 2396 textOverflow: genEnumValidator(['clip', 'ellipsis']), 2397 textIndent: TEXT_INDENT_VALIDATOR, 2398 lineHeight: TEXT_LINE_HEIGHT_VALIDATOR, 2399 letterSpacing: LENGTH_VALIDATOR, 2400 minLines: NUMBER_VALIDATOR, 2401 maxLines: ANYTHING_VALIDATOR, 2402 minFontSize: LENGTH_VALIDATOR, 2403 maxFontSize: LENGTH_VALIDATOR, 2404 fontSizeStep: LENGTH_VALIDATOR, 2405 preferFontSizes: ARRAY_LENGTH_VALIDATOR, 2406 adaptHeight: genEnumValidator(['true', 'false']), 2407 allowScale: genEnumValidator(['true', 'false']), 2408 fontVariant: ANYTHING_VALIDATOR, 2409 id: ANYTHING_VALIDATOR, 2410 x: PERCENTAGE_LENGTH_VALIDATOR, 2411 y: PERCENTAGE_LENGTH_VALIDATOR, 2412 dx: PERCENTAGE_LENGTH_VALIDATOR, 2413 dy: PERCENTAGE_LENGTH_VALIDATOR, 2414 rotate: NUMBER_VALIDATOR, 2415 fill: COLOR_VAR_VALIDATOR, 2416 fillOpacity: NUMBER_VALIDATOR, 2417 stroke: COLOR_VAR_VALIDATOR, 2418 strokeOpacity: NUMBER_VALIDATOR, 2419 strokeWidth: LENGTH_VALIDATOR, 2420 fontFeatureSettings: ANYTHING_VALIDATOR, 2421 textDecorationColor: COLOR_VAR_VALIDATOR 2422 }, 2423 calendar: { 2424 boundaryColOffset: LENGTH_VALIDATOR, 2425 boundaryRowOffset: LENGTH_VALIDATOR, 2426 colSpace: LENGTH_VALIDATOR, 2427 dailyFiveRowSpace: LENGTH_VALIDATOR, 2428 dayColor: COLOR_VAR_VALIDATOR, 2429 dayFontSize: LENGTH_VALIDATOR, 2430 dayHeight: LENGTH_VALIDATOR, 2431 dayWidth: LENGTH_VALIDATOR, 2432 focusedAreaBackgroundColor: COLOR_VAR_VALIDATOR, 2433 focusedAreaRadius: LENGTH_VALIDATOR, 2434 focusedDayColor: COLOR_VAR_VALIDATOR, 2435 focusedLunarColor: COLOR_VAR_VALIDATOR, 2436 gregorianCalendarHeight: LENGTH_VALIDATOR, 2437 lunarColor: COLOR_VAR_VALIDATOR, 2438 lunarDayFontSize: LENGTH_VALIDATOR, 2439 lunarDayYAxisOffset: LENGTH_VALIDATOR, 2440 lunarHeight: LENGTH_VALIDATOR, 2441 markLunarColor: COLOR_VAR_VALIDATOR, 2442 nonCurrentMonthDayColor: COLOR_VAR_VALIDATOR, 2443 nonCurrentMonthLunarColor: COLOR_VAR_VALIDATOR, 2444 nonCurrentMonthOffDayMarkColor: COLOR_VAR_VALIDATOR, 2445 nonCurrentMonthWorkDayMarkColor: COLOR_VAR_VALIDATOR, 2446 offDayMarkColor: COLOR_VAR_VALIDATOR, 2447 offDayMarkSize: LENGTH_VALIDATOR, 2448 scheduleMarkerRadius: LENGTH_VALIDATOR, 2449 scheduleMarkerXAxisOffset: LENGTH_VALIDATOR, 2450 scheduleMarkerYAxisOffset: LENGTH_VALIDATOR, 2451 underscoreLength: LENGTH_VALIDATOR, 2452 underscoreWidth: LENGTH_VALIDATOR, 2453 underscoreXAxisOffset: LENGTH_VALIDATOR, 2454 underscoreYAxisOffset: LENGTH_VALIDATOR, 2455 weekAndDayRowSpace: LENGTH_VALIDATOR, 2456 weekColor: COLOR_VAR_VALIDATOR, 2457 weekFontSize: LENGTH_VALIDATOR, 2458 weekHeight: LENGTH_VALIDATOR, 2459 weekWidth: LENGTH_VALIDATOR, 2460 weekendDayColor: COLOR_VAR_VALIDATOR, 2461 weekendLunarColor: COLOR_VAR_VALIDATOR, 2462 workDayMarkColor: COLOR_VAR_VALIDATOR, 2463 workDayMarkSize: LENGTH_VALIDATOR, 2464 workStateHorizontalMovingDistance: LENGTH_VALIDATOR, 2465 workStateVerticalMovingDistance: LENGTH_VALIDATOR, 2466 workStateWidth: LENGTH_VALIDATOR 2467 }, 2468 rating: { 2469 starBackground: URL_VALIDATOR, 2470 starForeground: URL_VALIDATOR, 2471 starSecondary: URL_VALIDATOR, 2472 rtlFlip: genEnumValidator(['true', 'false']) 2473 }, 2474 transition: { 2475 transitionProperty: TRANSITION_PROPERTY_VALIDATOR, 2476 transitionDuration: TRANSITION_INTERVAL_VALIDATOR, 2477 transitionDelay: TRANSITION_INTERVAL_VALIDATOR, 2478 transitionEnter: NAME_VALIDATOR, 2479 transitionExit: NAME_VALIDATOR, 2480 transitionDuration: TIME_VALIDATOR, 2481 transitionTimingFunction: TRANSITION_TIMING_FUNCTION_VALIDATOR 2482 }, 2483 transform: { 2484 transform: TRANSFORM_VALIDATOR, 2485 transformOrigin: TRANSFORM_ORIGIN_VALIDATOR 2486 }, 2487 customized: { 2488 itemSize: LENGTH_VALIDATOR, 2489 itemColor: COLOR_VAR_VALIDATOR, 2490 itemSelectedColor: COLOR_VAR_VALIDATOR, 2491 textColor: COLOR_VAR_VALIDATOR, 2492 timeColor: COLOR_VAR_VALIDATOR, 2493 textHighlightColor: COLOR_VAR_VALIDATOR 2494 }, 2495 list: { 2496 itemExtent: PERCENTAGE_LENGTH_VALIDATOR, 2497 fadeColor: COLOR_VAR_VALIDATOR, 2498 dividerColor: COLOR_VAR_VALIDATOR, 2499 dividerHeight: LENGTH_VALIDATOR, 2500 dividerLength: LENGTH_VALIDATOR, 2501 dividerOrigin: LENGTH_VALIDATOR, 2502 scrollbarColor: COLOR_VALIDATOR, 2503 scrollbarWidth: LENGTH_VALIDATOR, 2504 scrollbarOffset: ARRAY_LENGTH_VALIDATOR 2505 }, 2506 progress: { 2507 secondaryColor: COLOR_VAR_VALIDATOR, 2508 scaleWidth: LENGTH_VALIDATOR, 2509 scaleNumber: NUMBER_VALIDATOR, 2510 startAngle: ANGLE_VALIDATOR, 2511 totalAngle: ANGLE_VALIDATOR, 2512 centerX: LENGTH_VALIDATOR, 2513 centerY: LENGTH_VALIDATOR, 2514 radius: LENGTH_VALIDATOR, 2515 direction: genEnumValidator(['start-to-end', 'end-to-start']), 2516 sections: NAME_VALIDATOR, 2517 colors: ARRAY_COLOR_VALIDATOR, 2518 weights: ARRAY_NUMBER_VALIDATOR 2519 }, 2520 navigation: { 2521 titleColor: COLOR_VAR_VALIDATOR, 2522 subtitleColor: COLOR_VAR_VALIDATOR 2523 }, 2524 button: { 2525 iconWidth: LENGTH_VALIDATOR, 2526 iconHeight: LENGTH_VALIDATOR 2527 }, 2528 switch: { 2529 textonColor: COLOR_VAR_VALIDATOR, 2530 textoffColor: COLOR_VAR_VALIDATOR, 2531 textPadding: LENGTH_VALIDATOR 2532 }, 2533 share: { 2534 sharedTransitionEffect: genEnumValidator(['exchange', 'static']), 2535 sharedTransitionName: NAME_VALIDATOR, 2536 sharedTransitionTimingFunction: TRANSITION_TIMING_FUNCTION_VALIDATOR 2537 }, 2538 image: { 2539 matchTextDirection: genEnumValidator(['false', 'true']), 2540 fitOriginalSize: genEnumValidator(['false', 'true']), 2541 }, 2542 divider: { 2543 lineCap: genEnumValidator(['butt', 'square', 'round']) 2544 }, 2545 picker: { 2546 columnHeight: LENGTH_VALIDATOR 2547 }, 2548 pickerView: { 2549 selectedFontSize: LENGTH_VALIDATOR, 2550 selectedFontFamily: ANYTHING_VALIDATOR, 2551 focusColor: COLOR_VAR_VALIDATOR, 2552 focusFontSize: LENGTH_VALIDATOR, 2553 focusFontFamily: ANYTHING_VALIDATOR, 2554 disappearFontSize: LENGTH_VALIDATOR, 2555 disappearColor: COLOR_VAR_VALIDATOR 2556 }, 2557 colorpicker: { 2558 colorPickerColor: Color_Picker_VALIDATOR 2559 }, 2560 colorpickerView: { 2561 colorPickerColor: Color_Picker_VALIDATOR 2562 }, 2563 slider: { 2564 blockColor: COLOR_VAR_VALIDATOR, 2565 }, 2566 badge: { 2567 badgeColor: COLOR_VAR_VALIDATOR, 2568 badgeSize: LENGTH_VALIDATOR 2569 }, 2570 ellipse: { 2571 fill: COLOR_VAR_VALIDATOR, 2572 fillOpacity: NUMBER_VALIDATOR, 2573 fillRule: genEnumValidator(['nonzero', 'evenodd']), 2574 opacity: NUMBER_VALIDATOR, 2575 stroke: COLOR_VAR_VALIDATOR, 2576 strokeDasharray: ANYTHING_VALIDATOR, 2577 strokeDashoffset: LENGTH_VALIDATOR, 2578 strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']), 2579 strokeLinecap: genEnumValidator(['butt', 'round', 'square']), 2580 strokeMiterlimit: NUMBER_VALIDATOR, 2581 strokeOpacity: NUMBER_VALIDATOR, 2582 strokeWidth: LENGTH_VALIDATOR, 2583 transform: TRANSFORM_VALIDATOR, 2584 id: ANYTHING_VALIDATOR, 2585 cx: PERCENTAGE_LENGTH_VALIDATOR, 2586 cy: PERCENTAGE_LENGTH_VALIDATOR, 2587 rx: PERCENTAGE_LENGTH_VALIDATOR, 2588 ry: PERCENTAGE_LENGTH_VALIDATOR 2589 }, 2590 rect: { 2591 id: ANYTHING_VALIDATOR, 2592 fill: COLOR_VAR_VALIDATOR, 2593 fillOpacity: NUMBER_VALIDATOR, 2594 fillRule: genEnumValidator(['nonzero', 'evenodd']), 2595 opacity: NUMBER_VALIDATOR, 2596 strokeDasharray: ANYTHING_VALIDATOR, 2597 strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']), 2598 strokeLinecap: genEnumValidator(['butt', 'round', 'square']), 2599 strokeMiterlimit: NUMBER_VALIDATOR, 2600 strokeOpacity: NUMBER_VALIDATOR, 2601 strokeWidth: LENGTH_VALIDATOR, 2602 transform: TRANSFORM_VALIDATOR, 2603 width: PERCENTAGE_LENGTH_VALIDATOR, 2604 height: PERCENTAGE_LENGTH_VALIDATOR, 2605 x: PERCENTAGE_LENGTH_VALIDATOR, 2606 y: PERCENTAGE_LENGTH_VALIDATOR, 2607 rx: PERCENTAGE_LENGTH_VALIDATOR, 2608 ry: PERCENTAGE_LENGTH_VALIDATOR, 2609 stroke: COLOR_VAR_VALIDATOR, 2610 strokeDashoffset: LENGTH_VALIDATOR 2611 }, 2612 circle: { 2613 fill: COLOR_VAR_VALIDATOR, 2614 fillOpacity: NUMBER_VALIDATOR, 2615 fillRule: genEnumValidator(['nonzero', 'evenodd']), 2616 opacity: NUMBER_VALIDATOR, 2617 stroke: COLOR_VAR_VALIDATOR, 2618 strokeDasharray: ANYTHING_VALIDATOR, 2619 strokeDashoffset: LENGTH_VALIDATOR, 2620 strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']), 2621 strokeLinecap: genEnumValidator(['butt', 'round', 'square']), 2622 strokeMiterlimit: NUMBER_VALIDATOR, 2623 strokeOpacity: NUMBER_VALIDATOR, 2624 strokeWidth: LENGTH_VALIDATOR, 2625 transform: TRANSFORM_VALIDATOR, 2626 id: ANYTHING_VALIDATOR, 2627 cx: PERCENTAGE_LENGTH_VALIDATOR, 2628 cy: PERCENTAGE_LENGTH_VALIDATOR, 2629 r: PERCENTAGE_LENGTH_VALIDATOR 2630 }, 2631 path: { 2632 fillOpacity: NUMBER_VALIDATOR, 2633 fillRule: genEnumValidator(['nonzero', 'evenodd']), 2634 opacity: NUMBER_VALIDATOR, 2635 strokeDashoffset: LENGTH_VALIDATOR, 2636 strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']), 2637 strokeLinecap: genEnumValidator(['butt', 'round', 'square']), 2638 strokeMiterlimit: NUMBER_VALIDATOR, 2639 strokeOpacity: NUMBER_VALIDATOR, 2640 strokeWidth: LENGTH_VALIDATOR, 2641 transform: TRANSFORM_VALIDATOR, 2642 id: ANYTHING_VALIDATOR, 2643 d: ANYTHING_VALIDATOR, 2644 fill: COLOR_VAR_VALIDATOR, 2645 strokeDasharray: ANYTHING_VALIDATOR, 2646 stroke: COLOR_VAR_VALIDATOR 2647 }, 2648 svg: { 2649 fill: COLOR_VAR_VALIDATOR, 2650 fillOpacity: NUMBER_VALIDATOR, 2651 fillRule: genEnumValidator(['nonzero', 'evenodd']), 2652 opacity: NUMBER_VALIDATOR, 2653 stroke: COLOR_VAR_VALIDATOR, 2654 strokeDasharray: ANYTHING_VALIDATOR, 2655 strokeDashoffset: LENGTH_VALIDATOR, 2656 strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']), 2657 strokeLinecap: genEnumValidator(['butt', 'round', 'square']), 2658 strokeMiterlimit: NUMBER_VALIDATOR, 2659 strokeOpacity: NUMBER_VALIDATOR, 2660 strokeWidth: LENGTH_VALIDATOR, 2661 transform: TRANSFORM_VALIDATOR, 2662 id: ANYTHING_VALIDATOR, 2663 width: PERCENTAGE_LENGTH_VALIDATOR, 2664 height: PERCENTAGE_LENGTH_VALIDATOR, 2665 x: PERCENTAGE_LENGTH_VALIDATOR, 2666 y: PERCENTAGE_LENGTH_VALIDATOR, 2667 viewbox: ANYTHING_VALIDATOR 2668 }, 2669 polygon: { 2670 fill: COLOR_VAR_VALIDATOR, 2671 fillOpacity: NUMBER_VALIDATOR, 2672 opacity: NUMBER_VALIDATOR, 2673 stroke: COLOR_VAR_VALIDATOR, 2674 strokeDasharray: ANYTHING_VALIDATOR, 2675 strokeDashoffset: LENGTH_VALIDATOR, 2676 strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']), 2677 strokeLinecap: genEnumValidator(['butt', 'round', 'square']), 2678 strokeMiterlimit: NUMBER_VALIDATOR, 2679 strokeOpacity: NUMBER_VALIDATOR, 2680 strokeWidth: LENGTH_VALIDATOR, 2681 transform: TRANSFORM_VALIDATOR, 2682 id: ANYTHING_VALIDATOR, 2683 points: ANYTHING_VALIDATOR, 2684 fillRule: genEnumValidator(['nonzero', 'evenodd']) 2685 }, 2686 polyline: { 2687 fill: COLOR_VAR_VALIDATOR, 2688 fillOpacity: NUMBER_VALIDATOR, 2689 opacity: NUMBER_VALIDATOR, 2690 stroke: COLOR_VAR_VALIDATOR, 2691 strokeDasharray: ANYTHING_VALIDATOR, 2692 strokeDashoffset: LENGTH_VALIDATOR, 2693 strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']), 2694 strokeLinecap: genEnumValidator(['butt', 'round', 'square']), 2695 strokeMiterlimit: NUMBER_VALIDATOR, 2696 strokeOpacity: NUMBER_VALIDATOR, 2697 strokeWidth: LENGTH_VALIDATOR, 2698 transform: TRANSFORM_VALIDATOR, 2699 id: ANYTHING_VALIDATOR, 2700 points: ANYTHING_VALIDATOR, 2701 fillRule: genEnumValidator(['nonzero', 'evenodd']) 2702 }, 2703 tspan: { 2704 id: ANYTHING_VALIDATOR, 2705 x: PERCENTAGE_LENGTH_VALIDATOR, 2706 y: PERCENTAGE_LENGTH_VALIDATOR, 2707 dx: PERCENTAGE_LENGTH_VALIDATOR, 2708 dy: PERCENTAGE_LENGTH_VALIDATOR, 2709 rotate: NUMBER_VALIDATOR, 2710 fontSize: LENGTH_VALIDATOR, 2711 fill: COLOR_VAR_VALIDATOR, 2712 fillOpacity: NUMBER_VALIDATOR, 2713 stroke: COLOR_VAR_VALIDATOR, 2714 strokeOpacity: NUMBER_VALIDATOR, 2715 strokeWidth: LENGTH_VALIDATOR 2716 }, 2717 textPath: { 2718 id: ANYTHING_VALIDATOR, 2719 path: ANYTHING_VALIDATOR, 2720 startOffset: PERCENTAGE_LENGTH_VALIDATOR, 2721 fontSize: LENGTH_VALIDATOR, 2722 fill: COLOR_VAR_VALIDATOR, 2723 fillOpacity: NUMBER_VALIDATOR, 2724 stroke: COLOR_VAR_VALIDATOR, 2725 strokeOpacity: NUMBER_VALIDATOR, 2726 strokeWidth: LENGTH_VALIDATOR 2727 }, 2728 animate: { 2729 id: ANYTHING_VALIDATOR, 2730 attributeName: ANYTHING_VALIDATOR, 2731 begin: ANYTHING_VALIDATOR, 2732 dur: ANYTHING_VALIDATOR, 2733 end: ANYTHING_VALIDATOR, 2734 repeatCount: ANYTHING_VALIDATOR, 2735 fill: genEnumValidator(['freeze', 'remove']), 2736 calcMode: genEnumValidator(['discrete', 'linear', 'paced', 'spline']), 2737 keyTimes: ANYTHING_VALIDATOR, 2738 keySplines: ANYTHING_VALIDATOR, 2739 from: ANYTHING_VALIDATOR, 2740 to: ANYTHING_VALIDATOR, 2741 values: ANYTHING_VALIDATOR 2742 }, 2743 animateMotion: { 2744 id: ANYTHING_VALIDATOR, 2745 attributeName: ANYTHING_VALIDATOR, 2746 begin: ANYTHING_VALIDATOR, 2747 dur: ANYTHING_VALIDATOR, 2748 end: ANYTHING_VALIDATOR, 2749 repeatCount: ANYTHING_VALIDATOR, 2750 fill: genEnumValidator(['freeze', 'remove']), 2751 calcMode: genEnumValidator(['discrete', 'linear', 'paced', 'spline']), 2752 keyTimes: ANYTHING_VALIDATOR, 2753 keySplines: ANYTHING_VALIDATOR, 2754 from: ANYTHING_VALIDATOR, 2755 to: ANYTHING_VALIDATOR, 2756 keyPoints: ANYTHING_VALIDATOR, 2757 path: ANYTHING_VALIDATOR, 2758 rotate: ANYTHING_VALIDATOR 2759 }, 2760 animateTransform: { 2761 id: ANYTHING_VALIDATOR, 2762 attributeName: ANYTHING_VALIDATOR, 2763 begin: ANYTHING_VALIDATOR, 2764 dur: ANYTHING_VALIDATOR, 2765 end: ANYTHING_VALIDATOR, 2766 repeatCount: ANYTHING_VALIDATOR, 2767 fill: genEnumValidator(['freeze', 'remove']), 2768 calcMode: genEnumValidator(['discrete', 'linear', 'paced', 'spline']), 2769 from: ANYTHING_VALIDATOR, 2770 to: ANYTHING_VALIDATOR, 2771 type: genEnumValidator(['translate', 'scale', 'skewX', 'skewY']) 2772 }, 2773 line: { 2774 fill: COLOR_VAR_VALIDATOR, 2775 fillOpacity: NUMBER_VALIDATOR, 2776 opacity: NUMBER_VALIDATOR, 2777 stroke: COLOR_VAR_VALIDATOR, 2778 strokeDasharray: ANYTHING_VALIDATOR, 2779 strokeDashoffset: LENGTH_VALIDATOR, 2780 strokeLinejoin: genEnumValidator(['bevel', 'miter', 'round']), 2781 strokeLinecap: genEnumValidator(['butt', 'round', 'square']), 2782 strokeMiterlimit: NUMBER_VALIDATOR, 2783 strokeOpacity: NUMBER_VALIDATOR, 2784 strokeWidth: LENGTH_VALIDATOR, 2785 fillRule: genEnumValidator(['nonzero', 'evenodd']), 2786 transform: TRANSFORM_VALIDATOR, 2787 id: ANYTHING_VALIDATOR, 2788 x1: PERCENTAGE_LENGTH_VALIDATOR, 2789 y1: PERCENTAGE_LENGTH_VALIDATOR, 2790 x2: PERCENTAGE_LENGTH_VALIDATOR, 2791 y2: PERCENTAGE_LENGTH_VALIDATOR 2792 } 2793} 2794 2795var LITE_PROP_NAME_GROUPS = { 2796 boxModel: { 2797 width: PERCENTAGE_LENGTH_VALIDATOR, 2798 height: PERCENTAGE_LENGTH_VALIDATOR, 2799 padding: SHORTHAND_LENGTH_VALIDATOR, 2800 paddingLeft: LENGTH_VALIDATOR, 2801 paddingRight: LENGTH_VALIDATOR, 2802 paddingTop: LENGTH_VALIDATOR, 2803 paddingBottom: LENGTH_VALIDATOR, 2804 margin:SHORTHAND_AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2805 marginLeft: AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2806 marginRight: AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2807 marginTop: AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2808 marginBottom: AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2809 strokeWidth: LENGTH_VALIDATOR, 2810 }, 2811 border:{ 2812 borderWidth: SHORTHAND_LENGTH_VALIDATOR, 2813 borderColor: SHORTHAND_COLOR_VALIDATOR, 2814 borderRadius: LENGTH_VALIDATOR, 2815 }, 2816 animation:{ 2817 animationDuration: TIME_VALIDATOR, 2818 animationDelay: TIME_VALIDATOR, 2819 animationName: NAME_VALIDATOR, 2820 animationTimingFunction: genEnumValidator(['linear', 'ease-in', 'ease-out', 'ease-in-out']), 2821 animationIterationCount: ITERATIONCOUNT_VALIDATOR, 2822 animationFillMode: genEnumValidator(['none', 'forwards']) 2823 }, 2824 flexbox: { 2825 flexDirection: genEnumValidator(['row', 'column']), 2826 flexWrap: genEnumValidator(['nowrap', 'wrap']), 2827 justifyContent: genEnumValidator(['flex-start', 'flex-end', 'center', 'space-between', 2828 'space-around', 'space-evenly']), 2829 alignItems: genEnumValidator(['stretch', 'flex-start', 'flex-end', 'center']), 2830 }, 2831 position: { 2832 top: PERCENTAGE_LENGTH_VALIDATOR, 2833 left: PERCENTAGE_LENGTH_VALIDATOR, 2834 }, 2835 common: { 2836 opacity: NUMBER_VALIDATOR, 2837 backgroundColor: COLOR_VAR_VALIDATOR, 2838 backgroundImage: URL_VALIDATOR, 2839 placeholderColor: COLOR_VAR_VALIDATOR, 2840 display: genEnumValidator(['flex', 'none']), 2841 }, 2842 text: { 2843 color: COLOR_VAR_VALIDATOR, 2844 fontSize: LENGTH_VALIDATOR, 2845 fontFamily: genEnumValidator(['HYQiHei-65S']), 2846 letterSpacing: LENGTH_VALIDATOR, 2847 textAlign: genEnumValidator(['left', 'center', 'right']), 2848 textOverflow: genEnumValidator(['clip', 'ellipsis']), 2849 }, 2850 slider: { 2851 selectedColor: COLOR_VAR_VALIDATOR, 2852 selectedFontSize: LENGTH_VALIDATOR, 2853 selectedFontFamily: genEnumValidator(['HYQiHei-65S']), 2854 blockColor: COLOR_VAR_VALIDATOR, 2855 }, 2856 transform: { 2857 transform: TRANSFORM_VALIDATOR, 2858 }, 2859 progress: { 2860 centerX: LENGTH_VALIDATOR, 2861 centerY: LENGTH_VALIDATOR, 2862 radius: LENGTH_VALIDATOR, 2863 startAngle: ANGLE_VALIDATOR, 2864 totalAngle: ANGLE_VALIDATOR 2865 } 2866} 2867 2868var CARD_PROP_NAME_GROUPS = { 2869 boxModel: { 2870 width: PERCENTAGE_LENGTH_VALIDATOR, 2871 height: PERCENTAGE_LENGTH_VALIDATOR, 2872 overflow: genEnumValidator(['auto', 'hidden','scroll','visible']), 2873 padding: SHORTHAND_PERCENTAGE_LENGTH_VALIDATOR, 2874 paddingLeft: PERCENTAGE_LENGTH_VALIDATOR, 2875 paddingRight: PERCENTAGE_LENGTH_VALIDATOR, 2876 paddingTop: PERCENTAGE_LENGTH_VALIDATOR, 2877 paddingBottom: PERCENTAGE_LENGTH_VALIDATOR, 2878 paddingStart: PERCENTAGE_LENGTH_VALIDATOR, 2879 paddingEnd: PERCENTAGE_LENGTH_VALIDATOR, 2880 margin: SHORTHAND_AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2881 marginLeft: AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2882 marginRight: AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2883 marginTop: AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2884 marginBottom: AUTO_PERCENTAGE_LENGTH_VALIDATOR, 2885 marginStart: PERCENTAGE_LENGTH_VALIDATOR, 2886 marginEnd: PERCENTAGE_LENGTH_VALIDATOR, 2887 columns: NUMBER_VALIDATOR, 2888 displayIndex: NUMBER_VALIDATOR, 2889 aspectRatio: NUMBER_VALIDATOR, 2890 minWidth: PERCENTAGE_LENGTH_VALIDATOR, 2891 minHeight: PERCENTAGE_LENGTH_VALIDATOR, 2892 maxWidth: PERCENTAGE_LENGTH_VALIDATOR, 2893 maxHeight: PERCENTAGE_LENGTH_VALIDATOR, 2894 flexWeight: NUMBER_VALIDATOR, 2895 boxShadow: BOX_SHADOW_VALIDATOR, 2896 boxShadowH: LENGTH_VALIDATOR, 2897 boxShadowV: LENGTH_VALIDATOR, 2898 boxShadowBlur: LENGTH_VALIDATOR, 2899 boxShadowSpread: LENGTH_VALIDATOR, 2900 boxShadowColor: COLOR_VAR_VALIDATOR, 2901 filter: FILTER_VALIDATOR, 2902 backdropFilter: FILTER_VALIDATOR, 2903 windowFilter: FILTER_PERCENTAGE_VALIDATOR 2904 }, 2905 div: { 2906 gridTemplateColumns: GRID_TEMPLATE_VALIDATOR, 2907 gridTemplateRows: GRID_TEMPLATE_VALIDATOR, 2908 gridGap: LENGTH_VALIDATOR, 2909 gridColumnsGap: LENGTH_VALIDATOR, 2910 gridRowsGap: LENGTH_VALIDATOR, 2911 gridRowStart: NUMBER_VALIDATOR, 2912 gridRowEnd: NUMBER_VALIDATOR, 2913 gridColumnStart: NUMBER_VALIDATOR, 2914 gridColumnEnd: NUMBER_VALIDATOR 2915 }, 2916 border: { 2917 border: BORDER_VALIDATOR, 2918 borderWidth: SHORTHAND_LENGTH_VALIDATOR, 2919 borderLeftWidth: LENGTH_VALIDATOR, 2920 borderTopWidth: LENGTH_VALIDATOR, 2921 borderRightWidth: LENGTH_VALIDATOR, 2922 borderBottomWidth: LENGTH_VALIDATOR, 2923 borderColor: SHORTHAND_COLOR_VALIDATOR, 2924 borderLeftColor: COLOR_VAR_VALIDATOR, 2925 borderTopColor: COLOR_VAR_VALIDATOR, 2926 borderRightColor: COLOR_VAR_VALIDATOR, 2927 borderBottomColor: COLOR_VAR_VALIDATOR, 2928 borderStyle: genEnumValidator(['solid', 'dashed', 'dotted']), 2929 borderTopStyle: genEnumValidator(['solid', 'dashed', 'dotted']), 2930 borderRightStyle: genEnumValidator(['solid', 'dashed', 'dotted']), 2931 borderBottomStyle: genEnumValidator(['solid', 'dashed', 'dotted']), 2932 borderLeftStyle: genEnumValidator(['solid', 'dashed', 'dotted']), 2933 borderRadius: LENGTH_VALIDATOR, 2934 borderBottomLeftRadius: LENGTH_VALIDATOR, 2935 borderBottomRightRadius: LENGTH_VALIDATOR, 2936 borderTopLeftRadius: LENGTH_VALIDATOR, 2937 borderTopRightRadius: LENGTH_VALIDATOR, 2938 borderLeft: BORDER_VALIDATOR, 2939 borderRight: BORDER_VALIDATOR, 2940 borderTop: BORDER_VALIDATOR, 2941 borderBottom: BORDER_VALIDATOR 2942 }, 2943 flexbox: { 2944 flex: genEnumValidator(['none', 'auto', 'initial']), 2945 flexWrap: genEnumValidator(['nowrap', 'wrap']), 2946 flexGrow: NUMBER_VALIDATOR, 2947 flexShrink: NUMBER_VALIDATOR, 2948 flexBasis: LENGTH_VALIDATOR, 2949 flexDirection: genEnumValidator(['row', 'column']), 2950 justifyContent: genEnumValidator(['flex-start', 'flex-end', 'center', 'space-between', 2951 'space-around', 'space-evenly']), 2952 alignItems: genEnumValidator(['stretch', 'flex-start', 'flex-end', 'center', 'baseline']), 2953 alignContent: genEnumValidator(['stretch', 'flex-start', 'flex-end', 'center', 'space-between', 'space-around']), 2954 }, 2955 position: { 2956 position: genEnumValidator(['relative', 'fixed', 'absolute']), 2957 top: PERCENTAGE_LENGTH_VALIDATOR, 2958 bottom: PERCENTAGE_LENGTH_VALIDATOR, 2959 left: PERCENTAGE_LENGTH_VALIDATOR, 2960 right: PERCENTAGE_LENGTH_VALIDATOR, 2961 zIndex: INTEGER_VALIDATOR 2962 }, 2963 common: { 2964 background: BACKGROUND_VALIDATOR, 2965 backgroundColor: COLOR_VAR_VALIDATOR, 2966 backgroundImage: URL_VALIDATOR, 2967 backgroundSize: BACKGROUND_SIZE_VALIDATOR, 2968 backgroundRepeat: genEnumValidator(['repeat', 'no-repeat', 'repeat-x', 'repeat-y']), 2969 backgroundPosition: BACKGROUND_POSITION_VALIDATOR, 2970 opacity: NUMBER_VALIDATOR, 2971 appearingDuration: NUMBER_VALIDATOR, 2972 visibility: genEnumValidator(['visible', 'hidden']), 2973 display: genEnumValidator(['flex', 'none', 'grid']), 2974 imageFill: COLOR_VAR_VALIDATOR, 2975 maskImage: MASK_VALIDATOR, 2976 maskPosition: BACKGROUND_POSITION_VALIDATOR, 2977 maskSize: BACKGROUND_SIZE_VALIDATOR 2978 }, 2979 text: { 2980 color: COLOR_VAR_VALIDATOR, 2981 fontSize: LENGTH_VALIDATOR, 2982 allowScale: genEnumValidator(['true', 'false']), 2983 letterSpacing: LENGTH_VALIDATOR, 2984 fontStyle: genEnumValidator(['normal', 'italic']), 2985 fontFamily: ANYTHING_VALIDATOR, 2986 fontWeight: genEnumValidator(['normal', 'lighter', 'bold', 'bolder', "medium", "regular", 2987 '100', '200', '300', '400', '500', '600', '700', '800', '900']), 2988 textDecoration: genEnumValidator(['none', 'underline', 'line-through']), 2989 textAlign: genEnumValidator(['start', 'end', 'left', 'center', 'right']), 2990 textOverflow: genEnumValidator(['clip', 'ellipsis']), 2991 textIndent: TEXT_INDENT_VALIDATOR, 2992 lineHeight: LENGTH_VALIDATOR, 2993 maxLines: ANYTHING_VALIDATOR, 2994 minFontSize: LENGTH_VALIDATOR, 2995 maxFontSize: LENGTH_VALIDATOR, 2996 fontSizeStep: LENGTH_VALIDATOR, 2997 preferFontSizes: ARRAY_LENGTH_VALIDATOR, 2998 adaptHeight: genEnumValidator(['true', 'false']) 2999 }, 3000 progress: { 3001 secondaryColor: COLOR_VAR_VALIDATOR, 3002 scaleWidth: LENGTH_VALIDATOR, 3003 scaleNumber: NUMBER_VALIDATOR, 3004 startAngle: ANGLE_VALIDATOR, 3005 totalAngle: ANGLE_VALIDATOR, 3006 centerX: LENGTH_VALIDATOR, 3007 centerY: LENGTH_VALIDATOR, 3008 radius: LENGTH_VALIDATOR, 3009 direction: genEnumValidator(['start-to-end', 'end-to-start']), 3010 sections: NAME_VALIDATOR, 3011 colors: ARRAY_COLOR_VALIDATOR, 3012 weights: ARRAY_NUMBER_VALIDATOR 3013 }, 3014 chart: { 3015 strokeWidth: LENGTH_VALIDATOR, 3016 }, 3017 button: { 3018 textColor: COLOR_VAR_VALIDATOR, 3019 iconWidth: LENGTH_VALIDATOR, 3020 iconHeight: LENGTH_VALIDATOR 3021 }, 3022 image: { 3023 objectFit: genEnumValidator(['cover', 'fill', 'contain', 'none', 'scale-down']), 3024 matchTextDirection: genEnumValidator(['false', 'true']), 3025 fitOriginalSize: genEnumValidator(['false', 'true']), 3026 }, 3027 list: { 3028 itemExtent: PERCENTAGE_LENGTH_VALIDATOR, 3029 fadeColor: COLOR_VAR_VALIDATOR, 3030 dividerColor: COLOR_VAR_VALIDATOR, 3031 dividerHeight: LENGTH_VALIDATOR, 3032 dividerLength: LENGTH_VALIDATOR, 3033 dividerOrigin: LENGTH_VALIDATOR, 3034 scrollbarColor: COLOR_VALIDATOR, 3035 scrollbarWidth: LENGTH_VALIDATOR, 3036 scrollbarOffset: ARRAY_LENGTH_VALIDATOR 3037 } 3038} 3039 3040var backgroundValidatorMap = { 3041 linearGradient: LINEAR_GRADIENT_VALIDATOR, 3042 repeatingLinearGradient: LINEAR_GRADIENT_VALIDATOR, 3043 linearGradientColor: ARRAY_COLOR_STOP_VALIDATOR, 3044 linearGradientAngle: ANGLE_VALIDATOR, 3045 linearGradientDirection: GRADIENT_DIRECTION_VALIDATOR 3046} 3047 3048var transformValidatorMap = { 3049 translate: MULTIPLE_PERCENTAGE_LENGTH_VALIDATOR, 3050 translate3d: MULTIPLE_PERCENTAGE_LENGTH_VALIDATOR, 3051 translateX: PERCENTAGE_LENGTH_VALIDATOR, 3052 translateY: PERCENTAGE_LENGTH_VALIDATOR, 3053 translateZ: PERCENTAGE_LENGTH_VALIDATOR, 3054 scale: MULTIPLE_NUMBER_VALIDATOR, 3055 scale3d: MULTIPLE_NUMBER_VALIDATOR, 3056 scaleX: NUMBER_VALIDATOR, 3057 scaleY: NUMBER_VALIDATOR, 3058 scaleZ: NUMBER_VALIDATOR, 3059 rotate: MUTIPLE_ANGLE_VALIDATOR, 3060 rotate3d: ROTATE3D_VALIDATOR, 3061 rotateX: ANGLE_VALIDATOR, 3062 rotateY: ANGLE_VALIDATOR, 3063 rotateZ: ANGLE_VALIDATOR, 3064 skew: MUTIPLE_ANGLE_VALIDATOR, 3065 skewX: ANGLE_VALIDATOR, 3066 skewY: ANGLE_VALIDATOR, 3067 matrix: MULTIPLE_NUMBER_VALIDATOR, 3068 matrix3d: MULTIPLE_NUMBER_VALIDATOR, 3069 perspective: PERCENTAGE_LENGTH_VALIDATOR, 3070} 3071 3072var SUGGESTED_PROP_NAME_GROUP = {} 3073 3074var validatorMap = {} 3075 3076const card = process.env.DEVICE_LEVEL === 'card' 3077var isLiteDevice = process.env.DEVICE_LEVEL === 'lite' 3078 3079var PROP_NAME_GROUPS = process.env.DEVICE_LEVEL === 'lite' ? LITE_PROP_NAME_GROUPS : 3080 card ? CARD_PROP_NAME_GROUPS : RICH_PROP_NAME_GROUPS 3081 3082/** 3083 * flatten `PROP_NAME_GROUPS` to `validatorMap` 3084 */ 3085function genValidatorMap() { 3086 var groupName, group, name 3087 for (groupName in PROP_NAME_GROUPS) { 3088 group = PROP_NAME_GROUPS[groupName] 3089 for (name in group) { 3090 validatorMap[name] = group[name] 3091 } 3092 } 3093} 3094 3095genValidatorMap() 3096 3097function getValueUnit(dem) { 3098 var str = dem.toString() 3099 var getValue = str.match(/[-]{0,1}[1-9][0-9]*/) 3100 var getUnit = str.match(/px|cm|%|em|vp|fp/) 3101 var result = {value: getValue, unit: getUnit} 3102 return result 3103} 3104 3105function isOperator(value) { 3106 var operatorString = "+-*/()" 3107 return operatorString.indexOf(value) > -1 3108} 3109 3110function getPrioraty(value) { 3111 switch(value) { 3112 case '+': 3113 case '-': 3114 return 1 3115 case '*': 3116 case '/': 3117 return 2 3118 default: 3119 return 0 3120 } 3121} 3122 3123function prioraty(o1, o2) { 3124 return getPrioraty(o1) <= getPrioraty(o2) 3125} 3126 3127function dal2Rpn(exp) { 3128 var inputStack = [] 3129 var outputStack = [] 3130 var outputQueue = [] 3131 var str = 3132 exp.replace(/calc/g, "").replace(/(?<!var\(\-\-\w+|var\(\-\-\w+\,\s*\w+)\)/g, " )").replace(/(?<!var)\(/g, "( ") 3133 var inputStack=str.split(/(?<!\,)\s+/) 3134 var value, log 3135 while(inputStack.length > 0) { 3136 var cur = inputStack.shift() 3137 if(isOperator(cur)) { 3138 if(cur == '(') { 3139 outputStack.push(cur) 3140 } else if(cur == ')') { 3141 var po = outputStack.pop() 3142 while(po != '(' && outputStack.length > 0) { 3143 outputQueue.push(po) 3144 po = outputStack.pop() 3145 } 3146 if(po != '(') { 3147 log = {reason: 'ERROR: Expression unmatched ()'} 3148 } 3149 } else { 3150 while(prioraty(cur, outputStack[outputStack.length - 1]) && outputStack.length > 0) { 3151 outputQueue.push(outputStack.pop()) 3152 } 3153 outputStack.push(cur) 3154 } 3155 } else { 3156 outputQueue.push(cur) 3157 } 3158 } 3159 return { 3160 value: outputQueue, 3161 log: log 3162 } 3163} 3164 3165function checkComputation(left, right, operator) { 3166 var value, log 3167 if (operator == '*') { 3168 if ((right.match(/[a-zA-Z]/) && left.match(/[a-zA-Z]/)) || (!right.match(/[a-zA-Z]/) && !left.match(/[a-zA-Z]/))) { 3169 log = {reason: 'ERROR: The multiplier must contain and contain only one integer'} 3170 } 3171 } 3172 if (operator == '/') { 3173 if (right.match(/[a-zA-Z]|(?<![1-9])[0]/)) { 3174 log = {reason: 'ERROR: Divisor must be an integer and cannot be zero'} 3175 } 3176 } 3177 if (operator == '+') { 3178 if (!(right.match(/[a-zA-Z%]/) && left.match(/[a-zA-Z%]/))) { 3179 log = {reason: 'ERROR: Addition cannot contain integers'} 3180 } 3181 } 3182 if (operator == '-') { 3183 if (!(right.match(/[a-zA-Z%]/) && left.match(/[a-zA-Z%]/))) { 3184 log = {reason: 'ERROR: Subtraction cannot contain integers'} 3185 } 3186 } 3187 return log 3188} 3189 3190function getResult(left, right, operator) { 3191 var value, log, errLog 3192 if (left.match(/var/)) { 3193 left = cssVarFun(left) 3194 } 3195 if (right.match(/var/)) { 3196 right = cssVarFun(right) 3197 } 3198 errLog = checkComputation(left, right, operator) 3199 if (errLog) { 3200 return { value: null, log: errLog } 3201 } 3202 var result, value, unit 3203 var leftValue = getValueUnit(left) 3204 var rightValue = getValueUnit(right) 3205 if (left.match(/\(/) | right.match(/\(/)) { 3206 result = left + ' ' + operator + ' ' + right 3207 } else { 3208 if (operator == '*') { 3209 value = leftValue.value * rightValue.value 3210 if (leftValue.unit == null) { 3211 unit = rightValue.unit 3212 } else { unit = leftValue.unit} 3213 result = value + unit 3214 } else if (operator == '/') { 3215 if (parseInt(rightValue.value) != 0) { 3216 value = leftValue.value / rightValue.value 3217 unit = leftValue.unit 3218 result = value + unit 3219 } 3220 } else if (operator == '+') { 3221 if (JSON.stringify(leftValue.unit) == JSON.stringify(rightValue.unit)) { 3222 value = parseInt(leftValue.value) + parseInt(rightValue.value) 3223 unit = leftValue.unit 3224 result = value + unit 3225 } else result = '(' + left + ' ' + operator + ' ' + right + ')' 3226 } else if (operator == '-') { 3227 if (JSON.stringify(leftValue.unit) == JSON.stringify(rightValue.unit)) { 3228 value = parseInt(leftValue.value) - parseInt(rightValue.value) 3229 unit = leftValue.unit 3230 result = value + unit 3231 } else result = '(' + left + ' ' + operator + ' ' + right + ')' 3232 } 3233 } 3234 return { value: result, log: null } 3235} 3236 3237function evalRpn(rpnQueue) { 3238 var outputStack = [] 3239 var value, res, log 3240 while(rpnQueue.length > 0) { 3241 var cur = rpnQueue.shift() 3242 if(!isOperator(cur)) { 3243 outputStack.push(cur) 3244 } else { 3245 if(outputStack.length < 2) { 3246 log = {reason: 'ERROR: Expression does not conform to specification'} 3247 } 3248 var sec = outputStack.pop() 3249 var fir = outputStack.pop() 3250 res = getResult(fir, sec, cur) 3251 log = res.log 3252 if (log) { 3253 return { 3254 value: null, 3255 log: log 3256 } 3257 } else { 3258 outputStack.push(res.value) 3259 } 3260 } 3261 } 3262 if(outputStack.length != 1) { 3263 log = {reason: 'ERROR: Expression does not conform to specification'} 3264 } else { 3265 if (outputStack[0].match(/[+-]/)) { 3266 value = 'calc' + outputStack[0] 3267 } else { 3268 value = outputStack[0] 3269 } 3270 } 3271 return { 3272 value: value, 3273 log: log 3274 } 3275} 3276 3277var cssPropData = [] 3278 3279function saveCssProp(name, value) { 3280 if (name.match(/\-\-/)) { 3281 while (value.match(/var/)) { 3282 var value = cssVarFun(value) 3283 } 3284 cssPropData.push({name: name,value: value}) 3285 } 3286} 3287 3288function cssVarFun(value) { 3289 if (value.match(/calc/)) { 3290 return value 3291 } else { 3292 if (value.match(/var/)) { 3293 if (value.match(/\,/)) { 3294 var cssVarFir = value.substring(0,value.indexOf(",")).replace("var(","").trim() 3295 var cssVarSec = value.substring(value.indexOf(",")+1,value.length).replace(")","").trim() 3296 } else { 3297 var cssVarFir = value.replace("var(","").replace(")","").trim() 3298 var cssVarSec = "" 3299 } 3300 let varValue = cssVarSec 3301 for(var i=0, len=cssPropData.length; i<len; i++) { 3302 var cPDName = cssPropData[i].name.trim() 3303 cssVarFir = util.hyphenedToCamelCase(cssVarFir) 3304 if (cssVarFir == cPDName) { 3305 varValue = cssPropData[i].value 3306 } 3307 } 3308 return varValue 3309 } else { 3310 return value 3311 } 3312 } 3313} 3314 3315function expValidate(name, value) { 3316 var res, log 3317 saveCssProp(name, value) 3318 if (typeof value === 'string' && name != 'border') { 3319 if (value.match(/var/)) { 3320 value = cssVarFun(value) 3321 } 3322 if (value.match(/calc/)) { 3323 var checkOp = 3324 /[a-zA-Z0-9()]\+|\+[a-zA-Z0-9()]|[a-zA-Z0-9()](?<!\-)\-(?!\-)|(?<!\-)\-(?!\-)[a-zA-Z0-9()]|[a-zA-Z0-9()]\*|\*[a-zA-Z0-9()]|[a-zA-Z0-9()]\/|\/[a-zA-Z0-9()]/ 3325 if (value.match(checkOp) && value.match(/calc\(|var\(\-\-/)) { 3326 log = {reason: 'ERROR: Expression error, A space is required before and after the operator'} 3327 return { 3328 log: log 3329 } 3330 } 3331 res = dal2Rpn(value) 3332 res = evalRpn(res.value) 3333 log = res.log 3334 value = res.value 3335 } 3336 } 3337 return { 3338 value: value, 3339 log: log 3340 } 3341} 3342 3343/** 3344 * validate a CSS name/value pair 3345 * 3346 * @param {string} name camel cased 3347 * @param {string} value 3348 * @return {object} 3349 * - value:string or null 3350 * - log:{reason:string} or undefined 3351 */ 3352function validate(name, value) { 3353 var log, expRes 3354 expRes = expValidate(name, value) 3355 if (expRes.log) { 3356 return { 3357 value: null, 3358 log: expRes.log 3359 } 3360 } else { 3361 value = expRes.value 3362 } 3363 3364 var result 3365 var validator = validatorMap[name] 3366 if (typeof validator === 'function') { 3367 const flag = /{{{(.+?)}}}|{{(.+?)}}/.test(value) && card 3368 if (typeof value !== 'function' && !flag) { 3369 result = validator(value, name) 3370 } 3371 /* istanbul ignore else */ 3372 else { 3373 result = {value: value} 3374 } 3375 if (result.reason) { 3376 log = {reason: result.reason(name, value, result.value)} 3377 } 3378 } 3379 else { 3380 // ensure number type, no `px` 3381 /* istanbul ignore else */ 3382 if (typeof value !== 'function') { 3383 var match = value.match(LENGTH_REGEXP) 3384 if (match && (!match[1] || SUPPORT_CSS_UNIT.indexOf(match[1]) === -1)) { 3385 value = parseFloat(value) 3386 } 3387 } 3388 result = {value: value} 3389 var suggestedName = SUGGESTED_PROP_NAME_GROUP[name] 3390 var suggested = suggestedName ? ', suggest `' + util.camelCaseToHyphened(suggestedName) + '`' : '' 3391 log = {reason: 'WARNING: `' + util.camelCaseToHyphened(name) + 3392 '` is not a standard attribute name and may not be supported' + suggested} 3393 } 3394 return { 3395 value: result.value, 3396 log: log 3397 } 3398} 3399 3400var validateFuncMap = { 3401 length: LENGTH_VALIDATOR, 3402 number: NUMBER_VALIDATOR, 3403 date: DATE_VALIDATOR 3404} 3405 3406module.exports = { 3407 BASIC_COLOR_KEYWORDS: BASIC_COLOR_KEYWORDS, 3408 EXTENDED_COLOR_KEYWORDS: EXTENDED_COLOR_KEYWORDS, 3409 3410 LENGTH_VALIDATOR: LENGTH_VALIDATOR, 3411 COLOR_VALIDATOR: COLOR_VALIDATOR, 3412 COLOR_VAR_VALIDATOR: COLOR_VAR_VALIDATOR, 3413 NUMBER_VALIDATOR: NUMBER_VALIDATOR, 3414 INTEGER_VALIDATOR: INTEGER_VALIDATOR, 3415 genEnumValidator: genEnumValidator, 3416 3417 TRANSITION_PROPERTY_VALIDATOR: TRANSITION_PROPERTY_VALIDATOR, 3418 TRANSITION_DURATION_VALIDATOR: TRANSITION_INTERVAL_VALIDATOR, 3419 TRANSITION_DELAY_VALIDATOR: TRANSITION_INTERVAL_VALIDATOR, 3420 TRANSITION_TIMING_FUNCTION_VALIDATOR: TRANSITION_TIMING_FUNCTION_VALIDATOR, 3421 3422 PROP_NAME_GROUPS: PROP_NAME_GROUPS, 3423 validateFuncMap: validateFuncMap, 3424 3425 map: validatorMap, 3426 validate: validate 3427} 3428