ember-template-lint
Version:
Linter for Ember or Handlebars templates.
112 lines (104 loc) • 2.46 kB
JavaScript
import Rule from './_base.js';
const ERROR_MESSAGE = 'Excess whitespace in layout detected.';
const WHITESPACE_ENTITY_LIST = [
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
'  ',
'​',
'​',
'​',
'​',
'​',
'​',
'‌',
'‌',
'‍',
'‍',
'‎',
'‎',
'‏',
'‏',
' ',
' ',
'  ',
'⁠',
'⁠',
'⁡',
'⁡',
'⁡',
'⁢',
'⁢',
'⁢',
'⁣',
'⁣',
'⁣',
];
const CHARACTER_REGEX = '[a-zA-Z]';
// The goal here is to catch alternating non-whitespace/whitespace
// characters, for example, in 'W e l c o m e'.
//
// So the final pattern boils down to this:
//
// (whitespace)(non-whitespace)(whitespace)(non-whitespace)(whitespace)
//
// Specifically using this "5 alternations" rule since any less than this
// will return false positives and any more than this should not be
// necessary in 99.99% of cases
export default class NoWhitespaceWithinWord extends Rule {
constructor(...args) {
super(...args);
let whitespaceOrEntityRegex = `(?:\\s|${WHITESPACE_ENTITY_LIST.map(
(entity) => `\\${entity}`
).join('|')})+`;
let characterRegex = CHARACTER_REGEX;
this.regex = new RegExp(
`${whitespaceOrEntityRegex}${characterRegex}${whitespaceOrEntityRegex}${characterRegex}${whitespaceOrEntityRegex}`
);
}
/**
* @returns {import('./types.js').VisitorReturnType<NoWhitespaceWithinWord>}
*/
visitor() {
return {
TextNode(node, path) {
let parents = [...path.parents()];
if (
parents.some((parent) => parent.node.type === 'AttrNode') ||
parents.some(
(parent) => parent.node.type === 'ElementNode' && parent.node.tag === 'style'
)
) {
return;
}
let source = this.sourceForNode(node);
if (this.regex.test(source)) {
this.log({
message: ERROR_MESSAGE,
node,
source,
});
}
},
};
}
}