起因

有很多编辑器可以直接将markdown转换成html,为什么还要自己写呢?因为我想写完markdown之后,即可以保存在笔记软件中(比如有道),又可以放到github进行版本管理,还可以发布到博客(比如博客园)。这些如果都操作一遍,是很繁琐的,所以必须交给脚本去做。

原材料

  • markdown2 or mistune
  • pygments

操作原理

  • 首先,我需要一个markdown的词法解析器,然后我需要html转换器。这个可以由markdown2或者mistune来完成。
  • 然后,我的笔记中有较多的代码,我需要代码高亮。这首先需要将markdown中的代码块提取出来,然后判断是哪种语言,然后进行着色。这部分可以由pyments完成

代码

使用mistune(源码很有学习价值)。需要自己引入pygments模块渲染代码块,官网有参考例子。

import mistune
import sys
import codecs
from pygments import cnblogs_code
from pygments.lexers import get_lexer_by_name
from pygments.formatters import html class HighlightRenderer(mistune.Renderer):
def block_code(self, code, lang):
if not lang:
return '\n<pre><code>%s</code></pre>\n' % \
mistune.escape(code)
lexer = get_lexer_by_name(lang, stripall=True)
formatter = html.HtmlFormatter()
return cnblogs_code (code, lexer, formatter) def main(argv):
name = argv[0] input_file = codecs.open(name, mode='r', encoding='utf-8') text = input_file.read()
renderer = HighlightRenderer()
markdown = mistune.Markdown(renderer=renderer)
html = markdown(text) html_name = '%s.html' % (name[:-3])
output_file = codecs.open(
html_name, 'w', encoding='utf-8', errors='xmlcharrefreplace') output_file.write(html) if __name__ == "__main__":
main(sys.argv[1:])

上面代码还不能使代码着色,因为没有指定css,还需要在生成的html头中加入css,不同的css文件可以在http://richleland.github.io/pygments-css/找到。

