diff --git a/blueprints/route/files/__root__/__templatepath__/__templatename__.gjs b/blueprints/route/files/__root__/__templatepath__/__templatename__.gjs
new file mode 100644
index 00000000000..d2dd123bf19
--- /dev/null
+++ b/blueprints/route/files/__root__/__templatepath__/__templatename__.gjs
@@ -0,0 +1,6 @@
+<% if (addTitle) {%>import { pageTitle } from 'ember-page-title';
+
+<%}%>
+ <% if (addTitle) {%>{{pageTitle "<%= routeName %>"}}
+ <%}%>{{outlet}}
+
diff --git a/blueprints/route/files/__root__/__templatepath__/__templatename__.gts b/blueprints/route/files/__root__/__templatepath__/__templatename__.gts
new file mode 100644
index 00000000000..129c49ab84f
--- /dev/null
+++ b/blueprints/route/files/__root__/__templatepath__/__templatename__.gts
@@ -0,0 +1,14 @@
+import type { TOC } from '@ember/component/template-only';
+<% if (addTitle) {%>import { pageTitle } from 'ember-page-title';<%}%>
+
+interface <%= routeName %>Signature {
+ Args: {
+ model: unknown;
+ controller: unknown;
+ };
+}
+
+
+ <% if (addTitle) {%>{{pageTitle "<%= routeName %>"}}
+ <%}%>{{outlet}}
+ satisfies TOC<<%= routeName %>Signature>;
diff --git a/blueprints/route/index.js b/blueprints/route/index.js
index dcf1e9c3a14..3811dc40e6b 100644
--- a/blueprints/route/index.js
+++ b/blueprints/route/index.js
@@ -29,6 +29,12 @@ module.exports = {
name: 'reset-namespace',
type: Boolean,
},
+ {
+ name: 'route-authoring-format',
+ type: ['loose', 'strict'],
+ default: 'loose',
+ aliases: [{ loose: 'loose' }, { strict: 'strict' }],
+ },
],
init() {
@@ -80,6 +86,23 @@ module.exports = {
};
},
+ files() {
+ let files = this._super.files.apply(this, arguments);
+
+ if (this.options.routeAuthoringFormat === 'strict') {
+ const strictFilesToRemove =
+ this.options.isTypeScriptProject || this.options.typescript ? '.gjs' : '.gts';
+ files = files.filter(
+ (file) =>
+ !(file.endsWith('.js') || file.endsWith('.hbs') || file.endsWith(strictFilesToRemove))
+ );
+ } else {
+ files = files.filter((file) => !(file.endsWith('.gjs') || file.endsWith('.gts')));
+ }
+
+ return files;
+ },
+
locals: function (options) {
let moduleName = options.entity.name;
let rawRouteName = moduleName.split('/').pop();
diff --git a/node-tests/blueprints/route-test.js b/node-tests/blueprints/route-test.js
index 7c7b521f291..c018165bf66 100644
--- a/node-tests/blueprints/route-test.js
+++ b/node-tests/blueprints/route-test.js
@@ -149,6 +149,77 @@ describe('Blueprint: route', function () {
});
});
+ it('route foo --route-authoring-format strict', function () {
+ return emberGenerateDestroy(
+ ['route', 'foo', '--route-authoring-format', 'strict'],
+ (_file) => {
+ expect(_file('app/routes/foo.js')).to.equal(fixture('route/route.js'));
+
+ expect(_file('app/templates/foo.gjs')).to.equal(
+ fixture('route/strict-route-template.gjs')
+ );
+ expect(_file('app/templates/foo.hbs')).to.not.exist;
+
+ expect(_file('tests/unit/routes/foo-test.js')).to.equal(fixture('route-test/app.js'));
+
+ expect(file('app/router.js')).to.contain("this.route('foo')");
+ }
+ );
+ });
+
+ it('route foo --strict', function () {
+ return emberGenerateDestroy(['route', 'foo', '--strict'], (_file) => {
+ expect(_file('app/routes/foo.js')).to.equal(fixture('route/route.js'));
+
+ expect(_file('app/templates/foo.gjs')).to.equal(fixture('route/strict-route-template.gjs'));
+ expect(_file('app/templates/foo.hbs')).to.not.exist;
+
+ expect(_file('tests/unit/routes/foo-test.js')).to.equal(fixture('route-test/app.js'));
+
+ expect(file('app/router.js')).to.contain("this.route('foo')");
+ });
+ });
+
+ it('route foo --strict --typescript', function () {
+ return emberGenerateDestroy(['route', 'foo', '--strict', '--typescript'], (_file) => {
+ expect(_file('app/routes/foo.ts')).to.equal(fixture('route/route.js'));
+
+ expect(_file('app/templates/foo.gts')).to.equal(fixture('route/strict-route-template.gts'));
+ expect(_file('app/templates/foo.hbs')).to.not.exist;
+
+ expect(_file('tests/unit/routes/foo-test.ts')).to.equal(fixture('route-test/app.js'));
+
+ expect(file('app/router.js')).to.contain("this.route('foo')");
+ });
+ });
+
+ it('route foo --route-authoring-format loose', function () {
+ return emberGenerateDestroy(
+ ['route', 'foo', '--route-authoring-format', 'loose'],
+ (_file) => {
+ expect(_file('app/routes/foo.js')).to.equal(fixture('route/route.js'));
+
+ expect(_file('app/templates/foo.hbs')).to.equal('{{page-title "Foo"}}\n{{outlet}}');
+
+ expect(_file('tests/unit/routes/foo-test.js')).to.equal(fixture('route-test/app.js'));
+
+ expect(file('app/router.js')).to.contain("this.route('foo')");
+ }
+ );
+ });
+
+ it('route foo --loose', function () {
+ return emberGenerateDestroy(['route', 'foo', '--loose'], (_file) => {
+ expect(_file('app/routes/foo.js')).to.equal(fixture('route/route.js'));
+
+ expect(_file('app/templates/foo.hbs')).to.equal('{{page-title "Foo"}}\n{{outlet}}');
+
+ expect(_file('tests/unit/routes/foo-test.js')).to.equal(fixture('route-test/app.js'));
+
+ expect(file('app/router.js')).to.contain("this.route('foo')");
+ });
+ });
+
it('route foo --pod', function () {
return emberGenerateDestroy(['route', 'foo', '--pod'], (_file) => {
expect(_file('app/foo.js/route.js')).to.not.exist;
diff --git a/node-tests/fixtures/route/strict-route-template.gjs b/node-tests/fixtures/route/strict-route-template.gjs
new file mode 100644
index 00000000000..bda346473d7
--- /dev/null
+++ b/node-tests/fixtures/route/strict-route-template.gjs
@@ -0,0 +1,6 @@
+import { pageTitle } from 'ember-page-title';
+
+
+ {{pageTitle "Foo"}}
+ {{outlet}}
+
diff --git a/node-tests/fixtures/route/strict-route-template.gts b/node-tests/fixtures/route/strict-route-template.gts
new file mode 100644
index 00000000000..034f56fab6d
--- /dev/null
+++ b/node-tests/fixtures/route/strict-route-template.gts
@@ -0,0 +1,14 @@
+import type { TOC } from '@ember/component/template-only';
+import { pageTitle } from 'ember-page-title';
+
+interface FooSignature {
+ Args: {
+ model: unknown;
+ controller: unknown;
+ };
+}
+
+
+ {{pageTitle "Foo"}}
+ {{outlet}}
+ satisfies TOC;