{"id":28972549,"url":"https://github.com/ember-cli/ember-template-imports","last_synced_at":"2025-06-24T11:06:55.471Z","repository":{"id":38308327,"uuid":"339856328","full_name":"ember-cli/ember-template-imports","owner":"ember-cli","description":"Template import support in Ember!","archived":false,"fork":false,"pushed_at":"2025-02-28T17:31:17.000Z","size":1926,"stargazers_count":76,"open_issues_count":13,"forks_count":42,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-06-09T18:27:08.468Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","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/ember-cli.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","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":"2021-02-17T21:07:29.000Z","updated_at":"2025-03-14T12:24:03.000Z","dependencies_parsed_at":"2023-10-15T14:53:26.123Z","dependency_job_id":"8929d566-98eb-4849-8506-93cf74344292","html_url":"https://github.com/ember-cli/ember-template-imports","commit_stats":{"total_commits":147,"total_committers":23,"mean_commits":6.391304347826087,"dds":0.8435374149659864,"last_synced_commit":"21c232c629e9d48b18b42a69d0617fd8c62c2549"},"previous_names":["ember-cli/ember-template-imports"],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/ember-cli/ember-template-imports","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ember-cli%2Fember-template-imports","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ember-cli%2Fember-template-imports/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ember-cli%2Fember-template-imports/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ember-cli%2Fember-template-imports/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ember-cli","download_url":"https://codeload.github.com/ember-cli/ember-template-imports/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ember-cli%2Fember-template-imports/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260008668,"owners_count":22945331,"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":"2025-06-24T11:06:54.599Z","updated_at":"2025-06-24T11:06:55.448Z","avatar_url":"https://github.com/ember-cli.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"ember-template-imports\n==============================================================================\n\nThis addon provides the build tooling required to support Ember's next-gen component authoring format:\n\n```gjs\nimport { on } from '@ember/modifier';\nimport FancyButton from './fancy-button';\n\nfunction greet() {\n  alert(\"AHOY!\")\n}\n\n\u003ctemplate\u003e\n  \u003cp\u003eHello, {{@name}}!\u003c/p\u003e\n  \u003cFancyButton @label=\"Say hello!\" {{on \"click\" greet}} /\u003e\n\u003c/template\u003e\n```\n\nThis design uses `\u003ctemplate\u003e` to allow us to author JavaScript or TypeScript in\nthe same file as templates, while keeping a clear separation between the\ntemplate language and the JavaScript around it.\n\nThis \"next-gen\" format is [the official future][rfc-0779] of Ember's authoring\nstory, and is stable and usable today. (It is already being used in some of the\nlargest Ember apps in the world!) We expect it to become the recommended way of\nauthoring *all* Ember apps in the near future, once we are satisfied that we\nhave sufficiently polished up all the corners of the implementation.\n\n[rfc-0779]: https://rfcs.emberjs.com/id/0779-first-class-component-templates\n\n\n## Installation and setup\n\nInstall this package and [the supporting Prettier plugin][prettier-plugin]:\n\n[prettier-plugin]: https://github.com/gitKrystan/prettier-plugin-ember-template-tag\n\n- pnpm:\n\n  ```sh\n  pnpm add --save-dev ember-template-imports prettier-plugin-ember-template-tag\n  ```\n\n- Yarn:\n\n  ```sh\n  yarn add --dev ember-template-imports prettier-plugin-ember-template-tag\n  ```\n\n- npm:\n\n  ```sh\n  npm add --save-dev ember-template-imports prettier-plugin-ember-template-tag\n  ```\n\nThen configure the Prettier plugin following [the instructions from its\nREADME][prettier-plugin]. Additionally, make sure you are using at least v5.8.0\nof [ember-template-lint][etl] and v11.6.0 of [eslint-plugin-ember][epe], so your\nlinting tools will work correctly.\n\n[etl]: https://github.com/ember-template-lint/ember-template-lint\n[epe]: https://github.com/ember-cli/eslint-plugin-ember\n\nAdditionally, if you are using TypeScript, you will also want to set up\n[Glint][glint], following [its setup instructions][glint-setup]. (Make sure you\ninclude `@glint/environment-ember-template-imports`!)\n\n[glint]: https://typed-ember.gitbook.io/glint\n[glint-setup]: https://typed-ember.gitbook.io/glint/environments/ember/installation\n\n\n## Compatibility\n\n* Ember.js v3.27 or above\n* Ember CLI v3.27 or above\n* `ember-cli-htmlbars` 6.3.0 or above\n* Node.js v16 or above\n\n\n## Editor Integrations\n\nTo get syntax highlighting inside embedded templates and support for the GJS\nfile extension, you may need to configure your editor.\n\n### Visual Studio Code\n\nThe [Ember.js extension pack](https://marketplace.visualstudio.com/items?itemName=EmberTooling.emberjs) bundles everything you need to get started.\n\n\n### Neovim\n\n[Example Neovim Config](https://github.com/NullVoxPopuli/dotfiles/blob/main/home/.config/nvim/lua/plugins/syntax.lua#L52) with support for good highlighting of embedded templates in JS and TS, using:\n\n- https://github.com/nvim-treesitter/nvim-treesitter\n- https://github.com/ember-tooling/tree-sitter-glimmer\n- https://github.com/NullVoxPopuli/tree-sitter-glimmer-javascript/\n- https://github.com/NullVoxPopuli/tree-sitter-glimmer-typescript/\n\nAdditionally, when using the eslint-lsp, you'll need to tell ESLint to activate when `javascript.glimmer` and `typescript.glimmer` files are loaded. [Example](https://github.com/NullVoxPopuli/dotfiles/blob/main/home/.config/nvim/lua/plugin-config/lsp/init.lua#L147).\n\n\u003cdetails\u003e\u003csummary\u003eConfigure ESLint for gjs + gts and fix-on-save\u003c/summary\u003e\n\n```lua\nlocal lsp = require('lspconfig')\n  \n-- ✂️ \n\nlocal eslint = lsp['eslint']\n  \neslint.setup({\n  filetypes = { \n    \"javascript\", \"typescript\", \n    \"typescript.glimmer\", \"javascript.glimmer\", \n    \"json\", \n    \"markdown\" \n  },\n  on_attach = function(client, bufnr)\n    vim.api.nvim_create_autocmd(\"BufWritePre\", {\n      buffer = bufnr,\n      command = \"EslintFixAll\",\n    })\n  end,\n})\n```\n  \n\u003c/details\u003e\n\n\n### Other editors\n\nFor other editors, you may be able to get support using one of these other syntax definitions:\n\n- [TextMate](https://github.com/IgnaceMaes/glimmer-textmate-grammar)\n- TreeSitter\n  - [Glimmer / hbs](https://github.com/alexlafroscia/tree-sitter-glimmer)\n  - gjs: https://github.com/NullVoxPopuli/tree-sitter-glimmer-javascript/\n  - gts: https://github.com/NullVoxPopuli/tree-sitter-glimmer-typescript/\n\n\n## Using Template Tags and `.gjs`/`.gts` Files\n\nThe new `\u003ctemplate\u003e` tag format is available in `.gjs` and `.gts` files. These\nfile extensions represent a new file format \"GlimmerJS\" and \"GlimmerTS\", which\nare supersets of standard JavaScript and TypeScript respectively. In this\nsyntax, templates are defined in JavaScript files directly.\n\nThis example defines a template-only component, which is the default export of\n`hello.gjs`:\n\n```gjs\n// components/hello.gjs\n\u003ctemplate\u003e\n  \u003cspan\u003eHello, {{@name}}!\u003c/span\u003e\n\u003c/template\u003e\n```\n\nYou would be able to use this component in another component like so:\n\n```gjs\n// components/hello-world.gjs\nimport Hello from './hello';\n\n\u003ctemplate\u003e\n  \u003cHello @name=\"world\" /\u003e\n\u003c/template\u003e\n```\n\nYou can also export the component explicitly:\n\n```gjs\n// components/hello.gjs\nexport default \u003ctemplate\u003e\n  \u003cspan\u003eHello, {{@name}}!\u003c/span\u003e\n\u003c/template\u003e;\n```\n\nOmitting the `export default` is just syntactic sugar. In addition, you can\ndefine template-only components and assign them to variables, allowing you to\nexport components with named exports:\n\n```gjs\nexport const First = \u003ctemplate\u003eFirst\u003c/template\u003e;\n\nexport const Second = \u003ctemplate\u003eSecond\u003c/template\u003e;\n\nexport const Third = \u003ctemplate\u003eThird\u003c/template\u003e;\n```\n\nThis also allows you to create components that are only used locally, in the\nsame file:\n\n```gjs\nconst Option = \u003ctemplate\u003e\n  \u003coption selected={{@selected}} value={{@value}}\u003e\n    {{or @title @value}}\n  \u003c/option\u003e\n\u003c/template\u003e;\n\nexport const CustomSelect = \u003ctemplate\u003e\n  \u003cselect\u003e\n    {{#each @options as |opt|}}\n      \u003cOption\n        @value={{opt.value}}\n        @selected={{eq opt @selectedOption}}\n      /\u003e\n    {{/each}}\n  \u003c/select\u003e\n\u003c/template\u003e;\n```\n\nHelpers and modifiers can also be defined in the same file as your components,\nmaking them very flexible:\n\n```gjs\nimport { modifier } from 'ember-modifier';\n\nconst plusOne = (num) =\u003e num + 1;\n\nconst setScrollPosition = modifier((element, [position]) =\u003e {\n  element.scrollTop = position\n});\n\n\u003ctemplate\u003e\n  \u003cdiv class=\"scroll-container\" {{setScrollPosition @scrollPos}}\u003e\n    {{#each @items as |item index|}}\n      Item #{{plusOne index}}: {{item}}\n    {{/each}}\n  \u003c/div\u003e\n\u003c/template\u003e\n```\n\nFinally, to associate a template with a class-based component, you can use the\ntemplate syntax directly in the class body:\n\n```gjs\nimport Component from '@glimmer/component';\nimport { tracked } from '@glimmer/tracking';\nimport { on } from '@ember/modifier';\n\n// components/hello.gjs\nexport default class Hello extends Component {\n  @tracked count = 0;\n\n  increment = () =\u003e {\n    this.count += 1;\n  };\n\n  decrement = () =\u003e {\n    this.count -= 1;\n  };\n\n  \u003ctemplate\u003e\n    \u003cbutton {{on \"click\" this.increment}}\u003e+\u003c/button\u003e\n    Count: {{this.count}}\n    \u003cbutton {{on \"click\" this.decrement}}\u003e\u0026minus;\u003c/button\u003e\n  \u003c/template\u003e\n}\n```\n\nTemplate tag components can also be used for writing tests. In fact, this aligned syntax between app code and test code is one of the big advantages of the new authoring format.\n\nJust like in app code, the template tag has access to the outer scope. This means you can reference variables directly in your tests:\n\n```gjs\n// tests/integration/components/hello-test.gjs\nimport Hello from 'example-app/components/hello';\nimport { module, test } from 'qunit';\nimport { setupRenderingTest } from 'ember-qunit';\nimport { render } from '@ember/test-helpers';\n\nmodule('Integration | Component | hello', function (hooks) {\n  setupRenderingTest(hooks);\n\n  test('renders name argument', async function (assert) {\n    const name = 'world';\n    await render(\u003ctemplate\u003e\u003cHello @name={{name}} /\u003e\u003c/template\u003e);\n    assert.dom('[data-test-id=\"some-selector\"]').hasText(name);\n  });\n});\n\n```\n\n## Sourcemap Generation\n\nInline sourcemaps are inserted automatically, which downstream build tooling may extract or remove. To disable this sourcemap injection, set the `inline_source_map` flag to `false`:\n\n```js\n// ember-cli-build.js\nmodule.exports = function (defaults) {\n  let app = new EmberAddon(defaults, {\n    'ember-template-imports': {\n      inline_source_map: false\n    }\n  });\n```\n\n## Reference: built-in helpers, modifiers, components\n\nAs implemented as part of the [Strict Mode Templates RFC][rfc-496], the built in\nhelpers, modifiers and components are available for import:\n\n* `array` (`import { array } from '@ember/helper';`)\n* `concat` (`import { concat } from '@ember/helper';`)\n* `fn` (`import { fn } from '@ember/helper';`)\n* `get` (`import { get } from '@ember/helper';`)\n* `hash` (`import { hash } from '@ember/helper';`)\n* `unique-id` (`import { uniqueId } from '@ember/helper';`, needs Ember v5.2+)\n* `on` (`import { on } from '@ember/modifier';`)\n* `htmlSafe` (`import { htmlSafe } from '@ember/template';`)\n* `Input` (`import { Input } from '@ember/component';`)\n* `LinkTo` (`import { LinkTo } from '@ember/routing';`)\n* `Textarea` (`import { Textarea } from '@ember/component';`)\n\n[rfc-496]: https://github.com/emberjs/rfcs/pull/496\n\n## Reference: import external helpers, modifiers, components\n\nYou can import non `.gjs/.gts` helpers, modifiers and components from apps/addons\nyou may already be using when migrating your own components. To determine \nthe import path:\n\n1. Check the app\n   1. If found, import that\n   2. If not found,\n        1. Check all addon's app folders\n            1. When found, look in the matching file to see what the re-export is -- this is what you can use in your app\n        2. Check all v2-addon's ember-addon#app-js configs in package.json\n            1. When found, look in the matching file to see what the re-export is -- this is what you can use in\n\nFor example:\n\n```gjs\nimport BasicDropdown from 'ember-basic-dropdown/components/basic-dropdown';\n\n\u003ctemplate\u003e\n  \u003cBasicDropdown\u003e\n   \u003c!-- Your component implementation here --\u003e\n  \u003c/BasicDropdown\u003e\n\u003c/template\u003e\n```\n\n## History\n\nLike Glimmer components, the primitive APIs for supporting imports were built\nbefore we decided on a final format for their high level usage in [RFC\n0779][rfc-0779]. There were a number of different ideas for how we can integrate\nimports with templates, and the idea behind this addon was that it could be a\ntest bed for them all. This allowed us to share common tooling between\nsolutions, and work together as a community as we explored the design space.\n\nThe main alternative explored in a previous version was template literals,\nsimilar to the existing `hbs` helper in tests:\n\n```gjs\nimport { hbs } from 'ember-template-imports';\nimport MyComponent from './my-component';\n\nexport default hbs`\n  \u003cMyComponent/\u003e\n`;\n```\n\nFor the previous version of this addon, see [this repository][first-repo]. And\nhuge thanks to @patricklx for his contributions here!\n\n[first-repo]: https://github.com/patricklx/ember-template-imports\n\nAs of [RFC 0779][rfc-0779], we decided on `\u003ctemplate\u003e` over `hbs`; see the RFC for the full rationale. ~~The `hbs` format is still technically supported by this repo for transition purposes for the early adopters who helped us get here, but will be removed at some point in the near future!~~ `hbs` has been removed -- if you rely on this feature, please use `ember-template-imports @ \u003c v4`, until migrated to `\u003ctemplate\u003e`\n\n\n## Contributing\n\nSee the [Contributing](CONTRIBUTING.md) guide for details.\n\n\n## License\n\nThis project is licensed under the [MIT License](LICENSE.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fember-cli%2Fember-template-imports","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fember-cli%2Fember-template-imports","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fember-cli%2Fember-template-imports/lists"}