UNPKG

vitepress-theme-base-teek

Version:
118 lines (101 loc) 3.96 kB
import MarkdownIt from "markdown-it"; import container from "markdown-it-container"; import yaml from "js-yaml"; import { withBase } from "../../helper/util"; import { ImgCard } from "../types"; import { SiteConfig } from "vitepress"; const imgCardName = "imgCard"; const rootClass = "img-card"; /** * 生成图片卡片容器 * * @param md MarkdownIt 实例 * @param base 根路径 */ const imgCardPlugin = (md: MarkdownIt) => { const siteConfig: SiteConfig = (globalThis as any).VITEPRESS_CONFIG; const { base = "/" } = siteConfig.userConfig; // 注册容器 md.use(container, imgCardName, {}); // 注册成功后,就会监听到 container_xx_open,其中 xx 为注册的容器名 md.renderer.rules[`container_${imgCardName}_open`] = (tokens, idx) => { const containerToken = tokens[idx]; let html = `<div class="${rootClass}-container">`; for (let i = idx; i < tokens.length; i++) { const token = tokens[i]; // 如果来到 ${imgCardName} 的结束标签,则跳出循环 if (token.type === `container_${imgCardName}_close`) break; if (!["yaml", "yml"].includes(token.info)) continue; // 解析 yaml 内容 const yamlContent = yaml.load(token.content.trim()) as ImgCard.Props | ImgCard.Item[]; let data: ImgCard.Item[] = []; let config: ImgCard.Config = {}; if (Array.isArray(yamlContent)) data = yamlContent; else { data = yamlContent.data || []; config = yamlContent.config || {}; } // 获取容器名后面的卡片数量 const cardNum = containerToken.info.trim().slice(imgCardName.length).trim(); config.cardNum = config.cardNum || Number(cardNum || 3) || 3; html += renderImgCard({ config, data }, base); // 删除 yaml 代码块 if (config.showCode !== true) { token.type = ""; token.tag = ""; token.hidden = true; } } // 返回不能有 </div> 结尾 return html; }; }; /** * 获取图片卡片 HTML 标签 * * @param imgCard 图片卡片数据 * @param base 根路径 */ const renderImgCard = (imgCard: ImgCard.Props, base: string) => { const { data = [], config = {} } = imgCard; if (!data.length) return ""; const { cardGap = 20, lineClamp = 2, target = "_blank", objectFit = "cover", imgHeight = "auto" } = config; let { cardNum = 3 } = config; if (!cardNum || cardNum > 4 || cardNum < 1) cardNum = 3; return ` <div class="${rootClass} index-${cardNum}" style="--row-gap: ${cardGap}px; --column-gap: ${cardGap}px; --column-min-width: calc(100% / ${cardNum} - ${cardGap * (cardNum - 1)}px);" > ${data .map( card => ` <${card.link ? "a" : "span"} href="${withBase(base, card.link)}" target="${target}" class="${rootClass}__item ${cardNum ? `row-${cardNum}` : ""}" style="--img-height: ${imgHeight}; --img-object-fit: ${objectFit}; --desc-line-clamp: ${lineClamp}" > <div class="${rootClass}__item__img"> <img src="${withBase(base, card.img)}"> </div> <div class="${rootClass}__item__info"> <p class="name">${card.name}</p> ${card.desc ? `<p class="desc">${card.desc}</p>` : ""} </div> ${ card.avatar || card.author ? `<div class="${rootClass}__item__footer"> ${card.avatar ? `<img src="${withBase(base, card.avatar)}">` : ""} ${card.author ? `<span>${card.author}</span>` : ""} </div>` : "" } </${card.link ? "a" : "span"}> ` ) .join("")} </div> `; }; export default imgCardPlugin;