o
    Hiu                     @   sB  d Z ddlZddlZddlZddlmZ ddlZddlZddlZ	dgZ
e
D ]Ze	jedu r>ede  ede  q%ddlmZ ddlmZmZ dd	lmZ d%d
dZdd Zdd Zdd Zd&ddZd'ddZedkreejdk red ed ed ed e d ejd dkreejdkrejd ndZ!ee! dS ejd dkreejd k red! e d ejd Z"dZ#dZ$e%d eejD ]Z&eje& d"krd#Z#qeje& 'd$reje& Z$qee"e#e$ dS ejd Z(eejdkrejd ndZ)eejd krejd  ndZ$ee(e)e$ dS dS )(uO   
将 Markdown 文件转换为 HTML 格式
适用于 Python 3.7 及以上版本
    N)BeautifulSouppygmentsu   正在安装必要的依赖: zpip3 install )	highlight)get_lexer_by_name	TextLexer)HtmlFormatterc              
   C   s  t j| std|   dS |du rt j| d d }|du r-t jt j| d }ztj| ddd}| }W d   n1 sEw   Y  d|v pQd	|v }t	|}t
d
d|}tj|g dddddddddddd}t|}tddd}d| d|rd| d nd d| d}	|rt|}
|	d |
 d!| d"7 }	n|	d#| d"7 }	t|	d$}| }tj|d%dd}|| W d   n1 sw   Y  td&|  |W S  ty } ztd'|  ddl}|  W Y d}~dS d}~ww )(u  
    将 Markdown 文件转换为 HTML 文件
    
    参数:
        md_file_path (str): Markdown 文件路径
        html_file_path (str, optional): 输出的 HTML 文件路径，默认为与 md 文件同名但扩展名为 .html
        css_file_path (str, optional): CSS 文件路径，用于美化 HTML
        title (str, optional): HTML 文档的标题，默认使用文件名
        
    返回:
        str: 生成的 HTML 文件路径
    u"   错误: Markdown 文件不存在: Nr   z.htmlrutf-8encodingz[TOC]z[toc]z\[TOC\]|\[toc\] )zmarkdown.extensions.tableszmarkdown.extensions.fenced_codemarkdown.extensions.codehilitemarkdown.extensions.toczmarkdown.extensions.nl2brzmarkdown.extensions.sane_listsTFr   )use_pygments	noclasses	css_class   u   目录   )	permalink	baseleveltitle	toc_depth)r   r   )
