code layout
This commit is contained in:
		@@ -479,29 +479,63 @@ body {
 | 
				
			|||||||
    color: #656d76;
 | 
					    color: #656d76;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Molokai-inspired code blocks */
 | 
				
			||||||
.article-body pre {
 | 
					.article-body pre {
 | 
				
			||||||
    background: #f6f8fa;
 | 
					    background: #1B1D1E;
 | 
				
			||||||
    border: 1px solid #d1d9e0;
 | 
					    border: 1px solid #3E3D32;
 | 
				
			||||||
    border-radius: 6px;
 | 
					    border-radius: 8px;
 | 
				
			||||||
    padding: 16px;
 | 
					    padding: 0;
 | 
				
			||||||
    overflow-x: auto;
 | 
					    overflow: hidden;
 | 
				
			||||||
    margin: 16px 0;
 | 
					    margin: 16px 0;
 | 
				
			||||||
    font-size: 14px;
 | 
					    font-size: 14px;
 | 
				
			||||||
 | 
					    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.article-body code {
 | 
					/* Code filename header */
 | 
				
			||||||
    background: #f6f8fa;
 | 
					.article-body pre[data-filename]::before {
 | 
				
			||||||
    padding: 2px 4px;
 | 
					    content: attr(data-filename);
 | 
				
			||||||
    border-radius: 4px;
 | 
					    display: block;
 | 
				
			||||||
 | 
					    background: #272822;
 | 
				
			||||||
 | 
					    color: #A6E22E;
 | 
				
			||||||
 | 
					    padding: 8px 16px;
 | 
				
			||||||
 | 
					    border-bottom: 1px solid #3E3D32;
 | 
				
			||||||
    font-family: 'SF Mono', 'Monaco', 'Cascadia Code', 'Roboto Mono', monospace;
 | 
					    font-family: 'SF Mono', 'Monaco', 'Cascadia Code', 'Roboto Mono', monospace;
 | 
				
			||||||
    font-size: 14px;
 | 
					    font-size: 12px;
 | 
				
			||||||
 | 
					    font-weight: 500;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.article-body pre code {
 | 
					.article-body pre code {
 | 
				
			||||||
 | 
					    display: block;
 | 
				
			||||||
    background: none;
 | 
					    background: none;
 | 
				
			||||||
    padding: 0;
 | 
					    padding: 16px;
 | 
				
			||||||
 | 
					    color: #F8F8F2;
 | 
				
			||||||
 | 
					    font-family: 'SF Mono', 'Monaco', 'Cascadia Code', 'Roboto Mono', monospace;
 | 
				
			||||||
 | 
					    overflow-x: auto;
 | 
				
			||||||
 | 
					    line-height: 1.4;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Inline code */
 | 
				
			||||||
 | 
					.article-body code {
 | 
				
			||||||
 | 
					    background: #2F3129;
 | 
				
			||||||
 | 
					    color: #A6E22E;
 | 
				
			||||||
 | 
					    padding: 2px 6px;
 | 
				
			||||||
 | 
					    border-radius: 4px;
 | 
				
			||||||
 | 
					    font-family: 'SF Mono', 'Monaco', 'Cascadia Code', 'Roboto Mono', monospace;
 | 
				
			||||||
 | 
					    font-size: 13px;
 | 
				
			||||||
 | 
					    border: 1px solid #3E3D32;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Molokai color scheme for syntax highlighting */
 | 
				
			||||||
 | 
					.article-body pre code .hljs-keyword { color: #F92672; }
 | 
				
			||||||
 | 
					.article-body pre code .hljs-string { color: #E6DB74; }
 | 
				
			||||||
 | 
					.article-body pre code .hljs-comment { color: #75715E; font-style: italic; }
 | 
				
			||||||
 | 
					.article-body pre code .hljs-number { color: #AE81FF; }
 | 
				
			||||||
 | 
					.article-body pre code .hljs-variable { color: #FD971F; }
 | 
				
			||||||
 | 
					.article-body pre code .hljs-function { color: #A6E22E; }
 | 
				
			||||||
 | 
					.article-body pre code .hljs-tag { color: #F92672; }
 | 
				
			||||||
 | 
					.article-body pre code .hljs-attr { color: #A6E22E; }
 | 
				
			||||||
 | 
					.article-body pre code .hljs-value { color: #E6DB74; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Sidebar styles */
 | 
					/* Sidebar styles */
 | 
				
			||||||
.article-sidebar {
 | 
					.article-sidebar {
 | 
				
			||||||
    position: sticky;
 | 
					    position: sticky;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -92,8 +92,8 @@ impl MarkdownProcessor {
 | 
				
			|||||||
        for event in parser {
 | 
					        for event in parser {
 | 
				
			||||||
            match event {
 | 
					            match event {
 | 
				
			||||||
                pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(kind)) => {
 | 
					                pulldown_cmark::Event::Start(pulldown_cmark::Tag::CodeBlock(kind)) => {
 | 
				
			||||||
                    if let CodeBlockKind::Fenced(lang) = &kind {
 | 
					                    if let CodeBlockKind::Fenced(lang_info) = &kind {
 | 
				
			||||||
                        code_block = Some((String::new(), lang.to_string()));
 | 
					                        code_block = Some((String::new(), lang_info.to_string()));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                pulldown_cmark::Event::Text(text) => {
 | 
					                pulldown_cmark::Event::Text(text) => {
 | 
				
			||||||
@@ -104,8 +104,8 @@ impl MarkdownProcessor {
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                pulldown_cmark::Event::End(pulldown_cmark::TagEnd::CodeBlock) => {
 | 
					                pulldown_cmark::Event::End(pulldown_cmark::TagEnd::CodeBlock) => {
 | 
				
			||||||
                    if let Some((code, lang)) = code_block.take() {
 | 
					                    if let Some((code, lang_info)) = code_block.take() {
 | 
				
			||||||
                        let highlighted = self.highlight_code_block(&code, &lang, theme);
 | 
					                        let highlighted = self.highlight_code_block(&code, &lang_info, theme);
 | 
				
			||||||
                        events.push(pulldown_cmark::Event::Html(highlighted.into()));
 | 
					                        events.push(pulldown_cmark::Event::Html(highlighted.into()));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -117,13 +117,29 @@ impl MarkdownProcessor {
 | 
				
			|||||||
        Ok(html_output)
 | 
					        Ok(html_output)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn highlight_code_block(&self, code: &str, lang: &str, theme: &syntect::highlighting::Theme) -> String {
 | 
					    fn highlight_code_block(&self, code: &str, lang_info: &str, theme: &syntect::highlighting::Theme) -> String {
 | 
				
			||||||
 | 
					        // Parse language and filename from lang_info (e.g., "sh:/path/to/file" or "rust:main.rs")
 | 
				
			||||||
 | 
					        let (lang, filename) = if lang_info.contains(':') {
 | 
				
			||||||
 | 
					            let parts: Vec<&str> = lang_info.splitn(2, ':').collect();
 | 
				
			||||||
 | 
					            (parts[0], Some(parts[1]))
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            (lang_info, None)
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let syntax = self.syntax_set
 | 
					        let syntax = self.syntax_set
 | 
				
			||||||
            .find_syntax_by_token(lang)
 | 
					            .find_syntax_by_token(lang)
 | 
				
			||||||
            .unwrap_or_else(|| self.syntax_set.find_syntax_plain_text());
 | 
					            .unwrap_or_else(|| self.syntax_set.find_syntax_plain_text());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mut highlighter = syntect::easy::HighlightLines::new(syntax, theme);
 | 
					        let mut highlighter = syntect::easy::HighlightLines::new(syntax, theme);
 | 
				
			||||||
        let mut output = String::from("<pre><code>");
 | 
					        
 | 
				
			||||||
 | 
					        // Create pre tag with optional filename attribute
 | 
				
			||||||
 | 
					        let pre_tag = if let Some(filename) = filename {
 | 
				
			||||||
 | 
					            format!("<pre data-filename=\"{}\">", filename)
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            "<pre>".to_string()
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        let mut output = format!("{}<code>", pre_tag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for line in code.lines() {
 | 
					        for line in code.lines() {
 | 
				
			||||||
            let ranges = highlighter.highlight_line(line, &self.syntax_set).unwrap();
 | 
					            let ranges = highlighter.highlight_line(line, &self.syntax_set).unwrap();
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user