@@ -13,7 +13,8 @@ async function init() {
1313 renderUpdates ( md ) ;
1414 } catch ( err ) {
1515 console . error ( err ) ;
16- document . getElementById ( "certList" ) . innerHTML = `<p style="color:#ef4444">Failed to load certificate data.</p>` ;
16+ const certList = document . getElementById ( "certList" ) ;
17+ if ( certList ) certList . innerHTML = `<p style="color:#ef4444">Failed to load certificate data.</p>` ;
1718 }
1819}
1920
@@ -34,9 +35,7 @@ function parseCertTable(md) {
3435 for ( let i = start + 2 ; i < lines . length ; i ++ ) {
3536 const line = lines [ i ] . trim ( ) ;
3637 if ( ! line . startsWith ( "|" ) ) break ;
37- // split by '|' and trim
3838 const parts = line . split ( "|" ) . map ( p => p . trim ( ) ) ;
39- // expected parts: ["", "Company", "Type", "Status", "Valid From", "Valid To", "Download", ""]
4039 const company = parts [ 1 ] || "" ;
4140 const type = parts [ 2 ] || "" ;
4241 const statusRaw = parts [ 3 ] || "" ;
@@ -62,28 +61,24 @@ function parseCertTable(md) {
6261
6362function stripMd ( s ) {
6463 if ( ! s ) return "" ;
65- // only remove bold markers **, leave links intact
6664 return s . replace ( / \* \* / g, "" ) . trim ( ) ;
6765}
6866
6967function extractUrlFromMd ( s ) {
7068 if ( ! s ) return "" ;
71- // match Markdown link (exact URL)
7269 const m = s . match ( / \[ .* ?\] \( ( h t t p s ? : \/ \/ [ ^ \) ] + ) \) / ) ;
73- if ( m && m [ 1 ] ) return m [ 1 ] ; // return exact URL from README.md
74-
75- // fallback: if plain URL exists, just use it
70+ if ( m && m [ 1 ] ) return m [ 1 ] ;
7671 const m2 = s . match ( / h t t p s ? : \/ \/ \S + / ) ;
7772 if ( m2 ) return m2 [ 0 ] ;
78-
7973 return "" ;
8074}
8175
8276function decodeSafe ( u ) {
8377 try {
78+ // decodeURI to retain characters that decodeURIComponent would throw on
8479 return decodeURIComponent ( u ) ;
8580 } catch ( e ) {
86- return u ;
81+ try { return decodeURI ( u ) ; } catch ( e2 ) { return u ; }
8782 }
8883}
8984
@@ -113,6 +108,7 @@ function renderRecommended(md) {
113108
114109function renderCertCards ( certs ) {
115110 const container = document . getElementById ( "certList" ) ;
111+ if ( ! container ) return ;
116112 container . innerHTML = "" ;
117113
118114 if ( ! certs . length ) {
@@ -146,7 +142,6 @@ function renderCertCards(certs) {
146142 </div>
147143 ` ;
148144
149- // open modal with details on click / enter
150145 card . addEventListener ( "click" , ( ) => openModal ( c ) ) ;
151146 card . addEventListener ( "keypress" , ( e ) => { if ( e . key === "Enter" ) openModal ( c ) ; } ) ;
152147
@@ -157,6 +152,7 @@ function renderCertCards(certs) {
157152function renderUpdates ( md ) {
158153 const idx = md . indexOf ( "# Updates" ) ;
159154 const container = document . getElementById ( "updatesInner" ) ;
155+ if ( ! container ) return ;
160156 container . innerHTML = "" ;
161157
162158 if ( idx === - 1 ) {
@@ -192,35 +188,55 @@ function openModal(c) {
192188 const modal = document . getElementById ( "certModal" ) ;
193189 if ( ! modal ) return ;
194190
195- document . getElementById ( "modalName" ) . textContent = c . company ;
196- document . getElementById ( "modalMeta" ) . textContent = `${ c . type } • Status: ${ c . status || ( c . status === "" ? "Unknown" : c . status ) } ` ;
197- document . getElementById ( "modalDates" ) . textContent = `Valid: ${ c . validFrom } → ${ c . validTo } ` ;
191+ // Basic fields
192+ const nameEl = document . getElementById ( "modalName" ) ;
193+ const metaEl = document . getElementById ( "modalMeta" ) ;
194+ const datesEl = document . getElementById ( "modalDates" ) ;
195+ const dl = document . getElementById ( "modalDownload" ) ;
198196
199- // Hide/remove the modal-note if present (removes the Disclaimer)
200- const noteEl = document . getElementById ( "modalNote" ) ;
201- if ( noteEl ) {
202- noteEl . innerHTML = "" ;
203- noteEl . style . display = "none" ;
204- }
197+ if ( nameEl ) nameEl . textContent = c . company ;
198+ if ( metaEl ) metaEl . textContent = `${ c . type } • Status: ${ c . status || ( c . status === "" ? "Unknown" : c . status ) } ` ;
199+ if ( datesEl ) datesEl . textContent = `Valid: ${ c . validFrom } → ${ c . validTo } ` ;
200+
201+ // Force-hide/remove common modal-note elements that might contain the disclaimer
202+ // (covers different naming conventions so it actually vanishes)
203+ const noteSelectors = [ '#modalNote' , '#modal-note' , '.modal-note' , '[data-modal-note]' ] ;
204+ noteSelectors . forEach ( sel => {
205+ document . querySelectorAll ( sel ) . forEach ( el => {
206+ el . innerHTML = "" ;
207+ el . style . display = "none" ;
208+ // also remove from DOM to be safe
209+ if ( el . parentNode ) el . parentNode . removeChild ( el ) ;
210+ } ) ;
211+ } ) ;
205212
206- const dl = document . getElementById ( "modalDownload" ) ;
207- dl . innerHTML = "" ;
208- if ( c . download ) {
209- // Create a single anchor that shows the (decoded) URL as the button/text.
210- const a = document . createElement ( "a" ) ;
211- a . href = c . download ;
212- a . target = "_blank" ;
213- a . rel = "noopener noreferrer" ;
214- // Show a decoded URL for readability (falls back to original if decode fails)
215- a . textContent = decodeSafe ( c . download ) ;
216- a . className = "download-link" ;
217- // Make it look/behave like a button if you want CSS for .download-link
218- a . setAttribute ( "role" , "button" ) ;
219- dl . appendChild ( a ) ;
220-
221- // NOTE: we intentionally do NOT add a small raw URL under the button — per request.
213+ if ( ! dl ) {
214+ console . warn ( "modalDownload element not found" ) ;
222215 } else {
223- dl . innerHTML = `<div style="color:var(--muted);">No download link found.</div>` ;
216+ dl . innerHTML = "" ;
217+ if ( c . download ) {
218+ // Anchor (button) — visible text is "Download"
219+ const a = document . createElement ( "a" ) ;
220+ a . href = c . download ;
221+ a . target = "_blank" ;
222+ a . rel = "noopener noreferrer" ;
223+ a . textContent = "Download" ;
224+ a . className = "download-link" ;
225+ a . setAttribute ( "role" , "button" ) ;
226+ dl . appendChild ( a ) ;
227+
228+ // Small raw URL under the button for readability/copying
229+ const raw = document . createElement ( "div" ) ;
230+ raw . className = "download-raw" ;
231+ raw . style . marginTop = "8px" ;
232+ raw . style . fontSize = "12px" ;
233+ raw . style . color = "var(--muted)" ;
234+ raw . style . wordBreak = "break-all" ;
235+ raw . textContent = decodeSafe ( c . download ) ;
236+ dl . appendChild ( raw ) ;
237+ } else {
238+ dl . innerHTML = `<div style="color:var(--muted);">No download link found.</div>` ;
239+ }
224240 }
225241
226242 modal . classList . add ( "show" ) ;
0 commit comments