extensionsextension_configsdefaultstylez
.highlightz<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>z</title>
    z<link rel="stylesheet" href="">u  
    <style>
        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
            line-height: 1.6;
            padding: 0;
            margin: 0;
            color: #333;
            display: flex;
        }
        
        /* 目录样式 */
        .toc-container {
            width: 320px;
            height: 100vh;
            overflow-y: auto;
            position: sticky;
            top: 0;
            padding: 20px;
            background-color: #f8f9fa;
            border-right: 1px solid #e1e4e8;
            box-sizing: border-box;
        }
        
        .toc-container .toc {
            margin: 0;
            padding: 0;
        }
        
        .toc-container .toc ul {
            list-style-type: none;
            padding-left: 20px;
        }
        
        .toc-container .toc > ul {
            padding-left: 0;
        }
        
        .toc-container .toc li {
            margin: 8px 0;
        }
        
        .toc-container .toc a {
            color: #4a86e8;
            text-decoration: none;
            font-size: 14px;
            display: block;
            padding: 3px 0;
            border-left: 2px solid transparent;
            padding-left: 10px;
            transition: all 0.2s ease;
        }
        
        .toc-container .toc a:hover {
            border-left-color: #4a86e8;
            background-color: rgba(74, 134, 232, 0.1);
        }
        
        /* 顶部链接样式 */
        .toc-container .toc .toc-top-link {
            font-weight: bold;
            font-size: 16px;
            color: #333;
            padding: 5px 0;
            margin-bottom: 10px;
            border-bottom: 1px solid #e1e4e8;
        }
        
        .toc-container .toc .toc-top-link:hover {
            color: #4a86e8;
        }
        
        /* 内容样式 */
        .content-container {
            flex: 1;
            padding: 20px;
            max-width: 950px;
            margin: 0 auto;
            box-sizing: border-box;
        }
        
        /* 响应式布局 */
        @media (max-width: 768px) {
            body {
                flex-direction: column;
            }
            
            .toc-container {
                width: 100%;
                height: auto;
                max-height: 300px;
                position: relative;
            }
            
            .content-container {
                width: 100%;
            }
        }
        
        pre {
            background-color: #f5f5f5;
            padding: 10px;
            border-radius: 5px;
            overflow-x: auto;
        }
        
        code {
            font-family: Consolas, Monaco, 'Andale Mono', monospace;
            background-color: #f5f5f5;
            padding: 2px 4px;
            border-radius: 3px;
        }
        
        table {
            border-collapse: collapse;
            width: 100%;
            margin-bottom: 20px;
        }
        
        th, td {
            border: 1px solid #ddd;
            padding: 8px;
            text-align: left;
        }
        
        th {
            background-color: #f2f2f2;
        }
        
        img {
            max-width: 100%;
            height: auto;
        }
        
        blockquote {
            border-left: 4px solid #ddd;
            padding-left: 16px;
            margin-left: 0;
            color: #666;
        }
        
        blockquote pre {
            background-color: #f0f0f0;
            border-left: 3px solid #ccc;
        }
        
        /* 标题样式优化 */
        h2 {
            font-size: 1.5em;
            border-bottom: 1px solid #eaecef;
            padding-bottom: 0.3em;
            text-decoration: underline;  /* 为 h2 添加下划线 */
        }
        
        /* 超链接颜色优化 */
        a {
            color: #4a86e8;  /* 更淡的浅蓝色 */
            text-decoration: none;
        }
        
        a:hover {
            text-decoration: underline;
        }
        
        /* 代码高亮样式 */
        uQ  
        
        .highlight {
            background: #f8f8f8;
            border-radius: 5px;
            margin: 10px 0;
        }
        
        .highlight pre {
            background: transparent;
            margin: 0;
            padding: 10px;
            border: none;
            font-size: 0.85em;  /* 缩小代码块字体 */
            line-height: 1.5;  /* 增加代码块行间距 */
        }
        
        .highlight code {
            line-height: 1.5;  /* 增加代码行间距 */
        }
        
        /* 代码行样式 */
        .highlight .line {
            line-height: 1.5;  /* 增加代码行间距 */
            margin-bottom: 2px;  /* 行之间添加间距 */
            display: block;  /* 确保每行都是块级元素 */
        }
        
        /* 减弱蓝色代码的强度 */
        .highlight .n, .highlight .na, .highlight .nb, .highlight .bp, .highlight .nc, .highlight .no, .highlight .nd, .highlight .ni, .highlight .ne, .highlight .nf, .highlight .nl, .highlight .nn, .highlight .nx, .highlight .py, .highlight .nt, .highlight .nv, .highlight .ow, .highlight .o, .highlight .oi, .highlight .om {
            color: #5c8db8 !important;  /* 减弱蓝色代码的强度 */
        }
        
        /* Objective-C 语法高亮 */
        .language-objectivec .highlight .k, .language-objectivec .highlight .kt {
            color: #008 !important;  /* 关键字 - 深蓝色 */
        }
        
        .language-objectivec .highlight .nc {
            color: #b06 !important;  /* 类名 - 紫色 */
        }
        
        .language-objectivec .highlight .mi {
            color: #099 !important;  /* 数字 - 青色 */
        }
        
        .language-objectivec .highlight .s, .language-objectivec .highlight .s1, .language-objectivec .highlight .s2 {
            color: #d14 !important;  /* 字符串 - 红色 */
        }
        
        .language-objectivec .highlight .cp {
            color: #999 !important;  /* 预处理指令 - 灰色 */
        }
        
        /* XML 标签颜色 */
        .language-xml .highlight .nt {
            color: #905 !important;  /* XML标签名称 - 暗红色 */
        }
        
        .language-xml .highlight .na {
            color: #690 !important;  /* XML属性名称 - 绿色 */
        }
        
        .language-xml .highlight .s, .language-xml .highlight .s1, .language-xml .highlight .s2 {
            color: #07a !important;  /* XML字符串 - 蓝色 */
        }
        
        /* JSON 语法高亮 */
        .language-json .highlight .p {
            color: #333 !important;  /* JSON标点符号 */
        }
        
        .language-json .highlight .s2 {
            color: #d14 !important;  /* JSON字符串 - 红色 */
        }
        
        .language-json .highlight .kc {
            color: #099 !important;  /* JSON关键字(true/false/null) - 青色 */
        }
        
        .language-json .highlight .mi {
            color: #099 !important;  /* JSON数字 - 青色 */
        }
        
        .language-label {
            display: block;
            background: #e0e0e0;
            padding: 3px 10px;
            font-size: 12px;
            font-family: sans-serif;
            color: #666;
            border-top-left-radius: 5px;
            border-top-right-radius: 5px;
        }
        
        .language-label {
            display: block;
            background: #e0e0e0;
            padding: 3px 10px;
            font-size: 12px;
            font-family: sans-serif;
            color: #666;
            border-top-left-radius: 5px;
            border-top-right-radius: 5px;
        }
        
        /* 引用块中的代码样式 */
        blockquote .highlight {
            background: #f0f0f0;
        }
        
        /* 隐藏原始 TOC */
        .content-container .toc {
            display: none;
        }
    </style>
