Skip to content

Commit

Permalink
✨ Added warning for {{#each}} helper usage in templates (#228)
Browse files Browse the repository at this point in the history
closes #123

- As described in docs (https://docs.ghost.org/api/handlebars-themes/helpers/foreach/) it is highly encouraged to use {{#foreach}} helper instead of native handlebar's {{#each}}
- Added it as a part deprecation errors set because it's not really a template compilation error and just a helper use waning which fits better with deprecations group
- Error language used almost identical to the one in docs adjusted to how other rules are worded
  • Loading branch information
naz committed May 3, 2019
1 parent a2001a1 commit 19a6d01
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 11 deletions.
9 changes: 8 additions & 1 deletion lib/specs/v1.js
Expand Up @@ -16,7 +16,6 @@ knownHelpers = [
// Ghost apps
'input_email', 'input_password', 'amp_components', 'amp_content', 'amp_ghost_head', 'subscribe_form',
// Handlebars and express handlebars
// TODO add a warning that `each` should not be used because Ghost has special behaviour in `foreach`
'log', 'if', 'unless', 'with', 'block', 'contentFor', 'each', 'lookup'
// Registering these will break template compile checks
// 'blockHelperMissing', 'helperMissing',
Expand Down Expand Up @@ -355,6 +354,14 @@ rules = {
className: '.page-template-slug',
css: true
},
'GS001-DEPR-EACH': {
level: 'warning',
rule: 'Replace <code>{{#each}}</code> with <code>{{#foreach}}</code>',
fatal: false,
details: oneLineTrim`The <code>{{#foreach}}</code> helper is context-aware and should always be used instead of Handlebars <code>{{#each}}</code> when working with Ghost themes.<br>
See the description of <code>{{#foreach}}</code> helper <a href="${docsBaseUrl}foreach" target=_blank>here</a>.`,
regex: /{{\s*?#each\s*/g
},
'GS002-DISQUS-ID': {
level: 'error',
rule: 'Replace <code>{{id}}</code> with <code>{{comment_id}}</code> in Disqus embeds.',
Expand Down
29 changes: 22 additions & 7 deletions test/001-deprecations.test.js
Expand Up @@ -37,7 +37,8 @@ describe('001 Deprecations', function () {
'GS001-DEPR-CON-TIMG',
'GS001-DEPR-TIMG',
'GS001-DEPR-CSS-AT',
'GS001-DEPR-CSS-PATS'
'GS001-DEPR-CSS-PATS',
'GS001-DEPR-EACH'
);

// pageUrl
Expand Down Expand Up @@ -128,6 +129,10 @@ describe('001 Deprecations', function () {
output.results.fail['GS001-DEPR-CSS-AT'].should.be.a.ValidFailObject();
output.results.fail['GS001-DEPR-CSS-AT'].failures.length.should.eql(1);

// {{#each}} helper usage warning
output.results.fail['GS001-DEPR-EACH'].should.be.a.ValidFailObject();
output.results.fail['GS001-DEPR-EACH'].failures.length.should.eql(1);

output.results.pass.should.be.an.Object().which.is.empty();

done();
Expand All @@ -139,7 +144,7 @@ describe('001 Deprecations', function () {
output.should.be.a.ValidThemeObject();

output.results.fail.should.be.an.Object().which.is.empty();
output.results.pass.should.be.an.Array().with.lengthOf(27);
output.results.pass.should.be.an.Array().with.lengthOf(28);

done();
}).catch(done);
Expand All @@ -162,7 +167,7 @@ describe('001 Deprecations', function () {

output.results.fail['GS001-DEPR-PURL'].should.be.a.ValidFailObject();
output.results.fail['GS001-DEPR-PURL'].failures.length.should.eql(2);
output.results.pass.should.be.an.Array().with.lengthOf(19);
output.results.pass.should.be.an.Array().with.lengthOf(20);

done();
}).catch(done);
Expand Down Expand Up @@ -248,7 +253,8 @@ describe('001 Deprecations', function () {
'GS001-DEPR-BLOG',
'GS001-DEPR-LANG',
'GS001-DEPR-PAID',
'GS001-DEPR-USER-GET'
'GS001-DEPR-USER-GET',
'GS001-DEPR-EACH'
);

// pageUrl
Expand Down Expand Up @@ -528,6 +534,10 @@ describe('001 Deprecations', function () {
output.results.fail['GS001-DEPR-USER-GET'].should.be.a.ValidFailObject();
output.results.fail['GS001-DEPR-USER-GET'].failures.length.should.eql(1);

// {{#each}} helper usage warning
output.results.fail['GS001-DEPR-EACH'].should.be.a.ValidFailObject();
output.results.fail['GS001-DEPR-EACH'].failures.length.should.eql(1);

// there are some single author rules which are not invalid for this theme.
output.results.pass.length.should.eql(17);

Expand Down Expand Up @@ -584,7 +594,8 @@ describe('001 Deprecations', function () {
'GS001-DEPR-BLOG',
'GS001-DEPR-BPL',
'GS001-DEPR-SPL',
'GS001-DEPR-LANG'
'GS001-DEPR-LANG',
'GS001-DEPR-EACH'
);

// css class .kg-card-markdown
Expand Down Expand Up @@ -768,6 +779,10 @@ describe('001 Deprecations', function () {
output.results.fail['GS001-DEPR-LANG'].should.be.a.ValidFailObject();
output.results.fail['GS001-DEPR-LANG'].failures.length.should.eql(1);

// {{#each}} helper usage warning
output.results.fail['GS001-DEPR-EACH'].should.be.a.ValidFailObject();
output.results.fail['GS001-DEPR-EACH'].failures.length.should.eql(1);

output.results.pass.should.be.an.Array().with.lengthOf(46);

done();
Expand All @@ -779,7 +794,7 @@ describe('001 Deprecations', function () {
output.should.be.a.ValidThemeObject();

output.results.fail.should.be.an.Object().which.is.empty();
output.results.pass.should.be.an.Array().with.lengthOf(91);
output.results.pass.should.be.an.Array().with.lengthOf(92);

done();
}).catch(done);
Expand Down Expand Up @@ -833,7 +848,7 @@ describe('001 Deprecations', function () {
output.results.fail['GS001-DEPR-AUTH'].should.be.a.ValidFailObject();
output.results.fail['GS001-DEPR-AUTH'].failures.length.should.eql(1);

output.results.pass.should.be.an.Array().with.lengthOf(57);
output.results.pass.should.be.an.Array().with.lengthOf(58);

done();
}).catch(done);
Expand Down
Expand Up @@ -24,6 +24,8 @@
{{#if error}}
{{error.statusCode}}
{{/if}}

{{#each}}
</body>
{{ghost_foot}}
</html>
Expand Up @@ -34,6 +34,8 @@
{{#if error}}
{{error.statusCode}}
{{/if}}

{{#each}}
</body>
{{ghost_foot}}
{{@site.ghost_foot}}
Expand Down
2 changes: 2 additions & 0 deletions test/fixtures/themes/001-deprecations/v1/invalid/default.hbs
Expand Up @@ -16,6 +16,8 @@

{{!-- invalid usage of author property. Will not be detected. --}}
{{author_image}}

{{#each}}
</body>
{{ghost_foot}}
</html>
6 changes: 3 additions & 3 deletions test/general.test.js
Expand Up @@ -322,7 +322,7 @@ describe('Checker', function () {
{file: 'README.md', ext: '.md'}
]);

theme.results.pass.should.be.an.Array().with.lengthOf(96);
theme.results.pass.should.be.an.Array().with.lengthOf(97);
theme.results.pass.should.containEql('GS005-TPL-ERR', 'GS030-ASSET-REQ', 'GS030-ASSET-SYM');

theme.results.fail.should.be.an.Object().with.keys(
Expand Down Expand Up @@ -362,7 +362,7 @@ describe('Checker', function () {
{file: 'README.md', ext: '.md'}
]);

theme.results.pass.should.be.an.Array().with.lengthOf(32);
theme.results.pass.should.be.an.Array().with.lengthOf(33);
theme.results.pass.should.containEql('GS005-TPL-ERR', 'GS030-ASSET-REQ', 'GS030-ASSET-SYM');

theme.results.fail.should.be.an.Object().with.keys(
Expand Down Expand Up @@ -464,7 +464,7 @@ describe('format', function () {
theme.results.recommendation.byFiles['package.json'].length.should.eql(1);

theme.results.error.all.length.should.eql(88);
theme.results.warning.all.length.should.eql(2);
theme.results.warning.all.length.should.eql(5);

theme.results.error.byFiles['assets/my.css'].length.should.eql(3);
theme.results.error.byFiles['default.hbs'].length.should.eql(17);
Expand Down

0 comments on commit 19a6d01

Please sign in to comment.