卡片字段

正面

<div class="row word">{{Word}}</div>

{{#IPA}}
<div class="row pron">
  <span class="ipa">{{IPA}}</span>
  {{#Audio}}<span class="audio">{{Audio}}</span>{{/Audio}}
</div>
{{/IPA}}

{{#Audio}}
{{^IPA}}
<div class="row pron">
  <span class="audio">{{Audio}}</span>
</div>
{{/IPA}}
{{/Audio}}

<div class="tags">
  {{#Exam_Level}}<span class="chip">{{Exam_Level}}</span>{{/Exam_Level}}
  {{#COCA_Rank}}<span class="chip">COCA {{COCA_Rank}}</span>{{/COCA_Rank}}
  {{#Frq}}<span class="chip">Frq {{Frq}}</span>{{/Frq}}
</div>

背面

<div class="row word">{{Word}}</div>

<div class="row pron">
  {{#IPA}}<span class="ipa">{{IPA}}</span>{{/IPA}}
  {{#Audio}}<span class="audio">{{Audio}}</span>{{/Audio}}
</div>

<div class="hr"></div>

<div class="row meaning">{{Meaning}}</div>

{{#En_Meaning}}
<div class="row en">{{En_Meaning}}</div>
{{/En_Meaning}}

<div class="tags">
  {{#COCA_Rank}}<span class="chip">COCA {{COCA_Rank}}</span>{{/COCA_Rank}}
  {{#Frq}}<span class="chip">Frq {{Frq}}</span>{{/Frq}}
  {{#Times}}<span class="chip">Seen {{Times}}</span>{{/Times}}
  {{#Exam_Level}}<span class="chip">Exam {{Exam_Level}}</span>{{/Exam_Level}}
  {{#Video_Url}}<a class="chip link" href="{{Video_Url}}">Video</a>{{/Video_Url}}
</div>

<div class="hr"></div>

<div class="row morph">
  {{#Lemma}}<div class="box"><b>Lemma</b><br>{{Lemma}}</div>{{/Lemma}}
  {{#Prefix}}<div class="box"><b>Prefix</b><br>{{Prefix}}</div>{{/Prefix}}
  {{#Root}}<div class="box"><b>Root</b><br>{{Root}}</div>{{/Root}}
  {{#Suffix}}<div class="box"><b>Suffix</b><br>{{Suffix}}</div>{{/Suffix}}
</div>

<!-- 正确做法:直接渲染 Anki 图片 HTML -->
{{#Image}}
<div class="imgwrap" id="imgWrap">
  {{Image}}
</div>
{{/Image}}

{{#Tips}}
<div class="tips">
  <div class="tips-title">💡 Tips</div>
  <div class="tips-content">{{Tips}}</div>
</div>
{{/Tips}}

{{#Example}}
<div class="row example" id="exWrap">{{Example}}</div>
{{/Example}}

<script>
  (function () {
    function nlToBr(selector) {
      var el = document.querySelector(selector);
      if (!el) return;
      el.innerHTML = el.innerHTML.replace(/\\n/g, "<br>");
    }

    function isVisiblyEmpty(node) {
      if (!node) return true;
      if (node.querySelector("img, audio, video, svg, iframe")) return false;

      var t = (node.textContent || "")
        .replace(/\u00A0/g, "")
        .replace(/\u200B/g, "")
        .replace(/\u200C/g, "")
        .replace(/\u200D/g, "")
        .replace(/\uFEFF/g, "")
        .replace(/\s+/g, "")
        .trim();

      return t.length === 0;
    }

    function normalizeUrl(url) {
      return (url || "").trim().replace(/["'<>),]+$/g, "");
    }

    function looksLikeImageUrl(url) {
      if (!url) return false;

      var cleanUrl = normalizeUrl(url);

      if (/\.(png|jpe?g|gif|webp|bmp|svg)(\?[^\s]*)?$/i.test(cleanUrl)) {
        return true;
      }

      try {
        var parsed = new URL(cleanUrl, window.location.href);
        var host = (parsed.hostname || "").toLowerCase();
        var path = (parsed.pathname || "").toLowerCase();
        var query = (parsed.search || "").toLowerCase();
        var hintText = host + path + query;

        if (!/^https?:$/i.test(parsed.protocol)) {
          return false;
        }

        if (/\/images?(\/|$|\?)/i.test(path)) return true;
        if (/^th\.bing\.com$/i.test(host) && /^\/th\/id\//i.test(path)) return true;
        if (/image|img|photo|pic|thumb|thumbnail|media|asset|static|upload/.test(hintText)) {
          return true;
        }
        if (/cdn|gstatic|googleusercontent|licdn/.test(host)) return true;
        if (/tbn=|q=|w=|h=|fit=|format=|fm=/.test(query) && /(gstatic|cdn|img|image|media)/.test(hintText)) {
          return true;
        }
      } catch (e) {
        return false;
      }

      return false;
    }

    function createFallbackLink(url) {
      var link = document.createElement("a");
      link.href = url;
      link.target = "_blank";
      link.rel = "noopener noreferrer";
      link.className = "extlink";
      link.textContent = url;
      return link;
    }

    function createImageOrLink(url) {
      var cleanUrl = normalizeUrl(url);
      if (!cleanUrl) {
        return document.createTextNode("");
      }

      if (!looksLikeImageUrl(cleanUrl)) {
        return createFallbackLink(cleanUrl);
      }

      var img = document.createElement("img");
      img.src = cleanUrl;
      img.alt = "image";
      img.loading = "lazy";
      img.referrerPolicy = "no-referrer";
      img.onerror = function () {
        if (!img.dataset.fallbackApplied) {
          img.dataset.fallbackApplied = "1";
          img.replaceWith(createFallbackLink(cleanUrl));
        }
      };
      return img;
    }

    function fixImage() {
      var wrap = document.getElementById("imgWrap");
      if (!wrap) return;

      var nodes = Array.from(wrap.childNodes);

      nodes.forEach(function (node) {
        if (node.nodeType === Node.TEXT_NODE) {
          var text = node.textContent;
          var regex = /https?:\/\/[^\s<>"']+/gi;
          var match;
          var lastIndex = 0;
          var frag = document.createDocumentFragment();

          while ((match = regex.exec(text)) !== null) {
            var rawUrl = match[0];
            var url = normalizeUrl(rawUrl);

            if (!looksLikeImageUrl(url)) {
              continue;
            }

            frag.appendChild(
              document.createTextNode(text.slice(lastIndex, match.index))
            );

            frag.appendChild(createImageOrLink(url));

            lastIndex = match.index + rawUrl.length;
          }

          if (lastIndex > 0) {
            frag.appendChild(document.createTextNode(text.slice(lastIndex)));
            node.replaceWith(frag);
          }
        }
      });

      var links = Array.from(wrap.querySelectorAll("a[href]"));

      links.forEach(function (link) {
        var href = normalizeUrl(link.getAttribute("href"));
        if (!looksLikeImageUrl(href)) {
          return;
        }

        link.replaceWith(createImageOrLink(href));
      });
    }

    function fix() {
      nlToBr(".meaning");
      nlToBr(".en");
      nlToBr(".tips-content");

      var ex = document.getElementById("exWrap");
      if (ex && isVisiblyEmpty(ex)) {
        ex.style.display = "none";
      }

      fixImage();
    }

    fix();
    setTimeout(fix, 50);
  })();
</script>

CSS

/* ===== Theme ===== */
 
/* ===== Theme ===== */
:root {
  --bg: #faf7f2;
  --panel: #fffdf8;
  --fg: #1b1b1b;
  --muted: #6b6b6b;
  --border: #e6e0d6;
  --chip-bg: #f2ede6;
  --accent: #1f6f78;
  --shadow: 0 10px 30px rgba(31, 22, 10, 0.08);
}
 
.nightMode,
.night_mode,
body.nightMode {
  --bg: #121311;
  --panel: #171816;
  --fg: #e8e7e4;
  --muted: #b2ada4;
  --border: #2c2d2a;
  --chip-bg: #20211f;
  --accent: #6fb2b9;
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
}
 
/* ===== Base ===== */
.card {
  position: relative;
 
  font-family:
    "Iowan Old Style",
    "Palatino Linotype",
    "Source Han Serif SC",
    "Songti SC",
    "STSong",
    "Times New Roman",
    serif;
  font-size: 19px;
  line-height: 1.6;
  color: var(--fg);
  text-align: left;
 
  padding: 18px 16px;
  border: 1px solid color-mix(in srgb, var(--border) 75%, transparent);
  border-radius: 18px;
  background: linear-gradient(
    180deg,
    var(--panel) 0%,
    color-mix(in srgb, var(--panel) 96%, var(--bg)) 60%,
    var(--bg) 100%
  );
  background-clip: padding-box;
 
  box-shadow: var(--shadow);
  animation: fadein 260ms ease-out;
}
 
@keyframes fadein {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
 
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
 
/* ===== Layout ===== */
.row {
  margin: 10px 0;
}
 
.hr {
  height: 1px;
  margin: 14px 0;
  background: linear-gradient(
    90deg,
    transparent,
    color-mix(in srgb, var(--border) 60%, transparent),
    transparent
  );
}
 
/* ===== Word / Pron ===== */
.word {
  padding-right: 140px;
 
  font-size: 40px;
  font-weight: 800;
  letter-spacing: 0.3px;
  color: var(--fg);
}
 
.pron {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
 
  font-size: 17px;
  color: var(--muted);
}
 
.ipa {
  font-style: italic;
}
 
/* ===== Meaning / Example Text ===== */
.meaning {
  font-size: 22px;
  font-weight: 650;
  white-space: pre-line;
}
 
.en {
  font-size: 17px;
  color: var(--muted);
  white-space: pre-line;
}
 
/* ===== Tags ===== */
.tags {
  position: absolute;
  top: 10px;
  right: 10px;
 
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 6px;
 
  max-width: 45%;
}
 
.chip {
  display: inline-block;
 
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
 
  background: var(--chip-bg);
 
  font-size: 12px;
  color: var(--muted);
}
 
/* ===== Images:并排 + 自动换行 ===== */
.imgwrap {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
 
  margin-top: 12px;
}
 
.imgwrap img {
  display: block;
 
  width: calc(48% - 6px);
  height: auto;
 
  border: 1px solid var(--border);
  border-radius: 14px;
 
  object-fit: cover;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
}
 
.imgwrap img:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 22px rgba(0, 0, 0, 0.12);
}
 
/* ===== Tips ===== */
.tips {
  position: relative;
 
  margin-top: 12px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
 
  background: color-mix(in srgb, var(--chip-bg) 65%, transparent);
 
  font-size: 15px;
  line-height: 1.6;
}
 
.tips::before {
  content: "";
 
  position: absolute;
  top: 10px;
  bottom: 10px;
  left: 0;
 
  width: 3px;
  border-radius: 2px;
 
  background: var(--accent);
  opacity: 0.7;
}
 
.tips-title {
  margin-bottom: 6px;
  padding-left: 6px;
 
  font-size: 14px;
  font-weight: 700;
  color: var(--accent);
}
 
.tips-content {
  padding-left: 6px;
  white-space: pre-line;
}
 
/* ===== Example ===== */
.example {
  padding: 10px 12px;
  border-left: 3px solid var(--accent);
  border-radius: 10px;
 
  background: color-mix(in srgb, var(--chip-bg) 70%, transparent);
 
  font-size: 17px;
}
 
/* ===== Morph ===== */
.morph {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
 
  font-size: 14px;
  color: var(--muted);
}
 
.morph .box {
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: 12px;
 
  background: color-mix(in srgb, var(--panel) 80%, transparent);
}
 
.morph b {
  color: var(--fg);
}
 
/* ===== Responsive ===== */
@media (max-width: 600px) {
  .word {
    font-size: 34px;
  }
 
  .morph {
    grid-template-columns: 1fr;
  }
}
 
/* ===== Form Fix ===== */
input,
textarea,
select {
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 10px;
  outline: none;
 
  background: color-mix(in srgb, var(--panel) 88%, transparent);
 
  color: var(--fg);
}
 
input,
textarea {
  caret-color: var(--accent);
}
 
input::placeholder,
textarea::placeholder {
  color: color-mix(in srgb, var(--muted) 75%, transparent);
}
 
input:focus,
textarea:focus,
select:focus {
  border-color: color-mix(in srgb, var(--accent) 55%, var(--border));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent);
}