spec-up-t 1.0.76 → 1.0.77

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.
@@ -126,7 +126,7 @@ function tokenInput(){let t=document.createElement("button");t.classList.add("bu
126
126
  function pdfDownload(){fetch("index.pdf",{method:"HEAD"}).then(e=>{if(e.ok){let e=document.createElement("a");e.classList.add("button-pdf-download"),e.classList.add("btn"),e.target="_blank",e.rel="noopener noreferrer",e.href="index.pdf",e.title="Download this page as a PDF",e.innerHTML="PDF",document.querySelector("#container-search-h7vc6omi2hr2880").appendChild(e)}else console.log("PDF file does not exist. No PDF download button will be added.")}).catch(e=>{console.error("Error checking PDF file:",e)})}document.addEventListener("DOMContentLoaded",(function(){pdfDownload()}));
127
127
  function helpButtons(){const t=document.createElement("a");t.textContent="?",t.classList.add("help-button","btn"),t.title="Click to see the explanation of the buttons at the documentation website, in a new tab.",t.target="_blank",t.rel="noopener noreferrer",t.href="https://blockchainbird.github.io/spec-up-t-website/docs/general/specification#explanation-buttons",function(t){document.querySelectorAll("#content dl dt").forEach(e=>{e.appendChild(t.cloneNode(!0))})}(t)}document.addEventListener("DOMContentLoaded",helpButtons);
128
128
  function createAlphabetIndex(){const e=document.getElementById("alphabet-index-h7vc6omi2hr2880"),t=document.querySelector(".terms-and-definitions-list").querySelectorAll("dt"),n={};t.forEach(e=>{const t=e.querySelector("span");if(t&&t.id){const e=t.id,o=e.charAt(e.indexOf("term:")+5).toUpperCase();n[o]||(n[o]=t.id)}});const o=document.createElement("div");o.className="alphabet-index";const r=document.createElement("p");r.className="number-of-terms",r.textContent=`– There are ${t.length} terms –`;const c=e.parentNode;c.insertBefore(r,e.nextSibling),c.insertBefore(o,r.nextSibling),Object.keys(n).sort().forEach(e=>{const t=document.createElement("a");t.href="#"+n[e],t.textContent=e,o.appendChild(t)})}document.addEventListener("DOMContentLoaded",(function(){createAlphabetIndex()}));
129
- function collapseDefinitions(){const t=document.querySelectorAll("#content dl dd"),e=document.querySelectorAll(".collapse-all-defs-button");document.querySelectorAll("dt").forEach(t=>{const e=document.createElement("button");e.classList.add("collapse-all-defs-button","btn"),e.innerHTML="▲",e.setAttribute("id","toggleButton"),t.appendChild(e)}),document.addEventListener("click",n=>{n.target.classList.contains("collapse-all-defs-button")&&(!function(){const n=t[0].classList.contains("hidden");t.forEach(t=>{t.classList.toggle("hidden",!n),t.classList.toggle("visible",n)}),e.forEach(t=>{t.innerHTML=n?"▲":"▼",t.title=n?"Collapse all definitions":"Expand all definitions"})}(),n.target.scrollIntoView({behavior:"smooth",block:"start",inline:"nearest"}),setTimeout(()=>{window.scrollBy({top:-100,behavior:"smooth"})},500))})}document.addEventListener("DOMContentLoaded",(function(){collapseDefinitions()}));
129
+ function collapseDefinitions(){const t=document.querySelectorAll("#content dl.terms-and-definitions-list dd"),e=document.querySelectorAll("#content dl.terms-and-definitions-list dt"),n=document.querySelectorAll(".collapse-all-defs-button");e.forEach(t=>{const e=document.createElement("button");e.classList.add("collapse-all-defs-button","btn"),e.innerHTML="▲",e.setAttribute("id","toggleButton"),t.appendChild(e)}),document.addEventListener("click",e=>{e.target.classList.contains("collapse-all-defs-button")&&(!function(){const e=t[0].classList.contains("hidden");t.forEach(t=>{t.classList.toggle("hidden",!e),t.classList.toggle("visible",e)}),n.forEach(t=>{t.innerHTML=e?"▲":"▼",t.title=e?"Collapse all definitions":"Expand all definitions"})}(),e.target.scrollIntoView({behavior:"smooth",block:"start",inline:"nearest"}),setTimeout(()=>{window.scrollBy({top:-100,behavior:"smooth"})},500))})}document.addEventListener("DOMContentLoaded",(function(){collapseDefinitions()}));
130
130
  /**
131
131
  * @file This file adds an href attribute to the snapshot link on the page via client side JS DOM manipulation.
132
132
  * @author Kor Dwarshuis
@@ -1,5 +1,6 @@
1
1
  function collapseDefinitions() {
2
- const dds = document.querySelectorAll('#content dl dd');
2
+ const dds = document.querySelectorAll('#content dl.terms-and-definitions-list > dd');
3
+ const dts = document.querySelectorAll('#content dl.terms-and-definitions-list > dt');
3
4
  const buttons = document.querySelectorAll('.collapse-all-defs-button');
4
5
 
5
6
  function toggleVisibility() {
@@ -15,7 +16,7 @@ function collapseDefinitions() {
15
16
  }
16
17
 
17
18
  // Add button as last child of every <dl>
18
- document.querySelectorAll('dt').forEach(dt => {
19
+ dts.forEach(dt => {
19
20
  const button = document.createElement('button');
20
21
  button.classList.add('collapse-all-defs-button', 'btn');
21
22
  button.innerHTML = '▲';
package/index.js CHANGED
@@ -55,7 +55,8 @@ module.exports = function (options = {}) {
55
55
 
56
56
  function createScriptElementWithXrefDataForEmbeddingInHtml() {
57
57
  // Test if xrefs-data.js exists, else make it an empty string
58
- const inputPath = 'output/xrefs-data.js';
58
+ const inputPath = path.join('output', 'xrefs-data.js');
59
+
59
60
  let xrefsData = "";
60
61
  if (fs.existsSync(inputPath)) {
61
62
  xrefsData = '<script>' + fs.readFileSync(inputPath, 'utf8') + '</script>';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-up-t",
3
- "version": "1.0.76",
3
+ "version": "1.0.77",
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": {
@@ -21,7 +21,7 @@ function createTermIndex() {
21
21
  const config = fs.readJsonSync('specs.json');
22
22
  const specDirectories = config.specs.map(spec => spec.spec_directory);
23
23
  const specTermDirectoryName = config.specs.map(spec => spec.spec_terms_directory);
24
- const outputPathJSON = './term-index.json';
24
+ const outputPathJSON = path.join('output', 'term-index.json');
25
25
  const files = fs.readdirSync(path.join(specDirectories[0], specTermDirectoryName[0]))
26
26
  .filter(file => !file.startsWith('_'));
27
27
 
@@ -92,22 +92,44 @@ async function fetchTermInfoFromGithub(GITHUB_API_TOKEN, xref) {
92
92
 
93
93
  // Function to fetch the content of a file from a specific commit in a GitHub repository.
94
94
  async function fetchFileContentFromCommit(GITHUB_API_TOKEN, owner, repo, commitHash, filePath) {
95
- try {
96
- const treeUrl = `https://api.github.com/repos/${owner}/${repo}/git/trees/${commitHash}?recursive=1`;
97
- const treeResponse = await fetch(treeUrl, { headers: setupFetchHeaders(GITHUB_API_TOKEN) });
98
-
99
- if (treeResponse.ok) {
100
- const treeData = await treeResponse.json();
101
- const file = treeData.tree.find(item => item.path === filePath);
102
- if (file) {
103
- const fileContentResponse = await fetch(file.url);
104
- const fileContentData = await fileContentResponse.json();
105
- return Buffer.from(fileContentData.content, 'base64').toString('utf-8');
95
+ const MAX_RETRIES = 3;
96
+ let retries = 0;
97
+
98
+ while (retries < MAX_RETRIES) {
99
+ try {
100
+ const treeUrl = `https://api.github.com/repos/${owner}/${repo}/git/trees/${commitHash}?recursive=1`;
101
+ const treeResponse = await fetch(treeUrl, { headers: setupFetchHeaders(GITHUB_API_TOKEN) });
102
+
103
+ if (treeResponse.ok) {
104
+ const treeData = await treeResponse.json();
105
+ const file = treeData.tree.find(item => item.path === filePath);
106
+ if (file) {
107
+ const fileContentResponse = await fetch(file.url);
108
+ const fileContentData = await fileContentResponse.json();
109
+ if (fileContentData.content) {
110
+ return Buffer.from(fileContentData.content, 'base64').toString('utf-8');
111
+ } else {
112
+ console.error('Error: fileContentData.content is undefined');
113
+ }
114
+ } else {
115
+ console.error(`Error: File ${filePath} not found in commit ${commitHash}`);
116
+ }
117
+ } else if (treeResponse.status === 403 && treeResponse.headers.get('X-RateLimit-Remaining') === '0') {
118
+ const resetTime = treeResponse.headers.get('X-RateLimit-Reset');
119
+ const waitTime = resetTime ? (resetTime - Math.floor(Date.now() / 1000)) * 1000 : 60000;
120
+ console.warn(`Rate limit exceeded. Retrying in ${waitTime / 1000} seconds...`);
121
+ await new Promise(resolve => setTimeout(resolve, waitTime));
122
+ retries++;
123
+ } else {
124
+ console.error(`Error: Failed to fetch tree from ${treeUrl}`);
125
+ break;
106
126
  }
127
+ } catch (error) {
128
+ console.error(`Error fetching file content: ${error.message}`);
129
+ break;
107
130
  }
108
- } catch (error) {
109
- console.error(`\n SPEC-UP-T: Error fetching file content: ${error.message}\n`);
110
131
  }
132
+
111
133
  return null;
112
134
  }
113
135
 
@@ -18,8 +18,8 @@
18
18
  function insertTermIndex() {
19
19
  const fs = require('fs-extra');
20
20
  const path = require('path');
21
- const config = fs.readJsonSync('./specs.json');
22
- const terms = fs.readJsonSync('./term-index.json');
21
+ const config = fs.readJsonSync(path.join('specs.json'));
22
+ const terms = fs.readJsonSync(path.join('output', 'term-index.json'));
23
23
  const outputPathJSON = path.join('output', 'specs-generated.json');
24
24
  let specGenerated = config;
25
25
  let markdownPaths = specGenerated.specs[0].markdown_paths;
package/index.spec-up.js DELETED
@@ -1,366 +0,0 @@
1
-
2
- module.exports = function (options = {}) {
3
-
4
- const {
5
- fetchExternalSpecs,
6
- validateReferences,
7
- findExternalSpecByKey
8
- } = require('./references.js');
9
- const gulp = require('gulp');
10
- const fs = require('fs-extra');
11
- const path = require('path');
12
- const findPkgDir = require('find-pkg-dir');
13
- const modulePath = findPkgDir(__dirname);
14
- let config = fs.readJsonSync('./specs.json');
15
- let assets = fs.readJsonSync(modulePath + '/src/asset-map.json');
16
- let externalReferences;
17
- let references = [];
18
- let definitions = [];
19
-
20
- const katexRules = ['math_block', 'math_inline']
21
- const replacerRegex = /\[\[\s*([^\s\[\]:]+):?\s*([^\]\n]+)?\]\]/img;
22
- const replacerArgsRegex = /\s*,+\s*/;
23
- const replacers = [
24
- {
25
- test: 'insert',
26
- transform: function (path) {
27
- if (!path) return '';
28
- return fs.readFileSync(path, 'utf8');
29
- }
30
- }
31
- ];
32
-
33
- function applyReplacers(doc) {
34
- return doc.replace(replacerRegex, function (match, type, args) {
35
- let replacer = replacers.find(r => type.trim().match(r.test));
36
- return replacer ? replacer.transform(...args.trim().split(replacerArgsRegex)) : match;
37
- });
38
- }
39
-
40
- function normalizePath(path) {
41
- return path.trim().replace(/\/$/g, '') + '/';
42
- }
43
-
44
- function renderRefGroup(type) {
45
- let group = specGroups[type];
46
- if (!group) return '';
47
- let html = Object.keys(group).sort().reduce((html, name) => {
48
- let ref = group[name];
49
- return html += `
50
- <dt id="ref:${name}">${name}</dt>
51
- <dd>
52
- <cite><a href="${ref.href}">${ref.title}</a></cite>.
53
- ${ref.authors.join('; ')}; ${ref.rawDate}. <span class="reference-status">Status: ${ref.status}</span>.
54
- </dd>
55
- `;
56
- }, '<dl class="reference-list">')
57
- return `\n${html}\n</dl>\n`;
58
- }
59
-
60
- function findKatexDist() {
61
- const relpath = "node_modules/katex/dist";
62
- const paths = [
63
- path.join(process.cwd(), relpath),
64
- path.join(__dirname, relpath),
65
- ];
66
- for (const abspath of paths) {
67
- if (fs.existsSync(abspath)) {
68
- return abspath
69
- }
70
- }
71
- throw Error("katex distribution could not be located");
72
- }
73
-
74
- try {
75
-
76
- var toc;
77
- var specGroups = {};
78
- const noticeTypes = {
79
- note: 1,
80
- issue: 1,
81
- example: 1,
82
- warning: 1,
83
- todo: 1
84
- };
85
- const spaceRegex = /\s+/g;
86
- const specNameRegex = /^spec$|^spec[-]*\w+$/i;
87
- const terminologyRegex = /^def$|^ref$|^xref/i;
88
- const specCorpus = fs.readJsonSync(modulePath + '/assets/compiled/refs.json');
89
- const containers = require('markdown-it-container');
90
- const md = require('markdown-it')({
91
- html: true,
92
- linkify: true,
93
- typographer: true
94
- })
95
- .use(require('./src/markdown-it-extensions.js'), [
96
- {
97
- filter: type => type.match(terminologyRegex),
98
- parse(token, type, primary) {
99
- if (!primary) return;
100
- if (type === 'def') {
101
- definitions.push(token.info.args);
102
- return token.info.args.reduce((acc, syn) => {
103
- return `<span id="term:${syn.replace(spaceRegex, '-').toLowerCase()}">${acc}</span>`;
104
- }, primary);
105
- }
106
- else if (type === 'xref') {
107
- const url = findExternalSpecByKey(config, token.info.args[0]);
108
- const term = token.info.args[1].replace(spaceRegex, '-').toLowerCase();
109
- return `<a class="term-reference" data-local-href="#term:${token.info.args[0]}:${term}"
110
- href="${url}#term:${term}">${token.info.args[1]}</a>`;
111
- }
112
- else {
113
- references.push(primary);
114
- return `<a class="term-reference" href="#term:${primary.replace(spaceRegex, '-').toLowerCase()}">${primary}</a>`;
115
- }
116
- }
117
- },
118
- {
119
- filter: type => type.match(specNameRegex),
120
- parse(token, type, name) {
121
- if (name) {
122
- let _name = name.replace(spaceRegex, '-').toUpperCase();
123
- let spec = specCorpus[_name] ||
124
- specCorpus[_name.toLowerCase()] ||
125
- specCorpus[name.toLowerCase()] ||
126
- specCorpus[name];
127
- if (spec) {
128
- spec._name = _name;
129
- let group = specGroups[type] = specGroups[type] || {};
130
- token.info.spec = group[_name] = spec;
131
- }
132
- }
133
- },
134
- render(token, type, name) {
135
- if (name) {
136
- let spec = token.info.spec;
137
- if (spec) return `[<a class="spec-reference" href="#ref:${spec._name}">${spec._name}</a>]`;
138
- }
139
- else return renderRefGroup(type);
140
- }
141
- }
142
- ])
143
- .use(require('markdown-it-attrs'))
144
- .use(require('markdown-it-chart').default)
145
- .use(require('markdown-it-deflist'))
146
- .use(require('markdown-it-references'))
147
- .use(require('markdown-it-icons').default, 'font-awesome')
148
- .use(require('markdown-it-ins'))
149
- .use(require('markdown-it-mark'))
150
- .use(require('markdown-it-textual-uml'))
151
- .use(require('markdown-it-sub'))
152
- .use(require('markdown-it-sup'))
153
- .use(require('markdown-it-task-lists'))
154
- .use(require('markdown-it-multimd-table'), {
155
- multiline: true,
156
- rowspan: true,
157
- headerless: true
158
- })
159
- .use(containers, 'notice', {
160
- validate: function (params) {
161
- let matches = params.match(/(\w+)\s?(.*)?/);
162
- return matches && noticeTypes[matches[1]];
163
- },
164
- render: function (tokens, idx) {
165
- let matches = tokens[idx].info.match(/(\w+)\s?(.*)?/);
166
- if (matches && tokens[idx].nesting === 1) {
167
- let id;
168
- let type = matches[1];
169
- if (matches[2]) {
170
- id = matches[2].trim().replace(/\s+/g, '-').toLowerCase();
171
- if (noticeTitles[id]) id += '-' + noticeTitles[id]++;
172
- else noticeTitles[id] = 1;
173
- }
174
- else id = type + '-' + noticeTypes[type]++;
175
- return `<div id="${id}" class="notice ${type}"><a class="notice-link" href="#${id}">${type.toUpperCase()}</a>`;
176
- }
177
- else return '</div>\n';
178
- }
179
- })
180
- .use(require('markdown-it-prism'))
181
- .use(require('markdown-it-toc-and-anchor').default, {
182
- tocClassName: 'toc',
183
- tocFirstLevel: 2,
184
- tocLastLevel: 4,
185
- tocCallback: (_md, _tokens, html) => toc = html,
186
- anchorLinkSymbol: '§',
187
- anchorClassName: 'toc-anchor'
188
- })
189
- .use(require('@traptitech/markdown-it-katex'))
190
-
191
- async function render(spec, assets) {
192
- try {
193
- noticeTitles = {};
194
- specGroups = {};
195
- console.log('Rendering: ' + spec.title);
196
- return new Promise(async (resolve, reject) => {
197
- Promise.all((spec.markdown_paths || ['spec.md']).map(_path => {
198
- return fs.readFile(spec.spec_directory + _path, 'utf8').catch(e => reject(e))
199
- })).then(async docs => {
200
- const features = (({ source, logo }) => ({ source, logo }))(spec);
201
- if (spec.external_specs && !externalReferences) {
202
- externalReferences = await fetchExternalSpecs(spec);
203
- }
204
- let doc = docs.join("\n");
205
- doc = applyReplacers(doc);
206
- md[spec.katex ? "enable" : "disable"](katexRules);
207
- const render = md.render(doc);
208
- fs.writeFile(path.join(spec.destination, 'index.html'), `
209
- <!DOCTYPE html>
210
- <html lang="en">
211
- <head>
212
- <meta charset="utf-8">
213
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
214
- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
215
-
216
- <title>${spec.title}</title>
217
-
218
- <link href="https://fonts.googleapis.com/css2?family=Heebo:wght@300;400&display=swap" rel="stylesheet">
219
-
220
- ${assets.head}
221
- </head>
222
- <body features="${Object.keys(features).join(' ')}">
223
-
224
- ${assets.svg}
225
-
226
- <main>
227
-
228
- <header id="header" class="panel-header">
229
- <span id="toc_toggle" panel-toggle="toc">
230
- <svg icon><use xlink:href="#svg-nested-list"></use></svg>
231
- </span>
232
- <a id="logo" href="${spec.logo_link ? spec.logo_link : '#_'}">
233
- <img src="${spec.logo}" />
234
- </a>
235
- <span issue-count animate panel-toggle="repo_issues">
236
- <svg icon><use xlink:href="#svg-github"></use></svg>
237
- </span>
238
- </header>
239
-
240
- <article id="content">
241
- ${render}
242
- </article>
243
-
244
- </main>
245
-
246
- <slide-panels id="slidepanels">
247
- <slide-panel id="repo_issues" options="right">
248
- <header class="panel-header">
249
- <span>
250
- <svg icon><use xlink:href="#svg-github"></use></svg>
251
- <span issue-count></span>
252
- </span>
253
- <span class="repo-issue-toggle" panel-toggle="repo_issues">✕</span>
254
- </header>
255
- <ul id="repo_issue_list"></ul>
256
- </slide-panel>
257
-
258
- <slide-panel id="toc">
259
- <header class="panel-header">
260
- <span>Table of Contents</span>
261
- <span panel-toggle="toc">✕</span>
262
- </header>
263
- <div id="toc_list">
264
- ${toc}
265
- </div>
266
- </slide-panel>
267
-
268
- </slide-panels>
269
- <div style="display: none;">
270
- ${externalReferences}
271
- </div>
272
- </body>
273
- <script>window.specConfig = ${JSON.stringify(spec)}</script>
274
- ${assets.body}
275
- </html>
276
- `, function (err, data) {
277
- if (err) {
278
- reject(err);
279
- }
280
- else {
281
- resolve();
282
- }
283
- });
284
- validateReferences(references, definitions, render);
285
- references = [];
286
- definitions = [];
287
- });
288
- });
289
- }
290
- catch (e) {
291
- console.error(e);
292
- }
293
- }
294
-
295
- config.specs.forEach(spec => {
296
- spec.spec_directory = normalizePath(spec.spec_directory);
297
- spec.destination = normalizePath(spec.output_path || spec.spec_directory);
298
-
299
- fs.ensureDirSync(spec.destination);
300
-
301
- let assetTags = {
302
- svg: fs.readFileSync(modulePath + '/assets/icons.svg', 'utf8') || ''
303
- };
304
-
305
- let customAssets = (spec.assets || []).reduce((assets, asset) => {
306
- let ext = asset.path.split('.').pop();
307
- if (ext === 'css') {
308
- assets.css += `<link href="${asset.path}" rel="stylesheet"/>`;
309
- }
310
- if (ext === 'js') {
311
- assets.js[asset.inject || 'body'] += `<script src="${asset.path}" ${asset.module ? 'type="module"' : ''} ></script>`;
312
- }
313
- return assets;
314
- }, {
315
- css: '',
316
- js: { head: '', body: '' }
317
- });
318
-
319
- if (options.dev) {
320
- assetTags.head = assets.head.css.map(_path => `<link href="${_path}" rel="stylesheet"/>`).join('') +
321
- customAssets.css +
322
- assets.head.js.map(_path => `<script src="${_path}"></script>`).join('') +
323
- customAssets.js.head;
324
- assetTags.body = assets.body.js.map(_path => `<script src="${_path}" data-manual></script>`).join('') +
325
- customAssets.js.body;
326
- }
327
- else {
328
- assetTags.head = `
329
- <style>${fs.readFileSync(modulePath + '/assets/compiled/head.css', 'utf8')}</style>
330
- ${customAssets.css}
331
- <script>${fs.readFileSync(modulePath + '/assets/compiled/head.js', 'utf8')}</script>
332
- ${customAssets.js.head}
333
- `;
334
- assetTags.body = `<script>${fs.readFileSync(modulePath + '/assets/compiled/body.js', 'utf8')}</script>
335
- ${customAssets.js.body}`;
336
- }
337
-
338
- if (spec.katex) {
339
- const katexDist = findKatexDist();
340
- assetTags.body += `<script>/* katex */${fs.readFileSync(path.join(katexDist, 'katex.min.js'),
341
- 'utf8')}</script>`;
342
- assetTags.body += `<style>/* katex */${fs.readFileSync(path.join(katexDist, 'katex.min.css'),
343
- 'utf8')}</style>`;
344
-
345
- fs.copySync(path.join(katexDist, 'fonts'), path.join(spec.destination, 'fonts'));
346
- }
347
-
348
- if (!options.nowatch) {
349
- gulp.watch(
350
- [spec.spec_directory + '**/*', '!' + path.join(spec.destination, 'index.html')],
351
- render.bind(null, spec, assetTags)
352
- )
353
- }
354
-
355
- render(spec, assetTags).then(() => {
356
- if (options.nowatch) process.exit(0)
357
- }).catch(() => process.exit(1));
358
-
359
- });
360
-
361
- }
362
- catch (e) {
363
- console.error(e);
364
- }
365
-
366
- }
@@ -1,7 +0,0 @@
1
- function prepareTref(tref) {
2
-
3
-
4
-
5
- }
6
-
7
- module.export = { prepareTref };