1import {donationConfig} from './donation-config.js'; 2const escape = value => String(value ?? '').replace(/[&<>"']/g, c => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c])); 3export function renderDonation({tr, url, currency = '', config = donationConfig}) { 4 const bank = ['bank','krw','usd'].includes(currency), card = currency === 'card'; 5 const ko = (english,korean) => korean, en = english => english; 6 const choice = `<nav class="donation-method-nav" aria-label="${tr('Donation method','ê¸°ë¶ ë°©ë²')}"><a href="${url('donate/bank')}" ${bank ? 'aria-current="page"' : ''}><span aria-hidden="true">ð¦</span>${tr("Donate via domestic / int'l wire","ê³ì¢ ì´ì²´ë¡ 기ë¶í기")}</a><a aria-disabled="true" tabindex="-1" ${card ? 'aria-current="page"' : ''}><span aria-hidden="true">ð³</span>${tr('Donate by card','ì¹´ëë¡ ê¸°ë¶í기')}</a></nav>`; 7 8 const copy = (value, label) => `<button type="button" class="button donation-copy" data-donation-copy="${escape(value)}">${label}</button>`; 9 const row = (label,value,canCopy=false) => `<div><dt>${label}</dt><dd>${escape(value)}${canCopy ? copy(value,'Copy') : ''}</dd></div>`; 10 11 const bankCard = `<section class="donation-paper donation-bank" lang="ko" aria-labelledby="bank-title"><div class="donation-paper-top"><div><span class="involved-eyebrow">${ko('BANK TRANSFER','ê³ì¢ì´ì²´')}</span><h2 id="bank-title">${ko('Donate by bank transfer','êµë´ ê³ì¢ ì´ì²´ ìë´')}</h2></div><span class="donation-currency-stamp">â©</span></div><p class="donation-bank-name">${ko('KB Kookmin Bank','KBêµë¯¼ìí')}</p><p class="donation-account-number">${escape(config.account)}</p><p class="donation-beneficiary">${ko('Account holder','ìê¸ì£¼')}<br><strong>${escape(config.beneficiary)}</strong></p>${copy(config.account.replace(/\D/g,''),ko('Copy account number','ê³ì¢ë²í¸ ë³µì¬'))}<p class="donation-copy-hint">${ko('Copy the number, then paste it into your banking app.','ê³ì¢ë²í¸ë¥¼ ë³µì¬í ë¤ ìí ì±ì ë¶ì¬ë£ì´ì£¼ì¸ì.')}</p><p class="donation-copy-status" role="status" aria-live="polite"></p></section>`; 12 const wire = `<section class="donation-wire" lang="en" aria-labelledby="wire-title"><span class="involved-eyebrow">${en('BANK TRANSFER TO KOREA','íêµ ê³ì¢ë¡ í´ì¸ì¡ê¸')}</span><h2 id="wire-title">${tr('International wire transfer','í´ì¸ì¡ê¸ ìë´')}</h2><dl class="donation-wire-details">${row(en('Bank','ìí'),config.bank)}${row('SWIFT / BIC',config.swift,true)}${row(en('Account number','ê³ì¢ë²í¸'),config.account,true)}${row(en('Account holder (Korean)','ìê¸ì£¼ (íê¸)'),config.beneficiary)}${row(en('Bank address','ìí 주ì'),config.bankAddress)}${config.beneficiaryEnglish ? row(en('Beneficiaryâs registered English name','ìí ë±ë¡ ì문 ìê¸ì£¼'),config.beneficiaryEnglish) : ''}</dl><p class="donation-copy-status" role="status" aria-live="polite"></p><p>${en('KB Kookmin Bank does not require a separate routing number or clearing code. Use the SWIFT/BIC above.','êµë¯¼ìíì ë³ëì Routing Numberë Clearing Code를 ì구íì§ ììµëë¤. ì SWIFT/BIC를 ì¬ì©í´ì£¼ì¸ì.')}</p><p class="donation-wire-note">${en('Before sending, contact InKAS for the exact English beneficiary name registered with the bank and any additional details your sending bank requests.','ì¡ê¸ ì InKASì ìíì ë±ë¡ë ì íí ì문 ìê¸ì£¼ì ì¡ê¸ìíìì ì구íë ì¶ê° ì 보를 íì¸í´ì£¼ì¸ì.')}</p><a class="involved-link" href="${url('contact?topic=donations')}">${en('Request complete wire instructions','í´ì¸ì¡ê¸ ì ë³´ 문ì')} â</a><a class="donation-bank-source" href="https://omoney.kbstar.com/quics?page=C102552" target="_blank" rel="noopener noreferrer">${en('KBâs official remittance guide','êµë¯¼ìí ê³µì í´ì¸ì¡ê¸ ìë´')} â</a></section>`; 13 const cardPage = `<section class="donation-paper donation-card-payment"><span class="involved-eyebrow">EXIMBAY</span><h2>${tr("Card donations","ì¹´ë 기ë¶")}</h2><p>${tr("Card donations will be processed through Eximbay.","ì¹´ë 기ë¶ë Eximbay를 íµí´ ì§íë©ëë¤.")}</p><div class="donation-availability" role="note"><strong>
13${tr("Card payments are being prepared.","ì¹´ë ê²°ì 를 ì¤ë¹íê³ ììµëë¤.")}</strong><p>${tr("Online card donations are not available yet. You can currently donate by bank transfer.","ì¨ë¼ì¸ ì¹´ë 기ë¶ë ìì§ ì´ì©í ì ììµëë¤. íì¬ë ê³ì¢ ì´ì²´ë¡ 기ë¶íì¤ ì ììµëë¤.")}</p></div><a class="button donation-raised-button" href="${url("donate/bank")}">${tr("Donate via domestic / int\'l wire","ê³ì¢ ì´ì²´ë¡ 기ë¶í기")} â</a></section>`; 14 const context = `<aside class="donation-context"><div class="donation-context-copy"><h2>${tr("Donation enquiries","íì ìë´")}</h2><p>${tr("For donation receipts, regular giving, program sponsorship or company partnerships, contact InKAS.","기ë¶ê¸ ììì¦, ì 기 íì, íë¡ê·¸ë¨ íìê³¼ 기ì ·ë¨ì²´ íë ¥ì InKASì 문ìí´ì£¼ì¸ì.")}</p></div><div class="donation-context-links"><a class="involved-link" href="${url('contact?topic=donations')}">${tr("Contact InKAS","íì 문ì")} â</a><a class="involved-link" href="${url("transparency")}">${tr("Donation disclosures","기ë¶ê¸ ê³µì 보기")} â</a></div></aside>`; 15 return `<div class="donation-page wrap" data-preserve-text><a class="involved-link" href="${url("involved#support")}">â ${tr("Donations & partnerships","íì·íë ¥")}</a><header class="donation-heading"><span class="involved-eyebrow">InKAS / ${tr("DONATIONS","íì")}</span><h1>${bank ? tr("Donate via domestic / int\'l wire","ê³ì¢ ì´ì²´ë¡ 기ë¶í기") : card ? tr("Donate by card","ì¹´ëë¡ ê¸°ë¶í기") : tr("Donate to InKAS","InKAS íìí기")}</h1><p>${tr("Individuals, companies and groups can support homeland visits, birth-family reunions, language education and cultural exchange.","ê°ì¸Â·ê¸°ì ·ë¨ì²´ì íìì¼ë¡ 모êµë°©ë¬¸, ì¹ê°ì¡± ë§ë¨, ì¸ì´ êµì¡ê³¼ 문í êµë¥ë¥¼ ì§ìí©ëë¤.")}</p></header>${choice}${bank ? `<div class="donation-layout donation-transfer-layout">${bankCard}${wire}</div>${context}` : card ? `<div class="donation-layout donation-card-layout">${cardPage}</div>${context}` : context}</div>`; 16} 17export async function copyDonationText(text, {clipboard = globalThis.navigator?.clipboard, document = globalThis.document} = {}) { 18 try { if(clipboard?.writeText) { await clipboard.writeText(text); return true; } } catch {} 19 const field = document.createElement('textarea'); 20 field.value = text; field.readOnly = true; 21 field.style.cssText = 'position:fixed;left:0;top:0;opacity:0;font-size:16px'; 22 document.body.append(field); field.focus(); field.select(); field.setSelectionRange(0,text.length); 23 let copied = false; 24 try { copied = document.execCommand('copy'); } catch {} finally { field.remove(); } 25 return copied; 26} 27export function bindDonation(root, {tr: optionsTr}) { 28 for(const button of root.querySelectorAll('[data-donation-copy]')) button.addEventListener('click', async () => { 29 const text = button.dataset.donationCopy; 30 const section = button.closest('section'); 31 const status = section.querySelector('.donation-copy-status'); 32 const copied = await copyDonationText(text); 33 const tr = section.lang === 'en' ? en => en : section.lang === 'ko' ? (en,ko) => ko : optionsTr; 34 button.focus({preventScroll:true}); 35 if(copied) { status.textContent = tr('Copied. Paste it into your banking app.','ë³µì¬íì´ì. ìí ì±ì ë¶ì¬ë£ì´ì£¼ì¸ì.'); } 36 else { 37 status.textContent = tr('Select and copy the number below.','ìë ë´ì©ì ê¸¸ê² ëë¬ ë³µì¬í´ì£¼ì¸ì.'); 38 let field = section.querySelector('.donation-manual-copy'); 39 if(!field) { field = document.createElement('textarea'); field.className = 'donation-manual-copy'; field.readOnly = true; field.setAttribute('aria-label',tr('Bank details to copy','ë³µì¬í ìí ì ë³´')); status.after(field); } 40 field.value = text; field.focus(); field.select(); field.setSelectionRange(0,text.length); 41 } 42 }); 43}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.