spec-up-t 1.2.3 → 1.2.5
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/.sonarlint/connectedMode.json +5 -0
- package/assets/compiled/body.js +35 -32
- package/assets/compiled/head.css +7 -5
- package/assets/compiled/head.js +3 -3
- package/assets/css/add-bootstrap-classes-to-images.css +34 -0
- package/assets/css/adjust-font-size.css +6 -11
- package/assets/css/backToTop.css +0 -1
- package/assets/css/image-full-size.css +44 -0
- package/assets/css/index.css +1 -2
- package/assets/css/pdf-styles.css +23 -27
- package/assets/css/repo-issues.css +0 -6
- package/assets/css/search.css +0 -1
- package/assets/css/sidebar-toc.css +13 -12
- package/assets/css/terms-and-definitions.css +43 -37
- package/assets/js/add-bootstrap-classes-to-images.js +98 -0
- package/assets/js/add-href-to-snapshot-link.js +2 -1
- package/assets/js/addAnchorsToTerms.js +0 -1
- package/assets/js/adjust-font-size.js +0 -9
- package/assets/js/create-alphabet-index.js +12 -3
- package/assets/js/create-term-filter.js +12 -0
- package/assets/js/custom-elements.js +13 -18
- package/assets/js/declare-markdown-it.js +1 -1
- package/assets/js/hide-show-utility-container.js +17 -0
- package/assets/js/highlightMenuItems.js +3 -3
- package/assets/js/image-full-size.js +76 -0
- package/assets/js/index.js +1 -5
- package/assets/js/insert-trefs.js +2 -2
- package/assets/js/modal.js +3 -3
- package/assets/js/search.js +15 -3
- package/assets/js/utils.js +2 -3
- package/index.js +7 -17
- package/package.json +2 -2
- package/src/README.md +3 -3
- package/src/add-remove-xref-source.js +0 -2
- package/src/asset-map.json +5 -0
- package/src/collect-external-references.js +187 -179
- package/src/collectExternalReferences/fetchTermsFromIndex.js +2 -1
- package/src/config/paths.js +2 -2
- package/src/create-external-specs-list.js +1 -1
- package/src/create-term-index.js +126 -22
- package/src/fix-markdown-files.js +152 -90
- package/src/health-check/external-specs-checker.js +173 -94
- package/src/health-check/output-gitignore-checker.js +327 -191
- package/src/health-check/specs-configuration-checker.js +288 -210
- package/src/health-check/term-references-checker.js +200 -123
- package/src/health-check/tref-term-checker.js +264 -179
- package/src/health-check.js +52 -36
- package/src/init.js +1 -4
- package/src/insert-term-index.js +5 -5
- package/src/install-from-boilerplate/add-scripts-keys.js +3 -1
- package/src/install-from-boilerplate/boilerplate/gitignore +2 -1
- package/src/install-from-boilerplate/config-system-files.js +9 -1
- package/src/install-from-boilerplate/copy-system-files.js +1 -1
- package/src/markdown-it-extensions.js +199 -106
- package/src/references.js +1 -2
- package/src/utils/doesUrlExist.js +7 -5
- package/src/utils/fetch.js +14 -14
- package/templates/template.html +1 -2
- package/assets/js/insert-xrefs.js +0 -370
- package/src/create-term-relations.js +0 -131
- package/src/prepare-tref.js +0 -174
package/src/create-term-index.js
CHANGED
|
@@ -1,41 +1,145 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Steps:
|
|
3
|
-
* 1. Reads the configuration from 'specs.json'.
|
|
4
|
-
* 2. Extracts the directories containing the specifications and terms.
|
|
5
|
-
* 3. Lists all file names in the specified terms directory.
|
|
3
|
+
* 1. Reads the configuration from 'specs.json', with fallbacks for missing or invalid files.
|
|
4
|
+
* 2. Extracts the directories containing the specifications and terms, with defaults for missing values.
|
|
5
|
+
* 3. Lists all file names in the specified terms directory if it exists.
|
|
6
6
|
* 4. Joins each file name with the terms directory path.
|
|
7
|
-
* 5. Creates an '
|
|
7
|
+
* 5. Creates an '.cache' directory in the project root if it does not exist.
|
|
8
8
|
* 6. Writes the list of file paths to 'term-index.json' in the project root.
|
|
9
9
|
*
|
|
10
|
+
* If any errors occur during the process, appropriate warnings are logged, and an empty term index
|
|
11
|
+
* will be created rather than throwing fatal errors.
|
|
12
|
+
*
|
|
10
13
|
* @requires fs-extra - File system operations with extra methods.
|
|
11
14
|
* @requires path - Utilities for working with file and directory paths.
|
|
12
15
|
* @file src/create-term-index.js
|
|
13
16
|
* @author Kor Dwarshuis
|
|
14
|
-
* @version 1.
|
|
17
|
+
* @version 1.1.0
|
|
15
18
|
* @since 2024-09-02
|
|
16
19
|
*/
|
|
17
20
|
|
|
18
21
|
const { shouldProcessFile } = require('./utils/file-filter');
|
|
19
22
|
|
|
20
23
|
function createTermIndex() {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
try {
|
|
25
|
+
const fs = require('fs-extra');
|
|
26
|
+
const path = require('path');
|
|
27
|
+
const configPath = 'specs.json';
|
|
28
|
+
|
|
29
|
+
// Check if specs.json exists
|
|
30
|
+
if (!fs.existsSync(configPath)) {
|
|
31
|
+
console.warn(`Config file '${configPath}' not found. Using default configuration.`);
|
|
32
|
+
var config = { specs: [] };
|
|
33
|
+
} else {
|
|
34
|
+
// Read config with try-catch to handle parsing errors
|
|
35
|
+
try {
|
|
36
|
+
var config = fs.readJsonSync(configPath);
|
|
37
|
+
} catch (readError) {
|
|
38
|
+
console.warn(`Error reading config file: ${readError.message}. Using default configuration.`);
|
|
39
|
+
var config = { specs: [] };
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Provide defaults for missing config
|
|
44
|
+
if (!config) {
|
|
45
|
+
console.warn('Config file is empty or invalid. Using defaults.');
|
|
46
|
+
config = { specs: [] };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!config.specs) {
|
|
50
|
+
console.warn('No specs array found in config. Creating empty specs array.');
|
|
51
|
+
config.specs = [];
|
|
52
|
+
} else if (!Array.isArray(config.specs)) {
|
|
53
|
+
console.warn('Config specs is not an array. Converting to array.');
|
|
54
|
+
config.specs = [config.specs]; // Convert to array if it's an object
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// If no valid specs, create an empty term index
|
|
58
|
+
if (config.specs.length === 0) {
|
|
59
|
+
console.warn('No specs found in configuration. Creating an empty term index.');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Extract spec directories with fallback to current directory
|
|
63
|
+
const specDirectories = config.specs.map((spec, index) => {
|
|
64
|
+
if (!spec.spec_directory) {
|
|
65
|
+
console.warn(`Warning: spec_directory missing in specs.json entry #${index + 1}. Using current directory.`);
|
|
66
|
+
return '.'; // Default to current directory
|
|
67
|
+
}
|
|
68
|
+
return spec.spec_directory;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Extract term directories with fallback to default value
|
|
72
|
+
const specTermDirectoryName = config.specs.map((spec, index) => {
|
|
73
|
+
if (!spec.spec_terms_directory) {
|
|
74
|
+
console.warn(`Warning: spec_terms_directory missing in specs.json entry #${index + 1}. Using default 'terms' directory.`);
|
|
75
|
+
return 'terms'; // Default directory name for terms
|
|
76
|
+
}
|
|
77
|
+
return spec.spec_terms_directory;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Safety check - if we have no valid entries, warn and exit cleanly
|
|
81
|
+
if (specDirectories.length === 0 || specTermDirectoryName.length === 0) {
|
|
82
|
+
console.log('No term directories found in configuration. Creating empty term index.');
|
|
83
|
+
|
|
84
|
+
// Create an empty term index
|
|
85
|
+
const outputPathJSON = path.join('.cache', 'term-index.json');
|
|
86
|
+
if (!fs.existsSync('.cache')) {
|
|
87
|
+
fs.mkdirSync('.cache', { recursive: true });
|
|
88
|
+
}
|
|
89
|
+
fs.writeJsonSync(outputPathJSON, [], { spaces: 2 });
|
|
90
|
+
console.log(`✅ Empty term index created at: ${outputPathJSON}`);
|
|
91
|
+
return; // Exit function early
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Verify that the base spec directory exists
|
|
95
|
+
const baseSpecDir = specDirectories[0];
|
|
96
|
+
if (!baseSpecDir || !fs.existsSync(baseSpecDir)) {
|
|
97
|
+
console.warn(`Spec directory '${baseSpecDir}' does not exist. Creating empty term index.`);
|
|
98
|
+
|
|
99
|
+
// Create an empty term index
|
|
100
|
+
const outputPathJSON = path.join('.cache', 'term-index.json');
|
|
101
|
+
if (!fs.existsSync('.cache')) {
|
|
102
|
+
fs.mkdirSync('.cache', { recursive: true });
|
|
103
|
+
}
|
|
104
|
+
fs.writeJsonSync(outputPathJSON, [], { spaces: 2 });
|
|
105
|
+
console.log(`✅ Empty term index created at: ${outputPathJSON}`);
|
|
106
|
+
return; // Exit function early
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Verify that the terms directory exists
|
|
110
|
+
const termsDir = path.join(baseSpecDir, specTermDirectoryName[0]);
|
|
111
|
+
|
|
112
|
+
let files = [];
|
|
113
|
+
if (!fs.existsSync(termsDir)) {
|
|
114
|
+
console.warn(`Terms directory '${termsDir}' does not exist. Creating an empty term index.`);
|
|
115
|
+
} else {
|
|
116
|
+
// Get list of files and filter them
|
|
117
|
+
files = fs.readdirSync(termsDir).filter(shouldProcessFile);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (files.length === 0) {
|
|
121
|
+
console.log('Warning: No term files found to process.');
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const filePaths = files.map(file => specTermDirectoryName[0] + '/' + file);
|
|
125
|
+
const outputPathJSON = path.join('.cache', 'term-index.json');
|
|
126
|
+
|
|
127
|
+
// Create .cache directory if it doesn't exist
|
|
128
|
+
if (!fs.existsSync('.cache')) {
|
|
129
|
+
fs.mkdirSync('.cache', { recursive: true });
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Write the term index file
|
|
133
|
+
try {
|
|
134
|
+
fs.writeJsonSync(outputPathJSON, filePaths, { spaces: 2 });
|
|
135
|
+
console.log(`✅ Term index created with ${files.length} terms. Output: ${outputPathJSON}`);
|
|
136
|
+
} catch (writeError) {
|
|
137
|
+
throw new Error(`Failed to write term index file: ${writeError.message}`);
|
|
138
|
+
}
|
|
139
|
+
} catch (error) {
|
|
140
|
+
console.error(`❌ Error creating term index: ${error.message}`);
|
|
141
|
+
throw error;
|
|
34
142
|
}
|
|
35
|
-
|
|
36
|
-
fs.writeJsonSync(outputPathJSON, filePaths, { spaces: 2 });
|
|
37
|
-
|
|
38
|
-
console.log(`✅ The new terms were added. All done.`);
|
|
39
143
|
}
|
|
40
144
|
|
|
41
145
|
module.exports = {
|
|
@@ -2,99 +2,161 @@ const fs = require('fs');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const { shouldProcessFile } = require('./utils/file-filter');
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
previousLineWasEmpty = false;
|
|
49
|
-
} else if (!previousLineWasEmpty) {
|
|
50
|
-
newLines.push(''); // Add exactly one blank line
|
|
51
|
-
previousLineWasEmpty = true;
|
|
52
|
-
} else {
|
|
53
|
-
modified = true; // Skip additional blank lines
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Prepend `~ ` to lines that do not start with `[[def:`, `[[tref:`, are not blank, do not already start with `~ `, and are not HTML comments
|
|
58
|
-
for (let i = 0; i < newLines.length; i++) {
|
|
59
|
-
if (
|
|
60
|
-
!newLines[i].startsWith('[[def:') &&
|
|
61
|
-
!newLines[i].startsWith('[[tref:') &&
|
|
62
|
-
newLines[i].trim() !== '' &&
|
|
63
|
-
!newLines[i].startsWith('~ ') &&
|
|
64
|
-
!newLines[i].trim().startsWith('<!--')
|
|
65
|
-
) {
|
|
66
|
-
newLines[i] = `~ ${newLines[i]}`;
|
|
67
|
-
modified = true;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
// Ensure there is exactly one blank line at the end of the file
|
|
72
|
-
if (newLines[newLines.length - 1] !== '') {
|
|
73
|
-
newLines.push('');
|
|
74
|
-
modified = true;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Join the lines back into a single string
|
|
78
|
-
if (modified) {
|
|
79
|
-
data = newLines.join('\n');
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Write the modified content back to the file synchronously if there were any changes
|
|
83
|
-
if (modified) {
|
|
84
|
-
fs.writeFileSync(itemPath, data, 'utf8');
|
|
85
|
-
}
|
|
86
|
-
} catch (err) {
|
|
87
|
-
console.error(`❌ Error while trying to fix the markdown in file ${item.name}: ${err}`);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
} catch (err) {
|
|
92
|
-
console.error(`❌ Error reading directory: ${err}`);
|
|
5
|
+
/**
|
|
6
|
+
* Handles specific functionality for `[[def:` lines
|
|
7
|
+
* @param {string[]} lines - Array of file lines
|
|
8
|
+
* @returns {object} - Object containing modified lines and modification status
|
|
9
|
+
*/
|
|
10
|
+
function processDefLines(lines) {
|
|
11
|
+
const result = [...lines];
|
|
12
|
+
let modified = false;
|
|
13
|
+
|
|
14
|
+
for (let i = 0; i < result.length; i++) {
|
|
15
|
+
if (result[i].startsWith('[[def:')) {
|
|
16
|
+
// Ensure a blank line immediately follows `[[def:` lines
|
|
17
|
+
if (i + 1 < result.length && result[i + 1].trim() !== '') {
|
|
18
|
+
result.splice(i + 1, 0, ''); // Insert blank line
|
|
19
|
+
modified = true;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return { lines: result, modified };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Ensures there is exactly one blank line between paragraphs
|
|
29
|
+
* @param {string[]} lines - Array of file lines
|
|
30
|
+
* @returns {object} - Object containing modified lines and modification status
|
|
31
|
+
*/
|
|
32
|
+
function normalizeParagraphSpacing(lines) {
|
|
33
|
+
let newLines = [];
|
|
34
|
+
let previousLineWasEmpty = false;
|
|
35
|
+
let modified = false;
|
|
36
|
+
|
|
37
|
+
for (const line of lines) {
|
|
38
|
+
const isCurrentLineEmpty = line.trim() === '';
|
|
39
|
+
|
|
40
|
+
if (!isCurrentLineEmpty) {
|
|
41
|
+
newLines.push(line); // Add non-empty lines
|
|
42
|
+
previousLineWasEmpty = false;
|
|
43
|
+
} else if (!previousLineWasEmpty) {
|
|
44
|
+
newLines.push(''); // Add exactly one blank line
|
|
45
|
+
previousLineWasEmpty = true;
|
|
46
|
+
} else {
|
|
47
|
+
modified = true; // Skip additional blank lines
|
|
93
48
|
}
|
|
94
49
|
}
|
|
95
50
|
|
|
96
|
-
|
|
97
|
-
|
|
51
|
+
return { lines: newLines, modified };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Prepends `~ ` to appropriate lines
|
|
56
|
+
* @param {string[]} lines - Array of file lines
|
|
57
|
+
* @returns {object} - Object containing modified lines and modification status
|
|
58
|
+
*/
|
|
59
|
+
function prependTildeToLines(lines) {
|
|
60
|
+
const result = [...lines];
|
|
61
|
+
let modified = false;
|
|
62
|
+
|
|
63
|
+
for (let i = 0; i < result.length; i++) {
|
|
64
|
+
if (
|
|
65
|
+
!result[i].startsWith('[[def:') &&
|
|
66
|
+
!result[i].startsWith('[[tref:') &&
|
|
67
|
+
result[i].trim() !== '' &&
|
|
68
|
+
!result[i].startsWith('~ ') &&
|
|
69
|
+
!result[i].trim().startsWith('<!--')
|
|
70
|
+
) {
|
|
71
|
+
result[i] = `~ ${result[i]}`;
|
|
72
|
+
modified = true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return { lines: result, modified };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Ensures there is exactly one blank line at the end of the file
|
|
81
|
+
* @param {string[]} lines - Array of file lines
|
|
82
|
+
* @returns {object} - Object containing modified lines and modification status
|
|
83
|
+
*/
|
|
84
|
+
function ensureTrailingNewline(lines) {
|
|
85
|
+
const result = [...lines];
|
|
86
|
+
let modified = false;
|
|
87
|
+
|
|
88
|
+
if (result[result.length - 1] !== '') {
|
|
89
|
+
result.push('');
|
|
90
|
+
modified = true;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return { lines: result, modified };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Processes a single markdown file and applies formatting rules
|
|
98
|
+
* @param {string} filePath - Path to the markdown file
|
|
99
|
+
* @returns {void}
|
|
100
|
+
*/
|
|
101
|
+
function processMarkdownFile(filePath, fileName) {
|
|
102
|
+
try {
|
|
103
|
+
// Read the file synchronously
|
|
104
|
+
let data = fs.readFileSync(filePath, 'utf8');
|
|
105
|
+
|
|
106
|
+
// Split the content into lines
|
|
107
|
+
let lines = data.split('\n');
|
|
108
|
+
let modified = false;
|
|
109
|
+
|
|
110
|
+
// Apply each processing function in sequence
|
|
111
|
+
const defResult = processDefLines(lines);
|
|
112
|
+
lines = defResult.lines;
|
|
113
|
+
modified = modified || defResult.modified;
|
|
114
|
+
|
|
115
|
+
const spacingResult = normalizeParagraphSpacing(lines);
|
|
116
|
+
lines = spacingResult.lines;
|
|
117
|
+
modified = modified || spacingResult.modified;
|
|
118
|
+
|
|
119
|
+
const tildeResult = prependTildeToLines(lines);
|
|
120
|
+
lines = tildeResult.lines;
|
|
121
|
+
modified = modified || tildeResult.modified;
|
|
122
|
+
|
|
123
|
+
const newlineResult = ensureTrailingNewline(lines);
|
|
124
|
+
lines = newlineResult.lines;
|
|
125
|
+
modified = modified || newlineResult.modified;
|
|
126
|
+
|
|
127
|
+
// Write the modified content back to the file synchronously if there were any changes
|
|
128
|
+
if (modified) {
|
|
129
|
+
const newData = lines.join('\n');
|
|
130
|
+
fs.writeFileSync(filePath, newData, 'utf8');
|
|
131
|
+
}
|
|
132
|
+
} catch (err) {
|
|
133
|
+
console.error(`❌ Error while trying to fix the markdown in file ${fileName}: ${err}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Processes markdown files in a directory recursively
|
|
139
|
+
* @param {string} directory - The directory to process
|
|
140
|
+
* @returns {void}
|
|
141
|
+
*/
|
|
142
|
+
function fixMarkdownFiles(directory) {
|
|
143
|
+
try {
|
|
144
|
+
// Read the contents of the directory synchronously
|
|
145
|
+
const items = fs.readdirSync(directory, { withFileTypes: true });
|
|
146
|
+
|
|
147
|
+
// Loop through each item in the directory
|
|
148
|
+
items.forEach(item => {
|
|
149
|
+
const itemPath = path.join(directory, item.name);
|
|
150
|
+
if (item.isDirectory()) {
|
|
151
|
+
// If the item is a directory, call fixMarkdownFiles recursively
|
|
152
|
+
fixMarkdownFiles(itemPath);
|
|
153
|
+
} else if (item.isFile() && shouldProcessFile(item.name)) {
|
|
154
|
+
processMarkdownFile(itemPath, item.name);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
} catch (err) {
|
|
158
|
+
console.error(`❌ Error reading directory: ${err}`);
|
|
159
|
+
}
|
|
98
160
|
}
|
|
99
161
|
|
|
100
162
|
module.exports = {
|