spec-up-t 1.4.1 → 1.6.0-beta.1
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/assets/compiled/body.js +3 -2
- package/assets/compiled/head.css +5 -5
- package/assets/css/embedded-libraries/bootstrap.min.css +1 -1
- package/assets/css/header-navbar.css +4 -4
- package/assets/css/index.css +5 -4
- package/assets/css/refs.css +30 -0
- package/assets/css/terms-and-definitions.css +89 -1
- package/assets/js/github-issues.js +3 -3
- package/assets/js/insert-irefs.js +214 -0
- package/config/asset-map.json +2 -1
- package/examples/read-console-messages.js +102 -0
- package/gulpfile.js +42 -1
- package/index.js +49 -1
- package/package.json +2 -1
- package/src/create-docx.js +13 -6
- package/src/create-pdf.js +22 -18
- package/src/health-check.js +47 -629
- package/src/init.js +7 -3
- package/src/install-from-boilerplate/config-scripts-keys.js +1 -1
- package/src/markdown-it/README.md +2 -14
- package/src/markdown-it/index.js +1 -7
- package/src/parsers/template-tag-parser.js +42 -4
- package/src/pipeline/postprocessing/definition-list-postprocessor.js +4 -2
- package/src/pipeline/references/collect-external-references.js +101 -17
- package/src/pipeline/references/external-references-service.js +102 -21
- package/src/pipeline/references/fetch-terms-from-index.js +62 -1
- package/src/pipeline/references/process-xtrefs-data.js +67 -9
- package/src/pipeline/references/xtref-utils.js +22 -3
- package/src/pipeline/rendering/render-spec-document.js +0 -1
- package/src/run-healthcheck.js +177 -0
- package/src/utils/logger.js +129 -8
- package/src/utils/message-collector.js +144 -0
- package/src/utils/regex-patterns.js +3 -1
- package/templates/template.html +6 -6
- package/test/logger.test.js +290 -0
- package/test/message-collector.test.js +286 -0
- package/assets/css/insert-trefs.css +0 -1
- package/src/markdown-it/link-enhancement.js +0 -98
- package/src/utils/LOGGER.md +0 -81
package/src/init.js
CHANGED
|
@@ -8,14 +8,14 @@ async function initialize() {
|
|
|
8
8
|
try {
|
|
9
9
|
// Ensure the .cache directory exists
|
|
10
10
|
await fs.ensureDir(outputDir);
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
// Check if the init script has already run
|
|
13
13
|
if (await fs.pathExists(initFlagPath)) {
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
// Place the init script here
|
|
18
|
-
|
|
18
|
+
|
|
19
19
|
// End of the init script
|
|
20
20
|
|
|
21
21
|
// Create the init flag file
|
|
@@ -23,7 +23,11 @@ async function initialize() {
|
|
|
23
23
|
|
|
24
24
|
Logger.success('Initialization complete.');
|
|
25
25
|
} catch (error) {
|
|
26
|
-
Logger.error(
|
|
26
|
+
Logger.error('Initialization failed', {
|
|
27
|
+
context: 'Failed to set up spec-up-t boilerplate files',
|
|
28
|
+
hint: 'Ensure you have write permissions in the current directory. Try running with appropriate permissions or in a different directory',
|
|
29
|
+
details: error.message
|
|
30
|
+
});
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
|
|
@@ -11,7 +11,7 @@ const configScriptsKeys = {
|
|
|
11
11
|
"menu": "bash ./node_modules/spec-up-t/src/install-from-boilerplate/menu.sh",
|
|
12
12
|
"addremovexrefsource": "node --no-warnings -e \"require('spec-up-t/src/add-remove-xref-source.js')\"",
|
|
13
13
|
"configure": "node --no-warnings -e \"require('spec-up-t/src/configure.js')\"",
|
|
14
|
-
"healthCheck": "node --no-warnings
|
|
14
|
+
"healthCheck": "node --no-warnings ./node_modules/spec-up-t/src/health-check.js",
|
|
15
15
|
"custom-update": "npm update && node -e \"require('spec-up-t/src/install-from-boilerplate/custom-update.js')\""
|
|
16
16
|
};
|
|
17
17
|
|
|
@@ -46,19 +46,7 @@ Our extensions override default renderer rules and add custom inline parsing rul
|
|
|
46
46
|
- Creates template tokens with parsed information
|
|
47
47
|
- Provides a renderer rule to convert template tokens to HTML
|
|
48
48
|
|
|
49
|
-
### 3. `
|
|
50
|
-
|
|
51
|
-
**Purpose**: Adds path-based attributes to links for CSS styling and JavaScript targeting.
|
|
52
|
-
|
|
53
|
-
**Features**:
|
|
54
|
-
|
|
55
|
-
- Extracts domain and path segments from URLs
|
|
56
|
-
- Adds `path-0`, `path-1`, etc. attributes to anchor tags
|
|
57
|
-
- Special handling for auto-detected links (linkify)
|
|
58
|
-
|
|
59
|
-
**How it works**: Overrides `link_open` and `link_close` renderer rules.
|
|
60
|
-
|
|
61
|
-
### 4. `definition-lists.js`
|
|
49
|
+
### 3. `definition-lists.js`
|
|
62
50
|
|
|
63
51
|
**Purpose**: Advanced processing of definition lists for terminology and reference management.
|
|
64
52
|
|
|
@@ -75,7 +63,7 @@ Our extensions override default renderer rules and add custom inline parsing rul
|
|
|
75
63
|
- Uses helper functions to analyze token structure and content
|
|
76
64
|
- Applies CSS classes based on term types and context
|
|
77
65
|
|
|
78
|
-
###
|
|
66
|
+
### 4. `index.js`
|
|
79
67
|
|
|
80
68
|
**Purpose**: Main orchestrator that applies all enhancements in the correct order.
|
|
81
69
|
|
package/src/markdown-it/index.js
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
*
|
|
13
13
|
* - TABLE ENHANCEMENT: Bootstrap styling and responsive wrappers
|
|
14
14
|
* - TEMPLATE-TAG SYNTAX: Custom [[template-tag:args]] syntax processing
|
|
15
|
-
* - LINK ENHANCEMENT: Path-based attributes for links
|
|
16
15
|
* - DEFINITION LISTS: Advanced terminology and reference list handling
|
|
17
16
|
*
|
|
18
17
|
* This modular approach makes the code more maintainable and easier to
|
|
@@ -22,7 +21,6 @@
|
|
|
22
21
|
// Import all the specialized enhancement modules
|
|
23
22
|
const applyTableEnhancements = require('./table-enhancement');
|
|
24
23
|
const applyTemplateTagSyntax = require('./template-tag-syntax');
|
|
25
|
-
const applyLinkEnhancements = require('./link-enhancement');
|
|
26
24
|
const applyDefinitionListEnhancements = require('./definition-lists');
|
|
27
25
|
|
|
28
26
|
/**
|
|
@@ -64,10 +62,7 @@ function applyMarkdownItExtensions(md, templates = []) {
|
|
|
64
62
|
// 2. Template-tag syntax - should be applied early as other modules may depend on it
|
|
65
63
|
applyTemplateTagSyntax(md, templates);
|
|
66
64
|
|
|
67
|
-
// 3.
|
|
68
|
-
applyLinkEnhancements(md);
|
|
69
|
-
|
|
70
|
-
// 4. Definition lists - depends on template-tag syntax for term type detection
|
|
65
|
+
// 3. Definition lists - depends on template-tag syntax for term type detection
|
|
71
66
|
applyDefinitionListEnhancements(md);
|
|
72
67
|
|
|
73
68
|
// The markdown-it instance is now fully enhanced and ready for use
|
|
@@ -79,5 +74,4 @@ module.exports = applyMarkdownItExtensions;
|
|
|
79
74
|
// Also export individual modules for fine-grained control if needed
|
|
80
75
|
module.exports.tableEnhancements = applyTableEnhancements;
|
|
81
76
|
module.exports.templateTagSyntax = applyTemplateTagSyntax;
|
|
82
|
-
module.exports.linkEnhancements = applyLinkEnhancements;
|
|
83
77
|
module.exports.definitionLists = applyDefinitionListEnhancements;
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
const { findExternalSpecByKey } = require('../pipeline/references/external-references-service.js');
|
|
15
15
|
const { lookupXrefTerm } = require('../pipeline/rendering/render-utils.js');
|
|
16
16
|
const { whitespace, htmlComments, contentCleaning, externalReferences } = require('../utils/regex-patterns');
|
|
17
|
+
const Logger = require('../utils/logger.js');
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* Extracts the current file from token content for source tracking
|
|
@@ -32,7 +33,7 @@ function extractCurrentFile(token, globalState) {
|
|
|
32
33
|
* @param {Object} config - Configuration object containing specs and settings
|
|
33
34
|
* @param {Object} globalState - Global state object containing definitions, references, etc.
|
|
34
35
|
* @param {Object} token - The markdown-it token being processed
|
|
35
|
-
* @param {string} type - The type of construct (def, ref, xref, tref)
|
|
36
|
+
* @param {string} type - The type of construct (def, ref, iref, xref, tref)
|
|
36
37
|
* @param {string} primary - The primary content/term
|
|
37
38
|
* @returns {string} The rendered HTML for the construct
|
|
38
39
|
*/
|
|
@@ -44,6 +45,8 @@ function parseTemplateTag(config, globalState, token, type, primary) {
|
|
|
44
45
|
switch (type) {
|
|
45
46
|
case 'def':
|
|
46
47
|
return parseDef(globalState, token, primary, currentFile);
|
|
48
|
+
case 'iref':
|
|
49
|
+
return parseIref(globalState, primary);
|
|
47
50
|
case 'xref':
|
|
48
51
|
return parseXref(config, token);
|
|
49
52
|
case 'tref':
|
|
@@ -129,17 +132,41 @@ function parseRef(globalState, primary) {
|
|
|
129
132
|
return `<a class="term-reference" href="#term:${termId}">${primary}</a>`;
|
|
130
133
|
}
|
|
131
134
|
|
|
135
|
+
/**
|
|
136
|
+
* Processes [[iref: term]] constructs
|
|
137
|
+
* Creates a placeholder that will be replaced client-side with a copy of the term definition
|
|
138
|
+
* This allows inline copying of existing term definitions from the terms-and-definitions-list
|
|
139
|
+
* @param {Object} globalState - Global state to track inline references
|
|
140
|
+
* @param {string} primary - The term to inline copy
|
|
141
|
+
* @returns {string} HTML placeholder element that will be replaced by client-side script
|
|
142
|
+
*/
|
|
143
|
+
function parseIref(globalState, primary) {
|
|
144
|
+
// Track this inline reference for validation purposes
|
|
145
|
+
globalState.references.push(primary);
|
|
146
|
+
|
|
147
|
+
// Create a placeholder span with data attribute containing the term to copy
|
|
148
|
+
// The client-side script (insert-irefs.js) will find this and replace it with
|
|
149
|
+
// a copy of the actual <dt> and <dd> elements from the terms-and-definitions-list
|
|
150
|
+
const termId = primary.replace(whitespace.oneOrMore, '-').toLowerCase();
|
|
151
|
+
return `<span class="iref-placeholder" data-iref-term="${termId}" data-iref-original="${primary}"></span>`;
|
|
152
|
+
}
|
|
153
|
+
|
|
132
154
|
/**
|
|
133
155
|
* Processes [[xref: spec, term, alias, ...]] constructs
|
|
134
156
|
* Creates links to external specification terms with tooltips
|
|
135
157
|
* Uses primaryDisplayTerm concept: shows first alias if available, otherwise shows the term itself
|
|
136
158
|
* @param {Object} config - Configuration containing external specs
|
|
137
159
|
* @param {Object} token - The markdown-it token
|
|
138
|
-
* @returns {string} HTML anchor element linking to external term
|
|
160
|
+
* @returns {string} HTML anchor element linking to external term or error span if unresolved
|
|
139
161
|
*/
|
|
140
162
|
function parseXref(config, token) {
|
|
141
163
|
const externalSpec = findExternalSpecByKey(config, token.info.args[0]);
|
|
142
|
-
|
|
164
|
+
|
|
165
|
+
// If external spec cannot be found, return error indicator
|
|
166
|
+
if (!externalSpec) {
|
|
167
|
+
return `<span class="no-xref-found-message" title="External spec '${token.info.args[0]}' not found in configuration">xref cannot be resolved</span>`;
|
|
168
|
+
}
|
|
169
|
+
|
|
143
170
|
const termName = token.info.args[1];
|
|
144
171
|
const aliases = token.info.args.slice(2).filter(Boolean); // Get all aliases after the term
|
|
145
172
|
const term = termName.replace(whitespace.oneOrMore, '-').toLowerCase();
|
|
@@ -148,8 +175,11 @@ function parseXref(config, token) {
|
|
|
148
175
|
// Determine the primary display term (first alias if available, otherwise original term)
|
|
149
176
|
const primaryDisplayTerm = aliases.length > 0 ? aliases[0] : termName;
|
|
150
177
|
|
|
178
|
+
// Build the href attribute using the external spec's gh_page
|
|
179
|
+
const href = `${externalSpec.gh_page}#term:${term}`;
|
|
180
|
+
|
|
151
181
|
// Build link attributes with both local and external href capabilities
|
|
152
|
-
let linkAttributes = `class="x-term-reference term-reference" data-local-href="#term:${token.info.args[0]}:${term}" href="${
|
|
182
|
+
let linkAttributes = `class="x-term-reference term-reference" data-local-href="#term:${token.info.args[0]}:${term}" href="${href}"`;
|
|
153
183
|
|
|
154
184
|
// Add tooltip content if term definition is available
|
|
155
185
|
if (xrefTerm && xrefTerm.content) {
|
|
@@ -262,6 +292,13 @@ function processXTrefObject(xtref) {
|
|
|
262
292
|
if (allAliases.length > 0) {
|
|
263
293
|
xtrefObject.firstXrefAlias = allAliases[0];
|
|
264
294
|
}
|
|
295
|
+
|
|
296
|
+
// Log error if xref has more than one alias
|
|
297
|
+
// xref should only have 0 or 1 alias, unlike tref which supports multiple aliases
|
|
298
|
+
if (allAliases.length > 1) {
|
|
299
|
+
const extraAliases = allAliases.slice(1).join(', ');
|
|
300
|
+
Logger.error(`Invalid xref syntax: [[xref: ${xtrefObject.externalSpec}, ${xtrefObject.term}, ${allAliases.join(', ')}]] has ${allAliases.length} aliases. Only the first alias "${allAliases[0]}" will be used. Extra aliases ignored: ${extraAliases}.`);
|
|
301
|
+
}
|
|
265
302
|
}
|
|
266
303
|
|
|
267
304
|
return xtrefObject;
|
|
@@ -282,6 +319,7 @@ module.exports = {
|
|
|
282
319
|
createTemplateTagParser,
|
|
283
320
|
// Export individual functions for testing purposes
|
|
284
321
|
parseDef,
|
|
322
|
+
parseIref,
|
|
285
323
|
parseXref,
|
|
286
324
|
parseTref,
|
|
287
325
|
parseRef,
|
|
@@ -65,7 +65,8 @@ function sortDefinitionTermsInHtml(html) {
|
|
|
65
65
|
});
|
|
66
66
|
|
|
67
67
|
// Return the modified HTML
|
|
68
|
-
|
|
68
|
+
// Extract only the body's innerHTML to avoid wrapping in <html><head></head><body> tags
|
|
69
|
+
return dom.window.document.body.innerHTML;
|
|
69
70
|
}
|
|
70
71
|
|
|
71
72
|
/**
|
|
@@ -340,7 +341,8 @@ function fixDefinitionListStructure(html) {
|
|
|
340
341
|
}
|
|
341
342
|
|
|
342
343
|
// Return the fixed HTML
|
|
343
|
-
|
|
344
|
+
// Extract only the body's innerHTML to avoid wrapping in <html><head></head><body> tags
|
|
345
|
+
return dom.window.document.body.innerHTML;
|
|
344
346
|
}
|
|
345
347
|
|
|
346
348
|
module.exports = {
|
|
@@ -13,6 +13,7 @@ const fs = require('fs-extra');
|
|
|
13
13
|
const readlineSync = require('readline-sync');
|
|
14
14
|
|
|
15
15
|
const Logger = require('../../utils/logger');
|
|
16
|
+
const messageCollector = require('../../utils/message-collector');
|
|
16
17
|
const { shouldProcessFile } = require('../../utils/file-filter');
|
|
17
18
|
const { getCurrentBranch } = require('../../utils/git-info');
|
|
18
19
|
const { addNewXTrefsFromMarkdown, isXTrefInAnyFile } = require('./xtref-utils');
|
|
@@ -24,7 +25,8 @@ const { processXTrefObject } = require('../../parsers/template-tag-parser');
|
|
|
24
25
|
* automated callers of `collectExternalReferences` continue to receive a fully rendered spec.
|
|
25
26
|
*/
|
|
26
27
|
function renderSpecification() {
|
|
27
|
-
|
|
28
|
+
// Pass skipClear to preserve messages from collectExternalReferences
|
|
29
|
+
require('../../../index.js')({ nowatch: true, skipClear: true });
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
/**
|
|
@@ -44,7 +46,11 @@ function normalizeSpecConfiguration(config, { noSpecsMessage }) {
|
|
|
44
46
|
const specs = Array.isArray(config?.specs) ? config.specs : [];
|
|
45
47
|
|
|
46
48
|
if (specs.length === 0) {
|
|
47
|
-
Logger.error(noSpecsMessage
|
|
49
|
+
Logger.error(noSpecsMessage, {
|
|
50
|
+
context: 'specs.json is missing or has no specs array',
|
|
51
|
+
hint: 'Create a valid specs.json file in your project root. Run "npm run init" or copy from: https://github.com/trustoverip/spec-up-t-starter-pack',
|
|
52
|
+
details: 'The specs array is required to configure your specification'
|
|
53
|
+
});
|
|
48
54
|
return null;
|
|
49
55
|
}
|
|
50
56
|
|
|
@@ -63,7 +69,11 @@ function normalizeSpecConfiguration(config, { noSpecsMessage }) {
|
|
|
63
69
|
*/
|
|
64
70
|
function extendXTrefs(config, xtrefs) {
|
|
65
71
|
if (config.specs[0].external_specs_repos) {
|
|
66
|
-
Logger.warn('Your specs.json file uses an outdated structure
|
|
72
|
+
Logger.warn('Your specs.json file uses an outdated structure', {
|
|
73
|
+
context: 'The "external_specs_repos" field is deprecated',
|
|
74
|
+
hint: 'Update to the new structure using "external_specs" instead. See: https://github.com/trustoverip/spec-up-t/blob/master/src/install-from-boilerplate/boilerplate/specs.json',
|
|
75
|
+
details: 'External references may not work correctly with the old structure'
|
|
76
|
+
});
|
|
67
77
|
return;
|
|
68
78
|
}
|
|
69
79
|
|
|
@@ -116,7 +126,11 @@ function extendXTrefs(config, xtrefs) {
|
|
|
116
126
|
try {
|
|
117
127
|
xtref.branch = getCurrentBranch();
|
|
118
128
|
} catch (error) {
|
|
119
|
-
Logger.warn(`Could not get current branch for xtref ${xtref.externalSpec}:${xtref.term}
|
|
129
|
+
Logger.warn(`Could not get current branch for xtref ${xtref.externalSpec}:${xtref.term}`, {
|
|
130
|
+
context: 'Git branch detection failed for external reference',
|
|
131
|
+
hint: 'Ensure you\'re in a git repository, or specify github_repo_branch in specs.json external_specs configuration',
|
|
132
|
+
details: `${error.message}. Using default: main`
|
|
133
|
+
});
|
|
120
134
|
xtref.branch = 'main';
|
|
121
135
|
}
|
|
122
136
|
});
|
|
@@ -151,7 +165,7 @@ function processExternalReferences(config, GITHUB_API_TOKEN) {
|
|
|
151
165
|
}
|
|
152
166
|
|
|
153
167
|
const userInput = readlineSync.question(
|
|
154
|
-
`❌ This external reference is not a valid URL:
|
|
168
|
+
`❌ This external reference is not a valid URL:
|
|
155
169
|
|
|
156
170
|
Repository: ${repo.url},
|
|
157
171
|
|
|
@@ -193,14 +207,22 @@ function processExternalReferences(config, GITHUB_API_TOKEN) {
|
|
|
193
207
|
const termsDir = spec?.spec_terms_directory;
|
|
194
208
|
|
|
195
209
|
if (!specDir || !termsDir) {
|
|
196
|
-
Logger.warn(`Spec entry is missing spec_directory or spec_terms_directory
|
|
210
|
+
Logger.warn(`Spec entry is missing spec_directory or spec_terms_directory`, {
|
|
211
|
+
context: 'Invalid specs.json configuration',
|
|
212
|
+
hint: 'Ensure each spec in specs.json has both "spec_directory" and "spec_terms_directory" fields',
|
|
213
|
+
details: `Incomplete spec entry: ${JSON.stringify(spec)}`
|
|
214
|
+
});
|
|
197
215
|
return directories;
|
|
198
216
|
}
|
|
199
217
|
|
|
200
218
|
const resolvedDir = path.join(specDir, termsDir);
|
|
201
219
|
|
|
202
220
|
if (!fs.existsSync(resolvedDir)) {
|
|
203
|
-
Logger.warn(`Spec terms directory does not exist: ${resolvedDir}
|
|
221
|
+
Logger.warn(`Spec terms directory does not exist: ${resolvedDir}`, {
|
|
222
|
+
context: 'Directory specified in specs.json not found',
|
|
223
|
+
hint: 'Create the directory or update the path in specs.json. Typically this should be "spec/term-definitions" or similar',
|
|
224
|
+
details: `Expected path: ${resolvedDir}`
|
|
225
|
+
});
|
|
204
226
|
return directories;
|
|
205
227
|
}
|
|
206
228
|
|
|
@@ -209,7 +231,11 @@ function processExternalReferences(config, GITHUB_API_TOKEN) {
|
|
|
209
231
|
}, []);
|
|
210
232
|
|
|
211
233
|
if (specTermsDirectories.length === 0) {
|
|
212
|
-
Logger.warn('No spec terms directories found. Skipping external reference collection
|
|
234
|
+
Logger.warn('No spec terms directories found. Skipping external reference collection', {
|
|
235
|
+
context: 'Cannot collect external references without valid terminology directories',
|
|
236
|
+
hint: 'Check specs.json configuration. Ensure spec_directory and spec_terms_directory point to existing directories',
|
|
237
|
+
details: 'External trefs and xrefs will not be processed'
|
|
238
|
+
});
|
|
213
239
|
return;
|
|
214
240
|
}
|
|
215
241
|
|
|
@@ -232,7 +258,7 @@ function processExternalReferences(config, GITHUB_API_TOKEN) {
|
|
|
232
258
|
);
|
|
233
259
|
|
|
234
260
|
fileContents.forEach((content, filename) => {
|
|
235
|
-
addNewXTrefsFromMarkdown(content, allXTrefs, filename, processXTrefObject);
|
|
261
|
+
addNewXTrefsFromMarkdown(content, allXTrefs, filename, processXTrefObject, externalSpecsRepos);
|
|
236
262
|
});
|
|
237
263
|
|
|
238
264
|
extendXTrefs(config, allXTrefs.xtrefs);
|
|
@@ -242,9 +268,17 @@ function processExternalReferences(config, GITHUB_API_TOKEN) {
|
|
|
242
268
|
/**
|
|
243
269
|
* Public entry point for the external reference collection stage.
|
|
244
270
|
*
|
|
245
|
-
* @param {{ pat?: string }} options - Optional overrides (GitHub PAT).
|
|
271
|
+
* @param {{ pat?: string, collectMessages?: boolean }} options - Optional overrides (GitHub PAT, message collection).
|
|
246
272
|
*/
|
|
247
273
|
function collectExternalReferences(options = {}) {
|
|
274
|
+
// Start collecting messages if requested
|
|
275
|
+
const shouldCollectMessages = options.collectMessages !== false; // Collect by default
|
|
276
|
+
|
|
277
|
+
if (shouldCollectMessages) {
|
|
278
|
+
messageCollector.clearMessages();
|
|
279
|
+
messageCollector.startCollecting('collectExternalReferences');
|
|
280
|
+
}
|
|
281
|
+
|
|
248
282
|
const config = fs.readJsonSync('specs.json');
|
|
249
283
|
const normalizedConfig = normalizeSpecConfiguration(config, {
|
|
250
284
|
noSpecsMessage: 'No specs defined in specs.json. Nothing to collect.'
|
|
@@ -252,6 +286,10 @@ function collectExternalReferences(options = {}) {
|
|
|
252
286
|
|
|
253
287
|
// Bail out immediately if the specs.json file lacks the required specs collection.
|
|
254
288
|
if (!normalizedConfig) {
|
|
289
|
+
if (shouldCollectMessages) {
|
|
290
|
+
messageCollector.stopCollecting();
|
|
291
|
+
messageCollector.saveMessages();
|
|
292
|
+
}
|
|
255
293
|
return;
|
|
256
294
|
}
|
|
257
295
|
|
|
@@ -259,8 +297,11 @@ function collectExternalReferences(options = {}) {
|
|
|
259
297
|
const GITHUB_API_TOKEN = options.pat || process.env.GITHUB_API_TOKEN;
|
|
260
298
|
|
|
261
299
|
if (!GITHUB_API_TOKEN) {
|
|
262
|
-
Logger.warn('No GitHub Personal Access Token (PAT) found. Running without authentication
|
|
263
|
-
|
|
300
|
+
Logger.warn('No GitHub Personal Access Token (PAT) found. Running without authentication', {
|
|
301
|
+
context: 'GitHub API requests will use unauthenticated access',
|
|
302
|
+
hint: 'Set GITHUB_PAT environment variable to increase rate limit from 60 to 5000 requests/hour. See: https://trustoverip.github.io/spec-up-t-website/docs/getting-started/github-token',
|
|
303
|
+
details: 'You may hit rate limits when fetching many external references'
|
|
304
|
+
});
|
|
264
305
|
}
|
|
265
306
|
|
|
266
307
|
// Communicate that the expected external_specs array is missing entirely.
|
|
@@ -268,7 +309,16 @@ function collectExternalReferences(options = {}) {
|
|
|
268
309
|
Logger.info(
|
|
269
310
|
'No external_specs array found on the first spec entry in specs.json. External reference collection is skipped.'
|
|
270
311
|
);
|
|
271
|
-
|
|
312
|
+
|
|
313
|
+
if (shouldCollectMessages) {
|
|
314
|
+
messageCollector.stopCollecting();
|
|
315
|
+
messageCollector.saveMessages().then(path => {
|
|
316
|
+
Logger.success(`Console messages saved to: ${path}`);
|
|
317
|
+
renderSpecification();
|
|
318
|
+
});
|
|
319
|
+
} else {
|
|
320
|
+
renderSpecification();
|
|
321
|
+
}
|
|
272
322
|
return;
|
|
273
323
|
}
|
|
274
324
|
|
|
@@ -277,7 +327,16 @@ function collectExternalReferences(options = {}) {
|
|
|
277
327
|
Logger.info(
|
|
278
328
|
'The external_specs array in specs.json is empty. Add external repositories to collect external references.'
|
|
279
329
|
);
|
|
280
|
-
|
|
330
|
+
|
|
331
|
+
if (shouldCollectMessages) {
|
|
332
|
+
messageCollector.stopCollecting();
|
|
333
|
+
messageCollector.saveMessages().then(path => {
|
|
334
|
+
Logger.success(`Console messages saved to: ${path}`);
|
|
335
|
+
renderSpecification();
|
|
336
|
+
});
|
|
337
|
+
} else {
|
|
338
|
+
renderSpecification();
|
|
339
|
+
}
|
|
281
340
|
return;
|
|
282
341
|
}
|
|
283
342
|
|
|
@@ -287,15 +346,40 @@ function collectExternalReferences(options = {}) {
|
|
|
287
346
|
if (pipeline && typeof pipeline.then === 'function') {
|
|
288
347
|
return pipeline
|
|
289
348
|
.then(result => {
|
|
290
|
-
|
|
291
|
-
|
|
349
|
+
if (shouldCollectMessages) {
|
|
350
|
+
messageCollector.stopCollecting();
|
|
351
|
+
return messageCollector.saveMessages().then(path => {
|
|
352
|
+
Logger.success(`Console messages saved to: ${path}`);
|
|
353
|
+
renderSpecification();
|
|
354
|
+
return result;
|
|
355
|
+
});
|
|
356
|
+
} else {
|
|
357
|
+
renderSpecification();
|
|
358
|
+
return result;
|
|
359
|
+
}
|
|
292
360
|
})
|
|
293
361
|
.catch(error => {
|
|
294
362
|
Logger.error('Rendering failed after collecting external references.', error);
|
|
363
|
+
|
|
364
|
+
if (shouldCollectMessages) {
|
|
365
|
+
messageCollector.stopCollecting();
|
|
366
|
+
messageCollector.saveMessages().catch(() => {
|
|
367
|
+
// Silent fail on save error
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
|
|
295
371
|
throw error;
|
|
296
372
|
});
|
|
297
373
|
} else {
|
|
298
|
-
|
|
374
|
+
if (shouldCollectMessages) {
|
|
375
|
+
messageCollector.stopCollecting();
|
|
376
|
+
messageCollector.saveMessages().then(path => {
|
|
377
|
+
Logger.success(`Console messages saved to: ${path}`);
|
|
378
|
+
renderSpecification();
|
|
379
|
+
});
|
|
380
|
+
} else {
|
|
381
|
+
renderSpecification();
|
|
382
|
+
}
|
|
299
383
|
return pipeline;
|
|
300
384
|
}
|
|
301
385
|
}
|