<style type = "text/css">
.cnblogs_code .hll { background-color: #ffffcc }
.cnblogs_code .c { color: #60a0b0; font-style: italic } /* Comment */
.cnblogs_code .err { border: 1px solid #FF0000 } /* Error */
.cnblogs_code .k { color: #007020; font-weight: bold } /* Keyword */
.cnblogs_code .o { color: #666666 } /* Operator */
.cnblogs_code .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */
.cnblogs_code .cp { color: #007020 } /* Comment.Preproc */
.cnblogs_code .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */
.cnblogs_code .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */
.cnblogs_code .gd { color: #A00000 } /* Generic.Deleted */
.cnblogs_code .ge { font-style: italic } /* Generic.Emph */
.cnblogs_code .gr { color: #FF0000 } /* Generic.Error */
.cnblogs_code .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.cnblogs_code .gi { color: #00A000 } /* Generic.Inserted */
.cnblogs_code .go { color: #808080 } /* Generic.Output */
.cnblogs_code .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
.cnblogs_code .gs { font-weight: bold } /* Generic.Strong */
.cnblogs_code .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.cnblogs_code .gt { color: #0040D0 } /* Generic.Traceback */
.cnblogs_code .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
.cnblogs_code .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
.cnblogs_code .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
.cnblogs_code .kp { color: #007020 } /* Keyword.Pseudo */
.cnblogs_code .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
.cnblogs_code .kt { color: #902000 } /* Keyword.Type */
.cnblogs_code .m { color: #40a070 } /* Literal.Number */
.cnblogs_code .s { color: #4070a0 } /* Literal.String */
.cnblogs_code .na { color: #4070a0 } /* Name.Attribute */
.cnblogs_code .nb { color: #007020 } /* Name.Builtin */
.cnblogs_code .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
.cnblogs_code .no { color: #60add5 } /* Name.Constant */
.cnblogs_code .nd { color: #555555; font-weight: bold } /* Name.Decorator */
.cnblogs_code .ni { color: #d55537; font-weight: bold } /* Name.Entity */
.cnblogs_code .ne { color: #007020 } /* Name.Exception */
.cnblogs_code .nf { color: #06287e } /* Name.Function */
.cnblogs_code .nl { color: #002070; font-weight: bold } /* Name.Label */
.cnblogs_code .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
.cnblogs_code .nt { color: #062873; font-weight: bold } /* Name.Tag */
.cnblogs_code .nv { color: #bb60d5 } /* Name.Variable */
.cnblogs_code .ow { color: #007020; font-weight: bold } /* Operator.Word */
.cnblogs_code .w { color: #bbbbbb } /* Text.Whitespace */
.cnblogs_code .mf { color: #40a070 } /* Literal.Number.Float */
.cnblogs_code .mh { color: #40a070 } /* Literal.Number.Hex */
.cnblogs_code .mi { color: #40a070 } /* Literal.Number.Integer */
.cnblogs_code .mo { color: #40a070 } /* Literal.Number.Oct */
.cnblogs_code .sb { color: #4070a0 } /* Literal.String.Backtick */
.cnblogs_code .sc { color: #4070a0 } /* Literal.String.Char */
.cnblogs_code .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
.cnblogs_code .s2 { color: #4070a0 } /* Literal.String.Double */
.cnblogs_code .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
.cnblogs_code .sh { color: #4070a0 } /* Literal.String.Heredoc */
.cnblogs_code .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
.cnblogs_code .sx { color: #c65d09 } /* Literal.String.Other */
.cnblogs_code .sr { color: #235388 } /* Literal.String.Regex */
.cnblogs_code .s1 { color: #4070a0 } /* Literal.String.Single */
.cnblogs_code .ss { color: #517918 } /* Literal.String.Symbol */
.cnblogs_code .bp { color: #007020 } /* Name.Builtin.Pseudo */
.cnblogs_code .vc { color: #bb60d5 } /* Name.Variable.Class */
.cnblogs_code .vg { color: #bb60d5 } /* Name.Variable.Global */
.cnblogs_code .vi { color: #bb60d5 } /* Name.Variable.Instance */
.cnblogs_code .il { color: #40a070 } /* Literal.Number.Integer.Long */
</style>

所以完整的代码应该为:

import mistune
import sys
import codecs
from pygments import cnblogs_code
from pygments.lexers import get_lexer_by_name
from pygments.formatters import html class HighlightRenderer(mistune.Renderer):
def block_code(self, code, lang):
if not lang:
return '\n<pre><code>%s</code></pre>\n' % \
mistune.escape(code)
lexer = get_lexer_by_name(lang, stripall=True)
formatter = html.HtmlFormatter()
return cnblogs_code (code, lexer, formatter) def main(argv):
md_name = argv[0] with codecs.open(md_name, mode='r', encoding='utf-8') as mdfile:
with codecs.open("friendly.css",mode = 'r',encoding = 'utf-8') as cssfile:
md_text = mdfile.read()
css_text = cssfile.read()
renderer = HighlightRenderer()
markdown = mistune.Markdown(renderer=renderer)
html_text = markdown(md_text) html_name = '%s.html' % (md_name[:-3])
with codecs.open(html_name, 'w', encoding='utf-8', errors='xmlcharrefreplace') as output_file:
output_file.write(css_text + html_text) if __name__ == "__main__":
if len(sys.argv) == 2:
main(sys.argv[1:])
else:
print("Error:please specify markdown file path")

friendly.css文件中存放之前的css文件。

同样使用markdown2的代码如下:

import markdown2
import codecs
import sys def main(argv):
md_name = argv[0] with codecs.open(md_name, mode='r', encoding='utf-8') as mdfile:
with codecs.open("friendly.css", mode='r', encoding='utf-8') as cssfile:
md_text = mdfile.read()
css_text = cssfile.read() extras = ['code-friendly', 'fenced-code-blocks', 'footnotes']
html_text = markdown2.markdown(md_text, extras=extras) html_name = '%s.html' % (md_name[:-3])
with codecs.open(html_name, 'w', encoding='utf-8', errors='xmlcharrefreplace') as output_file:
output_file.write(css_text + html_text) if __name__ == "__main__":
if len(sys.argv) == 2:
main(sys.argv[1:])
else:
print("Error:please specify markdown file path")

使用python转换markdown to html的更多相关文章

  1. windows下用python转换markdown到html

    方法一: 安装markdown, pip install markdown, 安装好后,python -m markdown xxx.md -f xxx.html 方法二:安装markdown2, p ...

  2. ahk实现git图床自动预览以及转换markdown格式

    ahk实现git图床自动预览以及转换markdown格式 软件地址 https://gitee.com/layty/pic/tree/master/app 软件功能: 检测剪切板,如果剪切板有非文本信 ...

  3. 使用Python从Markdown文档中自动生成标题导航

    概述 知识与思路 代码实现 概述 Markdown 很适合于技术写作,因为技术写作并不需要花哨的排版和内容, 只要内容生动而严谨,文笔朴实而优美. 为了编写对读者更友好的文章,有必要生成文章的标题导航 ...

  4. python之markdown转html

    python之markdown转html 为了方便,定义一个markdown转html的函数,直接调用即可 import markdown def md2html(mdstr): exts = ['m ...

  5. python转换已转义的字符串

    python转换已转义的字符串 有时我们可能会获取得以下这样的字符串: >>> a = '{\\"name\\":\\"michael\\"} ...

  6. 【技术博客】利用Python将markdown文档转为html文档

    利用Python将markdown文档转为html文档 v1.0 作者:FZK 元素简单的md文件 Python中自带有一个markdown库,你可以直接这样使用 md_file = open(&qu ...

  7. 用Python制作markdown编辑器

    还记得在上篇提到的rest-framework,文档中提到了markdown也是可选应用. 那么这篇我们就来尝试使用markdown来制作一个在线的可以预览的editor. 安装 Python Mar ...

  8. python转换html到pdf文件

    1.安装wkhtmltopdf Windows平台直接在 http://wkhtmltopdf.org/downloads.html 下载稳定版的 wkhtmltopdf 进行安装,安装完成之后把该程 ...

  9. 使用python转换编码格式

    之前有写过一个使用powershell转换文档格式的方法,然而因为powershell支持不是很全,所以并不好用.这里使用python再做一个. 思路 检测源码格式,如果不是utf8,则进行转换,否则 ...

随机推荐

  1. 最小生成树 Prim算法 Kruskal算法实现

    最小生成树定义 最小生成树是一副连通加权无向图中一棵权值最小的生成树. 在一给定的无向图 G = (V, E) 中,(u, v) 代表连接顶点 u 与顶点 v 的边(即,而 w(u, v) 代表此边的 ...

  2. ICPC-Beijing 2006 狼抓兔子

    题目描述 题解: 裸的最小割. 但是最大流跑不过去怎么办? 转变一下,既然最大流是一条左下<->右上的通路,我们可以把图划分为若干区域, 最后找左下到右上的最短路就行了. 代码: #inc ...

  3. vue element-ui中引入第三方icon

    vue element-ui中引入第三方icon 把图标加入项目 设置项目名称,下载项目(项目名称自定义) 解压项目到开发目录 在main.js中全局引入css文件 修改下载下来的项目中的css文件, ...

  4. MySQL 慢查询优化

    为什么查询速度会慢 1.慢是指一个查询的响应时间长.一个查询的过程: 客户端发送一条查询给服务器 服务器端先检查查询缓存,如果命中了缓存,则立可返回存储在缓存中的结果.否则进入下一个阶段 服务器端进行 ...

  5. 【Codeforces 1083A】The Fair Nut and the Best Path

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] 我们最后要的是一条最长的路径. 这条路径的权值和是所有点的权值和-所有边的权值和且这个值最大. 显然如果我们在某一条边上的累计的权值和< ...

  6. 七、整合SQL基础和PL-SQL基础

    --Oracle数据库重要知识点整理 2017-01-24 soulsjie 目录 --一.创建及维护表... 2 --1.1 创建... 2 --1.2 维护表... 2 --二.临时表的分类.创建 ...

  7. [转]使用fdisk磁盘分区和 Linux 文件系统

    概述 在本文中,学习磁盘分区和 Linux 文件系统相关内容.学习: 创建分区 使用 mkfs 命令来设置 ext2.ext3.ext4.xfs.Reiser v3 和 vfat 文件系统 创建和管理 ...

  8. 深入理解计算机操作系统——12章:多进程,IO多路复用

    三种并行的应用程序: 1. 基于进程的并发编程: 2. 基于IO多路复用的并发: 3. 基于线程的并发编程: 12.1 基于进程的并发编程 进程的优劣: (1)进程间共享文件表,但不共享用户地址空间, ...

  9. codeforces Rockethon 2015 C Second price auction [想法]

    传送门 C. Second price auction time limit per test 2 seconds memory limit per test 256 megabytes input ...

  10. 显示倒计时的Button按钮

    package com.pingyijinren.helloworld.activity; import android.os.CountDownTimer; import android.suppo ...