spec-up-t 1.6.3-beta.1 → 1.6.3
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/.github/copilot-instructions.md +2 -0
- package/assets/compiled/body.js +9 -7
- package/assets/compiled/head.css +6 -6
- package/assets/css/adjust-font-size.css +0 -4
- package/assets/css/download-pdf-docx.css +19 -20
- package/assets/css/header-navbar.css +0 -4
- package/assets/css/index.css +36 -0
- package/assets/css/terms-and-definitions.css +0 -1
- package/assets/css/validate-external-refs.css +198 -3
- package/assets/js/add-href-to-snapshot-link.js +11 -5
- package/assets/js/download-pdf-docx.js +20 -9
- package/assets/js/edit-term-buttons.js +71 -68
- package/assets/js/github-issues.js +27 -27
- package/assets/js/insert-irefs.js +1 -1
- package/assets/js/validate-external-refs.js +356 -7
- package/package.json +3 -3
- package/src/add-remove-xref-source.js +0 -5
- package/src/collect-external-references.test.js +98 -0
- package/src/install-from-boilerplate/boilerplate/gitignore +2 -2
- package/src/install-from-boilerplate/boilerplate/menu-wrapper.sh +19 -0
- package/src/install-from-boilerplate/boilerplate/specs.json +3 -6
- package/src/install-from-boilerplate/config-scripts-keys.js +1 -1
- package/src/install-from-boilerplate/config-system-files.js +1 -0
- package/src/pipeline/references/collect-external-references.js +12 -0
- package/src/pipeline/references/external-references-service.js +1 -1
- package/src/pipeline/rendering/render-spec-document.js +5 -1
- package/templates/template.html +43 -10
- package/src/health-check/destination-gitignore-checker.js +0 -414
- package/src/health-check/external-specs-checker.js +0 -287
- package/src/health-check/specs-configuration-checker.js +0 -387
- package/src/health-check/term-references-checker.js +0 -270
- package/src/health-check/terms-intro-checker.js +0 -82
- package/src/health-check/tref-term-checker.js +0 -549
|
@@ -1,549 +0,0 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const { shouldProcessFile } = require('../utils/file-filter');
|
|
4
|
-
const Logger = require('../utils/logger');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Extracts the spec name and term from a tref tag at the beginning of a markdown file
|
|
8
|
-
* @param {string} firstLine - The first line of a markdown file
|
|
9
|
-
* @returns {Object|null} - Object containing repo and term, or null if not found
|
|
10
|
-
*/
|
|
11
|
-
function extractTrefInfo(firstLine) {
|
|
12
|
-
if (!firstLine.includes('[[tref:')) {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
// Extract content between [[tref: and ]]
|
|
18
|
-
const trefMatch = firstLine.match(/\[\[tref:([^\]]+)\]\]/);
|
|
19
|
-
if (!trefMatch?.length) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const trefContent = trefMatch[1]?.trim();
|
|
24
|
-
|
|
25
|
-
// Split by the first comma
|
|
26
|
-
const parts = trefContent.split(',');
|
|
27
|
-
if (parts.length < 2) {
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
// Extract repo and term
|
|
32
|
-
const repo = parts[0].trim();
|
|
33
|
-
const term = parts.slice(1).join(',').trim();
|
|
34
|
-
|
|
35
|
-
return { repo, term };
|
|
36
|
-
} catch (error) {
|
|
37
|
-
Logger.error('Error extracting tref info:', error);
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Find all JSON cache files for repositories
|
|
44
|
-
* @param {string} cacheDir - Directory containing the cached files
|
|
45
|
-
* @returns {Array} - List of all JSON cache files
|
|
46
|
-
*/
|
|
47
|
-
function findAllCacheFiles(cacheDir) {
|
|
48
|
-
if (!fs.existsSync(cacheDir)) {
|
|
49
|
-
return [];
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
try {
|
|
53
|
-
const files = fs.readdirSync(cacheDir)
|
|
54
|
-
.filter(file => file.endsWith('.json'))
|
|
55
|
-
.map(file => path.join(cacheDir, file));
|
|
56
|
-
|
|
57
|
-
return files;
|
|
58
|
-
} catch (error) {
|
|
59
|
-
Logger.error(`Error finding cache files:`, error);
|
|
60
|
-
return [];
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Checks if a term exists in a repository JSON cache file
|
|
66
|
-
* @param {string} filePath - Path to the cached repository file
|
|
67
|
-
* @param {string} term - Term to search for
|
|
68
|
-
* @returns {boolean} - Whether the term exists in the file
|
|
69
|
-
*/
|
|
70
|
-
function termExistsInRepo(filePath, term) {
|
|
71
|
-
if (!fs.existsSync(filePath)) {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
try {
|
|
76
|
-
const cacheData = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
77
|
-
|
|
78
|
-
// Check if the file has a terms array
|
|
79
|
-
if (!cacheData?.terms?.length) {
|
|
80
|
-
Logger.warn(`Cache file ${filePath} has no terms array`);
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Case-insensitive search for the term
|
|
85
|
-
const termLower = term.toLowerCase();
|
|
86
|
-
|
|
87
|
-
// Check each term in the terms array
|
|
88
|
-
for (const termObj of cacheData.terms) {
|
|
89
|
-
// First check the 'term' property if it exists
|
|
90
|
-
if (termObj.term?.toLowerCase() === termLower) {
|
|
91
|
-
return true;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// If there's a definition property, check if the term appears in it
|
|
95
|
-
if (termObj.definition) {
|
|
96
|
-
// Look for patterns like [[def: term]] or similar
|
|
97
|
-
const defMatch = termObj.definition.match(/\[\[def:\s*([^\],]+)/i);
|
|
98
|
-
if (defMatch?.[1]?.trim().toLowerCase() === termLower) {
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return false;
|
|
105
|
-
} catch (error) {
|
|
106
|
-
Logger.error(`Error checking if term exists in file ${filePath}:`, error);
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Find which repo a cache file belongs to
|
|
113
|
-
* @param {string} filePath - Path to the cache file
|
|
114
|
-
* @param {Array} externalSpecs - List of external specs
|
|
115
|
-
* @returns {string|null} - The external_spec identifier or null
|
|
116
|
-
*/
|
|
117
|
-
function findRepoForCacheFile(filePath, externalSpecs) {
|
|
118
|
-
try {
|
|
119
|
-
const cacheData = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
120
|
-
|
|
121
|
-
if (!cacheData?.repository) {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// Extract owner/repo from the repository field
|
|
126
|
-
const repoPath = cacheData.repository;
|
|
127
|
-
|
|
128
|
-
// Find matching external spec
|
|
129
|
-
for (const spec of externalSpecs) {
|
|
130
|
-
if (!spec.url) continue;
|
|
131
|
-
|
|
132
|
-
// Extract owner/repo from the URL
|
|
133
|
-
const match = spec.url.match(/github\.com\/([^/]+\/[^/]+)/i);
|
|
134
|
-
if (match?.[1] && repoPath.includes(match[1])) {
|
|
135
|
-
return spec.external_spec;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
return null;
|
|
140
|
-
} catch (error) {
|
|
141
|
-
Logger.error(`Error finding repository for cache file ${filePath}:`, error);
|
|
142
|
-
return null; // Could not determine repository due to error reading or parsing cache file
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Checks for specified term in all available external repos
|
|
148
|
-
* @param {string} cacheDir - Directory containing the cached repository files
|
|
149
|
-
* @param {Array} externalSpecs - List of external specs from specs.json
|
|
150
|
-
* @param {string} currentRepo - The repository being checked (to exclude it)
|
|
151
|
-
* @param {string} term - Term to search for
|
|
152
|
-
* @returns {Array} - List of repositories where the term was found
|
|
153
|
-
*/
|
|
154
|
-
function findTermInOtherRepos(cacheDir, externalSpecs, currentRepo, term) {
|
|
155
|
-
const reposWithTerm = [];
|
|
156
|
-
|
|
157
|
-
// Get all cache files
|
|
158
|
-
const cacheFiles = findAllCacheFiles(cacheDir);
|
|
159
|
-
|
|
160
|
-
for (const cacheFile of cacheFiles) {
|
|
161
|
-
// Check which repo this cache file belongs to
|
|
162
|
-
const repo = findRepoForCacheFile(cacheFile, externalSpecs);
|
|
163
|
-
|
|
164
|
-
// Skip if we couldn't determine which repo this is or if it's the current repo
|
|
165
|
-
if (!repo || repo === currentRepo) {
|
|
166
|
-
continue;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// Check if the term exists in this repo
|
|
170
|
-
if (termExistsInRepo(cacheFile, term)) {
|
|
171
|
-
reposWithTerm.push(repo);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
return reposWithTerm;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Find cache file for a specific external repo
|
|
180
|
-
* @param {string} cacheDir - Cache directory
|
|
181
|
-
* @param {Object} specConfig - External spec configuration
|
|
182
|
-
* @returns {string|null} - Path to the cache file or null
|
|
183
|
-
*/
|
|
184
|
-
function findCacheFileForRepo(cacheDir, specConfig) {
|
|
185
|
-
if (!fs.existsSync(cacheDir) || !specConfig?.url) {
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
try {
|
|
190
|
-
// Extract owner and repo from URL
|
|
191
|
-
const match = specConfig.url.match(/github\.com\/([^/]+)\/([^/]+)/i);
|
|
192
|
-
if (!match?.[1] || !match?.[2]) {
|
|
193
|
-
return null;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const owner = match[1];
|
|
197
|
-
const repo = match[2];
|
|
198
|
-
|
|
199
|
-
// Find all JSON files in the cache directory
|
|
200
|
-
const files = fs.readdirSync(cacheDir)
|
|
201
|
-
.filter(file => file.endsWith('.json'))
|
|
202
|
-
.map(file => ({
|
|
203
|
-
path: path.join(cacheDir, file),
|
|
204
|
-
name: file
|
|
205
|
-
}))
|
|
206
|
-
// Sort by timestamp descending (assuming timestamp is at the beginning of filename)
|
|
207
|
-
.sort((a, b) => {
|
|
208
|
-
const timestampA = parseInt(a.name.split('-')[0] ?? '0', 10);
|
|
209
|
-
const timestampB = parseInt(b.name.split('-')[0] ?? '0', 10);
|
|
210
|
-
return timestampB - timestampA;
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
// Find the most recent cache file for this repo
|
|
214
|
-
for (const file of files) {
|
|
215
|
-
if (file.name.includes(owner) && file.name.includes(repo)) {
|
|
216
|
-
return file.path;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
return null;
|
|
221
|
-
} catch (error) {
|
|
222
|
-
Logger.error(`Error finding cache file for repo:`, error);
|
|
223
|
-
return null;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Get configuration and setup data from specs.json
|
|
229
|
-
* @param {string} projectRoot - Root directory of the project
|
|
230
|
-
* @returns {Object} - Object containing results, specs data, external specs and spec directories
|
|
231
|
-
*/
|
|
232
|
-
async function getProjectConfiguration(projectRoot) {
|
|
233
|
-
const results = [];
|
|
234
|
-
|
|
235
|
-
// Path to the project's specs.json
|
|
236
|
-
const specsPath = path.join(projectRoot, 'specs.json');
|
|
237
|
-
|
|
238
|
-
// Check if specs.json exists
|
|
239
|
-
if (!fs.existsSync(specsPath)) {
|
|
240
|
-
return {
|
|
241
|
-
results: [{
|
|
242
|
-
name: 'Find specs.json file',
|
|
243
|
-
success: false,
|
|
244
|
-
details: 'specs.json file not found in project root'
|
|
245
|
-
}],
|
|
246
|
-
valid: false
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
results.push({
|
|
251
|
-
name: 'Find specs.json file',
|
|
252
|
-
success: true,
|
|
253
|
-
details: 'specs.json file found'
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
// Read specs.json to get the spec directory
|
|
257
|
-
const specsContent = fs.readFileSync(specsPath, 'utf8');
|
|
258
|
-
const specs = JSON.parse(specsContent);
|
|
259
|
-
|
|
260
|
-
// Get the external specs
|
|
261
|
-
if (!specs.specs?.length) {
|
|
262
|
-
results.push({
|
|
263
|
-
name: 'Find specs configuration',
|
|
264
|
-
success: false,
|
|
265
|
-
details: 'specs array not found in specs.json'
|
|
266
|
-
});
|
|
267
|
-
return { results, valid: false };
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// Collect all external specs and spec directories
|
|
271
|
-
const externalSpecs = [];
|
|
272
|
-
const specDirs = [];
|
|
273
|
-
|
|
274
|
-
specs.specs.forEach(spec => {
|
|
275
|
-
if (spec.external_specs?.length) {
|
|
276
|
-
externalSpecs.push(...spec.external_specs);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
if (spec.spec_directory && spec.spec_terms_directory) {
|
|
280
|
-
const termsDir = path.join(
|
|
281
|
-
projectRoot,
|
|
282
|
-
spec.spec_directory,
|
|
283
|
-
spec.spec_terms_directory
|
|
284
|
-
);
|
|
285
|
-
specDirs.push(termsDir);
|
|
286
|
-
}
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
if (externalSpecs.length === 0) {
|
|
290
|
-
results.push({
|
|
291
|
-
name: 'Find external specs',
|
|
292
|
-
success: false,
|
|
293
|
-
details: 'No external specs found in specs.json'
|
|
294
|
-
});
|
|
295
|
-
return { results, valid: false };
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
results.push({
|
|
299
|
-
name: 'Find external specs',
|
|
300
|
-
success: true,
|
|
301
|
-
details: `Found ${externalSpecs.length} external specs`
|
|
302
|
-
});
|
|
303
|
-
|
|
304
|
-
if (specDirs.length === 0) {
|
|
305
|
-
results.push({
|
|
306
|
-
name: 'Find spec terms directories',
|
|
307
|
-
success: false,
|
|
308
|
-
details: 'No spec terms directories found'
|
|
309
|
-
});
|
|
310
|
-
return { results, valid: false };
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
results.push({
|
|
314
|
-
name: 'Find spec terms directories',
|
|
315
|
-
success: true,
|
|
316
|
-
details: `Found ${specDirs.length} spec terms directories`
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
return {
|
|
320
|
-
results,
|
|
321
|
-
specs,
|
|
322
|
-
externalSpecs,
|
|
323
|
-
specDirs,
|
|
324
|
-
valid: true,
|
|
325
|
-
githubCacheDir: path.join(projectRoot, '.cache', 'github-cache')
|
|
326
|
-
};
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* Verify if a term exists in the specified repository
|
|
331
|
-
* @param {Object} options - Options for verification
|
|
332
|
-
* @param {string} options.githubCacheDir - Path to GitHub cache directory
|
|
333
|
-
* @param {string} options.repo - Repository to check
|
|
334
|
-
* @param {string} options.term - Term to find
|
|
335
|
-
* @param {string} options.file - File name for reporting
|
|
336
|
-
* @param {Array} options.externalSpecs - List of external specs
|
|
337
|
-
* @returns {Object} - Object containing results and status
|
|
338
|
-
*/
|
|
339
|
-
function verifyTermInRepo(options) {
|
|
340
|
-
const { githubCacheDir, repo, term, file, externalSpecs } = options;
|
|
341
|
-
const results = [];
|
|
342
|
-
|
|
343
|
-
// Check if the referenced repo exists in external_specs
|
|
344
|
-
const specConfig = externalSpecs.find(spec => spec.external_spec === repo);
|
|
345
|
-
if (!specConfig) {
|
|
346
|
-
results.push({
|
|
347
|
-
name: `Check repo reference in ${file}`,
|
|
348
|
-
success: false,
|
|
349
|
-
details: `Referenced repo "${repo}" is not defined in external_specs`
|
|
350
|
-
});
|
|
351
|
-
return { results, status: 'invalid_repo' };
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// Find the cache file for this repo
|
|
355
|
-
const cacheFile = findCacheFileForRepo(githubCacheDir, specConfig);
|
|
356
|
-
|
|
357
|
-
if (!cacheFile) {
|
|
358
|
-
results.push({
|
|
359
|
-
name: `Find cache for repo "${repo}" referenced in ${file}`,
|
|
360
|
-
success: false,
|
|
361
|
-
details: `No cache file found for repo "${repo}". Unable to verify if term "${term}" exists.`
|
|
362
|
-
});
|
|
363
|
-
return { results, status: 'no_cache' };
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
// Check if the term exists in the repo
|
|
367
|
-
const termExists = termExistsInRepo(cacheFile, term);
|
|
368
|
-
|
|
369
|
-
if (termExists) {
|
|
370
|
-
results.push({
|
|
371
|
-
name: `Term "${term}" in repo "${repo}" (${file})`,
|
|
372
|
-
success: true,
|
|
373
|
-
details: `Term "${term}" found in repo "${repo}"`
|
|
374
|
-
});
|
|
375
|
-
return { results, status: 'found' };
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
// Check if the term exists in other repos
|
|
379
|
-
const otherRepos = findTermInOtherRepos(githubCacheDir, externalSpecs, repo, term);
|
|
380
|
-
|
|
381
|
-
if (otherRepos.length > 0) {
|
|
382
|
-
// Show as warning (partial success) instead of failure
|
|
383
|
-
results.push({
|
|
384
|
-
name: `Term "${term}" in repo "${repo}" (${file})`,
|
|
385
|
-
success: 'partial', // Use 'partial' to indicate a warning
|
|
386
|
-
details: `Warning: Term <code>${term}</code> NOT found in repo ${repo} but found in these repos: <code>${otherRepos.join(', ')}</code>. Consider updating the reference.`
|
|
387
|
-
});
|
|
388
|
-
return { results, status: 'found_elsewhere' };
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
results.push({
|
|
392
|
-
name: `Term "${term}" in repo "${repo}" (${file})`,
|
|
393
|
-
success: false,
|
|
394
|
-
details: `Term <code>${term}</code> NOT found in repo <code>${repo}</code> and not found in any other external repos`
|
|
395
|
-
});
|
|
396
|
-
return { results, status: 'not_found' };
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
/**
|
|
400
|
-
* Process a single markdown file to check for tref tags
|
|
401
|
-
* @param {Object} options - Processing options
|
|
402
|
-
* @param {string} options.filePath - Path to markdown file
|
|
403
|
-
* @param {string} options.githubCacheDir - Path to GitHub cache directory
|
|
404
|
-
* @param {Array} options.externalSpecs - List of external specs
|
|
405
|
-
* @returns {Object} - Object containing results and counts
|
|
406
|
-
*/
|
|
407
|
-
function processMarkdownFile(options) {
|
|
408
|
-
const { filePath, githubCacheDir, externalSpecs } = options;
|
|
409
|
-
const file = path.basename(filePath);
|
|
410
|
-
const results = [];
|
|
411
|
-
const counts = {
|
|
412
|
-
filesWithTref: 0,
|
|
413
|
-
validTerms: 0,
|
|
414
|
-
invalidTerms: 0,
|
|
415
|
-
termsFoundInOtherRepos: 0
|
|
416
|
-
};
|
|
417
|
-
|
|
418
|
-
try {
|
|
419
|
-
const content = fs.readFileSync(filePath, 'utf8');
|
|
420
|
-
const lines = content.split('\n');
|
|
421
|
-
const firstLine = lines[0];
|
|
422
|
-
|
|
423
|
-
if (!firstLine.includes('[[tref:')) {
|
|
424
|
-
return { results, counts };
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
counts.filesWithTref = 1;
|
|
428
|
-
|
|
429
|
-
// Extract repo and term information
|
|
430
|
-
const trefInfo = extractTrefInfo(firstLine);
|
|
431
|
-
if (!trefInfo) {
|
|
432
|
-
results.push({
|
|
433
|
-
name: `Parse tref in ${file}`,
|
|
434
|
-
success: false,
|
|
435
|
-
details: `Could not parse tref information from first line: "${firstLine}"`
|
|
436
|
-
});
|
|
437
|
-
return { results, counts };
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
const { repo, term } = trefInfo;
|
|
441
|
-
|
|
442
|
-
// Verify the term
|
|
443
|
-
const verification = verifyTermInRepo({
|
|
444
|
-
githubCacheDir,
|
|
445
|
-
repo,
|
|
446
|
-
term,
|
|
447
|
-
file,
|
|
448
|
-
externalSpecs
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
results.push(...verification.results);
|
|
452
|
-
|
|
453
|
-
// Update counts based on verification status
|
|
454
|
-
if (verification.status === 'found') {
|
|
455
|
-
counts.validTerms = 1;
|
|
456
|
-
} else if (verification.status === 'found_elsewhere') {
|
|
457
|
-
counts.termsFoundInOtherRepos = 1;
|
|
458
|
-
} else if (verification.status === 'not_found') {
|
|
459
|
-
counts.invalidTerms = 1;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
} catch (error) {
|
|
463
|
-
results.push({
|
|
464
|
-
name: `Process file ${file}`,
|
|
465
|
-
success: false,
|
|
466
|
-
details: `Error processing file: ${error.message}`
|
|
467
|
-
});
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
return { results, counts };
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
/**
|
|
474
|
-
* Check if terms referenced via tref tags exist in the corresponding external repos
|
|
475
|
-
* @param {string} projectRoot - Root directory of the project
|
|
476
|
-
* @returns {Promise<Array>} - Array of check results
|
|
477
|
-
*/
|
|
478
|
-
async function checkTrefTerms(projectRoot) {
|
|
479
|
-
try {
|
|
480
|
-
// Get project configuration
|
|
481
|
-
const config = await getProjectConfiguration(projectRoot);
|
|
482
|
-
|
|
483
|
-
// If configuration is invalid, return early with errors
|
|
484
|
-
if (!config.valid) {
|
|
485
|
-
return config.results;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
const { results, specDirs, externalSpecs, githubCacheDir } = config;
|
|
489
|
-
|
|
490
|
-
// Initialize counters
|
|
491
|
-
let totalFiles = 0;
|
|
492
|
-
let filesWithTref = 0;
|
|
493
|
-
let validTerms = 0;
|
|
494
|
-
let invalidTerms = 0;
|
|
495
|
-
let termsFoundInOtherRepos = 0;
|
|
496
|
-
|
|
497
|
-
// Process each spec directory
|
|
498
|
-
for (const specDir of specDirs) {
|
|
499
|
-
if (!fs.existsSync(specDir)) {
|
|
500
|
-
continue;
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
// Get all markdown files
|
|
504
|
-
const allFiles = fs.readdirSync(specDir);
|
|
505
|
-
const markdownFiles = allFiles.filter(file => shouldProcessFile(file));
|
|
506
|
-
|
|
507
|
-
totalFiles += markdownFiles.length;
|
|
508
|
-
|
|
509
|
-
// Process each markdown file
|
|
510
|
-
for (const file of markdownFiles) {
|
|
511
|
-
const filePath = path.join(specDir, file);
|
|
512
|
-
const fileResult = processMarkdownFile({
|
|
513
|
-
filePath,
|
|
514
|
-
githubCacheDir,
|
|
515
|
-
externalSpecs
|
|
516
|
-
});
|
|
517
|
-
|
|
518
|
-
// Add results
|
|
519
|
-
results.push(...fileResult.results);
|
|
520
|
-
|
|
521
|
-
// Update counters
|
|
522
|
-
filesWithTref += fileResult.counts.filesWithTref;
|
|
523
|
-
validTerms += fileResult.counts.validTerms;
|
|
524
|
-
invalidTerms += fileResult.counts.invalidTerms;
|
|
525
|
-
termsFoundInOtherRepos += fileResult.counts.termsFoundInOtherRepos;
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// Add summary results
|
|
530
|
-
results.push({
|
|
531
|
-
name: 'Term reference validation summary',
|
|
532
|
-
success: invalidTerms === 0,
|
|
533
|
-
details: `Processed ${totalFiles} files, found ${filesWithTref} with tref tags. ${validTerms} terms found correctly, ${termsFoundInOtherRepos} terms found in alternative repos (warnings), ${invalidTerms} terms missing.`
|
|
534
|
-
});
|
|
535
|
-
|
|
536
|
-
return results;
|
|
537
|
-
} catch (error) {
|
|
538
|
-
Logger.error('Error checking tref terms:', error);
|
|
539
|
-
return [{
|
|
540
|
-
name: 'Term reference validation check',
|
|
541
|
-
success: false,
|
|
542
|
-
details: `Error: ${error.message}`
|
|
543
|
-
}];
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
module.exports = {
|
|
548
|
-
checkTrefTerms
|
|
549
|
-
};
|