autosnippet 1.1.13 → 1.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -36
- package/bin/asnip.js +58 -8
- package/bin/cache.js +7 -8
- package/bin/config.js +39 -0
- package/bin/create.js +157 -44
- package/bin/findPath.js +388 -132
- package/bin/init.js +7 -3
- package/bin/injection.js +49 -79
- package/bin/install.js +126 -13
- package/package.json +4 -4
package/bin/findPath.js
CHANGED
|
@@ -4,189 +4,445 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
// 全局常量
|
|
6
6
|
const HOLDER_NAME = 'AutoSnippet.boxspec.json';
|
|
7
|
-
const
|
|
8
|
-
const POD_SPEC_NAME = '.podspec';
|
|
7
|
+
const PACKAGE_SWIFT = 'Package.swift';
|
|
9
8
|
const README_NAME = 'readme.md';
|
|
10
|
-
const PCH_NAME = '.pch';
|
|
11
9
|
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (err) {
|
|
16
|
-
console.log(err);
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
let isEnd = false;
|
|
21
|
-
files.forEach(function (filename) {
|
|
10
|
+
// 目录缓存(优化:减少重复读取)
|
|
11
|
+
const directoryCache = new Map();
|
|
12
|
+
const CACHE_TTL = 60000; // 缓存 60 秒
|
|
22
13
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
/**
|
|
15
|
+
* 获取目录内容(带缓存)
|
|
16
|
+
*/
|
|
17
|
+
async function getDirectoryEntries(dirPath) {
|
|
18
|
+
const cacheKey = path.resolve(dirPath);
|
|
19
|
+
const cached = directoryCache.get(cacheKey);
|
|
20
|
+
|
|
21
|
+
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
|
|
22
|
+
return cached.entries;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const entries = await fs.promises.readdir(dirPath, {
|
|
27
|
+
withFileTypes: true // 返回 Dirent 对象,减少 stat 调用
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// 清理过期缓存(保持缓存大小合理)
|
|
31
|
+
if (directoryCache.size > 1000) {
|
|
32
|
+
const now = Date.now();
|
|
33
|
+
for (const [key, value] of directoryCache.entries()) {
|
|
34
|
+
if (now - value.timestamp >= CACHE_TTL) {
|
|
35
|
+
directoryCache.delete(key);
|
|
36
|
+
}
|
|
26
37
|
}
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
if (isEnd) {
|
|
30
|
-
return;
|
|
31
38
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
|
|
40
|
+
directoryCache.set(cacheKey, {
|
|
41
|
+
entries,
|
|
42
|
+
timestamp: Date.now()
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return entries;
|
|
46
|
+
} catch (err) {
|
|
47
|
+
if (err.code === 'ENOENT' || err.code === 'EACCES') {
|
|
48
|
+
return null; // 路径不存在或权限不足
|
|
37
49
|
}
|
|
38
|
-
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
39
52
|
}
|
|
40
53
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
/**
|
|
55
|
+
* 检测是否为工程根目录
|
|
56
|
+
* 通过查找常见的工程根目录标记来判断
|
|
57
|
+
*/
|
|
58
|
+
function isProjectRoot(dirPath, entries) {
|
|
59
|
+
if (!entries) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 工程根目录标记(按优先级)
|
|
64
|
+
const rootMarkers = [
|
|
65
|
+
'.git', // Git 仓库根目录
|
|
66
|
+
PACKAGE_SWIFT, // SPM 项目根目录
|
|
67
|
+
'.xcodeproj', // Xcode 项目根目录
|
|
68
|
+
'.xcworkspace', // Xcode 工作空间根目录
|
|
69
|
+
'Podfile', // CocoaPods 项目根目录
|
|
70
|
+
'.swiftpm', // Swift Package Manager 元数据目录
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
for (const entry of entries) {
|
|
74
|
+
const name = entry.name;
|
|
75
|
+
|
|
76
|
+
// 检查文件标记
|
|
77
|
+
if (entry.isFile() && rootMarkers.includes(name)) {
|
|
78
|
+
return true;
|
|
47
79
|
}
|
|
80
|
+
|
|
81
|
+
// 检查目录标记(.git 可能是目录)
|
|
82
|
+
if (entry.isDirectory() && rootMarkers.includes(name)) {
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
48
89
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
90
|
+
// 向上查找AutoSnippet配置文件(优化:找到配置文件后,继续向上查找直到找到工程根目录)
|
|
91
|
+
async function findASSpecPathAsync(filePath) {
|
|
92
|
+
let configPath = null;
|
|
93
|
+
let configDir = null;
|
|
94
|
+
let currentPath = path.resolve(filePath);
|
|
95
|
+
const maxLevels = 20; // 安全限制:最多向上查找 20 层
|
|
96
|
+
let levelsChecked = 0;
|
|
97
|
+
|
|
98
|
+
while (currentPath && levelsChecked < maxLevels) {
|
|
99
|
+
try {
|
|
100
|
+
const entries = await getDirectoryEntries(currentPath);
|
|
101
|
+
|
|
102
|
+
// 查找 AutoSnippet.boxspec.json
|
|
103
|
+
if (entries) {
|
|
104
|
+
for (const entry of entries) {
|
|
105
|
+
if (entry.isFile() && entry.name === HOLDER_NAME) {
|
|
106
|
+
if (!configPath) {
|
|
107
|
+
// 第一次找到配置文件
|
|
108
|
+
configPath = path.join(currentPath, entry.name);
|
|
109
|
+
configDir = currentPath;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
55
113
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
114
|
+
|
|
115
|
+
// 如果已经找到配置文件,检查是否到达工程根目录
|
|
116
|
+
if (configPath) {
|
|
117
|
+
// 如果在配置文件所在目录或以上发现了工程根目录标记,停止查找
|
|
118
|
+
if (isProjectRoot(currentPath, entries)) {
|
|
119
|
+
return configPath;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// 如果已经向上查找了,但没有找到工程根目录标记,继续查找
|
|
123
|
+
if (path.resolve(currentPath) !== configDir) {
|
|
124
|
+
// 当前目录不是配置文件所在目录,继续向上查找
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 继续向上查找
|
|
129
|
+
const parentPath = path.dirname(currentPath);
|
|
130
|
+
if (parentPath === currentPath) {
|
|
131
|
+
// 已到达根目录
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
currentPath = parentPath;
|
|
135
|
+
levelsChecked++;
|
|
136
|
+
|
|
137
|
+
} catch (err) {
|
|
138
|
+
// 错误处理:权限错误继续查找
|
|
139
|
+
if (err.code === 'ENOENT' || err.code === 'EACCES') {
|
|
140
|
+
const parentPath = path.dirname(currentPath);
|
|
141
|
+
if (parentPath === currentPath) {
|
|
142
|
+
break;
|
|
143
|
+
}
|
|
144
|
+
currentPath = parentPath;
|
|
145
|
+
levelsChecked++;
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
// 其他错误,抛出
|
|
149
|
+
throw err;
|
|
60
150
|
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// 如果找到配置文件,返回它(即使没有找到明确的工程根目录)
|
|
154
|
+
return configPath || null;
|
|
155
|
+
}
|
|
61
156
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
157
|
+
/**
|
|
158
|
+
* 同步版本:检测是否为工程根目录
|
|
159
|
+
*/
|
|
160
|
+
function isProjectRootSync(dirPath, files) {
|
|
161
|
+
if (!files || files.length === 0) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// 工程根目录标记(按优先级)
|
|
166
|
+
const rootMarkers = [
|
|
167
|
+
'.git', // Git 仓库根目录
|
|
168
|
+
PACKAGE_SWIFT, // SPM 项目根目录
|
|
169
|
+
'.xcodeproj', // Xcode 项目根目录
|
|
170
|
+
'.xcworkspace', // Xcode 工作空间根目录
|
|
171
|
+
'Podfile', // CocoaPods 项目根目录
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
// 检查文件名
|
|
175
|
+
for (const filename of files) {
|
|
176
|
+
if (rootMarkers.includes(filename)) {
|
|
177
|
+
// 检查是否为文件或目录
|
|
178
|
+
try {
|
|
179
|
+
const filePath = path.join(dirPath, filename);
|
|
180
|
+
const stats = fs.lstatSync(filePath);
|
|
181
|
+
if (stats.isFile() || stats.isDirectory()) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
} catch (err) {
|
|
185
|
+
// 忽略错误,继续检查
|
|
186
|
+
}
|
|
66
187
|
}
|
|
67
|
-
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return false;
|
|
68
191
|
}
|
|
69
192
|
|
|
70
|
-
//
|
|
71
|
-
function
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
193
|
+
// 向上查找AutoSnippet配置文件(保留回调版本,兼容现有代码)
|
|
194
|
+
function findASSpecPath(filePath, callback, configPath, configDir) {
|
|
195
|
+
// 初始化参数
|
|
196
|
+
if (configPath === undefined) configPath = null;
|
|
197
|
+
if (configDir === undefined) configDir = null;
|
|
198
|
+
|
|
199
|
+
const maxLevels = 20; // 安全限制:最多向上查找 20 层
|
|
200
|
+
let levelsChecked = 0;
|
|
201
|
+
|
|
202
|
+
function search(currentPath, foundConfigPath, foundConfigDir, level) {
|
|
203
|
+
if (level >= maxLevels) {
|
|
204
|
+
if (foundConfigPath) {
|
|
205
|
+
callback(foundConfigPath);
|
|
206
|
+
} else {
|
|
207
|
+
console.log('未找到 AutoSnippet.boxspec.json 文件,请检查路径。');
|
|
208
|
+
}
|
|
75
209
|
return;
|
|
76
210
|
}
|
|
211
|
+
|
|
212
|
+
fs.readdir(currentPath, function (err, files) {
|
|
213
|
+
if (err) {
|
|
214
|
+
// 错误处理:权限错误继续查找
|
|
215
|
+
if (err.code === 'ENOENT' || err.code === 'EACCES') {
|
|
216
|
+
const parentPath = path.join(currentPath, '/..');
|
|
217
|
+
const parentResolvedPath = path.resolve(parentPath);
|
|
218
|
+
|
|
219
|
+
// 如果已经到达根目录,停止查找
|
|
220
|
+
if (parentResolvedPath === path.resolve(currentPath)) {
|
|
221
|
+
if (foundConfigPath) {
|
|
222
|
+
callback(foundConfigPath);
|
|
223
|
+
} else {
|
|
224
|
+
console.log('未找到 AutoSnippet.boxspec.json 文件,请检查路径。');
|
|
225
|
+
}
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
search(parentPath, foundConfigPath, foundConfigDir, level + 1);
|
|
230
|
+
} else {
|
|
231
|
+
console.log(err);
|
|
232
|
+
}
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
77
235
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
236
|
+
let isFound = false;
|
|
237
|
+
let currentConfigPath = foundConfigPath;
|
|
238
|
+
let currentConfigDir = foundConfigDir;
|
|
239
|
+
|
|
240
|
+
// 查找 AutoSnippet.boxspec.json
|
|
241
|
+
files.forEach(function (filename) {
|
|
242
|
+
if (filename === HOLDER_NAME) {
|
|
243
|
+
isFound = true;
|
|
244
|
+
if (!currentConfigPath) {
|
|
245
|
+
// 第一次找到配置文件,记录路径(不立即调用回调)
|
|
246
|
+
currentConfigPath = path.join(currentPath, filename);
|
|
247
|
+
currentConfigDir = path.resolve(currentPath);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
});
|
|
82
251
|
|
|
83
|
-
|
|
84
|
-
if (
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
252
|
+
// 如果已经找到配置文件,检查是否到达工程根目录
|
|
253
|
+
if (currentConfigPath) {
|
|
254
|
+
// 如果在配置文件所在目录或以上发现了工程根目录标记,停止查找并调用回调
|
|
255
|
+
if (isProjectRootSync(currentPath, files)) {
|
|
256
|
+
callback(currentConfigPath);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
89
259
|
}
|
|
90
|
-
if (filename.endsWith(BOX_SPEC_NAME) || filename.endsWith(POD_SPEC_NAME)) {
|
|
91
|
-
const dotIndex = filename.lastIndexOf('.');
|
|
92
|
-
const ext = filename.substr(dotIndex);
|
|
93
260
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
261
|
+
// 继续向上查找
|
|
262
|
+
const parentPath = path.join(currentPath, '/..');
|
|
263
|
+
const parentResolvedPath = path.resolve(parentPath);
|
|
264
|
+
|
|
265
|
+
// 如果已经到达根目录,停止查找
|
|
266
|
+
if (parentResolvedPath === path.resolve(currentPath)) {
|
|
267
|
+
// 如果找到了配置文件,即使没找到工程根目录标记,也调用回调
|
|
268
|
+
if (currentConfigPath) {
|
|
269
|
+
callback(currentConfigPath);
|
|
270
|
+
} else {
|
|
271
|
+
console.log('未找到 AutoSnippet.boxspec.json 文件,请检查路径。');
|
|
272
|
+
}
|
|
273
|
+
return;
|
|
98
274
|
}
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
if (isEnd && specName) {
|
|
102
|
-
callback(filePath, specName, readme);
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
275
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
276
|
+
search(parentPath, currentConfigPath, currentConfigDir, level + 1);
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
search(filePath, configPath, configDir, 0);
|
|
281
|
+
}
|
|
110
282
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
283
|
+
// 向上查找 Package.swift 文件(SPM 模块规范文件)
|
|
284
|
+
async function findPackageSwiftPath(filePath) {
|
|
285
|
+
let currentPath = path.resolve(filePath);
|
|
286
|
+
|
|
287
|
+
while (currentPath) {
|
|
288
|
+
try {
|
|
289
|
+
const entries = await getDirectoryEntries(currentPath);
|
|
290
|
+
if (!entries) {
|
|
291
|
+
const parentPath = path.dirname(currentPath);
|
|
292
|
+
if (parentPath === currentPath) {
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
currentPath = parentPath;
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// 查找 Package.swift 文件
|
|
300
|
+
for (const entry of entries) {
|
|
301
|
+
if (entry.isFile() && entry.name === PACKAGE_SWIFT) {
|
|
302
|
+
return path.join(currentPath, entry.name);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// 继续向上查找
|
|
307
|
+
const parentPath = path.dirname(currentPath);
|
|
308
|
+
if (parentPath === currentPath) {
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
currentPath = parentPath;
|
|
312
|
+
|
|
313
|
+
} catch (err) {
|
|
314
|
+
if (err.code === 'ENOENT' || err.code === 'EACCES') {
|
|
315
|
+
const parentPath = path.dirname(currentPath);
|
|
316
|
+
if (parentPath === currentPath) {
|
|
317
|
+
break;
|
|
318
|
+
}
|
|
319
|
+
currentPath = parentPath;
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
throw err;
|
|
115
323
|
}
|
|
116
|
-
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return null;
|
|
117
327
|
}
|
|
118
328
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
329
|
+
/**
|
|
330
|
+
* 解析 Package.swift 文件,提取模块信息
|
|
331
|
+
*/
|
|
332
|
+
async function parsePackageSwift(packagePath) {
|
|
123
333
|
try {
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
334
|
+
const content = await fs.promises.readFile(packagePath, 'utf8');
|
|
335
|
+
|
|
336
|
+
// 简单解析 Package.swift(实际可以使用 Swift AST 解析器)
|
|
337
|
+
const packageNameMatch = content.match(/name:\s*"([^"]+)"/);
|
|
338
|
+
const targetsMatch = content.match(/\.target\s*\([^)]+name:\s*"([^"]+)"/g);
|
|
339
|
+
|
|
340
|
+
const packageName = packageNameMatch ? packageNameMatch[1] : null;
|
|
341
|
+
const targets = [];
|
|
342
|
+
|
|
343
|
+
if (targetsMatch) {
|
|
344
|
+
targetsMatch.forEach(match => {
|
|
345
|
+
const targetMatch = match.match(/name:\s*"([^"]+)"/);
|
|
346
|
+
if (targetMatch) {
|
|
347
|
+
targets.push(targetMatch[1]);
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return {
|
|
353
|
+
name: packageName,
|
|
354
|
+
targets: targets,
|
|
355
|
+
path: path.dirname(packagePath)
|
|
356
|
+
};
|
|
357
|
+
} catch (err) {
|
|
358
|
+
console.error('Error parsing Package.swift:', err);
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
129
362
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
363
|
+
// 向下查找模块头文件(优化:适配 SPM 结构,优先查找 include/ModuleName/ 目录)
|
|
364
|
+
async function findSubHeaderPath(filePath, headerName, moduleName) {
|
|
365
|
+
// ✅ 优先查找 include/ModuleName/ 目录(SPM 结构)
|
|
366
|
+
if (moduleName) {
|
|
367
|
+
const includePath = path.join(filePath, 'include', moduleName);
|
|
368
|
+
try {
|
|
369
|
+
const stats = await fs.promises.stat(includePath);
|
|
370
|
+
if (stats.isDirectory()) {
|
|
371
|
+
const headerPath = path.join(includePath, `${headerName}.h`);
|
|
134
372
|
try {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
373
|
+
await fs.promises.access(headerPath);
|
|
374
|
+
return headerPath;
|
|
375
|
+
} catch {
|
|
376
|
+
// 头文件不存在,继续查找
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
} catch {
|
|
380
|
+
// include 目录不存在,继续查找
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// ✅ 降级:在整个模块目录中查找(深度限制)
|
|
385
|
+
try {
|
|
386
|
+
const entries = await getDirectoryEntries(filePath);
|
|
387
|
+
if (!entries) {
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
for (const entry of entries) {
|
|
392
|
+
if (entry.isFile() && entry.name === `${headerName}.h`) {
|
|
393
|
+
return path.join(filePath, entry.name);
|
|
394
|
+
} else if (entry.isDirectory()) {
|
|
395
|
+
// 跳过 node_modules、.git 等目录
|
|
396
|
+
if (entry.name.startsWith('.') || entry.name === 'node_modules') {
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const result = await findSubHeaderPath(path.join(filePath, entry.name), headerName, null);
|
|
401
|
+
if (result) {
|
|
402
|
+
return result;
|
|
146
403
|
}
|
|
147
404
|
}
|
|
148
405
|
}
|
|
149
406
|
} catch (err) {
|
|
150
|
-
console.
|
|
407
|
+
console.error(err);
|
|
151
408
|
}
|
|
152
|
-
|
|
409
|
+
|
|
410
|
+
return null;
|
|
153
411
|
}
|
|
154
412
|
|
|
155
|
-
// 向下查找AutoSnippet
|
|
413
|
+
// 向下查找AutoSnippet配置文件(优化:异步 I/O)
|
|
156
414
|
async function findSubASSpecPath(filePath) {
|
|
157
415
|
let resultArray = [];
|
|
158
416
|
|
|
159
417
|
try {
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const filedir = path.join(filePath, filename);
|
|
418
|
+
const entries = await getDirectoryEntries(filePath);
|
|
419
|
+
if (!entries) {
|
|
420
|
+
return resultArray;
|
|
421
|
+
}
|
|
165
422
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (isDirectory) {
|
|
174
|
-
const array = await findSubASSpecPath(filedir);
|
|
175
|
-
resultArray = resultArray.concat(array);
|
|
176
|
-
}
|
|
177
|
-
} catch (err) {
|
|
178
|
-
console.error(err);
|
|
423
|
+
for (const entry of entries) {
|
|
424
|
+
if (entry.isFile() && entry.name === HOLDER_NAME) {
|
|
425
|
+
resultArray.push(path.join(filePath, entry.name));
|
|
426
|
+
} else if (entry.isDirectory()) {
|
|
427
|
+
// 跳过 node_modules、.git 等目录
|
|
428
|
+
if (entry.name.startsWith('.') || entry.name === 'node_modules') {
|
|
429
|
+
continue;
|
|
179
430
|
}
|
|
431
|
+
|
|
432
|
+
const array = await findSubASSpecPath(path.join(filePath, entry.name));
|
|
433
|
+
resultArray = resultArray.concat(array);
|
|
180
434
|
}
|
|
181
435
|
}
|
|
182
436
|
} catch (err) {
|
|
183
437
|
console.log(err);
|
|
184
438
|
}
|
|
439
|
+
|
|
185
440
|
return resultArray;
|
|
186
441
|
}
|
|
187
442
|
|
|
188
443
|
exports.findASSpecPath = findASSpecPath;
|
|
189
|
-
exports.
|
|
190
|
-
exports.
|
|
444
|
+
exports.findASSpecPathAsync = findASSpecPathAsync;
|
|
445
|
+
exports.findPackageSwiftPath = findPackageSwiftPath;
|
|
446
|
+
exports.parsePackageSwift = parsePackageSwift;
|
|
191
447
|
exports.findSubHeaderPath = findSubHeaderPath;
|
|
192
|
-
exports.findSubASSpecPath = findSubASSpecPath;
|
|
448
|
+
exports.findSubASSpecPath = findSubASSpecPath;
|
package/bin/init.js
CHANGED
|
@@ -47,10 +47,14 @@ async function initSpec() {
|
|
|
47
47
|
return false;
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
//
|
|
50
|
+
idsArray.push(item['{identifier}']);
|
|
51
|
+
// ✅ 头文件相对路径需要补齐(将子配置的相对路径转换为相对于主配置的路径)
|
|
52
52
|
if (item['{specHeadPath}']) {
|
|
53
|
-
|
|
53
|
+
// 解码原始路径,拼接子配置路径,再编码
|
|
54
|
+
const decodedPath = decodeURI(item['{specHeadPath}']);
|
|
55
|
+
const combinedPath = thePath ? path.join(thePath, decodedPath) : decodedPath;
|
|
56
|
+
// 规范化路径(处理 .. 和 .)
|
|
57
|
+
item['{specHeadPath}'] = encodeURI(path.normalize(combinedPath));
|
|
54
58
|
}
|
|
55
59
|
return true;
|
|
56
60
|
});
|