WebSymbols documentation (#1011)

- convert most bullet point lists to definition lists
- reformat all code snippets to have consistent spacing
- fix tags for equally named subsections
- add demo image and create a dark version of it
- add links to IntelliJ Platform code
- add update note
- split original Web Symbols content into 3 separate pages
- apply Karol's suggestions from code review

Co-authored-by: Karol Lewandowski
This commit is contained in:
Patrick Scheibe 2023-03-30 10:28:17 +02:00 committed by GitHub
parent 1fd0a3cc31
commit 5f535ffd63
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 1100 additions and 1 deletions

View File

@ -223,7 +223,12 @@
<toc-element topic="implementing_parser_and_psi.md"/>
<toc-element topic="syntax_highlighting_and_error_highlighting.md"/>
<toc-element topic="references_and_resolve.md"/>
<toc-element topic="symbols.md"/>
<toc-element topic="symbols.md">
<toc-element topic="websymbols.md">
<toc-element topic="websymbols_implementation.md"/>
<toc-element topic="websymbols_static_symbols.md"/>
</toc-element>
</toc-element>
<toc-element topic="declarations_and_references.md"/>
<toc-element topic="navigation.md"/>
<toc-element topic="code_completion.md"/>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 116 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 118 KiB

View File

@ -12,6 +12,13 @@ See [GitHub Changelog](https://github.com/JetBrains/intellij-sdk-docs/commits/ma
## 2023
### March
{#march-23}
Web Symbols
: Add [](websymbols.md) documentation, which is a framework that simplifies web technology development
by utilizing the [](symbols.md) API and supporting custom syntaxes.
### February
{#february-23}

View File

@ -0,0 +1,34 @@
<!-- Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
# Web Symbols
<link-summary>
Web Symbols framework simplifies web technology development by utilizing Symbol API and supporting custom syntaxes.
</link-summary>
> This API is available starting from 2022.3.1 and is currently in development and thus in an experimental state.
>
{style="warning"}
Web Symbols is a framework built on top of the platform's [Symbol API](symbols.md).
Its primary use is to reduce boilerplate when building support for web technologies,
however one can take advantage of it for any kind of technology.
Web Symbols API reduces work needed to provide reference resolution, find usages, documentation and rename refactoring.
It also provides an efficient JSON format (Web Types) for static symbol definitions.
Web Symbols core advantage, however, is the ability to evaluate symbol patterns.
Web frameworks tend to have custom syntaxes to enable various things,
e.g. through HTML attribute name (see [Model Queries example](websymbols_implementation.md#example) to see Vue directive syntax).
The pattern evaluator is able to recognize symbols in different sections of the element name and provide reference resolution,
documentation, usage occurrence, etc.
It also supports rename refactoring for symbols originating from source code.
Another advantage is the flexibility of Web Symbols query.
It is very easy to contribute new symbols from various sources, which works perfectly for multi-sourced
(e.g. source code, library code, Web Types) applications.
In the following sub-pages you learn about implementing Web Symbols for your plugin and how you can
contribute Web Symbols by statically defining them through JSON schemas:
- [](websymbols_implementation.md)
- [](websymbols_static_symbols.md)

View File

@ -0,0 +1,386 @@
<!-- Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
# Implementing Web Symbols
<link-summary>
Implementation details for the Web Symbols API.
</link-summary>
The core element of the framework is a
[`WebSymbol`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/WebSymbol.kt),
which represents an entity in the Web Symbols model.
It is described through `namespace`, `kind` and `name` properties. Its lifecycle is a single read action.
If you need it to survive between read actions, use `WebSymbol.createPointer()` to create a symbol pointer.
If the symbol is still valid, dereferencing the pointer will return a new instance of the symbol.
The property `namespace` describes which language or concept (not tied to a particular language) the symbol belongs to,
and `kind` describes which group of symbols within that particular language or concept it belongs to.
Examples:
- a CSS property: `namespace: CSS`, `kind: properties`
- a Java class: `namespace: Java`, `kind: classes`
- a plugin extension: `namespace: ij-plugin`, `kind: extensions`
A Web Symbol can originate from source code analysis, or it can be a symbol statically defined
through Web Types (JSON) or some other, custom format (see [](websymbols_static_symbols.md)).
In both cases such a symbol can have some `source` defined.
Each symbol is treated by the framework the same, regardless of their origin.
## General Properties
WebSymbol has a number of properties, which are used across IDE features:
{style="full"}
namespace
: Describes which language or concept the symbol belongs to.
kind
: Describes which group of symbols within the particular language or concept (namespace) the symbol belongs to.
The kind should be plural in form, e.g. "attributes".
name
: The name of the symbol. If the symbol does not have a pattern, the name will be used as-is for matching.
origin
: Specifies where this symbol comes from. Besides descriptive information like framework, library, version or default icon,
it also provides an interface to load symbol types and icons.
icon
: An optional icon associated with the symbol, which is going to be used across the IDE.
If none is specified, a default icon of the `origin` will be used and if thats not available, a default icon for symbol `namespace` and `kind`.
priority
: Symbols with higher priority will have precedence over those with lower priority, when matching is performed.
Symbols with higher priority will also show higher on the completion list.
proximity
: Provides additional way to sort symbols in code completion list within a particular priority.
The value must be a non-negative integer and the higher proximity, the higher the symbol would be on the list.
deprecated
: Documents, whether the symbol is deprecated. Deprecated symbols are appropriately highlighted in the code editor,
code completion and quick documentation.
experimental
: Documents, whether the symbol is considered an experimental feature and should be used with caution and might be
removed or its API altered in the future.
required
: Whether this symbol is required. What "is required" means, depends on the symbol.
For instance, for an HTML attribute it would mean that the attribute is required to be present for the particular HTML element.
defaultValue
: If the symbol represents some property, variable or anything that can hold a value, this property documents what is the default value.
attributeValue
: A special property to support symbols representing HTML attributes.
It can specify the kind (plain, expression, no-value), type (boolean, number, string, enum, complex, of-match),
whether an attribute value is required, a default value and the result type of value expression in the appropriate language.
If `COMPLEX` type is set, the value of `langType` will be used and if `OF_MATCH`, the type of the `symbol` will be used.
When merging information from several segments in the WebSymbolMatch, first non-null property values take precedence.
By default - when properties are `null` - attribute value is of plain type and is required.
type
: The type of the symbol. The type can be interpreted only within the context of symbol origin and in regard to its namespace and kind.
The type may be a language type, coming from e.g. Java or TypeScript, or it may be any arbitrary value.
Usually a type would be associated with symbols, which can hold a value, or represent some language symbol, like class, method, etc.
psiContext
: A PsiElement, which is a file or an element, which can be used to roughly locate the source of the symbol within a project to provide
a context for loading additional information, like types.
If the symbol is
[`PsiSourcedWebSymbol`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/PsiSourcedWebSymbol.kt)
(see [](#psisourcedwebsymbol)), then `psiContext` is equal to `source`.
properties
: Various symbol properties. There should be no assumption on the type of properties.
Properties can be used by plugins to provide additional information on the symbol.
See Web Types/Properties section for reference on the custom properties supported by IDEs.
presentation
: Returns
[`TargetPresentation`](%gh-ic%/platform/core-api/src/com/intellij/navigation/TargetPresentation.kt)
used by
[`SearchTarget`](%gh-ic%/platform/lang-impl/src/com/intellij/find/usages/api/SearchTarget.kt)
and
[`RenameTarget`](%gh-ic%/platform/lang-impl/src/com/intellij/refactoring/rename/api/RenameTarget.kt).
Default implementations of
[`WebSymbolRenameTarget`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/refactoring/WebSymbolRenameTarget.kt)
and
[`WebSymbolSearchTarget`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/search/WebSymbolSearchTarget.kt)
use the `presentation` property.
## Documentation Properties
Following properties handle generation of
[Quick Doc](https://www.jetbrains.com/help/idea/viewing-reference-information.html#inline-quick-documentation)
in the IDE:
{style="full"}
description
: An optional text, which describes the symbol purpose and usage. It is rendered in the documentation popup or view.
descriptionSections
: Additional sections, to be rendered in the symbols documentation. Each section should have a name, but the contents are optional.
docUrl
: An optional URL to a website with detailed symbol's documentation
documentation
: An interface holding information required to render documentation for the symbol. To customize symbols documentation,
one can override the method, or implement
[`WebSymbolDocumentationCustomizer`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/documentation/WebSymbolDocumentationCustomizer.kt).
[`WebSymbolDocumentation`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/documentation/WebSymbolDocumentation.kt)
interface provides builder methods for customizing the documentation.
`with*` methods return a copy of the documentation with customized fields.
## Query Related Properties
Following properties are related to name matching and code completion queries:
{style="full"}
pattern
: The pattern to match names against. As a result of pattern matching a
[`WebSymbolMatch`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/query/WebSymbolMatch.kt)
will be created.
A pattern may specify that a reference to other Web Symbols is expected in some part of it.
For such places, appropriate segments with referenced Web Symbols will be created and navigation,
validation and refactoring support is available out-of-the-box.
queryScope
: When pattern is being evaluated, matched symbols can provide additional scope for further resolution in the pattern.
By default, the `queryScope` returns the symbol itself
virtual
: Some symbols represent only a framework syntax, which does not translate to a particular symbol in the runtime.
For instance a Vue directive, which needs to be prefixed with `v-` will result in some special code generated,
but as such is not a real HTML attribute. This distinction allows us to ignore such symbols when looking for references.
abstract
: Some symbols may have a lot in common with each other and one can use abstract symbols as their super symbol,
currently only Web Types symbols can inherit from others.
extension
: Specifies whether the symbol is an extension. When matched along with a non-extension symbol it can provide or
override some properties of the symbol, or it can extend its scope contents.
## Methods
{#query-methods}
{style="full"}
createPointer()
: Returns the pointer to the symbol, which can survive between read actions. The dereferenced symbol should be valid,
i.e. any PSI based properties should return valid PsiElements.
getModificationCount()
: Symbols can be used in
[`CachedValue`](%gh-ic%/platform/core-api/src/com/intellij/psi/util/CachedValue.java)s
as dependencies. If a symbol instance can mutate over the time, it should properly implement this method.
isEquivalentTo()
: Returns true if two symbols are the same or equivalent for resolve purposes.
adjustNameForRefactoring()
: Web Symbols can have various naming conventions.
This method is used by the framework to determine a new name for a symbol based on its occurrence.
## PsiSourcedWebSymbol
A symbol should implement
[`PsiSourcedWebSymbol`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/PsiSourcedWebSymbol.kt)
if its declaration is a regular `PsiElement`, e.g. a variable or a declared type.
Once a symbol implements this interface it can be searched and refactored together with the PSI element declaration.
If your symbol is part of a string, or spans multiple PSI elements, or does not relate 1-1 with a PSI element,
instead of implementing this interface you should contribute dedicated declaration and reference providers.
### Properties
{#psisourcedwebsymbol-properties}
{style="full"}
source
: The `PsiElement`, which is the symbol declaration.
## CompositeWebSymbol
[`WebSymbolMatch`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/query/WebSymbolMatch.kt)
and some special symbols can have a name, which consists of other Web Symbols.
### Properties
{#compositewebsymbol-properties}
{style="full"}
nameSegments
: List of
[`WebSymbolNameSegment`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/WebSymbolNameSegment.kt).
Each segment describes a range in the symbol name.
Segments can be built of other Web Symbols and/or have related matching problems - missing required part,
unknown symbol name or be a duplicate of another segment. See Model Queries/Example section for an example.
## Web Symbols Scope
Web Symbols are contained within a loose model built from Web Symbols scopes, each time anew for a particular context.
Each Web Symbol is also a
[`WebSymbolsScope`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/WebSymbolsScope.kt)
and it can contain other Web Symbols.
For instance an HTML element symbol would contain some HTML attributes symbols, or a JavaScript class symbol would contain fields and methods symbols.
When configuring queries, Web Symbols scope are added to the list to create an initial scope for symbols resolve.
### Methods
{#websymbolsscope-methods}
{style="full"}
getSymbols()
: Returns symbols within the scope. If provided `name` is `null`, no pattern evaluation will happen and all symbols of a particular
kind and from particular namespace will be returned.
getCodeCompletions()
: Returns code completions for symbols within the scope.
isExclusiveFor()
: When scope is exclusive for a particular namespace and kind, resolve will not continue down the stack during pattern matching.
createPointer()
: Returns the pointer to the symbol scope, which can survive between read actions. The dereferenced symbol scope should be valid.
getModificationCount()
: Symbol scopes are used in CachedValues as dependencies for query executors.
If a symbol scope instance can mutate over the time, it should properly implement this method.
When implementing a scope, which contains many elements you should extend
[`WebSymbolsScopeWithCache`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/WebSymbolsScopeWithCache.kt),
which cache the list of symbols and uses efficient cache to speed up queries.
When extending the class, you only need to override the `initialize` method and provide parameters to the super constructor to specify how results should be cached.
## Model Queries
Web Symbols can contain patterns, which allow to compose them from other Web Symbols.
To find which symbols match available patterns we need to make a match query.
One can also run code completion query, which will produce a list of valid completions in the provided context.
To perform a query create a
[`WebSymbolsQueryExecutor`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/query/WebSymbolsQueryExecutor.kt)
using
[`WebSymbolsQueryExecutorFactory`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/query/WebSymbolsQueryExecutorFactory.kt).
The query executor will be configured by all the registered
[`WebSymbolsQueryConfigurator`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/query/WebSymbolsQueryConfigurator.kt)'s
based on the provided PSI context.
Configurators will provide initial Web Symbol scopes, rules for calculating Web Symbols context and rules for symbol names conversion.
The result of the match query is a list of WebSymbols.
Some of them might be
[`WebSymbolMatch`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/query/WebSymbolMatch.kt)es.
Such objects represent complex matches, when patterns are used.
Web Symbol Match has `nameSegments` property, which precisely describes how segments of the name relate to referenced Web Symbols and
whether there are any problems with resolution or the name itself.
When working with code completion, one can query for the list of code completions.
To properly calculate completions, a position in the current text under completion is required.
As a result, a list of
[`WebSymbolCodeCompletionItem`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/completion/WebSymbolCodeCompletionItem.kt)
will be provided.
### Example
Lets take a Vue directive as an example.
It is a special HTML attribute processed by Vue framework in runtime or during compile,
which results in additional code being attached to the DOM element.
Its structure looks as follows:
![JavaScript Example Image](websymbols_web_types.svg){ width="706"}
An example of how Vue directive might be declared in Web Types is here.
Once a match query is run on `v-on:click.once.alt`, we will get a
[`WebSymbolMatch`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/query/WebSymbolMatch.kt)
with following segments:
1. `v-`: Vue directive pattern symbol
2. `on`: Vue `on` directive
3. `:`
4. `click`: DOM `click` event symbol
5. `.`
6. `once`: Vue `on` directive `once` modifier
7. `alt`: Vue `on` directive `alt` modifier
### Patterns
Usually one would create such elements using Web Types, but sometimes there might be a need to do that programmatically.
To simplify resolution and make it less ambiguous,
a segment to match is selected by taking everything up to prefixes of following patterns.
Thus, if we want to have symbol references and regular expressions in the pattern,
they either have to terminate the pattern or must be followed by a static text.
A regular pattern static prefix is also considered a static text.
There are 6 types of patterns:
1. String match: try to match an exact text, the match is case-sensitive
2. Regular expression match: try match a regular expression, the match can be case-insensitive
3. Symbol reference placeholder: a symbol reference resolve will be attempted when this pattern is reached.
A resolve will be made by the symbols provider from an enclosing complex pattern.
If none of the symbols match the segment, the segment will have `UNKNOWN_SYMBOL` problem reported.
The matched symbol might be a WebSymbolMatch itself, which allows for nesting patterns.
4. Pattern sequence: a sequence of patterns. If some patterns are not matched, an empty segment with `MISSING_REQUIRED_PART` will be created.
5. Complex pattern: this pattern is called complex, because it makes several things:
- The provided patterns are treated as alternatives.
- It can have symbols resolver, which is used by nested symbol reference placeholder patterns.
- It allows to add an additional scope to resolve stack
- A complex pattern might be optional, in which case its absence is not reported as an error in enclosing sequence or complex pattern
- The match can be repeated, and any duplicate segments might have `DUPLICATED` problem set
- It can override proximity and priority, which by default is based on priority and proximity of matched symbols.
{style="alpha-lower"}
6. Completion auto popup: a special pattern, which works only in code completion queries.
It delimits the place, where when creating code completion items, pattern evaluation should be stopped and `...` added.
Selecting such items will result in adding the prefix part and then another code completion popup will open.
The pattern can be sticky, which means that the prefix will be shown in the nested code completion list.
### Query Context
When performing queries, some symbols should be excluded and others included in particular contexts.
For instance, if we have an Angular project, none of the Vue components should be available.
[`WebSymbolsContext`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/context/WebSymbolsContext.kt)
is created using rules provided by WebSymbolsQueryConfigurators with addition of custom
[`WebSymbolsContextProvider`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/context/WebSymbolsContextProvider.kt).
As a result, for each kind of context there is at most a single name assigned.
`WebSymbolsContext` can also be used outside the
[`WebSymbolsQueryExecutor`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/query/WebSymbolsQueryExecutor.kt)
as an efficient way to determine whether to enable or disable particular functionality in the IDE based on PSI or VFS context.
### Query stack
The stack is used as a scope for resolving symbols.
All scopes provided by
[`WebSymbolsQueryConfigurator`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/query/WebSymbolsQueryConfigurator.kt)s
together with the list of additional scopes passed as arguments to the query create an initial query stack.
Each time a symbol is matched, the list returned by `queryScope` property is added to the stack for any subsequent matches further up the pattern.
## Declarations, References, Search, Refactoring
To provide locations of declarations of Web Symbols, which are not
[`PsiSourcedWebSymbol`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/PsiSourcedWebSymbol.kt)s,
a dedicated
[`WebSymbolDeclarationProvider`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/declarations/WebSymbolDeclarationProvider.kt)
should be registered.
It should return a list of
[`WebSymbolDeclaration`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/declarations/WebSymbolDeclaration.kt)s
in a particular `PsiElement` at a particular offset.
Similarly, to provide references a
[`PsiSymbolReferenceProvider`](%gh-ic%/platform/core-api/src/com/intellij/model/psi/PsiSymbolReferenceProvider.java)
should be registered.
It should return
[`WebSymbolReference`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/references/WebSymbolReference.kt)
objects from `PsiSymbolReferenceProvider.getReferences()`.
To support search (aka find usages) Web Symbol needs to implement
[`SearchTarget`](%gh-ic%/platform/lang-impl/src/com/intellij/find/usages/api/SearchTarget.kt)
or a
[`WebSymbolSearchTarget`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/search/WebSymbolSearchTarget.kt)
needs to be provided for it through a
[`SymbolSearchTargetFactory`](%gh-ic%/platform/lang-impl/src/com/intellij/find/usages/symbol/SymbolSearchTargetFactory.java).
To support name refactoring, the
[`RenameTarget`](%gh-ic%/platform/lang-impl/src/com/intellij/refactoring/rename/api/RenameTarget.kt).
interface needs to be implemented,
or a
[`WebSymbolRenameTarget`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/refactoring/WebSymbolRenameTarget.kt)
needs to be provided for it through a
[`SymbolRenameTargetFactory`](%gh-ic%/platform/lang-impl/src/com/intellij/refactoring/rename/symbol/SymbolRenameTargetFactory.java).

View File

@ -0,0 +1,425 @@
<!-- Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. -->
# Statically Defined Web Symbols
<link-summary>
Contributing statically defined Web Symbols through JSON schemas.
</link-summary>
Web Types is a JSON metadata format, which provides an easy way to contribute statically defined Web Symbols.
The JSON Web Types detailed schema can be accessed by
[following this link](https://github.com/JetBrains/web-types/blob/master/schema/web-types.json).
The format is open source and IDE-agnostic by itself, however currently it is being actively used mostly by JetBrains IDEs.
It was originally created to facilitate the contribution of statically defined symbols for the
[Vue](https://vuejs.org/) framework, and therefore you might notice some deprecated properties in the schema.
A simple Web Types file looks as follows, where this file defines an `my-element` HTML element with a `foo` attribute.:
```JSON
{
"$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
"name": "example",
"version": "0.0.1",
"description-markup": "markdown",
"contributions": {
"html": {
"elements": [
{
"name": "my-element",
"description": "A custom HTML element",
"doc-url": "https://example.com/docs/my-element",
"attributes": [
{
"name": "foo",
"description": "A custom attribute of `my-element`"
}
]
}
]
}
}
}
```
## File Structure
The Web Types file should, at minimum, contain `name`, `version` and `contributions` properties.
It should also include `$schema` property which can be either
`https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json`
or
`http://json.schemastore.org/web-types`.
The schema contains detailed documentation for all the JSON entities.
Directly under `contributions` property are listed namespaces with their contributions.
Currently only `html`, `css` or `js` namespaces are allowed, however in the future this limitation
will be lifted to support Web Types for other technologies.
The `namespace` object contains symbol kind names listed as properties.
Some symbol kinds are predefined and directly supported by IDE (see Symbol Kinds/Supported for reference).
The kind of symbol should relate to its role.
For instance a Vue directive should be of the kind `vue-directives`.
Each framework should define a set of custom symbol kinds if needed.
Reference for the most important symbol kinds defined by frameworks supported by IDEs is below.
Each symbol kind name property of a namespace object is an array of symbol contributions.
A symbol contribution should have at least a name.
Contributions in addition to standard properties can define sub-contributions and custom properties.
A custom property is a JSON property, whose value is of a simple type (string, number or boolean),
or is an array of simple types.
If a contributions JSON propertys value is an object value or an array of objects, it is treated as a list of sub-contributions.
Such contributions will be assigned to the same namespace as the parent contributions.
To use a different namespace for sub-contributions, nest symbol kind JSON property name under a `js`, `css` or `html` property. E.g:
```JSON
{
"contributions": {
"html": {
"elements": [
{
"name": "my-element",
"description": "A custom HTML element",
"attributes": [
{
"name": "foo",
"description": "A custom HTML attribute of `my-element`"
}
],
"css": {
"properties": [
{
"name": "--bg-color",
"description": "Background color of my-element"
}
]
}
}
]
}
}
}
```
In the example below, Web Types contributes information that the `my-element` HTML element supports a custom CSS property `--bg-color`.
The `attributes` are implicitly under the `html` namespace.
To contribute `foo` attribute one could also write it in longer form:
```JSON
{
"name": "my-element",
"description": "A custom HTML element",
"html": {
"attributes": [
{
"name": "foo",
"description": "A custom attribute of `my-element`"
}
]
}
}
```
Each Web Types contribution is represented in the Web Symbols framework by a
[`PsiSourcedWebSymbol`](%gh-ic%/platform/webSymbols/src/com/intellij/webSymbols/PsiSourcedWebSymbol.kt)
object.
All the Web Types contributions are mapped 1-1 and custom properties are accessible through `properties` property.
## Including Web Types
Web Types can currently be discovered by the IDE in following ways:
{style="full"}
NPM
: The IDE will automatically discover any Web Types shipped with the NPM library and specified in the
`web-types` property of `package.json`.
The property accepts a string or an array of strings with relative paths to Web Types files shipped with the package.
Local Project
: In your JavaScript projects in `package.json` files you can specify `web-types` property similarly to the NPM package.
The property accepts a string or an array of strings with relative paths to Web Types files within the project.
IDE Plugin
: You can ship Web Types JSON with your IDE plugin.
To point an IDE to its location use `com.intellij.webSymbols.webTypes` extension point and pass the file location in `source` attribute value.
With `enableByDefault` attribute you can choose whether the Web Types file should be contributed to Web Symbols scope by default,
or only if an NPM package with the same name is present in the project.
## Special Properties
{style="full"}
inject-language
: Supported by `html/elements` and `html/attributes`, allows to inject the specified language into HTML element text or HTML attribute value.
doc-hide-pattern
: If a symbol uses a RegEx pattern, usually it will be displayed in a documentation popup section "pattern". Setting this property to `true` hides that section.
hide-from-completion
: By default all symbols show up in code completion. Setting this property to `true` prevents a symbol from showing up in the code completion.
## Symbol Kinds
Web Types files are used internally by IDEs and tooling to define rules for frameworks.
Following is the reference for symbol kinds used by framework support.
### Direct Support
In version 2022.3 IDEs with JavaScript plugin installed provide direct support for following symbol kinds:
- `html/elements`
- `html/attributes`
- `css/properties`
- `css/pseudo-classes`
- `css/pseudo-elements`
- `css/functions`
- `css/classes`
### Angular
Angular plugin Web Types are available
[here](https://github.com/JetBrains/intellij-plugins/tree/master/AngularJS/resources/web-types)
for reference.
Any Web Types file targeting only Angular support should have `framework` property set to `angular`.
Highlights: `js/ng-custom-events` contribute symbols with patterns for any custom events supported by Angular `EventManager`s, e.g.:
```JSON
{
"ng-custom-events": [
{
"name": "Custom modifiers for declarative events handling",
"priority": "normal",
"pattern": {
"template": [
{
"items": {
"path": "/js/events",
"includeVirtual": false
}
},
{
"items": "ng-event-plugins-modifiers",
"template": [
".",
"#...",
"#item:modifiers"
],
"priority": "high",
"repeat": true,
"unique": true,
"required": false
}
]
},
"ng-event-plugins-modifiers": [
{
"name": "prevent"
},
{
"name": "stop"
}
]
}
]
}
```
### Vue
Vue plugin Web Types are available here for reference.
Any Web Types file targeting only Vue support should have `framework` property set to `vue`.
Highlights:
{style="full"}
/html/vue-components
: Use `/html/vue-components` to contribute Vue components.
/html/vue-directives
: Use `/html/vue-directives` to contribute Vue directives.
Use `attribute-value` property to specify the type of value expression. E.g.:
```JSON
{
"attribute-value": {
"type": "boolean",
"required": true
}
}
```
/html/vue-file-top-elements
: Use `/html/vue-file-top-elements` to contribute any custom top-level elements available in Vue Single Component File
A Vue `/html/vue-components` contribution supports:
{style="full"}
/html/props
: Use `/html/props` to contribute Vue component props, e.g:
```JSON
{
"props": [{
"name": "appear",
"description": "Whether to apply transition on initial render.",
"type": "boolean",
"default": "false"
}]
}
```
/html/slots
: Use `/html/slots` to contribute Vue component slots.
For scoped slots use `vue-properties` to provide list of scoped slot properties.
Example:
```JSON
{
"slots": [{
"name": "img",
"description": "Expects the [v-img](/components/images) component.",
"doc-url": "https://vuetifyjs.com/en/api/v-app-bar/#slots",
"vue-properties": [
{
"name": "props",
"type": "{ height: string, src: string | srcObject }"
}
]
}]
}
```
/js/events
: Use `/js/events` to contribute Vue component events, e.g.:
```JSON
{
"js": {
"events": [
{
"name": "input",
"description": "The updated bound model"
}
]
}
}
```
html/vue-model
: Use `html/vue-model` to contribute settings for Vue model directive. E.g.:
```JSON
{
"vue-model": {
"prop": "show",
"event": "input"
}
}
```
A Vue `/html/vue-directives` contribution supports:
{style="full"}
/html/argument
: Use `/html/argument` as a Vue directive argument. E.g.:
```JSON
{
"argument": {
"name": "attribute or property name",
"description": "Optional attribute or property name",
"pattern": {
"items": [
{
"path": "/html/attributes",
"includeVirtual": false
}
]
}
}
}
```
/html/modifiers
: Use `/html/modifiers` as a Vue directive modifier. E.g.:
```JSON
{
"modifiers": [
{
"name": "body",
"description": "Make the mask append to the body element",
"type": "boolean"
},
{
"name": "fullscreen",
"type": "boolean"
}
]
}
```
### Web Components
For Lit support, install into your Node project as a devDependency `@web-types/lit`.
Web Types are available here for reference.
Web Components should use:
- `/html/attributes`: for attributes available in HTML
- `/js/properties`: for Web Component DOM class properties
- `/js/events`: for Web Component events
Example Web Component:
```JSON
{
"$schema": "https://raw.githubusercontent.com/JetBrains/web-types/master/schema/web-types.json",
"name": "Cool library",
"version": "1.0.0",
"js-types-syntax": "typescript",
"description-markup": "markdown",
"contributions": {
"html": {
"elements": [
{
"name": "cool-component",
"description": "Use the cool component to make your website more attractive.",
"doc-url": "https://example.com/docs/cool-component",
"attributes": [
{
"name": "color",
"description": "Choose color for coolness",
"default": "blue",
"required": false,
"doc-url": "https://example.com/docs/cool-component#attrs",
"value": {
"type": "string"
}
}
],
"slots": [
{
"name": "container"
}
],
"events": [
{
"name": "color:changed",
"description": "Emitted when color changes"
}
],
"js": {
"properties": [
{
"name": "color",
"type": "string",
"default": "blue"
}
]
},
"css": {
"properties": [
{
"name": "--cool-degree"
}
]
}
}
]
}
}
}
```