spec-up-t 1.0.89 → 1.0.91

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.
@@ -83,9 +83,9 @@ function fetchCommitHashes() {
83
83
  };
84
84
  }
85
85
 
86
- // B: Debounced “GitHub rate limit exceeded” error message
86
+ // B: Debounced “GitHub API rate limit exceeded” error message
87
87
  const debouncedError = debounce(() => {
88
- notyf.error('GitHub rate limit exceeded. See <a target="_blank" rel="noopener" href="https://trustoverip.github.io/spec-up-t-website/docs/github-token/">documentation</a> for more info.');
88
+ notyf.error('GitHub API rate limit exceeded. See <a target="_blank" rel="noopener" href="https://trustoverip.github.io/spec-up-t-website/docs/github-token/">documentation</a> for more info.');
89
89
  }, 3000); // Delay in milliseconds
90
90
 
91
91
  // Fetch the content of a term-file from GitHub
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-up-t",
3
- "version": "1.0.89",
3
+ "version": "1.0.91",
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": {
@@ -0,0 +1,101 @@
1
+ async function searchGitHubCode(GITHUB_API_TOKEN, searchString, owner, repo, subdirectory) {
2
+ const { Octokit } = await import("octokit");
3
+ const { throttling } = await import("@octokit/plugin-throttling");
4
+
5
+ // Create a throttled Octokit instance
6
+ const ThrottledOctokit = Octokit.plugin(throttling);
7
+ const octokit = new ThrottledOctokit({
8
+ auth: GITHUB_API_TOKEN,
9
+ throttle: {
10
+ onRateLimit: (retryAfter, options) => {
11
+ console.warn(`Request quota exhausted for request ${options.method} ${options.url}`);
12
+ if (!process.env.GITHUB_API_TOKEN) {
13
+ console.warn('GitHub API rate limit exceeded. See <a target="_blank" rel="noopener" href="https://trustoverip.github.io/spec-up-t-website/docs/github-token/">documentation</a> for more info.');
14
+ process.exit(1);
15
+ }
16
+ if (options.request.retryCount <= 1) {
17
+ console.log(`Retrying after ${retryAfter} seconds...`);
18
+ return true;
19
+ }
20
+ },
21
+ onAbuseLimit: (retryAfter, options) => {
22
+ console.warn(`Abuse detected for request ${options.method} ${options.url}`);
23
+ },
24
+ onSecondaryRateLimit: (retryAfter, options) => {
25
+ console.warn(`Secondary rate limit hit for request ${options.method} ${options.url}`);
26
+ if (options.request.retryCount <= 1) {
27
+ console.log(`Retrying after ${retryAfter} seconds...`);
28
+ return true;
29
+ }
30
+ },
31
+ },
32
+ });
33
+
34
+ try {
35
+ // Perform the search using Octokit with exact match
36
+ const searchResponse = await octokit.rest.search.code({
37
+ q: `"${searchString}" repo:${owner}/${repo} path:${subdirectory}`, // Exact match in subdirectory
38
+ headers: {
39
+ Accept: "application/vnd.github.v3.text-match+json", // Include text-match media type
40
+ },
41
+ });
42
+
43
+ // Log the search results
44
+ console.log("Total results:", searchResponse.data.total_count);
45
+
46
+ // Fetch the content of each file
47
+ for (const item of searchResponse.data.items) {
48
+ // Check if text_matches exists and is not empty
49
+ if (!item.text_matches || item.text_matches.length === 0) {
50
+ console.log(`Skipping ${item.path}: No text matches found.`);
51
+ continue;
52
+ }
53
+
54
+ // Check if the match is in the first line using text_matches
55
+ const isFirstLineMatch = item.text_matches.some(match => {
56
+ if (!match.fragment) {
57
+ console.log(`Skipping ${item.path}: No fragment found in text match.`);
58
+ return false;
59
+ }
60
+
61
+ const firstLine = match.fragment.split("\n")[0];
62
+ return firstLine.includes(searchString);
63
+ });
64
+
65
+ if (!isFirstLineMatch) {
66
+ console.log(`Skipping ${item.path}: Match not in the first line.`);
67
+ continue; // Skip this file
68
+ }
69
+
70
+ // Fetch file content
71
+ let content = "";
72
+ try {
73
+ const fileContentResponse = await octokit.rest.repos.getContent({
74
+ owner: item.repository.owner.login, // Repository owner
75
+ repo: item.repository.name, // Repository name
76
+ path: item.path, // File path
77
+ });
78
+
79
+ // Decode the file content (it's base64-encoded)
80
+ if (fileContentResponse.data.content) {
81
+ content = Buffer.from(fileContentResponse.data.content, "base64").toString("utf-8");
82
+ } else {
83
+ // If the file is larger than 1 MB, GitHub's API will return a download URL instead of the content.
84
+ console.log("File is too large. Download URL:", fileContentResponse.data.download_url);
85
+ }
86
+ } catch (error) {
87
+ console.error(`Error fetching content for ${item.path}:`, error);
88
+ content = ""; // Set content to an empty string if there's an error
89
+ }
90
+
91
+ // Attach the content to the item
92
+ item.content = content;
93
+ }
94
+
95
+ return searchResponse;
96
+ } catch (error) {
97
+ console.error("Error searching GitHub or fetching file content:", error);
98
+ }
99
+ }
100
+
101
+ exports.searchGitHubCode = searchGitHubCode;
@@ -10,209 +10,270 @@
10
10
  * @since 2024-06-09