</head>
<body>
u_   
    <div class="toc-container">
        <h2>目录</h2>
        <div class="toc">
            zo
        </div>
    </div>
    <div class="content-container">
        <div class="markdown-body">
            z*
        </div>
    </div>
</body>
</html>zU
    <div class="content-container">
        <div class="markdown-body">
            html.parserwu,   ✅ Markdown 文件已成功转换为 HTML: u   转换过程中发生错误: )ospathexistsprintsplitextbasenamecodecsopenreadpreprocess_markdownresubmarkdownpostprocess_htmlr   get_style_defsgenerate_tocr   prettifywrite	Exception	traceback	print_exc)md_file_pathhtml_file_pathcss_file_pathr   md_file
md_contenthas_tochtml_contentpygments_csshtml_templatetoc_htmlsouppretty_html	html_fileer3    rC   H/data/storage/obfuscation/tool/ObjectiveC/oc_custom/custom_md_to_html.py
md_to_html   s   

 ,   &	


rE   c                 C   s  t | d}|g d}|sdS d}d}g }|D ]X}t|jd }| }|d}	|	s9tdd| }	|	|d< ||krPt	|| D ]}
|d7 }|
d	 qCn||k rct	|| D ]}
|| 7 }qZ|d
|	 d| d7 }|}q|r{|| 7 }|ss|d	7 }|S )u   
    从 HTML 内容中提取标题并生成目录
    
    参数:
        html_content (str): HTML 内容
        
    返回:
        str: 目录的 HTML 代码
    r   )h1h2h3h4h5h6u   <p>没有找到标题</p>z<ul>r   idz[^a-zA-Z0-9_-]-z</ul>z<li><a href="#r   z	</a></li>)r   find_allintnameget_textgetr*   r+   lowerrangeappendpop)r;   r?   headingsr>   current_levelstackheadinglevelheading_text
heading_id_rC   rC   rD   r/     s:   


r/   c           	      C   s  |  d}d}d}d}g }d}|t|k r|| }|drR|s"d}d|v rL|d}|d t|k r>||d d	  }nd}|d	| d
 | }d}|| n*|rf|rfd|v rf|d d}|d7 }q|rw|dswd}d}|| n|| |d7 }|t|k sd|S )uD   
    预处理 Markdown 内容，处理引用块中的代码块
    
Fr   r   >Tz```r   N%%CODE_BLOCK_START%%z> %%CODE_BLOCK_END%%r   )splitlen
startswithfindstriprU   join)	r9   linesin_quotein_code	code_langresult_linesiline
code_startrC   rC   rD   r)     s@   





)r)   c                 C   s  dddddddddddd	ddd
}t | d}|d}|r!d|d< |dD ]
}|d}|r1d}|dg }|D ]}|drJ|dd } nq;|rQ|dkr| }	|	r`|	 dd nd}
|
dsl|
drod}nA|
dr{d|
v r{d}n5|
ds|
d rd}n(|
d!s|
d"rd!|
v rd#|	v sd"|
v rd$|	v rd%}n|
d&sd'|	v rd}||v rtd(| d)||   || }|r-|dkr-zCt	|d*d+}t
d,d-}| }	t|	||}|d.}d/|d< ||_|d.}d0| |d< || t |d}|| || W q& ty, } ztd1| d2|  W Y d}~q&d}~ww td3 q&t|}d4}d5d6 }tj|||tjd7}|S )8u@   
    后处理 HTML 内容，处理代码块和语法高亮
    
