spec-up-t 1.4.1 → 1.5.0

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.
@@ -1,5 +1,5 @@
1
1
  :root{--card-bg:#fff;--card-bg-dt:#fcfcfc;--toc-bg:#fff;--toc-text:#212529;--header-navbar-bg:#f8f9fa;--header-navbar-text:#212529;--card-text:#212529;--card-border:rgba(0, 0, 0, 0.125);--card-shadow:rgba(0, 0, 0, 0.075);--card-hover-bg:#f8f9fa}[data-bs-theme=dark]{--card-bg:#212529;--card-bg-dt:#24282d;--toc-bg:#212529;--toc-text:#f8f9fa;--header-navbar-bg:#343a40;--header-navbar-text:#f8f9fa;--card-text:#f8f9fa;--card-border:rgba(255, 255, 255, 0.125);--card-shadow:rgba(0, 0, 0, 0.2);--card-hover-bg:#343a40}
2
- @charset "UTF-8";/*!
2
+ /*!
3
3
  * Bootstrap v5.3.3 (https://getbootstrap.com/)
4
4
  * Copyright 2011-2024 The Bootstrap Authors
5
5
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
@@ -7,7 +7,7 @@
7
7
  slide-panels{position:fixed;top:0;left:0;height:100%;width:100%;pointer-events:none;z-index:100;contain:paint}slide-panels:before{content:" ";display:block;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.3);transition:opacity .35s ease;opacity:0;cursor:pointer;pointer-events:none}slide-panels[open]:before{opacity:1;pointer-events:all}slide-panel{display:flex;flex-direction:column;box-sizing:border-box;position:absolute;top:0;left:0;bottom:0;background:#fff;box-shadow:0 0 5px 1px rgba(0,0,0,.15);transform:translate3d(-100%,0,0);transition:transform .35s ease;z-index:1;pointer-events:all}slide-panel[options~=right]{left:auto;right:0;transform:translate3d(100%,0,0)}slide-panel[open]{transform:translate3d(0,0,0)}detail-box{display:block}detail-box>header [detail-box-toggle]{width:2em;height:2em;text-align:center;cursor:pointer}detail-box>header [detail-box-toggle]:before{content:" ";display:inline-block;width:0;height:0;border-left:.55em solid transparent;border-right:.55em solid transparent;border-top:.8em solid;vertical-align:sub;cursor:pointer}detail-box[open] header [detail-box-toggle]:before{border-top:none;border-bottom:.8em solid}detail-box>section{height:0;opacity:0;min-width:100%;transition:height .3s ease,opacity .3s;overflow:hidden}detail-box[open]>section{opacity:1}tab-panels>nav{display:flex}tab-panels>nav>*{margin-left:-2px;padding:.5em 1em;background:#e0e0e0;border:1px solid #aaa;border-radius:0;cursor:pointer}tab-panels>nav>:focus{outline:0;background:#ccc}tab-panels>nav>:first-child{border-top-left-radius:5px;border-bottom-left-radius:5px}tab-panels>nav>:last-child{border-top-right-radius:5px;border-bottom-right-radius:5px}tab-panels>nav>[selected]{color:var(--themed-element-text);background:var(--themed-element-bk);border:var(--themed-element-border);opacity:.9999}tab-panels>section{display:none}tab-panels>section[selected]{display:block}
8
8
  code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}
9
9
  @keyframes chartjs-render-animation{from{opacity:.99}to{opacity:1}}.chartjs-render-monitor{animation:chartjs-render-animation 1ms}.chartjs-size-monitor,.chartjs-size-monitor-expand,.chartjs-size-monitor-shrink{position:absolute;direction:ltr;left:0;top:0;right:0;bottom:0;overflow:hidden;pointer-events:none;visibility:hidden;z-index:-1}.chartjs-size-monitor-expand>div{position:absolute;width:1000000px;height:1000000px;left:0;top:0}.chartjs-size-monitor-shrink>div{position:absolute;width:200%;height:200%;left:0;top:0}
10
- #logo img{width:100px}.bi{display:inline-block;width:1.2rem;height:1.2rem}#header,#header *{background-color:var(--header-navbar-bg);color:var(--header-navbar-text)}[issue-count]:after{content:"(" attr(issue-count) ")";margin:0 0 0 .3em;padding:.1em 0 0}[issue-count=""][animate]{display:none;opacity:0}[issue-count][animate]:not([issue-count=""]){animation:display-show 1s}#header a:not(#logo),#header a:not(#logo) *,#header button,#header button *{background:#a9dde0}
10
+ #logo img{width:100px}.bi{display:inline-block;width:1.2rem;height:1.2rem}#header,#header *{background-color:var(--header-navbar-bg);color:var(--header-navbar-text)}[data-issue-count]:after{content:"(" attr(data-issue-count) ")";margin:0 0 0 .3em;padding:.1em 0 0}[data-issue-count=""][data-animate]{display:none;opacity:0}[data-issue-count][data-animate]:not([data-issue-count=""]){animation:display-show 1s}#header a:not(#logo),#header a:not(#logo) *,#header button,#header button *{background:#a9dde0}
11
11
  .container{min-height:100vh}@media (min-width:768px){.sidebar{position:sticky;top:0;height:100vh;overflow-y:auto;z-index:100}}ul.toc{padding:1em 0 1.75em;font-size:.85em}ul.toc,ul.toc ul{margin:0;padding:0;list-style:none}ul.toc li a{display:block;padding:.4em .8em;text-decoration:none;color:var(--toc-text);transition:background .2s ease,padding-left .2s ease,border-left .2s ease;padding-left:.8em;border-left:3px solid transparent;border-bottom:1px solid rgba(0,0,0,.03)}ul.toc ul{margin-left:1.2em!important;margin-top:.3em}ul.toc a:hover{background:#f9f9f9;padding-left:1em;border-left:3px solid #007bff}ul.toc>li>ul>li>a{padding-left:1.5em}ul.toc>li>ul>li>ul>li>a{padding-left:2em}ul.toc a:focus{outline:2px solid #007bff;outline-offset:-2px;box-shadow:0 0 0 3px rgba(0,123,255,.25);position:relative;z-index:1}.spec-footer{font-size:.7em;text-align:center}ul.toc li a.active,ul.toc li a[aria-current=page]{border-left:3px solid #007bff;font-weight:500;background:#f0f0f0}ul.toc li:last-child a{border-bottom:none}#toc ul li{position:relative}#toc ul li.has-children{position:relative}.collapse-toggle{position:absolute;top:.35em;right:0;width:28px;height:28px;background:0 0;border:1px solid transparent;border-radius:3px;padding:0;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background-color .2s,border-color .2s;z-index:2}.collapse-toggle:hover{background-color:rgba(0,0,0,.05)}.collapse-toggle:focus{outline:2px solid #007bff;outline-offset:1px;border-color:#007bff;box-shadow:0 0 0 3px rgba(0,123,255,.25)}.collapse-toggle::after{content:"";border-style:solid;border-width:.15em .15em 0 0;display:inline-block;height:.5em;width:.5em;position:relative;transform:rotate(135deg);transition:transform .2s ease}.collapse-toggle.collapsed::after{transform:rotate(45deg)}#toc ul li.has-children>ul{max-height:1000px;overflow:hidden;transition:max-height .3s ease-in-out,opacity .3s ease-in-out;opacity:1}#toc ul li.has-children.collapsed>ul{max-height:0;overflow:hidden;opacity:.6}.screen-reader-text{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}.screen-reader-text:focus{width:auto;height:auto;clip:auto;display:block;padding:15px 23px 14px;background-color:#fff;color:#007bff;z-index:100000;font-size:1em;font-weight:700;text-decoration:none;line-height:normal;box-shadow:0 0 2px 2px rgba(0,0,0,.2)}
12
12
  h2,h3,h4,h5,h6{margin-top:1.5em!important}#terminology-section-utility-container{margin:1em auto;width:100%}@media (min-width:576px){#terminology-section-utility-container{position:sticky;top:3.5em;z-index:10}}.toc-anchor{font-size:.875em;color:#73c2df;text-decoration:none;transition:opacity .3s ease}.toc-anchor:hover{opacity:1}dl.terms-and-definitions-list{margin:0;padding:0;position:relative;z-index:1}dl.terms-and-definitions-list>dt{font-weight:700;margin:0;background-color:var(--card-bg-dt);border:1px solid var(--card-border);padding:.5rem 1.25rem;border-radius:.375rem .375rem 0 0;color:var(--card-text);position:relative;line-height:1.5;font-size:1.05em;display:flex;flex-wrap:wrap;align-items:center;gap:.5rem;min-height:2.5rem}dl.terms-and-definitions-list>dt>span{flex:1 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:all .2s ease-in-out}dl.terms-and-definitions-list>dt:focus>span,dl.terms-and-definitions-list>dt:hover>span,dl.terms-and-definitions-list>dt>span:focus,dl.terms-and-definitions-list>dt>span:hover{white-space:normal;overflow:visible;text-overflow:initial;word-wrap:break-word;line-height:1.4}dl.terms-and-definitions-list>dt:active>span,dl.terms-and-definitions-list>dt>span:active{white-space:normal;overflow:visible;text-overflow:initial;word-wrap:break-word;line-height:1.4}dl.terms-and-definitions-list>dt .btn{font-size:1.2em!important}dl.terms-and-definitions-list>dt:hover{background-color:var(--card-hover-bg);transition:background-color .2s ease-in-out}dl.terms-and-definitions-list>dd{margin:0;background-color:var(--card-bg);border:1px solid var(--card-border);border-top:none;padding:.5rem 2rem;color:var(--card-text);width:100%;position:relative}dl.terms-and-definitions-list dd p{margin:0;color:var(--card-text);padding-left:.5rem}dl.terms-and-definitions-list>dd::before{display:none}dl.terms-and-definitions-list dd table{margin:.5em 0;width:100%;border-collapse:collapse}dl.terms-and-definitions-list dd table td,dl.terms-and-definitions-list dd table th{padding:.5em;border:1px solid #ddd}dl.terms-and-definitions-list dd table th{background-color:#f5f5f5}dl>dd:has(table).meta-info-content-wrapper{display:block;font-size:.7em;position:relative;max-height:none;height:auto;overflow:visible;transition:all .3s ease-out}dl>dd:has(table).meta-info-content-wrapper td,dl>dd:has(table).meta-info-content-wrapper th{padding:.3em}dl>dd:has(table).collapsed.meta-info-content-wrapper{max-height:0;height:0;padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;overflow:hidden;transition:all .3s ease-out;line-height:0}dl>dd:has(table).meta-info-content-wrapper>div{display:block;padding:inherit}.meta-info-toggle-button{position:relative;cursor:pointer}dl.terms-and-definitions-list dt+dd{border-bottom:none}dl.terms-and-definitions-list dd+dd{border-top:none;border-bottom:none}dl.terms-and-definitions-list dd+dt{margin-top:1rem}dl.terms-and-definitions-list dd.last-dd{border-radius:0 0 .375rem .375rem;border-bottom:1px solid var(--card-border)}html.dense-info dl.terms-and-definitions-list>dt{padding:.1rem 1.25rem;line-height:inherit;font-size:inherit;min-height:auto}html.dense-info dl.terms-and-definitions-list dd+dt{margin-top:.3rem}html.dense-info dl.terms-and-definitions-list>dt::before{display:none}html.dense-info dl.terms-and-definitions-list>dt>span{flex:1 1 auto;min-width:0}.term-external{position:relative}dl.terms-and-definitions-list>dd.term-external,dl.terms-and-definitions-list>dt.term-external{background:#a9dde03b}.term-local{position:relative}dl.terms-and-definitions-list>dd.term-local,dl.terms-and-definitions-list>dt.term-local{background:#f0f8ff}dl.terms-and-definitions-list .term-original-term{font-style:italic}dl.terms-and-definitions-list .term-external-parenthetical-terms{font-weight:400}dl.terms-and-definitions-list .term-local-original-term{font-style:italic}dl.terms-and-definitions-list .term-local-parenthetical-terms{font-weight:400}.btn{font-variant:small-caps;text-transform:uppercase;position:relative;z-index:5}.transclusion-heading{font-size:1.3em;font-weight:700;margin:.2em 0 .2em}dl.terms-and-definitions-list>dd.term-external-embedded{position:relative;padding-left:2.5rem;padding-top:.3rem;padding-bottom:.3rem}dl.terms-and-definitions-list span.term-external::after{content:"";position:absolute;top:50%;transform:translateY(-50%);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' class='bi bi-box-arrow-right' viewBox='0 0 16 16' fill='currentColor'%3E%3Cpath fill-rule='evenodd' d='M10 12.5a.5.5 0 0 1-.5.5h-8a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h8a.5.5 0 0 1 .5.5v2a.5.5 0 0 0 1 0v-2A1.5 1.5 0 0 0 9.5 2h-8A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h8a1.5 1.5 0 0 0 1.5-1.5v-2a.5.5 0 0 0-1 0v2z'/%3E%3Cpath fill-rule='evenodd' d='M15.854 8.354a.5.5 0 0 0 0-.708l-3-3a.5.5 0 0 0-.708.708L14.293 7.5H5.5a.5.5 0 0 0 0 1h8.793l-2.147 2.146a.5.5 0 0 0 .708.708l3-3z'/%3E%3C/svg%3E");background-size:contain;background-repeat:no-repeat;background-position:center;width:.8rem;height:.8rem;left:.2rem}dl.terms-and-definitions-list span.term-external{padding-left:1.5rem;display:inline-block}.placeholder-tref{display:none}.no-xref-found-message{background:#f8c481;color:#03365f;margin:0 .5em;padding:0 .8em;border-radius:.25rem;font-size:.8rem;font-variant:small-caps;text-transform:uppercase}
13
13
  .btn{font-size:.7em!important;margin:0 0 0 .5em!important}
@@ -1,4 +1,4 @@
1
- @charset "UTF-8";/*!
1
+ /*!
2
2
  * Bootstrap v5.3.3 (https://getbootstrap.com/)
3
3
  * Copyright 2011-2024 The Bootstrap Authors
4
4
  * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
@@ -13,18 +13,18 @@
13
13
  color: var(--header-navbar-text);
14
14
  }
15
15
 
16
- [issue-count]:after {
17
- content: "(" attr(issue-count) ")";
16
+ [data-issue-count]:after {
17
+ content: "(" attr(data-issue-count) ")";
18
18
  margin: 0 0 0 0.3em;
19
19
  padding: 0.1em 0 0;
20
20
  }
21
21
 
22
- [issue-count=""][animate] {
22
+ [data-issue-count=""][data-animate] {
23
23
  display: none;
24
24
  opacity: 0;
25
25
  }
26
26
 
27
- [issue-count][animate]:not([issue-count=""]) {
27
+ [data-issue-count][data-animate]:not([data-issue-count=""]) {
28
28
  animation: display-show 1s;
29
29
  }
30
30
 
@@ -10,13 +10,13 @@
10
10
  .then(response => response.json())
11
11
  .then(issues => {
12
12
  let count = issues.length;
13
- document.querySelectorAll('[issue-count]').forEach(node => {
14
- node.setAttribute('issue-count', count)
13
+ document.querySelectorAll('[data-issue-count]').forEach(node => {
14
+ node.setAttribute('data-issue-count', count)
15
15
  });
16
16
  repo_issue_list.innerHTML = issues.map(issue => {
17
17
  return `<li class="repo-issue">
18
18
  <detail-box>
19
- <section>${md.render(issue.body || '')}</section>
19
+ <div>${md.render(issue.body || '')}</div>
20
20
  <header class="repo-issue-title">
21
21
  <span class="repo-issue-number">${issue.number}</span>
22
22
  <span class="repo-issue-link">
@@ -0,0 +1,102 @@
1
+ /**
2
+ * @file Example demonstrating message collector usage
3
+ *
4
+ * This example shows how to read and analyze the console messages
5
+ * captured during menu operations [1] and [4].
6
+ *
7
+ * Usage:
8
+ * node examples/read-console-messages.js
9
+ */
10
+
11
+ const fs = require('fs-extra');
12
+ const path = require('path');
13
+
14
+ async function analyzeConsoleMessages() {
15
+ const messagePath = path.join(process.cwd(), '.cache', 'console-messages.json');
16
+
17
+ // Check if the file exists
18
+ if (!await fs.pathExists(messagePath)) {
19
+ console.log('❌ No console messages found.');
20
+ console.log(' Run "npm run render" or "npm run collectExternalReferences" first.');
21
+ process.exit(1);
22
+ }
23
+
24
+ // Read the messages
25
+ const output = await fs.readJson(messagePath);
26
+
27
+ // Display metadata
28
+ console.log('\n📊 Console Message Analysis');
29
+ console.log('═'.repeat(60));
30
+ console.log(`Generated at: ${output.metadata.generatedAt}`);
31
+ console.log(`Total messages: ${output.metadata.totalMessages}`);
32
+ console.log(`Operations: ${output.metadata.operations.join(', ')}`);
33
+ console.log('\nMessages by type:');
34
+ Object.entries(output.metadata.messagesByType).forEach(([type, count]) => {
35
+ console.log(` ${type}: ${count}`);
36
+ });
37
+
38
+ // Analyze errors
39
+ const errors = output.messages.filter(m => m.type === 'error');
40
+ if (errors.length > 0) {
41
+ console.log('\n❌ Errors detected:');
42
+ errors.forEach(error => {
43
+ console.log(` [${error.timestamp}] ${error.message}`);
44
+ if (error.additionalData && error.additionalData.length > 0) {
45
+ console.log(` Details: ${error.additionalData.join(', ')}`);
46
+ }
47
+ });
48
+ } else {
49
+ console.log('\n✅ No errors detected');
50
+ }
51
+
52
+ // Analyze warnings
53
+ const warnings = output.messages.filter(m => m.type === 'warn');
54
+ if (warnings.length > 0) {
55
+ console.log('\n🟡 Warnings detected:');
56
+ warnings.forEach(warning => {
57
+ console.log(` [${warning.timestamp}] ${warning.message}`);
58
+ });
59
+ } else {
60
+ console.log('✅ No warnings detected');
61
+ }
62
+
63
+ // Show successful operations
64
+ const successes = output.messages.filter(m => m.type === 'success');
65
+ console.log(`\n✅ Successful operations: ${successes.length}`);
66
+ if (successes.length > 0 && successes.length <= 5) {
67
+ successes.forEach(success => {
68
+ console.log(` - ${success.message}`);
69
+ });
70
+ }
71
+
72
+ // Operation breakdown
73
+ const messagesByOp = output.messages.reduce((acc, msg) => {
74
+ if (msg.operation) {
75
+ acc[msg.operation] = (acc[msg.operation] || 0) + 1;
76
+ }
77
+ return acc;
78
+ }, {});
79
+
80
+ console.log('\n📋 Messages by operation:');
81
+ Object.entries(messagesByOp).forEach(([op, count]) => {
82
+ console.log(` ${op}: ${count} messages`);
83
+ });
84
+
85
+ // Health summary
86
+ console.log('\n🏥 Health Summary:');
87
+ if (errors.length > 0) {
88
+ console.log(' Status: ❌ ERROR - Issues detected during operation');
89
+ } else if (warnings.length > 0) {
90
+ console.log(' Status: 🟡 WARNING - Operation completed with warnings');
91
+ } else {
92
+ console.log(' Status: ✅ SUCCESS - Operation completed successfully');
93
+ }
94
+
95
+ console.log('═'.repeat(60) + '\n');
96
+ }
97
+
98
+ // Run the analysis
99
+ analyzeConsoleMessages().catch(error => {
100
+ console.error('❌ Failed to analyze messages:', error.message);
101
+ process.exit(1);
102
+ });
package/gulpfile.js CHANGED
@@ -32,6 +32,40 @@ async function fetchSpecRefs() {
32
32
  }).catch(e => console.log(e));
