spec-up-t 1.1.54 → 1.1.55

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/branches.md CHANGED
@@ -25,11 +25,6 @@ De volgorde van de termen. Hoofdletter kleine letter probleem
25
25
  Tref creeren via index.html
26
26
 
27
27
 
28
- ## test/fixtref
29
-
30
- Bewaren, maar kan weg als ik uiteindelijk een andere oplossing heb gevonden.
31
-
32
-
33
28
  ## test/xtrefnew
34
29
 
35
30
  Lokaal Bewaren
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-up-t",
3
- "version": "1.1.54",
3
+ "version": "1.1.55",
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": {
@@ -31,6 +31,7 @@
31
31
  "dotenv": "^16.4.7",
32
32
  "find-pkg-dir": "^2.0.0",
33
33
  "fs-extra": "^11.3.0",
34
+ "glob": "^11.0.1",
34
35
  "gulp": "4.0.2",
35
36
  "gulp-clean-css": "4.3.0",
36
37
  "gulp-concat": "2.6.1",
@@ -0,0 +1,207 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const https = require('https');
4
+ const url = require('url');
5
+
6
+ /**
7
+ * Check if a given URL has correct GitHub Pages structure
8
+ * @param {string} urlStr - URL to check
9
+ * @returns {boolean} - Whether the URL has correct GitHub Pages structure
10
+ */
11
+ function isValidGitHubPagesUrl(urlStr) {
12
+ try {
13
+ const parsedUrl = new URL(urlStr);
14
+ // GitHub Pages URLs are either username.github.io or github.io/repo-name
15
+ return (
16
+ parsedUrl.hostname === 'github.io' ||
17
+ parsedUrl.hostname.endsWith('.github.io')
18
+ );
19
+ } catch (error) {
20
+ return false;
21
+ }
22
+ }
23
+
24
+ /**
25
+ * Check if a given URL has correct GitHub repo structure
26
+ * @param {string} urlStr - URL to check
27
+ * @returns {boolean} - Whether the URL has correct GitHub repo structure
28
+ */
29
+ function isValidGitHubRepoUrl(urlStr) {
30
+ try {
31
+ const parsedUrl = new URL(urlStr);
32
+ return (
33
+ parsedUrl.hostname === 'github.com' &&
34
+ parsedUrl.pathname.split('/').filter(Boolean).length >= 2
35
+ );
36
+ } catch (error) {
37
+ return false;
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Check if URL exists (returns a valid response)
43
+ * @param {string} urlStr - URL to check
44
+ * @returns {Promise<boolean>} - Whether the URL exists
45
+ */
46
+ function urlExists(urlStr) {
47
+ return new Promise((resolve) => {
48
+ try {
49
+ const parsedUrl = new URL(urlStr);
50
+ const options = {
51
+ method: 'HEAD',
52
+ host: parsedUrl.hostname,
53
+ path: parsedUrl.pathname + parsedUrl.search,
54
+ timeout: 5000
55
+ };
56
+
57
+ const req = https.request(options, (res) => {
58
+ resolve(res.statusCode >= 200 && res.statusCode < 400);
59
+ });
60
+
61
+ req.on('error', () => {
62
+ resolve(false);
63
+ });
64
+
65
+ req.on('timeout', () => {
66
+ req.destroy();
67
+ resolve(false);
68
+ });
69
+
70
+ req.end();
71
+ } catch (error) {
72
+ resolve(false);
73
+ }
74
+ });
75
+ }
76
+
77
+ /**
78
+ * Check external specs in a specs.json file
79
+ * @param {string} projectRoot - Root directory of the project
80
+ * @returns {Promise<Array>} - Array of check results
81
+ */
82
+ async function checkExternalSpecs(projectRoot) {
83
+ const results = [];
84
+
85
+ try {
86
+ const specsPath = path.join(projectRoot, 'specs.json');
87
+
88
+ // Check if specs.json exists
89
+ if (!fs.existsSync(specsPath)) {
90
+ return [{
91
+ name: 'Find specs.json file',
92
+ success: false,
93
+ details: 'specs.json file not found in project root'
94
+ }];
95
+ }
96
+
97
+ results.push({
98
+ name: 'Find specs.json file',
99
+ success: true,
100
+ details: 'specs.json file found'
101
+ });
102
+
103
+ // Read specs.json
104
+ const specsContent = fs.readFileSync(specsPath, 'utf8');
105
+ const specs = JSON.parse(specsContent);
106
+
107
+ // Check if external_specs key exists
108
+ if (!specs.specs || !Array.isArray(specs.specs) || !specs.specs.some(spec => spec.external_specs)) {
109
+ results.push({
110
+ name: 'Find external_specs in specs.json',
111
+ success: false,
112
+ details: 'external_specs key not found in specs.json'
113
+ });
114
+ return results;
115
+ }
116
+
117
+ results.push({
118
+ name: 'Find external_specs in specs.json',
119
+ success: true,
120
+ details: 'external_specs key found in specs.json'
121
+ });
122
+
123
+ // Find all external specs
124
+ const externalSpecs = [];
125
+ specs.specs.forEach(spec => {
126
+ if (spec.external_specs && Array.isArray(spec.external_specs)) {
127
+ externalSpecs.push(...spec.external_specs);
128
+ }
129
+ });
130
+
131
+ // Check each external spec
132
+ for (const spec of externalSpecs) {
133
+ // Check gh_page structure
134
+ if (spec.gh_page) {
135
+ const isValidGhPage = isValidGitHubPagesUrl(spec.gh_page);
136
+ results.push({
137
+ name: `Check "${spec.external_spec}" gh_page URL structure`,
138
+ success: isValidGhPage,
139
+ details: isValidGhPage
140
+ ? 'Valid GitHub Pages URL structure'
141
+ : `Invalid GitHub Pages URL structure: ${spec.gh_page}`
142
+ });
143
+
144
+ // Check if gh_page exists
145
+ if (isValidGhPage) {
146
+ const ghPageExists = await urlExists(spec.gh_page);
147
+ results.push({
148
+ name: `Check "${spec.external_spec}" gh_page URL exists`,
149
+ success: ghPageExists,
150
+ details: ghPageExists
151
+ ? 'GitHub Pages URL is accessible'
152
+ : `GitHub Pages URL is not accessible: ${spec.gh_page}`
153
+ });
154
+ }
155
+ } else {
156
+ results.push({
157
+ name: `Check "${spec.external_spec}" gh_page URL`,
158
+ success: false,
159
+ details: 'gh_page URL is missing'
160
+ });
161
+ }
162
+
163
+ // Check url structure
164
+ if (spec.url) {
165
+ const isValidRepoUrl = isValidGitHubRepoUrl(spec.url);
166
+ results.push({
167
+ name: `Check "${spec.external_spec}" repo URL structure`,
168
+ success: isValidRepoUrl,
169
+ details: isValidRepoUrl
170
+ ? 'Valid GitHub repository URL structure'
171
+ : `Invalid GitHub repository URL structure: ${spec.url}`
172
+ });
173
+
174
+ // Check if url exists
175
+ if (isValidRepoUrl) {
176
+ const repoUrlExists = await urlExists(spec.url);
177
+ results.push({
178
+ name: `Check "${spec.external_spec}" repo URL exists`,
179
+ success: repoUrlExists,
180
+ details: repoUrlExists
181
+ ? 'GitHub repository URL is accessible'
182
+ : `GitHub repository URL is not accessible: ${spec.url}`
183
+ });
184
+ }
185
+ } else {
186
+ results.push({
187
+ name: `Check "${spec.external_spec}" repo URL`,
188
+ success: false,
189
+ details: 'Repository URL is missing'
190
+ });
191
+ }
192
+ }
193
+
194
+ return results;
195
+ } catch (error) {
196
+ console.error('Error checking external specs:', error);
197
+ return [{
198
+ name: 'External specs check',
199
+ success: false,
200
+ details: `Error: ${error.message}`
201
+ }];
202
+ }
203
+ }
204
+
205
+ module.exports = {
206
+ checkExternalSpecs
207
+ };
@@ -0,0 +1,261 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { execSync } = require('child_process');
4
+
5
+ /**
6
+ * Checks if a path is gitignored
7
+ * @param {string} projectRoot - Root directory of the project
8
+ * @param {string} targetPath - Path to check (relative to project root)
9
+ * @returns {boolean} - Whether the path is gitignored
10
+ */
11
+ function isPathGitIgnored(projectRoot, targetPath) {
12
+ try {
13
+ // Use git check-ignore to determine if the path is ignored
14
+ // If command exits with status 0, path is ignored
15
+ // 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)
18
+ } catch (error) {
19
+ return false; // Path is not ignored (command exited with non-zero status)
20
+ }
21
+ }
22
+
23
+ /**
24
+ * Check if the output directory is being ignored by Git
25
+ * @param {string} projectRoot - Root directory of the project
26
+ * @returns {Promise<Array>} - Array of check results
27
+ */
28
+ async function checkOutputDirGitIgnore(projectRoot) {
29
+ const results = [];
30
+
31
+ try {
32
+ // Path to the project's specs.json
33
+ const specsPath = path.join(projectRoot, 'specs.json');
34
+
35
+ // Check if specs.json exists
36
+ if (!fs.existsSync(specsPath)) {
37
+ return [{
38
+ name: 'Find specs.json file',
39
+ success: false,
40
+ details: 'specs.json file not found in project root'
41
+ }];
42
+ }
43
+
44
+ results.push({
45
+ name: 'Find specs.json file',
46
+ success: true,
47
+ details: 'specs.json file found'
48
+ });
49
+
50
+ // Read specs.json to get the output path
51
+ const specsContent = fs.readFileSync(specsPath, 'utf8');
52
+ const specs = JSON.parse(specsContent);
53
+
54
+ // Get the output_path value
55
+ const outputPath = specs.specs?.[0]?.output_path;
56
+
57
+ if (!outputPath) {
58
+ results.push({
59
+ name: 'Find output_path field',
60
+ success: false,
61
+ details: 'output_path field not found in specs.json'
62
+ });
63
+ return results;
64
+ }
65
+
66
+ results.push({
67
+ name: 'Find output_path field',
68
+ success: true,
69
+ details: `output_path field found: "${outputPath}"`
70
+ });
71
+
72
+ // Normalize the path to handle different formats (./, /, etc.)
73
+ const normalizedPath = outputPath.replace(/^\.\/|^\//, '');
74
+
75
+ // Check if the path exists
76
+ const fullPath = path.join(projectRoot, normalizedPath);
77
+ const outputPathExists = fs.existsSync(fullPath);
78
+
79
+ if (!outputPathExists) {
80
+ results.push({
81
+ name: 'Output directory existence',
82
+ status: 'warning',
83
+ success: true, // Still considered a "success" for backward compatibility
84
+ details: `Output directory "${outputPath}" does not exist yet. This is OK if you haven't rendered the specs yet.`
85
+ });
86
+ } else {
87
+ results.push({
88
+ name: 'Output directory existence',
89
+ success: true,
90
+ details: `Output directory "${outputPath}" exists`
91
+ });
92
+ }
93
+
94
+ // Check if .gitignore exists
95
+ const gitignorePath = path.join(projectRoot, '.gitignore');
96
+ if (!fs.existsSync(gitignorePath)) {
97
+ results.push({
98
+ name: 'Find .gitignore file',
99
+ status: 'warning',
100
+ success: true, // Still considered a "success" for backward compatibility
101
+ details: '.gitignore file not found in project root. Consider adding one for better version control.'
102
+ });
103
+
104
+ // If no .gitignore, we can assume the output path is not ignored
105
+ results.push({
106
+ name: 'Check if output directory is gitignored',
107
+ success: true,
108
+ details: 'No .gitignore file found, so output directory is not being ignored'
109
+ });
110
+
111
+ return results;
112
+ }
113
+
114
+ results.push({
115
+ name: 'Find .gitignore file',
116
+ success: true,
117
+ details: '.gitignore file found'
118
+ });
119
+
120
+ // Read .gitignore content
121
+ const gitignoreContent = fs.readFileSync(gitignorePath, 'utf8');
122
+ const lines = gitignoreContent.split('\n');
123
+
124
+ // Extract the directory name from the path
125
+ const dirName = path.basename(normalizedPath);
126
+
127
+ // IMPROVED: First directly check .gitignore for patterns that would ignore the output directory
128
+ const dirIgnorePatterns = [];
129
+
130
+ for (const line of lines) {
131
+ const trimmedLine = line.trim();
132
+ // Skip empty lines and comments
133
+ if (trimmedLine === '' || trimmedLine.startsWith('#')) {
134
+ continue;
135
+ }
136
+
137
+ // Directly check for common patterns that would ignore the output directory
138
+ if (
139
+ trimmedLine === normalizedPath ||
140
+ trimmedLine === `/${normalizedPath}` ||
141
+ trimmedLine === `./${normalizedPath}` ||
142
+ trimmedLine === `${normalizedPath}/` ||
143
+ trimmedLine === `/${normalizedPath}/` ||
144
+ trimmedLine === `./${normalizedPath}/` ||
145
+ // Check for just the directory name (e.g., "docs")
146
+ trimmedLine === dirName ||
147
+ trimmedLine === `/${dirName}` ||
148
+ trimmedLine === `./${dirName}` ||
149
+ trimmedLine === `${dirName}/` ||
150
+ trimmedLine === `/${dirName}/` ||
151
+ trimmedLine === `./${dirName}/` ||
152
+ // Check for wildcards covering all directories
153
+ trimmedLine === '*/' ||
154
+ // Check for wildcards that might match our path using regex
155
+ (trimmedLine.includes('*') && new RegExp('^' + trimmedLine.replace(/\*/g, '.*').replace(/\//g, '\\/') + '$').test(normalizedPath))
156
+ ) {
157
+ dirIgnorePatterns.push(trimmedLine);
158
+ }
159
+ }
160
+
161
+ // If we found patterns that would ignore the output directory, report them regardless of git check-ignore
162
+ if (dirIgnorePatterns.length > 0) {
163
+ results.push({
164
+ name: 'Check if output directory is gitignored',
165
+ success: false,
166
+ details: `Found patterns in .gitignore that would ignore the output directory: ${dirIgnorePatterns.join(', ')}. Remove these entries to ensure generated content is tracked.`
167
+ });
168
+ } else {
169
+ // Fall back to using git check-ignore for verification
170
+ const isIgnored = isPathGitIgnored(projectRoot, normalizedPath);
171
+
172
+ results.push({
173
+ name: 'Check if output directory is gitignored',
174
+ success: !isIgnored,
175
+ details: isIgnored
176
+ ? `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.`
177
+ : `Output directory "${outputPath}" is not being ignored by Git, which is good.`
178
+ });
179
+ }
180
+
181
+ // Check for HTML file ignoring patterns
182
+ const htmlIgnorePatterns = [];
183
+
184
+ for (const line of lines) {
185
+ const trimmedLine = line.trim();
186
+ // Skip empty lines and comments
187
+ if (trimmedLine === '' || trimmedLine.startsWith('#')) {
188
+ continue;
189
+ }
190
+
191
+ if (
192
+ trimmedLine === 'index.html' ||
193
+ trimmedLine === '*.html' ||
194
+ trimmedLine === '/index.html' ||
195
+ trimmedLine === '**/index.html' ||
196
+ trimmedLine === '**/*.html'
197
+ ) {
198
+ htmlIgnorePatterns.push(trimmedLine);
199
+ }
200
+ }
201
+
202
+ // If we found HTML patterns in .gitignore, flag them regardless of git check-ignore result
203
+ if (htmlIgnorePatterns.length > 0) {
204
+ results.push({
205
+ name: 'Check if index.html files are gitignored',
206
+ success: false,
207
+ details: `Found patterns in .gitignore that would ignore HTML files: ${htmlIgnorePatterns.join(', ')}. This is problematic as they're crucial output files.`
208
+ });
209
+ } else {
210
+ // Only use git check-ignore as a fallback if we didn't find explicit HTML patterns
211
+ const indexHtmlPath = path.join(normalizedPath, 'index.html');
212
+ const isIndexHtmlIgnored = isPathGitIgnored(projectRoot, indexHtmlPath);
213
+
214
+ results.push({
215
+ name: 'Check if index.html files are gitignored',
216
+ success: !isIndexHtmlIgnored,
217
+ details: isIndexHtmlIgnored
218
+ ? `index.html files in the output directory would be ignored by Git. This is problematic as they're crucial output files.`
219
+ : `index.html files in the output directory are properly tracked by Git.`
220
+ });
221
+
222
+ // If index.html is ignored but we couldn't find an explicit pattern, look for more complex patterns
223
+ if (isIndexHtmlIgnored && htmlIgnorePatterns.length === 0) {
224
+ // Look for more complex patterns that might be ignoring index.html files
225
+ for (const line of lines) {
226
+ const trimmedLine = line.trim();
227
+ if (trimmedLine === '' || trimmedLine.startsWith('#')) {
228
+ continue;
229
+ }
230
+
231
+ // Check for wildcards and patterns that might match index.html
232
+ if (trimmedLine.includes('*') || trimmedLine.includes('.html')) {
233
+ htmlIgnorePatterns.push(trimmedLine);
234
+ }
235
+ }
236
+
237
+ if (htmlIgnorePatterns.length > 0) {
238
+ results.push({
239
+ name: 'Found complex .gitignore entries potentially affecting HTML files',
240
+ status: 'warning',
241
+ success: true, // Still considered a "success" for backward compatibility
242
+ details: `The following entries in .gitignore might cause HTML files to be ignored: ${htmlIgnorePatterns.join(', ')}. Consider reviewing these patterns.`
243
+ });
244
+ }
245
+ }
246
+ }
247
+
248
+ return results;
249
+ } catch (error) {
250
+ console.error('Error checking output directory gitignore status:', error);
251
+ return [{
252
+ name: 'Output directory gitignore check',
253
+ success: false,
254
+ details: `Error: ${error.message}`
255
+ }];
256
+ }
257
+ }
258
+
259
+ module.exports = {
260
+ checkOutputDirGitIgnore
261
+ };