11
11
  */
12
12
 
13
- const fs = require('fs-extra');
14
- const path = require('path');
15
- const readlineSync = require('readline-sync');
16
- const { searchGitHubCode } = require('./get-xtrefs-data/searchGitHubCode.js');
17
- const { matchTerm } = require('./get-xtrefs-data/matchTerm');
18
- const config = fs.readJsonSync('specs.json');
19
- const { doesUrlExist } = require('./utils/doesUrlExist.js');
20
- const { addPath, getPath, getAllPaths } = require('./config/paths');
21
-
22
- const externalSpecsRepos = config.specs[0].external_specs;
23
-
24
- // Check if the URLs for the external specs repositories are valid, and prompt the user to abort if they are not.
25
- externalSpecsRepos.forEach(repo => {
26
- // Construct the URL for the terms directory of the repository
27
- const termsDirUrl = `${repo.url}/blob/main/${repo.terms_dir}`;
28
-
29
- doesUrlExist(termsDirUrl).then(exists => {
30
- if (!exists) {
31
- const userInput = readlineSync.question(`\n SPEC-UP-T: This external reference is not a valid URL:\n ${termsDirUrl}\n Do you want to stop? (yes/no): `);
32
- if (userInput.toLowerCase() === 'yes' || userInput.toLowerCase() === 'y') {
33
- console.log('Stopping...');
34
- process.exit(1);
35
- }
36
- }
37
- }).catch(error => {
38
- console.error('\n SPEC-UP-T:Error checking URL existence:', error);
39
- });
40
- });
41
-
42
- // Collect all directories that contain files with a term and definition
43
- // This maps over the specs in the config file and constructs paths to directories
44
- // where the term definition files are located.
45
- const specTermsDirectories = config.specs.map(spec => spec.spec_directory + '/' + spec.spec_terms_directory);
46
-
47
- // Ensure that the 'output' directory exists, creating it if necessary.
48
- if (!fs.existsSync('output')) {
49
- fs.mkdirSync('output');
50
- }
51
13
 
