{ "info": { "author": "Tim Perevezentsev", "author_email": "riffm2005@gmail.com", "bugtrack_url": null, "classifiers": [], "description": "====\nmint\n====\n\n- about_\n\n- usage_\n\n- syntax_\n\n - tags_\n\n - attributes_\n\n - escaping_\n\n - python expressions_\n\n - loops_\n\n - conditions_\n\n - comments_\n\n - simplification_\n\n- inheritance_\n\n- utils_\n\n- CLI_\n\n\n.. _about:\n\n-----\nabout\n-----\n\n**mint** - is small, fast and easy to use (x)html templates engine.\nImplemented with python language.\n\nWhy use **mint**?:\n\nsingle python module\n You can copy ``mint.py`` to your project package and use it.\n\nminimalistic syntax\n Your templates will become smaller and more readable due to\n indent based syntax.\n\nworks fast\n **mint** uses ``ast`` python module from standard library\n (since python2.6, thank you Armin and co). So all templates compiles to\n optimized python byte code (during first call) which works fast.\n\nsmart\n **mint** knows about (x)html tags and attributes,\n so you get smart escaping. (There is a plan to implement html\n validation during rendering)\n\nnot standing in your way\n **mint** does't hide exceptions like some other template engines, and\n shows line in your template file where exception was raised\n\nTemplate engine was inspired by haml (a template engine written in ruby),\nbut some concepts were redisigned for simplification and adoptation to python world.\n\n\nHome page: https://github.com/riffm/mint\nIssue tracker: https://github.com/riffm/mint/issues\n\n.. _usage:\n\n-----\nusage\n-----\n\nSimple API::\n\n >>> import mint\n >>> loader = mint.Loader('./templates', cache=True)\n >>> namespace = dict(a='a', b='b')\n >>> result = loader.get_template('index.mint').render(**namespace)\n\n``mint.Loader`` accepts names of directories and then search for template files\nby name provided in ``get_template(name)`` call.\n\n.. _syntax:\n\n------\nsyntax\n------\n\n**mint** syntax is based on indention, so you see the document structure and\nupdate document fast. You can move blocks of code and do not search for\nbegining of parent tag and where it ends.\n\n\n.. _tags:\n\ntags\n----\n\nJust use ``@`` character before tag name to render a tag::\n\n @tagname\n\nWhy **mint** does't use ``%`` char, like haml do?\nI think that ``@`` char is more readable and it is just third button on the keyboard,\nso you type it by one hand (without finger gymnastics).\nNext example shows tags structure::\n\n @html\n @head\n @body\n\nIndented tags ``@head`` and ``@body`` are children for tag ``@html`` (parent tag).\n\nText is interpreted as text::\n\n @div\n @p\n Text of paragraph\n\nSo last example will be rendered as::\n\n
\n

\n Text of paragraph\n

\n
\n\nBy the way you can use short variant::\n\n @div\n @p Text of paragraph\n\n\n.. _attributes:\n\nattributes\n----------\n\nTo define attribute **mint** uses concept similar to method calls::\n\n @div.id(content)\n\nPreviouse example will be rendered as::\n\n
\n\nTo define multiple attributes **mint** uses (so called) chaining::\n\n @img.alt().src(/img/my_picture.png)\n\nPreviouse example will be rendered as::\n\n \"\"\n\nNote that **mint** knows about selfclosed html tags.\n\nWhy do not use python dictionary declaration syntax instead?\nSomething like ``{alt:\"\", src:\"/img/my_picture.png\"}``\n\nBecause it is overloaded for html templating. \"Chained-methods-call\" like\nsyntax uses less chars to type.\n\n**mint** alows to set/append value of tag attribute somewhere inside tag::\n\n @div.class(main)\n // set value of attribute\n @.class(header)\n\n @div.class(main)\n // append value to attribute\n @+class( header)\n\nwill be rendered as::\n\n
\n\n
\n\nThis is very handy when you need to set content of tag and it's attributes based\non some condition.\n\n.. _escaping:\n\nescaping\n--------\n\nAs you know there are some chars we need to escape in xml. And **mint** does this\nautomatically for you. It escapes all text inside tags and attributes.\nAutoescaping can't be turned off::\n\n @a.href(/docs?type=1&published=true) docs\n @p.class( ' \" < > & )\n
\n\nWill be rendered as::\n\n docs\n

\n <div class="inside" />\n

\n\n\n.. _expressions:\n\npython expressions\n------------------\n\nOf course, template engine without possibility to insert python expressions is unusable.\nSo in **mint** you can do this with syntax similar to ``jinja2`` or ``django``::\n\n @html\n @head\n @title {{ doc.title }}\n @body\n @div.id(content)\n Here we have content {{ doc.content }}\n\nUnder the hood **mint** calls ``unicode`` on python expression\nand escapes result.\n\nNote that you can provide any valid python expression between tokens ``{{`` ``}}``.\nAlso note that you can use limited subset of python ``__builtins__``.\n\nIn **mint** templates expressions can be used inside text elements and inside attributes::\n\n @p.class(title {{ doc.main_doc_class }}).id({{ doc.id }}) {{ doc.body }}\n\nAs you remember all content inserted in tags (as text) and in attributes is\nescaped by **mint**. And this is good, but sometimes you need to insert\nunescaped html. For this purpose mint uses special class ``mint.Markup``, which\nimplements ``__html__`` method (this is something like convention). To insert\nhtml inside templates you need to mark your python variables with\n``mint.Markup`` inside your python code.\n\nIn previous example if ``doc.body`` has html we need attribute ``body`` to return\n``mint.Markup(html_string)``. And that ``html_string`` will be inserted in template\nwithout escaping. That is the preferred way to insert markup inside html template.\n\nAlso note that there are two contexts to insert markup - tag and attribute.\nIn case of tag ``mint.Markup`` instances will be inserted without modifications.\nBut if you attemted to insert markup in attribute it will be additionaly escaped.\n\nFor example we have such python code::\n\n class Doc(object):\n def __init__(self, title, body):\n self.title = mint.Markup(title)\n self.body = mint.Markup(body)\n\n doc = Doc('title', '

content of document

')\n\nAnd such template::\n\n @div.class(doc)\n @p.class(title).title({{ doc.title }}) {{ doc.title }}\n {{ doc.body }}\n\nThe result will be::\n\n
\n

\n title\n

\n

content of document

\n
\n\nThis feature of **mint** is very handy.\n\n.. _loops:\n\nloops\n-----\n\nIn **mint** you can use python statement ``for``::\n\n @ul\n #for img in images:\n @li @img.src({{ img.file }})\n\nNote that::\n\n @li @img.src({{ img.file }})\n\nis similar to::\n\n @li\n @img.src({{ img.file }})\n\nThis is inline tags notation.\n\n.. _conditions:\n\nconditions\n----------\n\nConditions are easy to write too::\n\n #for doc in docs:\n #if doc.id != current_id:\n @a.href({{ url_for('doc', id=doc.id) }}) {{ doc.title }}\n #elif doc.title == 'I need paragraph':\n @p {{ doc.title }}\n #else:\n {{ doc.title }}\n\n\n.. _comments:\n\ncomments\n--------\nTo comment a line use token ``//``::\n\n // In this div we provide content, yours C.O.\n @div.id(content)\n\nXml comments are supported, use token ``--``::\n\n -- In this div we provide content, yours C.O.\n @div.id(content)\n\nto get::\n\n \n
\n\nSometimes you need to use special tokens in text, so if a line starts with\ntoken ``\\`` line is not interpreted by **mint**::\n\n @p.class(title) Here we have title\n \\@p.class(title) Here we have title\n\nWill provide::\n\n

Here we have title

\n @p.class(title) Here we have title\n\n\n.. _simplification:\n\nsimplification\n--------------\n\nSimplification of syntax provides ambiguity. But it is very handy sometimes.\nIn **mint** templates you can write such things::\n\n @ul\n #for image in images:\n @li.class(image) @img.alt().src({{ image.path }})\n\nThis simplification alows to write nested tags in one line, one by one. In\nprevious example all ``img`` tags will be inside ``li``.\n\nRemember rule #1: This records::\n\n @div.id(1) @div.id(2) @div.id(3)\n\n @div.id(1)\n @div.id(2) @div.id(3)\n\n @div.id(1)\n @div.id(2)\n @div.id(3)\n\nare the same.\n\nRule #2: you can append text to and only to last tag when you use syntax\nsimplification::\n\n @ul\n #for doc in docs:\n @li @p.class(title) {{ doc.title }}\n @p.class(descr) {{ doc.description }}\n\n``li`` will be rendered as::\n\n
  • \n

    ...

    \n

    ...

    \n
  • \n\nBe careful when using syntax simplification.\n\n.. _inheritance:\n\n-----------\ninheritance\n-----------\n\n**mint** uses slots to implement template inheritance. Slot is nothing more but\npython function that retuns markup. Slot can be defined and called anywhere in template::\n\n // layout.mint\n @html\n @head\n @title {{ title }}\n @body\n @div.id(content)\n\n #def content():\n @p.class(title) {{ title }}\n {{ text }}\n\n #content()\n\n @div.id(footer)\n\nAs you can see in previous example we define slot ``content`` and call it after that.\nDuring call of slot it's content will be inserted in template. And if we need to insert\ndifferent content in that place we should inherit ``layout.mint`` and override ``content``\nslot implementation::\n\n // news.mint\n #base: layout.mint\n\n #def content():\n #for item in news:\n @a.href({{ url_for('news-item', id=item.id) }}) {{ news.title }}\n\nIt is simple and powerful concept.\n\nSlots are python functions, so they see all global variables passed to template and have\nown scope. This is very handy, because sometimes people have problems with such things\nin other templates engines.\n\nFor example we need a block inside ``for`` loop::\n\n // layout.mint\n @div.id(content)\n #for item in items:\n #loop_slot()\n\n // photos.mint\n #base: layout.mint\n\n #def loop_slot():\n @p.class(title) {{ item.title }}\n @img.alt().src({{ item.image.path }})\n\nFor **mint** this is natural behavior. And ``item`` is just global variable for\nslot ``loop_slot``. But in this case it's better to provide ``item`` to slot\nexplicitly::\n\n // layout.mint\n @div.id(content)\n #for item in items:\n #loop_slot(item)\n\n // photos.mint\n #base: layout.mint\n\n #def loop_slot(item):\n @p.class(title) {{ item.title }}\n @img.alt().src({{ item.image.path }})\n\nAlso we can call base slot inside overrided slot. In our case base slot will\npoint to slot with same name in our base template. ``__base__`` variable points\ninside current slot scope to implementation of current slot in parent template::\n\n // base.mint\n -- somewhere in head tag\n #def js():\n @script.type(text/javascript).src(/js/main.js)\n #js()\n\n\n // photos.mint\n #base: base.mint\n #def js():\n #__base__()\n @script.type(text/javascript).src(/js/photos.js)\n\nThis example will results in::\n\n \n \n \n\nSlots are plain python functions, slots returns ``Markup`` objects so we can pass slots\nor result of slot call to other slots.\n\nAnd more. We can use slots outside of templates. Lets take photos.mint from\nexample with ``for`` loop::\n\n >>> import mint\n >>> t = mint.Loader('.').get_template('photos.mint')\n >>> loop_slot = t.slot('loop_slot')\n >>> # lets take image somewhere\n >>> item = images.get(1)\n >>> loop_slot(item)\n Markup(u'

    ...

    \"\"')\n\nBut sometimes slots needs global variables, you must provide such variables\nwith kwargs in method ``slot(name, **globals)`` of ``Template`` object.\n\n\n.. _utils:\n\n-----\nutils\n-----\n\n**mint** provides global variable ``utils`` which contains useful constants and helper\nfunctions.\n\nDoctype declarations\n\n- ``utils.doctype.html_strict``\n- ``utils.doctype.html_transitional``\n- ``utils.doctype.xhtml_strict``\n- ``utils.doctype.xhtml_transitional``\n\nExample of usage::\n\n {{ utils.doctype.html_strict }}\n @html\n\nClass ``mint.Markup`` is ``utils.markup`` (this is replacement for hack ``{{ var|safe }}``)\n\n``utils.loop`` is helper function to use with ``for`` statement. It takes iterable\nobject and returns tuple of item and special object that consist of useful info for each\niteration::\n\n #for item, l in utils.loop(items):\n @a.href({{ item.url }})\n {{ item.title }} {{ (l.first, l.last, l.odd) }} {{ l.cycle('one', 'two', 'three') }}\n\nIn previous example ``l.cycle('one', 'two', 'three')`` will return one of values provided\nin sequence. It is handy to colorize tables.\n\nHtml helpers\n\n- ``utils.script``\n- ``utils.scripts``\n- ``utils.link``\n\n\n.. _CLI:\n\n----------------------\nCommand Line Interface\n----------------------\n\n``mint`` has a CLI. To list available options use ``--help`` flag::\n\n % python -m mint --help\n Usage: mint.py [options] [template]\n\n Options:\n -h, --help show this help message and exit\n -c, --code Show only python code of compiled template.\n -t, --tokenize Show tokens stream of template.\n -r N, --repeat=N Try to render template N times and display average time\n result.\n -p, --pprint Turn pretty print on.\n -m, --monitor Monitor current directory and subdirectories for changes\n in mint files. And render corresponding html files.\n\nCLI works in two modes:\n\n- rendering\n- monitoring\n\n\nThat's all folks!\n\n\n---------\nchangelog\n---------\n\nv0.5\n----\n\n* Smart indent. Tokenizer sets `indent level` for whole template equal indent\n level of first indented line (as in python)\n\n* Mint nodes now based on `ast.AST` and to transform `mint` tree to `python`\n tree we use `ast.NodeTransformer` subclass. This feature allows us write\n transformers for other languages (js =)\n\n* Added `pretty printing` of html result. Default indention is two spaces and\n is unchangable\n\n* Updated vim highlight for mint files\n\n* Added html helpers `utils.script`, `utils.link` and `utils.scripts`\n\n* New `CLI` interface. Some features\n\n * shows result python code listing for mint template\n\n * shows tokens stream for mint template\n\n * renders templates and prints result to stdout (note: if no outer variables\n used)\n\n * measures average rendering time for template (note: if no outer variables\n used)\n\n * `monitoring` feature\n\n* Fixes\n\n\nv0.4.4\n------\n\nWorking implementation", "description_content_type": null, "docs_url": null, "download_url": "UNKNOWN", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "http://github.com/riffm/mint", "keywords": null, "license": "MIT", "maintainer": null, "maintainer_email": null, "name": "mint", "package_url": "https://pypi.org/project/mint/", "platform": "UNKNOWN", "project_url": "https://pypi.org/project/mint/", "project_urls": { "Download": "UNKNOWN", "Homepage": "http://github.com/riffm/mint" }, "release_url": "https://pypi.org/project/mint/0.5/", "requires_dist": null, "requires_python": null, "summary": "Simple indetion based template engine", "version": "0.5" }, "last_serial": 794828, "releases": { "0.5": [ { "comment_text": "", "digests": { "md5": "516f9a5233f6ce45350959acc7bfae57", "sha256": "30df771d00852c041d80a863b5ab2c331fb97748807611c40ae0db71a7ef2d2c" }, "downloads": -1, "filename": "mint-0.5.tar.gz", "has_sig": false, "md5_digest": "516f9a5233f6ce45350959acc7bfae57", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20484, "upload_time": "2011-08-02T12:47:47", "url": "https://files.pythonhosted.org/packages/96/a1/9a1ad38ad36c38a3cdd4ffdfb945af099d278daf32533b12875d3736b3c8/mint-0.5.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "516f9a5233f6ce45350959acc7bfae57", "sha256": "30df771d00852c041d80a863b5ab2c331fb97748807611c40ae0db71a7ef2d2c" }, "downloads": -1, "filename": "mint-0.5.tar.gz", "has_sig": false, "md5_digest": "516f9a5233f6ce45350959acc7bfae57", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20484, "upload_time": "2011-08-02T12:47:47", "url": "https://files.pythonhosted.org/packages/96/a1/9a1ad38ad36c38a3cdd4ffdfb945af099d278daf32533b12875d3736b3c8/mint-0.5.tar.gz" } ] }