spec-up-t 1.2.6 → 1.2.7

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.
@@ -57,7 +57,8 @@ function collapseDefinitions() {
57
57
  "See more about",
58
58
  "See more on",
59
59
  "See more at",
60
- "More:"
60
+ "More:",
61
+ "Supporting definitions:"
61
62
  ];
62
63
  return definitionHidePrefixes.some(prefix => content.startsWith(prefix));
63
64
  }
package/jest.config.js ADDED
@@ -0,0 +1,20 @@
1
+ module.exports = {
2
+ collectCoverageFrom: [
3
+ 'src/**/*.{js,jsx}',
4
+ '!src/**/*.test.{js,jsx}',
5
+ '!src/**/__tests__/**',
6
+ '!src/**/__mocks__/**',
7
+ ],
8
+ coverageDirectory: 'coverage',
9
+ coverageReporters: ['text', 'lcov', 'html'],
10
+ coverageThreshold: {
11
+ global: {
12
+ branches: 80,
13
+ functions: 80,
14
+ lines: 80,
15
+ statements: 80,
16
+ },
17
+ },
18
+ testEnvironment: 'node',
19
+ verbose: true,
20
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-up-t",
3
- "version": "1.2.6",
3
+ "version": "1.2.7",
4
4
  "description": "Technical specification drafting tool that generates rich specification documents from markdown. Forked from https://github.com/decentralized-identity/spec-up by Daniel Buchner (https://github.com/csuwildcat)",
5
5
  "main": "./index",
6
6
  "repository": {
@@ -70,6 +70,7 @@
70
70
  "jest": "^29.7.0"
71
71
  },
72
72
  "scripts": {
73
- "test": "NODE_OPTIONS=--experimental-vm-modules jest"
73
+ "test": "jest",
74
+ "test:coverage": "jest --coverage"
74
75
  }
75
76
  }
@@ -1,6 +1,17 @@
1
+ /**
2
+ * @file destination-gitignore-checker.js
3
+ * @description Checks if the final destination directory (from output_path in specs.json)
4
+ * is being ignored by Git. This is the directory where index.html is generated,
5
+ * NOT the temporary .cache directory (formerly called "output").
6
+ *
7
+ * Important: This file deals with concept #1 (output_path from specs.json),
8
+ * not concept #2 (the temporary .cache directory for build artifacts).
9
+ */
10
+
1
11
  const fs = require('fs');
2
12
  const path = require('path');
3
- const { execSync } = require('child_process');
13
+ const { spawnSync } = require('child_process');
14
+ const fileOpener = require('../utils/file-opener');
4
15
 
5
16
  /**
6
17
  * Checks if a path is gitignored
@@ -13,8 +24,11 @@ function isPathGitIgnored(projectRoot, targetPath) {
13
24
  // Use git check-ignore to determine if the path is ignored
14
25
  // If command exits with status 0, path is ignored
15
26
  // If command exits with status 1, path is not ignored
16
- execSync(`git -C "${projectRoot}" check-ignore -q "${targetPath}"`, { stdio: 'ignore' });
17
- return true; // Path is ignored (command exited with status 0)
27
+ const gitPath = fileOpener.getCommandPath('git');
28
+ const result = spawnSync(gitPath, ['-C', projectRoot, 'check-ignore', '-q', targetPath], {
29
+ stdio: 'ignore'
30
+ });
31
+ return result.status === 0; // Path is ignored (command exited with status 0)
18
32
  } catch (error) {
19
33
  console.log(`Error checking if path is gitignored: ${error.message}`);
20
34
  return false; // Path is not ignored (command exited with non-zero status)
@@ -87,11 +101,11 @@ function extractOutputPath(specsPath) {
87
101
  }
88
102
 
89
103
  /**
90
- * Check if the output directory exists
104
+ * Check if the final destination directory (from output_path) exists
91
105
  * @param {string} projectRoot - Root directory of the project
92
106
  * @param {string} outputPath - Output path from specs.json
93
107
  * @param {string} normalizedPath - Normalized output path
94
- * @returns {Object} - Result with output directory check
108
+ * @returns {Object} - Result with final destination directory check
95
109
  */
