aurelia-template-lint
Sanity check of Aurelia Templates
Info
Aurelia is a front-end platform built upon existing (or upcoming) industry standards. One such standard is to ensure that all view-markup is parsable by regular browsers; while this allows Aurelia to forgo the need for a custom parser, it does mean poorly formatted html will be ignored without warning.
The goal of aurelia-template-lint
is to detect problems with your template html and source before they become a problem in the browser, or are ignored by the browser entirely.
Install
Note: node.js 6 is required.
Note: it is recommended you use this via the gulp plugin. There is also a webpack loader available
Note: If you use this library directly, in a production environment (ci), then ensure you lock to a minor version as this library is under development and subject to breaking changes on minor versions
npm install aurelia-template-lint --save-dev
Usage
const AureliaLinter = AureliaLinter var linter = ; var html = "<template></template>" linter ;
can be configured by passing a config object
const Config = Config var config = ; configobsoleteTagOpts; var linter = config;
Config
Config is an object type of the form and default:
Example
using the default config (plus type checking - see below), the example:
foo.html
01:02: 03: 04: 05: 06: 07: 08: 09: 10: 11: 12: ${item.ino} 13: ${item.role.isAdmn} 14: ${item.update().sizeee}15: 16: 17: ${address.postcdo}18: 19: 20: 21: ${item.nme}22: 23: 24: 25:
foo.ts
;;;
will result in the following errors:
suspected unclosed element detected [ln: 1 col: 1]
self-closing element [ln: 2 col: 3]
require tag is missing a 'from' attribute [ln: 2 col: 3]
Incorrect syntax for "for" [ln: 3 col: 8]
* The form is: "$local of $items" or "[$key, $value] of $items",
<content> is obsolete [ln: 4 col: 3]
* use slot instead
more than one default slot detected [ln: 5 col: 16]
template as child of <table> not allowed [ln: 7 col: 5]
interpolation not allowed in style attribute [ln: 9 col: 3]
conflicting attributes: [repeat.for, with.bind] [ln: 10 col: 3]
* template controllers shouldn't be placed on the same element
cannot find 'ino' in type 'Item' [ln: 13 col: 5]
cannot find 'isAdmn' in type 'Role' [ln: 15 col: 5]
cannot find 'sizeee' in type 'Data' [ln: 17 col: 5]
cannot find 'postcdo' in type 'Address' [ln: 18 col: 5]
cannot find 'nme' in type 'Item' [ln: 21 col: 11]
cannot find 'modl' in type 'Car' [ln: 24 col: 8]
mismatched close tag [ln: 25 col: 1]
The full example is available in the repository; including the custom typings.
Rules
Rules used by default:
- SelfClose
- ensure non-void elements do not self-close
- Parser
- returns detected unclosed/ill-matched elements errors captured during parsing
- ObsoleteTag
- identify obsolete tag usage
- ObsoleteAttributes
- identify obsolete attribute usage
- AttributeValue
- ensure attributes exactly match an expected pattern
- ensure attributes don't contain any matches of an pattern
- ensure attribute is used for a tag
- Slot
- don't allow two, or more, slots to have the same name;
- don't allow more than one default slot;
- Require
- ensure require elments have a 'from' attribute
- ConflictingAttributes
- ensure element doesn't have attribute combination marked as conflicting.
- i.e. template controller attributes (
if.bind
andrepeat.for
on the same element)
- Template
- ensure root is a template element, unless its
- no more than one template element present
- Binding Syntax
- ensure binding syntax is correct
- Binding Access
- ensure binding correlates with fields of known types (static type checking)
I'm more than happy to add or improve rules; so please feel free to create an issue, or even a pull request.
Static Type Checking
In order to use static type checking you must opt-in by setting useRuleAureliaBindingAccess = true
.
your template html and source must have a path that defined as being in the same directory, i.e: "source/foo.html" and "source/foo.ts". You pass the path of the html file to the lint function. See Below.
It is posible to change the glob configuration to include javascript files instead of typescript; but this can only check first-depth access.
var config = ; configuseRuleAureliaBindingAccess = true;configreflectionOptssourceFileGlob = "example/**/*.ts"; //or "example/**/*.js" var linter = config; var htmlpath = "./example/foo.html";var html = fs; linter ;
please report any false-negatives, code exceptions or issues with an example of what (HTML/TS) causes the problem.
also note it will probably be far easier to use this via gulp plugin, where you'll only need to pass the config object
Background
This project was the result of wondering why aurelia applications had missing content when you used self-closing tags. In the end it turns out that if your template html is ill-formed, the browser's parser will not complain and you will simply have missing content and/or an ill formed DOM element tree.
See:
- StackOverflow: aurelia-self-closing-require-element-does-not-work
- StackOverflow: aurelia-sanity-check-template-html
Compiling
Clone the repository. In the project root run
npm installnpm test
test with:
gulp compile:typescript && node example.js
Visual Studio Code
Once installed, you can use make use of Visual Studio Code launcher (ctrl + f5
). Also allows you to place breakpoints on ts spec files (currently only for those files in outDir
path in launch.json
see: https://github.com/Microsoft/vscode/issues/6915)
Contributors
Special thanks to:
- atsu85 - https://github.com/atsu85
- Jan Žák - https://github.com/zakjan
If you would like to contribute code or failing tests (for rules you'd like) you are most welcome to do so. Please feel free to PR or raise an issue. :)
Icon
Icon courtesy of The Noun Project