objectivec
javascript
typescriptpythonrubybashcpphtmlr,   )zobjective-cobjczobj-cjstspyrbshzshzc++html5mdpodpodfiler   rF   ztext-align: center;r   precodeNclassz	language-	   	plaintextr_   r   r   z#importz
@interfacezObjective-C<r`   xmlzimport zfrom {[}]jsonzplatform :ioszpod u   应用语言别名映射: z -> Tstripallr   r   divzlanguage-labelzhighlight language-u   高亮代码时出错 (语言: ): u'   未检测到语言或语言为plaintextzG&gt; %%CODE_BLOCK_START%%(.*?)(?:\n&gt; .*?)*?\n&gt; %%CODE_BLOCK_END%%c              
   S   s  |  d}td|}|r| d nd}g }|dD ]}d|v s'd|v r(q|dr7||d	d   q|| qd|}z |rKt|d
dnt	 }t
dd}t|||}	d| d|	 dW S  ty }
 ztd| d|
  d| d| dW  Y d }
~
S d }
~
ww )Nr   z!%%CODE_BLOCK_START%%(.*?)(?:\n|$)r   r   r_   ra   z%%CODE_BLOCK_END%%z&gt;    Tr   r   r   z(<blockquote><div class="language-label">z</div><div class="highlight">z</div></blockquote>u4   处理引用块中的代码高亮时出错 (语言: r   z'<blockquote><pre><code class="language-r   z</code></pre></blockquote>)groupr*   searchrf   rb   rd   rU   rg   r   r   r   r   r2   r#   )matchblock
lang_matchlang
code_linesrn   code_contentlexer	formatterhighlightedrB   rC   rC   rD   replace_code_block  s*   



z,postprocess_html.<locals>.replace_code_block)flags)r   re   rN   rR   rd   rQ   rf   rb   r#   r   r   r   new_tagstringrU   replace_withr2   strr*   r+   DOTALL)r;   LANGUAGE_ALIASESr?   first_h1r   r   r   classescls	code_text
first_liner   r   highlighted_code
lang_labelhighlight_divnew_contentrB   html_strpatternr   rC   rC   rD   r-   "  s   



 





 r-   Tc           
      C   s   t j| std|   g S g }t | D ])\}}}|D ]}| dr:t j||}t||d}	|	r:|	|	 q|s? nqtdt
| d |S )u^  
    批量转换目录中的所有 Markdown 文件为 HTML
    
    参数:
        directory_path (str): 目录路径
        recursive (bool, optional): 是否递归处理子目录，默认为 True
        css_file_path (str, optional): CSS 文件路径，用于美化 HTML
        
    返回:
        list: 生成的 HTML 文件路径列表
    u%   错误: 指定的路径不是目录: z.md)r7   u#   ✅ 批量转换完成，共生成 u    个 HTML 文件)r    r!   isdirr#   walkrS   endswithrg   rE   rU   rc   )
directory_path	recursiver7   
html_filesrootdirsfilesfiler5   r6   rC   rC   rD   batch_convert_md_to_html  s"   
r   c              
   C   s   | du rt jt  d} d}z'tj| ddd}|| W d   n1 s(w   Y  td|   | W S  tyP } ztd|  W Y d}~dS d}~ww )	u   
    创建默认的 CSS 文件用于美化 HTML
    
    参数:
        output_path (str, optional): CSS 文件输出路径，默认为当前目录下的 markdown.css
        
    返回:
        str: CSS 文件路径
    Nzmarkdown.cssu  /* Markdown 样式 */
body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    line-height: 1.6;
    color: #333;
    background-color: #fff;
    margin: 0;
    padding: 0;
}

/* 布局样式 */
.container {
    display: flex;
    min-height: 100vh;
}

/* 目录侧边栏样式 */
.toc-sidebar {
    width: 280px;
    background-color: #f8f9fa;
    border-right: 1px solid #e9ecef;
    padding: 20px 0;
    position: fixed;
    height: 100vh;
    overflow-y: auto;
}

.toc-container {
    padding: 0 20px;
}

.toc-container h2 {
    margin-top: 0;
    padding-bottom: 10px;
    border-bottom: 1px solid #dee2e6;
    text-decoration: none;
}

.toc-container ul {
    list-style-type: none;
    padding-left: 0;
}

.toc-container ul ul {
    padding-left: 20px;
}

.toc-container li {
    margin-bottom: 8px;
}

.toc-container a {
    color: #495057;
    text-decoration: none;
    display: block;
    padding: 5px 0;
    border-radius: 3px;
    transition: background-color 0.2s;
}

.toc-container a:hover {
    background-color: #e9ecef;
    padding-left: 5px;
}

/* 内容区域样式 */
.content {
    flex: 1;
    padding: 20px;
    margin-left: 280px;
    max-width: 900px;
}

.markdown-body {
    max-width: 900px;
    margin: 0 auto;
}

h1, h2, h3, h4, h5, h6 {
    margin-top: 24px;
    margin-bottom: 16px;
    font-weight: 600;
    line-height: 1.25;
}

h1 {
    font-size: 2em;
    border-bottom: 1px solid #eaecef;
    padding-bottom: 0.3em;
}

h2 {
    font-size: 1.5em;
    border-bottom: 1px solid #eaecef;
    padding-bottom: 0.3em;
    text-decoration: underline;  /* 为 h2 添加下划线 */
}

h3 {
    font-size: 1.25em;
}

h4 {
    font-size: 1em;
}

h5 {
    font-size: 0.875em;
}

h6 {
    font-size: 0.85em;
    color: #6a737d;
}

a {
    color: #4a86e8;  /* 更淡的浅蓝色 */
    text-decoration: none;
}

a:hover {
    text-decoration: underline;
}

pre {
    background-color: #f6f8fa;
    border-radius: 3px;
    padding: 16px;
    overflow: auto;
    font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
    font-size: 80%;  /* 缩小代码块字体 */
    line-height: 1.5;  /* 增加代码块行间距 */
}

code {
    background-color: rgba(27, 31, 35, 0.05);
    border-radius: 3px;
    font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
    font-size: 85%;
    margin: 0;
    padding: 0.2em 0.4em;
}

pre code {
    background-color: transparent;
    padding: 0;
    line-height: 1.5;  /* 增加代码行间距 */
}

blockquote {
    margin: 0;
    padding: 0 1em;
    color: #6a737d;
    border-left: 0.25em solid #dfe2e5;
}

table {
    border-spacing: 0;
    border-collapse: collapse;
    width: 100%;
    overflow: auto;
    margin-bottom: 16px;
}

table th {
    font-weight: 600;
    background-color: #f6f8fa;
}

table th, table td {
    padding: 6px 13px;
    border: 1px solid #dfe2e5;
}

table tr {
    background-color: #fff;
    border-top: 1px solid #c6cbd1;
}

table tr:nth-child(2n) {
    background-color: #f6f8fa;
}

img {
    max-width: 100%;
    box-sizing: content-box;
}

hr {
    height: 0.25em;
    padding: 0;
    margin: 24px 0;
    background-color: #e1e4e8;
    border: 0;
}

ul, ol {
    padding-left: 2em;
}

li + li {
    margin-top: 0.25em;
}

/* 代码高亮样式 */
.highlight {
    background: #f8f8f8;
    border-radius: 5px;
}

.highlight pre {
    background: transparent;
    margin: 0;
    padding: 10px;
    border: none;
    font-size: 0.85em;  /* 缩小代码块字体 */
    line-height: 1.5;  /* 增加代码块行间距 */
}

.highlight code {
    line-height: 1.5;  /* 增加代码行间距 */
}

/* 代码行样式 */
.highlight .line {
    line-height: 1.5;  /* 增加代码行间距 */
    margin-bottom: 2px;  /* 行之间添加间距 */
    display: block;  /* 确保每行都是块级元素 */
}

/* 减弱蓝色代码的强度 */
.highlight .n, .highlight .na, .highlight .nb, .highlight .bp, .highlight .nc, .highlight .no, .highlight .nd, .highlight .ni, .highlight .ne, .highlight .nf, .highlight .nl, .highlight .nn, .highlight .nx, .highlight .py, .highlight .nt, .highlight .nv, .highlight .ow, .highlight .o, .highlight .oi, .highlight .om {{
    color: #5c8db8 !important;  /* 减弱蓝色代码的强度 */
}

/* 引用块中的代码样式 */
blockquote .highlight {
    background: #f0f0f0;
}

/* 任务列表样式 */
.task-list-item {
    list-style-type: none;
}

.task-list-item input {
    margin: 0 0.2em 0.25em -1.6em;
    vertical-align: middle;
}
r   r	   r
   u    ✅ 已创建默认 CSS 文件: u"   创建 CSS 文件时发生错误: )	r    r!   rg   getcwdr&   r'   r1   r#   r2   )output_pathcss_contentcss_filerB   rC   rC   rD   create_default_css  s   
 |r   __main__   u   用法:uZ     单个文件转换: python3 md_to_html.py <path/to/file.md> [output.html] [css_file.css]ud     批量转换目录: python3 md_to_html.py --batch <directory_path> [--no-recursive] [css_file.css]uH     创建默认 CSS: python3 md_to_html.py --create-css [output_path.css]r   z--create-cssz--batchr   u   错误: 请指定目录路径z--no-recursiveFz.css)NNN)TN)N)*__doc__r    sysr&   bs4r   r,   r*   importlib.util	importlibrequired_packagespackageutil	find_specr#   systemr   r   pygments.lexersr   r   pygments.formattersr   rE   r/   r)   r-   r   r   __name__rc   argvexitoutput_css_pathr   r   r7   rT   rm   r   r5   r6   rC   rC   rC   rD   <module>   st    
   97 
	
#  





