2022.3+Web Types
Edit pageLast modified: 13 June 2024Web 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. The format is open source and IDE-agnostic by itself. However, currently it is being actively used mostly by JetBrains IDEs.
Originally, it was created to facilitate the contribution of statically defined symbols for the Vue framework, which may explain the presence of some deprecated properties in the schema.
A simple Web Types file looks as follows, where this file defines a my-element
HTML element with a foo
attribute:
{
"$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 least, 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 Direct Support for reference). The kind of symbol should be related 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 contribution’s JSON property’s 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.:
{
"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 a foo
attribute, one could also write it in longer form:
{
"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
object. All the Web Types contributions are mapped one-to-one, and custom properties are accessible through properties
property.
Including Web Types
Web Types can currently be discovered by the IDE in the following ways:
- NPM
The IDE will automatically discover any Web Types shipped with the NPM library and specified in the
web-types
property ofpackage.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 specifyweb-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 insource
attribute value. WithenableByDefault
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
Symbol Kinds
Web Types files are used internally by IDEs and tools to define rules for frameworks. Following is the reference for symbol kinds used by framework support.
Direct Support
IDEs provide direct support for the following symbol kinds:
html/elements
html/attributes
css/properties
css/pseudo-classes
css/pseudo-elements
css/functions
css/classes
css/parts
(since 2023.2)
Prior to 2023.1, IDEs were required to have JavaScript plugin installed for the support to work.
Angular
Angular plugin Web Types are available here 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.:
{
"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:
A Vue /html/vue-components
contribution supports:
/html/props
Use
/html/props
to contribute Vue component props, e.g:{ "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, usevue-properties
to provide a list of scoped slot properties. Example:{ "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 }" } ] }] }
A Vue /html/vue-directives
contribution supports:
Web Components
For Lit support, install it in 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:
{
"$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"
}
]
}
}
]
}
}
}
Thanks for your feedback!