一个最小列子
将过滤器写成一个函数,然后再filter过滤函数中定义一个tag对于应到定义的过滤函数1
2
3
4
5
6
7
8import markdown
def markdown2html(text):
return markdown.markdown(text, extensions=['extra'])
app=Flask(__name__)
env =app.jinja_env
env.filters['markdown1']=markdown2html
1 | <!DOCTYPE html> |
上面是一个比较简单的例子,很方便实用,看看标准写法怎么集成的
标准库怎么做
在使用flask-markdown的仓库的时候,想要在前端使用markdown
这个过滤器,看到文档中说这个仓库已经集成了markdown
方法的过滤器,这个过滤器的作用是将md文档转换成html文档。
看了一下flask-markdown的库
1 | # -*- coding: utf-8 -*- |
这里引入了一个初始化app,然后将app中的jinja环境添加以一个拓展MarkdownExtension
。看下拓展源码里面是什么
1 | # -*- coding: utf-8 -*- |
在MarkdownExtension
拓展类中初始化的方法实际上和我最开始写的自定义模板是一样的功能markdowner=markdown.Markdown(extensions=['extra'])
,但是下面为啥要写这么多东西。
这是拓展的另一种写法,带着注释分析下
1 | # -*- coding: utf-8 -*- |
总的来说,扩展中核心部分就在parse()函数里,而最关键的就是这个parser对象,它是一个jinja2.parser.Parser的对象。
- parser.stream 获取当前的文档处理流,它可以基于文档中的行迭代,所以可以使用next()方法向下一行前进,并返回当前行
- parser.parse_expression() 解析下一个表达式,并将结果返回
- parser.parse_statements() 解析下一段语句,并将结果返回。可以连续解析多行。它有两个参数
- 第一个是结束位置end_tokens,上例中是
{ % endcode % }
标签,它是个列表,可是设置多个结束标志,遇到其中任意一个即结束 - 第二个是布尔值drop_needle,默认为False,即解析完后流的当前位置指向结束语句
{ % endcode % }
之前。设为True时,即将流的当前位置设在结束语句之后
- 第一个是结束位置end_tokens,上例中是
在parse()函数最后,我们创建了一个nodes.CallBlock的块节点对象,并将其返回。初始化时,我们先传入了_markdown_support()方法的调用;然后两个空列表分别对应了字段和属性,本例中用不到,所以设空;再传入解析后的语句块body。CallBlock节点初始化完后,还要记得将当前行号设置进去。接下来,我们对于语句块的所有操作,都可以写在_markdown_support()方法里了。
_markdown_support()里的内容我就不多介绍了,只需要记得声明这个方法时,最后一定要接收一个参数caller,它是个回调函数,可以获取之前创建CallBlock节点时传入的语句块内容。
总结
代码看一遍发现flask-markdown就是一个自定义过滤器,也就这一个功能。
然而在我前端调用的时候发现还不能进行使用markdown
的过滤器。就暂时使用最简单的方法定义过滤器,回头想起来再看下库怎么回事。