Đến nội dung chính

Khối mã

Mã đưa ra để người ta sao chép rồi chạy — chỉ đáng chỗ khi có tên tệp, nút sao chép và cuộn ngang.

Hiển thị dữ liệu

Xem trước trực tiếp

Nguồn

<figure class="dc-code">
  <figcaption class="dc-code__bar">
    <span class="dc-code__file">fetchOrders.js</span>
    <span class="dc-code__lang">JavaScript</span>
    <button type="button" class="dc-code__copy">복사<span class="dc-sr"> — 코드 전체를 클립보드에 담습니다</span></button>
  </figcaption>
  <pre class="dc-code__pre" tabindex="0"><code class="dc-code__code">async function fetchOrders(shopId) {
  const res = await fetch('/api/shops/' + shopId + '/orders');
  if (!res.ok) throw new Error('주문을 불러오지 못했습니다');
  return res.json();
}</code></pre>
  <p class="dc-code__msg" role="status" aria-live="polite"></p>
</figure>
.dc-code { margin:0; border:1px solid var(--dc-line); border-radius:var(--dc-r-md); background:var(--dc-sunken); overflow:hidden; font-family:var(--dc-font); }
.dc-code__bar { display:flex; flex-wrap:wrap; align-items:center; gap:var(--dc-2) var(--dc-3); padding:var(--dc-2) var(--dc-3); border-bottom:1px solid var(--dc-line); background:var(--dc-surface); }
.dc-code__file { font-family:var(--dc-mono); font-size:13px; font-weight:600; color:var(--dc-text); }
.dc-code__lang { padding:2px var(--dc-2); border-radius:var(--dc-r-full); background:var(--dc-sunken); color:var(--dc-text-sub); font-size:11px; }
.dc-code__copy { margin-left:auto; min-height:32px; padding:0 var(--dc-3); border:1px solid var(--dc-line-field); border-radius:var(--dc-r-sm); background:var(--dc-surface); color:var(--dc-text); font:inherit; font-size:13px; cursor:pointer; }
.dc-code__copy:hover { background:var(--dc-sunken); }
.dc-code__pre { margin:0; padding:var(--dc-4); overflow-x:auto; }
.dc-code__code { display:block; font-family:var(--dc-mono); font-size:13px; line-height:1.7; color:var(--dc-text); white-space:pre; }
.dc-code__msg { margin:0; min-height:1.3em; padding:0 var(--dc-3) var(--dc-2); font-size:12px; color:var(--dc-ok); }
.dc-code__msg.is-fail { color:var(--dc-danger); }
.dc-code__prompt { color:var(--dc-brand-text); user-select:none; }
.dc-code__out { color:var(--dc-text-sub); }
.dc-code--num .dc-code__code { counter-reset:dc-line; }
.dc-code__line { display:block; counter-increment:dc-line; }
.dc-code__line::before { content:counter(dc-line); display:inline-block; width:2em; margin-right:var(--dc-3); text-align:right; color:var(--dc-text-sub); }
document.querySelectorAll('.dc-code__copy').forEach(function (btn) {
  btn.addEventListener('click', function () {
    var box = btn.closest('.dc-code');
    var code = box && box.querySelector('.dc-code__code');
    var msg = box && box.querySelector('.dc-code__msg');
    if (!code) return;
    var hide = box.querySelectorAll('.dc-code__prompt, .dc-code__out');
    var text;
    if (hide.length) {
      /* 프롬프트 기호와 실행 결과까지 붙어 오면 그대로 붙여넣을 수 없다 */
      hide.forEach(function (n) { n.style.display = 'none'; });
      text = code.innerText.split('n').filter(function (l) { return l.trim() !== ''; }).join('n');
      hide.forEach(function (n) { n.style.removeProperty('display'); });
    } else {
      text = code.innerText;
    }
    var done = function () { if (!msg) return; msg.classList.remove('is-fail'); msg.textContent = '복사했습니다'; };
    var fail = function () { if (!msg) return; msg.classList.add('is-fail'); msg.textContent = '복사하지 못했습니다. 직접 선택해 주세요'; };
    if (navigator.clipboard && navigator.clipboard.writeText) {
      navigator.clipboard.writeText(text).then(done, fail);
    } else {
      fail();
    }
  });
});

Cách dùng

  • Ghi tên tệp phía trên mã, nếu không người đọc không biết dán vào đâu
  • Để dòng dài cuộn ngang thay vì ngắt dòng; mã bị ngắt dán vào là lỗi
  • Sau khi bấm sao chép, hãy báo Đã sao chép bằng chữ

Điểm cần lưu ý

  • Cho thẻ pre tabindex 0 để bàn phím cũng cuộn ngang được
  • Đừng chỉ dựa vào màu cú pháp; giữ tương phản chữ từ 4.5:1 trở lên

Tiếp theo