iT邦幫忙

2025 iThome 鐵人賽

DAY 16
0

在昨天我們已經完成複製帶連結的通知文字了!
但如果要讓其他人使用的話,我們需要讓使用者在 Popup 輸入自訂範本時,能直覺且獨立操作完成 —— 也就是防呆設計。

WHY

第一次使用的人可能會遇到的情況:

  1. 忘記變數名稱(例如:{REVIEWER_NAME} 打成 {REVIEWER}),導致輸出錯誤。
  2. 範本太長時沒有即時回饋,使用者會困惑。
  3. 沒有範例預覽,使用者不知道結果會長什麼樣子。

HOW

Placeholder 與說明文字

  • 在 textarea placeholder 中顯示參考範例
    <textarea class="w-full h-20 border-1 border-gray-600 rounded p-2" rows="5" :placeholder="templateExample" v-model="templateContent"></textarea>
    
    const templateExample = "例:Hello {REVIEWER_NAME},這是最新的 {MR_LINK},再麻煩你,謝謝"
    
  • 在空位列出可用佔位符清單:{REVIEWER_NAME}、{MR_LINK},並標注用途。
    <div class="mt-2">
        <ul class="list-disc">
          <li class="font-bold border-b border-b-gray-400">
            <div>範本選項</div>
            <div>說明</div>
          </li>
          <li>
            <div>{REVIEWER_NAME}</div>
            <div>Reviewer 名字純文字</div>
          </li>
          <li>
            <div>{MR_LINK}</div>
            <div>
              <div>Merge Request 連結</div>
              <div class="text-xs">(會自動填入完整連結,讓 Slack 自動識別)</div>
            </div>
          </li>
        </ul>
      </div>
    

即時預覽參考

  • 當使用者在 textarea 輸入時,用一組「範例資料」動態把範本渲染成最終文字,並顯示在下方 preview 區塊。
  • 讓使用者立刻看見輸入的結果,能快速調整格式或換行。
<div class="bg-sky-100 rounded p-2">
  <span class="bg-sky-200 px-2 rounded-full text-sky-800">參考</span>
  <div class="text-sky-600 mt-1">{{ dynamicContent }}</div>
</div>
const defaultData = {
  REVIEWER_NAME: 'Jason',
  MR_LINK: 'Demonstrate clangsa with compiledb and inlined scripts'
}
const dynamicContent = computed(() => applyTemplate(templateContent.value, defaultData))

// 套用範本
function applyTemplate(template, data) {
  return template.replace(/\{([A-Z0-9_]+)\}/g, (_, key) => {
    const val = data[key];
    if (Array.isArray(val)) return val.join(', ');
    return val ?? '<--未知變數-->';
  });
}

儲存時變數檢查

  • 用正則找出所有 {...} 佔位符:
    // 取得佔位符清單
      function extractPlaceholders(template) {
        return [...template.matchAll(/\{([A-Z0-9_]+)\}/g)].map(m => m[1]);
      }
    
    規則:
    • 使用 {} 將名稱包起來
    • 皆使用英文大寫
    • 僅能使用_區分單字
  • 檢查是否有未知佔位符(非預期的 key),提示使用者。
  • 限制範本最大長度(例如 1000 字)並提示過長情況。
// 儲存範例
const error = ref('')
async function saveTemplate() {
  const template = templateContent.value.trimEnd()
  if (template.length > 1000) {
    error.value = '文字太長,請縮短一點~'
    return
  };
  const availableKey = Object.keys(defaultData)
  const unknownKey = extractPlaceholders(template).filter(k => !availableKey.includes(k));

  if (unknownKey.length) {
    error.value = `發現未知變數:${unknownKey.join(', ')}`
    return
  };
  chrome.storage.sync.set({ reviewTemplate: template })
  templateContent.value = template
  error.value = ''
}

快速按鈕

在可用佔位符清單放小按鈕,點擊就插入 {REVIEWER_NAME}、{MR_LINK} 等,避免打錯字。

<button class="text-emerald-800 bg-emerald-100 hover:bg-emerald-200 px-1 rounded-full" @click="insertKey('{REVIEWER_NAME}')">{REVIEWER_NAME}</button>
//快速插入佔位符
function insertKey(keyName) {
  templateContent.value += keyName
}

注意事項

  • XSS 風險:若你同時提供 HTML 模式(ClipboardItem 的 text/html),切勿把 user-generated HTML 直接注入網頁中做 innerHTML 渲染;在 preview 若需要顯示 HTML,只做純文字顯示或 sanitize(簡單上可用 textContent)。
  • 長度限制:某些目標平台(如 Slack)會對訊息長度做限制,提醒使用者不要過長。

實際測試

  • 初始畫面
    https://ithelp.ithome.com.tw/upload/images/20250924/20153928vq1hgoOKz3.png
  • 儲存時發現有未知的變數時,顯示錯誤訊息
    https://ithelp.ithome.com.tw/upload/images/20250924/20153928h3R32RPFMU.png

上一篇
Day 15 : 為通知文字加上連結,成為貼心的同事
下一篇
Day 17:規劃 ─ 支援多專案 Merge Request 的差異格式
系列文
從零開始改善工作之 Chrome Extension: MR 通知文字小工具22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言