- Monorepo for tools that analyze lit-html templates
-
-
-
-
-
-
+
lit-analyzer
+
+ Monorepo for tools that analyze lit-html templates
+
+
+
+
+
+
+
-
-
-
-This mono-repository consists of the following tools:
-
-- [**`vscode-lit-plugin`**](/packages/vscode-lit-plugin) VS Code plugin that adds syntax highlighting, type checking and code completion for lit-html.
-
-- [**`ts-lit-plugin`**](/packages/ts-lit-plugin) Typescript plugin that adds type checking and code completion to lit-html templates.
-
-- [**`lit-analyzer`**](/packages/lit-analyzer) CLI that analyzes lit-html templates in your code to validate html and type check bindings.
+
+
+
+
+This mono-repository consists of the following tools:
+
+- [**`vscode-lit-plugin`**](/packages/vscode-lit-plugin) VS Code plugin that adds syntax highlighting, type checking and code completion for lit-html.
+
+- [**`ts-lit-plugin`**](/packages/ts-lit-plugin) Typescript plugin that adds type checking and code completion to lit-html templates.
+
+- [**`lit-analyzer`**](/packages/lit-analyzer) CLI that analyzes lit-html templates in your code to validate html and type check bindings.
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#rules)
-## ➤ Rules
-
-You can find a list of all rules [here](https://github.com/runem/lit-analyzer/blob/master/docs/readme/rules.md).
+## ➤ Rules
+
+You can find a list of all rules [here](https://github.com/runem/lit-analyzer/blob/master/docs/readme/rules.md).
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#contributing)
-## ➤ Contributing
-
-If you are interested in contributing to this repository please read [`contributing.md`](/CONTRIBUTING.md)
+## ➤ Contributing
+
+If you are interested in contributing to this repository please read [`contributing.md`](/CONTRIBUTING.md)
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#contributors)
-## ➤ Contributors
-
-| [](https://twitter.com/runemehlsen) | [](https://twitter.com/andreasmehlsen) | [](https://twitter.com/rictic) | [](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
-| :--------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------: |
-| [Rune Mehlsen](https://twitter.com/runemehlsen) | [Andreas Mehlsen](https://twitter.com/andreasmehlsen) | [Peter Burns](https://twitter.com/rictic) | [You?](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
+## ➤ Contributors
+
+
+| [](https://twitter.com/runemehlsen) | [](https://twitter.com/andreasmehlsen) | [](https://twitter.com/rictic) | [](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
+|:--------------------------------------------------:|:--------------------------------------------------:|:--------------------------------------------------:|:--------------------------------------------------:|
+| [Rune Mehlsen](https://twitter.com/runemehlsen) | [Andreas Mehlsen](https://twitter.com/andreasmehlsen) | [Peter Burns](https://twitter.com/rictic) | [You?](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#license)
-## ➤ License
-
-Licensed under [MIT](https://opensource.org/licenses/MIT).
+## ➤ License
+
+Licensed under [MIT](https://opensource.org/licenses/MIT).
diff --git a/dev/src/my-element-1.ts b/dev/src/my-element-1.ts
index 4c8c9a46..4cb5f680 100644
--- a/dev/src/my-element-1.ts
+++ b/dev/src/my-element-1.ts
@@ -3,12 +3,16 @@ import "./my-element-2";
@customElement("my-element")
export class MyElement extends LitElement {
- @property({ attribute: "hello" }) test: number | undefined;
+ @property({ attribute: "hell>o" }) test: number | undefined;
- @property({ type: String }) test2: number | undefined;
+ @property({ type: Date }) test2: number | undefined;
@internalProperty() internal: number | undefined;
+ static get observedAttributes() {
+ return ["this is a test", "testing"];
+ }
+
render() {
return html`
diff --git a/docs/readme/rules.md b/docs/readme/rules.md
index aab3ef3b..11a76803 100644
--- a/docs/readme/rules.md
+++ b/docs/readme/rules.md
@@ -43,7 +43,6 @@ Each rule can have severity of `off`, `warning` or `error`. You can toggle rules
| Rule | Description | Severity normal | Severity strict |
| :------ | ----------- | --------------- | --------------- |
| [no-incompatible-property-type](#-no-incompatible-property-type) | When using the @property decorator in Typescript, the property option `type` is checked against the declared property Typescript type | error | error |
-| [no-unknown-property-converter](#-no-unknown-property-converter) | LitElement provides default converters. For example 'Function' is not a valid default converter type for a LitElement-managed property. | error | error |
| [no-invalid-attribute-name](#-no-invalid-attribute-name) | When using the property option `attribute`, the value is checked to make sure it's a valid attribute name. | error | error |
| [no-invalid-tag-name](#-no-invalid-tag-name) | When defining a custom element the tag name is checked to make sure it's valid. | error | error |
@@ -398,7 +397,15 @@ html``
#### 💞 no-incompatible-property-type
-When using the @property decorator in Typescript, the property option `type` is checked against the declared property Typescript type.
+This rule checks that LitElement-controlled properties are correctly configured in accordance with the default value converter.
+
+The following is a summary of what this rule does:
+
+1. The `type` given to the LitElement property configuration is checked against the actual Typescript type of the property.
+2. The default converter only accepts the types `String`, `Boolean`, `Number`, `Array` and `Object`, so all other values for `type` are considered warnings.
+3. The absence of a `type` is only considered a warning if the property is not assignable to the `string` type.
+
+This rule will not check for a given LitElement-controlled property if the property has custom converter configured.
The following examples are considered warnings:
@@ -409,30 +416,7 @@ class MyElement extends LitElement {
@property({type: Boolean}) count: number;
@property({type: String}) disabled: boolean;
@property({type: Object}) list: ListItem[];
-}
-```
-
-The following examples are not considered warnings:
-
-
-```js
-class MyElement extends LitElement {
- @property({type: String}) text: string;
- @property({type: Number}) count: number;
- @property({type: Boolean}) disabled: boolean;
- @property({type: Array}) list: ListItem[];
-}
-```
-
-#### 👎 no-unknown-property-converter
-
-The default converter in LitElement only accepts `String`, `Boolean`, `Number`, `Array` and `Object`, so all other values for `type` are considered warnings. This check doesn't run if a custom converter is used.
-
-The following example is considered a warning:
-
-```js
-class MyElement extends LitElement {
static get properties () {
return {
callback: {
@@ -446,11 +430,16 @@ class MyElement extends LitElement {
}
```
-The following example is not considered a warning:
+The following examples are not considered warnings:
```js
class MyElement extends LitElement {
+ @property({type: String}) text: string;
+ @property({type: Number}) count: number;
+ @property({type: Boolean}) disabled: boolean;
+ @property({type: Array}) list: ListItem[];
+
static get properties () {
return {
callback: {
@@ -462,6 +451,7 @@ class MyElement extends LitElement {
}
}
}
+
}
```
diff --git a/packages/lit-analyzer/README.md b/packages/lit-analyzer/README.md
index a7961be0..266a9325 100644
--- a/packages/lit-analyzer/README.md
+++ b/packages/lit-analyzer/README.md
@@ -1,654 +1,656 @@
-
lit-analyzer
-
- CLI that type checks bindings in lit-html templates
-
-
-
-
-
-
+
lit-analyzer
+
+ CLI that type checks bindings in lit-html templates
+
+
+
+
+
+
-
-
+
+
+
+
+
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#installation)
-## ➤ Installation
-
-
-```bash
-npm install lit-analyzer -g
-```
-
-**Note:**
-
-- If you use Visual Studio Code you can also install the [lit-plugin](https://marketplace.visualstudio.com/items?itemName=runem.lit-plugin) extension.
-- If you use Typescript you can also install [ts-lit-plugin](https://github.com/runem/lit-analyzer/blob/master/packages/ts-lit-plugin).
+## ➤ Installation
+
+
+```bash
+npm install lit-analyzer -g
+```
+
+**Note:**
+
+- If you use Visual Studio Code you can also install the [lit-plugin](https://marketplace.visualstudio.com/items?itemName=runem.lit-plugin) extension.
+- If you use Typescript you can also install [ts-lit-plugin](https://github.com/runem/lit-analyzer/blob/master/packages/ts-lit-plugin).
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#usage)
-## ➤ Usage
-
-`lit-analyzer` analyzes an optional `input glob` and emits the output to the console as default. When the `input glob` is omitted it will analyze all components in `src`.
-
-
-```bash
-lit-analyzer src
-lit-analyzer "src/**/*.{js,ts}"
-lit-analyzer my-element.js
-lit-analyzer --format markdown --outFile result.md
-```
+## ➤ Usage
+
+`lit-analyzer` analyzes an optional `input glob` and emits the output to the console as default. When the `input glob` is omitted it will analyze all components in `src`.
+
+
+```bash
+lit-analyzer src
+lit-analyzer "src/**/*.{js,ts}"
+lit-analyzer my-element.js
+lit-analyzer --format markdown --outFile result.md
+```
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#configuration)
-## ➤ Configuration
-
-You can configure the CLI with arguments:
-
-
-```bash
-lit-analyzer --strict --rules.no-unknown-tag-name off --format markdown
-```
-
-**Note:** You can also configure the CLI using a `tsconfig.json` file (see [ts-lit-plugin](https://github.com/runem/lit-analyzer/blob/master/packages/ts-lit-plugin)).
-
-### Available arguments
-
-
-| Option | Description | Type | Default |
-| :----- | ----------- | ---- | ------- |
-| `--help` | Print help message | `boolean` | |
-| `--rules.rule-name` | Enable or disable rules (example: --rules.no-unknown-tag-name off). Severity can be "off" \| "warn" \| "error". See a list of rules [here](https://github.com/runem/lit-analyzer/blob/master/docs/readme/rules.md). | `{"rule-name": "off" \| "warn" \| "error"}` | |
-| `--strict` | Enable strict mode. This changes the default ruleset | `boolean` | |
-| `--format` | Change the format of how diagnostics are reported | `code` \| `list` \| `markdown` | code |
-| `--maxWarnings` | Fail only when the number of warnings is larger than this number | `number` | -1 |
-| `--outFile` | Emit all output to a single file | `filePath` | |
-| `--quiet` | Report only errors and not warnings | `boolean` | |
-| `--failFast` | Exit the process right after the first problem has been found | `boolean` | |
-| `--debug` | Enable CLI debug mode | `boolean` | |
+## ➤ Configuration
+
+You can configure the CLI with arguments:
+
+
+```bash
+lit-analyzer --strict --rules.no-unknown-tag-name off --format markdown
+```
+
+**Note:** You can also configure the CLI using a `tsconfig.json` file (see [ts-lit-plugin](https://github.com/runem/lit-analyzer/blob/master/packages/ts-lit-plugin)).
+
+### Available arguments
+
+
+| Option | Description | Type | Default |
+| :----- | ----------- | ---- | ------- |
+| `--help` | Print help message | `boolean` | |
+| `--rules.rule-name` | Enable or disable rules (example: --rules.no-unknown-tag-name off). Severity can be "off" \| "warn" \| "error". See a list of rules [here](https://github.com/runem/lit-analyzer/blob/master/docs/readme/rules.md). | `{"rule-name": "off" \| "warn" \| "error"}` | |
+| `--strict` | Enable strict mode. This changes the default ruleset | `boolean` | |
+| `--format` | Change the format of how diagnostics are reported | `code` \| `list` \| `markdown` | code |
+| `--maxWarnings` | Fail only when the number of warnings is larger than this number | `number` | -1 |
+| `--outFile` | Emit all output to a single file | `filePath` | |
+| `--quiet` | Report only errors and not warnings | `boolean` | |
+| `--failFast` | Exit the process right after the first problem has been found | `boolean` | |
+| `--debug` | Enable CLI debug mode | `boolean` | |
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#rules)
-## ➤ Rules
-
-The default severity of each rule depend on the `strict` [configuration option](#-configuration). Strict mode is disabled as default.
-
-Each rule can have severity of `off`, `warning` or `error`. You can toggle rules as you like.
-
-**Validating custom elements**
-
-
-| Rule | Description | Severity normal | Severity strict |
-| :------ | ----------- | --------------- | --------------- |
-| [no-unknown-tag-name](#-no-unknown-tag-name) | The existence of tag names are checked. Be aware that not all custom elements from libraries will be found out of the box. | off | warning |
-| [no-missing-import](#-no-missing-import) | When using custom elements in HTML it is checked if the element has been imported and is available in the current context. | off | warning |
-| [no-unclosed-tag](#-no-unclosed-tag) | Unclosed tags, and invalid self closing tags like custom elements tags, are checked. | warning | error |
-
-**Validating binding names**
-
-
-| Rule | Description | Severity normal | Severity strict |
-| :------ | ----------- | --------------- | --------------- |
-| [no-unknown-attribute](#-no-unknown-attribute-no-unknown-property) [no-unknown-property](#-no-unknown-attribute-no-unknown-property) | You will get a warning whenever you use an unknown attribute or property within your `lit-html` template. | off | warning |
-| [no-unknown-event](#-no-unknown-event) | When using event bindings it's checked that the event names are fired. | off | off |
-| [no-unknown-slot](#-no-unknown-slot) | Using the "@slot" jsdoc tag on your custom element class, you can tell which slots are accepted for a particular element. | off | warning |
-
-**Validating binding types**
-
-
-| Rule | Description | Severity normal | Severity strict |
-| :------ | ----------- | --------------- | --------------- |
-| [no-invalid-boolean-binding](#-no-invalid-boolean-binding) | Disallow boolean attribute bindings on non-boolean types. | error | error |
-| [no-expressionless-property-binding](#-no-expressionless-property-binding) | Disallow property bindings without an expression. | error | error |
-| [no-noncallable-event-binding](#-no-noncallable-event-binding) | Disallow event listener bindings with a noncallable type. | error | error |
-| [no-boolean-in-attribute-binding](#-no-boolean-in-attribute-binding) | Disallow attribute bindings with a boolean type. | error | error |
-| [no-complex-attribute-binding](#-no-complex-attribute-binding) | Disallow attribute bindings with a complex type. | error | error |
-| [no-nullable-attribute-binding](#-no-nullable-attribute-binding) | Disallow attribute bindings with nullable types such as "null" or "undefined". | error | error |
-| [no-incompatible-type-binding](#-no-incompatible-type-binding) | Disallow incompatible type in bindings. | error | error |
-| [no-invalid-directive-binding](#-no-invalid-directive-binding) | Disallow using built-in directives in unsupported bindings. | error | error |
-| [no-unintended-mixed-binding](#-no-unintended-mixed-binding) | Disallow mixed value bindings where a character `'`, `"`, `}` or `/` is unintentionally included in the binding. | warn | warn |
-
-**Validating LitElement**
-
-
-| Rule | Description | Severity normal | Severity strict |
-| :------ | ----------- | --------------- | --------------- |
-| [no-incompatible-property-type](#-no-incompatible-property-type) | When using the @property decorator in Typescript, the property option `type` is checked against the declared property Typescript type | error | error |
-| [no-unknown-property-converter](#-no-unknown-property-converter) | LitElement provides default converters. For example 'Function' is not a valid default converter type for a LitElement-managed property. | error | error |
-| [no-invalid-attribute-name](#-no-invalid-attribute-name) | When using the property option `attribute`, the value is checked to make sure it's a valid attribute name. | error | error |
-| [no-invalid-tag-name](#-no-invalid-tag-name) | When defining a custom element the tag name is checked to make sure it's valid. | error | error |
-
-**Validating CSS**
-
-
-| Rule | Description | Severity normal | Severity strict |
-| :------ | ----------- | --------------- | --------------- |
-| [💅 no-invalid-css](#-no-invalid-css) | CSS within the tagged template literal `css` will be validated. | warning | error |
-
-### Validating custom elements
-
-All web components in your code are analyzed using [web-component-analyzer](https://github.com/runem/web-component-analyzer) which supports native custom elements and web components built with LitElement.
-
-#### 🤷 no-unknown-tag-name
-
-Web components defined in libraries need to either extend the global `HTMLElementTagNameMap` (typescript definition file) or include the "@customElement tag-name" jsdoc on the custom element class.
-
-Below you will see an example of what to add to your library typescript definition files if you want type checking support for a given html tag name.
-
-
-```typescript
-declare global {
- interface HTMLElementTagNameMap {
- "my-element": MyElement;
- }
-}
-```
-
-#### 📣 no-missing-import
-
-When using custom elements in HTML it is checked if the element has been imported and is available in the current context. It's considered imported if any imported module (or their imports) defines the custom element.
-
-The following example is considered a warning:
-
-
-```js
-// No import of "my-element"
-html``
-```
-
-The following example is not considered a warning:
-
-
-```js
-import "my-element.js";
-html``
-```
-
-#### ☯ no-unclosed-tag
-
-Unclosed tags, and invalid self closing tags like custom elements tags, are checked.
-
-The following examples are considered warnings:
-
-
-```js
-html`
`
-html``
-html``
-```
-
-The following examples are not considered warnings:
-
-
-```js
-html``
-html``
-html``
-html``
-```
-
-### Validating binding names
-
-Attributes, properties and events are picked up on custom elements using [web-component-analyzer](https://github.com/runem/web-component-analyzer) which supports native custom elements and web components built with LitElement.
-
-#### ✅ no-unknown-attribute, no-unknown-property
-
-You will get a warning whenever you use an unknown attribute or property. This check is made on both custom elements and built in elements.
-
-**The following example is considered a warning:**
-
-
-```js
-html``
-```
-
-**The following example is not considered a warning:**
-
-
-```js
-html``
-```
-
-#### ⚡️ no-unknown-event
-
-You can opt in to check for unknown event names. Using the `@fires` jsdoc or the statement `this.dispatch(new CustomEvent("my-event))` will make the event name available. All event names are accepted globally because events bubble.
-
-The following example is considered a warning:
-
-
-```js
-html``
-```
-
-The following example is not considered a warning:
-
-
-```js
-html``
-```
-
-#### 📬 no-unknown-slot
-
-Using the "@slot" jsdoc tag on your custom element class, you can tell which slots are accepted for a particular element. Then you will get warnings for invalid slot names and if you forget to add the slot attribute on elements without an unnamed slot.
-
-
-```js
-/**
- * @slot - This is a comment for the unnamed slot
- * @slot right - Right content
- * @slot left
- */
-class MyElement extends HTMLElement {
-}
-customElements.define("my-element", MyElement);
-```
-
-The following example is considered a warning:
-
-
-```js
-html`
-
-
-
-`
-```
-
-The following example is not considered a warning:
-
-
-```js
-html`
-
-
-
-
-
-`
-```
-
-### Validating binding types
-
-Be aware that many checks involving analyzing bindings will work better in Typescript files because we have more information about the values being bound.
-
-#### ❓ no-invalid-boolean-binding
-
-It never makes sense to use the boolean attribute binding on a non-boolean type.
-
-The following example is considered a warning:
-
-
-```js
-html``
-```
-
-The following example is not considered a warning:
-
-
-```js
-html``
-```
-
-#### ⚫️ no-expressionless-property-binding
-
-Because of how `lit-html` [parses bindings internally](https://github.com/Polymer/lit-html/issues/843) you cannot use the property binding without an expression.
-
-The following example is considered a warning:
-
-
-```js
-html``
-```
-
-The following example is not considered a warning:
-
-
-```js
-html``
-```
-
-#### 🌀 no-noncallable-event-binding
-
-It's a common mistake to incorrectly call the function when setting up an event handler binding instead of passing a reference to the function. This makes the function call whenever the code evaluates.
-
-The following examples are considered warnings:
-
-
-```js
-html``
-html``
-```
-
-The following examples are not considered warnings:
-
-
-```js
-html``
-html``
-```
-
-#### 😈 no-boolean-in-attribute-binding
-
-You should not be binding to a boolean type using an attribute binding because it could result in binding the string "true" or "false". Instead you should be using a **boolean** attribute binding.
-
-This error is particular tricky, because the string "false" is truthy when evaluated in a conditional.
-
-The following example is considered a warning:
-
-
-```js
-html``
-```
-
-The following example is not considered a warning:
-
-
-```js
-html``
-```
-
-#### ☢️ no-complex-attribute-binding
-
-Binding an object using an attribute binding would result in binding the string "[object Object]" to the attribute. In this cases it's probably better to use a property binding instead.
-
-The following example is considered a warning:
-
-
-```js
-html``
-```
-
-The following example is not considered a warning:
-
-
-```js
-html``
-```
-
-#### ⭕️ no-nullable-attribute-binding
-
-Binding `undefined` or `null` in an attribute binding will result in binding the string "undefined" or "null". Here you should probably wrap your expression in the "ifDefined" directive.
-
-The following examples are considered warnings:
-
-
-```js
-html``
-html``
-```
-
-The following examples are not considered warnings:
-
-
-```js
-html``
-html``
-```
-
-#### 💔 no-incompatible-type-binding
-
-Assignments in your HTML are typed checked just like it would be in Typescript.
-
-The following examples are considered warnings:
-
-
-```js
-html``
-html``
-html``
-html``
-```
-
-The following examples are not considered warnings:
-
-
-```js
-html``
-html``
-html``
-html``
-```
-
-#### 💥 no-invalid-directive-binding
-
-Directives are checked to make sure that the following rules are met:
-
-- `ifDefined` is only used in an attribute binding.
-- `class` is only used in an attribute binding on the 'class' attribute.
-- `style` is only used in an attribute binding on the 'style' attribute.
-- `unsafeHTML`, `cache`, `repeat`, `asyncReplace` and `asyncAppend` are only used within a text binding.
-
-The directives already make these checks on runtime, so this will help you catch errors before runtime.
-
-The following examples are considered warnings:
-
-
-```js
-html``
-html``
-html``
-```
-
-The following examples are not considered warnings:
-
-
-```js
-html``
-html``
-html``
-html``
-```
-
-#### 🕷 no-unintended-mixed-binding
-
-Sometimes unintended characters sneak into bindings. This often indicates a typo such as `` where the expression is directly followed by a "}" which will be included in the value being bound, resulting in "foo}". Another example is self-closing tags without a space between the binding and "/" like `` which will result in binding the string "myvalue/".
-
-This rule disallows mixed value bindings where a character `'`, `"`, `}` or `/` is unintentionally included in the binding.
-
-The following examples are considered warnings:
-
-
-```js
-html``
-html``
-html``
-html``
-```
-
-The following examples are not considered warnings:
-
-
-```js
-html``
-html``
-html``
-html``
-```
-
-### Validating LitElement
-
-#### 💞 no-incompatible-property-type
-
-When using the @property decorator in Typescript, the property option `type` is checked against the declared property Typescript type.
-
-The following examples are considered warnings:
-
-
-```js
-class MyElement extends LitElement {
- @property({type: Number}) text: string;
- @property({type: Boolean}) count: number;
- @property({type: String}) disabled: boolean;
- @property({type: Object}) list: ListItem[];
-}
-```
-
-The following examples are not considered warnings:
-
-
-```js
-class MyElement extends LitElement {
- @property({type: String}) text: string;
- @property({type: Number}) count: number;
- @property({type: Boolean}) disabled: boolean;
- @property({type: Array}) list: ListItem[];
-}
-```
-
-#### 👎 no-unknown-property-converter
-
-The default converter in LitElement only accepts `String`, `Boolean`, `Number`, `Array` and `Object`, so all other values for `type` are considered warnings. This check doesn't run if a custom converter is used.
-
-The following example is considered a warning:
-
-
-```js
-class MyElement extends LitElement {
- static get properties () {
- return {
- callback: {
- type: Function
- },
- text: {
- type: MyElement
- }
- }
- }
-}
-```
-
-The following example is not considered a warning:
-
-
-```js
-class MyElement extends LitElement {
- static get properties () {
- return {
- callback: {
- type: Function,
- converter: myCustomConverter
- },
- text: {
- type: String
- }
- }
- }
-}
-```
-
-#### ⁉️ no-invalid-attribute-name
-
-When using the property option `attribute`, the value is checked to make sure it's a valid attribute name.
-
-The following example is considered a warning:
-
-
-```js
-class MyElement extends LitElement {
- static get properties () {
- return {
- text: {
- attribute: "invald=name"
- }
- }
- }
-}
-```
-
-#### ⁉️ no-invalid-tag-name
-
-When defining a custom element, the tag name is checked to make sure it's a valid custom element name.
-
-The following example is considered a warning:
-
-
-```js
-@customElement("wrongElementName")
-class MyElement extends LitElement {
-}
-
-customElements.define("alsoWrongName", MyElement);
-```
-
-The following example is not considered a warning:
-
-
-```js
-@customElement("my-element")
-class MyElement extends LitElement {
-}
-
-customElements.define("correct-element-name", MyElement);
-```
-
-### Validating CSS
-
-`lit-analyzer` uses [vscode-css-languageservice](https://github.com/Microsoft/vscode-css-languageservice) to validate CSS.
-
-#### 💅 no-invalid-css
-
-CSS within the tagged template literal `css` will be validated.
-
-The following example is considered a warning:
-
-
-```js
-css`
- button
- background: red;
- }
-`
-```
-
-The following example is not considered a warning:
-
-
-```js
-css`
- button {
- background: red;
- }
-`
-```
+## ➤ Rules
+
+The default severity of each rule depend on the `strict` [configuration option](#-configuration). Strict mode is disabled as default.
+
+Each rule can have severity of `off`, `warning` or `error`. You can toggle rules as you like.
+
+**Validating custom elements**
+
+
+| Rule | Description | Severity normal | Severity strict |
+| :------ | ----------- | --------------- | --------------- |
+| [no-unknown-tag-name](#-no-unknown-tag-name) | The existence of tag names are checked. Be aware that not all custom elements from libraries will be found out of the box. | off | warning |
+| [no-missing-import](#-no-missing-import) | When using custom elements in HTML it is checked if the element has been imported and is available in the current context. | off | warning |
+| [no-unclosed-tag](#-no-unclosed-tag) | Unclosed tags, and invalid self closing tags like custom elements tags, are checked. | warning | error |
+
+**Validating binding names**
+
+
+| Rule | Description | Severity normal | Severity strict |
+| :------ | ----------- | --------------- | --------------- |
+| [no-unknown-attribute](#-no-unknown-attribute-no-unknown-property) [no-unknown-property](#-no-unknown-attribute-no-unknown-property) | You will get a warning whenever you use an unknown attribute or property within your `lit-html` template. | off | warning |
+| [no-unknown-event](#-no-unknown-event) | When using event bindings it's checked that the event names are fired. | off | off |
+| [no-unknown-slot](#-no-unknown-slot) | Using the "@slot" jsdoc tag on your custom element class, you can tell which slots are accepted for a particular element. | off | warning |
+
+**Validating binding types**
+
+
+| Rule | Description | Severity normal | Severity strict |
+| :------ | ----------- | --------------- | --------------- |
+| [no-invalid-boolean-binding](#-no-invalid-boolean-binding) | Disallow boolean attribute bindings on non-boolean types. | error | error |
+| [no-expressionless-property-binding](#-no-expressionless-property-binding) | Disallow property bindings without an expression. | error | error |
+| [no-noncallable-event-binding](#-no-noncallable-event-binding) | Disallow event listener bindings with a noncallable type. | error | error |
+| [no-boolean-in-attribute-binding](#-no-boolean-in-attribute-binding) | Disallow attribute bindings with a boolean type. | error | error |
+| [no-complex-attribute-binding](#-no-complex-attribute-binding) | Disallow attribute bindings with a complex type. | error | error |
+| [no-nullable-attribute-binding](#-no-nullable-attribute-binding) | Disallow attribute bindings with nullable types such as "null" or "undefined". | error | error |
+| [no-incompatible-type-binding](#-no-incompatible-type-binding) | Disallow incompatible type in bindings. | error | error |
+| [no-invalid-directive-binding](#-no-invalid-directive-binding) | Disallow using built-in directives in unsupported bindings. | error | error |
+| [no-unintended-mixed-binding](#-no-unintended-mixed-binding) | Disallow mixed value bindings where a character `'`, `"`, `}` or `/` is unintentionally included in the binding. | warn | warn |
+
+**Validating LitElement**
+
+
+| Rule | Description | Severity normal | Severity strict |
+| :------ | ----------- | --------------- | --------------- |
+| [no-incompatible-property-type](#-no-incompatible-property-type) | When using the @property decorator in Typescript, the property option `type` is checked against the declared property Typescript type | error | error |
+| [no-invalid-attribute-name](#-no-invalid-attribute-name) | When using the property option `attribute`, the value is checked to make sure it's a valid attribute name. | error | error |
+| [no-invalid-tag-name](#-no-invalid-tag-name) | When defining a custom element the tag name is checked to make sure it's valid. | error | error |
+
+**Validating CSS**
+
+
+| Rule | Description | Severity normal | Severity strict |
+| :------ | ----------- | --------------- | --------------- |
+| [💅 no-invalid-css](#-no-invalid-css) | CSS within the tagged template literal `css` will be validated. | warning | error |
+
+### Validating custom elements
+
+All web components in your code are analyzed using [web-component-analyzer](https://github.com/runem/web-component-analyzer) which supports native custom elements and web components built with LitElement.
+
+#### 🤷 no-unknown-tag-name
+
+Web components defined in libraries need to either extend the global `HTMLElementTagNameMap` (typescript definition file) or include the "@customElement tag-name" jsdoc on the custom element class.
+
+Below you will see an example of what to add to your library typescript definition files if you want type checking support for a given html tag name.
+
+
+```typescript
+declare global {
+ interface HTMLElementTagNameMap {
+ "my-element": MyElement;
+ }
+}
+```
+
+#### 📣 no-missing-import
+
+When using custom elements in HTML it is checked if the element has been imported and is available in the current context. It's considered imported if any imported module (or their imports) defines the custom element.
+
+The following example is considered a warning:
+
+
+```js
+// No import of "my-element"
+html``
+```
+
+The following example is not considered a warning:
+
+
+```js
+import "my-element.js";
+html``
+```
+
+#### ☯ no-unclosed-tag
+
+Unclosed tags, and invalid self closing tags like custom elements tags, are checked.
+
+The following examples are considered warnings:
+
+
+```js
+html`
`
+html``
+html``
+```
+
+The following examples are not considered warnings:
+
+
+```js
+html``
+html``
+html``
+html``
+```
+
+### Validating binding names
+
+Attributes, properties and events are picked up on custom elements using [web-component-analyzer](https://github.com/runem/web-component-analyzer) which supports native custom elements and web components built with LitElement.
+
+#### ✅ no-unknown-attribute, no-unknown-property
+
+You will get a warning whenever you use an unknown attribute or property. This check is made on both custom elements and built in elements.
+
+**The following example is considered a warning:**
+
+
+```js
+html``
+```
+
+**The following example is not considered a warning:**
+
+
+```js
+html``
+```
+
+#### ⚡️ no-unknown-event
+
+You can opt in to check for unknown event names. Using the `@fires` jsdoc or the statement `this.dispatch(new CustomEvent("my-event))` will make the event name available. All event names are accepted globally because events bubble.
+
+The following example is considered a warning:
+
+
+```js
+html``
+```
+
+The following example is not considered a warning:
+
+
+```js
+html``
+```
+
+#### 📬 no-unknown-slot
+
+Using the "@slot" jsdoc tag on your custom element class, you can tell which slots are accepted for a particular element. Then you will get warnings for invalid slot names and if you forget to add the slot attribute on elements without an unnamed slot.
+
+
+```js
+/**
+ * @slot - This is a comment for the unnamed slot
+ * @slot right - Right content
+ * @slot left
+ */
+class MyElement extends HTMLElement {
+}
+customElements.define("my-element", MyElement);
+```
+
+The following example is considered a warning:
+
+
+```js
+html`
+
+
+
+`
+```
+
+The following example is not considered a warning:
+
+
+```js
+html`
+
+
+
+
+
+`
+```
+
+### Validating binding types
+
+Be aware that many checks involving analyzing bindings will work better in Typescript files because we have more information about the values being bound.
+
+#### ❓ no-invalid-boolean-binding
+
+It never makes sense to use the boolean attribute binding on a non-boolean type.
+
+The following example is considered a warning:
+
+
+```js
+html``
+```
+
+The following example is not considered a warning:
+
+
+```js
+html``
+```
+
+#### ⚫️ no-expressionless-property-binding
+
+Because of how `lit-html` [parses bindings internally](https://github.com/Polymer/lit-html/issues/843) you cannot use the property binding without an expression.
+
+The following example is considered a warning:
+
+
+```js
+html``
+```
+
+The following example is not considered a warning:
+
+
+```js
+html``
+```
+
+#### 🌀 no-noncallable-event-binding
+
+It's a common mistake to incorrectly call the function when setting up an event handler binding instead of passing a reference to the function. This makes the function call whenever the code evaluates.
+
+The following examples are considered warnings:
+
+
+```js
+html``
+html``
+```
+
+The following examples are not considered warnings:
+
+
+```js
+html``
+html``
+```
+
+#### 😈 no-boolean-in-attribute-binding
+
+You should not be binding to a boolean type using an attribute binding because it could result in binding the string "true" or "false". Instead you should be using a **boolean** attribute binding.
+
+This error is particular tricky, because the string "false" is truthy when evaluated in a conditional.
+
+The following example is considered a warning:
+
+
+```js
+html``
+```
+
+The following example is not considered a warning:
+
+
+```js
+html``
+```
+
+#### ☢️ no-complex-attribute-binding
+
+Binding an object using an attribute binding would result in binding the string "[object Object]" to the attribute. In this cases it's probably better to use a property binding instead.
+
+The following example is considered a warning:
+
+
+```js
+html``
+```
+
+The following example is not considered a warning:
+
+
+```js
+html``
+```
+
+#### ⭕️ no-nullable-attribute-binding
+
+Binding `undefined` or `null` in an attribute binding will result in binding the string "undefined" or "null". Here you should probably wrap your expression in the "ifDefined" directive.
+
+The following examples are considered warnings:
+
+
+```js
+html``
+html``
+```
+
+The following examples are not considered warnings:
+
+
+```js
+html``
+html``
+```
+
+#### 💔 no-incompatible-type-binding
+
+Assignments in your HTML are typed checked just like it would be in Typescript.
+
+The following examples are considered warnings:
+
+
+```js
+html``
+html``
+html``
+html``
+```
+
+The following examples are not considered warnings:
+
+
+```js
+html``
+html``
+html``
+html``
+```
+
+#### 💥 no-invalid-directive-binding
+
+Directives are checked to make sure that the following rules are met:
+
+- `ifDefined` is only used in an attribute binding.
+- `class` is only used in an attribute binding on the 'class' attribute.
+- `style` is only used in an attribute binding on the 'style' attribute.
+- `unsafeHTML`, `cache`, `repeat`, `asyncReplace` and `asyncAppend` are only used within a text binding.
+
+The directives already make these checks on runtime, so this will help you catch errors before runtime.
+
+The following examples are considered warnings:
+
+
+```js
+html``
+html``
+html``
+```
+
+The following examples are not considered warnings:
+
+
+```js
+html``
+html``
+html``
+html``
+```
+
+#### 🕷 no-unintended-mixed-binding
+
+Sometimes unintended characters sneak into bindings. This often indicates a typo such as `` where the expression is directly followed by a "}" which will be included in the value being bound, resulting in "foo}". Another example is self-closing tags without a space between the binding and "/" like `` which will result in binding the string "myvalue/".
+
+This rule disallows mixed value bindings where a character `'`, `"`, `}` or `/` is unintentionally included in the binding.
+
+The following examples are considered warnings:
+
+
+```js
+html``
+html``
+html``
+html``
+```
+
+The following examples are not considered warnings:
+
+
+```js
+html``
+html``
+html``
+html``
+```
+
+### Validating LitElement
+
+#### 💞 no-incompatible-property-type
+
+This rule checks that LitElement-controlled properties are correctly configured in accordance with the default value converter.
+
+The following is a summary of what this rule does:
+
+1. The `type` given to the LitElement property configuration is checked against the actual Typescript type of the property.
+2. The default converter only accepts the types `String`, `Boolean`, `Number`, `Array` and `Object`, so all other values for `type` are considered warnings.
+3. The absence of a `type` is only considered a warning if the property is not assignable to the `string` type.
+
+This rule will not check for a given LitElement-controlled property if the property has custom converter configured.
+
+The following examples are considered warnings:
+
+
+```js
+class MyElement extends LitElement {
+ @property({type: Number}) text: string;
+ @property({type: Boolean}) count: number;
+ @property({type: String}) disabled: boolean;
+ @property({type: Object}) list: ListItem[];
+
+ static get properties () {
+ return {
+ callback: {
+ type: Function
+ },
+ text: {
+ type: MyElement
+ }
+ }
+ }
+}
+```
+
+The following examples are not considered warnings:
+
+
+```js
+class MyElement extends LitElement {
+ @property({type: String}) text: string;
+ @property({type: Number}) count: number;
+ @property({type: Boolean}) disabled: boolean;
+ @property({type: Array}) list: ListItem[];
+
+ static get properties () {
+ return {
+ callback: {
+ type: Function,
+ converter: myCustomConverter
+ },
+ text: {
+ type: String
+ }
+ }
+ }
+
+}
+```
+
+#### ⁉️ no-invalid-attribute-name
+
+When using the property option `attribute`, the value is checked to make sure it's a valid attribute name.
+
+The following example is considered a warning:
+
+
+```js
+class MyElement extends LitElement {
+ static get properties () {
+ return {
+ text: {
+ attribute: "invald=name"
+ }
+ }
+ }
+}
+```
+
+#### ⁉️ no-invalid-tag-name
+
+When defining a custom element, the tag name is checked to make sure it's a valid custom element name.
+
+The following example is considered a warning:
+
+
+```js
+@customElement("wrongElementName")
+class MyElement extends LitElement {
+}
+
+customElements.define("alsoWrongName", MyElement);
+```
+
+The following example is not considered a warning:
+
+
+```js
+@customElement("my-element")
+class MyElement extends LitElement {
+}
+
+customElements.define("correct-element-name", MyElement);
+```
+
+### Validating CSS
+
+`lit-analyzer` uses [vscode-css-languageservice](https://github.com/Microsoft/vscode-css-languageservice) to validate CSS.
+
+#### 💅 no-invalid-css
+
+CSS within the tagged template literal `css` will be validated.
+
+The following example is considered a warning:
+
+
+```js
+css`
+ button
+ background: red;
+ }
+`
+```
+
+The following example is not considered a warning:
+
+
+```js
+css`
+ button {
+ background: red;
+ }
+`
+```
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#documenting-slots-events-attributes-and-properties)
-## ➤ Documenting slots, events, attributes and properties
-
-Code is analyzed using [web-component-analyzer](https://github.com/runem/web-component-analyzer) in order to find properties, attributes and events. Unfortunately, sometimes it's not possible to analyze these things by looking at the code, and you will have to document how your component looks using `jsdoc`like this:
-
-
-```js
-/**
- * This is my element
- * @attr size
- * @attr {red|blue} color - The color of my element
- * @prop {String} value
- * @prop {Boolean} myProp - This is my property
- * @fires change
- * @fires my-event - This is my own event
- * @slot - This is a comment for the unnamed slot
- * @slot right - Right content
- * @slot left
- */
-class MyElement extends HTMLElement {
-}
-
-customElements.define("my-element", MyElement);
-```
+## ➤ Documenting slots, events, attributes and properties
+
+Code is analyzed using [web-component-analyzer](https://github.com/runem/web-component-analyzer) in order to find properties, attributes and events. Unfortunately, sometimes it's not possible to analyze these things by looking at the code, and you will have to document how your component looks using `jsdoc`like this:
+
+
+```js
+/**
+ * This is my element
+ * @attr size
+ * @attr {red|blue} color - The color of my element
+ * @prop {String} value
+ * @prop {Boolean} myProp - This is my property
+ * @fires change
+ * @fires my-event - This is my own event
+ * @slot - This is a comment for the unnamed slot
+ * @slot right - Right content
+ * @slot left
+ */
+class MyElement extends HTMLElement {
+}
+
+customElements.define("my-element", MyElement);
+```
+
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#contributors)
-## ➤ Contributors
-
-| [](https://twitter.com/runemehlsen) | [](https://twitter.com/andreasmehlsen) | [](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
-| :--------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------: |
-| [Rune Mehlsen](https://twitter.com/runemehlsen) | [Andreas Mehlsen](https://twitter.com/andreasmehlsen) | [You?](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
+## ➤ Contributors
+
+
+| [](https://twitter.com/runemehlsen) | [](https://twitter.com/andreasmehlsen) | [](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
+|:--------------------------------------------------:|:--------------------------------------------------:|:--------------------------------------------------:|
+| [Rune Mehlsen](https://twitter.com/runemehlsen) | [Andreas Mehlsen](https://twitter.com/andreasmehlsen) | [You?](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#license)
-## ➤ License
-
-Licensed under [MIT](https://opensource.org/licenses/MIT).
+## ➤ License
+
+Licensed under [MIT](https://opensource.org/licenses/MIT).
diff --git a/packages/lit-analyzer/src/analyze/default-lit-analyzer-context.ts b/packages/lit-analyzer/src/analyze/default-lit-analyzer-context.ts
index 548e7eed..0f1f3a8d 100644
--- a/packages/lit-analyzer/src/analyze/default-lit-analyzer-context.ts
+++ b/packages/lit-analyzer/src/analyze/default-lit-analyzer-context.ts
@@ -8,7 +8,7 @@ import noExpressionlessPropertyBindingRule from "../rules/no-expressionless-prop
import noIncompatibleTypeBindingRule from "../rules/no-incompatible-type-binding";
import noInvalidAttributeName from "../rules/no-invalid-attribute-name";
import noInvalidDirectiveBindingRule from "../rules/no-invalid-directive-binding";
-import noInvalidProperty from "../rules/no-invalid-property";
+import noIncompatiblePropertyType from "../rules/no-incompatible-property-type";
import noInvalidTagName from "../rules/no-invalid-tag-name";
import noMissingImport from "../rules/no-missing-import";
import noNoncallableEventBindingRule from "../rules/no-noncallable-event-binding";
@@ -52,7 +52,7 @@ const rules: RuleModule[] = [
noUnknownAttribute,
noUnknownProperty,
noUnknownEvent,
- noInvalidProperty,
+ noIncompatiblePropertyType,
noInvalidTagName,
noInvalidAttributeName
];
diff --git a/packages/lit-analyzer/src/analyze/document-analyzer/html/lit-html-document-analyzer.ts b/packages/lit-analyzer/src/analyze/document-analyzer/html/lit-html-document-analyzer.ts
index 4bd5ca0d..8fc74fbd 100644
--- a/packages/lit-analyzer/src/analyze/document-analyzer/html/lit-html-document-analyzer.ts
+++ b/packages/lit-analyzer/src/analyze/document-analyzer/html/lit-html-document-analyzer.ts
@@ -15,8 +15,9 @@ import { LitOutliningSpan, LitOutliningSpanKind } from "../../types/lit-outlinin
import { LitQuickInfo } from "../../types/lit-quick-info";
import { LitRenameInfo } from "../../types/lit-rename-info";
import { LitRenameLocation } from "../../types/lit-rename-location";
+import { flatten } from "../../util/array-util";
import { iterableDefined } from "../../util/iterable-util";
-import { flatten, intersects } from "../../util/general-util";
+import { intersects } from "../../util/general-util";
import { codeFixesForHtmlReport } from "./code-fix/code-fixes-for-html-report";
import { completionsAtOffset } from "./completion/completions-at-offset";
import { definitionForHtmlAttr } from "./definition/definition-for-html-attr";
diff --git a/packages/lit-analyzer/src/analyze/lit-analyzer-config.ts b/packages/lit-analyzer/src/analyze/lit-analyzer-config.ts
index a7255bbe..f1b89a3c 100644
--- a/packages/lit-analyzer/src/analyze/lit-analyzer-config.ts
+++ b/packages/lit-analyzer/src/analyze/lit-analyzer-config.ts
@@ -2,7 +2,6 @@ import { HtmlData } from "./parse/parse-html-data/html-data-tag";
import { LitDiagnosticSeverity } from "./types/lit-diagnostic";
export type LitAnalyzerRuleName =
- | "no-invalid-property"
| "no-unknown-tag-name"
| "no-missing-import"
| "no-unclosed-tag"
@@ -20,7 +19,6 @@ export type LitAnalyzerRuleName =
| "no-incompatible-type-binding"
| "no-invalid-directive-binding"
| "no-incompatible-property-type"
- | "no-unknown-property-converter"
| "no-invalid-attribute-name"
| "no-invalid-tag-name"
| "no-invalid-css";
@@ -43,7 +41,6 @@ export const ALL_RULE_NAMES: LitAnalyzerRuleName[] = [
"no-incompatible-type-binding",
"no-invalid-directive-binding",
"no-incompatible-property-type",
- "no-unknown-property-converter",
"no-invalid-attribute-name",
"no-invalid-tag-name",
"no-invalid-css"
@@ -54,7 +51,6 @@ export type LitAnalyzerRuleSeverity = "off" | "warn" | "warning" | "error" | 0 |
export type LitAnalyzerRules = Partial>;
const DEFAULT_RULES_NOSTRICT: Required = {
- "no-invalid-property": "warn",
"no-unknown-tag-name": "off",
"no-missing-import": "off",
"no-unclosed-tag": "warn",
@@ -72,14 +68,12 @@ const DEFAULT_RULES_NOSTRICT: Required = {
"no-incompatible-type-binding": "error",
"no-invalid-directive-binding": "error",
"no-incompatible-property-type": "error",
- "no-unknown-property-converter": "error",
"no-invalid-attribute-name": "error",
"no-invalid-tag-name": "error",
"no-invalid-css": "warn"
};
const DEFAULT_RULES_STRICT: Required = {
- "no-invalid-property": "warn",
"no-unknown-tag-name": "warn",
"no-missing-import": "warn",
"no-unclosed-tag": "error",
@@ -97,7 +91,6 @@ const DEFAULT_RULES_STRICT: Required = {
"no-incompatible-type-binding": "error",
"no-invalid-directive-binding": "error",
"no-incompatible-property-type": "error",
- "no-unknown-property-converter": "error",
"no-invalid-attribute-name": "error",
"no-invalid-tag-name": "error",
"no-invalid-css": "error"
diff --git a/packages/lit-analyzer/src/analyze/lit-analyzer.ts b/packages/lit-analyzer/src/analyze/lit-analyzer.ts
index 36691d1c..6cadb2e8 100644
--- a/packages/lit-analyzer/src/analyze/lit-analyzer.ts
+++ b/packages/lit-analyzer/src/analyze/lit-analyzer.ts
@@ -21,8 +21,8 @@ import { LitQuickInfo } from "./types/lit-quick-info";
import { LitRenameInfo } from "./types/lit-rename-info";
import { LitRenameLocation } from "./types/lit-rename-location";
import { Range } from "./types/range";
+import { flatten } from "./util/array-util";
import { getNodeAtPosition, nodeIntersects } from "./util/ast-util";
-import { flatten } from "./util/general-util";
import { iterableFirst } from "./util/iterable-util";
export class LitAnalyzer {
diff --git a/packages/lit-analyzer/src/analyze/parse/document/parse-documents-in-source-file.ts b/packages/lit-analyzer/src/analyze/parse/document/parse-documents-in-source-file.ts
index 1991b319..a2275d52 100644
--- a/packages/lit-analyzer/src/analyze/parse/document/parse-documents-in-source-file.ts
+++ b/packages/lit-analyzer/src/analyze/parse/document/parse-documents-in-source-file.ts
@@ -1,6 +1,7 @@
import { SourceFile, TaggedTemplateExpression } from "typescript";
import { HtmlNodeKind, IHtmlNodeStyleTag } from "../../types/html-node/html-node-types";
-import { flatten, intersects } from "../../util/general-util";
+import { flatten } from "../../util/array-util";
+import { intersects } from "../../util/general-util";
import { findTaggedTemplates } from "../tagged-template/find-tagged-templates";
import { CssDocument } from "./text-document/css-document/css-document";
import { HtmlDocument } from "./text-document/html-document/html-document";
diff --git a/packages/lit-analyzer/src/analyze/types/lit-diagnostic.ts b/packages/lit-analyzer/src/analyze/types/lit-diagnostic.ts
index 7ef25a1a..58939ba4 100644
--- a/packages/lit-analyzer/src/analyze/types/lit-diagnostic.ts
+++ b/packages/lit-analyzer/src/analyze/types/lit-diagnostic.ts
@@ -27,7 +27,9 @@ export enum LitHtmlDiagnosticKind {
MISSING_SLOT_ATTRIBUTE = "MISSING_SLOT_ATTRIBUTE",
DIRECTIVE_NOT_ALLOWED_HERE = "DIRECTIVE_NOT_ALLOWED_HERE",
INVALID_MIXED_BINDING = "INVALID_MIXED_BINDING",
- INVALID_TAG_NAME = "INVALID_TAG_NAME"
+ INVALID_TAG_NAME = "INVALID_TAG_NAME",
+ INVALID_ATTRIBUTE_NAME = "INVALID_ATTRIBUTE_NAME",
+ INVALID_PROPERTY_TYPE = "INVALID_PROPERTY_TYPE"
}
export type LitDiagnosticSeverity = "error" | "warning";
@@ -153,7 +155,17 @@ export interface LitHtmlDiagnosticInvalidTagName extends LitDiagnosticBase {
kind: LitHtmlDiagnosticKind.INVALID_TAG_NAME;
}
+export interface LitHtmlDiagnosticInvalidAttributeName extends LitDiagnosticBase {
+ kind: LitHtmlDiagnosticKind.INVALID_ATTRIBUTE_NAME;
+}
+
+export interface LitHtmlDiagnosticInvalidPropertyType extends LitDiagnosticBase {
+ kind: LitHtmlDiagnosticKind.INVALID_PROPERTY_TYPE;
+}
+
export type LitHtmlDiagnostic =
+ | LitHtmlDiagnosticInvalidPropertyType
+ | LitHtmlDiagnosticInvalidAttributeName
| LitHtmlDiagnosticInvalidTagName
| LitHtmlDiagnosticUnknownTag
| LitHtmlDiagnosticMissingImport
diff --git a/packages/lit-analyzer/src/analyze/util/array-util.ts b/packages/lit-analyzer/src/analyze/util/array-util.ts
new file mode 100644
index 00000000..5dfb287a
--- /dev/null
+++ b/packages/lit-analyzer/src/analyze/util/array-util.ts
@@ -0,0 +1,17 @@
+/**
+ * Flattens a nested array.
+ * @param items
+ */
+export function flatten(items: T[][]): T[] {
+ return items.reduce((acc, item) => [...acc, ...item], []);
+}
+
+/**
+ * Joins an array with a custom final splitter
+ * @param items
+ * @param splitter
+ * @param finalSplitter
+ */
+export function joinArray(items: string[], splitter = ", ", finalSplitter = "or"): string {
+ return items.join(splitter).replace(/, ([^,]*)$/, ` ${finalSplitter} $1`);
+}
diff --git a/packages/lit-analyzer/src/analyze/util/general-util.ts b/packages/lit-analyzer/src/analyze/util/general-util.ts
index 1d7e8af4..53ae4c1e 100644
--- a/packages/lit-analyzer/src/analyze/util/general-util.ts
+++ b/packages/lit-analyzer/src/analyze/util/general-util.ts
@@ -24,14 +24,6 @@ export function intersects(position: number | Range, { start, end }: Range): boo
}
}
-/**
- * Flattens a nested array
- * @param items
- */
-export function flatten(items: T[][]): T[] {
- return items.reduce((acc, item) => [...acc, ...item], []);
-}
-
export function rangeToTSSpan({ start, end }: Range): { start: number; length: number } {
return { start, length: end - start };
}
diff --git a/packages/lit-analyzer/src/cli/analyze-globs.ts b/packages/lit-analyzer/src/cli/analyze-globs.ts
index af0c67cc..689961d6 100644
--- a/packages/lit-analyzer/src/cli/analyze-globs.ts
+++ b/packages/lit-analyzer/src/cli/analyze-globs.ts
@@ -2,7 +2,7 @@ import { async } from "fast-glob";
import { existsSync, lstatSync } from "fs";
import { join } from "path";
import { Diagnostic, flattenDiagnosticMessageText, Program, SourceFile } from "typescript";
-import { flatten } from "../analyze/util/general-util";
+import { flatten } from "../analyze/util/array-util";
import { CompileResult, compileTypescript } from "./compile";
import { LitAnalyzerCliConfig } from "./lit-analyzer-cli-config";
diff --git a/packages/lit-analyzer/src/cli/cli.ts b/packages/lit-analyzer/src/cli/cli.ts
index b70337cb..fb68d490 100644
--- a/packages/lit-analyzer/src/cli/cli.ts
+++ b/packages/lit-analyzer/src/cli/cli.ts
@@ -75,7 +75,6 @@ export async function cli() {
o no-incompatible-type-binding
o no-invalid-directive-binding
o no-incompatible-property-type
- o no-unknown-property-converter
o no-invalid-attribute-name
o no-invalid-tag-name
o no-invalid-css
diff --git a/packages/lit-analyzer/src/rules/no-incompatible-property-type.ts b/packages/lit-analyzer/src/rules/no-incompatible-property-type.ts
new file mode 100644
index 00000000..450939bc
--- /dev/null
+++ b/packages/lit-analyzer/src/rules/no-incompatible-property-type.ts
@@ -0,0 +1,235 @@
+import { isAssignableToSimpleTypeKind, SimpleType, SimpleTypeKind, toSimpleType, toTypeString } from "ts-simple-type";
+import { Node } from "typescript";
+import { ComponentMember } from "web-component-analyzer";
+import { LitElementPropertyConfig } from "web-component-analyzer/lib/cjs/lit-element-property-config-a6e5ad36";
+import { litDiagnosticRuleSeverity } from "../analyze/lit-analyzer-config";
+import { LitAnalyzerRequest } from "../analyze/lit-analyzer-context";
+import { LitHtmlDiagnostic, LitHtmlDiagnosticKind } from "../analyze/types/lit-diagnostic";
+import { RuleModule } from "../analyze/types/rule-module";
+import { joinArray } from "../analyze/util/array-util";
+import { lazy } from "../analyze/util/general-util";
+import { rangeFromNode } from "../analyze/util/lit-range-util";
+
+const rule: RuleModule = {
+ name: "no-incompatible-property-type",
+
+ visitComponentMember(member: ComponentMember, request: LitAnalyzerRequest): LitHtmlDiagnostic[] | void {
+ if (member.meta == null) return;
+
+ const checker = request.program.getTypeChecker();
+ return validateLitPropertyConfig(
+ member.meta.node?.type || member.meta.node?.decorator?.expression || member.node,
+ member.meta,
+ {
+ propName: member.propName || "",
+ simplePropType: toSimpleType(member.node, checker)
+ },
+ request
+ );
+ }
+};
+
+/**
+ * Returns a string, that can be used in a lit @property decorator for the type key, representing the simple type kind.
+ * @param simpleTypeKind
+ */
+function toLitPropertyTypeString(simpleTypeKind: SimpleTypeKind): string {
+ switch (simpleTypeKind) {
+ case SimpleTypeKind.STRING:
+ return "String";
+ case SimpleTypeKind.NUMBER:
+ return "Number";
+ case SimpleTypeKind.BOOLEAN:
+ return "Boolean";
+ case SimpleTypeKind.ARRAY:
+ return "Array";
+ case SimpleTypeKind.OBJECT:
+ return "Object";
+ default:
+ return "";
+ }
+}
+
+/**
+ * Prepares functions that can lazily test assignability against simple type kinds.
+ * This tester function uses a cache for performance.
+ * @param simpleType
+ */
+function prepareSimpleAssignabilityTester(
+ simpleType: SimpleType
+): { isAssignableTo: (kind: SimpleTypeKind) => boolean; acceptedTypeKinds: () => SimpleTypeKind[] } {
+ // Test assignments to all possible type kinds
+ const _isAssignableToCache = new Map();
+ function isAssignableTo(simpleTypeKind: SimpleTypeKind): boolean {
+ if (_isAssignableToCache.has(simpleTypeKind)) {
+ return _isAssignableToCache.get(simpleTypeKind)!;
+ }
+
+ const result = (() => {
+ switch (simpleTypeKind) {
+ case SimpleTypeKind.STRING:
+ return isAssignableToSimpleTypeKind(simpleType, [SimpleTypeKind.STRING, SimpleTypeKind.STRING_LITERAL], { op: "or" });
+ case SimpleTypeKind.NUMBER:
+ return isAssignableToSimpleTypeKind(simpleType, [SimpleTypeKind.NUMBER, SimpleTypeKind.NUMBER_LITERAL], { op: "or" });
+ case SimpleTypeKind.BOOLEAN:
+ return isAssignableToSimpleTypeKind(simpleType, [SimpleTypeKind.BOOLEAN, SimpleTypeKind.BOOLEAN_LITERAL], { op: "or" });
+ case SimpleTypeKind.ARRAY:
+ return isAssignableToSimpleTypeKind(simpleType, [SimpleTypeKind.ARRAY, SimpleTypeKind.TUPLE], { op: "or" });
+ case SimpleTypeKind.OBJECT:
+ return isAssignableToSimpleTypeKind(simpleType, [SimpleTypeKind.OBJECT, SimpleTypeKind.INTERFACE], {
+ op: "or"
+ });
+ case SimpleTypeKind.ANY:
+ return isAssignableToSimpleTypeKind(simpleType, SimpleTypeKind.ANY);
+ default:
+ return false;
+ }
+ })();
+
+ _isAssignableToCache.set(simpleTypeKind, result);
+
+ return result;
+ }
+
+ // Collect type kinds that can be used in as "type" in the @property decorator
+ const acceptedTypeKinds = lazy(() => {
+ return [SimpleTypeKind.STRING, SimpleTypeKind.NUMBER, SimpleTypeKind.BOOLEAN, SimpleTypeKind.ARRAY, SimpleTypeKind.OBJECT, SimpleTypeKind.ANY]
+ .filter(kind => kind !== SimpleTypeKind.ANY)
+ .filter(kind => isAssignableTo(kind));
+ });
+
+ return { acceptedTypeKinds, isAssignableTo };
+}
+
+/**
+ * Runs through a lit configuration and validates against the "simplePropType".
+ * Emits diagnostics through the context.
+ * @param node
+ * @param litConfig
+ * @param propName
+ * @param simplePropType
+ * @param request
+ */
+function validateLitPropertyConfig(
+ node: Node,
+ litConfig: LitElementPropertyConfig,
+ { propName, simplePropType }: { propName: string; simplePropType: SimpleType },
+ request: LitAnalyzerRequest
+): LitHtmlDiagnostic[] | void {
+ // Check if "type" is one of the built in default type converter hint
+ if (typeof litConfig.type === "string" && !litConfig.hasConverter) {
+ return [
+ {
+ kind: LitHtmlDiagnosticKind.INVALID_PROPERTY_TYPE,
+ source: "no-incompatible-property-type",
+ severity: litDiagnosticRuleSeverity(request.config, "no-incompatible-property-type"),
+ message: `'${litConfig.type}' is not a valid type for the default converter. Have you considered {attribute: false} instead?`,
+ file: request.file,
+ location: rangeFromNode(node)
+ }
+ ];
+ }
+
+ // Don't continue if we don't know the property type (eg if we are in a js file)
+ // Don't continue if this property has a custom converter (because then we don't know how the value will be converted)
+ if (simplePropType == null || litConfig.hasConverter || typeof litConfig.type === "string") {
+ return;
+ }
+
+ const { acceptedTypeKinds, isAssignableTo } = prepareSimpleAssignabilityTester(simplePropType);
+
+ // Test the @property type against the actual type if a type has been provided
+ if (litConfig.type != null) {
+ // Report error if the @property type is not assignable to the actual type
+ if (!isAssignableTo(litConfig.type.kind) && !isAssignableTo(SimpleTypeKind.ANY)) {
+ // Suggest what to use instead
+ if (acceptedTypeKinds().length >= 1) {
+ const potentialKindText = joinArray(
+ acceptedTypeKinds().map(kind => `'${toLitPropertyTypeString(kind)}'`),
+ ", ",
+ "or"
+ );
+
+ return [
+ {
+ kind: LitHtmlDiagnosticKind.INVALID_PROPERTY_TYPE,
+ source: "no-incompatible-property-type",
+ severity: litDiagnosticRuleSeverity(request.config, "no-incompatible-property-type"),
+ message: `@property type should be ${potentialKindText} instead of '${toLitPropertyTypeString(litConfig.type.kind)}'`,
+ file: request.file,
+ location: rangeFromNode(node)
+ }
+ ];
+ }
+
+ // If no suggesting can be provided, report that they are not assignable
+ // The OBJECT @property type is an escape from this error
+ else if (litConfig.type.kind !== SimpleTypeKind.OBJECT) {
+ return [
+ {
+ kind: LitHtmlDiagnosticKind.INVALID_PROPERTY_TYPE,
+ source: "no-incompatible-property-type",
+ severity: litDiagnosticRuleSeverity(request.config, "no-incompatible-property-type"),
+ message: `@property type '${toTypeString(litConfig.type)}' is not assignable to the actual type '${toTypeString(simplePropType)}'`,
+ file: request.file,
+ location: rangeFromNode(node)
+ }
+ ];
+ }
+ }
+ }
+
+ // If no type has been specified, suggest what to use as the @property type
+ else if (litConfig.attribute !== false) {
+ // Don't do anything if there are multiple possibilities for a type.
+ if (isAssignableTo(SimpleTypeKind.ANY)) {
+ return;
+ }
+
+ // Don't report errors because String conversion is default
+ else if (isAssignableTo(SimpleTypeKind.STRING)) {
+ return;
+ }
+
+ // Suggest what to use instead if there are multiple accepted @property types for this property
+ else if (acceptedTypeKinds().length > 0) {
+ // Suggest types to use and include "{attribute: false}" if the @property type is ARRAY or OBJECT
+ const acceptedTypeText = joinArray(
+ [
+ ...acceptedTypeKinds().map(kind => `'{type: ${toLitPropertyTypeString(kind)}}'`),
+ ...(isAssignableTo(SimpleTypeKind.ARRAY) || isAssignableTo(SimpleTypeKind.OBJECT) ? ["'{attribute: false}'"] : [])
+ ],
+ ", ",
+ "or"
+ );
+
+ return [
+ {
+ kind: LitHtmlDiagnosticKind.INVALID_PROPERTY_TYPE,
+ source: "no-incompatible-property-type",
+ severity: litDiagnosticRuleSeverity(request.config, "no-incompatible-property-type"),
+ message: `Missing ${acceptedTypeText} on @property decorator for '${propName}'`,
+ file: request.file,
+ location: rangeFromNode(node)
+ }
+ ];
+ } else {
+ return [
+ {
+ kind: LitHtmlDiagnosticKind.INVALID_PROPERTY_TYPE,
+ source: "no-incompatible-property-type",
+ severity: litDiagnosticRuleSeverity(request.config, "no-incompatible-property-type"),
+ message: `The built in converter doesn't handle the property type '${toTypeString(
+ simplePropType
+ )}'. Please add '{attribute: false}' on @property decorator for '${propName}'`,
+ file: request.file,
+ location: rangeFromNode(node)
+ }
+ ];
+ }
+ }
+
+ // message: `You need to add '{attribute: false}' to @property decorator for '${propName}' because '${toTypeString(simplePropType)}' type is not a primitive`
+}
+
+export default rule;
diff --git a/packages/lit-analyzer/src/rules/no-invalid-attribute-name.ts b/packages/lit-analyzer/src/rules/no-invalid-attribute-name.ts
index 5645c855..f75c09e9 100644
--- a/packages/lit-analyzer/src/rules/no-invalid-attribute-name.ts
+++ b/packages/lit-analyzer/src/rules/no-invalid-attribute-name.ts
@@ -1,38 +1,40 @@
+import { Node } from "typescript";
import { ComponentMember } from "web-component-analyzer";
+import { litDiagnosticRuleSeverity } from "../analyze/lit-analyzer-config";
import { LitAnalyzerRequest } from "../analyze/lit-analyzer-context";
-import { LitHtmlDiagnostic } from "../analyze/types/lit-diagnostic";
+import { LitHtmlDiagnostic, LitHtmlDiagnosticKind } from "../analyze/types/lit-diagnostic";
import { RuleModule } from "../analyze/types/rule-module";
+import { isValidAttributeName } from "../analyze/util/is-valid-name";
+import { rangeFromNode } from "../analyze/util/lit-range-util";
const rule: RuleModule = {
name: "no-invalid-attribute-name",
visitComponentMember(member: ComponentMember, request: LitAnalyzerRequest): LitHtmlDiagnostic[] | void {
- console.log(`component member`);
// Check if the tag name is invalid
- if (member.meta != null) {
- console.log("found meta", member.meta.attribute);
- } else if (member.kind === "attribute") {
- console.log("found attr", member.attrName);
- }
-
- /*const node = iterableFirst(definition.tagNameNodes) || iterableFirst(definition.identifierNodes);
+ let attrName: undefined | string;
+ let attrNameNode: undefined | Node;
- // Only report diagnostic if the tag is not builtin
- const tag = request.htmlStore.getHtmlTag(definition.tagName);
- if (node != null && tag != null && !tag.builtIn) {
- return [
- {
- kind: LitHtmlDiagnosticKind.INVALID_TAG_NAME,
- source: "no-invalid-tag-name",
- severity: litDiagnosticRuleSeverity(request.config, "no-invalid-tag-name"),
- message: `This custom element tag name is invalid.`,
- file: request.file,
- location: rangeFromNode(node)
- }
- ];
- }*/
+ if (member.kind === "attribute") {
+ attrName = member.attrName;
+ attrNameNode = member.node;
+ } else if (typeof member.meta?.attribute === "string") {
+ attrName = member.meta.attribute;
+ attrNameNode = member.meta.node?.attribute || member.node;
+ }
- return [];
+ if (attrName != null && attrNameNode != null && !isValidAttributeName(attrName)) {
+ return [
+ {
+ kind: LitHtmlDiagnosticKind.INVALID_ATTRIBUTE_NAME,
+ source: "no-invalid-attribute-name",
+ severity: litDiagnosticRuleSeverity(request.config, "no-invalid-attribute-name"),
+ message: `'${attrName}' is not a valid attribute name.`,
+ file: request.file,
+ location: rangeFromNode(attrNameNode)
+ }
+ ];
+ }
}
};
diff --git a/packages/lit-analyzer/src/rules/no-invalid-property.ts b/packages/lit-analyzer/src/rules/no-invalid-property.ts
index c4eaf6a4..a5ddebd8 100644
--- a/packages/lit-analyzer/src/rules/no-invalid-property.ts
+++ b/packages/lit-analyzer/src/rules/no-invalid-property.ts
@@ -1,51 +1,38 @@
-import { isAssignableToSimpleTypeKind, SimpleType, SimpleTypeKind, toSimpleType, toTypeString } from "ts-simple-type";
+/*import { isAssignableToSimpleTypeKind, SimpleType, SimpleTypeKind, toSimpleType, toTypeString } from "ts-simple-type";
import { Node } from "typescript";
-import { ComponentDeclaration } from "web-component-analyzer";
+import { ComponentMember } from "web-component-analyzer";
import { LitElementPropertyConfig } from "web-component-analyzer/lib/cjs/lit-element-property-config-a6e5ad36";
import { LitAnalyzerRequest } from "../analyze/lit-analyzer-context";
import { LitHtmlDiagnostic } from "../analyze/types/lit-diagnostic";
import { RuleModule } from "../analyze/types/rule-module";
-import { isValidAttributeName } from "../analyze/util/is-valid-name";
+import { lazy } from "../analyze/util/general-util";
const rule: RuleModule = {
name: "no-invalid-property",
- visitComponentDeclaration(declaration: ComponentDeclaration, context: LitAnalyzerRequest): LitHtmlDiagnostic[] | void {
- for (const member of declaration.members) {
- if (member.meta == null) continue;
- //const meta = member.meta;
- //console.log(`META FOR `, member.attrName, member.propName, meta);
- const checker = context.program.getTypeChecker();
- validateLitPropertyConfig(
- member.node,
- member.meta,
- {
- propName: member.propName || "",
- simplePropType: toSimpleType(member.node, checker)
- },
- context
- );
- }
+ visitComponentMember(member: ComponentMember, request: LitAnalyzerRequest): LitHtmlDiagnostic[] | void {
+ if (member.meta == null) return;
+
+ const checker = request.program.getTypeChecker();
+ validateLitPropertyConfig(
+ member.node,
+ member.meta,
+ {
+ propName: member.propName || "",
+ simplePropType: toSimpleType(member.node, checker)
+ },
+ request
+ );
return [];
}
-};
-
-/**
- * Joins an array with a custom final splitter
- * @param items
- * @param splitter
- * @param finalSplitter
- */
-export function joinArray(items: string[], splitter: string = ", ", finalSplitter: string = "or"): string {
- return items.join(splitter).replace(/, ([^,]*)$/, ` ${finalSplitter} $1`);
-}
+};*/
/**
* Returns a string, that can be used in a lit @property decorator for the type key, representing the simple type kind.
* @param simpleTypeKind
*/
-function toLitPropertyTypeString(simpleTypeKind: SimpleTypeKind): string {
+/*function toLitPropertyTypeString(simpleTypeKind: SimpleTypeKind): string {
switch (simpleTypeKind) {
case SimpleTypeKind.STRING:
return "String";
@@ -60,7 +47,7 @@ function toLitPropertyTypeString(simpleTypeKind: SimpleTypeKind): string {
default:
return "";
}
-}
+}*/
/**
* Runs through a lit configuration and validates against the "simplePropType".
@@ -71,25 +58,12 @@ function toLitPropertyTypeString(simpleTypeKind: SimpleTypeKind): string {
* @param simplePropType
* @param request
*/
-function validateLitPropertyConfig(
+/*function validateLitPropertyConfig(
node: Node,
litConfig: LitElementPropertyConfig,
- { propName, simplePropType }: { propName: string; simplePropType: SimpleType | undefined },
+ { propName, simplePropType }: { propName: string; simplePropType: SimpleType },
request: LitAnalyzerRequest
) {
- if (typeof litConfig.attribute === "string") {
- if (!isValidAttributeName(litConfig.attribute)) {
- console.log({
- message: `Invalid attribute name '${litConfig.attribute}'`
- });
- /*context.emitDiagnostics({
- node: (litConfig.node && litConfig.node.attribute) || node,
- severity: "error",
- message: `Invalid attribute name '${litConfig.attribute}'`
- });*/
- }
- }
-
// Check if "type" is one of the built in default type converter hint
if (typeof litConfig.type === "string" && !litConfig.hasConverter) {
console.log({ message: `'${litConfig.type}' is not a valid type for the default converter. Have you considered {attribute: false} instead?` });
@@ -97,7 +71,7 @@ function validateLitPropertyConfig(
node: (litConfig.node && litConfig.node.type) || node,
message: `'${litConfig.type}' is not a valid type for the default converter. Have you considered {attribute: false} instead?`,
severity: "warning"
- });*/
+ });
return;
}
@@ -108,31 +82,75 @@ function validateLitPropertyConfig(
}
// Test assignments to all possible type kinds
- const isAssignableTo: Partial> = {
- [SimpleTypeKind.STRING]: isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.STRING, SimpleTypeKind.STRING_LITERAL], { op: "or" }),
- [SimpleTypeKind.NUMBER]: isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.NUMBER, SimpleTypeKind.NUMBER_LITERAL], { op: "or" }),
- [SimpleTypeKind.BOOLEAN]: isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.BOOLEAN, SimpleTypeKind.BOOLEAN_LITERAL], { op: "or" }),
- [SimpleTypeKind.ARRAY]: isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.ARRAY, SimpleTypeKind.TUPLE], { op: "or" }),
- [SimpleTypeKind.OBJECT]: isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.OBJECT, SimpleTypeKind.INTERFACE], {
- op: "or"
- }),
- [SimpleTypeKind.ANY]: isAssignableToSimpleTypeKind(simplePropType, SimpleTypeKind.ANY)
- };
+ const _isAssignableToCache = new Map();
+ function isAssignableTo(simpleTypeKind: SimpleTypeKind): boolean {
+ if (_isAssignableToCache.has(simpleTypeKind)) {
+ return _isAssignableToCache.get(simpleTypeKind)!;
+ }
+
+ if (simplePropType == null) {
+ return false;
+ }
+
+ const result = (() => {
+ switch (simpleTypeKind) {
+ case SimpleTypeKind.STRING:
+ return isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.STRING, SimpleTypeKind.STRING_LITERAL], { op: "or" });
+ case SimpleTypeKind.NUMBER:
+ return isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.NUMBER, SimpleTypeKind.NUMBER_LITERAL], { op: "or" });
+ case SimpleTypeKind.BOOLEAN:
+ return isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.BOOLEAN, SimpleTypeKind.BOOLEAN_LITERAL], { op: "or" });
+ case SimpleTypeKind.ARRAY:
+ return isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.ARRAY, SimpleTypeKind.TUPLE], { op: "or" });
+ case SimpleTypeKind.OBJECT:
+ return isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.OBJECT, SimpleTypeKind.INTERFACE], {
+ op: "or"
+ });
+ case SimpleTypeKind.ANY:
+ return isAssignableToSimpleTypeKind(simplePropType, SimpleTypeKind.ANY);
+ default:
+ return false;
+ }
+ })();
+
+ _isAssignableToCache.set(simpleTypeKind, result);
+
+ return result;
+ }
+ /*const isAssignableTo: Partial boolean>> = {
+ [SimpleTypeKind.STRING]: lazy(() =>
+ isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.STRING, SimpleTypeKind.STRING_LITERAL], { op: "or" })
+ ),
+ [SimpleTypeKind.NUMBER]: lazy(() =>
+ isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.NUMBER, SimpleTypeKind.NUMBER_LITERAL], { op: "or" })
+ ),
+ [SimpleTypeKind.BOOLEAN]: lazy(() =>
+ isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.BOOLEAN, SimpleTypeKind.BOOLEAN_LITERAL], { op: "or" })
+ ),
+ [SimpleTypeKind.ARRAY]: lazy(() => isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.ARRAY, SimpleTypeKind.TUPLE], { op: "or" })),
+ [SimpleTypeKind.OBJECT]: lazy(() =>
+ isAssignableToSimpleTypeKind(simplePropType, [SimpleTypeKind.OBJECT, SimpleTypeKind.INTERFACE], {
+ op: "or"
+ })
+ ),
+ [SimpleTypeKind.ANY]: lazy(() => isAssignableToSimpleTypeKind(simplePropType, SimpleTypeKind.ANY))
+ };/
// Collect type kinds that can be used in as "type" in the @property decorator
- const acceptedTypeKinds = Object.entries(isAssignableTo)
- .filter(([, assignable]) => assignable)
- .map(([kind]) => kind as SimpleTypeKind)
- .filter(kind => kind !== SimpleTypeKind.ANY);
+ const acceptedTypeKinds = lazy(() => {
+ return [SimpleTypeKind.STRING, SimpleTypeKind.NUMBER, SimpleTypeKind.BOOLEAN, SimpleTypeKind.ARRAY, SimpleTypeKind.OBJECT, SimpleTypeKind.ANY]
+ .filter(kind => kind !== SimpleTypeKind.ANY)
+ .filter(kind => isAssignableTo(kind));
+ });
// Test the @property type against the actual type if a type has been provided
if (litConfig.type != null) {
// Report error if the @property type is not assignable to the actual type
- if (isAssignableTo[litConfig.type.kind] === false && isAssignableTo[SimpleTypeKind.ANY] === false) {
+ if (!isAssignableTo(litConfig.type.kind) && !isAssignableTo(SimpleTypeKind.ANY)) {
// Suggest what to use instead
- if (acceptedTypeKinds.length >= 1) {
+ if (acceptedTypeKinds().length >= 1) {
const potentialKindText = joinArray(
- acceptedTypeKinds.map(kind => `'${toLitPropertyTypeString(kind)}'`),
+ acceptedTypeKinds().map(kind => `'${toLitPropertyTypeString(kind)}'`),
", ",
"or"
);
@@ -142,7 +160,7 @@ function validateLitPropertyConfig(
node: (litConfig.node && litConfig.node.type) || node,
message: `@property type should be ${potentialKindText} instead of '${toLitPropertyTypeString(litConfig.type.kind)}'`,
severity: "warning"
- });*/
+ });/
}
// If no suggesting can be provided, report that they are not assignable
@@ -155,54 +173,52 @@ function validateLitPropertyConfig(
node: (litConfig.node && litConfig.node.type) || node,
message: `@property type '${toTypeString(litConfig.type)}' is not assignable to the actual type '${toTypeString(simplePropType)}'`,
severity: "warning"
- });*/
+ });/
}
}
}
// If no type has been specified, suggest what to use as the @property type
- else {
- if (!litConfig.hasConverter && litConfig.attribute !== false) {
- // Don't do anything if there are multiple possibilities for a type.
- if (isAssignableTo[SimpleTypeKind.ANY]) {
- }
+ else if (litConfig.attribute !== false) {
+ // Don't do anything if there are multiple possibilities for a type.
+ if (isAssignableTo(SimpleTypeKind.ANY)) {
+ }
- // Don't report errors because String conversion is default
- else if (isAssignableTo[SimpleTypeKind.STRING]) {
- }
+ // Don't report errors because String conversion is default
+ else if (isAssignableTo(SimpleTypeKind.STRING)) {
+ }
- // Suggest what to use instead if there are multiple accepted @property types for this property
- else if (acceptedTypeKinds.length > 0) {
- // Suggest types to use and include "{attribute: false}" if the @property type is ARRAY or OBJECT
- const acceptedTypeText = joinArray(
- [
- ...acceptedTypeKinds.map(kind => `'{type: ${toLitPropertyTypeString(kind)}}'`),
- ...(isAssignableTo[SimpleTypeKind.ARRAY] || isAssignableTo[SimpleTypeKind.OBJECT] ? ["'{attribute: false}'"] : [])
- ],
- ", ",
- "or"
- );
+ // Suggest what to use instead if there are multiple accepted @property types for this property
+ else if (acceptedTypeKinds().length > 0) {
+ // Suggest types to use and include "{attribute: false}" if the @property type is ARRAY or OBJECT
+ const acceptedTypeText = joinArray(
+ [
+ ...acceptedTypeKinds().map(kind => `'{type: ${toLitPropertyTypeString(kind)}}'`),
+ ...(isAssignableTo(SimpleTypeKind.ARRAY) || isAssignableTo(SimpleTypeKind.OBJECT) ? ["'{attribute: false}'"] : [])
+ ],
+ ", ",
+ "or"
+ );
- console.log({ message: `Missing ${acceptedTypeText} on @property decorator for '${propName}'` });
- /*context.emitDiagnostics({
+ console.log({ message: `Missing ${acceptedTypeText} on @property decorator for '${propName}'` });
+ /*context.emitDiagnostics({
node,
severity: "warning",
message: `Missing ${acceptedTypeText} on @property decorator for '${propName}'`
- });*/
- } else {
- console.log({
- message: `The built in converter doesn't handle the property type '${toTypeString(
- simplePropType
- )}'. Please add '{attribute: false}' on @property decorator for '${propName}'`
- });
- /*context.emitDiagnostics({
+ });/
+ } else {
+ console.log({
+ message: `The built in converter doesn't handle the property type '${toTypeString(
+ simplePropType
+ )}'. Please add '{attribute: false}' on @property decorator for '${propName}'`
+ });
+ /*context.emitDiagnostics({
node,
severity: "warning",
message: `The built in converter doesn't handle the property type '${toTypeString(
simplePropType
)}'. Please add '{attribute: false}' on @property decorator for '${propName}'`
- });*/
- }
+ });/
}
}
@@ -212,7 +228,8 @@ function validateLitPropertyConfig(
severity: "warning",
message: `You need to add '{attribute: false}' to @property decorator for '${propName}' because '${toTypeString(simplePropType)}' type is not a primitive`
});
- }*/
+ }/
}
export default rule;
+*/
diff --git a/packages/lit-analyzer/src/rules/no-invalid-tag-name.ts b/packages/lit-analyzer/src/rules/no-invalid-tag-name.ts
index 82594152..1d858323 100644
--- a/packages/lit-analyzer/src/rules/no-invalid-tag-name.ts
+++ b/packages/lit-analyzer/src/rules/no-invalid-tag-name.ts
@@ -15,7 +15,8 @@ const rule: RuleModule = {
if (!isValidCustomElementName(definition.tagName)) {
const node = iterableFirst(definition.tagNameNodes) || iterableFirst(definition.identifierNodes);
- // Only report diagnostic if the tag is not built in
+ // Only report diagnostic if the tag is not built in,
+ // because this function among other things tests for missing "-" in custom element names
const tag = request.htmlStore.getHtmlTag(definition.tagName);
if (node != null && tag != null && !tag.builtIn) {
return [
diff --git a/packages/ts-lit-plugin/README.md b/packages/ts-lit-plugin/README.md
index d4b83c1e..1840ab70 100644
--- a/packages/ts-lit-plugin/README.md
+++ b/packages/ts-lit-plugin/README.md
@@ -7,18 +7,21 @@
-
-
-
+
+
+
+
-[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#installation)
+
+[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#installation)
+
## ➤ Installation
First, install the plugin:
@@ -50,8 +53,9 @@ Finally, restart you Typescript Language Service, and you should start getting d
- If you use Visual Studio Code you can also install the [lit-plugin](https://marketplace.visualstudio.com/items?itemName=runem.lit-plugin) extension.
- If you would rather use a CLI, you can install the [lit-analyzer](https://github.com/runem/lit-analyzer/blob/master/packages/lit-analyzer).
-[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#configuration)
-
+
+[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#configuration)
+
## ➤ Configuration
You can configure this plugin through your `tsconfig.json`.
@@ -92,8 +96,10 @@ You can configure this plugin through your `tsconfig.json`.
| `globalEvents` | List of event names that you expect to be present at all times | `string[]` | |
| `customHtmlData` | This plugin supports the [custom vscode html data format](https://code.visualstudio.com/updates/v1_31#_html-and-css-custom-data-support) through this setting. | [Vscode Custom HTML Data Format](https://github.com/Microsoft/vscode-html-languageservice/blob/master/docs/customData.md). Supports arrays, objects and relative file paths | |
-[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#rules)
+
+[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#rules)
+
## ➤ Rules
The default severity of each rule depend on the `strict` [configuration option](#-configuration). Strict mode is disabled as default.
@@ -139,7 +145,6 @@ Each rule can have severity of `off`, `warning` or `error`. You can toggle rules
| Rule | Description | Severity normal | Severity strict |
| :------ | ----------- | --------------- | --------------- |
| [no-incompatible-property-type](#-no-incompatible-property-type) | When using the @property decorator in Typescript, the property option `type` is checked against the declared property Typescript type | error | error |
-| [no-unknown-property-converter](#-no-unknown-property-converter) | LitElement provides default converters. For example 'Function' is not a valid default converter type for a LitElement-managed property. | error | error |
| [no-invalid-attribute-name](#-no-invalid-attribute-name) | When using the property option `attribute`, the value is checked to make sure it's a valid attribute name. | error | error |
| [no-invalid-tag-name](#-no-invalid-tag-name) | When defining a custom element the tag name is checked to make sure it's valid. | error | error |
@@ -494,7 +499,15 @@ html``
#### 💞 no-incompatible-property-type
-When using the @property decorator in Typescript, the property option `type` is checked against the declared property Typescript type.
+This rule checks that LitElement-controlled properties are correctly configured in accordance with the default value converter.
+
+The following is a summary of what this rule does:
+
+1. The `type` given to the LitElement property configuration is checked against the actual Typescript type of the property.
+2. The default converter only accepts the types `String`, `Boolean`, `Number`, `Array` and `Object`, so all other values for `type` are considered warnings.
+3. The absence of a `type` is only considered a warning if the property is not assignable to the `string` type.
+
+This rule will not check for a given LitElement-controlled property if the property has custom converter configured.
The following examples are considered warnings:
@@ -505,30 +518,7 @@ class MyElement extends LitElement {
@property({type: Boolean}) count: number;
@property({type: String}) disabled: boolean;
@property({type: Object}) list: ListItem[];
-}
-```
-
-The following examples are not considered warnings:
-
-
-```js
-class MyElement extends LitElement {
- @property({type: String}) text: string;
- @property({type: Number}) count: number;
- @property({type: Boolean}) disabled: boolean;
- @property({type: Array}) list: ListItem[];
-}
-```
-#### 👎 no-unknown-property-converter
-
-The default converter in LitElement only accepts `String`, `Boolean`, `Number`, `Array` and `Object`, so all other values for `type` are considered warnings. This check doesn't run if a custom converter is used.
-
-The following example is considered a warning:
-
-
-```js
-class MyElement extends LitElement {
static get properties () {
return {
callback: {
@@ -542,11 +532,16 @@ class MyElement extends LitElement {
}
```
-The following example is not considered a warning:
+The following examples are not considered warnings:
```js
class MyElement extends LitElement {
+ @property({type: String}) text: string;
+ @property({type: Number}) count: number;
+ @property({type: Boolean}) disabled: boolean;
+ @property({type: Array}) list: ListItem[];
+
static get properties () {
return {
callback: {
@@ -558,6 +553,7 @@ class MyElement extends LitElement {
}
}
}
+
}
```
@@ -636,8 +632,9 @@ css`
`
```
-[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#documenting-slots-events-attributes-and-properties)
-
+
+[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#documenting-slots-events-attributes-and-properties)
+
## ➤ Documenting slots, events, attributes and properties
Code is analyzed using [web-component-analyzer](https://github.com/runem/web-component-analyzer) in order to find properties, attributes and events. Unfortunately, sometimes it's not possible to analyze these things by looking at the code, and you will have to document how your component looks using `jsdoc`like this:
@@ -662,16 +659,20 @@ class MyElement extends HTMLElement {
customElements.define("my-element", MyElement);
```
-[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#contributors)
+
+[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#contributors)
+
## ➤ Contributors
+
| [](https://twitter.com/runemehlsen) | [](https://twitter.com/andreasmehlsen) | [](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
-| :--------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------: |
-| [Rune Mehlsen](https://twitter.com/runemehlsen) | [Andreas Mehlsen](https://twitter.com/andreasmehlsen) | [You?](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
-
-[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#license)
+|:--------------------------------------------------:|:--------------------------------------------------:|:--------------------------------------------------:|
+| [Rune Mehlsen](https://twitter.com/runemehlsen) | [Andreas Mehlsen](https://twitter.com/andreasmehlsen) | [You?](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
+
+[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#license)
+
## ➤ License
-
+
Licensed under [MIT](https://opensource.org/licenses/MIT).
diff --git a/packages/vscode-lit-plugin/README.md b/packages/vscode-lit-plugin/README.md
index 7256c872..d9d84053 100644
--- a/packages/vscode-lit-plugin/README.md
+++ b/packages/vscode-lit-plugin/README.md
@@ -1,732 +1,736 @@
-
-
-
-
-
-
-
- Syntax highlighting, type checking and code completion for lit-html
-
-
+
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#installation)
-## ➤ Installation
-
-Simply search for [lit-plugin](https://marketplace.visualstudio.com/items?itemName=runem.lit-plugin) in the vscode marketplace and install the extension.
-
-**Note**: You can also run `code --install-extension runem.lit-plugin` to install it.
+## ➤ Installation
+
+Simply search for [lit-plugin](https://marketplace.visualstudio.com/items?itemName=runem.lit-plugin) in the vscode marketplace and install the extension.
+
+**Note**: You can also run `code --install-extension runem.lit-plugin` to install it.
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#rules)
-## ➤ Rules
-
-The default severity of each rule depend on the `strict` [configuration option](#-configuration). Strict mode is disabled as default.
-
-Each rule can have severity of `off`, `warning` or `error`. You can toggle rules as you like.
-
-**Validating custom elements**
-
-
-| Rule | Description | Severity normal | Severity strict |
-| :------ | ----------- | --------------- | --------------- |
-| [no-unknown-tag-name](#-no-unknown-tag-name) | The existence of tag names are checked. Be aware that not all custom elements from libraries will be found out of the box. | off | warning |
-| [no-missing-import](#-no-missing-import) | When using custom elements in HTML it is checked if the element has been imported and is available in the current context. | off | warning |
-| [no-unclosed-tag](#-no-unclosed-tag) | Unclosed tags, and invalid self closing tags like custom elements tags, are checked. | warning | error |
-
-**Validating binding names**
-
-
-| Rule | Description | Severity normal | Severity strict |
-| :------ | ----------- | --------------- | --------------- |
-| [no-unknown-attribute](#-no-unknown-attribute-no-unknown-property) [no-unknown-property](#-no-unknown-attribute-no-unknown-property) | You will get a warning whenever you use an unknown attribute or property within your `lit-html` template. | off | warning |
-| [no-unknown-event](#-no-unknown-event) | When using event bindings it's checked that the event names are fired. | off | off |
-| [no-unknown-slot](#-no-unknown-slot) | Using the "@slot" jsdoc tag on your custom element class, you can tell which slots are accepted for a particular element. | off | warning |
-
-**Validating binding types**
-
-
-| Rule | Description | Severity normal | Severity strict |
-| :------ | ----------- | --------------- | --------------- |
-| [no-invalid-boolean-binding](#-no-invalid-boolean-binding) | Disallow boolean attribute bindings on non-boolean types. | error | error |
-| [no-expressionless-property-binding](#-no-expressionless-property-binding) | Disallow property bindings without an expression. | error | error |
-| [no-noncallable-event-binding](#-no-noncallable-event-binding) | Disallow event listener bindings with a noncallable type. | error | error |
-| [no-boolean-in-attribute-binding](#-no-boolean-in-attribute-binding) | Disallow attribute bindings with a boolean type. | error | error |
-| [no-complex-attribute-binding](#-no-complex-attribute-binding) | Disallow attribute bindings with a complex type. | error | error |
-| [no-nullable-attribute-binding](#-no-nullable-attribute-binding) | Disallow attribute bindings with nullable types such as "null" or "undefined". | error | error |
-| [no-incompatible-type-binding](#-no-incompatible-type-binding) | Disallow incompatible type in bindings. | error | error |
-| [no-invalid-directive-binding](#-no-invalid-directive-binding) | Disallow using built-in directives in unsupported bindings. | error | error |
-| [no-unintended-mixed-binding](#-no-unintended-mixed-binding) | Disallow mixed value bindings where a character `'`, `"`, `}` or `/` is unintentionally included in the binding. | warn | warn |
-
-**Validating LitElement**
-
-
-| Rule | Description | Severity normal | Severity strict |
-| :------ | ----------- | --------------- | --------------- |
-| [no-incompatible-property-type](#-no-incompatible-property-type) | When using the @property decorator in Typescript, the property option `type` is checked against the declared property Typescript type | error | error |
-| [no-unknown-property-converter](#-no-unknown-property-converter) | LitElement provides default converters. For example 'Function' is not a valid default converter type for a LitElement-managed property. | error | error |
-| [no-invalid-attribute-name](#-no-invalid-attribute-name) | When using the property option `attribute`, the value is checked to make sure it's a valid attribute name. | error | error |
-| [no-invalid-tag-name](#-no-invalid-tag-name) | When defining a custom element the tag name is checked to make sure it's valid. | error | error |
-
-**Validating CSS**
-
-
-| Rule | Description | Severity normal | Severity strict |
-| :------ | ----------- | --------------- | --------------- |
-| [💅 no-invalid-css](#-no-invalid-css) | CSS within the tagged template literal `css` will be validated. | warning | error |
-
-### Validating custom elements
-
-All web components in your code are analyzed using [web-component-analyzer](https://github.com/runem/web-component-analyzer) which supports native custom elements and web components built with LitElement.
-
-#### 🤷 no-unknown-tag-name
-
-Web components defined in libraries need to either extend the global `HTMLElementTagNameMap` (typescript definition file) or include the "@customElement tag-name" jsdoc on the custom element class.
-
-Below you will see an example of what to add to your library typescript definition files if you want type checking support for a given html tag name.
-
-
-```typescript
-declare global {
- interface HTMLElementTagNameMap {
- "my-element": MyElement;
- }
-}
-```
-
-#### 📣 no-missing-import
-
-When using custom elements in HTML it is checked if the element has been imported and is available in the current context. It's considered imported if any imported module (or their imports) defines the custom element.
-
-The following example is considered a warning:
-
-
-```js
-// No import of "my-element"
-html``
-```
-
-The following example is not considered a warning:
-
-
-```js
-import "my-element.js";
-html``
-```
-
-#### ☯ no-unclosed-tag
-
-Unclosed tags, and invalid self closing tags like custom elements tags, are checked.
-
-The following examples are considered warnings:
-
-
-```js
-html`
`
-html``
-html``
-```
-
-The following examples are not considered warnings:
-
-
-```js
-html``
-html``
-html``
-html``
-```
-
-### Validating binding names
-
-Attributes, properties and events are picked up on custom elements using [web-component-analyzer](https://github.com/runem/web-component-analyzer) which supports native custom elements and web components built with LitElement.
-
-#### ✅ no-unknown-attribute, no-unknown-property
-
-You will get a warning whenever you use an unknown attribute or property. This check is made on both custom elements and built in elements.
-
-**The following example is considered a warning:**
-
-
-```js
-html``
-```
-
-**The following example is not considered a warning:**
-
-
-```js
-html``
-```
-
-#### ⚡️ no-unknown-event
-
-You can opt in to check for unknown event names. Using the `@fires` jsdoc or the statement `this.dispatch(new CustomEvent("my-event))` will make the event name available. All event names are accepted globally because events bubble.
-
-The following example is considered a warning:
-
-
-```js
-html``
-```
-
-The following example is not considered a warning:
-
-
-```js
-html``
-```
-
-#### 📬 no-unknown-slot
-
-Using the "@slot" jsdoc tag on your custom element class, you can tell which slots are accepted for a particular element. Then you will get warnings for invalid slot names and if you forget to add the slot attribute on elements without an unnamed slot.
-
-
-```js
-/**
- * @slot - This is a comment for the unnamed slot
- * @slot right - Right content
- * @slot left
- */
-class MyElement extends HTMLElement {
-}
-customElements.define("my-element", MyElement);
-```
-
-The following example is considered a warning:
-
-
-```js
-html`
-
-
-
-`
-```
-
-The following example is not considered a warning:
-
-
-```js
-html`
-
-
-
-
-
-`
-```
-
-### Validating binding types
-
-Be aware that many checks involving analyzing bindings will work better in Typescript files because we have more information about the values being bound.
-
-#### ❓ no-invalid-boolean-binding
-
-It never makes sense to use the boolean attribute binding on a non-boolean type.
-
-The following example is considered a warning:
-
-
-```js
-html``
-```
-
-The following example is not considered a warning:
-
-
-```js
-html``
-```
-
-#### ⚫️ no-expressionless-property-binding
-
-Because of how `lit-html` [parses bindings internally](https://github.com/Polymer/lit-html/issues/843) you cannot use the property binding without an expression.
-
-The following example is considered a warning:
-
-
-```js
-html``
-```
-
-The following example is not considered a warning:
-
-
-```js
-html``
-```
-
-#### 🌀 no-noncallable-event-binding
-
-It's a common mistake to incorrectly call the function when setting up an event handler binding instead of passing a reference to the function. This makes the function call whenever the code evaluates.
-
-The following examples are considered warnings:
-
-
-```js
-html``
-html``
-```
-
-The following examples are not considered warnings:
-
-
-```js
-html``
-html``
-```
-
-#### 😈 no-boolean-in-attribute-binding
-
-You should not be binding to a boolean type using an attribute binding because it could result in binding the string "true" or "false". Instead you should be using a **boolean** attribute binding.
-
-This error is particular tricky, because the string "false" is truthy when evaluated in a conditional.
-
-The following example is considered a warning:
-
-
-```js
-html``
-```
-
-The following example is not considered a warning:
-
-
-```js
-html``
-```
-
-#### ☢️ no-complex-attribute-binding
-
-Binding an object using an attribute binding would result in binding the string "[object Object]" to the attribute. In this cases it's probably better to use a property binding instead.
-
-The following example is considered a warning:
-
-
-```js
-html``
-```
-
-The following example is not considered a warning:
-
-
-```js
-html``
-```
-
-#### ⭕️ no-nullable-attribute-binding
-
-Binding `undefined` or `null` in an attribute binding will result in binding the string "undefined" or "null". Here you should probably wrap your expression in the "ifDefined" directive.
-
-The following examples are considered warnings:
-
-
-```js
-html``
-html``
-```
-
-The following examples are not considered warnings:
-
-
-```js
-html``
-html``
-```
-
-#### 💔 no-incompatible-type-binding
-
-Assignments in your HTML are typed checked just like it would be in Typescript.
-
-The following examples are considered warnings:
-
-
-```js
-html``
-html``
-html``
-html``
-```
-
-The following examples are not considered warnings:
-
-
-```js
-html``
-html``
-html``
-html``
-```
-
-#### 💥 no-invalid-directive-binding
-
-Directives are checked to make sure that the following rules are met:
-
-- `ifDefined` is only used in an attribute binding.
-- `class` is only used in an attribute binding on the 'class' attribute.
-- `style` is only used in an attribute binding on the 'style' attribute.
-- `unsafeHTML`, `cache`, `repeat`, `asyncReplace` and `asyncAppend` are only used within a text binding.
-
-The directives already make these checks on runtime, so this will help you catch errors before runtime.
-
-The following examples are considered warnings:
-
-
-```js
-html``
-html``
-html``
-```
-
-The following examples are not considered warnings:
-
-
-```js
-html``
-html``
-html``
-html``
-```
-
-#### 🕷 no-unintended-mixed-binding
-
-Sometimes unintended characters sneak into bindings. This often indicates a typo such as `` where the expression is directly followed by a "}" which will be included in the value being bound, resulting in "foo}". Another example is self-closing tags without a space between the binding and "/" like `` which will result in binding the string "myvalue/".
-
-This rule disallows mixed value bindings where a character `'`, `"`, `}` or `/` is unintentionally included in the binding.
-
-The following examples are considered warnings:
-
-
-```js
-html``
-html``
-html``
-html``
-```
-
-The following examples are not considered warnings:
-
-
-```js
-html``
-html``
-html``
-html``
-```
-
-### Validating LitElement
-
-#### 💞 no-incompatible-property-type
-
-When using the @property decorator in Typescript, the property option `type` is checked against the declared property Typescript type.
-
-The following examples are considered warnings:
-
-
-```js
-class MyElement extends LitElement {
- @property({type: Number}) text: string;
- @property({type: Boolean}) count: number;
- @property({type: String}) disabled: boolean;
- @property({type: Object}) list: ListItem[];
-}
-```
-
-The following examples are not considered warnings:
-
-
-```js
-class MyElement extends LitElement {
- @property({type: String}) text: string;
- @property({type: Number}) count: number;
- @property({type: Boolean}) disabled: boolean;
- @property({type: Array}) list: ListItem[];
-}
-```
-
-#### 👎 no-unknown-property-converter
-
-The default converter in LitElement only accepts `String`, `Boolean`, `Number`, `Array` and `Object`, so all other values for `type` are considered warnings. This check doesn't run if a custom converter is used.
-
-The following example is considered a warning:
-
-
-```js
-class MyElement extends LitElement {
- static get properties () {
- return {
- callback: {
- type: Function
- },
- text: {
- type: MyElement
- }
- }
- }
-}
-```
-
-The following example is not considered a warning:
-
-
-```js
-class MyElement extends LitElement {
- static get properties () {
- return {
- callback: {
- type: Function,
- converter: myCustomConverter
- },
- text: {
- type: String
- }
- }
- }
-}
-```
-
-#### ⁉️ no-invalid-attribute-name
-
-When using the property option `attribute`, the value is checked to make sure it's a valid attribute name.
-
-The following example is considered a warning:
-
-
-```js
-class MyElement extends LitElement {
- static get properties () {
- return {
- text: {
- attribute: "invald=name"
- }
- }
- }
-}
-```
-
-#### ⁉️ no-invalid-tag-name
-
-When defining a custom element, the tag name is checked to make sure it's a valid custom element name.
-
-The following example is considered a warning:
-
-
-```js
-@customElement("wrongElementName")
-class MyElement extends LitElement {
-}
-
-customElements.define("alsoWrongName", MyElement);
-```
-
-The following example is not considered a warning:
-
-
-```js
-@customElement("my-element")
-class MyElement extends LitElement {
-}
-
-customElements.define("correct-element-name", MyElement);
-```
-
-### Validating CSS
-
-`lit-analyzer` uses [vscode-css-languageservice](https://github.com/Microsoft/vscode-css-languageservice) to validate CSS.
-
-#### 💅 no-invalid-css
-
-CSS within the tagged template literal `css` will be validated.
-
-The following example is considered a warning:
-
-
-```js
-css`
- button
- background: red;
- }
-`
-```
-
-The following example is not considered a warning:
-
-
-```js
-css`
- button {
- background: red;
- }
-`
-```
+## ➤ Rules
+
+The default severity of each rule depend on the `strict` [configuration option](#-configuration). Strict mode is disabled as default.
+
+Each rule can have severity of `off`, `warning` or `error`. You can toggle rules as you like.
+
+**Validating custom elements**
+
+
+| Rule | Description | Severity normal | Severity strict |
+| :------ | ----------- | --------------- | --------------- |
+| [no-unknown-tag-name](#-no-unknown-tag-name) | The existence of tag names are checked. Be aware that not all custom elements from libraries will be found out of the box. | off | warning |
+| [no-missing-import](#-no-missing-import) | When using custom elements in HTML it is checked if the element has been imported and is available in the current context. | off | warning |
+| [no-unclosed-tag](#-no-unclosed-tag) | Unclosed tags, and invalid self closing tags like custom elements tags, are checked. | warning | error |
+
+**Validating binding names**
+
+
+| Rule | Description | Severity normal | Severity strict |
+| :------ | ----------- | --------------- | --------------- |
+| [no-unknown-attribute](#-no-unknown-attribute-no-unknown-property) [no-unknown-property](#-no-unknown-attribute-no-unknown-property) | You will get a warning whenever you use an unknown attribute or property within your `lit-html` template. | off | warning |
+| [no-unknown-event](#-no-unknown-event) | When using event bindings it's checked that the event names are fired. | off | off |
+| [no-unknown-slot](#-no-unknown-slot) | Using the "@slot" jsdoc tag on your custom element class, you can tell which slots are accepted for a particular element. | off | warning |
+
+**Validating binding types**
+
+
+| Rule | Description | Severity normal | Severity strict |
+| :------ | ----------- | --------------- | --------------- |
+| [no-invalid-boolean-binding](#-no-invalid-boolean-binding) | Disallow boolean attribute bindings on non-boolean types. | error | error |
+| [no-expressionless-property-binding](#-no-expressionless-property-binding) | Disallow property bindings without an expression. | error | error |
+| [no-noncallable-event-binding](#-no-noncallable-event-binding) | Disallow event listener bindings with a noncallable type. | error | error |
+| [no-boolean-in-attribute-binding](#-no-boolean-in-attribute-binding) | Disallow attribute bindings with a boolean type. | error | error |
+| [no-complex-attribute-binding](#-no-complex-attribute-binding) | Disallow attribute bindings with a complex type. | error | error |
+| [no-nullable-attribute-binding](#-no-nullable-attribute-binding) | Disallow attribute bindings with nullable types such as "null" or "undefined". | error | error |
+| [no-incompatible-type-binding](#-no-incompatible-type-binding) | Disallow incompatible type in bindings. | error | error |
+| [no-invalid-directive-binding](#-no-invalid-directive-binding) | Disallow using built-in directives in unsupported bindings. | error | error |
+| [no-unintended-mixed-binding](#-no-unintended-mixed-binding) | Disallow mixed value bindings where a character `'`, `"`, `}` or `/` is unintentionally included in the binding. | warn | warn |
+
+**Validating LitElement**
+
+
+| Rule | Description | Severity normal | Severity strict |
+| :------ | ----------- | --------------- | --------------- |
+| [no-incompatible-property-type](#-no-incompatible-property-type) | When using the @property decorator in Typescript, the property option `type` is checked against the declared property Typescript type | error | error |
+| [no-invalid-attribute-name](#-no-invalid-attribute-name) | When using the property option `attribute`, the value is checked to make sure it's a valid attribute name. | error | error |
+| [no-invalid-tag-name](#-no-invalid-tag-name) | When defining a custom element the tag name is checked to make sure it's valid. | error | error |
+
+**Validating CSS**
+
+
+| Rule | Description | Severity normal | Severity strict |
+| :------ | ----------- | --------------- | --------------- |
+| [💅 no-invalid-css](#-no-invalid-css) | CSS within the tagged template literal `css` will be validated. | warning | error |
+
+### Validating custom elements
+
+All web components in your code are analyzed using [web-component-analyzer](https://github.com/runem/web-component-analyzer) which supports native custom elements and web components built with LitElement.
+
+#### 🤷 no-unknown-tag-name
+
+Web components defined in libraries need to either extend the global `HTMLElementTagNameMap` (typescript definition file) or include the "@customElement tag-name" jsdoc on the custom element class.
+
+Below you will see an example of what to add to your library typescript definition files if you want type checking support for a given html tag name.
+
+
+```typescript
+declare global {
+ interface HTMLElementTagNameMap {
+ "my-element": MyElement;
+ }
+}
+```
+
+#### 📣 no-missing-import
+
+When using custom elements in HTML it is checked if the element has been imported and is available in the current context. It's considered imported if any imported module (or their imports) defines the custom element.
+
+The following example is considered a warning:
+
+
+```js
+// No import of "my-element"
+html``
+```
+
+The following example is not considered a warning:
+
+
+```js
+import "my-element.js";
+html``
+```
+
+#### ☯ no-unclosed-tag
+
+Unclosed tags, and invalid self closing tags like custom elements tags, are checked.
+
+The following examples are considered warnings:
+
+
+```js
+html`
`
+html``
+html``
+```
+
+The following examples are not considered warnings:
+
+
+```js
+html``
+html``
+html``
+html``
+```
+
+### Validating binding names
+
+Attributes, properties and events are picked up on custom elements using [web-component-analyzer](https://github.com/runem/web-component-analyzer) which supports native custom elements and web components built with LitElement.
+
+#### ✅ no-unknown-attribute, no-unknown-property
+
+You will get a warning whenever you use an unknown attribute or property. This check is made on both custom elements and built in elements.
+
+**The following example is considered a warning:**
+
+
+```js
+html``
+```
+
+**The following example is not considered a warning:**
+
+
+```js
+html``
+```
+
+#### ⚡️ no-unknown-event
+
+You can opt in to check for unknown event names. Using the `@fires` jsdoc or the statement `this.dispatch(new CustomEvent("my-event))` will make the event name available. All event names are accepted globally because events bubble.
+
+The following example is considered a warning:
+
+
+```js
+html``
+```
+
+The following example is not considered a warning:
+
+
+```js
+html``
+```
+
+#### 📬 no-unknown-slot
+
+Using the "@slot" jsdoc tag on your custom element class, you can tell which slots are accepted for a particular element. Then you will get warnings for invalid slot names and if you forget to add the slot attribute on elements without an unnamed slot.
+
+
+```js
+/**
+ * @slot - This is a comment for the unnamed slot
+ * @slot right - Right content
+ * @slot left
+ */
+class MyElement extends HTMLElement {
+}
+customElements.define("my-element", MyElement);
+```
+
+The following example is considered a warning:
+
+
+```js
+html`
+
+
+
+`
+```
+
+The following example is not considered a warning:
+
+
+```js
+html`
+
+
+
+
+
+`
+```
+
+### Validating binding types
+
+Be aware that many checks involving analyzing bindings will work better in Typescript files because we have more information about the values being bound.
+
+#### ❓ no-invalid-boolean-binding
+
+It never makes sense to use the boolean attribute binding on a non-boolean type.
+
+The following example is considered a warning:
+
+
+```js
+html``
+```
+
+The following example is not considered a warning:
+
+
+```js
+html``
+```
+
+#### ⚫️ no-expressionless-property-binding
+
+Because of how `lit-html` [parses bindings internally](https://github.com/Polymer/lit-html/issues/843) you cannot use the property binding without an expression.
+
+The following example is considered a warning:
+
+
+```js
+html``
+```
+
+The following example is not considered a warning:
+
+
+```js
+html``
+```
+
+#### 🌀 no-noncallable-event-binding
+
+It's a common mistake to incorrectly call the function when setting up an event handler binding instead of passing a reference to the function. This makes the function call whenever the code evaluates.
+
+The following examples are considered warnings:
+
+
+```js
+html``
+html``
+```
+
+The following examples are not considered warnings:
+
+
+```js
+html``
+html``
+```
+
+#### 😈 no-boolean-in-attribute-binding
+
+You should not be binding to a boolean type using an attribute binding because it could result in binding the string "true" or "false". Instead you should be using a **boolean** attribute binding.
+
+This error is particular tricky, because the string "false" is truthy when evaluated in a conditional.
+
+The following example is considered a warning:
+
+
+```js
+html``
+```
+
+The following example is not considered a warning:
+
+
+```js
+html``
+```
+
+#### ☢️ no-complex-attribute-binding
+
+Binding an object using an attribute binding would result in binding the string "[object Object]" to the attribute. In this cases it's probably better to use a property binding instead.
+
+The following example is considered a warning:
+
+
+```js
+html``
+```
+
+The following example is not considered a warning:
+
+
+```js
+html``
+```
+
+#### ⭕️ no-nullable-attribute-binding
+
+Binding `undefined` or `null` in an attribute binding will result in binding the string "undefined" or "null". Here you should probably wrap your expression in the "ifDefined" directive.
+
+The following examples are considered warnings:
+
+
+```js
+html``
+html``
+```
+
+The following examples are not considered warnings:
+
+
+```js
+html``
+html``
+```
+
+#### 💔 no-incompatible-type-binding
+
+Assignments in your HTML are typed checked just like it would be in Typescript.
+
+The following examples are considered warnings:
+
+
+```js
+html``
+html``
+html``
+html``
+```
+
+The following examples are not considered warnings:
+
+
+```js
+html``
+html``
+html``
+html``
+```
+
+#### 💥 no-invalid-directive-binding
+
+Directives are checked to make sure that the following rules are met:
+
+- `ifDefined` is only used in an attribute binding.
+- `class` is only used in an attribute binding on the 'class' attribute.
+- `style` is only used in an attribute binding on the 'style' attribute.
+- `unsafeHTML`, `cache`, `repeat`, `asyncReplace` and `asyncAppend` are only used within a text binding.
+
+The directives already make these checks on runtime, so this will help you catch errors before runtime.
+
+The following examples are considered warnings:
+
+
+```js
+html``
+html``
+html``
+```
+
+The following examples are not considered warnings:
+
+
+```js
+html``
+html``
+html``
+html``
+```
+
+#### 🕷 no-unintended-mixed-binding
+
+Sometimes unintended characters sneak into bindings. This often indicates a typo such as `` where the expression is directly followed by a "}" which will be included in the value being bound, resulting in "foo}". Another example is self-closing tags without a space between the binding and "/" like `` which will result in binding the string "myvalue/".
+
+This rule disallows mixed value bindings where a character `'`, `"`, `}` or `/` is unintentionally included in the binding.
+
+The following examples are considered warnings:
+
+
+```js
+html``
+html``
+html``
+html``
+```
+
+The following examples are not considered warnings:
+
+
+```js
+html``
+html``
+html``
+html``
+```
+
+### Validating LitElement
+
+#### 💞 no-incompatible-property-type
+
+This rule checks that LitElement-controlled properties are correctly configured in accordance with the default value converter.
+
+The following is a summary of what this rule does:
+
+1. The `type` given to the LitElement property configuration is checked against the actual Typescript type of the property.
+2. The default converter only accepts the types `String`, `Boolean`, `Number`, `Array` and `Object`, so all other values for `type` are considered warnings.
+3. The absence of a `type` is only considered a warning if the property is not assignable to the `string` type.
+
+This rule will not check for a given LitElement-controlled property if the property has custom converter configured.
+
+The following examples are considered warnings:
+
+
+```js
+class MyElement extends LitElement {
+ @property({type: Number}) text: string;
+ @property({type: Boolean}) count: number;
+ @property({type: String}) disabled: boolean;
+ @property({type: Object}) list: ListItem[];
+
+ static get properties () {
+ return {
+ callback: {
+ type: Function
+ },
+ text: {
+ type: MyElement
+ }
+ }
+ }
+}
+```
+
+The following examples are not considered warnings:
+
+
+```js
+class MyElement extends LitElement {
+ @property({type: String}) text: string;
+ @property({type: Number}) count: number;
+ @property({type: Boolean}) disabled: boolean;
+ @property({type: Array}) list: ListItem[];
+
+ static get properties () {
+ return {
+ callback: {
+ type: Function,
+ converter: myCustomConverter
+ },
+ text: {
+ type: String
+ }
+ }
+ }
+
+}
+```
+
+#### ⁉️ no-invalid-attribute-name
+
+When using the property option `attribute`, the value is checked to make sure it's a valid attribute name.
+
+The following example is considered a warning:
+
+
+```js
+class MyElement extends LitElement {
+ static get properties () {
+ return {
+ text: {
+ attribute: "invald=name"
+ }
+ }
+ }
+}
+```
+
+#### ⁉️ no-invalid-tag-name
+
+When defining a custom element, the tag name is checked to make sure it's a valid custom element name.
+
+The following example is considered a warning:
+
+
+```js
+@customElement("wrongElementName")
+class MyElement extends LitElement {
+}
+
+customElements.define("alsoWrongName", MyElement);
+```
+
+The following example is not considered a warning:
+
+
+```js
+@customElement("my-element")
+class MyElement extends LitElement {
+}
+
+customElements.define("correct-element-name", MyElement);
+```
+
+### Validating CSS
+
+`lit-analyzer` uses [vscode-css-languageservice](https://github.com/Microsoft/vscode-css-languageservice) to validate CSS.
+
+#### 💅 no-invalid-css
+
+CSS within the tagged template literal `css` will be validated.
+
+The following example is considered a warning:
+
+
+```js
+css`
+ button
+ background: red;
+ }
+`
+```
+
+The following example is not considered a warning:
+
+
+```js
+css`
+ button {
+ background: red;
+ }
+`
+```
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#configuration)
-## ➤ Configuration
-
-You can configure this plugin by going to `VS Code Settings` > `Extension` > `lit-plugin`.
-
-**Note:** You can also configure the plugin using a `tsconfig.json` file (see [ts-lit-plugin](https://github.com/runem/lit-analyzer/blob/master/packages/ts-lit-plugin)).
-
-### Available options
-
-
-| Option | Description | Type | Default |
-| :----- | ----------- | ---- | ------- |
-| `strict` | Enabling strict mode will change which rules are applied as default (see list of [rules](https://github.com/runem/lit-analyzer/blob/master/docs/readme/rules.md)) | `boolean` | false |
-| `rules` | Enable/disable individual rules or set their severity. Example: `{"no-unknown-tag-name": "off"}` | `{"rule-name": "off" \| "warn" \| "error"}` | The default rules enabled depend on the `strict` option |
-| `disable` | Completely disable this plugin. | `boolean` | false |
-| `dontShowSuggestions` | This option sets strict as | `boolean` | false |
-| `htmlTemplateTags` | List of template tags to enable html support in. | `string[]` | ["html", "raw"] | |
-| `cssTemplateTags` | This option sets strict as | `string[]` | ["css"] |
-| `globalTags` | List of html tag names that you expect to be present at all times. | `string[]` | |
-| `globalAttributes` | List of html attributes names that you expect to be present at all times. | `string[]` | |
-| `globalEvents` | List of event names that you expect to be present at all times | `string[]` | |
-| `customHtmlData` | This plugin supports the [custom vscode html data format](https://code.visualstudio.com/updates/v1_31#_html-and-css-custom-data-support) through this setting. | [Vscode Custom HTML Data Format](https://github.com/Microsoft/vscode-html-languageservice/blob/master/docs/customData.md). Supports arrays, objects and relative file paths | |
+## ➤ Configuration
+
+You can configure this plugin by going to `VS Code Settings` > `Extension` > `lit-plugin`.
+
+**Note:** You can also configure the plugin using a `tsconfig.json` file (see [ts-lit-plugin](https://github.com/runem/lit-analyzer/blob/master/packages/ts-lit-plugin)).
+
+### Available options
+
+
+| Option | Description | Type | Default |
+| :----- | ----------- | ---- | ------- |
+| `strict` | Enabling strict mode will change which rules are applied as default (see list of [rules](https://github.com/runem/lit-analyzer/blob/master/docs/readme/rules.md)) | `boolean` | false |
+| `rules` | Enable/disable individual rules or set their severity. Example: `{"no-unknown-tag-name": "off"}` | `{"rule-name": "off" \| "warn" \| "error"}` | The default rules enabled depend on the `strict` option |
+| `disable` | Completely disable this plugin. | `boolean` | false |
+| `dontShowSuggestions` | This option sets strict as | `boolean` | false |
+| `htmlTemplateTags` | List of template tags to enable html support in. | `string[]` | ["html", "raw"] | |
+| `cssTemplateTags` | This option sets strict as | `string[]` | ["css"] |
+| `globalTags` | List of html tag names that you expect to be present at all times. | `string[]` | |
+| `globalAttributes` | List of html attributes names that you expect to be present at all times. | `string[]` | |
+| `globalEvents` | List of event names that you expect to be present at all times | `string[]` | |
+| `customHtmlData` | This plugin supports the [custom vscode html data format](https://code.visualstudio.com/updates/v1_31#_html-and-css-custom-data-support) through this setting. | [Vscode Custom HTML Data Format](https://github.com/Microsoft/vscode-html-languageservice/blob/master/docs/customData.md). Supports arrays, objects and relative file paths | |
+
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#other-features)
-## ➤ Other features
-
-[Rules](#-rules) as described before, gives you diagnostics directly in your code. Features described in this section will give you super powers by making your lit-html templates come to life.
-
-### 🚶Goto definition
-
-`Cmd+Click (Mac)` / `Ctrl+Click (Windows)` on a tag, attribute, property or event name and goto the definition.
-
-### ✏️ Code completions for css and html
-
-
-
-Press `Ctrl+Space` in an html or css context and to get code completions.
-
-### 📖 Quick info on hover for html tags and attributes
-
-Hover above a tag, attribute, property or event and see more information about the identifier such as type and jsdoc.
-
-### 🚪 Auto close tags
-
-When typing html inside a template tag `lit-plugin` auto-closes tags as you would expect.
-
-### 🔍 Automatically finds custom elements
-
-If you define a custom element somewhere in your code `lit-plugin` will automatically find it. Then it will provide auto-import functionality, type checking and code completion out of the box by analyzing the element. [web-component-analyzer](https://github.com/runem/web-component-analyzer) is the tool that takes care of analyzing components.
-
-### 🌎 Support for dependencies that extend the global HTMLElementTagNameMap
-
-
-
-If a dependency with Typescript definitions extends the global `HTMLElementTagNameMap` this plugin will pick up on the map between the tag name and the class. Below you will see an example of what to add to your library typescript definition files if you want type checking support for a given html tag.
-
-
-```typescript
-declare global {
- interface HTMLElementTagNameMap {
- "my-element": MyElement;
- }
-}
-```
-
-**Two limitations using this approach as of now**
-
-- By using this approach the plugin wont see detailed information about a given element as (e.g @property decorators and initializers) because it can only read public fields and their corresponding types. Therefore all properties on custom elements imported from libraries are optional and wont respect meta information in @property decorators.
-- `lit-plugin` will only be able two find your elements if you somewhere in the code imports the file. Before your import the file it will complain that the element is unknown not that it can be imported. This due to the constraint that Typescript only adds library files to the array of program files once the file has been imported.
-
-This plugin already supports [custom vscode html data format](https://code.visualstudio.com/updates/v1_31#_html-and-css-custom-data-support) (see the configuration section) and I will of course work on supporting more ways of shipping metadata alongside custom elements.
+## ➤ Other features
+
+[Rules](#-rules) as described before, gives you diagnostics directly in your code. Features described in this section will give you super powers by making your lit-html templates come to life.
+
+### 🚶Goto definition
+
+`Cmd+Click (Mac)` / `Ctrl+Click (Windows)` on a tag, attribute, property or event name and goto the definition.
+
+### ✏️ Code completions for css and html
+
+
+
+Press `Ctrl+Space` in an html or css context and to get code completions.
+
+### 📖 Quick info on hover for html tags and attributes
+
+Hover above a tag, attribute, property or event and see more information about the identifier such as type and jsdoc.
+
+### 🚪 Auto close tags
+
+When typing html inside a template tag `lit-plugin` auto-closes tags as you would expect.
+
+### 🔍 Automatically finds custom elements
+
+If you define a custom element somewhere in your code `lit-plugin` will automatically find it. Then it will provide auto-import functionality, type checking and code completion out of the box by analyzing the element. [web-component-analyzer](https://github.com/runem/web-component-analyzer) is the tool that takes care of analyzing components.
+
+### 🌎 Support for dependencies that extend the global HTMLElementTagNameMap
+
+
+
+If a dependency with Typescript definitions extends the global `HTMLElementTagNameMap` this plugin will pick up on the map between the tag name and the class. Below you will see an example of what to add to your library typescript definition files if you want type checking support for a given html tag.
+
+
+```typescript
+declare global {
+ interface HTMLElementTagNameMap {
+ "my-element": MyElement;
+ }
+}
+```
+
+**Two limitations using this approach as of now**
+
+- By using this approach the plugin wont see detailed information about a given element as (e.g @property decorators and initializers) because it can only read public fields and their corresponding types. Therefore all properties on custom elements imported from libraries are optional and wont respect meta information in @property decorators.
+- `lit-plugin` will only be able two find your elements if you somewhere in the code imports the file. Before your import the file it will complain that the element is unknown not that it can be imported. This due to the constraint that Typescript only adds library files to the array of program files once the file has been imported.
+
+This plugin already supports [custom vscode html data format](https://code.visualstudio.com/updates/v1_31#_html-and-css-custom-data-support) (see the configuration section) and I will of course work on supporting more ways of shipping metadata alongside custom elements.
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#documenting-slots-events-attributes-and-properties)
-## ➤ Documenting slots, events, attributes and properties
-
-Code is analyzed using [web-component-analyzer](https://github.com/runem/web-component-analyzer) in order to find properties, attributes and events. Unfortunately, sometimes it's not possible to analyze these things by looking at the code, and you will have to document how your component looks using `jsdoc`like this:
-
-
-```js
-/**
- * This is my element
- * @attr size
- * @attr {red|blue} color - The color of my element
- * @prop {String} value
- * @prop {Boolean} myProp - This is my property
- * @fires change
- * @fires my-event - This is my own event
- * @slot - This is a comment for the unnamed slot
- * @slot right - Right content
- * @slot left
- */
-class MyElement extends HTMLElement {
-}
-
-customElements.define("my-element", MyElement);
-```
+## ➤ Documenting slots, events, attributes and properties
+
+Code is analyzed using [web-component-analyzer](https://github.com/runem/web-component-analyzer) in order to find properties, attributes and events. Unfortunately, sometimes it's not possible to analyze these things by looking at the code, and you will have to document how your component looks using `jsdoc`like this:
+
+
+```js
+/**
+ * This is my element
+ * @attr size
+ * @attr {red|blue} color - The color of my element
+ * @prop {String} value
+ * @prop {Boolean} myProp - This is my property
+ * @fires change
+ * @fires my-event - This is my own event
+ * @slot - This is a comment for the unnamed slot
+ * @slot right - Right content
+ * @slot left
+ */
+class MyElement extends HTMLElement {
+}
+
+customElements.define("my-element", MyElement);
+```
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#feature-comparison)
-## ➤ Feature comparison
-
-This plugin is similar to [vscode-lit-html](https://github.com/mjbvz/vscode-lit-html) on many points. The power of `vscode-lit-html` is that it covers all the basic functionality of HTML in tagged templates, so it's a plugin that can be easily used with other libraries than `lit-html`. However `vscode-lit-plugin` (this one) aims to be a specialized plugin for working with `lit-element / lit-html`, so for example it supports `css` and discovers web components out of the box.
-
-Below is a comparison table of the two plugins:
-
-
-| Feature | [vscode-lit-html](https://github.com/mjbvz/vscode-lit-html) | [vscode-lit-plugin](https://github.com/runem/vscode-lit-plugin) |
-|-------------------------|------------|------------|
-| CSS support | ❌ | ✅ |
-| Goto definition | ❌ | ✅ |
-| Check missing imports | ❌ | ✅ |
-| Auto discover web components | ❌ | ✅ |
-| Template type checking | ❌ | ✅ |
-| Report unknown tag names | ❌ | ✅ |
-| Report unknown attrs | ❌ | ✅ |
-| Report unknown props | ❌ | ✅ |
-| Report unknown events | ❌ | ✅ |
-| Report unknown slots | ❌ | ✅ |
-| Support for vscode custom data format | ❌| ✅ |
-| Refactor tag names | ❌ | ✅ |
-| Refactor attr names | ❌ | ❌ |
-| Auto close tags | ✅ | ✅ |
-| Syntax Highlighting | ✅ | ✅ |
-| Completions | ✅ | ✅ |
-| Quick info on hover | ✅ | ✅ |
-| Code folding | ✅ | ⚠️ (disabled until problem with calling 'program.getSourceFile' is fixed) |
-| Formatting | ✅ | ⚠️ (disabled until problem with nested templates is fixed) |
+## ➤ Feature comparison
+
+This plugin is similar to [vscode-lit-html](https://github.com/mjbvz/vscode-lit-html) on many points. The power of `vscode-lit-html` is that it covers all the basic functionality of HTML in tagged templates, so it's a plugin that can be easily used with other libraries than `lit-html`. However `vscode-lit-plugin` (this one) aims to be a specialized plugin for working with `lit-element / lit-html`, so for example it supports `css` and discovers web components out of the box.
+
+Below is a comparison table of the two plugins:
+
+
+| Feature | [vscode-lit-html](https://github.com/mjbvz/vscode-lit-html) | [vscode-lit-plugin](https://github.com/runem/vscode-lit-plugin) |
+|-------------------------|------------|------------|
+| CSS support | ❌ | ✅ |
+| Goto definition | ❌ | ✅ |
+| Check missing imports | ❌ | ✅ |
+| Auto discover web components | ❌ | ✅ |
+| Template type checking | ❌ | ✅ |
+| Report unknown tag names | ❌ | ✅ |
+| Report unknown attrs | ❌ | ✅ |
+| Report unknown props | ❌ | ✅ |
+| Report unknown events | ❌ | ✅ |
+| Report unknown slots | ❌ | ✅ |
+| Support for vscode custom data format | ❌| ✅ |
+| Refactor tag names | ❌ | ✅ |
+| Refactor attr names | ❌ | ❌ |
+| Auto close tags | ✅ | ✅ |
+| Syntax Highlighting | ✅ | ✅ |
+| Completions | ✅ | ✅ |
+| Quick info on hover | ✅ | ✅ |
+| Code folding | ✅ | ⚠️ (disabled until problem with calling 'program.getSourceFile' is fixed) |
+| Formatting | ✅ | ⚠️ (disabled until problem with nested templates is fixed) |
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#how-does-this-plugin-work)
-## ➤ How does this plugin work?
-
-All features are provided by these three libraries:
-
-- **[ts-lit-plugin](https://github.com/runem/lit-analyzer)**: The typescript plugin that powers the logic through the typescript language service (code completion, type checking, eg.). Therefore issues regarding anything but syntax highlighting should be opened in `ts-lit-plugin` and not `vscode-lit-plugin`.
-- **[vscode-lit-html](https://github.com/mjbvz/vscode-lit-html)**: Provides highlighting for the html template tag.
-- **[vscode-styled-components](https://github.com/styled-components/vscode-styled-components)**: Provides highlighting for the css template tag.
-
-This library couples it all together and synchronizes relevant settings between vscode and `ts-lit-plugin`.
+## ➤ How does this plugin work?
+
+All features are provided by these three libraries:
+
+- **[ts-lit-plugin](https://github.com/runem/lit-analyzer)**: The typescript plugin that powers the logic through the typescript language service (code completion, type checking, eg.). Therefore issues regarding anything but syntax highlighting should be opened in `ts-lit-plugin` and not `vscode-lit-plugin`.
+- **[vscode-lit-html](https://github.com/mjbvz/vscode-lit-html)**: Provides highlighting for the html template tag.
+- **[vscode-styled-components](https://github.com/styled-components/vscode-styled-components)**: Provides highlighting for the css template tag.
+
+This library couples it all together and synchronizes relevant settings between vscode and `ts-lit-plugin`.
+
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#contributors)
-## ➤ Contributors
-
-| [](https://twitter.com/runemehlsen) | [](https://twitter.com/andreasmehlsen) | [](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
-| :--------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------: |
-| [Rune Mehlsen](https://twitter.com/runemehlsen) | [Andreas Mehlsen](https://twitter.com/andreasmehlsen) | [You?](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
+## ➤ Contributors
+
+
+| [](https://twitter.com/runemehlsen) | [](https://twitter.com/andreasmehlsen) | [](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
+|:--------------------------------------------------:|:--------------------------------------------------:|:--------------------------------------------------:|
+| [Rune Mehlsen](https://twitter.com/runemehlsen) | [Andreas Mehlsen](https://twitter.com/andreasmehlsen) | [You?](https://github.com/runem/lit-analyzer/blob/master/CONTRIBUTING.md) |
+
[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png)](#license)
-## ➤ License
-
-Licensed under [MIT](https://opensource.org/licenses/MIT).
+## ➤ License
+
+Licensed under [MIT](https://opensource.org/licenses/MIT).
diff --git a/packages/vscode-lit-plugin/package.json b/packages/vscode-lit-plugin/package.json
index d6ed5a08..be9cc322 100644
--- a/packages/vscode-lit-plugin/package.json
+++ b/packages/vscode-lit-plugin/package.json
@@ -342,17 +342,6 @@
"error"
]
},
- "lit-plugin.rules.no-unknown-property-converter": {
- "type": "string",
- "description": "Check that the converter of @property decorators exists.",
- "default": "default",
- "enum": [
- "default",
- "off",
- "warning",
- "error"
- ]
- },
"lit-plugin.rules.no-invalid-attribute-name": {
"type": "string",
"description": "Check the validity of the attribute names.",
diff --git a/packages/vscode-lit-plugin/schemas/tsconfig.schema.json b/packages/vscode-lit-plugin/schemas/tsconfig.schema.json
index ee84341e..cb2f7b27 100644
--- a/packages/vscode-lit-plugin/schemas/tsconfig.schema.json
+++ b/packages/vscode-lit-plugin/schemas/tsconfig.schema.json
@@ -173,11 +173,6 @@
"description": "Check the 'type' key of the @property decorator against the actual property type.",
"enum": ["off", "warning", "error"]
},
- "no-unknown-property-converter": {
- "type": "string",
- "description": "Check that the converter of @property decorators exists.",
- "enum": ["off", "warning", "error"]
- },
"no-invalid-attribute-name": {
"type": "string",
"description": "Check the validity of the attribute names.",