96
110
  function checkOutputDirExists(projectRoot, outputPath, normalizedPath) {
97
111
  // Check if the path exists
@@ -100,17 +114,17 @@ function checkOutputDirExists(projectRoot, outputPath, normalizedPath) {
100
114
 
101
115
  if (!outputPathExists) {
102
116
  return {
103
- name: 'Output directory existence',
117
+ name: 'Final destination directory existence',
104
118
  status: 'warning',
105
119
  success: true, // Still considered a "success" for backward compatibility
106
- details: `Output directory "${outputPath}" does not exist yet. This is OK if you haven't rendered the specs yet.`
120
+ details: `Final destination directory "${outputPath}" does not exist yet. This is OK if you haven't rendered the specs yet.`
107
121
  };
108
122
  }
109
123
 
110
124
  return {
111
- name: 'Output directory existence',
125
+ name: 'Final destination directory existence',
112
126
  success: true,
113
- details: `Output directory "${outputPath}" exists`
127
+ details: `Final destination directory "${outputPath}" exists`
114
128
  };
115
129
  }
116
130
 
@@ -245,7 +259,7 @@ function findComplexHtmlPatterns(lines) {
245
259
  }
246
260
 
247
261
  /**
248
- * Check if HTML files in the output directory are being ignored by Git
262
+ * Check if HTML files in the final destination directory are being ignored by Git
249
263
  * @param {string} projectRoot - Root directory of the project
250
264
  * @param {string} normalizedPath - Normalized output path
251
265
  * @param {string} outputPath - Original output path
@@ -273,8 +287,8 @@ function checkHtmlFilesGitignore(projectRoot, normalizedPath, outputPath, releva
273
287
  name: 'Check if index.html files are gitignored',
274
288
  success: !isIndexHtmlIgnored,
275
289
  details: isIndexHtmlIgnored
276
- ? `index.html files in the output directory would be ignored by Git. This is problematic as they're crucial output files.`
277
- : `index.html files in the output directory are properly tracked by Git.`
290
+ ? `index.html files in the final destination directory would be ignored by Git. This is problematic as they're crucial output files.`
291
+ : `index.html files in the final destination directory are properly tracked by Git.`
278
292
  });
279
293
 
280
294
  // If index.html is ignored but we couldn't find an explicit pattern, look for more complex patterns
@@ -295,22 +309,22 @@ function checkHtmlFilesGitignore(projectRoot, normalizedPath, outputPath, releva
295
309
  }
296
310
 
297
311
  /**
298
- * Check if output directory is being ignored by Git
312
+ * Check if final destination directory (from output_path) is being ignored by Git
299
313
  * @param {string} projectRoot - Root directory of the project
300
314
  * @param {string} normalizedPath - Normalized output path
301
315
  * @param {string} outputPath - Original output path
302
316
  * @param {string} dirName - Directory name from path
303
317
  * @param {Array} relevantLines - Relevant lines from .gitignore
304
- * @returns {Array} - Results for output directory gitignore check
318
+ * @returns {Array} - Results for final destination directory gitignore check
305
319
  */
306
320
  function checkOutputDirIgnorePatterns(projectRoot, normalizedPath, outputPath, dirName, relevantLines) {
307
321
  const dirIgnorePatterns = findOutputDirIgnorePatterns(relevantLines, normalizedPath, dirName);
308
322
 
309
323
  if (dirIgnorePatterns.length > 0) {
310
324
  return [{
311
- name: 'Check if output directory is gitignored',
325
+ name: 'Check if final destination directory is gitignored',
312
326
  success: false,
313
- details: `Found patterns in .gitignore that would ignore the output directory: ${dirIgnorePatterns.join(', ')}. Remove these entries to ensure generated content is tracked.`
327
+ details: `Found patterns in .gitignore that would ignore the final destination directory: ${dirIgnorePatterns.join(', ')}. Remove these entries to ensure generated content is tracked.`
314
328
  }];
315
329
  }
316
330
 
@@ -318,20 +332,21 @@ function checkOutputDirIgnorePatterns(projectRoot, normalizedPath, outputPath, d
318
332
  const isIgnored = isPathGitIgnored(projectRoot, normalizedPath);
319
333
 
320
334
  return [{
321
- name: 'Check if output directory is gitignored',
335
+ name: 'Check if final destination directory is gitignored',
322
336
  success: !isIgnored,
323
337
  details: isIgnored
324
- ? `Output directory "${outputPath}" is being ignored by Git. This could be due to a complex pattern in .gitignore. Remove any entries that might affect this directory.`
325
- : `Output directory "${outputPath}" is not being ignored by Git, which is good.`
338
+ ? `Final destination directory "${outputPath}" is being ignored by Git. This could be due to a complex pattern in .gitignore. Remove any entries that might affect this directory.`
339
+ : `Final destination directory "${outputPath}" is not being ignored by Git, which is good.`
326
340
  }];
327
341
  }
328
342
 
329
343
  /**
330
- * Check if the output directory is being ignored by Git
344
+ * Check if the final destination directory (from output_path in specs.json) is being ignored by Git
345
+ * This checks the directory where index.html is generated, NOT the temporary .cache directory
331
346
  * @param {string} projectRoot - Root directory of the project
332
347
  * @returns {Promise<Array>} - Array of check results
333
348
  */
334
- async function checkOutputDirGitIgnore(projectRoot) {
349
+ async function checkDestinationGitIgnore(projectRoot) {
335
350
  const results = [];
336
351
 
337
352
  try {
@@ -369,7 +384,7 @@ async function checkOutputDirGitIgnore(projectRoot) {
369
384
  const relevantLines = getRelevantGitignoreLines(gitignoreContent);
370
385
  const dirName = path.basename(normalizedPath);
371
386
 
372
- // Check output directory ignore patterns
387
+ // Check final destination directory ignore patterns
373
388
  const dirResults = checkOutputDirIgnorePatterns(
374
389
  projectRoot, normalizedPath, outputPath, dirName, relevantLines
375
390
  );
@@ -383,9 +398,9 @@ async function checkOutputDirGitIgnore(projectRoot) {
383
398
 
384
399
  return results;
385
400
  } catch (error) {
386
- console.error('Error checking output directory gitignore status:', error);
401
+ console.error('Error checking final destination directory gitignore status:', error);
387
402
  return [{
388
- name: 'Output directory gitignore check',
403
+ name: 'Final destination directory gitignore check',
389
404
  success: false,
390
405
  details: `Error: ${error.message}`
391
406
  }];
@@ -393,5 +408,5 @@ async function checkOutputDirGitIgnore(projectRoot) {
393
408
  }
394
409
 
395
410
  module.exports = {
396
- checkOutputDirGitIgnore
411
+ checkDestinationGitIgnore
397
412
  };
@@ -2,16 +2,15 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const http = require('http');
6
5
  const https = require('https');
7
- const { execSync } = require('child_process');
6
+ const fileOpener = require('./utils/file-opener');
8
7
 
9
8
  // Import modules from the health-check directory
10
9
  const externalSpecsChecker = require('./health-check/external-specs-checker');
11
10
  const termReferencesChecker = require('./health-check/term-references-checker');
12
11
  const specsConfigurationChecker = require('./health-check/specs-configuration-checker');
13
12
  const termsIntroChecker = require('./health-check/terms-intro-checker');
14
- const outputGitignoreChecker = require('./health-check/output-gitignore-checker');
13
+ const destinationGitignoreChecker = require('./health-check/destination-gitignore-checker');
15
14
  const trefTermChecker = require('./health-check/tref-term-checker');
16
15
 
17
16
  // Configuration
@@ -23,7 +22,7 @@ if (!fs.existsSync(OUTPUT_DIR)) {
23
22
  }
24
23
 
25
24
  // Helper function to read specs.json file
26
- function getRepoInfo() {
25
+ async function getRepoInfo() {
27
26
  try {
28
27
  // Path to the default boilerplate specs.json
29
28
  const defaultSpecsPath = path.join(
@@ -90,7 +89,7 @@ function getRepoInfo() {
90
89
  }
91
90
 
92
91
  // If values have changed, verify the repository exists
93
- const repoExists = checkRepositoryExists(
92
+ const repoExists = await checkRepositoryExists(
94
93
  sourceInfo.host,
95
94
  sourceInfo.account,
96
95
  sourceInfo.repo
@@ -135,34 +134,33 @@ function getRepoInfo() {
135
134
 
136
135
  // Helper function to check if a repository exists
137
136
  function checkRepositoryExists(host, account, repo) {
138
- try {
139
- // For synchronous checking, we'll use a simple HTTP HEAD request
137
+ return new Promise((resolve) => {
140
138
  const url = `https://${host}.com/${account}/${repo}`;
141
139
 
142
- // Simple synchronous HTTP request using execSync
143
- const cmd = process.platform === 'win32'
144
- ? `curl -s -o /nul -w "%{http_code}" -I ${url}`
145
- : `curl -s -o /dev/null -w "%{http_code}" -I ${url}`;
140
+ try {
141
+ const request = https.request(url, { method: 'HEAD', timeout: 10000 }, (response) => {
142
+ // 200, 301, 302 status codes indicate the repo exists
143
+ const exists = [200, 301, 302].includes(response.statusCode);
144
+ resolve(exists);
145
+ });
146
146
 
147
- const statusCode = execSync(cmd).toString().trim();
148
-
149
- // 200, 301, 302 status codes indicate the repo exists
150
- return ['200', '301', '302'].includes(statusCode);
151
- } catch (error) {
152
- console.error('Error checking repository existence:', error);
153
- return false;
154
- }
155
- }
156
-
157
- // Helper function to get the appropriate file open command based on platform
158
- function getOpenCommand() {
159
- if (process.platform === 'win32') {
160
- return 'start';
161
- } else if (process.platform === 'darwin') {
162
- return 'open';
163
- } else {
164
- return 'xdg-open';
165
- }
147
+ request.on('error', (error) => {
148
+ console.error('Error checking repository existence:', error.message);
149
+ resolve(false);
150
+ });
151
+
152
+ request.on('timeout', () => {
153
+ console.error('Timeout checking repository existence');
154
+ request.destroy();
155
+ resolve(false);
156
+ });
157
+
158
+ request.end();
159
+ } catch (error) {
160
+ console.error('Error checking repository existence:', error.message);
161
+ resolve(false);
162
+ }
163
+ });
166
164
  }
167
165
 
168
166
  // Helper function to format current time for the filename
@@ -249,17 +247,17 @@ async function runHealthCheck() {
249
247
  results: termsIntroResults
250
248
  });
251
249
 
252
- // Run output directory gitignore check
253
- const outputGitignoreResults = await outputGitignoreChecker.checkOutputDirGitIgnore(process.cwd());
250
+ // Run destination directory gitignore check
251
+ const destinationGitignoreResults = await destinationGitignoreChecker.checkDestinationGitIgnore(process.cwd());
254
252
  results.push({
255
253
  title: 'Check <code>.gitignore</code>',
256
- results: outputGitignoreResults
254
+ results: destinationGitignoreResults
257
255
  });
258
256
 
259
257
  // Add more checks here in the future
260
258
 
261
259
  // Generate and open the report
262
- generateReport(results);
260
+ await generateReport(results);
263
261
  } catch (error) {
264
262
  console.error('Error running health checks:', error);
265
263
  process.exit(1);
@@ -267,10 +265,10 @@ async function runHealthCheck() {
267
265
  }
268
266
 
269
267
  // Generate HTML report
270
- function generateReport(checkResults) {
268
+ async function generateReport(checkResults) {
271
269
  const timestamp = getFormattedTimestamp();
272
270
  // Get repository information from specs.json
273
- const repoInfo = getRepoInfo();
271
+ const repoInfo = await getRepoInfo();
274
272
  const reportFileName = `health-check-${timestamp}-${repoInfo.account}-${repoInfo.repo}.html`;
275
273
  const reportPath = path.join(OUTPUT_DIR, reportFileName);
276
274
 
@@ -282,8 +280,10 @@ function generateReport(checkResults) {
282
280
 
283
281
  // Open the report in the default browser
284
282
  try {
285
- const openCommand = getOpenCommand();
286
- execSync(`${openCommand} "${reportPath}"`);
283
+ const success = fileOpener.openHtmlFile(reportPath);
284
+ if (!success) {
285
+ console.error('Failed to open the report in browser');
286
+ }
287
287
  } catch (error) {
288
288
  console.error('Failed to open the report:', error);
289
289
  }
@@ -0,0 +1,35 @@
1
+ # Utils Module
2
+
3
+ This directory contains utility modules that provide cross-platform functionality for the Spec-Up-T health check system.
4
+
5
+ ## file-opener.js
6
+
7
+ Provides secure, cross-platform file opening functionality with proper command path resolution.
8
+
9
+ ### Features:
10
+ - **Cross-platform support**: Handles Windows (`start`), macOS (`open`), and Linux (`xdg-open`)
11
+ - **Secure path resolution**: Uses absolute command paths instead of relying on PATH environment variable
12
+ - **Error handling**: Graceful fallback when commands cannot be located
13
+
14
+ ### Functions:
15
+ - `getCommandPath(command)` - Resolves absolute path for a given command
16
+ - `getOpenCommand()` - Returns the platform-specific file opening command path
17
+ - `openFile(filePath)` - Opens any file in its default application
18
+ - `openHtmlFile(htmlFilePath)` - Specifically opens HTML files in the default browser
19
+
20
+ ### Security:
21
+ This module was created to address SonarQube security issues by:
22
+ 1. Eliminating shell injection vulnerabilities through proper argument separation
23
+ 2. Avoiding PATH hijacking by using absolute command paths
24
+ 3. Providing controlled, sanitized command execution
25
+
26
+ ### Usage:
27
+ ```javascript
28
+ const fileOpener = require('./utils/file-opener');
29
+
30
+ // Open an HTML report
31
+ const success = fileOpener.openHtmlFile('/path/to/report.html');
32
+
33
+ // Get absolute path for a command
34
+ const gitPath = fileOpener.getCommandPath('git');
35
+ ```
@@ -0,0 +1,89 @@
1
+ const fs = require('fs');
2
+ const { spawnSync } = require('child_process');
3
+
4
+ /**
5
+ * Helper function to get the absolute path of a command
6
+ * @param {string} command - The command to find
7
+ * @returns {string} - The absolute path to the command or the command name as fallback
8
+ */
9
+ function getCommandPath(command) {
10
+ // Define common system paths where commands are typically located
11
+ const commonPaths = [
12
+ `/usr/bin/${command}`,
13
+ `/bin/${command}`,
14
+ `/usr/local/bin/${command}`,
15
+ `/opt/homebrew/bin/${command}`, // For Homebrew on Apple Silicon Macs
16
+ `/opt/local/bin/${command}`, // For MacPorts
17
+ ];
18
+
19
+ // For Windows, add common Windows paths
20
+ if (process.platform === 'win32') {
21
+ commonPaths.unshift(
22
+ `C:\\Windows\\System32\\${command}.exe`,
23
+ `C:\\Windows\\${command}.exe`,
24
+ `C:\\Program Files\\Git\\bin\\${command}.exe`, // Git for Windows
25
+ `C:\\Program Files (x86)\\Git\\bin\\${command}.exe`
26
+ );
27
+ }
28
+
29
+ // Check each path to see if the command exists
30
+ for (const cmdPath of commonPaths) {
31
+ if (fs.existsSync(cmdPath)) {
32
+ return cmdPath;
33
+ }
34
+ }
35
+
36
+ // If we can't find the absolute path, return the command name as fallback
37
+ // This maintains functionality while logging the issue
38
+ console.warn(`Warning: Could not find absolute path for command '${command}', using relative path as fallback`);
39
+ return command;
40
+ }
41
+
42
+ /**
43
+ * Get the appropriate file open command based on platform
44
+ * @returns {string} - The absolute path to the platform-specific open command
45
+ */
46
+ function getOpenCommand() {
47
+ let command;
48
+ if (process.platform === 'win32') {
49
+ command = 'start';
50
+ } else if (process.platform === 'darwin') {
51
+ command = 'open';
52
+ } else {
53
+ command = 'xdg-open';
54
+ }
55
+
56
+ return getCommandPath(command);
57
+ }
58
+
59
+ /**
60
+ * Open a file in the default application for the current platform
61
+ * @param {string} filePath - The path to the file to open
62
+ * @returns {boolean} - True if the file was opened successfully, false otherwise
63
+ */
64
+ function openFile(filePath) {
65
+ try {
66
+ const openCommand = getOpenCommand();
67
+ const result = spawnSync(openCommand, [filePath], { stdio: 'ignore' });
68
+ return result.status === 0;
69
+ } catch (error) {
70
+ console.error('Failed to open file:', error);
71
+ return false;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Open an HTML file in the default web browser
77
+ * @param {string} htmlFilePath - The path to the HTML file to open
78
+ * @returns {boolean} - True if the file was opened successfully, false otherwise
79
+ */
80
+ function openHtmlFile(htmlFilePath) {
81
+ return openFile(htmlFilePath);
82
+ }
83
+
84
+ module.exports = {
85
+ getCommandPath,
86
+ getOpenCommand,
87
+ openFile,
88
+ openHtmlFile
89
+ };
package/branches.md DELETED
@@ -1,17 +0,0 @@
1
- # Beschrijving van de branches
2
-
3
- ## improve/compact-terms
4
-
5
- Maak de termen weergave meer compact
6
- Filters
7
-
8
-
9
- ## various
10
-
11
-
12
- ## test/xtrefnew
13
-
14
- Lokaal Bewaren
15
- Lijkt goed te werken.
16
- Met AI gebouwde oplossing waarbij ik probeer iets aan de API limieten te doen. Ik heb twee belangrijke bestanden weggedaan en AI ze opnieuw laten bouwen op basis van een prompt en de bestanden die ik had. Het lijkt te werken, maar ik heb geen idee of het goed is. Het is een beetje een experiment.
17
-
package/src/README.md DELETED
@@ -1,98 +0,0 @@
1
- <h1>Spec-Up-T External References Collection Workflow</h1>
2
- <p>This codebase implements a system for collecting and processing cross-specification references from markdown files. Here's a workflow diagram of what happens when <a class="chat-inline-anchor-widget show-file-icons" title="" draggable="true" href="vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html" data-href="file:///Users/kor/webdev/Blockchain-Bird/KERI/Spec-Up/active-bcb/spec-up-t/spec-up-t/src/collect-external-references.js#37%2C10" data-keybinding-context="1187"><span class="icon-label">collectExternalReferences()</span></a> is called:</p>
3
- <h2>Workflow Overview</h2>
4
- <ol>
5
- <li>
6
- <p><strong>Initialization &amp; Configuration</strong></p>
7
- <ul>
8
- <li>Loads environment variables using dotenv</li>
9
- <li>Reads <a class="chat-inline-anchor-widget show-file-icons" title="" draggable="true" href="vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html" data-href="file:///Users/kor/webdev/Blockchain-Bird/KERI/Spec-Up/active-bcb/spec-up-t/spec-up-t/src/collect-external-references.js#42%2C39" data-keybinding-context="1188"><span class="icon-label">specs.json</span></a> configuration file</li>
10
- <li>Obtains GitHub Personal Access Token (PAT) from options or environment variables</li>
11
- </ul>
12
- </li>
13
- <li>
14
- <p><strong>Validation Checks</strong></p>
15
- <ul>
16
- <li>Verifies GitHub PAT is available, stops with instructions if missing</li>
17
- <li>Confirms external repositories are configured in specs.json</li>
18
- <li>Validates repository URLs using <a class="chat-inline-anchor-widget show-file-icons" title="" draggable="true" href="vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html" data-href="file:///Users/kor/webdev/Blockchain-Bird/KERI/Spec-Up/active-bcb/spec-up-t/spec-up-t/src/utils/doesUrlExist.js#8%2C16" data-keybinding-context="1189"><span class="icon-label">doesUrlExist.js</span></a></li>
19
- </ul>
20
- </li>
21
- <li>
22
- <p><strong>Content Collection</strong></p>
23
- <ul>
24
- <li>Creates necessary output directories</li>
25
- <li>Reads all markdown files from specified term directories</li>
26
- <li>Concatenates content into a single string for processing</li>
27
- </ul>
28
- </li>
29
- <li>
30
- <p><strong>Cross-Reference Extraction</strong></p>
31
- <ul>
32
- <li>Uses regex to find <code>[[xref:...]]</code> and <code>[[tref:...]]</code> patterns in markdown</li>
33
- <li>Processes these patterns into structured objects with <a class="chat-inline-anchor-widget show-file-icons" title="" draggable="true" href="vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html" data-href="file:///Users/kor/webdev/Blockchain-Bird/KERI/Spec-Up/active-bcb/spec-up-t/spec-up-t/src/collect-external-references.js#158%2C58" data-keybinding-context="1190"><span class="icon-label">externalSpec</span></a> and <a class="chat-inline-anchor-widget show-file-icons" title="" draggable="true" href="vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html" data-href="file:///Users/kor/webdev/Blockchain-Bird/KERI/Spec-Up/active-bcb/spec-up-t/spec-up-t/src/collect-external-references.js#186%2C64" data-keybinding-context="1191"><span class="icon-label">term</span></a> properties</li>
34
- <li>Filters out duplicates and keeps only references found in current markdown content</li>
35
- </ul>
36
- </li>
37
- <li>
38
- <p><strong>Metadata Enhancement</strong></p>
39
- <ul>
40
- <li>Extends each reference with additional repository information:
41
- <ul>
42
- <li>Repository URL</li>
43
- <li>Owner/repo names</li>
44
- <li>Terms directory path</li>
45
- <li>Avatar URL</li>
46
- </ul>
47
- </li>
48
- </ul>
49
- </li>
50
- <li>
51
- <p><strong>GitHub API Interaction</strong></p>
52
- <ul>
53
- <li>For each reference, calls <a class="chat-inline-anchor-widget show-file-icons" title="" draggable="true" href="vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html" data-href="file:///Users/kor/webdev/Blockchain-Bird/KERI/Spec-Up/active-bcb/spec-up-t/spec-up-t/src/collectExternalReferences/fetchTermsFromGitHubRepository.js#16%2C16" data-keybinding-context="1192"><span class="icon-label">fetchTermsFromGitHubRepository</span></a> which:
54
- <ul>
55
- <li>Uses Octokit to interface with GitHub API</li>
56
- <li>Implements caching to minimize API requests</li>
57
- <li>Handles rate limiting with throttling and retries</li>
58
- <li>Searches for terms within specified repositories/directories</li>
59
- </ul>
60
- </li>
61
- </ul>
62
- </li>
63
- <li>
64
- <p><strong>Term Content Processing</strong></p>
65
- <ul>
66
- <li>When terms are found, retrieves:
67
- <ul>
68
- <li>File content</li>
69
- <li>Latest commit hash</li>
70
- <li>Repository metadata</li>
71
- </ul>
72
- </li>
73
- <li>Uses <a class="chat-inline-anchor-widget show-file-icons" title="" draggable="true" href="vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html" data-href="file:///Users/kor/webdev/Blockchain-Bird/KERI/Spec-Up/active-bcb/spec-up-t/spec-up-t/src/collectExternalReferences/matchTerm.js#3%2C10" data-keybinding-context="1193"><span class="icon-label">matchTerm.js</span></a> to validate the term within content</li>
74
- </ul>
75
- </li>
76
- <li>
77
- <p><strong>Output Generation</strong></p>
78
- <ul>
79
- <li>Creates three output files:
80
- <ul>
81
- <li><code>.cache/xtrefs-data.json</code> - JSON data file</li>
82
- <li><code>.cache/xtrefs-data.js</code> - JavaScript module file</li>
83
- <li><code>.cache/xtrefs-history/xtrefs-data-[timestamp].js</code> - Historical record</li>
84
- </ul>
85
- </li>
86
- </ul>
87
- </li>
88
- </ol>
89
- <h2>Key Functions</h2>
90
- <ul>
91
- <li><a class="chat-inline-anchor-widget show-file-icons" title="" draggable="true" href="vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html" data-href="file:///Users/kor/webdev/Blockchain-Bird/KERI/Spec-Up/active-bcb/spec-up-t/spec-up-t/src/collect-external-references.js#37%2C10" data-keybinding-context="1194"><span class="icon-label">collectExternalReferences()</span></a>: Main orchestration function</li>
92
- <li><a class="chat-inline-anchor-widget show-file-icons" title="" draggable="true" href="vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html" data-href="file:///Users/kor/webdev/Blockchain-Bird/KERI/Spec-Up/active-bcb/spec-up-t/spec-up-t/src/collect-external-references.js#143%2C18" data-keybinding-context="1195"><span class="icon-label">extendXTrefs()</span></a>: Adds repository metadata to references</li>
93
- <li><a class="chat-inline-anchor-widget show-file-icons" title="" draggable="true" href="vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html" data-href="file:///Users/kor/webdev/Blockchain-Bird/KERI/Spec-Up/active-bcb/spec-up-t/spec-up-t/src/collect-external-references.js#192%2C18" data-keybinding-context="1196"><span class="icon-label">processXTref()</span></a>: Parses reference syntax into structured objects</li>
94
- <li><a class="chat-inline-anchor-widget show-file-icons" title="" draggable="true" href="vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html" data-href="file:///Users/kor/webdev/Blockchain-Bird/KERI/Spec-Up/active-bcb/spec-up-t/spec-up-t/src/collect-external-references.js#184%2C18" data-keybinding-context="1197"><span class="icon-label">isXTrefInMarkdown()</span></a>: Validates references against current content</li>
95
- <li><a class="chat-inline-anchor-widget show-file-icons" title="" draggable="true" href="vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html" data-href="file:///Users/kor/webdev/Blockchain-Bird/KERI/Spec-Up/active-bcb/spec-up-t/spec-up-t/src/collectExternalReferences/fetchTermsFromGitHubRepository.js#16%2C16" data-keybinding-context="1198"><span class="icon-label">fetchTermsFromGitHubRepository()</span></a>: Interacts with GitHub API to find terms</li>
96
- <li><a class="chat-inline-anchor-widget show-file-icons" title="" draggable="true" href="vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench/workbench.html" data-href="file:///Users/kor/webdev/Blockchain-Bird/KERI/Spec-Up/active-bcb/spec-up-t/spec-up-t/src/collectExternalReferences/processXTrefsData.js#9%2C16" data-keybinding-context="1199"><span class="icon-label">processXTrefsData()</span></a>: Processes the data and generates output files</li>
97
- </ul>
98
- <p>This system enables cross-specification linking by fetching and maintaining references to terms defined in external GitHub repositories, ensuring that documentation can link to canonical definitions maintained elsewhere.</p>