52
- // Ensure that the 'output/xtrefs-history' directory exists, creating it if necessary.
53
- if (!fs.existsSync('output/xtrefs-history')) {
54
- fs.mkdirSync('output/xtrefs-history');
55
- }
14
+ function updateXTrefs(GITHUB_API_TOKEN, skipExisting) {
15
+ const fs = require('fs-extra');
16
+ const readlineSync = require('readline-sync');
17
+ const config = fs.readJsonSync('specs.json');
18
+ const externalSpecsRepos = config.specs[0].external_specs;
56
19
 
57
- // Define paths for various output files, including JSON and JS files.
58
- const outputPathJSON = 'output/xtrefs-data.json';
59
- const outputPathJS = 'output/xtrefs-data.js';
60
- const outputPathJSTimeStamped = 'output/xtrefs-history/xtrefs-data-' + Date.now() + '.js';
20
+ const explanationPAT =
21
+ `\n SPEC-UP-T: No GitHub Personal Access Token (PAT) was found.
61
22
 
62
- function updateXTrefs(GITHUB_API_TOKEN, skipExisting) {
63
- // Function to extend xtref objects with additional information, such as repository URL and directory information.
64
- function extendXTrefs(config, xtrefs) {
65
- if (config.specs[0].external_specs_repos) {
66
- console.log("\n SPEC-UP-T: PLEASE NOTE: Your specs.json file is outdated (not your fault, we changed something). Use this one: https://github.com/trustoverip/spec-up-t-starter-pack/blob/main/spec-up-t-boilerplate/specs.json or e-mail kor@dwarshuis.com for help. \n");
23
+ GitHub requires you to set up a PAT to retrieve external references.
24
+
25
+ There is no point in continuing without a PAT, so we stop here.
26
+
27
+ Find instructions on how to get a PAT at https://trustoverip.github.io/spec-up-t-website/docs/getting-started/github-token
28
+
29
+ `;
30
+
31
+ const explanationNoExternalReferences =
32
+ `\n SPEC-UP-T: No external references were found in the specs.json file.
33
+
34
+ There is no point in continuing without external references, so we stop here.
35
+
36
+ Please add external references to the specs.json file that you will find at the root of your project.
37
+
38
+ `;
39
+
40
+
41
+ // First do some checks
42
+
43
+ // Do not run the script if the GitHub API token is not set
44
+ if (!GITHUB_API_TOKEN) {
45
+ console.log(explanationPAT);
46
+ const userInput = readlineSync.question('Press any key');
47
+
48
+ // React to user pressing any key
49
+ if (userInput.trim() !== '') {
50
+ console.log('Stopping...');
67
51
  return;
68
52
  }
53
+ }
69
54
 
70
- xtrefs.forEach(xtref => {
71
- config.specs.forEach(spec => {
72
- // Loop through "external_specs" to find the repository URL for each xtref
73
- xtref.repoUrl = null;
74
- xtref.terms_dir = null;
75
- xtref.owner = null;
76
- xtref.repo = null;
77
-
78
- spec.external_specs.forEach(repo => {
79
- if (repo.external_spec === xtref.externalSpec) {
80
- xtref.repoUrl = repo.url;
81
- xtref.terms_dir = repo.terms_dir;
82
- const urlParts = new URL(xtref.repoUrl).pathname.split('/');
83
- xtref.owner = urlParts[1];
84
- xtref.repo = urlParts[2];
55
+ else if (externalSpecsRepos.length === 0) {
56
+ // Check if the URLs for the external specs repositories are valid, and prompt the user to abort if they are not.
57
+ console.log(explanationNoExternalReferences);
58
+ const userInput = readlineSync.question('Press any key');
59
+
60
+ // React to user pressing any key
61
+ if (userInput.trim() !== '') {
62
+ console.log('Stopping...');
63
+ return;
64
+ }
65
+ } else {
66
+ main();
67
+ }
68
+
69
+ function main() {
70
+ const path = require('path');
71
+ const { searchGitHubCode } = require('./get-xtrefs-data/searchGitHubCode.js');
72
+ const { matchTerm } = require('./get-xtrefs-data/matchTerm');
73
+ const { doesUrlExist } = require('./utils/doesUrlExist.js');
74
+ const { addPath, getPath, getAllPaths } = require('./config/paths');
75
+
76
+ // Check if the URLs for the external specs repositories are valid, and prompt the user to abort if they are not.
77
+ externalSpecsRepos.forEach(repo => {
78
+ doesUrlExist(repo.url, repo.terms_dir).then(exists => {
79
+ if (!exists) {
80
+ const userInput = readlineSync.question(
81
+ ` SPEC-UP-T: This external reference is not a valid URL:
82
+ Repository: ${repo.url},
83
+
84
+ Terms directory: ${repo.terms_dir}
85
+
86
+ Please fix the external references to the specs.json file that you will find at the root of your project.
87
+
88
+ Do you want to stop? (yes/no): `);
89
+ if (userInput.toLowerCase() === 'yes' || userInput.toLowerCase() === 'y') {
90
+ console.log('Stopping...');
91
+ process.exit(1);
85
92
  }
86
- });
93
+ }
94
+ }).catch(error => {
95
+ console.error('\n SPEC-UP-T:Error checking URL existence:', error);
96
+ });
97
+ });
98
+
99
+ // Collect all directories that contain files with a term and definition
100
+ // This maps over the specs in the config file and constructs paths to directories
101
+ // where the term definition files are located.
102
+ const specTermsDirectories = config.specs.map(spec => spec.spec_directory + '/' + spec.spec_terms_directory);
103
+
104
+ // Ensure that the 'output' directory exists, creating it if necessary.
105
+ if (!fs.existsSync('output')) {
106
+ fs.mkdirSync('output');
107
+ }
108
+
109
+ // Ensure that the 'output/xtrefs-history' directory exists, creating it if necessary.
110
+ if (!fs.existsSync('output/xtrefs-history')) {
111
+ fs.mkdirSync('output/xtrefs-history');
112
+ }
113
+
114
+ // Define paths for various output files, including JSON and JS files.
115
+ const outputPathJSON = 'output/xtrefs-data.json';
116
+ const outputPathJS = 'output/xtrefs-data.js';
117
+ const outputPathJSTimeStamped = 'output/xtrefs-history/xtrefs-data-' + Date.now() + '.js';
118
+ // Function to extend xtref objects with additional information, such as repository URL and directory information.
119
+ function extendXTrefs(config, xtrefs) {
120
+ if (config.specs[0].external_specs_repos) {
121
+ console.log("\n SPEC-UP-T: PLEASE NOTE: Your specs.json file is outdated (not your fault, we changed something). Use this one: https://github.com/trustoverip/spec-up-t-starter-pack/blob/main/spec-up-t-boilerplate/specs.json or e-mail kor@dwarshuis.com for help. \n");
122
+ return;
123
+ }
87
124
 
88
- // Loop through "external_specs" to find the site URL for each xtref
125
+ xtrefs.forEach(xtref => {
126
+ config.specs.forEach(spec => {
127
+ // Loop through "external_specs" to find the repository URL for each xtref
128
+ xtref.repoUrl = null;
129
+ xtref.terms_dir = null;
130
+ xtref.owner = null;
131
+ xtref.repo = null;
89
132
 
90
- xtref.site = null;
91
- if (spec.external_specs) {
92
- spec.external_specs.forEach(externalSpec => {
93
- const key = Object.keys(externalSpec)[0];
94
- if (key === xtref.externalSpec) {
95
- xtref.site = externalSpec[key];
133
+ spec.external_specs.forEach(repo => {
134
+ if (repo.external_spec === xtref.externalSpec) {
135
+ xtref.repoUrl = repo.url;
136
+ xtref.terms_dir = repo.terms_dir;
137
+ const urlParts = new URL(xtref.repoUrl).pathname.split('/');
138
+ xtref.owner = urlParts[1];
139
+ xtref.repo = urlParts[2];
96
140
  }
97
141
  });
142
+
143
+ // Loop through "external_specs" to find the site URL for each xtref
144
+
145
+ xtref.site = null;
146
+ if (spec.external_specs) {
147
+ spec.external_specs.forEach(externalSpec => {
148
+ const key = Object.keys(externalSpec)[0];
149
+ if (key === xtref.externalSpec) {
150
+ xtref.site = externalSpec[key];
151
+ }
152
+ });
153
+ }
154
+ });
155
+ });
156
+ }
157
+
158
+ // Function to check if an xtref is in the markdown content
159
+ function isXTrefInMarkdown(xtref, markdownContent) {
160
+ // const regex = new RegExp(`\\[\\[xref:${xref.term}\\]\\]`, 'g');
161
+ const regex = new RegExp(`\\[\\[(?:x|t)ref:${xtref.term}\\]\\]`, 'g');
162
+ const result = regex.test(markdownContent);
163
+ return result;
164
+ }
165
+
166
+ // Function to process and clean up xref / tref strings found in the markdown file, returning an object with `externalSpec` and `term` properties.
167
+ function processXTref(xtref) {
168
+ let [externalSpec, term] = xtref.replace(/\[\[(?:xref|tref):/, '').replace(/\]\]/, '').trim().split(/,/, 2);
169
+ return {
170
+ externalSpec: externalSpec.trim(),
171
+ term: term.trim()
172
+ };
173
+ }
174
+
175
+ // Initialize an object to store all xtrefs.
176
+ let allXTrefs = { xtrefs: [] };
177
+
178
+ // If the output JSON file exists, load its data.
179
+ if (fs.existsSync(outputPathJSON)) {
180
+ const existingXTrefs = fs.readJsonSync(outputPathJSON);
181
+ allXTrefs = existingXTrefs && existingXTrefs.xtrefs ? existingXTrefs : { xtrefs: [] };
182
+ }
183
+
184
+ // Collect all markdown content
185
+ let allMarkdownContent = '';
186
+
187
+ // Read all main repo Markdown files from a list of directories and concatenate their content into a single string.
188
+ specTermsDirectories.forEach(specDirectory => {
189
+ fs.readdirSync(specDirectory).forEach(file => {
190
+ if (file.endsWith('.md')) {
191
+ const markdown = fs.readFileSync(`${specDirectory}/${file}`, 'utf8');
192
+ allMarkdownContent += markdown;
98
193
  }
99
194
  });
100
195
  });
101
- }
102
196
 
103
- // Function to check if an xtref is in the markdown content
104
- function isXTrefInMarkdown(xtref, markdownContent) {
105
- // const regex = new RegExp(`\\[\\[xref:${xref.term}\\]\\]`, 'g');
106
- const regex = new RegExp(`\\[\\[(?:x|t)ref:${xtref.term}\\]\\]`, 'g');
107
- const result = regex.test(markdownContent);
108
- return result;
109
- }
197
+ // Remove existing entries if not in the combined markdown content
198
+ allXTrefs.xtrefs = allXTrefs.xtrefs.filter(existingXTref => {
199
+ return isXTrefInMarkdown(existingXTref, allMarkdownContent);
200
+ });
110
201
 
111
- // Function to process and clean up xref / tref strings found in the markdown file, returning an object with `externalSpec` and `term` properties.
112
- function processXTref(xtref) {
113
- let [externalSpec, term] = xtref.replace(/\[\[(?:xref|tref):/, '').replace(/\]\]/, '').trim().split(/,/, 2);
114
- return {
115
- externalSpec: externalSpec.trim(),
116
- term: term.trim()
202
+ // Add new entries if they are in the markdown
203
+ const regex = /\[\[(?:xref|tref):.*?\]\]/g;
204
+
205
+ // `regex` is the regular expression object, and `allMarkdownContent` is the string being tested. The test method returns a boolean value: true if the pattern is found within the string, and false otherwise.
206
+ if (regex.test(allMarkdownContent)) {
207
+ const xtrefs = allMarkdownContent.match(regex);
208
+ xtrefs.forEach(xtref => {
209
+ const newXTrefObj = processXTref(xtref);
210
+ // Ensure that newXTrefObj is only added to the xtrefs array if there isn't already an object with the same term and externalSpec properties. This helps maintain the uniqueness of entries in the array based on these two properties.
211
+ if (!allXTrefs.xtrefs.some(existingXTref =>
212
+ existingXTref.term === newXTrefObj.term && existingXTref.externalSpec === newXTrefObj.externalSpec)) {
213
+ allXTrefs.xtrefs.push(newXTrefObj);
214
+ }
215
+ });
117
216
  };
118
- }
119
217
 
120
- // Initialize an object to store all xtrefs.
121
- let allXTrefs = { xtrefs: [] };
218
+ // Example at this point:
219
+ // allXTrefs.xtrefs: [
220
+ // { externalSpec: 'kmg-1', term: 'authentic-chained-data-container' },
221
+ // ]
122
222
 
123
- // If the output JSON file exists, load its data.
124
- if (fs.existsSync(outputPathJSON)) {
125
- const existingXTrefs = fs.readJsonSync(outputPathJSON);
126
- allXTrefs = existingXTrefs && existingXTrefs.xtrefs ? existingXTrefs : { xtrefs: [] };
127
- }
223
+ // Extend each xref with additional data and fetch commit information from GitHub.
224
+ extendXTrefs(config, allXTrefs.xtrefs);
128
225
 
129
- // Collect all markdown content
130
- let allMarkdownContent = '';
226
+ // Example at this point:
227
+ // allXTrefs.xtrefs: [
228
+ // {
229
+ // externalSpec: 'kmg-1',
230
+ // term: 'authentic-chained-data-container',
231
+ // repoUrl: 'https://github.com/henkvancann/keri-main-glossary',
232
+ // terms_dir: 'spec/terms-definitions',
233
+ // owner: 'henkvancann',
234
+ // repo: 'keri-main-glossary',
235
+ // site: null
236
+ // }
237
+ // ]
131
238
 
132
- // Read all main repo Markdown files from a list of directories and concatenate their content into a single string.
133
- specTermsDirectories.forEach(specDirectory => {
134
- fs.readdirSync(specDirectory).forEach(file => {
135
- if (file.endsWith('.md')) {
136
- const markdown = fs.readFileSync(`${specDirectory}/${file}`, 'utf8');
137
- allMarkdownContent += markdown;
138
- }
139
- });
140
- });
141
-
142
- // Remove existing entries if not in the combined markdown content
143
- allXTrefs.xtrefs = allXTrefs.xtrefs.filter(existingXTref => {
144
- return isXTrefInMarkdown(existingXTref, allMarkdownContent);
145
- });
146
-
147
- // Add new entries if they are in the markdown
148
- const regex = /\[\[(?:xref|tref):.*?\]\]/g;
149
-
150
- // `regex` is the regular expression object, and `allMarkdownContent` is the string being tested. The test method returns a boolean value: true if the pattern is found within the string, and false otherwise.
151
- if (regex.test(allMarkdownContent)) {
152
- const xtrefs = allMarkdownContent.match(regex);
153
- xtrefs.forEach(xtref => {
154
- const newXTrefObj = processXTref(xtref);
155
- // Ensure that newXTrefObj is only added to the xtrefs array if there isn't already an object with the same term and externalSpec properties. This helps maintain the uniqueness of entries in the array based on these two properties.
156
- if (!allXTrefs.xtrefs.some(existingXTref =>
157
- existingXTref.term === newXTrefObj.term && existingXTref.externalSpec === newXTrefObj.externalSpec)) {
158
- allXTrefs.xtrefs.push(newXTrefObj);
159
- }
160
- });
161
- };
162
-
163
- // Example at this point:
164
- // allXTrefs.xtrefs: [
165
- // { externalSpec: 'kmg-1', term: 'authentic-chained-data-container' },
166
- // ]
167
-
168
- // Extend each xref with additional data and fetch commit information from GitHub.
169
- extendXTrefs(config, allXTrefs.xtrefs);
170
-
171
- // Example at this point:
172
- // allXTrefs.xtrefs: [
173
- // {
174
- // externalSpec: 'kmg-1',
175
- // term: 'authentic-chained-data-container',
176
- // repoUrl: 'https://github.com/henkvancann/keri-main-glossary',
177
- // terms_dir: 'spec/terms-definitions',
178
- // owner: 'henkvancann',
179
- // repo: 'keri-main-glossary',
180
- // site: null
181
- // }
182
- // ]
183
-
184
- (async () => {
185
- try {
186
- for (let xtref of allXTrefs.xtrefs) {
187
- const fetchedData = await searchGitHubCode(GITHUB_API_TOKEN, xtref.term, xtref.owner, xtref.repo, xtref.terms_dir);
188
-
189
- fetchedData.data.items.forEach(item => {
190
- // If the term is found according to the matchTerm function (in the first line, line should start with “[[def:), etc) add the commit hash and content to the xtref object
191
- if (matchTerm(item.content, xtref.term)) {
192
- // console.log('KORKOR item: ', item);
193
- xtref.commitHash = item.sha;
194
- xtref.content = item.content;
195
- console.log(`\n SPEC-UP-T: Match found for term: ${xtref.term} in ${xtref.externalSpec};`);
196
- } else {
239
+ (async () => {
240
+ try {
241
+ for (let xtref of allXTrefs.xtrefs) {
242
+ const fetchedData = await searchGitHubCode(GITHUB_API_TOKEN, xtref.term, xtref.owner, xtref.repo, xtref.terms_dir);
243
+ if (fetchedData.data.items.length === 0) {
197
244
  xtref.commitHash = "not found";
198
245
  xtref.content = "This term was not found in the external repository.";
199
- console.log(`\n SPEC-UP-T: No match found for term: ${xtref.term} in ${xtref.externalSpec};`);
246
+ } else {
247
+ fetchedData.data.items.forEach(item => {
248
+ // If the term is found according to the matchTerm function (in the first line, line should start with “[[def:), etc) add the commit hash and content to the xtref object
249
+ if (matchTerm(item.content, xtref.term)) {
250
+ xtref.commitHash = item.sha;
251
+ xtref.content = item.content;
252
+ console.log(`\n SPEC-UP-T: Match found for term: ${xtref.term} in ${xtref.externalSpec};`);
253
+ } else {
254
+ xtref.commitHash = "not found";
255
+ xtref.content = "This term was not found in the external repository.";
256
+ console.log(`\n SPEC-UP-T: No match found for term: ${xtref.term} in ${xtref.externalSpec};`);
257
+ }
258
+ });
200
259
  }
201
- });
260
+ }
261
+
262
+ const allXTrefsStr = JSON.stringify(allXTrefs, null, 2);
263
+ fs.writeFileSync(outputPathJSON, allXTrefsStr, 'utf8');
264
+ const stringReadyForFileWrite = `const allXTrefs = ${allXTrefsStr};`;
265
+ fs.writeFileSync(outputPathJS, stringReadyForFileWrite, 'utf8');
266
+ fs.writeFileSync(outputPathJSTimeStamped, stringReadyForFileWrite, 'utf8');
267
+
268
+ // Run the render function to update the HTML file
269
+ require('../index.js')({ nowatch: true });
270
+ } catch (error) {
271
+ console.error('An error occurred:', error);
202
272
  }
273
+ })();
274
+ }
203
275
 
204
- const allXTrefsStr = JSON.stringify(allXTrefs, null, 2);
205
- fs.writeFileSync(outputPathJSON, allXTrefsStr, 'utf8');
206
- const stringReadyForFileWrite = `const allXTrefs = ${allXTrefsStr};`;
207
- fs.writeFileSync(outputPathJS, stringReadyForFileWrite, 'utf8');
208
- fs.writeFileSync(outputPathJSTimeStamped, stringReadyForFileWrite, 'utf8');
209
276
 
210
- // Run the render function to update the HTML file
211
- require('../index.js')({ nowatch: true });
212
- } catch (error) {
213
- console.error('An error occurred:', error);
214
- }
215
- })();
216
277
  }
217
278
 
218
279
  module.exports = {
@@ -1,4 +1,5 @@
1
- async function doesUrlExist(url) {
1
+ async function doesUrlExist(repo, termsDir) {
2
+ const url = `${repo}/blob/main/${termsDir}`;
2
3
  try {
3
4
  const response = await fetch(url, { method: 'HEAD' });
4
5
  if (response.ok) {