spec-up-t 1.4.0 → 1.4.1-beta.2

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.
@@ -9,7 +9,7 @@ code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shad
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
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}
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
- 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-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}
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}
14
14
  .highlight-matches-search{font-size:1em;outline:3px solid #1d6dae39;outline-offset:5px;transition:outline .3s ease-in-out}.highlight-matches-search.active{outline:3px solid #1d6dae;transition:outline .3s ease-in-out}.highlight-matches-DIF-search{background-color:#1d6dae11}.highlight-matches-ToIP-search{background-color:#a9dde0b0}.highlight-matches-BTC-search{background-color:#f19019a1}.highlight-matches-KERI-search{background-color:#b5d070d5}.highlight-matches-SSI-search{background-color:#ff0}.highlight-matches-GLEIF-search{background-color:#52dac6a6}
15
15
  .highlight-cfib41dyhcd99sm{background-color:#1d6dae11}
@@ -30,5 +30,5 @@ article a[href^="https://"]:not(.btn)::after,article a[href^=http]:not(.btn)::af
30
30
  #content .figure:has(.scrollHintImage){padding:0;margin:0;width:auto;height:auto}
31
31
  .highlight2{padding-left:1em;padding-right:1em;border:1px dashed #71bbe6;background:#a9dde03b}
32
32
  #toc ul.toc{counter-reset:toc-section}#toc ul.toc>li{counter-reset:toc-subsection}#toc ul.toc>li>ul>li{counter-reset:toc-subsubsection}#toc ul.toc>li>a::before{counter-increment:toc-section;content:counter(toc-section) ". ";font-weight:700;margin-right:.5em}#toc ul.toc>li>ul>li>a::before{counter-increment:toc-subsection;content:counter(toc-section) "." counter(toc-subsection) " ";font-weight:700;margin-right:.5em}#toc ul.toc>li>ul>li>ul>li>a::before{counter-increment:toc-subsubsection;content:counter(toc-section) "." counter(toc-subsection) "." counter(toc-subsubsection) " ";font-weight:700;margin-right:.5em}main article{counter-reset:main-section}main article h2{counter-reset:main-subsection}main article h3{counter-reset:main-subsubsection}main article h2 .toc-anchor::after{counter-increment:main-section;content:" " counter(main-section) ".";font-weight:700}main article h3 .toc-anchor::after{counter-increment:main-subsection;content:" " counter(main-section) "." counter(main-subsection);font-weight:700}main article h4 .toc-anchor::after{counter-increment:main-subsubsection;content:" " counter(main-section) "." counter(main-subsection) "." counter(main-subsubsection);font-weight:700}main article h5::before,main article h6::before{font-weight:700;margin-right:.5em}@media print{#toc ul.toc>li>a::before,#toc ul.toc>li>ul>li>a::before,#toc ul.toc>li>ul>li>ul>li>a::before,main article h2 .toc-anchor::after,main article h3 .toc-anchor::after,main article h4 .toc-anchor::after{color:#000!important}}
33
- .term-external-original-term{font-style:italic}.term-external-parenthetical-terms{font-weight:400}
33
+
34
34
  :target{scroll-margin-top:calc(50vh)}body:not([hashscroll]) :target{animation:highlight-target 3.5s .25s ease}body:not([hashscroll]) dt:has(:target){animation:highlight-target-parent-dt 3.5s .25s ease}dl.terms-and-definitions-list>.highlight{background-color:#ff0!important;transition:background-color .3s ease-in-out}svg[icon]{width:1.25em;height:1.25em;vertical-align:text-top}@keyframes highlight-target{50%{background-color:#ff0}}@keyframes highlight-target-parent-dt{50%{background-color:#ff0;border:1px solid #00c8ff}}#svg{display:none}main *{overflow-wrap:anywhere;word-break:normal}.table-responsive{overflow-x:auto!important;-webkit-overflow-scrolling:touch;width:100%;max-width:100%}.table-responsive *{overflow-wrap:normal!important;word-break:normal!important;white-space:nowrap!important}dd td img{max-width:30px}.notice{margin:1em 0;padding:.5em .9em .55em .65em;border-left:.5em solid}.notice p{margin:.4em 0 0}.note{background:#e9fbe9;border-color:#52e052}.note .notice-link{display:block;color:#178217}.issue{background:#e9f0fb;border-color:#527fe0}.issue .notice-link:before{display:block;color:#1e4cae}.warning{background:#fbe9e9;border-color:#e05252}.warning .notice-link{display:block;color:#ae1e1e}.example{color:#cebe00;background:#1a1e23;border-left:.5em solid}.example .notice-link{display:block;color:inherit;font-size:1.1em;font-family:Heebo,sans-serif}.example pre[class*=language-]{padding:0;border-radius:0}.todo{background:#fbe4ff;border-color:#9700e2}.todo .notice-link{display:block;color:#6d00a2}.alert-primary{background-color:#f9fcff;border-color:#b2ebf2;color:#00838f}.alert-secondary{background-color:#f5f5f5;border-color:#e0e0e0;color:#616161}.alert-success{background-color:#e8f5e9;border-color:#c8e6c9;color:#388e3c}.alert-danger{background-color:#ffebee;border-color:#ef9a9a;color:#d32f2f}.alert-warning{background-color:#fffde7;border-color:#fff9c4;color:#f9a825}.alert-info{background-color:#e1f5fe;border-color:#b3e5fc;color:#0288d1}.alert-light{background-color:#f9f9f9;border-color:#eee;color:#424242}.alert-dark{background-color:#e0e0e0;border-color:#bdbdbd;color:#212121}.alert a{color:inherit;font-weight:700}.alert-primary a{color:#006064}.alert-success a{color:#2e7d32}.alert-danger a{color:#b71c1c}.alert-warning a{color:#f57f17}.alert-info a{color:#01579b}.alert-dark a{color:#000}[data-bs-theme=dark] .alert-primary{background-color:#004d40;border-color:#00695c;color:#b2dfdb}[data-bs-theme=dark] .alert-secondary{background-color:#424242;border-color:#616161;color:#e0e0e0}[data-bs-theme=dark] .alert-success{background-color:#1b5e20;border-color:#2e7d32;color:#a5d6a7}[data-bs-theme=dark] .alert-danger{background-color:#b71c1c;border-color:#c62828;color:#ef9a9a}[data-bs-theme=dark] .alert-warning{background-color:#f57f17;border-color:#ffb300;color:#ffe082}[data-bs-theme=dark] .alert-info{background-color:#01579b;border-color:#0277bd;color:#81d4fa}[data-bs-theme=dark] .alert-light{background-color:#303030;border-color:#424242;color:#e0e0e0}[data-bs-theme=dark] .alert-dark{background-color:#212121;border-color:#424242;color:#bdbdbd}[data-bs-theme=dark] .alert a{color:inherit;font-weight:700}[data-bs-theme=dark] .alert-primary a{color:#80cbc4}[data-bs-theme=dark] .alert-success a{color:#81c784}[data-bs-theme=dark] .alert-danger a{color:#ef5350}[data-bs-theme=dark] .alert-warning a{color:#ffca28}[data-bs-theme=dark] .alert-info a{color:#4fc3f7}[data-bs-theme=dark] .alert-dark a{color:#9e9e9e}#offcanvasSettings .btn-menu-item{border-radius:unset;width:100%;text-align:left;border:1px solid #dee2e6;background-color:var(--card-bg);color:var(--card-text);padding:10px 15px;margin-bottom:5px;transition:background-color .2s ease}#offcanvasSettings .btn-menu-item:hover{background-color:#e9ecef}
@@ -1,7 +1 @@
1
- .term-external-original-term {
2
- font-style: italic;
3
- }
4
-
5
- .term-external-parenthetical-terms {
6
- font-weight: normal;
7
- }
1
+ /* Currently empty */
@@ -282,6 +282,15 @@ dl.terms-and-definitions-list>dd.term-local {
282
282
  background: #f0f8ff;
283
283
  }
284
284
 
285
+ /* Generic class for all original terms (both local and external) */
286
+ dl.terms-and-definitions-list .term-original-term {
287
+ font-style: italic;
288
+ }
289
+
290
+ dl.terms-and-definitions-list .term-external-parenthetical-terms {
291
+ font-weight: normal;
292
+ }
293
+
285
294
  /* Local term original term and parenthetical styling */
286
295
  dl.terms-and-definitions-list .term-local-original-term {
287
296
  font-style: italic;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spec-up-t",
3
- "version": "1.4.0",
3
+ "version": "1.4.1-beta.2",
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": {
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Template Tag Parser HTML Output Tests
3
+ *
4
+ * These tests verify that the HTML output contains all required CSS classes
5
+ * and structural elements that are essential for proper rendering and styling.
6
+ *
7
+ * These tests were added after discovering that shallow `.toContain()` assertions
8
+ * were insufficient to catch missing CSS classes that broke functionality.
9
+ */
10
+
11
+ const {
12
+ parseDef,
13
+ parseRef,
14
+ parseXref,
15
+ parseTref
16
+ } = require('./template-tag-parser');
17
+
18
+ describe('Template Tag Parser - HTML Output Validation', () => {
19
+ let mockConfig, mockGlobal;
20
+
21
+ beforeEach(() => {
22
+ mockConfig = {
23
+ specs: [{
24
+ external_specs: [{
25
+ external_spec: 'test-spec',
26
+ gh_page: 'https://example.com/spec'
27
+ }]
28
+ }]
29
+ };
30
+
31
+ mockGlobal = {
32
+ definitions: [],
33
+ references: [],
34
+ specGroups: {},
35
+ noticeTitles: {},
36
+ currentFile: 'test.md'
37
+ };
38
+
39
+ global.definitions = mockGlobal.definitions;
40
+ global.references = mockGlobal.references;
41
+ global.specGroups = mockGlobal.specGroups;
42
+ global.noticeTitles = mockGlobal.noticeTitles;
43
+ });
44
+
45
+ describe('parseDef - HTML structure validation', () => {
46
+ // Test: Does def output contain the required CSS class for styling?
47
+ test('should include term-original-term class when def has aliases', () => {
48
+ const mockToken = {
49
+ info: { args: ['test-term', 'alias1'] }
50
+ };
51
+
52
+ const result = parseDef(mockGlobal, mockToken, 'Test Term', 'test.md');
53
+
54
+ // Critical: This class is required for CSS styling
55
+ expect(result).toContain('term-original-term');
56
+ expect(result).toContain('term-local-original-term');
57
+ });
58
+
59
+ test('should include term-original-term class when def has no aliases', () => {
60
+ const mockToken = {
61
+ info: { args: ['test-term'] }
62
+ };
63
+
64
+ const result = parseDef(mockGlobal, mockToken, 'Test Term', 'test.md');
65
+
66
+ // Even without aliases, the original term should have proper class
67
+ expect(result).toContain('term-original-term');
68
+ expect(result).toContain('term-local-original-term');
69
+ });
70
+
71
+ test('should include term-local-parenthetical-terms class for multiple aliases', () => {
72
+ const mockToken = {
73
+ info: { args: ['test-term', 'alias1', 'alias2', 'alias3'] }
74
+ };
75
+
76
+ const result = parseDef(mockGlobal, mockToken, 'Test Term', 'test.md');
77
+
78
+ expect(result).toContain('term-local-parenthetical-terms');
79
+ });
80
+
81
+ test('should display primary alias first, then other aliases, then original term', () => {
82
+ const mockToken = {
83
+ info: { args: ['original-term', 'primary-alias', 'second-alias'] }
84
+ };
85
+
86
+ const result = parseDef(mockGlobal, mockToken, 'Test Term', 'test.md');
87
+
88
+ // Primary alias should appear first (not in parentheses) in the innermost span
89
+ expect(result).toMatch(/>primary-alias <span class='term-local-parenthetical-terms'>/);
90
+
91
+ // Second alias should appear in parentheses
92
+ expect(result).toContain('second-alias');
93
+
94
+ // Original term should appear last in parentheses with proper class
95
+ expect(result).toContain('<span class=\'term-local-original-term term-original-term\' title=\'original term\'>original-term</span>');
96
+ });
97
+
98
+ test('should have nested span structure with all IDs', () => {
99
+ const mockToken = {
100
+ info: { args: ['term1', 'alias1', 'alias2'] }
101
+ };
102
+
103
+ const result = parseDef(mockGlobal, mockToken, 'Test Term', 'test.md');
104
+
105
+ // Check all IDs are present
106
+ expect(result).toContain('id="term:term1"');
107
+ expect(result).toContain('id="term:alias1"');
108
+ expect(result).toContain('id="term:alias2"');
109
+
110
+ // Check nested structure (outer span has last alias ID)
111
+ expect(result).toMatch(/^<span id="term:alias2">/);
112
+ });
113
+ });
114
+
115
+ describe('parseTref - HTML structure validation', () => {
116
+ // Test: Does tref output contain the required CSS classes for styling?
117
+ test('should include term-external-original-term and term-original-term classes when tref has aliases', () => {
118
+ const mockToken = {
119
+ info: { args: ['external-spec', 'test-term', 'alias1'] }
120
+ };
121
+
122
+ const result = parseTref(mockToken);
123
+
124
+ // Critical: These classes are required for CSS styling
125
+ expect(result).toContain('term-original-term');
126
+ expect(result).toContain('term-external-original-term');
127
+ });
128
+
129
+ test('should include term-original-term class when tref has no aliases', () => {
130
+ const mockToken = {
131
+ info: { args: ['external-spec', 'test-term'] }
132
+ };
133
+
134
+ const result = parseTref(mockToken);
135
+
136
+ // Even without aliases, the original term should have proper class
137
+ expect(result).toContain('term-original-term');
138
+ expect(result).toContain('term-external-original-term');
139
+ });
140
+
141
+ test('should include term-external-parenthetical-terms class for multiple aliases', () => {
142
+ const mockToken = {
143
+ info: { args: ['external-spec', 'test-term', 'alias1', 'alias2', 'alias3'] }
144
+ };
145
+
146
+ const result = parseTref(mockToken);
147
+
148
+ expect(result).toContain('term-external-parenthetical-terms');
149
+ });
150
+
151
+ test('should include term-external class on outer span', () => {
152
+ const mockToken = {
153
+ info: { args: ['external-spec', 'test-term', 'alias1'] }
154
+ };
155
+
156
+ const result = parseTref(mockToken);
157
+
158
+ expect(result).toContain('class="term-external"');
159
+ });
160
+
161
+ test('should display primary alias first, then other aliases, then original term', () => {
162
+ const mockToken = {
163
+ info: { args: ['spec', 'original-term', 'primary-alias', 'second-alias'] }
164
+ };
165
+
166
+ const result = parseTref(mockToken);
167
+
168
+ // Primary alias should appear first (not in parentheses)
169
+ expect(result).toContain('>primary-alias <span');
170
+
171
+ // Second alias should appear in parentheses
172
+ expect(result).toContain('second-alias');
173
+
174
+ // Original term should appear last in parentheses with proper class
175
+ expect(result).toContain('<span class=\'term-external-original-term term-original-term\' title=\'original term\'>original-term</span>');
176
+ });
177
+
178
+ test('should have data-original-term attribute', () => {
179
+ const mockToken = {
180
+ info: { args: ['spec', 'test-term', 'alias1'] }
181
+ };
182
+
183
+ const result = parseTref(mockToken);
184
+
185
+ expect(result).toContain('data-original-term="test-term"');
186
+ });
187
+
188
+ test('should have proper title attribute on inner span when alias exists', () => {
189
+ const mockToken = {
190
+ info: { args: ['spec', 'test-term', 'alias1'] }
191
+ };
192
+
193
+ const result = parseTref(mockToken);
194
+
195
+ expect(result).toContain('title="Externally defined as test-term"');
196
+ });
197
+ });
198
+
199
+ describe('parseXref - HTML structure validation', () => {
200
+ test('should include x-term-reference and term-reference classes', () => {
201
+ const mockToken = {
202
+ info: { args: ['test-spec', 'test-term'] }
203
+ };
204
+
205
+ const result = parseXref(mockConfig, mockToken);
206
+
207
+ expect(result).toContain('class="x-term-reference term-reference"');
208
+ });
209
+
210
+ test('should display primary alias instead of term when alias provided', () => {
211
+ const mockToken = {
212
+ info: { args: ['test-spec', 'test-term', 'my-alias'] }
213
+ };
214
+
215
+ const result = parseXref(mockConfig, mockToken);
216
+
217
+ // Should show alias, not the term
218
+ expect(result).toContain('>my-alias</a>');
219
+ expect(result).not.toContain('>test-term</a>');
220
+ });
221
+
222
+ test('should display term when no alias provided', () => {
223
+ const mockToken = {
224
+ info: { args: ['test-spec', 'test-term'] }
225
+ };
226
+
227
+ const result = parseXref(mockConfig, mockToken);
228
+
229
+ expect(result).toContain('>test-term</a>');
230
+ });
231
+
232
+ test('should have both data-local-href and href attributes', () => {
233
+ const mockToken = {
234
+ info: { args: ['test-spec', 'test-term'] }
235
+ };
236
+
237
+ const result = parseXref(mockConfig, mockToken);
238
+
239
+ expect(result).toContain('data-local-href="#term:test-spec:test-term"');
240
+ expect(result).toContain('href="https://example.com/spec#term:test-term"');
241
+ });
242
+ });
243
+
244
+ describe('parseRef - HTML structure validation', () => {
245
+ test('should include term-reference class', () => {
246
+ const result = parseRef(mockGlobal, 'test-term');
247
+
248
+ expect(result).toContain('class="term-reference"');
249
+ });
250
+
251
+ test('should create proper href with term: prefix', () => {
252
+ const result = parseRef(mockGlobal, 'test-term');
253
+
254
+ expect(result).toContain('href="#term:test-term"');
255
+ });
256
+
257
+ test('should display the term as link text', () => {
258
+ const result = parseRef(mockGlobal, 'my-test-term');
259
+
260
+ expect(result).toContain('>my-test-term</a>');
261
+ });
262
+ });
263
+
264
+ describe('Regression tests - ensure critical classes are never removed', () => {
265
+ // These tests protect against the specific bug that was fixed
266
+ test('def: term-original-term class must always be present', () => {
267
+ const withAlias = { info: { args: ['term', 'alias'] } };
268
+ const withoutAlias = { info: { args: ['term'] } };
269
+
270
+ expect(parseDef(mockGlobal, withAlias, 'Test', 'test.md')).toContain('term-original-term');
271
+ expect(parseDef(mockGlobal, withoutAlias, 'Test', 'test.md')).toContain('term-original-term');
272
+ });
273
+
274
+ test('def: term-local-original-term class must always be present', () => {
275
+ const withAlias = { info: { args: ['term', 'alias'] } };
276
+ const withoutAlias = { info: { args: ['term'] } };
277
+
278
+ expect(parseDef(mockGlobal, withAlias, 'Test', 'test.md')).toContain('term-local-original-term');
279
+ expect(parseDef(mockGlobal, withoutAlias, 'Test', 'test.md')).toContain('term-local-original-term');
280
+ });
281
+
282
+ test('tref: term-original-term class must always be present', () => {
283
+ const withAlias = { info: { args: ['spec', 'term', 'alias'] } };
284
+ const withoutAlias = { info: { args: ['spec', 'term'] } };
285
+
286
+ expect(parseTref(withAlias)).toContain('term-original-term');
287
+ expect(parseTref(withoutAlias)).toContain('term-original-term');
288
+ });
289
+
290
+ test('tref: term-external-original-term class must always be present', () => {
291
+ const withAlias = { info: { args: ['spec', 'term', 'alias'] } };
292
+ const withoutAlias = { info: { args: ['spec', 'term'] } };
293
+
294
+ expect(parseTref(withAlias)).toContain('term-external-original-term');
295
+ expect(parseTref(withoutAlias)).toContain('term-external-original-term');
296
+ });
297
+
298
+ test('tref: term-external class must always be present on outer span', () => {
299
+ const withAlias = { info: { args: ['spec', 'term', 'alias'] } };
300
+ const withoutAlias = { info: { args: ['spec', 'term'] } };
301
+
302
+ expect(parseTref(withAlias)).toContain('class="term-external"');
303
+ expect(parseTref(withoutAlias)).toContain('class="term-external"');
304
+ });
305
+ });
306
+ });
@@ -89,15 +89,18 @@ function parseDef(globalState, token, primary, currentFile) {
89
89
  parentheticalContent.push(...aliases.slice(1));
90
90
  }
91
91
 
92
- // Add original term if it's different from the primary display term
93
- if (termName !== primaryDisplayTerm) {
94
- parentheticalContent.push(`<span class='term-local-original-term' title='original term'>${termName}</span>`);
95
- }
92
+ // Always add the original term if there are aliases, with special styling
93
+ // This ensures consistent behavior regardless of whether alias1 equals the term
94
+ // The original term should always be visible in the parenthetical list
95
+ parentheticalContent.push(`<span class='term-local-original-term term-original-term' title='original term'>${termName}</span>`);
96
96
 
97
97
  // Append parenthetical terms if any exist
98
98
  if (parentheticalContent.length > 0) {
99
99
  displayText += ` <span class='term-local-parenthetical-terms'>(${parentheticalContent.join(', ')})</span>`;
100
100
  }
101
+ } else {
102
+ // No aliases: wrap the term name itself as the original term
103
+ displayText = `<span class='term-local-original-term term-original-term' title='original term'>${termName}</span>`;
101
104
  }
102
105
 
103
106
  // Generate HTML spans for each term/alias combination
@@ -183,15 +186,18 @@ function parseTref(token) {
183
186
  parentheticalContent.push(...aliases.slice(1));
184
187
  }
185
188
 
186
- // Add original term if it's different from the primary display term
187
- if (termName !== primaryDisplayTerm) {
188
- parentheticalContent.push(`<span class='term-external-original-term' title='original term'>${termName}</span>`);
189
- }
189
+ // Always add the original term if there are aliases, with special styling
190
+ // This ensures consistent behavior regardless of whether alias1 equals the term
191
+ // The original term should always be visible in the parenthetical list
192
+ parentheticalContent.push(`<span class='term-external-original-term term-original-term' title='original term'>${termName}</span>`);
190
193
 
191
194
  // Append parenthetical terms if any exist
192
195
  if (parentheticalContent.length > 0) {
193
196
  displayText += ` <span class='term-external-parenthetical-terms'>(${parentheticalContent.join(', ')})</span>`;
194
197
  }
198
+ } else {
199
+ // No aliases: wrap the term name itself as the original term
200
+ displayText = `<span class='term-external-original-term term-original-term' title='original term'>${termName}</span>`;
195
201
  }
196
202
 
197
203
  const termId = `term:${termName.replace(whitespace.oneOrMore, '-').toLowerCase()}`;
@@ -62,6 +62,33 @@ describe('Template Tag Parsing Functions', () => {
62
62
  });
63
63
  });
64
64
 
65
+ // Test: Does the parser handle the case when alias1 equals the term?
66
+ // Issue #194: When alias1 is the same as the term, the term should still appear in parentheses
67
+ test('should include term in parentheses even when alias1 equals term', () => {
68
+ const mockToken = {
69
+ info: { args: ['action', 'action', 'actions', 'act', 'acts'] }
70
+ };
71
+
72
+ const result = parseDef(mockGlobal, mockToken, 'Action', 'test.md');
73
+
74
+ // Should show: action (actions, act, acts, action)
75
+ // The term "action" should appear both as primary and in parenthetical list
76
+ expect(result).toContain('action');
77
+ expect(result).toContain('actions');
78
+ expect(result).toContain('act');
79
+ expect(result).toContain('acts');
80
+
81
+ // The original term should be in the parenthetical content with special styling
82
+ expect(result).toContain('term-local-original-term');
83
+ expect(result).toContain('term-local-parenthetical-terms');
84
+
85
+ // Verify all term IDs are present
86
+ expect(result).toContain('id="term:action"');
87
+ expect(result).toContain('id="term:actions"');
88
+ expect(result).toContain('id="term:act"');
89
+ expect(result).toContain('id="term:acts"');
90
+ });
91
+
65
92
  // Test: Can the system parse reference markup into proper links?
66
93
  test('should parse reference correctly', () => {
67
94
  const result = parseRef(mockGlobal, 'test-term');
@@ -105,17 +105,15 @@ async function fetchAllTermsFromIndex(token, owner, repo, options = {}) {
105
105
  return;
106
106
  }
107
107
 
108
- let termText = '';
109
- termSpan.childNodes.forEach(node => {
110
- if (node.nodeType === dom.window.Node.TEXT_NODE) {
111
- termText += node.textContent.trim();
112
- }
113
- });
114
-
115
- if (!termText) {
116
- termText = termSpan.textContent.trim();
108
+ // Extract the canonical term identifier from the term-local-original-term span.
109
+ // This contains the original term identifier as used in the source file naming
110
+ // and tref/xref references. If this span doesn't exist, skip the term entirely.
111
+ const originalTermSpan = dt.querySelector('span.term-local-original-term');
112
+ if (!originalTermSpan) {
113
+ return;
117
114
  }
118
115
 
116
+ const termText = originalTermSpan.textContent.trim();
119
117
  if (!termText) {
120
118
  return;
121
119
  }
@@ -14,7 +14,7 @@ async function processXTrefsData(allXTrefs, GITHUB_API_TOKEN, outputPathJSON, ou
14
14
 
15
15
  allXTrefs.xtrefs = allXTrefs.xtrefs.filter(xtref => {
16
16
  if (!xtref.owner || !xtref.repo || !xtref.repoUrl) {
17
- Logger.warn(`Removing incomplete reference: ${xtref.externalSpec}, ${xtref.term}`);
17
+ Logger.error(`Removing incomplete reference: ${xtref.externalSpec}, ${xtref.term}`);
18
18
  return false;
19
19
  }
20
20
  return true;
@@ -37,7 +37,10 @@ async function processXTrefsData(allXTrefs, GITHUB_API_TOKEN, outputPathJSON, ou
37
37
 
38
38
  for (const repoKey of Object.keys(xrefsByRepo)) {
39
39
  const repoGroup = xrefsByRepo[repoKey];
40
- Logger.process(`Processing repository: ${repoKey} (${repoGroup.xtrefs.length} terms)`);
40
+ // Build a repository URL for logging. Prefer an explicit repoUrl from
41
+ // an xtref, otherwise fall back to the canonical GitHub URL.
42
+ const repoUrl = repoGroup.xtrefs[0]?.repoUrl || `https://github.com/${repoKey}`;
43
+ Logger.process(`Processing repository: ${repoKey} (${repoGroup.xtrefs.length} terms) - ${repoUrl}`);
41
44
 
42
45
  const ghPageUrl = repoGroup.xtrefs[0]?.ghPageUrl;
43
46
  const allTermsData = await fetchAllTermsFromIndex(
@@ -48,7 +51,7 @@ async function processXTrefsData(allXTrefs, GITHUB_API_TOKEN, outputPathJSON, ou
48
51
  );
49
52
 
50
53
  if (!allTermsData) {
51
- Logger.error(`Could not fetch terms from repository ${repoKey}`);
54
+ Logger.error(`Could not fetch terms from repository ${repoKey} (${repoUrl})`);
52
55
  repoGroup.xtrefs.forEach(xtref => {
53
56
  xtref.commitHash = 'not found';
54
57
  xtref.content = 'This term was not found in the external repository.';
@@ -71,11 +74,30 @@ async function processXTrefsData(allXTrefs, GITHUB_API_TOKEN, outputPathJSON, ou
71
74
  xtref.commitHash = 'not found';
72
75
  xtref.content = 'This term was not found in the external repository.';
73
76
  xtref.avatarUrl = null;
74
- Logger.error(`Origin: ${xtref.sourceFile || xtref.sourceFiles.join(', ')} 👉 No match found for term: ${xtref.term} in ${xtref.externalSpec} (${repoKey})`);
77
+
78
+ // Build a readable list of source files for the error message.
79
+ // Two possible data structures exist:
80
+ // 1. xtref.sourceFile is a STRING like "primitive.md"
81
+ // 2. xtref.sourceFiles is an ARRAY OF OBJECTS like [{file: "primitive.md", type: "xref"}]
82
+ //
83
+ // The ternary operator works as follows:
84
+ // - If xtref.sourceFile exists (legacy case) → use it directly (it's already a string)
85
+ // - Otherwise → extract file names from the sourceFiles array:
86
+ // - .map(sf => sf.file) extracts just the filename from each object
87
+ // - .join(', ') combines them into a comma-separated string
88
+ const sourceFilesList = xtref.sourceFile
89
+ ? xtref.sourceFile
90
+ : (xtref.sourceFiles || []).map(sf => sf.file).join(', ');
91
+
92
+ // Prefer an explicit repo URL if provided on the xtref, otherwise
93
+ // build a standard GitHub URL from the owner/repo.
94
+ const githubUrl = xtref.repoUrl || `https://github.com/${repoKey}`;
95
+
96
+ Logger.error(`Origin: ${sourceFilesList} 👉 No match found for term: ${xtref.term} in ${xtref.externalSpec} (${githubUrl})`);
75
97
  }
76
98
  }
77
99
 
78
- Logger.success(`Finished processing repository: ${repoKey}`);
100
+ Logger.success(`Finished processing repository: ${repoKey} (${repoUrl})`);
79
101
  Logger.separator();
80
102
  }
81
103
 
@@ -25,7 +25,7 @@ function getCurrentBranch() {
25
25
  }).trim();
26
26
 
27
27
  if (branch) {
28
- Logger.info(`Current git branch: ${branch}`);
28
+ // This is too much info, comment out for the moment, Logger.info(`Current git branch: ${branch}`);
29
29
  return branch;
30
30
  }
31
31
 
@@ -61,7 +61,6 @@ function getGithubRepoInfo(spec) {
61
61
  const account = source.account || 'unknown';
62
62
  const repo = source.repo || 'unknown';
63
63
  const branch = getCurrentBranch();
64
-
65
64
  const content = `${account},${repo},${branch}`;
66
65
  Logger.info(`GitHub repo info: ${content}`);
67
66
  return content;
@@ -51,7 +51,7 @@ class Logger {
51
51
  * Highlight important data - magenta
52
52
  */
53
53
  static highlight(message, ...args) {
54
- console.log(chalk.magenta('✨'), chalk.magenta(message), ...args);
54
+ console.log(chalk.blue('✨'), chalk.blue(message), ...args);
55
55
  }
56
56
 
57
57
  /**
@@ -1,34 +0,0 @@
1
- /**
2
- * @file match-term.js
3
- * @description Utilities for matching a specific term within a [[def: ...]] definition block.
4
- */
5
-
6
- const { isLineWithDefinition } = require('../../utils/is-line-with-definition');
7
- const Logger = require('../../utils/logger');
8
-
9
- function matchTerm(text, term) {
10
- if (!text || typeof text !== 'string') {
11
- Logger.warn('Nothing to match for term:', term);
12
- return false;
13
- }
14
-
15
- const firstLine = text.split('\n')[0].trim();
16
- if (!isLineWithDefinition(firstLine)) {
17
- Logger.warn('String does not start with `[[def:` or end with `]]`');
18
- return false;
19
- }
20
-
21
- const startPos = firstLine.indexOf('[[def:') + 6;
22
- const endPos = firstLine.indexOf(']]');
23
- if (startPos === -1 || endPos === -1) {
24
- return false;
25
- }
26
-
27
- const relevantPart = firstLine.substring(startPos, endPos);
28
- const termsArray = relevantPart.split(',').map(entry => entry.trim());
29
- return termsArray.includes(term);
30
- }
31
-
32
- module.exports = {
33
- matchTerm
34
- };
@@ -1,36 +0,0 @@
1
- const { matchTerm } = require('./match-term');
2
-
3
- // Tests for matching terms within definition markup
4
- describe('matchTerm', () => {
5
- // Test: Can the system find terms that exist in definition markup?
6
- test('returns true when the term is found in a correctly formatted definition', () => {
7
- const text = '[[def: term1, term2]]\nSome additional text';
8
- expect(matchTerm(text, 'term1')).toBe(true);
9
- expect(matchTerm(text, 'term2')).toBe(true);
10
- });
11
-
12
- // Test: Does the system correctly identify when a term is not present?
13
- test('returns false when the term is not found in the definition', () => {
14
- const text = '[[def: term1, term2]]\nSome additional text';
15
- expect(matchTerm(text, 'term3')).toBe(false);
16
- });
17
-
18
- // Test: Does the system handle invalid input gracefully?
19
- test('returns false when the text is null or not a string', () => {
20
- expect(matchTerm(null, 'term1')).toBe(false);
21
- expect(matchTerm(123, 'term1')).toBe(false);
22
- });
23
-
24
- // Test: Does the system require proper definition markup format?
25
- test('returns false when the first line is not a valid definition', () => {
26
- const text = 'Invalid definition line\n[[def: term1, term2]]';
27
- expect(matchTerm(text, 'term1')).toBe(false);
28
- });
29
-
30
- // Test: Can the system handle whitespace variations in markup?
31
- test('handles extra spaces correctly', () => {
32
- const text = '[[def: term1 , term2 ]]';
33
- expect(matchTerm(text, 'term1')).toBe(true);
34
- expect(matchTerm(text, 'term2')).toBe(true);
35
- });
36
- });