add mermaid
This commit is contained in:
parent
d6a1a3e67b
commit
700fc80bc5
117
src/main.rs
117
src/main.rs
@ -218,52 +218,67 @@ fn markdown_to_html(markdown: &str, ss: &SyntaxSet, ts: &ThemeSet, file_path: &s
|
|||||||
Event::End(Tag::CodeBlock(_)) => {
|
Event::End(Tag::CodeBlock(_)) => {
|
||||||
in_code_block = false;
|
in_code_block = false;
|
||||||
|
|
||||||
// Определяем отображаемое имя языка
|
// Проверка на Mermaid
|
||||||
let lang_display = current_lang.as_deref().unwrap_or("text");
|
let is_mermaid = current_lang.as_deref() == Some("mermaid");
|
||||||
|
|
||||||
// Экранируем имя языка для HTML атрибута и текста
|
if is_mermaid {
|
||||||
let lang_escaped = escape_html(lang_display);
|
// Для Mermaid просто экранируем контент и оборачиваем в div
|
||||||
|
// Кнопка копирования тоже нужна
|
||||||
|
let escaped_code = escape_html(¤t_code);
|
||||||
|
let mermaid_html = format!(
|
||||||
|
r#"<div class="code-block-wrapper mermaid-wrapper">
|
||||||
|
<div class="code-header">
|
||||||
|
<span class="code-lang">Mermaid Diagram</span>
|
||||||
|
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
|
||||||
|
</div>
|
||||||
|
<div class="mermaid" style="background: transparent; padding: 20px; text-align: center;">{}</div>
|
||||||
|
</div>"#,
|
||||||
|
escaped_code
|
||||||
|
);
|
||||||
|
processed_events.push(Event::Html(mermaid_html.into()));
|
||||||
|
} else {
|
||||||
|
// Обычная обработка кода с подсветкой
|
||||||
|
let lang_display = current_lang.as_deref().unwrap_or("text");
|
||||||
|
let lang_escaped = escape_html(lang_display);
|
||||||
|
|
||||||
// Подсветка синтаксиса (построчно)
|
let highlighted_html = if let Some(lang) = ¤t_lang {
|
||||||
let highlighted_html = if let Some(lang) = ¤t_lang {
|
if let Some(syntax) = ss.find_syntax_by_token(lang) {
|
||||||
if let Some(syntax) = ss.find_syntax_by_token(lang) {
|
let mut h = HighlightLines::new(syntax, theme);
|
||||||
let mut h = HighlightLines::new(syntax, theme);
|
let mut result_html = String::new();
|
||||||
let mut result_html = String::new();
|
|
||||||
|
|
||||||
for line in current_code.lines() {
|
for line in current_code.lines() {
|
||||||
let line_with_newline = format!("{}\n", line);
|
let line_with_newline = format!("{}\n", line);
|
||||||
match h.highlight_line(&line_with_newline, ss) {
|
match h.highlight_line(&line_with_newline, ss) {
|
||||||
Ok(regions) => {
|
Ok(regions) => {
|
||||||
let html_line = styled_line_to_highlighted_html(®ions[..], IncludeBackground::No)
|
let html_line = styled_line_to_highlighted_html(®ions[..], IncludeBackground::No)
|
||||||
.unwrap_or_else(|_| escape_html(&line_with_newline));
|
.unwrap_or_else(|_| escape_html(&line_with_newline));
|
||||||
result_html.push_str(&html_line);
|
result_html.push_str(&html_line);
|
||||||
},
|
},
|
||||||
Err(_) => result_html.push_str(&escape_html(&line_with_newline)),
|
Err(_) => result_html.push_str(&escape_html(&line_with_newline)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
result_html
|
||||||
|
} else {
|
||||||
|
escape_html(¤t_code)
|
||||||
}
|
}
|
||||||
result_html
|
|
||||||
} else {
|
} else {
|
||||||
escape_html(¤t_code)
|
escape_html(¤t_code)
|
||||||
}
|
};
|
||||||
} else {
|
|
||||||
escape_html(¤t_code)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Формируем HTML с заголовком и кнопкой копирования
|
let code_container = format!(
|
||||||
// Мы экранируем current_code еще раз для data-атрибута, хотя для копирования будем брать текст из pre
|
r#"<div class="code-block-wrapper">
|
||||||
let code_container = format!(
|
<div class="code-header">
|
||||||
r#"<div class="code-block-wrapper">
|
<span class="code-lang">{}</span>
|
||||||
<div class="code-header">
|
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
|
||||||
<span class="code-lang">{}</span>
|
</div>
|
||||||
<button class="copy-btn" onclick="copyCode(this)">Copy</button>
|
<pre style="margin: 0; border-radius: 0 0 6px 6px;"><code>{}</code></pre>
|
||||||
</div>
|
</div>"#,
|
||||||
<pre style="margin: 0; border-radius: 0 0 6px 6px;"><code>{}</code></pre>
|
lang_escaped,
|
||||||
</div>"#,
|
highlighted_html
|
||||||
lang_escaped,
|
);
|
||||||
highlighted_html
|
|
||||||
);
|
|
||||||
|
|
||||||
processed_events.push(Event::Html(code_container.into()));
|
processed_events.push(Event::Html(code_container.into()));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Event::Text(text) if in_code_block => {
|
Event::Text(text) if in_code_block => {
|
||||||
current_code.push_str(&text);
|
current_code.push_str(&text);
|
||||||
@ -288,6 +303,8 @@ fn markdown_to_html(markdown: &str, ss: &SyntaxSet, ts: &ThemeSet, file_path: &s
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Markdown Preview</title>
|
<title>Markdown Preview</title>
|
||||||
|
<!-- Подключаем Mermaid JS -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
|
||||||
<style>
|
<style>
|
||||||
body {{ background-color: #121212; color: #e0e0e0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; margin: 0; padding: 40px 20px; display: flex; justify-content: center; line-height: 1.6; }}
|
body {{ background-color: #121212; color: #e0e0e0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; margin: 0; padding: 40px 20px; display: flex; justify-content: center; line-height: 1.6; }}
|
||||||
.content {{ max-width: 800px; width: 100%; background-color: #1e1e1e; padding: 40px; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.5); }}
|
.content {{ max-width: 800px; width: 100%; background-color: #1e1e1e; padding: 40px; border-radius: 12px; box-shadow: 0 4px 20px rgba(0,0,0,0.5); }}
|
||||||
@ -356,6 +373,16 @@ fn markdown_to_html(markdown: &str, ss: &SyntaxSet, ts: &ThemeSet, file_path: &s
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
/* Специфичные стили для Mermaid */
|
||||||
|
.mermaid-wrapper .mermaid {{
|
||||||
|
background-color: #f9f9f9; /* Светлый фон для контраста диаграммы */
|
||||||
|
border-radius: 0 0 6px 6px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}}
|
||||||
|
/* Принудительная темная тема для SVG внутри mermaid, если нужно,
|
||||||
|
но лучше использовать конфиг mermaid.init ниже */
|
||||||
|
|
||||||
#status {{ position: fixed; top: 10px; right: 10px; padding: 5px 10px; border-radius: 4px; font-size: 12px; font-weight: bold; }}
|
#status {{ position: fixed; top: 10px; right: 10px; padding: 5px 10px; border-radius: 4px; font-size: 12px; font-weight: bold; }}
|
||||||
.connected {{ background-color: #2ecc71; color: #000; }}
|
.connected {{ background-color: #2ecc71; color: #000; }}
|
||||||
.disconnected {{ background-color: #e74c3c; color: #fff; }}
|
.disconnected {{ background-color: #e74c3c; color: #fff; }}
|
||||||
@ -387,15 +414,14 @@ fn markdown_to_html(markdown: &str, ss: &SyntaxSet, ts: &ThemeSet, file_path: &s
|
|||||||
connect();
|
connect();
|
||||||
|
|
||||||
function copyCode(button) {{
|
function copyCode(button) {{
|
||||||
// Находим обертку, затем pre внутри неё
|
|
||||||
const wrapper = button.closest('.code-block-wrapper');
|
const wrapper = button.closest('.code-block-wrapper');
|
||||||
if (!wrapper) return;
|
if (!wrapper) return;
|
||||||
|
|
||||||
const pre = wrapper.querySelector('pre');
|
// Для mermaid берем текст из div.mermaid, для кода из pre
|
||||||
if (!pre) return;
|
const target = wrapper.querySelector('pre') || wrapper.querySelector('.mermaid');
|
||||||
|
if (!target) return;
|
||||||
|
|
||||||
// Получаем текстовое содержимое (без HTML тегов подсветки)
|
const codeText = target.innerText;
|
||||||
const codeText = pre.innerText;
|
|
||||||
|
|
||||||
navigator.clipboard.writeText(codeText).then(() => {{
|
navigator.clipboard.writeText(codeText).then(() => {{
|
||||||
const originalText = button.innerText;
|
const originalText = button.innerText;
|
||||||
@ -413,6 +439,13 @@ fn markdown_to_html(markdown: &str, ss: &SyntaxSet, ts: &ThemeSet, file_path: &s
|
|||||||
button.innerText = 'Error';
|
button.innerText = 'Error';
|
||||||
}});
|
}});
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
// Инициализация Mermaid с темной темой
|
||||||
|
mermaid.initialize({{
|
||||||
|
startOnLoad: true,
|
||||||
|
theme: 'dark',
|
||||||
|
securityLevel: 'loose',
|
||||||
|
}});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>"#,
|
</html>"#,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user