{"id":18319753,"url":"https://github.com/redding/nm","last_synced_at":"2026-05-17T06:40:27.390Z","repository":{"id":15963053,"uuid":"18705698","full_name":"redding/nm","owner":"redding","description":"Node-Map: a data templating DSL.","archived":false,"fork":false,"pushed_at":"2021-06-23T14:10:54.000Z","size":94,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-08T00:55:43.047Z","etag":null,"topics":["json","ruby","template-language"],"latest_commit_sha":null,"homepage":"","language":"Ruby","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/redding.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":"2014-04-12T14:18:38.000Z","updated_at":"2021-06-23T14:10:53.000Z","dependencies_parsed_at":"2022-09-13T18:21:50.917Z","dependency_job_id":null,"html_url":"https://github.com/redding/nm","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"purl":"pkg:github/redding/nm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redding%2Fnm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redding%2Fnm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redding%2Fnm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redding%2Fnm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/redding","download_url":"https://codeload.github.com/redding/nm/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/redding%2Fnm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279008451,"owners_count":26084459,"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","status":"online","status_checked_at":"2025-10-11T02:00:06.511Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["json","ruby","template-language"],"created_at":"2024-11-05T18:14:09.710Z","updated_at":"2025-10-13T07:08:17.984Z","avatar_url":"https://github.com/redding.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nm\n\nNode-Map: a data templating DSL. Named for its two main markup methods: \"node\" and \"map\". Designed to template data objects for JSON/BSON/whatever/etc serialization.\n\n## Usage\n\nTemplate:\n\n```ruby\n# in /path/to/views/slideshow.json.nm\n\nnode \"slideshow\" do\n  node \"start_slide\", start_slide\n  node \"slides\" do\n    map slides do |slide|\n      node \"id\",    slide.id\n      node \"title\", slide.title\n      node \"image\", slide.image_url\n      node \"thumb\", slide.thumb_url\n      node \"url\",   slide.url\n    end\n  end\nend\n```\n\nRender:\n\n```ruby\nrequire \"nm\"\nsource = Nm::Source.new(\"/path/to/views\")\nsource.render(\n  \"slideshow.json\",\n  locals: {\n    start_slide: 1,\n    slides: [ ... ] #=\u003e list of slide objects 1, 2 and 3\n  }\n)\n```\n\nOutput:\n\n```ruby\n{ \"slideshow\" =\u003e {\n    \"start_slide\" =\u003e 1,\n    \"slides\" =\u003e [\n      { \"id\"    =\u003e \"slide-1\",\n        \"title\" =\u003e \"Slide 1\",\n        \"thumb\" =\u003e \"//path/to/slide-1-thumb.jpg\",\n        \"image\" =\u003e \"//path/to/slide-1-image.jpg\",\n        \"url\"   =\u003e \"//path/to/slide-1-url\",\n      },\n      { \"id\"    =\u003e \"slide-2\",\n        \"title\" =\u003e \"Slide 2\",\n        \"thumb\" =\u003e \"//path/to/slide-2-thumb.jpg\",\n        \"image\" =\u003e \"//path/to/slide-2-image.jpg\",\n        \"url\"   =\u003e \"//path/to/slide-2-url\",\n      },\n      { \"id\"    =\u003e \"slide-3\",\n        \"title\" =\u003e \"Slide 3\",\n        \"thumb\" =\u003e \"//path/to/slide-3-thumb.jpg\",\n        \"image\" =\u003e \"//path/to/slide-3-image.jpg\",\n        \"url\"   =\u003e \"//path/to/slide-3-url\",\n      }\n    ]\n  }\n}\n```\n\n## Notes\n\n### Cache Templates\n\nBy default the source doesn't cache template files. You can configure it to cache templates using the `:cache` option:\n\n```ruby\nsource = Nm::Source.new(\"/path/to/views\", cache: true)\n```\n\n### Default locals\n\nYou can specify a set of default locals to use on all renders for a source using the `:locals` option:\n\n```ruby\nsource =\n  Nm::Source.new(\"/path/to/views\", locals: { \"something\" =\u003e \"value\" })\n```\n\n### Render Format\n\nRendering templates returns a data object (`::Hash` or `::Array`). To serialize, bring in your favorite JSON/BSON/whatever serializer and pass the rendered object to it.\n\n### Markup Methods\n\nThere are two main markup methods:\n\n* `node`: create a named attribute on a hash object\n* `map`: create a list object mapped from a given list\n\n### Default render value\n\nNm templates render an empty object (ie `::Hash.new`) if no source is given or no markup methods are called in the template source. The idea is that the templates should always return *something* and avoid `nil` values as much as possible.\n\nThis is also more consistent with rendering mapped lists vs reduced objects.  Say your are mapping a list of objects in your template (using the `map` markup method):\n\n```ruby\nmap incoming_list do |item|\n  node \"name\",  item.name\n  node \"value\", item.value\nend\n```\n\nIf there are no items in the incoming list, the template render produces an empty list. Now say you are reducing an incoming list to a single object:\n\n```ruby\nincoming_list.each do |item|\n  node item.name, item.value\nend\n```\n\nIf there are no items in the incoming list, no markup methods are called, but the template render still produces an empty object b/c that is the default value.\n\n### Partials\n\n**Note**: using partials negatively impacts template rendering performance.\n\n(from example above)\n\n```ruby\n# in /path/to/views/slideshow.json.nm\n\nnode \"slideshow\" do\n  node \"start_slide\", start_slide\n  node \"slides\" do\n    map slides do |slide|\n      partial \"_slide.json\", slide: slide\n    end\n  end\nend\n\n# in /path/to/views/_slide.json.nm\n\nnode \"id\",    slide.id\nnode \"title\", slide.title\nnode \"image\", slide.image_url\nnode \"thumb\", slide.thumb_url\nnode \"url\",   slide.url\n```\n\nThis will render the same output as above.\n\n### Markup Aliases\n\nIf you find you need to use a local named `node` or `map`, the markup methods are aliased as `n`, `_node`, `m`, and `_map` respectively. Any combination of aliases is valid:\n\n```ruby\nnode \"slideshow\" do\n  n \"start_slide\", start_slide\n  _node \"slides\" do\n    _map slides do |slide|\n      _node \"id\",    slide.id\n      node  \"title\", slide.title\n      _node \"image\", slide.image_url\n      node  \"thumb\", slide.thumb_url\n      _node \"url\",   slide.url\n    end\n    m other_slides do |slide|\n      node  \"id\",    slide.id\n      _node \"title\", slide.title\n      node  \"image\", slide.image_url\n      _node \"thumb\", slide.thumb_url\n      node  \"url\",   slide.url\n    end\n  end\nend\n```\n\n## Installation\n\nAdd this line to your application\"s Gemfile:\n\n    gem \"nm\"\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install nm\n\n## Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am \"Added some feature\"`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredding%2Fnm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fredding%2Fnm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fredding%2Fnm/lists"}