// import highlight from 'highlight.js';
|
import hljs from 'highlight.js';
|
import Markdown from 'markdown-it';
|
// 导入 highlight.js 的样式,这里使用 github 主题
|
import 'highlight.js/styles/github.css';
|
|
const md = new Markdown({
|
linkify: true,
|
typographer: true,
|
breaks: true,
|
langPrefix: 'language-',
|
highlight: (str: string, lang: string) => {
|
if (lang && hljs.getLanguage(lang)) {
|
try {
|
return hljs.highlight(str, { language: lang }).value;
|
} catch {
|
return str;
|
}
|
}
|
return str;
|
},
|
});
|
|
// 自定义代码块渲染
|
md.renderer.rules.fence = (tokens, idx, options, env, slf) => {
|
const token = tokens[idx];
|
const lang = token.info || '';
|
const highlighted = options.highlight?.(token.content, lang, '') || token.content;
|
return `
|
<div class="code-markdown-it-block">
|
<div class="code-markdown-it-header">
|
<div class="code-markdown-it-header-left">
|
<span class="code-markdown-it-lang">${lang}</span>
|
</div>
|
<div class="code-markdown-it-header-right">
|
<button title="复制" class="code-markdown-it-copy" onclick="this.classList.add('copied'); setTimeout(() => this.classList.remove('copied'), 1500); navigator.clipboard.writeText(this.parentElement.parentElement.nextElementSibling.textContent)">
|
<svg class="copy-icon" viewBox="0 0 16 16" width="16" height="16">
|
<path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path>
|
<path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
|
</svg>
|
<svg class="check-icon" viewBox="0 0 16 16" width="16" height="16">
|
<path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.75.75 0 0 1 1.06-1.06L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path>
|
</svg>
|
</button>
|
<button title="展开" class="code-markdown-it-toggle" onclick="const block = this.parentElement.parentElement.parentElement; block.classList.toggle('collapsed'); this.title = block.classList.contains('collapsed') ? '展开' : '折叠'">
|
<svg class="expand-icon" viewBox="0 0 24 24" width="16" height="16">
|
<path d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"></path>
|
</svg>
|
</button>
|
</div>
|
</div>
|
<pre class="code-markdown-it-content"><code class="${options.langPrefix}${lang}">${highlighted}</code></pre>
|
</div>
|
`.trim();
|
};
|
|
// 添加自定义样式
|
const style = document.createElement('style');
|
// 自定义段落渲染规则
|
md.renderer.rules.paragraph_open = (tokens, idx) => {
|
return '<p class="inline-block">'; // 添加 inline-block 类来控制显示
|
};
|
style.textContent = `
|
.code-markdown-it-block {
|
margin: 1em 0;
|
border-radius: 6px;
|
overflow: hidden;
|
border: 1px solid #e1e4e8;
|
}
|
.code-markdown-it-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
padding: 8px 16px;
|
background: #f6f8fa;
|
border-bottom: 1px solid #e1e4e8;
|
}
|
.code-markdown-it-header-left {
|
display: flex;
|
align-items: center;
|
}
|
.code-markdown-it-header-right {
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
}
|
.code-markdown-it-lang {
|
font-size: 14px;
|
font-weight: 600;
|
color: #24292e;
|
// text-transform: uppercase;
|
}
|
.code-markdown-it-copy {
|
display: inline-flex;
|
align-items: center;
|
justify-content: center;
|
background: none;
|
border: none;
|
padding: 4px;
|
cursor: pointer;
|
color: #586069;
|
border-radius: 4px;
|
}
|
.code-markdown-it-copy:hover {
|
background: #f3f4f6;
|
color: #24292e;
|
}
|
.code-markdown-it-copy .check-icon {
|
display: none;
|
}
|
.code-markdown-it-copy.copied .copy-icon {
|
display: none;
|
}
|
.code-markdown-it-copy.copied .check-icon {
|
display: block;
|
color: #22863a;
|
}
|
.code-markdown-it-toggle {
|
background: none;
|
border: none;
|
padding: 4px;
|
cursor: pointer;
|
color: #586069;
|
display: flex;
|
align-items: center;
|
}
|
.code-markdown-it-toggle:hover {
|
color: #24292e;
|
}
|
.code-markdown-it-content {
|
margin: 0;
|
padding: 16px;
|
overflow-x: auto;
|
}
|
.code-markdown-it-block.collapsed .code-markdown-it-content {
|
display: none;
|
}
|
.code-markdown-it-block.collapsed .expand-icon {
|
transform: rotate(-90deg);
|
}
|
.expand-icon {
|
transition: transform 0.2s;
|
fill: currentColor;
|
}
|
.copy-icon, .check-icon {
|
fill: currentColor;
|
}
|
`;
|
document.head.appendChild(style);
|
export { md };
|