33
33
  }
34
34
 
35
+ /**
36
+ * Removes forbidden control characters from compiled JavaScript files
37
+ * to ensure W3C HTML validation compliance.
38
+ *
39
+ * Specifically removes:
40
+ * - U+0001 (SOH - Start of Heading)
41
+ * - U+001B (ESC - Escape, used in ANSI color codes)
42
+ *
43
+ * These characters appear in third-party libraries (mermaid.js, dagre-d3)
44
+ * and cause W3C validation errors when embedded in HTML.
45
+ *
46
+ * @param {string} filePath - Absolute path to the JavaScript file to clean
47
+ * @returns {Promise<void>}
48
+ */
49
+ async function removeForbiddenControlCharacters(filePath) {
50
+ try {
51
+ let content = await fs.readFile(filePath, 'utf8');
52
+
53
+ // Remove U+0001 (SOH - Start of Heading)
54
+ // This appears in dagre-d3 library as a null character separator
55
+ content = content.replace(/\x01/g, '');
56
+
57
+ // Remove U+001B (ESC - Escape)
58
+ // This appears in ANSI color codes like [35m, [31m, etc.
59
+ content = content.replace(/\x1b/g, '');
60
+
61
+ await fs.writeFile(filePath, content, 'utf8');
62
+ console.log(`✓ Cleaned forbidden characters from ${filePath}`);
63
+ } catch (error) {
64
+ console.error(`✗ Error cleaning ${filePath}:`, error.message);
65
+ throw error;
66
+ }
67
+ }
68
+
35
69
  async function compileAssets() {
36
70
  await fs.ensureDir(compileLocation);
37
71
  return new Promise(resolve => {
@@ -48,7 +82,14 @@ async function compileAssets() {
48
82
  .pipe(terser())
49
83
  .pipe(concat('body.js'))
50
84
  .pipe(gulp.dest(compileLocation))
51
- ).on('finish', function () {
85
+ ).on('finish', async function () {
86
+ // Post-process compiled JavaScript files to remove forbidden control characters
87
+ try {
88
+ await removeForbiddenControlCharacters(`${compileLocation}/head.js`);
89
+ await removeForbiddenControlCharacters(`${compileLocation}/body.js`);
90
+ } catch (error) {
91
+ console.error('Failed to clean compiled files:', error);
92
+ }
52
93
  resolve();
53
94
  })
54
95
  });
package/index.js CHANGED
@@ -1,7 +1,20 @@
1
1
  const { initialize } = require('./src/init');
2
2
  const Logger = require('./src/utils/logger');
3
+ const messageCollector = require('./src/utils/message-collector');
3
4
 
4
5
  module.exports = async function (options = {}) {
6
+ // Start collecting messages if requested
7
+ const shouldCollectMessages = options.collectMessages !== false; // Collect by default
8
+
9
+ if (shouldCollectMessages) {
10
+ // Only clear messages if not called from another operation (like collectExternalReferences)
11
+ // If skipClear is true, we're continuing from a previous operation
12
+ if (!options.skipClear) {
13
+ messageCollector.clearMessages();
14
+ }
15
+ messageCollector.startCollecting('render');
16
+ }
17
+
5
18
  try {
6
19
  const { initializeConfig } = require('./src/pipeline/configuration/prepare-spec-configuration.js');
7
20
  let toc = '';
@@ -137,8 +150,16 @@ module.exports = async function (options = {}) {
137
150
 
138
151
  // Run render and wait for it
139
152
  render(spec, assetTags, { externalReferences, references, definitions, specGroups, noticeTitles }, config, template, assets, Logger, md, externalSpecsList)
140
- .then(() => {
153
+ .then(async () => {
141
154
  Logger.info('Render completed for:', spec.destination);
155
+
156
+ // Save collected messages
157
+ if (shouldCollectMessages) {
158
+ messageCollector.stopCollecting();
159
+ const messagePath = await messageCollector.saveMessages();
160
+ Logger.success(`Console messages saved to: ${messagePath}`);
161
+ }
162
+
142
163
  if (options.nowatch) {
143
164
  Logger.info('Exiting with nowatch');
144
165
  process.exit(0);
@@ -146,6 +167,15 @@ module.exports = async function (options = {}) {
146
167
  })
147
168
  .catch((e) => {
148
169
  Logger.error('Render failed:', e.message);
170
+
171
+ // Save messages even on failure
172
+ if (shouldCollectMessages) {
173
+ messageCollector.stopCollecting();
174
+ messageCollector.saveMessages().catch(() => {
175
+ // Silent fail on save error
176
+ });
177
+ }
178
+
149
179
  process.exit(1);
150
180
  });
151
181
 
@@ -159,10 +189,28 @@ module.exports = async function (options = {}) {
159
189
  });
160
190
  } catch (error) {
161
191
  Logger.error(`Error during initialization or module execution: ${error.message}`);
192
+
193
+ // Save messages even on error
194
+ if (shouldCollectMessages) {
195
+ messageCollector.stopCollecting();
196
+ await messageCollector.saveMessages().catch(() => {
197
+ // Silent fail on save error
198
+ });
199
+ }
200
+
162
201
  throw error; // Re-throw to let the caller handle the error
163
202
  }
164
203
  } catch (error) {
165
204
  Logger.error(`Error during initialization: ${error.message}`);
205
+
206
+ // Save messages even on error
207
+ if (shouldCollectMessages) {
208
+ messageCollector.stopCollecting();
209
+ await messageCollector.saveMessages().catch(() => {
210
+ // Silent fail on save error
211
+ });
212
+ }
213
+
166
214
  throw error; // Re-throw to let the caller handle the error
167
215
  }
168
216
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-up-t",
3
- "version": "1.4.1",
3
+ "version": "1.5.0",
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": {
@@ -64,6 +64,7 @@
64
64
  "prismjs": "^1.24.0",
65
65
  "puppeteer": "^23.2.1",
66
66
  "readline-sync": "^1.4.10",
67
+ "spec-up-t-healthcheck": "^1.0.0",
67
68
  "yargs": "^17.7.2"
68
69
  },
69
70
  "overrides": {