16a23e08bSopenharmony_ci/*
26a23e08bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
36a23e08bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
46a23e08bSopenharmony_ci * you may not use this file except in compliance with the License.
56a23e08bSopenharmony_ci * You may obtain a copy of the License at
66a23e08bSopenharmony_ci *
76a23e08bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
86a23e08bSopenharmony_ci *
96a23e08bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
106a23e08bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
116a23e08bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126a23e08bSopenharmony_ci * See the License for the specific language governing permissions and
136a23e08bSopenharmony_ci * limitations under the License.
146a23e08bSopenharmony_ci */
156a23e08bSopenharmony_ciconst isType = require('../lite/lite-utils');
166a23e08bSopenharmony_ciconst rulePath = process.env.RULE_PATH;
176a23e08bSopenharmony_ciconst smartvisionTag = {
186a23e08bSopenharmony_ci  camera: {
196a23e08bSopenharmony_ci    events: ['error'],
206a23e08bSopenharmony_ci  },
216a23e08bSopenharmony_ci  video: {
226a23e08bSopenharmony_ci    events: [
236a23e08bSopenharmony_ci      'prepared',
246a23e08bSopenharmony_ci      'start',
256a23e08bSopenharmony_ci      'pause',
266a23e08bSopenharmony_ci      'finish',
276a23e08bSopenharmony_ci      'error',
286a23e08bSopenharmony_ci      'seeking',
296a23e08bSopenharmony_ci      'seeked',
306a23e08bSopenharmony_ci      'timeupdate',
316a23e08bSopenharmony_ci    ],
326a23e08bSopenharmony_ci    attrs: {
336a23e08bSopenharmony_ci      autoplay: {
346a23e08bSopenharmony_ci        enum: ['false', 'true'],
356a23e08bSopenharmony_ci      },
366a23e08bSopenharmony_ci      controls: {
376a23e08bSopenharmony_ci        enum: ['true', 'false'],
386a23e08bSopenharmony_ci      },
396a23e08bSopenharmony_ci      muted: {
406a23e08bSopenharmony_ci        enum: ['false', 'true'],
416a23e08bSopenharmony_ci      },
426a23e08bSopenharmony_ci      src: { checkPath: true },
436a23e08bSopenharmony_ci    },
446a23e08bSopenharmony_ci  },
456a23e08bSopenharmony_ci};
466a23e08bSopenharmony_ci
476a23e08bSopenharmony_ciconst litewearableTag = {
486a23e08bSopenharmony_ci  'div': {},
496a23e08bSopenharmony_ci  'canvas': {},
506a23e08bSopenharmony_ci  'stack': {},
516a23e08bSopenharmony_ci  'qrcode': {
526a23e08bSopenharmony_ci    atomic: true,
536a23e08bSopenharmony_ci    selfClosing: true,
546a23e08bSopenharmony_ci    uevents: ['click', 'longpress', 'swipe'],
556a23e08bSopenharmony_ci    attrs: {
566a23e08bSopenharmony_ci      value: {
576a23e08bSopenharmony_ci        required: true,
586a23e08bSopenharmony_ci      },
596a23e08bSopenharmony_ci      type: {
606a23e08bSopenharmony_ci        enum: ['rect', 'circle'],
616a23e08bSopenharmony_ci      },
626a23e08bSopenharmony_ci    },
636a23e08bSopenharmony_ci  },
646a23e08bSopenharmony_ci  'list': {
656a23e08bSopenharmony_ci    events: ['scrollend'],
666a23e08bSopenharmony_ci    children: ['list-item'],
676a23e08bSopenharmony_ci  },
686a23e08bSopenharmony_ci  'list-item': {
696a23e08bSopenharmony_ci    excludeRoot: true,
706a23e08bSopenharmony_ci    parents: ['list'],
716a23e08bSopenharmony_ci  },
726a23e08bSopenharmony_ci  'swiper': {
736a23e08bSopenharmony_ci    unSupportedChildren: ['list'],
746a23e08bSopenharmony_ci    events: ['change'],
756a23e08bSopenharmony_ci    attrs: {
766a23e08bSopenharmony_ci      index: {
776a23e08bSopenharmony_ci        checkFunc: 'number',
786a23e08bSopenharmony_ci      },
796a23e08bSopenharmony_ci      loop: {
806a23e08bSopenharmony_ci        enum: ['true', 'false'],
816a23e08bSopenharmony_ci      },
826a23e08bSopenharmony_ci      duration: {
836a23e08bSopenharmony_ci        checkFunc: 'number',
846a23e08bSopenharmony_ci      },
856a23e08bSopenharmony_ci      vertical: {
866a23e08bSopenharmony_ci        enum: ['false', 'true'],
876a23e08bSopenharmony_ci      },
886a23e08bSopenharmony_ci    },
896a23e08bSopenharmony_ci  },
906a23e08bSopenharmony_ci  'tabs': {
916a23e08bSopenharmony_ci    events: ['change'],
926a23e08bSopenharmony_ci    children: ['tab-content', 'tab-bar'],
936a23e08bSopenharmony_ci  },
946a23e08bSopenharmony_ci  'tab-bar': {
956a23e08bSopenharmony_ci    parents: ['tabs'],
966a23e08bSopenharmony_ci    children: ['text'],
976a23e08bSopenharmony_ci    attrs: {
986a23e08bSopenharmony_ci      mode: {
996a23e08bSopenharmony_ci        enum: ['fixed'],
1006a23e08bSopenharmony_ci      },
1016a23e08bSopenharmony_ci    },
1026a23e08bSopenharmony_ci  },
1036a23e08bSopenharmony_ci  'tab-content': {
1046a23e08bSopenharmony_ci    parents: ['tabs'],
1056a23e08bSopenharmony_ci    children: ['div', 'stack'], // to be checked
1066a23e08bSopenharmony_ci  },
1076a23e08bSopenharmony_ci  'image-animator': {
1086a23e08bSopenharmony_ci    atomic: true,
1096a23e08bSopenharmony_ci    selfClosing: true,
1106a23e08bSopenharmony_ci    events: ['stop'],
1116a23e08bSopenharmony_ci    attrs: {
1126a23e08bSopenharmony_ci      images: {
1136a23e08bSopenharmony_ci        required: true,
1146a23e08bSopenharmony_ci      },
1156a23e08bSopenharmony_ci      iteration: {},
1166a23e08bSopenharmony_ci      reverse: {
1176a23e08bSopenharmony_ci        enum: ['false', 'true'],
1186a23e08bSopenharmony_ci      },
1196a23e08bSopenharmony_ci      fixedsize: {
1206a23e08bSopenharmony_ci        enum: ['true', 'false'],
1216a23e08bSopenharmony_ci      },
1226a23e08bSopenharmony_ci      duration: {
1236a23e08bSopenharmony_ci        required: true,
1246a23e08bSopenharmony_ci      },
1256a23e08bSopenharmony_ci      fillmode: {
1266a23e08bSopenharmony_ci        enum: ['none', 'forwards'],
1276a23e08bSopenharmony_ci      },
1286a23e08bSopenharmony_ci    },
1296a23e08bSopenharmony_ci  },
1306a23e08bSopenharmony_ci  'image': {
1316a23e08bSopenharmony_ci    alias: ['img'],
1326a23e08bSopenharmony_ci    atomic: true,
1336a23e08bSopenharmony_ci    selfClosing: true,
1346a23e08bSopenharmony_ci    attrs: {
1356a23e08bSopenharmony_ci      src: {
1366a23e08bSopenharmony_ci        checkPath: true,
1376a23e08bSopenharmony_ci      },
1386a23e08bSopenharmony_ci    },
1396a23e08bSopenharmony_ci  },
1406a23e08bSopenharmony_ci  'progress': {
1416a23e08bSopenharmony_ci    atomic: true,
1426a23e08bSopenharmony_ci    selfClosing: true,
1436a23e08bSopenharmony_ci    attrs: {
1446a23e08bSopenharmony_ci      type: {
1456a23e08bSopenharmony_ci        enum: ['horizontal', 'arc'],
1466a23e08bSopenharmony_ci      },
1476a23e08bSopenharmony_ci      percent: {
1486a23e08bSopenharmony_ci        checkFunc: 'number',
1496a23e08bSopenharmony_ci      },
1506a23e08bSopenharmony_ci    },
1516a23e08bSopenharmony_ci  },
1526a23e08bSopenharmony_ci  'text': {
1536a23e08bSopenharmony_ci    atomic: true,
1546a23e08bSopenharmony_ci    textContent: true,
1556a23e08bSopenharmony_ci    attrs: {
1566a23e08bSopenharmony_ci      type: {
1576a23e08bSopenharmony_ci        enum: ['text', 'html'],
1586a23e08bSopenharmony_ci      },
1596a23e08bSopenharmony_ci      value: {},
1606a23e08bSopenharmony_ci    },
1616a23e08bSopenharmony_ci  },
1626a23e08bSopenharmony_ci  'marquee': {
1636a23e08bSopenharmony_ci    atomic: true,
1646a23e08bSopenharmony_ci    attrs: {
1656a23e08bSopenharmony_ci      scrollamount: {
1666a23e08bSopenharmony_ci        def: 6,
1676a23e08bSopenharmony_ci        checkFunc: 'number',
1686a23e08bSopenharmony_ci      },
1696a23e08bSopenharmony_ci    },
1706a23e08bSopenharmony_ci  },
1716a23e08bSopenharmony_ci  'analog-clock': {
1726a23e08bSopenharmony_ci    attrs: {
1736a23e08bSopenharmony_ci      hour: {
1746a23e08bSopenharmony_ci        checkFunc: 'number',
1756a23e08bSopenharmony_ci      },
1766a23e08bSopenharmony_ci      min: {
1776a23e08bSopenharmony_ci        checkFunc: 'number',
1786a23e08bSopenharmony_ci      },
1796a23e08bSopenharmony_ci      sec: {
1806a23e08bSopenharmony_ci        checkFunc: 'number',
1816a23e08bSopenharmony_ci      },
1826a23e08bSopenharmony_ci    },
1836a23e08bSopenharmony_ci  },
1846a23e08bSopenharmony_ci  'clock-hand': {
1856a23e08bSopenharmony_ci    parents: ['analog-clock'],
1866a23e08bSopenharmony_ci    attrs: {
1876a23e08bSopenharmony_ci      type: {
1886a23e08bSopenharmony_ci        enum: ['hour', 'min', 'sec'],
1896a23e08bSopenharmony_ci      },
1906a23e08bSopenharmony_ci      src: {
1916a23e08bSopenharmony_ci        checkPath: true,
1926a23e08bSopenharmony_ci      },
1936a23e08bSopenharmony_ci    },
1946a23e08bSopenharmony_ci  },
1956a23e08bSopenharmony_ci  'chart': {
1966a23e08bSopenharmony_ci    atomic: true,
1976a23e08bSopenharmony_ci    selfClosing: true,
1986a23e08bSopenharmony_ci    attrs: {
1996a23e08bSopenharmony_ci      type: {
2006a23e08bSopenharmony_ci        enum: ['line', 'bar'],
2016a23e08bSopenharmony_ci      },
2026a23e08bSopenharmony_ci      datasets: {},
2036a23e08bSopenharmony_ci      options: {},
2046a23e08bSopenharmony_ci    },
2056a23e08bSopenharmony_ci  },
2066a23e08bSopenharmony_ci  'input': {
2076a23e08bSopenharmony_ci    atomic: true,
2086a23e08bSopenharmony_ci    selfClosing: true,
2096a23e08bSopenharmony_ci    events: ['change'],
2106a23e08bSopenharmony_ci    attrs: {
2116a23e08bSopenharmony_ci      checked: {
2126a23e08bSopenharmony_ci        enum: ['false', 'true'],
2136a23e08bSopenharmony_ci      },
2146a23e08bSopenharmony_ci      type: {
2156a23e08bSopenharmony_ci        enum: ['button', 'checkbox', 'password', 'radio', 'text'],
2166a23e08bSopenharmony_ci      },
2176a23e08bSopenharmony_ci      name: {},
2186a23e08bSopenharmony_ci      value: {},
2196a23e08bSopenharmony_ci      placeholder: {},
2206a23e08bSopenharmony_ci      maxlength: {
2216a23e08bSopenharmony_ci        checkFunc: 'number',
2226a23e08bSopenharmony_ci      },
2236a23e08bSopenharmony_ci    },
2246a23e08bSopenharmony_ci  },
2256a23e08bSopenharmony_ci  'slider': {
2266a23e08bSopenharmony_ci    atomic: true,
2276a23e08bSopenharmony_ci    selfClosing: true,
2286a23e08bSopenharmony_ci    events: ['change'],
2296a23e08bSopenharmony_ci    attrs: {
2306a23e08bSopenharmony_ci      min: {
2316a23e08bSopenharmony_ci        def: 0,
2326a23e08bSopenharmony_ci        checkFunc: 'number',
2336a23e08bSopenharmony_ci      },
2346a23e08bSopenharmony_ci      max: {
2356a23e08bSopenharmony_ci        def: 100,
2366a23e08bSopenharmony_ci        checkFunc: 'number',
2376a23e08bSopenharmony_ci      },
2386a23e08bSopenharmony_ci      value: {
2396a23e08bSopenharmony_ci        def: 0,
2406a23e08bSopenharmony_ci        checkFunc: 'number',
2416a23e08bSopenharmony_ci      },
2426a23e08bSopenharmony_ci    },
2436a23e08bSopenharmony_ci  },
2446a23e08bSopenharmony_ci  'switch': {
2456a23e08bSopenharmony_ci    events: ['change'],
2466a23e08bSopenharmony_ci    atomic: true,
2476a23e08bSopenharmony_ci    selfClosing: true,
2486a23e08bSopenharmony_ci    attrs: {
2496a23e08bSopenharmony_ci      checked: {
2506a23e08bSopenharmony_ci        enum: ['false', 'true'],
2516a23e08bSopenharmony_ci      },
2526a23e08bSopenharmony_ci    },
2536a23e08bSopenharmony_ci  },
2546a23e08bSopenharmony_ci  'picker-view': {
2556a23e08bSopenharmony_ci    atomic: true,
2566a23e08bSopenharmony_ci    selfClosing: true,
2576a23e08bSopenharmony_ci    uevents: ['change'],
2586a23e08bSopenharmony_ci    attrs: {
2596a23e08bSopenharmony_ci      type: {
2606a23e08bSopenharmony_ci        enum: ['text', 'time'],
2616a23e08bSopenharmony_ci      },
2626a23e08bSopenharmony_ci      range: {},
2636a23e08bSopenharmony_ci      selected: {},
2646a23e08bSopenharmony_ci    },
2656a23e08bSopenharmony_ci  },
2666a23e08bSopenharmony_ci};
2676a23e08bSopenharmony_ci
2686a23e08bSopenharmony_ciconst liteCommonTag = {
2696a23e08bSopenharmony_ci  events: [
2706a23e08bSopenharmony_ci    'click',
2716a23e08bSopenharmony_ci    'longpress',
2726a23e08bSopenharmony_ci    'touchstart',
2736a23e08bSopenharmony_ci    'touchmove',
2746a23e08bSopenharmony_ci    'touchcancel',
2756a23e08bSopenharmony_ci    'touchend',
2766a23e08bSopenharmony_ci    'key',
2776a23e08bSopenharmony_ci    'swipe',
2786a23e08bSopenharmony_ci  ],
2796a23e08bSopenharmony_ci  attrs: {
2806a23e08bSopenharmony_ci    id: {},
2816a23e08bSopenharmony_ci    style: {},
2826a23e08bSopenharmony_ci    class: {},
2836a23e08bSopenharmony_ci    ref: {},
2846a23e08bSopenharmony_ci    if: {
2856a23e08bSopenharmony_ci      excludeRoot: true,
2866a23e08bSopenharmony_ci      def: 'true',
2876a23e08bSopenharmony_ci    },
2886a23e08bSopenharmony_ci    elif: {
2896a23e08bSopenharmony_ci      def: 'true',
2906a23e08bSopenharmony_ci    },
2916a23e08bSopenharmony_ci    else: {
2926a23e08bSopenharmony_ci      excludeRoot: true,
2936a23e08bSopenharmony_ci    },
2946a23e08bSopenharmony_ci    for: {
2956a23e08bSopenharmony_ci      excludeRoot: true,
2966a23e08bSopenharmony_ci    },
2976a23e08bSopenharmony_ci    tid: {},
2986a23e08bSopenharmony_ci    show: {
2996a23e08bSopenharmony_ci      excludeRoot: true,
3006a23e08bSopenharmony_ci      def: 'true',
3016a23e08bSopenharmony_ci    },
3026a23e08bSopenharmony_ci  },
3036a23e08bSopenharmony_ci};
3046a23e08bSopenharmony_ci
3056a23e08bSopenharmony_ci/**
3066a23e08bSopenharmony_ci * Rules for adapting to different environments. If it is `liteWearable` device type,
3076a23e08bSopenharmony_ci * set to this type of verification rule.
3086a23e08bSopenharmony_ci * @param {String} deviceType device type.
3096a23e08bSopenharmony_ci * @return {Object} Validation rules.
3106a23e08bSopenharmony_ci */
3116a23e08bSopenharmony_cifunction select(deviceType) {
3126a23e08bSopenharmony_ci  tag = {
3136a23e08bSopenharmony_ci    liteWearable: litewearableTag,
3146a23e08bSopenharmony_ci    smartVision: { ...litewearableTag, ...smartvisionTag },
3156a23e08bSopenharmony_ci  };
3166a23e08bSopenharmony_ci  return tag[deviceType];
3176a23e08bSopenharmony_ci}
3186a23e08bSopenharmony_cilet liteNativeTag = select(process.env.DEVICE_TYPE);
3196a23e08bSopenharmony_ci
3206a23e08bSopenharmony_ci/**
3216a23e08bSopenharmony_ci * Whether the file exists, get customized rules.
3226a23e08bSopenharmony_ci */
3236a23e08bSopenharmony_ci(function checkFile() {
3246a23e08bSopenharmony_ci  if (rulePath) {
3256a23e08bSopenharmony_ci    const customTag = require(rulePath);
3266a23e08bSopenharmony_ci    isExtends(customTag);
3276a23e08bSopenharmony_ci  }
3286a23e08bSopenharmony_ci})();
3296a23e08bSopenharmony_ci
3306a23e08bSopenharmony_ci/**
3316a23e08bSopenharmony_ci * Get the component types supported by the current verification rule.
3326a23e08bSopenharmony_ci * @return {Array} Supported component name.
3336a23e08bSopenharmony_ci */
3346a23e08bSopenharmony_cifunction getKeys() {
3356a23e08bSopenharmony_ci  const res = [];
3366a23e08bSopenharmony_ci  const keys = Object.keys(liteNativeTag);
3376a23e08bSopenharmony_ci  for (let i = 0; i < keys.length; i++) {
3386a23e08bSopenharmony_ci    const key = keys[i];
3396a23e08bSopenharmony_ci    res.push(key);
3406a23e08bSopenharmony_ci  }
3416a23e08bSopenharmony_ci  res.push('attrs');
3426a23e08bSopenharmony_ci  return res;
3436a23e08bSopenharmony_ci}
3446a23e08bSopenharmony_ci
3456a23e08bSopenharmony_ci/**
3466a23e08bSopenharmony_ci * According to user-defined rules, combine into new verification rules.
3476a23e08bSopenharmony_ci * @param {Object} customTag User-defined rule object.
3486a23e08bSopenharmony_ci */
3496a23e08bSopenharmony_cifunction isExtends(customTag) {
3506a23e08bSopenharmony_ci  if (customTag.extends == 'recommended') {
3516a23e08bSopenharmony_ci    const nativekeys = getKeys();
3526a23e08bSopenharmony_ci    merge(liteNativeTag, customTag.rules, nativekeys);
3536a23e08bSopenharmony_ci  } else {
3546a23e08bSopenharmony_ci    liteNativeTag = customTag.rules;
3556a23e08bSopenharmony_ci  }
3566a23e08bSopenharmony_ci}
3576a23e08bSopenharmony_ci/**
3586a23e08bSopenharmony_ci * Combine the original rules and user-defined rules.
3596a23e08bSopenharmony_ci * @param {Object} object Original rules.
3606a23e08bSopenharmony_ci * @param {Object} source user-defined rules.
3616a23e08bSopenharmony_ci * @param {Array} nativekeys Supported component name.
3626a23e08bSopenharmony_ci * @return {Array} Merged object.
3636a23e08bSopenharmony_ci */
3646a23e08bSopenharmony_cifunction merge(object, source, nativekeys) {
3656a23e08bSopenharmony_ci  const keys = Object.keys(source);
3666a23e08bSopenharmony_ci  for (let i = 0; i < keys.length; i++) {
3676a23e08bSopenharmony_ci    const key = keys[i];
3686a23e08bSopenharmony_ci    const value = source[key];
3696a23e08bSopenharmony_ci    let target = object[key];
3706a23e08bSopenharmony_ci    if (target != null && !nativekeys.includes(key)) {
3716a23e08bSopenharmony_ci      console.error(
3726a23e08bSopenharmony_ci          `\u001b[31mError in .literc.js: \n` +
3736a23e08bSopenharmony_ci          `Attribute '${key}' already exists and cannot be modified\u001b[39m`,
3746a23e08bSopenharmony_ci      );
3756a23e08bSopenharmony_ci      process.exit(1);
3766a23e08bSopenharmony_ci    } else if (isType.isObject(value)) {
3776a23e08bSopenharmony_ci      target = isType.isObject(target) ? target : {};
3786a23e08bSopenharmony_ci      object[key] = merge(target, value, nativekeys);
3796a23e08bSopenharmony_ci    } else if (!(isType.isNull(value) || isType.isUndefined(value))) {
3806a23e08bSopenharmony_ci      object[key] = value;
3816a23e08bSopenharmony_ci    }
3826a23e08bSopenharmony_ci  }
3836a23e08bSopenharmony_ci  return object;
3846a23e08bSopenharmony_ci}
3856a23e08bSopenharmony_ci
3866a23e08bSopenharmony_cimodule.exports = {
3876a23e08bSopenharmony_ci  liteNativeTag: liteNativeTag,
3886a23e08bSopenharmony_ci  liteCommonTag: liteCommonTag,
3896a23e08bSopenharmony_ci};
390