• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15const isType = require('../lite/lite-utils');
16const rulePath = process.env.RULE_PATH;
17const smartvisionTag = {
18  camera: {
19    events: ['error'],
20  },
21  video: {
22    events: [
23      'prepared',
24      'start',
25      'pause',
26      'finish',
27      'error',
28      'seeking',
29      'seeked',
30      'timeupdate',
31    ],
32    attrs: {
33      autoplay: {
34        enum: ['false', 'true'],
35      },
36      controls: {
37        enum: ['true', 'false'],
38      },
39      muted: {
40        enum: ['false', 'true'],
41      },
42      src: { checkPath: true },
43    },
44  },
45};
46
47const litewearableTag = {
48  'div': {},
49  'canvas': {},
50  'stack': {},
51  'qrcode': {
52    atomic: true,
53    selfClosing: true,
54    uevents: ['click', 'longpress', 'swipe'],
55    attrs: {
56      value: {
57        required: true,
58      },
59      type: {
60        enum: ['rect', 'circle'],
61      },
62    },
63  },
64  'list': {
65    events: ['scrollend'],
66    children: ['list-item'],
67  },
68  'list-item': {
69    excludeRoot: true,
70    parents: ['list'],
71  },
72  'swiper': {
73    unSupportedChildren: ['list'],
74    events: ['change'],
75    attrs: {
76      index: {
77        checkFunc: 'number',
78      },
79      loop: {
80        enum: ['true', 'false'],
81      },
82      duration: {
83        checkFunc: 'number',
84      },
85      vertical: {
86        enum: ['false', 'true'],
87      },
88    },
89  },
90  'tabs': {
91    events: ['change'],
92    children: ['tab-content', 'tab-bar'],
93  },
94  'tab-bar': {
95    parents: ['tabs'],
96    children: ['text'],
97    attrs: {
98      mode: {
99        enum: ['fixed'],
100      },
101    },
102  },
103  'tab-content': {
104    parents: ['tabs'],
105    children: ['div', 'stack'], // to be checked
106  },
107  'image-animator': {
108    atomic: true,
109    selfClosing: true,
110    events: ['stop'],
111    attrs: {
112      images: {
113        required: true,
114      },
115      iteration: {},
116      reverse: {
117        enum: ['false', 'true'],
118      },
119      fixedsize: {
120        enum: ['true', 'false'],
121      },
122      duration: {
123        required: true,
124      },
125      fillmode: {
126        enum: ['none', 'forwards'],
127      },
128    },
129  },
130  'image': {
131    alias: ['img'],
132    atomic: true,
133    selfClosing: true,
134    attrs: {
135      src: {
136        checkPath: true,
137      },
138    },
139  },
140  'progress': {
141    atomic: true,
142    selfClosing: true,
143    attrs: {
144      type: {
145        enum: ['horizontal', 'arc'],
146      },
147      percent: {
148        checkFunc: 'number',
149      },
150    },
151  },
152  'text': {
153    atomic: true,
154    textContent: true,
155    attrs: {
156      type: {
157        enum: ['text', 'html'],
158      },
159      value: {},
160    },
161  },
162  'marquee': {
163    atomic: true,
164    attrs: {
165      scrollamount: {
166        def: 6,
167        checkFunc: 'number',
168      },
169    },
170  },
171  'analog-clock': {
172    attrs: {
173      hour: {
174        checkFunc: 'number',
175      },
176      min: {
177        checkFunc: 'number',
178      },
179      sec: {
180        checkFunc: 'number',
181      },
182    },
183  },
184  'clock-hand': {
185    parents: ['analog-clock'],
186    attrs: {
187      type: {
188        enum: ['hour', 'min', 'sec'],
189      },
190      src: {
191        checkPath: true,
192      },
193    },
194  },
195  'chart': {
196    atomic: true,
197    selfClosing: true,
198    attrs: {
199      type: {
200        enum: ['line', 'bar'],
201      },
202      datasets: {},
203      options: {},
204    },
205  },
206  'input': {
207    atomic: true,
208    selfClosing: true,
209    events: ['change'],
210    attrs: {
211      checked: {
212        enum: ['false', 'true'],
213      },
214      type: {
215        enum: ['button', 'checkbox', 'radio'],
216      },
217      name: {},
218      value: {},
219    },
220  },
221  'slider': {
222    atomic: true,
223    selfClosing: true,
224    events: ['change'],
225    attrs: {
226      min: {
227        def: 0,
228        checkFunc: 'number',
229      },
230      max: {
231        def: 100,
232        checkFunc: 'number',
233      },
234      value: {
235        def: 0,
236        checkFunc: 'number',
237      },
238    },
239  },
240  'switch': {
241    events: ['change'],
242    atomic: true,
243    selfClosing: true,
244    attrs: {
245      checked: {
246        enum: ['false', 'true'],
247      },
248    },
249  },
250  'picker-view': {
251    atomic: true,
252    selfClosing: true,
253    uevents: ['change'],
254    attrs: {
255      type: {
256        enum: ['text', 'time'],
257      },
258      range: {},
259      selected: {},
260    },
261  },
262};
263
264const liteCommonTag = {
265  events: [
266    'click',
267    'longpress',
268    'touchstart',
269    'touchmove',
270    'touchcancel',
271    'touchend',
272    'key',
273    'swipe',
274  ],
275  attrs: {
276    id: {},
277    style: {},
278    class: {},
279    ref: {},
280    if: {
281      excludeRoot: true,
282      def: 'true',
283    },
284    elif: {
285      def: 'true',
286    },
287    else: {
288      excludeRoot: true,
289    },
290    for: {
291      excludeRoot: true,
292    },
293    tid: {},
294    show: {
295      excludeRoot: true,
296      def: 'true',
297    },
298  },
299};
300
301/**
302 * Rules for adapting to different environments. If it is `liteWearable` device type,
303 * set to this type of verification rule.
304 * @param {String} deviceType device type.
305 * @return {Object} Validation rules.
306 */
307function select(deviceType) {
308  tag = {
309    liteWearable: litewearableTag,
310    smartVision: { ...litewearableTag, ...smartvisionTag },
311  };
312  return tag[deviceType];
313}
314let liteNativeTag = select(process.env.DEVICE_TYPE);
315
316/**
317 * Whether the file exists, get customized rules.
318 */
319(function checkFile() {
320  if (rulePath) {
321    const customTag = require(rulePath);
322    isExtends(customTag);
323  }
324})();
325
326/**
327 * Get the component types supported by the current verification rule.
328 * @return {Array} Supported component name.
329 */
330function getKeys() {
331  const res = [];
332  const keys = Object.keys(liteNativeTag);
333  for (let i = 0; i < keys.length; i++) {
334    const key = keys[i];
335    res.push(key);
336  }
337  res.push('attrs');
338  return res;
339}
340
341/**
342 * According to user-defined rules, combine into new verification rules.
343 * @param {Object} customTag User-defined rule object.
344 */
345function isExtends(customTag) {
346  if (customTag.extends == 'recommended') {
347    const nativekeys = getKeys();
348    merge(liteNativeTag, customTag.rules, nativekeys);
349  } else {
350    liteNativeTag = customTag.rules;
351  }
352}
353/**
354 * Combine the original rules and user-defined rules.
355 * @param {Object} object Original rules.
356 * @param {Object} source user-defined rules.
357 * @param {Array} nativekeys Supported component name.
358 * @return {Array} Merged object.
359 */
360function merge(object, source, nativekeys) {
361  const keys = Object.keys(source);
362  for (let i = 0; i < keys.length; i++) {
363    const key = keys[i];
364    const value = source[key];
365    let target = object[key];
366    if (target != null && !nativekeys.includes(key)) {
367      console.error(
368          `\u001b[31mError in .literc.js: \n` +
369          `Attribute '${key}' already exists and cannot be modified\u001b[39m`,
370      );
371      process.exit(1);
372    } else if (isType.isObject(value)) {
373      target = isType.isObject(target) ? target : {};
374      object[key] = merge(target, value, nativekeys);
375    } else if (!(isType.isNull(value) || isType.isUndefined(value))) {
376      object[key] = value;
377    }
378  }
379  return object;
380}
381
382module.exports = {
383  liteNativeTag: liteNativeTag,
384  liteCommonTag: liteCommonTag,
385};
386