{"id":15225212,"url":"https://github.com/tategakibunko/jingoo","last_synced_at":"2025-04-09T19:09:19.224Z","repository":{"id":2501641,"uuid":"3476397","full_name":"tategakibunko/jingoo","owner":"tategakibunko","description":"OCaml template engine almost compatible with jinja2","archived":false,"fork":false,"pushed_at":"2024-03-12T23:22:26.000Z","size":694,"stargazers_count":129,"open_issues_count":5,"forks_count":18,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-09T19:09:11.967Z","etag":null,"topics":["jinja2","ocaml","template-engine"],"latest_commit_sha":null,"homepage":"","language":"OCaml","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/tategakibunko.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2012-02-18T05:31:43.000Z","updated_at":"2025-02-01T00:38:49.000Z","dependencies_parsed_at":"2024-03-13T00:27:30.863Z","dependency_job_id":"59c7d02c-922d-4bcd-a577-729bb2b226ae","html_url":"https://github.com/tategakibunko/jingoo","commit_stats":null,"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tategakibunko%2Fjingoo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tategakibunko%2Fjingoo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tategakibunko%2Fjingoo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tategakibunko%2Fjingoo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tategakibunko","download_url":"https://codeload.github.com/tategakibunko/jingoo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248094993,"owners_count":21046770,"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":["jinja2","ocaml","template-engine"],"created_at":"2024-09-28T18:05:09.725Z","updated_at":"2025-04-09T19:09:19.183Z","avatar_url":"https://github.com/tategakibunko.png","language":"OCaml","funding_links":[],"categories":["Web Development","\u003ca name=\"OCaml\"\u003e\u003c/a\u003eOCaml"],"sub_categories":[],"readme":"# jingoo\n\n## About jingoo\n\nJingoo is OCaml template engine almost compatible with [Jinja2](https://github.com/pallets/jinja/)(python template engine).\n\n## Install\n\n### manual\n\n```bash\nmake\nsudo make install\n```\n### opam\n\n```bash\nopam install jingoo\n```\n\n## Difference between Jinja2 and Jingoo\n\n1. i18n features are not supported yet.\n2. Cause of language difference between ocaml and python,\n   some of built-in filters are different from original one,\n   especially orders of arguments and supported optional arguments etc.\n3. Single line comment is not supported. Because single '#' is used very much especially in html.\n\n## Usage\n\n### Simple usage\n\n```ocaml\nopen Jingoo\n\n(* output from direct string template *)\nlet result = Jg_template.from_string \"{{ msg }}\" ~models:[(\"msg\", Jg_types.Tstr \"hello, world!\")]\n\n(* or output from file template *)\nlet result2 = Jg_template.from_file \"hello.jingoo\" ~models:[(\"msg\", Jg_types.Tstr \"hello, world!\")]\n\n(* or you can use functional model like this by using Jg_template2 module(ver \u003e= 1.4.0) *)\nlet result3 = Jg_template2.from_string \"{{ msg }}(random value = {{ randam_int }})\" ~models:(function\n | \"msg\" -\u003e Jg_types.Tstr \"hello, world!\"\n | \"randam_int\" -\u003e Jg_types.Tint (Random.int 100)\n | _ -\u003e Jg_types.Tnull\n)\n\n(* or you can use closure for models by using Jg_template2 module(ver \u003e= 1.4.0) *)\nlet hash = Hashtbl.create 10 in\nlet () = Hashtbl.add hash \"msg\" (Jg_types.Tstr \"hello, world!\") in\nlet result4 = Jg_template2.from_string \"{{ msg }}\" ~models:(fun key -\u003e\n  try Hashtbl.find hash key with Not_found -\u003e Tnull\n)\n```\n\n### More detailed example\n\n### template code\n\n```jinja2\n{# sample.jingoo #}\n\u003ch1\u003e{{ title }}\u003c/h1\u003e\n\n\u003cul\u003e\n{% for user in users %}\n  \u003cli\u003e\u003ca href=\"{{ user.url }}\"\u003e{{ user.name }}(age = {{ user.age }})\u003c/a\u003e\u003c/li\u003e\n{% endfor %}\n\u003c/ul\u003e\n\n{% if is_debug %}\n\u003cp\u003ethis is debug mode!\u003c/p\u003e\n{% endif %}\n```\n\n### ocaml code\n\n```ocaml\nopen Jingoo\n\nlet result = Jg_template.from_file \"sample.jingoo\" ~models:[\n  (\"title\", Jg_types.Tstr \"more detailed example\");\n  (\"is_debug\", Jg_types.Tbool true);\n  (\"users\", Jg_types.Tlist [\n    Jg_types.Tobj [\n      (\"name\", Jg_types.Tstr \"taro\");\n      (\"url\", Jg_types.Tstr \"https://example.com\");\n      (\"age\", Jg_types.Tint 20);\n    ];\n    Jg_types.Tobj [\n      (\"name\", Jg_types.Tstr \"jiro\");\n      (\"url\", Jg_types.Tstr \"https://example2.com\");\n      (\"age\", Jg_types.Tint 10);\n    ];\n  ])\n]\n```\n\n### Custom filter example\n\nSet your custom filter to `filters` field of environment.\n\n```ocaml\nopen Jingoo\n\nlet to_mail ?(kwargs=[]) ?(defaults=[]) value =\n  let id = Jg_runtime.string_of_tvalue value in\n  let domain = Jg_runtime.string_of_tvalue (Jg_runtime.jg_get_kvalue \"domain\" kwargs ~defaults) in\n  Jg_types.Tstr (id ^ \"@\" ^ domain)\n\nlet () =\n  let result = Jg_template.from_string \"{{id | to_mail(domain='gmail.com')}}\"\n    (* set your extension to 'filters' field of environment *)\n    ~env:{Jg_types.std_env with\n      filters = [\n        (* CAUTION!: if jingoo \u003c= 1.2.21, use 'Jg_runtime.func_arg1' instead of 'Jg_types.func_arg1_kw' *)\n        (\"to_mail\", Jg_types.func_arg1_kw (to_mail ~defaults:[\n          (\"domain\", Jg_types.Tstr \"gmail.com\");\n        ]));\n      ]\n    }\n    ~models:[\n      (\"id\", Jg_types.Tstr \"foo\")\n    ] in\n  (* should output 'foo@gmail.com' *)\n  print_endline result\n```\n\n### Dynlink filter example\n\n1. Write your own filter(`my_ext.ml` for example) and add it by `Jg_stub.add`(namespace as `my_ext` and func_name as `to_md5` for example).\n\n```ocaml\nopen Jingoo\n\nlet to_md5 ?(kwargs=[]) ?(defaults=[]) value =\n  let seed = Jg_runtime.jg_get_kvalue \"seed\" kwargs ~defaults in\n  match value, seed with\n  | Jg_types.Tstr str, Jg_types.Tstr seed -\u003e\n     Jg_types.Tstr (Digest.to_hex (Digest.string (str ^ seed)))\n  | _ -\u003e Jg_types.Tnull\n\nlet () =\n  (* CAUTION!: if jingoo \u003c= 1.2.21, use 'Jg_runtime.func_arg1' instead of 'Jg_types.func_arg1_kw' *)\n  Jg_stub.add_func ~namespace:\"my_ext\" ~func_name:\"to_md5\" (Jg_types.func_arg1_kw (to_md5 ~defaults:[\n    (\"seed\", Jg_types.Tstr \"\");\n  ]))\n```\n\n2. Compile it to `my_ext.cmxs` by `-shared` option.\n\n```bash\nocamlfind ocamlopt -shared -o my_ext.cmxs my_ext.ml\n```\n\n3. Set `my_ext.cmxs` to `extensions` field of environment, and you can use your custom filter `my_ext.to_md5`.\n\n```ocaml\nopen Jingoo\n\nlet result = Jg_template.from_string \"{{msg | my_ext.to_md5(seed='aaa')}}\"\n  (* set your extension to 'extensions' field *)\n  ~env:{Jg_types.std_env with\n    extensions = [\n      \"my_ext.cmxs\";\n    ]\n  }\n  ~models:[\n    (\"msg\", Jg_types.Tstr \"foo\");\n  ] in\n(* should output '3cb988a734183289506ab7738261c827' *)\nprint_endline result\n```\n\n## Cheatsheet\n\nSee [samples](https://github.com/tategakibunko/jingoo/tree/master/example/samples) directory.\n\n`*.jingoo` is template example and `*.expected` is expected string.\n\n## Documentation\n\n[http://tategakibunko.github.io/jingoo/](http://tategakibunko.github.io/jingoo/)\n\n## Playground\n\n[https://sagotch.github.io/try-jingoo/](https://sagotch.github.io/try-jingoo/)\n\n## License\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftategakibunko%2Fjingoo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftategakibunko%2Fjingoo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftategakibunko%2Fjingoo/lists"}