vue3實現markdown文檔轉HTML
安裝marked
npm install marked
<template><!-- 后臺可添加樣式編輯器 --><div class="markdown-editor" :class="{ 'fullscreen': isFullscreen, 'preview-mode': isPreviewMode }"><div class="editor-container"><!-- Markdown 輸入區域 --><div class="markdown-input" v-show="!isPreviewMode"><el-card class="editor-card"><template #header><div class="header"><div class="toolbar"><!-- 導出文件 --><el-button-group><el-button size="small" @click="exportFile" title="導出文件"><el-icon><Download /></el-icon></el-button></el-button-group><!-- 格式化工具 --><el-button-group><el-button size="small" @click="insertMarkdown('heading')" title="標題"><strong>H</strong></el-button><el-button size="small" @click="insertMarkdown('bold')" title="加粗"><strong>B</strong></el-button><el-button size="small" @click="insertMarkdown('italic')" title="斜體"><em>I</em></el-button><el-button size="small" @click="insertMarkdown('quote')" title="引用"><el-icon><ChatLineSquare /></el-icon></el-button><el-button size="small" @click="insertMarkdown('code')" title="代碼"><el-icon><Notebook /></el-icon></el-button><el-button size="small" @click="insertMarkdown('link')" title="鏈接"><el-icon><Link /></el-icon></el-button><el-button size="small" @click="insertMarkdown('image')" title="圖片"><el-icon><Picture /></el-icon></el-button><el-button size="small" @click="insertMarkdown('list')" title="列表"><el-icon><List /></el-icon></el-button></el-button-group><!-- 預覽控制 --><el-button-group><el-button size="small" @click="togglePreview" title="預覽模式" :type="isPreviewMode ? 'primary' : ''"class="preview-button"><el-icon><View /></el-icon>預覽</el-button></el-button-group></div></div></template><el-input v-model="markdownContent" type="textarea" :rows="20" placeholder="請輸入 Markdown 內容..."@input="handleContentChange" /></el-card></div><!-- HTML 預覽區域 --><div class="preview-container"><el-card class="preview-card"><template #header><div class="header"><div><span v-show="!isPreviewMode">HTML 預覽</span><el-button v-show="isPreviewMode" size="small" @click="togglePreview" title="退出預覽"class="preview-exit-button"><el-icon><Close /></el-icon>退出預覽</el-button></div><div style="display: flex; gap: 10px;align-items: center;"><!-- 預覽頁面導出為圖片 --><!-- <div class="export-img"><el-button size="small" @click="exportImg" title="下載png圖片"><el-icon><Download /></el-icon></el-button></div> --></div></div></template><div class="preview-content"><div class="card" ref="card"><div class="card-header"></div><div class="card-content"><div class="card-content-inner" v-html="htmlContent"></div></div><div class="card-footer"></div></div></div></el-card></div><div><!-- 樣式選擇區 --><el-card class="style-card"><template #header><div class="header"><span>style 選擇</span><el-button @click="handleAddStyle" size="small" title="添加樣式"class="preview-exit-button"><el-icon><Close /></el-icon>添加樣式</el-button></div></template><!-- 樣式列表 --><div class="style-content"><divv-for="style in styleList":key="style.value"class="style-item":class="{ 'active': currentStyle === style.value }"@click="setStyle(style.value)">{{ style.name }}</div></div></el-card></div></div><!-- 添加樣式彈窗 --><AddStyleDialog ref="addStyleDialogRef" @confirm="handleStyleConfirm" @preview="handleStylePreview"></AddStyleDialog></div>
</template><script setup lang="ts">
import AddStyleDialog from './components/AddStyleDialog.vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { ref, onMounted, reactive,onUnmounted } from 'vue'
import { marked } from 'marked'
import {Download, ChatLineSquare, Notebook, Link,Picture, List, View, FullScreen
} from '@element-plus/icons-vue'const addStyleDialogRef = ref()
const editorContainerRef = ref<HTMLElement>()
const addedStyles = ref<{name: string; element: HTMLStyleElement}[]>([])const handleAddStyle = () => {addStyleDialogRef.value?.open()
}// 確認添加樣式
const handleStyleConfirm = () => {}// 預覽樣式
const handleStylePreview = (styleData: { name: string; code: string }) => {currentStyle.value = ''// 移除所有舊的樣式標簽const oldStyles = document.querySelectorAll('style[data-md-style]')oldStyles.forEach(style => style.remove())// 創建新的樣式標簽const styleTag = document.createElement('style')styleTag.type = 'text/css'styleTag.setAttribute('data-md-style', 'true') // 添加標識,方便后續刪除// 根據選擇的樣式設置內容styleTag.innerHTML = styleData.code// 插入到頁面頭部document.head.appendChild(styleTag)
}// 樣式列表
const styleList = [{name: '樣式1',value: 'style1'},{name: '樣式2',value: 'style2'}
]// 編輯器狀態
const markdownContent = ref('')
const currentStyle = ref('style1') // 默認選擇樣式1
const htmlContent = ref('')
const textareaRef = ref<HTMLTextAreaElement | null>(null)
const card: any = ref('')
const isPreviewMode = ref(false)
const isFullscreen = ref(false)// 編輯歷史
const history = reactive({past: [] as string[],future: [] as string[]
})// 文件操作函數
const exportFile = () => {const blob = new Blob([markdownContent.value], { type: 'text/markdown' })const url = URL.createObjectURL(blob)const a = document.createElement('a')a.href = urla.download = 'markdown.md'a.click()URL.revokeObjectURL(url)
}// 編輯歷史操作
const saveHistory = () => {history.past.push(markdownContent.value)history.future = []if (history.past.length > 50) {history.past.shift()}
}// 預覽控制
const togglePreview = () => {isPreviewMode.value = !isPreviewMode.value
}const toggleFullscreen = () => {const element = document.documentElementif (!isFullscreen.value) {if (element.requestFullscreen) {element.requestFullscreen()}} else {if (document.exitFullscreen) {document.exitFullscreen()}}isFullscreen.value = !isFullscreen.value
}let cssData1 = `
.card {max-width: 420px;background: #ffffff;border-radius: 16px;overflow: hidden;box-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);font-family: 'PingFang SC', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', sans-serif;line-height: 1.65;color: #333;margin: 24px auto;transition: all 0.3s ease;
}.card:hover {transform: translateY(-4px);box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}.card-header {background: #ff2442;height: 6px;border-radius: 16px 16px 0 0;
}.card-content {padding: 32px;
}.card-content-inner {padding: 0;
}.card-content-inner > *:first-child {margin-top: 0;
}.card-content-inner > *:last-child {margin-bottom: 0;
}.card-content-inner h1 {font-size: 24px;font-weight: 700;margin: 0 0 24px;color: #1a1a1a;letter-spacing: -0.2px;line-height: 1.4;position: relative;padding-bottom: 16px;
}.card-content-inner h1:after {content: "";position: absolute;bottom: 0;left: 0;width: 36px;height: 3px;background: #ff2442;border-radius: 2px;
}.card-content-inner h2 {font-size: 20px;font-weight: 600;margin: 32px 0 20px;color: #2c2c2c;padding-bottom: 8px;border-bottom: 1px solid #f5f5f5;
}.card-content-inner p {font-size: 16px;margin: 0 0 24px;color: #444;text-align: justify;hyphens: auto;
}.card-content-inner ol,
.card-content-inner ul {padding-left: 24px;margin: 0 0 24px;
}.card-content-inner ol li,
.card-content-inner ul li {margin-bottom: 12px;padding-left: 8px;
}.card-content-inner ol li {position: relative;counter-increment: list-counter;
}.card-content-inner ol li::before {content: counter(list-counter);position: absolute;left: -26px;top: 2px;width: 20px;height: 20px;background: #ffebee;color: #ff2442;border-radius: 50%;display: flex;align-items: center;justify-content: center;font-size: 12px;font-weight: 600;
}.card-content-inner ul li::before {content: "?";color: #ff2442;font-weight: bold;display: inline-block;width: 1em;margin-left: -1em;
}.card-content-inner strong {color: #ff2442;font-weight: 600;
}.card-content-inner a {color: #ff2442;text-decoration: none;border-bottom: 1px solid rgba(255, 36, 66, 0.3);transition: all 0.2s ease;
}.card-content-inner a:hover {color: #e01e3c;border-bottom-color: #e01e3c;
}.card-content-inner code {background: #fff0f2;padding: 2px 6px;border-radius: 4px;font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;font-size: 14px;color: #ff2442;
}.card-content-inner pre {background: #fffafb;padding: 18px;border-radius: 8px;overflow-x: auto;margin: 0 0 24px;font-size: 14px;line-height: 1.5;border-left: 3px solid #ff2442;
}.card-content-inner pre code {background: none;padding: 0;color: #444;font-size: 14px;
}.card-content-inner blockquote {border-left: 3px solid #ffcdd2;padding: 4px 20px 4px 20px;margin: 0 0 24px;color: #666;background: #fffafa;border-radius: 0 8px 8px 0;font-style: italic;
}.card-content-inner hr {border: 0;height: 1px;background: linear-gradient(to right, rgba(255, 36, 66, 0.1), transparent);margin: 32px 0;
}.card-footer {padding: 16px 32px;background: #fffafa;border-top: 1px solid #f9f0f0;color: #999;font-size: 13px;display: flex;justify-content: space-between;
}/* 小紅書特色元素 */
.card-content-inner h1 + p {font-size: 17px;color: #666;margin-top: -8px;margin-bottom: 28px;
}.card-content-inner img {max-width: 100%;border-radius: 12px;margin: 24px 0;display: block;box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
}/* 留白增強 */
.card-content-inner p + h2 {margin-top: 36px;
}.card-content-inner ul + h2,
.card-content-inner ol + h2 {margin-top: 40px;
}
`
let cssData2 = `
.card {max-width: 680px;background: #ffffff;border-radius: 12px;overflow: hidden;box-shadow: 0 8px 30px rgba(0, 0, 0, 0.06);font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, sans-serif;line-height: 1.7;color: #333;margin: 40px auto;transition: transform 0.3s ease;
}.card:hover {transform: translateY(-3px);
}.card-header {background: linear-gradient(135deg, #6e8efb, #a777e3);height: 6px;border-radius: 12px 12px 0 0;
}.card-content {padding: 40px;
}.card-content-inner {padding: 0;
}.card-content-inner > *:first-child {margin-top: 0;
}.card-content-inner > *:last-child {margin-bottom: 0;
}.card-content-inner h1 {font-size: 28px;font-weight: 700;margin: 0 0 30px;color: #1a1a1a;letter-spacing: -0.01em;line-height: 1.3;
}.card-content-inner h2 {font-size: 22px;font-weight: 600;margin: 40px 0 20px;color: #2c2c2c;padding-bottom: 8px;border-bottom: 1px solid #f0f0f0;
}.card-content-inner h3 {font-size: 18px;font-weight: 600;margin: 35px 0 15px;color: #3a3a3a;
}.card-content-inner p {font-size: 17px;margin: 0 0 28px;color: #444;text-align: justify;hyphens: auto;
}.card-content-inner ol,
.card-content-inner ul {padding-left: 24px;margin: 0 0 28px;
}.card-content-inner ol li,
.card-content-inner ul li {margin-bottom: 12px;padding-left: 12px;
}.card-content-inner ol li {position: relative;counter-increment: list-counter;
}.card-content-inner ol li::before {content: counter(list-counter);position: absolute;left: -24px;top: 0;width: 24px;height: 24px;background: #f5f7ff;color: #6e8efb;border-radius: 50%;display: flex;align-items: center;justify-content: center;font-size: 13px;font-weight: 500;
}.card-content-inner ul li::before {content: "?";color: #a777e3;font-weight: bold;display: inline-block;width: 1em;margin-left: -1em;
}.card-content-inner strong {color: #2c2c2c;font-weight: 600;
}.card-content-inner em {font-style: italic;color: #555;
}.card-content-inner a {color: #6e8efb;text-decoration: none;border-bottom: 1px solid rgba(110, 142, 251, 0.3);transition: all 0.2s ease;
}.card-content-inner a:hover {color: #a777e3;border-bottom-color: #a777e3;
}.card-content-inner code {background: #f8f9ff;padding: 3px 6px;border-radius: 4px;font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;font-size: 15px;color: #6e8efb;
}.card-content-inner pre {background: #f8f9ff;padding: 20px;border-radius: 8px;overflow-x: auto;margin: 0 0 30px;font-size: 15px;line-height: 1.5;border-left: 3px solid #a777e3;
}.card-content-inner pre code {background: none;padding: 0;color: #444;font-size: 15px;
}.card-content-inner blockquote {border-left: 3px solid #e0e0e0;padding: 4px 20px 4px 24px;margin: 0 0 30px;color: #555;font-style: italic;background: #fafbff;border-radius: 0 8px 8px 0;
}.card-content-inner hr {border: 0;height: 1px;background: #f0f0f0;margin: 40px 0;
}.card-footer {padding: 20px 40px;background: #fafbff;border-top: 1px solid #f0f0f0;color: #777;font-size: 14px;display: flex;justify-content: space-between;
}/* 留白增強 */
.card-content-inner p + h2,
.card-content-inner ul + h2,
.card-content-inner ol + h2 {margin-top: 50px;
}.card-content-inner p + h3 {margin-top: 40px;
}.card-content-inner img {max-width: 100%;border-radius: 8px;margin: 30px 0;display: block;
}
`
const setStyle = (e:any) => {currentStyle.value = e// 移除所有舊的樣式標簽const oldStyles = document.querySelectorAll('style[data-md-style]')oldStyles.forEach(style => style.remove())// 創建新的樣式標簽const styleTag = document.createElement('style')styleTag.type = 'text/css'styleTag.setAttribute('data-md-style', 'true') // 添加標識,方便后續刪除// 根據選擇的樣式設置內容styleTag.innerHTML = currentStyle.value === 'style1' ? cssData1 : cssData2// 插入到頁面頭部document.head.appendChild(styleTag)
}// 配置marked選項
marked.setOptions({breaks: true, // 將回車轉換為 <br>gfm: true, // 啟用 GitHub 風格的 Markdown// sanitize: false, // 允許HTML標簽
})// 使用marked進行Markdown轉HTML
const convertMarkdownToHtml = (markdown: string): any => {return marked(markdown)
}// 處理內容變化
const handleContentChange = () => {saveHistory()updatePreview()
}// 更新預覽
const updatePreview = () => {htmlContent.value = convertMarkdownToHtml(markdownContent.value)
}// 在光標位置插入Markdown語法
const insertMarkdown = (type: string) => {const textarea = document.querySelector('.el-textarea__inner') as HTMLTextAreaElementif (!textarea) returnconst start = textarea.selectionStartconst end = textarea.selectionEndconst selected = markdownContent.value.substring(start, end)let insertion = ''switch (type) {case 'bold':insertion = `**${selected || '粗體文本'}**`breakcase 'italic':insertion = `*${selected || '斜體文本'}*`breakcase 'heading':insertion = `\n## ${selected || '標題'}\n`breakcase 'link':insertion = `[${selected || '鏈接文本'}](https://example.com)`breakcase 'list':insertion = `\n- ${selected || '列表項'}\n- 列表項\n- 列表項\n`breakcase 'quote':insertion = `\n> ${selected || '引用文本'}\n`breakcase 'code':insertion = selected ?`\`\`\`\n${selected}\n\`\`\`` :`\`\`\`\n代碼塊\n\`\`\``breakcase 'image':insertion = ``breakdefault:return}const newContent =markdownContent.value.substring(0, start) +insertion +markdownContent.value.substring(end)markdownContent.value = newContent// 保存歷史記錄saveHistory()// 更新預覽updatePreview()// 聚焦回文本區域setTimeout(() => {textarea.focus()const newCursorPos = start + insertion.lengthtextarea.setSelectionRange(newCursorPos, newCursorPos)}, 0)
}// 復制HTML到剪貼板
const copyHtml = () => {navigator.clipboard.writeText(htmlContent.value).then(() => {ElMessage({message: 'HTML已復制到剪貼板',type: 'success',duration: 2000})}).catch(err => {ElMessage({message: '復制失敗: ' + err,type: 'error',duration: 2000})})
}// 組件掛載時初始化
onMounted(() => {// 設置示例Markdown內容markdownContent.value = `# MD2Card> MD2Card 是一個 markdown 轉知識卡片工具,可以讓你用 Markdown 制作優雅的圖文海報。 🌟## 它的主要功能:1. 將 Markdown 轉化為**知識卡片**
2. 多種主題風格任你選擇
3. 長文自動拆分,或者根據 markdown --- 橫線拆分
4. 可以復制圖片到剪貼板,或者下載為PNG、SVG圖片
5. 所見即所得
6. 免費
`updatePreview()// 初始化應用默認樣式setStyle(currentStyle.value)
})onUnmounted(()=>{// 移除所有的樣式標簽const oldStyles = document.querySelectorAll('style[data-md-style]')oldStyles.forEach(style => style.remove())
})
</script><style scoped lang="scss">
.markdown-editor {height: calc(100vh - 40px);box-sizing: border-box;overflow: hidden;
}.markdown-editor.fullscreen {position: fixed;top: 0;left: 0;right: 0;bottom: 0;z-index: 9999;padding: 0;
}.editor-container {height: 100%;display: flex;.markdown-input,.preview-container {flex: 1;height: 100%;overflow-y: auto;}.style-card{width: 260px;}
}.editor-card,
.preview-card,
.style-card {height: 100%;position: relative;transition: all 0.3s ease;display: flex;flex-direction: column;.preview-content{height: auto;}:deep(.el-card__body) {flex: 1;overflow: auto;padding: 0;display: flex;flex-direction: column;}/* Editor card specific styles */&.editor-card {:deep(.el-textarea) {flex: 1;display: flex;flex-direction: column;.el-textarea__inner {flex: 1;resize: none;border: none;box-shadow: none;padding: 20px;}}}/* Preview card specific styles */&.preview-card {height: 100%;:deep(.el-card__body) {// height: 100%;// overflow: auto;padding: 0;display: flex;flex-direction: column;}.card {flex: 1;min-height: 0; /* 修復flex容器滾動問題 */padding: 20px;}.card-content {height: auto;}}/* Style card specific styles */&.style-card {.style-content {flex: 1;overflow: auto;padding: 10px;.style-item {padding: 8px 12px;margin-bottom: 8px;border: 1px solid #e0deed;color: #0f0a29;background: #fff;border-radius: 4px;cursor: pointer;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;transition: all 0.2s ease;&:hover {border-color: #a598e5;}&.active {border-color: #4c33cc;color: #4c33cc;background: #f6f5fc;font-weight: 500;}}}}
}.header {display: flex;justify-content: space-between;align-items: center;
}.toolbar {display: flex;gap: 10px;
}/* 工具欄按鈕組之間的分隔 */
.toolbar .el-button-group+.el-button-group {margin-left: 8px;padding-left: 8px;border-left: 1px solid #dcdfe6;
}/* 激活狀態的按鈕樣式 */
:deep(.el-button--primary) {background-color: var(--el-color-primary-light-3);border-color: var(--el-color-primary-light-3);color: #fff;
}/* 預覽模式下的布局調整 */
.preview-button {z-index: 1000;
}.preview-mode {:deep(.el-row) {.el-col:first-child {display: none;}.el-col:last-child {width: 100%;position: relative;.preview-exit-button {position: absolute;top: 76px;left: 26px;z-index: 2000;background-color: #fff;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);color: var(--el-text-color-primary);&:hover {background-color: var(--el-color-primary-light-9);}}}}.header .preview-button {display: none;}
}/* 預覽按鈕樣式 */
.preview-button {margin-right: 10px;
}/* 預覽模式下的退出按鈕樣式 */
.preview-exit-button {/* position: absolute;top: 10px;left: 10px;z-index: 2000; */background-color: #fff;box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);color: var(--el-text-color-primary);&:hover {background-color: var(--el-color-primary-light-9);}
}/* 全屏模式下的樣式調整 */
.fullscreen {:deep(.el-main) {padding: 0;}.editor-card,.preview-card {border-radius: 0;}
}/* 響應式布局 */
@media screen and (max-width: 768px) {.toolbar {flex-wrap: wrap;}.toolbar .el-button-group {margin-bottom: 8px;}.header {flex-direction: column;align-items: flex-start;gap: 10px;}
}
</style>
添加彈窗
<template><el-dialog v-model="dialogVisible" title="添加CSS樣式" width="700px" top="5vh"><div class="css-editor-container"><!-- 樣式名稱輸入框 --><el-inputv-model="styleName"placeholder="樣式名稱(如:my-style)"style="margin-bottom: 15px"/><!-- 帶有基本語法高亮的 CSS 編輯器 --><div class="code-editor-wrapper"><textareav-model="cssCode"@input="updateHighlight"class="code-input"spellcheck="false"placeholder="請輸入CSS代碼..."></textarea></div></div><!-- 底部按鈕 --><template #footer><span class="dialog-footer"><el-button @click="handlePreview">預覽</el-button><el-button type="primary" @click="handleConfirm">確認</el-button></span></template></el-dialog>
</template><script setup>
import { ref, computed } from 'vue'const dialogVisible = ref(false)
const styleName = ref('')
const cssCode = ref('')const updateHighlight = () => {// 自動更新高亮
}// 打開對話框
const open = () => {dialogVisible.value = truecssCode.value = ''styleName.value = ''
}// 確認按鈕處理函數
const emit = defineEmits(['confirm','preview'])
const handleConfirm = () => {// 打印輸入的CSS樣式和樣式名稱console.log('樣式名稱:', styleName.value)console.log('CSS樣式:', cssCode.value)// // 觸發confirm事件,將數據傳遞給父組件// emit('confirm', {// name: styleName.value.trim(),// code: cssCode.value.trim()// })// // 關閉對話框// dialogVisible.value = false
}const handlePreview = () => {// 預覽CSS樣式console.log('預覽CSS樣式:', cssCode.value)// // 觸發confirm事件,將數據傳遞給父組件emit('preview', {name: styleName.value.trim(),code: cssCode.value.trim()})// 關閉對話框dialogVisible.value = false
}defineExpose({ open })
</script><style scoped>
.css-editor-container {display: flex;flex-direction: column;
}.code-editor-wrapper {position: relative;height: 300px;border: 1px solid #dcdfe6;border-radius: 4px;overflow: hidden;margin-bottom: 15px;
}.code-highlight {position: absolute;top: 0;left: 0;width: 100%;height: 100%;margin: 0;padding: 10px;font-family: 'Courier New', monospace;font-size: 14px;line-height: 1.5;white-space: pre-wrap;word-wrap: break-word;overflow: auto;background: #f5f7fa;pointer-events: none;z-index: 1;
}.code-input {position: absolute;top: 0;left: 0;width: 100%;height: 100%;margin: 0;padding: 10px;font-family: 'Courier New', monospace;font-size: 14px;line-height: 1.5;color: #333;background: transparent;border: none;outline: none;resize: none;z-index: 2;
}/* 語法高亮樣式 */
.comment {color: #999;font-style: italic;
}.punctuation {color: #333;
}.selector {color: #905;
}.property {color: #07a;
}.value {color: #690;
}.dialog-footer {display: flex;justify-content: flex-end;gap: 10px;
}
</style>
注:
這是一個靜態的功能參考,在這里的樣式使用的給定的樣式切換,后續對接接口后可換成一個下拉列表,選擇后通過接口返回的css樣式數據來更換一樣的效果。這里預想的是回臺直接返回樣式的一個字符串格式內容,其他的想法可自行修改。
這里的css樣式只是使用了一個文本輸入框實現了功能效果,不帶樣式代碼高亮顯示的功能
樣式可使用deepseek來生成
復制這段文字,修改生成條件就可生成不同的樣式的css代碼,直接粘貼到css代碼輸入框中,點擊預覽就可看到新css樣式的效果。
/*
可以讓 deepseek 等大模型實現css,實現卡片樣式自定義,以下是發送的提示詞模板:我需要在 md2card.com 實現自定義小紅書卡片樣式
以下是 md2card.com 中卡片的HTML結構:
```html
<div class="card"><div class="card-header"></div><div class="card-content"><div class="card-content-inner"><h1 data-text="標題">標題</h1><h2 data-text="標題二">標題二</h2><p>內容</p><ol><li data-index="0">列表</li></ol></div></div><div class="card-footer"></div>
</div>`card-content-inner` 為 markdown 編譯后的內容區域,還包括標題、列表、引用、代碼、加粗等常見 markdown 編譯的內容請為我設計一張卡片,其風格為“簡約現代”,可以進一步融入“留白”的設計理念,應用“小紅書知識分享”的場景
【設計風格要求】:
【輸入要求】:只需要返回 css 代碼*/
.card {
}