{"id":17109387,"url":"https://github.com/hkoba/yatt_lite","last_synced_at":"2026-04-02T02:48:00.683Z","repository":{"id":1043359,"uuid":"874076","full_name":"hkoba/yatt_lite","owner":"hkoba","description":"YATT::Lite - Template with \"use strict\"","archived":false,"fork":false,"pushed_at":"2025-04-02T08:22:22.000Z","size":2847,"stargazers_count":5,"open_issues_count":41,"forks_count":0,"subscribers_count":3,"default_branch":"dev","last_synced_at":"2025-04-06T12:06:47.710Z","etag":null,"topics":["perl","psgi","template-engine"],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hkoba.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2010-08-31T05:54:57.000Z","updated_at":"2025-03-29T08:42:19.000Z","dependencies_parsed_at":"2024-02-11T09:31:09.417Z","dependency_job_id":"1abd6185-35c3-4cd4-bc82-93ff79e078fa","html_url":"https://github.com/hkoba/yatt_lite","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hkoba%2Fyatt_lite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hkoba%2Fyatt_lite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hkoba%2Fyatt_lite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hkoba%2Fyatt_lite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hkoba","download_url":"https://codeload.github.com/hkoba/yatt_lite/tar.gz/refs/heads/dev","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248658342,"owners_count":21140926,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["perl","psgi","template-engine"],"created_at":"2024-10-14T16:23:05.973Z","updated_at":"2026-04-02T02:48:00.637Z","avatar_url":"https://github.com/hkoba.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"YATT::Lite - Template with \"use strict\" ![Build Status](https://github.com/hkoba/yatt_lite/actions/workflows/perl_linux.yml/badge.svg)\n==================\n\nYATT is Yet Another Template Toolkit, strongly aimed at **static checking of\ntemplate errors**.  \n[YATT::Lite] is the latest version of YATT, written in Pure Perl.\n\nNote: Although I have been using YATT::Lite in some side-projects\nfor my client since 2011\n(and previous version YATT.pm in all other main-projects\nfor them since late 2008),\nI am not yet satisfied especially with its API.\nActually, I want to discuss *How web templates should be* with someone.\nIf you are interested in this topic, please contact me!\n\n\nHow YATT templates look like\n--------------------\n\nBiggest goal of YATT is to detect as many kinds of errors as possible\nbefore it actually run. For example, YATT can detect\nmisspellings of template parameters and (so-called) widget names.\nFollowing is an example of valid yatt template:\n\n```xml\n\u003c!yatt:args who content\u003e\n\u003ch2\u003eHello \u0026yatt:who;!\u003c/h2\u003e\n\u003cp\u003e\u0026yatt:content;\u003c/p\u003e\n\u003cyatt:myfooter mycomp=who /\u003e\n\n\u003c!yatt:widget myfooter mycomp=\"?My Company\"\u003e\n\u0026copy; 2013 \u0026yatt:mycomp;, Inc.\n```\n\nIf you misspell ``who``, ``content``, ``myfooter`` and/or ``mycomp`` above,\nstatic check tool (``yatt lint``) detects them.  \nYou might think most good programmers don't do such mistakes.\nIf so, imagine who will write templates near future.\n...Do you want to write templates by yourself, forever? I don't.\nI want to employ designers and delegate all view related matters to them.\nAnd, designers often do such mistakes.\nDo you want to blame them everytime they misspelled? I don't.\nInstead, I want to give them good safe-guard tools.\nThat's why I started to make YATT.\n\nMinimum PSGI app example\n--------------------\n\nTo have more chance to detect errors, YATT::Lite manages **set(s) of templates**\ninstead of single template. In other words,\nYATT::Lite works like Virtual File System(VFS) of templates.  \nUsers of YATT::Lite will invoke ``$yatt-\u003erender($path,$args)``\nwith virtual template path + arguments\nand get its output. Here is a minimum psgi app example of YATT::Lite (Actually via YATT::Lite::Factory):\n\n```perl\nuse strict;\nuse FindBin;\nuse Plack::Request;\nuse Plack::Response;\n\nuse YATT::Lite::Factory;\nmy $yatt = YATT::Lite::Factory-\u003enew(doc_root =\u003e \"$FindBin::Bin/html\");\n\nreturn $yatt if YATT::Lite::Factory-\u003ewant_object; # To help yatt lint\n\nreturn sub {\n  my ($env) = @_;\n  my $req  = Plack::Request-\u003enew($env);\n  my $html = $yatt-\u003erender($env-\u003e{PATH_INFO}, $req-\u003eparameters);\n  my $res  = Plack::Response-\u003enew(200);\n  $res-\u003econtent_type('text/html');\n  $res-\u003ebody($html);\n  return $res-\u003efinalize;\n};\n```\n\nAbove code only serves ``*.yatt`` templates. To serve other static files\nlike ``*.css`` and ``*.gif``, your psgi app needs to analyze a request\nand route it to other handler (ie. Plack::App::File) for static files.  \nSince this is very common,\nYATT::Lite comes with sample Web Framework([WebMVC0]) \nwhich directly behaves as [PSGI] application.\nIt also supports FastCGI and CGI too. With the WebMVC0,\nminimum psgi app will look like following:\n\n```perl\nuse strict;\nuse FindBin;\n\nuse YATT::Lite::WebMVC0::SiteApp -as_base;\nmy $site = MY-\u003enew(doc_root =\u003e \"$FindBin::Bin/html\");\n\nreturn $site-\u003eto_app; # to_app is enough for yatt lint\n```\n\n\nFollowings are some comparison notes with other frameworks:\n\n* Like PHP, (WebMVC0::SiteApp of) YATT::Lite integrates static contents\ndirectory and (primary) template directory. It routes incoming requests\ndirectly into ``*.yatt`` template files. Also, it can hide ``.yatt`` extension\nby default (ie. if you have ``foo.yatt`` and\nincoming request is ``foo``, ``foo/bar`` or ``foo/bar/baz``, the ``foo.yatt``\nwill be invoked).\nAlso, you can define url routing patterns and per-directory hooks.\nYou can use many abstraction techniques too.\nEach templates are compiled on-the-fly and cached as perl scripts\nso you can add/modify your templates while running your webapp.\n\n* Unlike PHP and other template engines, YATT has quite HTML-like syntax. \nAll YATT syntax items are *namespace-prefixed* equivalents\nof HTML syntax items. i.e. ``\u003c!yatt:...\u003e`` for declarations,\n``\u003cyatt:...\u003e`` for invocations, ``\u0026yatt:...;`` for entity references\nand ``\u003c?perl...?\u003e`` for (dirty ;-) processing instructions.\nYou can configure YATT to use project/team specific namespace prefix,\nso designers can easily identify special tags.\n\n\nOne more example: Session\n--------------------\nYou can use YATT with other PSGI Middlewares as usual.\nHowever, if you want to get `yatt lint` support too, you must tell\n$yatt to know your actual psgi app (sub), by calling `$site-\u003ewrapped_by($sub)`.\n\n\n```perl\nuse strict;\nuse FindBin;\n\nuse YATT::Lite::WebMVC0::SiteApp -as_base, -Entity, qw/*CON/;\nuse YATT::Lite::PSGIEnv;\n\n{\n  my $site = MY-\u003enew(doc_root =\u003e \"$FindBin::Bin/html\");\n\n  Entity session =\u003e sub {\n    my ($this, $name, $default) = @_;\n    my Env $env = $CON-\u003eenv;\n    $env-\u003e{'psgix.session'}{$name} // $default;\n  };\n\n  Entity set_session =\u003e sub {\n    my ($this, $name, $value) = @_;\n    my Env $env = $CON-\u003eenv;\n    $env-\u003e{'psgix.session'}{$name} = $value;\n    '';\n  };\n\n  use Plack::Builder;\n  return $site-\u003ewrapped_by(builder {\n    enable 'Session';\n    $site-\u003eto_app;\n  });\n}\n```\n\n\nNow you can use two entity functions: \n``\u0026yatt:session(name,default);`` and ``\u0026yatt:set_session(name,value);``.\n\n```xml\n\u003c!yatt:args user\u003e\n\u003cyatt:if \"\u0026yatt:user;\"\u003e\n\n set user as \u0026yatt:user; \u003cbr\u003e\n \u0026yatt:set_session(user,:user);\n \u003ca href=\"./\"\u003eback\u003c/a\u003e\n\n\u003c:yatt:else/\u003e\n\n \u003ch2\u003eHello, \u0026yatt:session(user,((Unknown user)));\u003c/h2\u003e\n \u003cform\u003e\n   User name: \u003cinput name=\"user\"\u003e\u003cinput type=\"submit\"\u003e\n \u003c/form\u003e\n\n\u003c/yatt:if\u003e\n```\n\n\nYou can define entity functions in ``app.psgi`` and/or\nper-directory ``.htyattrc.pl`` script.\nEntity functions are used like ``\u0026yatt:myfunc(..);``\nanywhere in .yatt templates\nto embed variables, process user parameters and access backend databases.\n\n* Unlike Ruby-on-Rails and other major Web Frameworks,\nYATT::Lite itself is Model-Agnostic.\nIn other words, YATT::Lite do not depend on any specific ORM.\nSo you can use your favorite ORMs.\n(Actually, WebMVC0 contains some support for ORM ([DBIx::Class]),\nbut you are not limited to them.)\n\nYATT focuses empowering Web Designers\n--------------------\n\nAs described above, YATT is designed primarily to give\nmore power (with safety) to **Template Writers (Web Designers)**,\nwho are rarely trained as programmers.\nWith YATT, you can safely delegate more tasks to them.\n(This means programmers can concentrate on fundamental infrastructure tasks\nrather than view-related, biz-issue-specific, ad-hoc tasks.\nAnd eventually, you might find\nyou can keep your programming team slim, fit and dense than others;-)\n\nTo make YATT easily understandable by Web Designers,\nYATT has declarative, compositional semantics.\nYATT allows them to define **new tags** (called *yatt widgets*).\nSo, from their point of view, YATT is just a seemless extension to HTML.\n\nTo give safety to Web Designers, YATT provides ``yatt lint``, \nwhich is integrated to [Emacs] via ``yatt-mode.el``.\nEverytime they save a YATT template, yatt lint verifies it.\nSyntax errors, spelling misses of variables, entities and widget names...\nall such errors will be detected instantly,\nand emacs will jump to the line of the error.\n\nAlso, YATT has many safer default behaviors, ie. automatic output escaping\nbased on argument type declaration and config file naming convention\nwhich helps access restriction.\n\n\nINSTALLATION\n--------------------\n\nYou have several options to install YATT::Lite.\n\n### Minimum setup one-liner\n\n    $ mkdir myapp1\n    $ cd myapp1\n    $ curl https://raw.githubusercontent.com/hkoba/yatt_lite/dev/scripts/skels/min/install.sh | bash\n    $ ls\n    app.psgi  html  lib\n    $ git status -su\n    A  .gitmodules\n    A  lib/YATT\n    ?? app.psgi\n    ?? html/index.yatt\n    $ plackup\n\nAbove script also works from locally installed repo, like following:\n\n    $ mkdir ../myapp2\n    $ cd  ../myapp2\n    $ ../myapp1/lib/YATT/scripts/skels/min/install.sh -l\n    $ ls\n    app.psgi  html  lib\n    $\n\n(with -l, lib/YATT is symlinked. without -l, uses git submodule)\n\n### cpanm\n\nIf you simply want to use YATT::Lite only as a Perl module,\nYou can install YATT::Lite like other CPAN modules.\n\n    $ cpanm YATT::Lite\n\nAlso, if you want to use latest version of YATT::Lite,\nyou can install YATT::Lite just through git command.\n(But see [NON-STANDARD DIRECTORY STRUCTURE](#non-standard-directory-structure))\n\n    $ git clone git://github.com/hkoba/yatt_lite.git lib/YATT\n    $ (cd lib/YATT \u0026\u0026 cpanm --installdeps .)\n\n    # or If your project is managed in git, clone as submodule like this:\n\n    $ git submodule add git://github.com/hkoba/yatt_lite.git lib/YATT\n    $ git submodule update --init\n    $ (cd lib/YATT \u0026\u0026 cpanm --installdeps .)\n\nTo create a yatt-enabled webapp, just copy sample app.psgi and run plackup:\n\n    $ cp lib/YATT/samples/app.psgi .\n    $ mkdir html\n    $ plackup\n\nNow you are ready to write your first yatt app.\nOpen your favorite editor and create a yatt template ``html/index.yatt``\nlike this:\n\n```xml\n\u003c!yatt:args x y\u003e\n\u003ch2\u003eHello \u0026yatt:x; world!\u003c/h2\u003e\n\u0026yatt:y;\n```\n\n\nThen try to access:\n  \n     http://0:5000/\n     http://0:5000/?x=foo\n     http://0:5000/?x=foo\u0026y=bar\n\n\n## Emacs integration (yatt-mode.el and yatt-lint-any-mode.el)\n\nCurrently, there is no installer for yatt-mode.el yet.\nIt depends on ``mmm-mode.el`` and ``cperl-mode.el``,\nso please install them manually if you don't have them.\n\nAfter that, to use yatt-mode,\nyou may need to add something like following to your ``.emacs``\n(assuming you cloned yatt_lite git repository as ~/perl5/lib/YATT):\n\n```elisp\n(load \"~/perl5/lib/YATT/elisp/yatt-autoload.el\")\n```\n\nThis adds autoload definition of ``yatt-mode``.\nIt also adds ``yatt-lint-any-mode.el``, which can do save-time check\nfor other perl-related files (*.pm, *.pl...) too.\n\n\nSUPPORT AND DOCUMENTATION\n--------------------\n\nYou can look for Source Code Repository at:\n\n    https://github.com/hkoba/yatt_lite\n\n\n### Document viewer (ylpodview)\n\nIn source distribution, \nbasic documents are placed under ``YATT/Lite/docs``. You can read them via:\nhttps://yatt-yl-podview-rrdekxdjda-an.a.run.app/\n(But for now, most pods are not yet finished and written only in Japanese.)\n\nAlso, you can run ylpodview (POD viewer) locally by:\n\n    $ cd lib\n    $ plackup YATT/samples/ylpodview/approot/app.psgi\n\nand try to access http://0:5000/\n\nNON-STANDARD DIRECTORY STRUCTURE\n--------------------\n\nYATT::Lite distribution doesn't conform normal CPAN style \ndirectory structure. It works best when it is cloned as ``YATT/``\nin one of your ``@INC`` directories. This is experimental,\nbut intentional. Because: \n\n1. I want to use YATT::Lite as a git submodule.\n   IMHO, to make/keep web-framework useful,\n   it is vitally important to allow evolution of each installation\n   of the web-framework. And to make sure such evolution manageable,\n   staying under git is most practical way for github hosted project.\n\n2. To make such evolution safe, I need to bundle all test suits.\n   Also, support scripts should be kept consistent with them.\n   So, tests and scripts for yatt is placed under\n   ``lib/YATT/t`` and ``lib/YATT/scripts``.\n\n\nCOPYRIGHT AND LICENCE\n--------------------\n\nCopyright (C) 2007..2014 \"KOBAYASI, Hiroaki\"\n\nThis program is free software; you can redistribute it and/or modify it\nunder the same terms as Perl itself.\n\n[YATT::Lite]: https://yatt-yl-podview-rrdekxdjda-an.a.run.app/mod/YATT::Lite\n[PSGI]: http://plackperl.org/\n[WebMVC0]: https://yatt-yl-podview-rrdekxdjda-an.a.run.app/mod/YATT::Lite::WebMVC0::SiteApp\n[DBIx::Class]: https://yatt-yl-podview-rrdekxdjda-an.a.run.app/mod/DBIx::Class\n[Emacs]: http://www.gnu.org/software/emacs/\n[cpanminus]: http://search.cpan.org/perldoc?App::cpanminus#INSTALL\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhkoba%2Fyatt_lite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhkoba%2Fyatt_lite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhkoba%2Fyatt_lite/lists"}