Customizing HTML IntelliSense in Visual Studio
Purpose
When a project uses custom HTML attributes and JavaScript is used to process these specific attributes, you can extend Visual Studio's HTML IntelliSense to avoid forgetting these attributes or making typos during development.
Current Limitations
- Settings are applied to the Visual Studio installation globally, not per project.
- Settings are reset every time Visual Studio is updated.
Configuration Steps
Navigate to the Visual Studio HTML IntelliSense template directory and open the "SchemaCatalog.xml" file. Reference locations are as follows:
- 2019 Community:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\Extensions\Microsoft\Web Tools\Languages\Schemas\HTML\ - 2022 Community:
C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\Extensions\Microsoft\Web Tools\Languages\Schemas\HTML
- 2019 Community:
Add a
<schema />entry in "SchemaCatalog.xml" to reference your custom XSD (XML Schema Definition) file. The<schema />attributes are as follows:- File: The filename of the XSD to extend.
- IsSupplemental: Must be set to
truefor HTML IntelliSense to take effect. - CustomPrefix: The keyword that triggers
IntelliSense. This must match the prefix of your custom attributes to function correctly.
Example:
xml<?xml version="1.0" encoding="utf-8"?> <schemas> <schema File="html.xsd" FriendlyName="HTML" Uri="http://schemas.microsoft.com/intellisense/html" /> <schema File="jQuery_mobile.xsd" FriendlyName="jQuery Mobile" Uri="http://schemas.microsoft.com/intellisense/jquery-mobile" IsSupplemental="true" CustomPrefix="data-" /> <schema File="windows.xsd" FriendlyName="Windows App" Uri="http://schemas.microsoft.com/intellisense/windows" IsSupplemental="true" CustomPrefix="data-" /> <schema File="aria.xsd" FriendlyName="WIA-ARIA" Uri="http://schemas.microsoft.com/intellisense/aria" IsSupplemental="true" CustomPrefix="aria-" /> <schema File="angular.xsd" FriendlyName="AngularJS" Uri="http://schemas.microsoft.com/intellisense/angular" IsSupplemental="true" CustomPrefix="ng-" /> <schema File="svg.xsd" Uri="http://www.w3.org/2000/svg" IsXml="true" /> <schema File="xml.xsd" Uri="http://www.w3.org/XML/1998/namespace" /> <schema File="xlink.xsd" Uri="http://www.w3.org/1999/xlink" /> <!--Add the line below, replace 'Wing' with your own code--> <schema File="Wing.xsd" FriendlyName="Wing" IsSupplemental="true" CustomPrefix="data-" /> <!-- Visual Studio 2022 has more code following this, omitted here due to layout constraints --> </schemas>
TIP
- Updating Visual Studio causes custom HTML IntelliSense to stop working because the "SchemaCatalog.xml" file is reset.
- If you find AngularJS or Aria IntelliSense distracting, you can comment out their XML references; this will prevent them from appearing until the next Visual Studio update.
- Create the XSD file in the same folder. If you encounter permission issues while saving, create it elsewhere and copy it over.
- If Visual Studio is already open, you must restart it for the changes to take effect.
XSD File Explanation
Structure Overview
<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:vs="http://schemas.microsoft.com/Visual-Studio-Intellisense"
vs:ishtmlschema="true">
<xsd:annotation>
<xsd:documentation>
Microsoft Visual Studio schema for Wing
</xsd:documentation>
</xsd:annotation>
<!-- The above declares the XML format; adjust the description inside documentation as needed -->
<!-- Excerpt from aria.xsd, simplified for explanation. "aria-" is set by CustomPrefix -->
<!-- When "aria-" is typed in an input, "aria-invalid" and "aria-activedescendant" will be listed -->
<!-- If "aria-invalid" is selected, attribute values "false" and "true" will be provided as options -->
<xsd:element name="input">
<xsd:complexType>
<xsd:attribute name="aria-invalid">
<xsd:simpleType>
<xsd:restriction base="xsd:NMTOKEN">
<xsd:enumeration value="false" />
<xsd:enumeration value="true" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="aria-activedescendant" />
</xsd:complexType>
</xsd:element>
</xsd:schema>Node Explanation
Since the function of each node was determined through experimentation with existing files, the following is a general explanation. You can refer to the "XML Schema Tutorial" for XSD structure, though I am not certain which specific parts are effective for Visual Studio.
<xsd:element />: Sets the HTML element that triggers IntelliSense. XML attributes:- name: Sets the HTML TAG. Use "___all___" to trigger on any TAG.
<xsd:complexType />: Can contain multiple<xsd:attribute />or<xsd:attributeGroup />elements inside.<xsd:attribute />: Used to define custom HTML attributes. XML attributes:- name: The custom attribute name.
<xsd:attributeGroup />: Used to group multiple<xsd:complexType />definitions. XML attributes:- name: The group name.
- ref: References a group by its defined name.
<xsd:restriction />: Used to restrict HTML attribute values, paired with<xsd:enumeration />to list valid values.
Implementation Example
Below is the content of an XSD file used for an Unobtrusive JavaScript API I previously used with jQuery.
<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:vs="http://schemas.microsoft.com/Visual-Studio-Intellisense"
vs:ishtmlschema="true">
<xsd:annotation>
<xsd:documentation>
Microsoft Visual Studio schema for Wing
</xsd:documentation>
</xsd:annotation>
<xsd:attributeGroup name="formatAttributeGroup">
<xsd:attribute name="data-format">
<xsd:simpleType>
<xsd:restriction base="xsd:NMTOKEN">
<xsd:enumeration value="trim" />
<xsd:enumeration value="trim|lowerCase" />
<xsd:enumeration value="trim|upperCase" />
<xsd:enumeration value="lowerCase" />
<xsd:enumeration value="upperCase" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:attributeGroup>
<xsd:attributeGroup name="copyAttributeGroup">
<xsd:attribute name="data-copy-target" />
<xsd:attribute name="data-copy-always">
<xsd:simpleType>
<xsd:restriction base="xsd:NMTOKEN">
<xsd:enumeration value="true" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
</xsd:attributeGroup>
<xsd:attributeGroup name="checkAttributeGroup">
<xsd:attribute name="data-check-target" />
<xsd:attribute name="data-check-parant" />
</xsd:attributeGroup>
<xsd:attributeGroup name="resetAttributeGroup">
<xsd:attribute name="data-reset-target" />
</xsd:attributeGroup>
<xsd:attributeGroup name="resetValueAttributeGroup">
<xsd:attribute name="data-reset-value" />
</xsd:attributeGroup>
<xsd:attributeGroup name="buttonAttributeGroup">
<xsd:attribute name="data-alert-message" />
<xsd:attribute name="data-confirm-message" />
<xsd:attribute name="data-route-url" />
<xsd:attribute name="data-window-url" />
<xsd:attribute name="data-window-name" />
<xsd:attribute name="data-window-features" />
<xsd:attribute name="data-action-url" />
<xsd:attribute name="data-action-confirm" />
<xsd:attribute name="data-action-ignore-error">
<xsd:simpleType>
<xsd:restriction base="xsd:NMTOKEN">
<xsd:enumeration value="true" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="data-action-callback" />
<xsd:attribute name="data-query-url" />
<xsd:attribute name="data-query-condition" />
<xsd:attribute name="data-query-list" />
<xsd:attribute name="data-query-auto">
<xsd:simpleType>
<xsd:restriction base="xsd:NMTOKEN">
<xsd:enumeration value="true" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="data-query-confirm" />
<xsd:attribute name="data-query-ignore-error">
<xsd:simpleType>
<xsd:restriction base="xsd:NMTOKEN">
<xsd:enumeration value="true" />
</xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="data-query-callback" />
</xsd:attributeGroup>
<xsd:element name="input">
<xsd:complexType>
<xsd:attributeGroup ref="formatAttributeGroup" />
<xsd:attributeGroup ref="copyAttributeGroup" />
<xsd:attributeGroup ref="checkAttributeGroup" />
<xsd:attributeGroup ref="resetAttributeGroup" />
<xsd:attributeGroup ref="resetValueAttributeGroup" />
<xsd:attributeGroup ref="buttonAttributeGroup" />
</xsd:complexType>
</xsd:element>
<xsd:element name="textarea">
<xsd:complexType>
<xsd:attributeGroup ref="formatAttributeGroup" />
<xsd:attributeGroup ref="copyAttributeGroup" />
<xsd:attributeGroup ref="resetValueAttributeGroup" />
</xsd:complexType>
</xsd:element>
<xsd:element name="select">
<xsd:complexType>
<xsd:attributeGroup ref="resetValueAttributeGroup" />
</xsd:complexType>
</xsd:element>
<xsd:element name="button">
<xsd:complexType>
<xsd:attributeGroup ref="resetAttributeGroup" />
<xsd:attributeGroup ref="buttonAttributeGroup" />
</xsd:complexType>
</xsd:element>
</xsd:schema>Usage results:
Typing "data-" lists the relevant attributes.

Selecting "data-format" lists the selectable attribute values.

TIP
Unobtrusive JavaScript can be understood similarly to Bootstrap or "jquery.validate.unobtrusive.js". By defining a large number of custom attributes and binding events to these attributes—or using attribute values as variables for events—you can trigger JavaScript events simply by setting those attributes in HTML. This was a mainstream approach before the popularity of modern frontend frameworks.
Change Log
- 2022-11-11 Initial document creation.