Jinja2ã¯ããã³ãã¬ãŒããã¬ã³ããªã³ã°ããããã®Pythonã©ã€ãã©ãªã§ããããã¯ãFlaskã§Webã¢ããªã±ãŒã·ã§ã³ãäœæããããã®äºå®äžã®æšæºã§ãããçµã¿èŸŒã¿ã®Djangoãã³ãã¬ãŒãã·ã¹ãã ã®ããªãäžè¬çãªä»£æ¿ææ®µã§ãã èšèªã«åŒ·ãçµã³ã€ããŠããŸãããJinja2ã¯ãã¶ã€ããŒãã¬ã€ã¢ãŠããã¶ã€ããŒåãã®ããŒã«ãšããŠäœçœ®ä»ããããŠãããã¬ã€ã¢ãŠããç°¡çŽ åããŠéçºããåé¢ããéçºè
以å€ã®ãŠãŒã¶ãŒãã§ããéãPythonããåé¢ããããšããŠããŸãã ãã ããã¬ã€ã¢ãŠãã ãã䜿çšã§ããããã§ã¯ãããŸããã ããšãã°ãç§ã®ä»äºã§ã¯ãJinja2ãã³ãã¬ãŒãã䜿çšããŠSQLã¯ãšãªãçæããŸãã
Jinja2ã¯
æ¡åŒµå¯èœã§ãå€ãã®æ©èœïŒåœéåãã«ãŒã管çãªã©ïŒãæ¡åŒµæ©èœãšããŠå®è£
ãããŠããŸãã ããããæ¡åŒµæ©èœãèšè¿°ããããã®ããã¥ã¡ã³ãã¯ãç§ã«ã¯æããŸãããããäžå®å
šã§ãã åçŽãªïŒãã ãæ
éã«ã³ã¡ã³ããããïŒæ¡åŒµæ©èœã®äŸãããããã«èªãã®ãéåžžã«é£ãã
ããã€ãã® Jinja2ã¯ã©ã¹ã®APIã®èª¬æã«ãžã£ã³ãããŸãã ãã®èšäºã§ã¯ããã®çç¥ãä¿®æ£ããèªè
ã®é ã«Jinja2ã®ä»çµã¿ãæ¡åŒµæ©èœã®ããã¿ãæ¡åŒµæ©èœã䜿çšããŠãã³ãã¬ãŒãåŠçã®ããŸããŸãªæ®µéã倿Žããæ¹æ³ã®å®å
šãã€æç¢ºãªå³ãäœæããŸãã


