1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 | import * as _ from 'lodash/fp'
|
33 | import * as fs from 'fs-extra'
|
34 | import * as path from 'path'
|
35 | import { chalk } from '@tarojs/helper'
|
36 |
|
37 | import { IErrorLine } from './interface'
|
38 |
|
39 | const xml2js = require('xml2js')
|
40 |
|
41 | const ABILITYXML = ['ability.xml']
|
42 |
|
43 | export default async function ({ appPath }) {
|
44 | const PROJECT_PACKAGE_PATH = path.join(appPath, 'package.json')
|
45 | const PROJECT_FOLDER_FILES = fs.readdirSync('./')
|
46 | if (!fs.existsSync(PROJECT_PACKAGE_PATH)) {
|
47 | console.log(chalk.red(`找不到${PROJECT_PACKAGE_PATH},请确定当前目录是Taro项目根目录!`))
|
48 | process.exit(1)
|
49 | }
|
50 |
|
51 | const inProjectFolder = filenames => (_.intersectionBy(_.toLower, PROJECT_FOLDER_FILES, filenames)).length > 0
|
52 | const hasAbilityXML = inProjectFolder(ABILITYXML)
|
53 |
|
54 | const errorLines: IErrorLine[] = []
|
55 |
|
56 | if (!hasAbilityXML) {
|
57 | errorLines.push({
|
58 | desc: '没有检查到 ability.xml, 编写 ability.xml可以让其他应用方便地叫起应用内服务',
|
59 | valid: true
|
60 | })
|
61 | } else {
|
62 | const PROJECT_ABILITY_FILE_PATH = path.join(appPath, 'ability.xml')
|
63 | const data = fs.readFileSync(PROJECT_ABILITY_FILE_PATH)
|
64 |
|
65 | xml2js.parseString(data, function(err, result){
|
66 |
|
67 | if (err) {
|
68 | errorLines.push({
|
69 | desc: 'ability.xml 解析错误,请检查文件格式!',
|
70 | valid: true
|
71 | })
|
72 | } else {
|
73 |
|
74 | const abilities = result.aml.ability;
|
75 | if (abilities == null) {
|
76 | errorLines.push({
|
77 | desc: '没有发现 ability声明, 请检查是否定义完整',
|
78 | valid: true
|
79 | })
|
80 | } else {
|
81 |
|
82 | const intentRegex = /ability.intent.[0-9A-Z_]+$/
|
83 | const parameterRegex = /^[A-Za-z0-9_]+$/
|
84 |
|
85 | for(const x in abilities){
|
86 | const abilityIndex = parseInt(x, 10) + 1
|
87 |
|
88 |
|
89 | if(!intentRegex.test(abilities[x].$.intent)){
|
90 | errorLines.push({
|
91 | desc: '第'+abilityIndex+'个ability的intent格式错误',
|
92 | valid: true,
|
93 | solution: 'intent 必须声明为格式为ability.intent.xxx的字符串,xxx可以包含数字,大写字母和下划线'
|
94 | })
|
95 | }
|
96 |
|
97 |
|
98 | const services = abilities[x].service;
|
99 |
|
100 | if (services == null) {
|
101 | errorLines.push({
|
102 | desc: '第'+abilityIndex+'个ability没有发现 service声明, 请检查是否定义完整',
|
103 | valid: true
|
104 | })
|
105 | } else {
|
106 | for (const y in services) {
|
107 | const serviceIndex = parseInt(y, 10) + 1
|
108 |
|
109 |
|
110 | if(!parameterRegex.test(services[y].parameter[0].$.linkParameter)){
|
111 | errorLines.push({
|
112 | desc: '第'+abilityIndex+'个ability的第'+serviceIndex+'个service linkParameter 格式错误',
|
113 | valid: true,
|
114 | solution: 'linkParameter 只能包含数字,大写字母,小写字母和下划线'
|
115 | })
|
116 | }
|
117 |
|
118 |
|
119 | if(!parameterRegex.test(services[y].parameter[0].$.intentParameter)){
|
120 | errorLines.push({
|
121 | desc: '第'+abilityIndex+'个ability的第'+serviceIndex+'个service intentParameter 格式错误',
|
122 | valid: true,
|
123 | solution: 'intentParameter 只能包含数字,大写字母,小写字母和下划线'
|
124 | })
|
125 | }
|
126 | }
|
127 | }
|
128 | }
|
129 | }
|
130 | }
|
131 | })
|
132 | }
|
133 |
|
134 | return {
|
135 | desc: '检查原子化服务规范',
|
136 | lines: errorLines
|
137 | }
|
138 | }
|