spec-up-t 1.4.1-beta.2 → 1.4.1-beta.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spec-up-t",
|
|
3
|
-
"version": "1.4.1-beta.
|
|
3
|
+
"version": "1.4.1-beta.3",
|
|
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": {
|
package/src/freeze-spec-data.js
CHANGED
|
@@ -44,3 +44,7 @@ const destFile = path.join(newVersionDir, 'index.html');
|
|
|
44
44
|
fs.copyFileSync(sourceFile, destFile);
|
|
45
45
|
|
|
46
46
|
Logger.success(`Created a freezed specification version in ${destFile}`);
|
|
47
|
+
|
|
48
|
+
// Update the versions index.html to include the newly created version
|
|
49
|
+
const createVersionsIndex = require('./pipeline/configuration/create-versions-index.js');
|
|
50
|
+
createVersionsIndex(outputPath);
|
package/src/freeze.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* freeze.js
|
|
4
|
+
*
|
|
5
|
+
* Legacy wrapper to run the existing src/freeze-spec-data.js script.
|
|
6
|
+
* This file intentionally keeps logic minimal: it simply requires the
|
|
7
|
+
* implementation file so older tooling or CI jobs that call `freeze.js`
|
|
8
|
+
* continue to work without changing behaviour.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* node freeze.js
|
|
12
|
+
* or make it executable and run:
|
|
13
|
+
* ./freeze.js
|
|
14
|
+
*
|
|
15
|
+
* Rationale for keeping this file:
|
|
16
|
+
* - It provides a stable legacy entry point used by external consumers.
|
|
17
|
+
* - The real implementation remains in src/freeze-spec-data.js so maintenance
|
|
18
|
+
* and tests remain focused there.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const path = require('path');
|
|
22
|
+
|
|
23
|
+
// The implementation `freeze-spec-data.js` now lives in the same `src` folder
|
|
24
|
+
// as this wrapper, so require it directly from __dirname.
|
|
25
|
+
const scriptPath = path.join(__dirname, 'freeze-spec-data.js');
|
|
26
|
+
|
|
27
|
+
try {
|
|
28
|
+
// Require executes the implementation file. It is expected to run
|
|
29
|
+
// synchronously at top-level (the existing file performs its actions
|
|
30
|
+
// when loaded).
|
|
31
|
+
require(scriptPath);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
// Keep error reporting minimal and consistent with CLI usage.
|
|
34
|
+
// Use stderr for messages and exit with non-zero code on failure.
|
|
35
|
+
// This keeps behaviour predictable for callers.
|
|
36
|
+
// eslint-disable-next-line no-console
|
|
37
|
+
console.error('Failed to execute freeze script:', err && err.message ? err.message : err);
|
|
38
|
+
process.exitCode = 1;
|
|
39
|
+
}
|
|
@@ -200,15 +200,22 @@ function parseTref(token) {
|
|
|
200
200
|
displayText = `<span class='term-external-original-term term-original-term' title='original term'>${termName}</span>`;
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
//
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
203
|
+
// Generate HTML spans for each term/alias combination, similar to parseDef
|
|
204
|
+
// This creates anchor points that can be referenced by [[ref: ...]] links
|
|
205
|
+
// token.info.args for tref is [externalSpec, term, alias1, alias2, ...]
|
|
206
|
+
// We need to create IDs for the term and all aliases (skip the externalSpec at index 0)
|
|
207
|
+
const termsAndAliases = [termName, ...aliases];
|
|
208
|
+
|
|
209
|
+
return termsAndAliases.reduce((acc, syn, index) => {
|
|
210
|
+
// Generate a unique term ID by normalizing the synonym: replace whitespace with hyphens and convert to lowercase
|
|
211
|
+
const termId = `term:${syn.replace(whitespace.oneOrMore, '-').toLowerCase()}`;
|
|
212
|
+
// Add title attribute to the innermost span (first in the array, which wraps the display text directly)
|
|
213
|
+
// This provides a tooltip showing which external term this alias refers to
|
|
214
|
+
const titleAttr = index === 0 && aliases.length > 0 ? ` title="Externally defined as ${termName}"` : '';
|
|
215
|
+
// Add class and data attributes only to the outermost span (last one created)
|
|
216
|
+
const outerAttrs = index === termsAndAliases.length - 1 ? ` data-original-term="${termName}" class="term-external"` : '';
|
|
217
|
+
return `<span id="${termId}"${outerAttrs}${titleAttr}>${acc}</span>`;
|
|
218
|
+
}, displayText);
|
|
212
219
|
}
|
|
213
220
|
|
|
214
221
|
/**
|
|
@@ -237,7 +244,7 @@ function processXTrefObject(xtref) {
|
|
|
237
244
|
|
|
238
245
|
// Collect all aliases from parts after the term (index 1), trim and filter empties
|
|
239
246
|
const allAliases = parts.slice(2).map(p => p.trim()).filter(Boolean);
|
|
240
|
-
|
|
247
|
+
|
|
241
248
|
// Initialize both tref and xref alias arrays
|
|
242
249
|
xtrefObject.trefAliases = [];
|
|
243
250
|
xtrefObject.xrefAliases = [];
|
|
@@ -118,22 +118,24 @@ async function mergeXrefTermsIntoAllXTrefs(xrefTerms, outputPathJSON, outputPath
|
|
|
118
118
|
// Add xref terms to the allXTrefs structure
|
|
119
119
|
// Mark them with source: 'xref' to distinguish from tref entries
|
|
120
120
|
xrefTerms.forEach(xrefTerm => {
|
|
121
|
-
// Check if this term already exists (
|
|
121
|
+
// Check if this term already exists (match by externalSpec and term only)
|
|
122
|
+
// Don't filter by source because entries from markdown scanning don't have source field
|
|
122
123
|
const existingIndex = allXTrefs.xtrefs.findIndex(existing =>
|
|
123
124
|
existing.externalSpec === xrefTerm.externalSpec &&
|
|
124
|
-
existing.term === xrefTerm.term
|
|
125
|
-
existing.source === 'xref'
|
|
125
|
+
existing.term === xrefTerm.term
|
|
126
126
|
);
|
|
127
127
|
|
|
128
128
|
if (existingIndex >= 0) {
|
|
129
|
-
// Update existing entry
|
|
129
|
+
// Update existing entry - preserve the existing metadata but add/update content
|
|
130
130
|
allXTrefs.xtrefs[existingIndex] = {
|
|
131
131
|
...allXTrefs.xtrefs[existingIndex],
|
|
132
|
-
|
|
132
|
+
content: xrefTerm.content, // Update the content from fetched HTML
|
|
133
|
+
source: xrefTerm.source, // Add source field
|
|
134
|
+
termId: xrefTerm.termId, // Add termId if not present
|
|
133
135
|
lastUpdated: new Date().toISOString()
|
|
134
136
|
};
|
|
135
137
|
} else {
|
|
136
|
-
// Add new entry
|
|
138
|
+
// Add new entry (this term wasn't referenced in the markdown)
|
|
137
139
|
allXTrefs.xtrefs.push({
|
|
138
140
|
...xrefTerm,
|
|
139
141
|
lastUpdated: new Date().toISOString()
|
|
@@ -179,28 +181,53 @@ function extractTermsFromHtml(externalSpec, html) {
|
|
|
179
181
|
batch.each((index, termElement) => {
|
|
180
182
|
try {
|
|
181
183
|
const $termElement = $(termElement);
|
|
182
|
-
const termId = $termElement.attr('id');
|
|
183
184
|
|
|
184
|
-
//
|
|
185
|
-
|
|
185
|
+
// The id can be on the dt element itself OR on span(s) inside it
|
|
186
|
+
// Some terms have multiple nested spans with different IDs (e.g., aliases)
|
|
187
|
+
// We need to extract ALL term IDs from the dt element
|
|
188
|
+
const termIds = [];
|
|
189
|
+
|
|
190
|
+
// First check if dt itself has an id
|
|
191
|
+
const dtId = $termElement.attr('id');
|
|
192
|
+
if (dtId && dtId.includes('term:')) {
|
|
193
|
+
termIds.push(dtId.replace('term:', ''));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Then find all spans with ids that contain 'term:'
|
|
197
|
+
$termElement.find('span[id*="term:"]').each((i, span) => {
|
|
198
|
+
const spanId = $(span).attr('id');
|
|
199
|
+
if (spanId && spanId.includes('term:')) {
|
|
200
|
+
const termName = spanId.replace('term:', '');
|
|
201
|
+
if (!termIds.includes(termName)) {
|
|
202
|
+
termIds.push(termName);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Skip if no valid term IDs found
|
|
208
|
+
if (termIds.length === 0) {
|
|
186
209
|
return;
|
|
187
210
|
}
|
|
188
211
|
|
|
189
|
-
const termName = termId.replace('term:', '');
|
|
190
212
|
const dd = $termElement.next('dd');
|
|
191
213
|
|
|
192
214
|
if (dd.length > 0) {
|
|
193
|
-
//
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
215
|
+
const ddContent = $.html(dd); // Store the complete DD content once
|
|
216
|
+
|
|
217
|
+
// Create a term object for each ID found in this dt element
|
|
218
|
+
// This handles cases where one term definition has multiple aliases
|
|
219
|
+
termIds.forEach(termName => {
|
|
220
|
+
const termObj = {
|
|
221
|
+
externalSpec: externalSpec,
|
|
222
|
+
term: termName,
|
|
223
|
+
content: ddContent,
|
|
224
|
+
// Add metadata for consistency with tref structure
|
|
225
|
+
source: 'xref', // Distinguish from tref entries
|
|
226
|
+
termId: `term:${externalSpec}:${termName}`, // Fully qualified term ID
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
terms.push(termObj);
|
|
230
|
+
});
|
|
204
231
|
}
|
|
205
232
|
} catch (termError) {
|
|
206
233
|
Logger.warn(`Error processing term in ${externalSpec}:`, termError.message);
|