ã°ããŒãã«ã«ãJinja2ã¯åPythonå®è¡å¯èœãã³ãã¬ãŒããã³ã³ãã€ã«ããŸããããã¯ã³ã³ããã¹ãå
¥åãåãåããæååïŒã¬ã³ããªã³ã°ããããã³ãã¬ãŒãïŒãè¿ããŸãã ããã»ã¹å
šäœã¯æ¬¡ã®ããã«ãªããŸãã
- ããŠã³ããŒããã ãã³ãã¬ãŒãããã¡ã€ã«ã·ã¹ãã ãPythonããã±ãŒãžã®ãããã©ã«ããŒãã¡ã¢ãªã«ä¿åãããããªã³ã¶ãã©ã€ã§åçŽã«çæããããšãã§ããŸã-ãŸããJinja2ã¯ã©ã®ã¡ãœãããé¢é£ãããã倿ãããã³ãã¬ãŒããœãŒã¹ãã¡ã¢ãªã«ããŒãããŸãã
- ããŒã¯ã³å åå¥è§£æåšïŒåå¥è§£æåšïŒã¯ãæãåçŽãªãšã³ãã£ãã£ã§ããããŒã¯ã³ã®ãã³ãã¬ãŒãã®ãœãŒã¹ã³ãŒããç ŽããŸãã ããŒã¯ã³ã®äŸã¯ãã¿ã°ãéãæ§æèŠçŽ
{%
ã§ãã - è§£æäž ã ããŒãµãŒã¯ãããŒã¯ã³ã®ã¹ããªãŒã ãè§£æããæ§ææ§æãåé¢ããŸãã æ§æã³ã³ã¹ãã©ã¯ãã®äŸã¯ã
{{ variable }}
ã³ã³ã¹ãã©ã¯ãã§ããããã¯ã倿°ã®å€ã眮ãæããŸãïŒ3ã€ã®ããŒã¯ã³ã§æ§æãããŸã- {{
ã variable
åãããã³}}
éãvariable
ïŒã - æé©å ã ãã®æ®µéã§ããã¹ãŠã®å®æ°åŒãèšç®ãããŸãã ããšãã°ãæ§æ
{{ 1 + 2 }}
ã¯{{ 3 }}
ã«å€æãããŸãã - äžä»£ ã äŸç¶ãšããŠæœè±¡æ§æããªãŒïŒASTïŒãšããŠæ ŒçŽãããŠããæ§ææ§æäœã¯ãPythonã³ãŒãã«å€æãããŸãã
- ã³ã³ãã€ã« ã çµæã®Pythonã³ãŒãã¯ãçµã¿èŸŒã¿ã®
compile
颿°ã«ãã£ãŠã³ã³ãã€ã«ãããŸãã çµæã®ãªããžã§ã¯ãã¯ãçµã¿èŸŒã¿é¢æ°exec
ããŠèµ·åã§ããŸãããã³ãã¬ãŒãã¯ãã¬ã³ããªã³ã°æã«ãã³ãã¬ãŒããå®è¡ããŸãã


jinja2.ext.Extension
æ¡åŒµæ©èœãäœæããã«ã¯ã
jinja2.ext.Extension
ãç¶æ¿ããã¯ã©ã¹ãå®çŸ©ããå¿
èŠããããŸãã æ¡åŒµæ©èœãæå¹ã«ããã«ã¯ãç°å¢ã®äœææã«æ¡åŒµæ©èœã®ãªã¹ãã«ãªã¹ããããã
add_extension
ã¡ãœããã䜿çšããŠäœæããåŸã«è¿œå ããŸãã
åã®èšèã®ä»£ããã«ç°¡åãªã€ã©ã¹ãïŒ
from jinja2 import Environment from jinja2.ext import Extension class MyFirstExtension(Extension): pass class MySecondExtension(Extension): pass environment = Environment(extensions=[MyFirstExtension]) environment.add_extension(MySecondExtension) print(environment.extensions)
圌ãã«äœããããããã«æããããšã¯æ®ã£ãŠããŸãïŒ ãã®ããããããŸãã«èšã£ãŠãåå®çŸ©ã§ããã¡ãœããã¯3ã€ã ãã§ãã
preprocess
;filter_stream
ïŒãã®æå³ã¯äœã§ãïŒ;parse
ã
ããŠãé çªã«å§ããŸãããã


ãã³ãã¬ãŒããœãŒã¹ã®çŽæ¥èªã¿èŸŒã¿ãå¶åŸ¡ããæãç°¡åãªæ¹æ³ã¯ãç¬èªã®ããŒããŒãå®è£
ããããšã§ãã ãããè¡ãã«ã¯åºæ¬çã§ãïŒ
jinja2.loaders.BaseLoader
ããç¶æ¿ãã
get_source(environment, template_name)
ã¡ãœããããªãŒããŒã©ã€ãããŸã-å®äºã§ãã ããã¯æå³ã®ããããšããããŸãã ãããã£ãŠãããæ¥ããã³ãã¬ãŒãã®ä»ã®éšåãšã®åŸæ¹äºææ§ã®ããã«ããã³ãã¬ãŒãã®ãã©ã«ãå
šäœããã³ãã¬ãŒããçæãã1ã€ã®ãšã¬ã¬ã³ããªé¢æ°ã«çœ®ãæããããšãã§ããå Žåããããã®ãã³ãã¬ãŒãããŸã ååšãããµããããŠããŒãããŒããŒãäœæããããšãã§ããŸãïŒãããŠãèªåã§
git rm
ãŸãïŒ ã
ãã ããããã¯ãªããããã¯ã§ããæ¡åŒµæ©èœã¯ã©ãã«ãããŸããïŒ ãã€ã§ãèªåãæããã®ãç¶æ¿ããããã§å¿
èŠã ãšæããã®ã倿Žã§ããããšã¯æããã§ãïŒ é©ããããšã«ã念ã®ããæ¡åŒµAPIã«ããã³ãã¬ãŒãã®ãœãŒã¹ã³ãŒããçŽæ¥å¶åŸ¡ããæ¹æ³ããããŸãã
ãã®ããã
Extension
ã¯ã©ã¹ã«ã¯ãããŒãåŸã«ããŒã¯ã³åã®åã«åãã³ãã¬ãŒãã«å¯ŸããŠåŒã³åºããã
preprocess
ã¡ãœãããå«ãŸããŠããŸãã 眲åã¯æ¬¡ã®ããã«ãªããŸãã
def preprocess(self, source, name, filename=None): """ : source (String) - name (String) - filename (String None) - ( ) : String - """
ãã®æ¹æ³ã§ã¯ãå¿
èŠãªããšã¯äœã§ãã§ããŸãã æè¡çã«ã¯ãããã®ã©ããã§ç¬èªã®ãã³ãã¬ãŒãèšèªãJinja2ãã³ãã¬ãŒãã«ã³ã³ãã€ã«ããããšãå®è£
ã§ããŸãã ããã...ãªãã§ããïŒ ããããããœãŒã¹ãçŽæ¥å€æŽããæ©èœã¯ãéèŠãªæ¡åŒµæ©èœãäœæããéã®è£å©ãšããŠåœ¹ç«ã¡ãŸãã ãã ããJinja2 APIãŸãã¯ãã®å®è£
ã®æ©èœã«ã€ããŠã®ç¥èã¯ããã§ã¯å¿
èŠãªãããããã®æ®µéã®è©³çްã«ã¯è§ŠãããããŒã¯ã³åã«é²ã¿ãŸããã


ç§ãã¡ã«ãšã£ãŠéåžžã«è峿·±ãã®ã¯
filter_stream
ã¡ãœããã§ãããã®ã¡ãœããã¯ããããéãã«ã¹ã¿ãã€ãºã®è±å¯ãªå¯èœæ§ãšããã®ç¥ç§çãªååãåŒãä»ããŸãã 眲åã¯æ¬¡ã®ããã«ãªããŸãã
def filter_stream(self, stream): """ : stream (jinja2.lexer.TokenStream) - : jinja2.lexer.TokenStream - """
äžè¬ã«ãJinja2ã®åå¥è§£æåšãšæ§æè§£æåšã®çžäºäœçšã¯æ¬¡ã®ããã«ç·šæãããŠããŸãã åå¥ã¢ãã©ã€ã¶ãŒïŒ
jinja2.lexer.Lexer
ïŒã¯ããã¹ãŠã®ããŒã¯ã³ã次ã
ã«
jinja2.lexer.Token
ãããžã§ãã¬ãŒã¿ãŒïŒ
jinja2.lexer.Lexer
ïŒãçæãããã®ãžã§ãã¬ãŒã¿ãŒã
jinja2.lexer.TokenStream
ãªããžã§ã¯ãã«ã©ããããŸãããã®ãªããžã§ã¯ãã¯ãã¹ããªãŒã ããããã¡ãŒããããã€ãã®äŸ¿å©ãªè§£æã¡ãœãããæäŸããŸãïŒããšãã°ãçŸåšã®ããŒã¯ã³ãã¹ããªãŒã ããåŒãåºãããšãªã衚瀺ããæ©èœïŒã åæ§ã«ãæ¡åŒµæ©èœã¯ãã®ãããŒã«åœ±é¿ãäžããïŒã¡ãœããã®ååã瀺åããããã«ïŒãã£ã«ã¿ãªã³ã°ããã ãã§ãªããæ¡åŒµããããšãã§ããŸãã
Jinja2ã®ããŒã¯ã³-ãªããžã§ã¯ãã¯éåžžã«åçŽã§ãã æ¬è³ªçã«ããããã¯3ã€ã®ååä»ããã£ãŒã«ãã®ã¿ãã«ã§ãïŒ
lineno
ããŒã¯ã³ä»ãã®è¡çªå·ã- type-ããŒã¯ã³ã®ã¿ã€ãã
- value-ããŒã¯ã³ã®æååå€ã
type
ãã£ãŒã«ãã®ããŸããŸãªå®æ°ã¯
jinja2/lexer.py
å®çŸ©ãããŠã
jinja2/lexer.py
ïŒ
TOKEN_ADD TOKEN_NE TOKEN_VARIABLE_BEGIN TOKEN_ASSIGN TOKEN_PIPE TOKEN_VARIABLE_END TOKEN_COLON TOKEN_POW TOKEN_RAW_BEGIN TOKEN_COMMA TOKEN_RBRACE TOKEN_RAW_END TOKEN_DIV TOKEN_RBRACKET TOKEN_COMMENT_BEGIN TOKEN_DOT TOKEN_RPAREN TOKEN_COMMENT_END TOKEN_EQ TOKEN_SEMICOLON TOKEN_COMMENT TOKEN_FLOORDIV TOKEN_SUB TOKEN_LINESTATEMENT_BEGIN TOKEN_GT TOKEN_TILDE TOKEN_LINESTATEMENT_END TOKEN_GTEQ TOKEN_WHITESPACE TOKEN_LINECOMMENT_BEGIN TOKEN_LBRACE TOKEN_FLOAT TOKEN_LINECOMMENT_END TOKEN_LBRACKET TOKEN_INTEGER TOKEN_LINECOMMENT TOKEN_LPAREN TOKEN_NAME TOKEN_DATA TOKEN_LT TOKEN_STRING TOKEN_INITIAL TOKEN_LTEQ TOKEN_OPERATOR TOKEN_EOF TOKEN_MOD TOKEN_BLOCK_BEGIN TOKEN_MUL TOKEN_BLOCK_END
ããŒã¯ã³ãæäœããäžè¬çãªæ¡åŒµæ©èœã¯æ¬¡ã®ããã«ãªããŸãã
from jinja2.ext import Extension from jinja2.lexer import TokenStream class TokensModifyingExtension(Extension): def filter_stream(self, stream): generator = self._generator(stream) return lexer.TokenStream(generator, stream.name, stream.filename) def _generator(self, stream): for token in stream:
äŸãšããŠã倿°ã®ã¬ã³ããªã³ã°ã®ããžãã¯ã倿Žããæ¡åŒµæ©èœãäœæããŸãããã Jinja2ã§ã¬ã³ããªã³ã°ãããšããšã
str
颿°ã«ãã£ãŠæååã«å€æããããšããšã§ããªããžã§ã¯ãã®åäœãç°ãªããã®ã«ããããšããŸãã ãªããžã§ã¯ãã«ããã³ãã¬ãŒãã§äœ¿çšããã
__jinja__(self)
ã¡ãœãããå®çŸ©ãããªãã·ã§ã³ããããŸãã ãããè¡ãæãç°¡åãªæ¹æ³ã¯ã
__jinja__
ã¡ãœãããåŒã³åºãã«ã¹ã¿ã ãã£ã«ã¿ãŒã远å ãããã®åŒã³åºãããã©ãŒã
{{ <expression> }}
åæ§æã«èªåçã«çœ®ãæããããšã§ãã ãã¹ãŠã®æ¡åŒµã³ãŒãã¯æ¬¡ã®ããã«ãªããŸãã
from jinja2 import Environment from jinja2.ext import Extension from jinja2 import lexer class VariablesCustomRenderingExtension(Extension):
䜿çšäŸïŒ
class Kohai(object): def __jinja__(self): return "senpai rendered me!" if __name__ == "__main__": env = Environment(extensions=[VariablesCustomRenderingExtension]) template = env.from_string("""Kohai says: {{ kohai }}""") print(template.render(kohai=Kohai()))
Githubã§ãã¹ãŠèŠãããšãã§ããŸãã


ãªãŒããŒã©ã€ãã«äœ¿çšã§ããæåŸã§æãè峿·±ã
Extension
ã¯ã©ã¹ã¡ãœããã¯
parse
ã§ãã
def parse(self, parser): """ : parse (jinja2.parser.Parser) - : jinja2.nodes.Stmt List[jinja2.nodes.Stmt] - AST, """
ããã¯ãæ¡åŒµã¯ã©ã¹ã§å®çŸ©ã§ãã
tags
屿§ãšé£æºããŠæ©èœããŸãã ãã®å±æ§ã«ã¯å€ãã®ã¿ã°ãå«ãŸããŠããå¿
èŠãããããã®åŠçã¯æ¡åŒµæ©èœã«å§ããããŸããæ¬¡ã«äŸã瀺ããŸãã
class RepeatNTimesExtension(Extension): tags = {"repeat"}
ãããã£ãŠãæ§æè§£æãã察å¿ããã¿ã°ã®éå§ãå«ãæ§é ã«å°éãããšã
parse
ã¡ãœãããåŒã³åºãããŸãã
some text and then {% repeat ... ^
ãã®å ŽåãçŸåšåŠçäžã®ããŒã¯ã³ã瀺ã
parser.stream.current
屿§ã«ã¯
Token(lineno, TOKEN_NAME, "repeat")
ãå«ãŸããŸãã
次ã«ã
parse
ã¡ãœããå
ã§ãã«ã¹ã¿ã ã¿ã°ã
parse
ãè§£æçµæïŒæ§æããªãŒã®1ã€ä»¥äžã®ããŒãïŒãè¿ãå¿
èŠããããŸãã Jinja2ã§ã¯ãç¬èªã®ã¿ã€ãã®ããŒããèµ·åããããšã¯ã§ããŸããããããã£ãŠãçµã¿èŸŒã¿ã®ããŒãã«æºè¶³ããå¿
èŠããããŸãã 幞ããªããšã«ãïŒã»ãŒïŒãŠãããŒãµã«ãª
CallBlock
ããŒãããããŸãããã
CallBlock
以äžã§
CallBlock
ãŸãã
ãããŸã§ã®éã
For
usã®ãããªæ¢åã®ããŒãã¿ã€ãã®ããžãã¯ã¯åé¡ãããŸããã以äžã«ã
parse
ã¡ãœããå
ã§äœ¿çšããã¬ã·ãã®ã»ããã瀺ããŸãã
å¿
èŠãªãã®ããã¹ãŠè§£æãããã1ã€ä»¥äžã®ããªãŒããŒããäœæããŠãè§£æã®çµæãšããŠããããè¿ãããšãã§ããŸãã Jinja2ããŒãã®äœæã«ã€ããŠç¥ã£ãŠããã¹ãããšïŒ
- ãã¹ãŠã®ããŒãã¯ã©ã¹ã¯
jinja2.nodes
ã§å®çŸ©ããã jinja2.nodes
ãç¶æ¿ãjinja2.nodes.Node
ã ãããã®ãªã¹ãã¯å±éã§ããŸããã jinja2.nodes.Stmt
ãç¶æ¿ããããŒãã®ã¿ãparse
ããçŽæ¥è¿ããparse
ã æ®ãã¯æã
æ©èœããŸããããã¹ãŠãå£ãå¯èœæ§ããããŸãã ãããã£ãŠã次ã®ã¯ã©ã¹ããéžæã§ããŸãã
Assign ExprStmt Include AssignBlock Extends Macro Block FilterBlock Output Break For Scope CallBlock FromImport ScopedEvalContextModifier Continue If EvalContextModifier Import
Node
ãç¶æ¿ããåã¯ã©ã¹ã§ã¯ã fields
ãã£ãŒã«ãããã£ãŒã«ãã®ãªã¹ãã§å®çŸ©ãããŸãã ãã¹ãŠã®ãã£ãŒã«ããæå®ãããããã£ãŒã«ããæå®ããªãããšã§ããŒããäœæã§ããŸãïŒãããã¯None
ã«åæåããããããã®å€ã¯åŸã§æå®ã§ããŸãïŒã ãŸããããŒåŒæ°ã䜿çšããŠãã¹ãŠã®ããŒããäœæããå Žåã lineno
ãæå®ã§ããŸãã ããã䜿çšããŠããšã©ãŒã®å Žåã«é©åãªãã¬ãŒã¹ããã¯ãååŸããŸãã
äŸïŒ
from jinja2.nodes import *
ãã£ãŒã«ãã¯ããŒåŒæ°ã§æå®ã§ããªãããšã«æ³šæããŠãã ããïŒæ§ç¯
Include(template=template_name, with_context=False, ignore_missing=False)
åäœããŸããã- å€ãã®ããŒããã£ãŒã«ããããŒãã§ãã ãããã£ãŠã
Include
ã¯ãæåå"lib/stuff.j2"
ããã³ãã¬ãŒããã£ãŒã«ããšããŠåãå
¥ããããšã«åæããŸããnodes.Const("lib/stuff.j2")
ã ã©ã®ã¿ã€ãã®ãã£ãŒã«ããããããªãå Žåã¯ã jinja2/parser.py
ã§å¯Ÿå¿ããããŒããè§£æããã³ãŒããèŠã€ããŠjinja2/parser.py
-å°ãªããšãç°¡åã«çè§£ã§ããŸãïŒå°ãªããšããã®èšäºãèªãã åŸã¯...ïŒã
ãã®ãã¹ãŠã®ç¥èãé©çšããäŸãšããŠã
{% repeat N times %}...{% endrepeat %}
ã³ã³ã¹ãã©ã¯ãã
{% for _ in range(N) %}...{% endfor %}
ã³ã³ã¹ãã©ã¯ã
{% for _ in range(N) %}...{% endfor %}
ïŒ
from jinja2.ext import Extension from jinja2 import nodes class RepeatNTimesExtension(Extension):
䜿çšäŸïŒ
if __name__ == "__main__": env = Environment(extensions=[RepeatNTimesExtension]) template = env.from_string(u""" {%- repeat 3 times -%} {% if not loop.first and not loop.last %}, {% endif -%} {% if loop.last %} {% endif -%} {%- endrepeat -%} """) print(template.render())
Githubã§ãã¹ãŠèŠãããšãã§ããŸãã


Jinja2ã¢ãŒããã¯ãã£ã¯è€éã§ãããããæ§æããªãŒããŒãã®æ°ããã¯ã©ã¹ã远å ã§ããªããããä»»æã®åŠçãå®è¡ã§ãããŠãããŒãµã«ããŒããå¿
èŠã§ãã ãã®ãããªããŒãããããããã¯
CallBlock
ã§ãã
æåã«ã
{% call %}
ã¿ã°ãããèªäœã§ã©ã®ããã«æ©èœããããæãåºããŸãããã
å
¬åŒããã¥ã¡ã³ãã®äŸïŒ
{% macro dump_users(users) -%} <ul> {%- for user in users %} <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li> {%- endfor %} </ul> {%- endmacro %} {% call(user) dump_users(list_of_user) %} <dl> <dl>Realname</dl> <dd>{{ user.realname|e }}</dd> <dl>Description</dl> <dd>{{ user.description }}</dd> </dl> {% endcall %}
次ã®ããšãèµ·ãããŸãã
caller
ãšããååã®äžæãã¯ããäœæãããŸãã ãã¯ãã®æ¬æã¯ã {% call... %}
ãš{% endcall %}
éã®ã³ã³ãã³ãã§ãã ãã¯ãã¯åŒæ°ãæã€ããšãã§ããŸãïŒäžèšã®äŸã§ã¯ãããã¯1ã€ã®user
åŒæ°ã§ãïŒããåŒæ°ãæããªãããšãã§ããŸãïŒç°¡ææ§æ{% call something(...) %}
ïŒãcall(...)
ã³ã³ã¹ãã©ã¯ãã®åŸã«æå®ããããã¯ããcall(...)
ãŸãã 圌ã¯caller
ãã¯ãã«ã¢ã¯ã»ã¹ã§ããããããããã䜿çšããŸãïŒäœ¿çšããªãå ŽåããããŸãïŒã
ãã ããJinja2ã®ãã¯ãã¯ãæååãè¿ã颿°ã«ãããŸããã ãããã£ãŠã
CallBlock
ããŒãã¯ãæ¡åŒµæ©èœã®è
žå
ã®ã©ããã§å®çŸ©ãã颿°ãåæ§ã«äŸçµŠããããšãã§ããŸãã
CallBlock
ã䜿çšããŠããã¹ããåŠçããäžè¬çãªæ¡åŒµæ©èœã¯ã次ã®ããã«ãªããŸãã
from jinja2.ext import Extension from jinja2 import nodes class ReplaceTabsWithSpacesExtension(Extension): tags = {"replacetabs"} def parse(self, parser): lineno = next(parser.stream).lineno
ã©ã®ããã«æ©èœããŸããïŒ
call_method
ã¯ãJinja2ããŒãã®ã¯ã©ã¹ã¡ãœãããžã®åŒã³åºããã©ããããExtension
ã¯ã©ã¹ã®ç¹å¥ãªã¡ãœããã§ãã çµæã¯ãã©ã¡ãŒã¿ãŒãšããŠCallBlock
åŒãæåŸ
ããå Žæãç¹ã«CallBlock
颿°åŒã³åºããæåŸ
ããå Žæã«æž¡ãããšãã§ããŸããCodeBlock
ã®parse
CodeBlock
ããæ»ããšããæ¥ããšã ReplaceTabsWithSpacesExtension._process
ã¡ãœãããåŒã³åºããŸãã æåã«ã call_method
åŒã³åºãäžã«æå®ãããåŒæ°ãæž¡ããïŒãã®å Žåã1ã€ã®åŒæ°ã¯4ã€ã®ã¹ããŒã¹ã®æååã§ãïŒã次ã«åãcaller
ãæž¡ãããŸããããã¯åã«Jinja2ãã¯ãã§ãããåã«æååãååŸããããã«åŒã³åºãããŸããcaller
ãã¯ããåŒæ°ã§åŒã³åºãå¿
èŠãããå Žåã CodeBlock
ããŒãã®ãã£ãŒã«ãã«ãªã¹ãããå¿
èŠããããŸãïŒãã®äŸã§ã¯ç©ºã®ãªã¹ãããããŸãïŒã
Githubã®äœ¿çšäŸãåç
§ããŠãã ããã
æåŸã«ã
CallBlock
ã䜿çšããæ¡åŒµæ©èœã®ããå°ãè€éãªäŸãšã仿¥è¡ã£ããã1ã€ã®ããšã¯ãã€ã³ãã³ããã£ã¯ãµãŒã§ãã ãã³ãã¬ãŒãã®ãœãŒã¹ã³ãŒããšçµæã®äž¡æ¹ãã€ã³ãã³ãã«é¢ããŠé©åã«èŠããããã«ãå°ãªããšãããã€ãã®éèŠã§ãªããã³ãã¬ãŒããJinja2ã§èšè¿°ããããšã¯ã»ãšãã©äžå¯èœã§ããããšãç¥ãããŠããŸãã ãã®èª€è§£ãä¿®æ£ããã¿ã°ã远å ããŠã¿ãŸãããã
import re from jinja2.ext import Extension from jinja2 import lexer, nodes
䜿çšäŸïŒ
if __name__ == "__main__": env = Environment(extensions=[AutoindentExtension]) template = env.from_string(u""" {%- autoindent %} {% if True %} What is true, is true. {% endif %} {% if not False %} But what is false, is not true. {% endif %} {% endautoindent -%} """) print(template.render())
Githubã§ãã¹ãŠèŠãããšãã§ããŸããç¬èªã®æ¡åŒµæ©èœã®éçºã«ãé¢å¿ããå¯ãããã ãããããšãããããŸãããã®èšäºã§äœ¿çšãããŠããJinjaããŽãšãã®ããŒãã®æš©å©ã¯ãJinjaããŒã ã«å±ããŸãïŒè©³çްïŒã