{"id":13393180,"url":"https://github.com/sstephenson/eco","last_synced_at":"2025-03-13T19:31:27.551Z","repository":{"id":1078117,"uuid":"922017","full_name":"sstephenson/eco","owner":"sstephenson","description":"Embedded CoffeeScript templates","archived":true,"fork":false,"pushed_at":"2019-07-02T05:26:52.000Z","size":339,"stargazers_count":1705,"open_issues_count":33,"forks_count":70,"subscribers_count":35,"default_branch":"master","last_synced_at":"2025-03-02T12:03:31.198Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"CoffeeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sstephenson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-09-19T05:01:25.000Z","updated_at":"2025-02-19T22:18:01.000Z","dependencies_parsed_at":"2022-07-06T06:00:51.460Z","dependency_job_id":null,"html_url":"https://github.com/sstephenson/eco","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sstephenson%2Feco","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sstephenson%2Feco/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sstephenson%2Feco/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sstephenson%2Feco/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sstephenson","download_url":"https://codeload.github.com/sstephenson/eco/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243469145,"owners_count":20295694,"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":[],"created_at":"2024-07-30T17:00:44.946Z","updated_at":"2025-03-13T19:31:25.163Z","avatar_url":"https://github.com/sstephenson.png","language":"CoffeeScript","funding_links":[],"categories":["CoffeeScript","Currently Supported Dialects"],"sub_categories":["HTML"],"readme":"Eco: Embedded CoffeeScript templates\n====================================\n\nEco lets you embed [CoffeeScript](http://coffeescript.org/) logic in\nyour markup. It's like EJS and ERB, but with CoffeeScript inside the\n`\u003c% ... %\u003e`. Use it from [Node.js](http://nodejs.org/) to render your\napplication's views on the server side, or compile your templates\nto JavaScript with the `eco` command-line utility and use them to\ndynamically render views in the browser.\n\nHere's how an Eco template looks:\n\n    \u003c% if @projects.length: %\u003e\n      \u003c% for project in @projects: %\u003e\n        \u003ca href=\"\u003c%= project.url %\u003e\"\u003e\u003c%= project.name %\u003e\u003c/a\u003e\n        \u003cp\u003e\u003c%= project.description %\u003e\u003c/p\u003e\n      \u003c% end %\u003e\n    \u003c% else: %\u003e\n      No projects\n    \u003c% end %\u003e\n\n# Usage\n\nUse `eco.render()` to render your templates. The first argument is the\ntemplate source as a string. The second argument is the context object\nwhich contains your view state and any helper methods you want to call.\n\n    eco = require \"eco\"\n    fs  = require \"fs\"\n\n    template = fs.readFileSync __dirname + \"/views/projects.html.eco\", \"utf-8\"\n    console.log eco.render template, projects: [\n      { name: \"Mobile app\", url: \"/projects/1\", description: \"Iteration 1\" },\n      { name: \"Home page redesign\", url: \"/projects/2\" }\n    ]\n\nEco is fully synchronous. If your template needs to access data from\nasynchronous operations, perform those first before calling `render`.\n\n## Language reference\n\nEco's syntax is simple:\n\n* `\u003c% expression %\u003e`: Evaluate a CoffeeScript expression without\n  printing its return value.\n* `\u003c%= expression %\u003e`: Evaluate a CoffeeScript expression, escape its\n  return value, and print it.\n* `\u003c%- expression %\u003e`: Evaluate a CoffeeScript expression and print\n  its return value without escaping it.\n* `\u003c%= @property %\u003e`: Print the escaped value of the property\n  `property` from the context object passed to `render`.\n* `\u003c%= @helper() %\u003e`: Call the helper method `helper` from the context\n  object passed to `render`, then print its escaped return value.\n* `\u003c% @helper -\u003e %\u003e...\u003c% end %\u003e`: Call the helper method `helper` with\n  a function as its first argument. When invoked, the function will\n  capture and return the content `...` inside the tag.\n* `\u003c%%` and `%%\u003e` will result in a literal `\u003c%` and `%\u003e` in the\n  rendered template, respectively.\n\n## A note about whitespace\n\nCoffeeScript is whitespace-sensitive, but your templates\naren't. Therefore, Eco code tags that begin an indented CoffeeScript\nblock must be suffixed with a colon. To indicate the end of an\nindented block, use the special tag `\u003c% end %\u003e`. For example:\n\n    \u003c% if @project.isOnHold(): %\u003e\n      On Hold\n    \u003c% end %\u003e\n\nYou don't need to write the `if` and `end` tags on separate lines:\n\n    \u003c% if @project.isOnHold(): %\u003e On Hold \u003c% end %\u003e\n\nAnd you can use the single-line postfix form of `if` as you'd expect:\n\n    \u003c%= \"On Hold\" if @project.isOnHold() %\u003e\n\nCertain forms in CoffeeScript, such as `else`, must be unindented\nfirst. Eco handles that for you automatically:\n\n    \u003c% if @project.isOnHold(): %\u003e\n      On Hold\n    \u003c% else if @project.isArchived(): %\u003e\n      Archived\n    \u003c% end %\u003e\n\n## The context object\n\nThe context object you pass to `eco.render()` becomes the value of\n`this` inside your template. You can use CoffeeScript's `@` sigil to\neasily access properties and call helper methods on the context\nobject.\n\n    eco.render \"\u003cp\u003e\u003c%= @description %\u003e\u003c/p\u003e\",\n      description: \"HTML 5 mobile app\"\n\n## Helpers\n\nHelper methods on your context object can access other properties on\nthe context object in the same way they're accessed in the template:\nthrough `this`, or with the `@` sigil.\n\n    translations = require \"translations\"\n\n    eco.render \"\u003cspan\u003e\u003c%= @translate 'common.welcomeText' %\u003e\u003c/span\u003e\",\n      language:  \"en\"\n      translate: (key) -\u003e\n        translations[@language][key]\n\n## Escaping and unescaping\n\nWhen you print an expression in a template with `\u003c%= ... %\u003e`, its\nvalue is HTML-escaped. For example,\n\n    eco.render \"\u003c%= @description %\u003e\",\n      description: \"\u003cstrong\u003eHTML 5\u003c/strong\u003e mobile app\"\n\nwould render:\n\n    \u0026lt;strong\u0026gt;HTML 5\u0026lt;/strong\u0026gt; mobile app\n\nYou can use the `\u003c%- ... %\u003e` tag to print the value of an expression\nwithout escaping it. So this code:\n\n    eco.render \"\u003c%- @description %\u003e\",\n      description: \"\u003cstrong\u003eHTML 5\u003c/strong\u003e mobile app\"\n\nwould produce:\n\n    \u003cstrong\u003eHTML 5\u003c/strong\u003e mobile app\n\nIt is sometimes useful to generate markup in helper methods. The\nspecial `safe` method on the context object tells Eco that the string\ncan be printed in `\u003c%= ... %\u003e` tags without being escaped. You can use\nthis in conjunction with the context object's `escape` method to\nselectively sanitize parts of the string. For example,\n\n    eco.render \"\u003c%= @linkTo @project %\u003e\",\n      project: { id: 4, name: \"Crate \u0026 Barrel\" }\n      linkTo: (project) -\u003e\n        url  = \"/projects/#{project.id}\"\n        name = @escape project.name\n        @safe \"\u003ca href='#{url}'\u003e#{name}\u003c/a\u003e\"\n\nwould render:\n\n    \u003ca href='/projects/4'\u003eCrate \u0026amp; Barrel\u003c/a\u003e\n\n## Custom escape helpers\n\nBy default, Eco's `escape` method takes a string and returns an\nHTML-escaped string. You can override this behavior to escape for\nformats other than HTML, or to bypass escaping entirely. For example,\n\n    eco.render \"From: \u003c%= @address %\u003e\",\n      address: \"Sam Stephenson \u003csstephenson@gmail.com\u003e\"\n      escape:  (string) -\u003e string\n\nwould return:\n\n    From: Sam Stephenson \u003csstephenson@gmail.com\u003e\n\n## Blocks and capturing\n\nYou can capture blocks of a template by wrapping them in a function\ndefinition. For example, rendering this template:\n\n    \u003c% div = (contents) =\u003e %\u003e\n       \u003cdiv\u003e\u003c%- contents %\u003e\u003c/div\u003e\n    \u003c% end %\u003e\n    \u003c%= div \"Hello\" %\u003e\n\nwould produce:\n\n    \u003cdiv\u003eHello\u003c/div\u003e\n\nCaptured blocks can be passed to helper methods too. In this example,\nthe capture body is passed to the `formFor` helper as its last\nargument. Then the `formFor` helper calls this argument to produce a\nvalue.\n\n    template = \"\"\"\n      \u003c%= @formFor @project, (form) =\u003e %\u003e\n        \u003clabel\u003eName:\u003c/label\u003e\n        \u003c%= form.textField \"name\" %\u003e\n      \u003c% end %\u003e\n    \"\"\"\n\n    eco.render template,\n      project: { id: 1, name: \"Mobile app\" }\n      formFor: (project, yield_to) -\u003e\n        form =\n          textField: (attribute) =\u003e\n            name  = @escape attribute\n            value = @escape @project[attribute]\n            @safe \"\u003cinput type='text' name='#{name}' value='#{value}'\u003e\"\n\n        url  = \"/projects/#{@project.id}\"\n        body = yield_to form\n        @safe \"\u003cform action='#{url}' method='post'\u003e#{body}\u003c/form\u003e\"\n\nNote: In general, you should use CoffeeScript's fat arrow (`=\u003e`) to\ndefine capturing functions, so that you have access to the context\nobject inside the captured block. Treat the plain arrow (`-\u003e`) as an\noptimization, for when you are certain the capture body will not need\nto reference properties or helper methods on the context object.\n\n\n# Contributing\n\nYou can check out the Eco source code from GitHub:\n\n    $ git clone http://github.com/sstephenson/eco.git\n\nTo run Eco's test suite, install\n[nodeunit](http://github.com/caolan/nodeunit) and run `cake test`.\n\nReport bugs on the [GitHub issue tracker](http://github.com/sstephenson/eco/issues).\n\n# License (MIT)\n\nCopyright (c) 2010 Sam Stephenson \u003csstephenson@gmail.com\u003e\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n# Special thanks\n\n* Jeremy Ashkenas \u003cjashkenas@gmail.com\u003e\n* Josh Peek \u003cjosh@joshpeek.com\u003e\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsstephenson%2Feco","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsstephenson%2Feco","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsstephenson%2Feco/lists"}