• 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', 'password', 'radio', 'text'],
216      },
217      name: {},
218      value: {},
219      placeholder: {},
220      maxlength: {
221        checkFunc: 'number',
222      },
223    },
224  },
225  'slider': {
226    atomic: true,
227    selfClosing: true,
228    events: ['change'],
229    attrs: {
230      min: {
231        def: 0,
232        checkFunc: 'number',
233      },
234      max: {
235        def: 100,
236        checkFunc: 'number',
237      },
238      value: {
239        def: 0,
240        checkFunc: 'number',
241      },
242    },
243  },
244  'switch': {
245    events: ['change'],
246    atomic: true,
247    selfClosing: true,
248    attrs: {
249      checked: {
250        enum: ['false', 'true'],
251      },
252    },
253  },
254  'picker-view': {
255    atomic: true,
256    selfClosing: true,
257    uevents: ['change'],
258    attrs: {
259      type: {
260        enum: ['text', 'time'],
261      },
262      range: {},
263      selected: {},
264    },
265  },
266};
267
268const liteCommonTag = {
269  events: [
270    'click',
271    'longpress',
272    'touchstart',
273    'touchmove',
274    'touchcancel',
275    'touchend',
276    'key',
277    'swipe',
278  ],
279  attrs: {
280    id: {},
281    style: {},
282    class: {},
283    ref: {},
284    if: {
285      excludeRoot: true,
286      def: 'true',
287    },
288    elif: {
289      def: 'true',
290    },
291    else: {
292      excludeRoot: true,
293    },
294    for: {
295      excludeRoot: true,
296    },
297    tid: {},
298    show: {
299      excludeRoot: true,
300      def: 'true',
301    },
302  },
303};
304
305/**
306 * Rules for adapting to different environments. If it is `liteWearable` device type,
307 * set to this type of verification rule.
308 * @param {String} deviceType device type.
309 * @return {Object} Validation rules.
310 */
311function select(deviceType) {
312  tag = {
313    liteWearable: litewearableTag,
314    smartVision: { ...litewearableTag, ...smartvisionTag },
315  };
316  return tag[deviceType];
317}
318let liteNativeTag = select(process.env.DEVICE_TYPE);
319
320/**
321 * Whether the file exists, get customized rules.
322 */
323(function checkFile() {
324  if (rulePath) {
325    const customTag = require(rulePath);
326    isExtends(customTag);
327  }
328})();
329
330/**
331 * Get the component types supported by the current verification rule.
332 * @return {Array} Supported component name.
333 */
334function getKeys() {
335  const res = [];
336  const keys = Object.keys(liteNativeTag);
337  for (let i = 0; i < keys.length; i++) {
338    const key = keys[i];
339    res.push(key);
340  }
341  res.push('attrs');
342  return res;
343}
344
345/**
346 * According to user-defined rules, combine into new verification rules.
347 * @param {Object} customTag User-defined rule object.
348 */
349function isExtends(customTag) {
350  if (customTag.extends == 'recommended') {
351    const nativekeys = getKeys();
352    merge(liteNativeTag, customTag.rules, nativekeys);
353  } else {
354    liteNativeTag = customTag.rules;
355  }
356}
357/**
358 * Combine the original rules and user-defined rules.
359 * @param {Object} object Original rules.
360 * @param {Object} source user-defined rules.
361 * @param {Array} nativekeys Supported component name.
362 * @return {Array} Merged object.
363 */
364function merge(object, source, nativekeys) {
365  const keys = Object.keys(source);
366  for (let i = 0; i < keys.length; i++) {
367    const key = keys[i];
368    const value = source[key];
369    let target = object[key];
370    if (target != null && !nativekeys.includes(key)) {
371      console.error(
372          `\u001b[31mError in .literc.js: \n` +
373          `Attribute '${key}' already exists and cannot be modified\u001b[39m`,
374      );
375      process.exit(1);
376    } else if (isType.isObject(value)) {
377      target = isType.isObject(target) ? target : {};
378      object[key] = merge(target, value, nativekeys);
379    } else if (!(isType.isNull(value) || isType.isUndefined(value))) {
380      object[key] = value;
381    }
382  }
383  return object;
384}
385
386module.exports = {
387  liteNativeTag: liteNativeTag,
388  liteCommonTag: liteCommonTag,
389};
390