Inspections

The ISML checks for syntax, attributes, templates, routes and resources, output encoding and template variables, with their quick fixes, suppression comments and the HTML warnings the plugin hides

The plugin checks templates as you type and offers a fix for most problems. Every ISML inspection is in Settings › Editor › Inspections › SFCC › ISML, where you can change its level or turn it off. Turning off the whole ISML group is the JetBrains counterpart of the VS Code intellij-sfcc.isml.linter setting

A template path that resolves to no file is an error. Create template asks for the cartridge, this one first and then the cartridge path, and writes the file from the ISML Template file template

Checks that read only the template and the tag catalog work without a license and while the IDE indexes. Checks that read other files, such as templates, controllers and resource bundles, need a license and wait until indexing ends, so they never report a problem from a half-built index

Syntax

All syntax checks are free:

InspectionLevelMessageFix
ISML tag outside its parent tagError<isnext> outside <isloop>, A second <iselse> in one <isif>Remove <isnext>, Remove <iselse>
Branch after iselseError<iselseif> after <iselse>Move before <iselse>, which moves the branch with its body
ISML closing tag that closes nothingWarning</isset>: <isset> has no closing tagRemove </isset>
Self-closed paired ISML tagWarning<isif> must not be self-closedRemove '/' when an end tag follows, otherwise Expand to a start and an end tag
Redundant iselse or iselseif closing tagWeak warningRedundant </iselse>Remove </iselse>
ISML tag name not in lower caseWeak warningISML tag names are lower caseConvert the tag name to lower case

Attributes

The attribute checks read the tag catalog, so they're free too. Only the custom tag parts need a license, see Custom Tags

InspectionMessageFixes
Unknown ISML attributeUnknown attribute 'tempate' of <isinclude>Change to 'template' for a close name, Remove 'tempate'
Missing required ISML attribute<isset> needs 'value', <isinclude> needs 'template' or 'url'Add 'value', or one Add fix for each choice
Conflicting ISML attributes'template' cannot be combined with 'url'Remove one of them
Duplicate ISML attributeA second copy of an attributeRemove the copy
Invalid ISML attribute value'scope' takes literal text, not an expression, 'items' takes an expression: 'pdict.products' is literal text, 'sesion' is not a value of 'scope': page, request, session, 'hour' takes a whole numberRemove ${}, Wrap in ${}, Change to 'session' for a close value
Deprecated ISML tag, attribute or value'iterator' is deprecated, use 'items', shown struck throughChange to 'items' when the catalog names a replacement
iscontent not first or repeatedMore than one <iscontent>, <iscontent> after <div>, which can write outputRemove the duplicate <iscontent>, Move to the top of the file
iscontent type does not match the dataA JSON or XML body under a text/html <iscontent>, as a weak warningChange to the type that fits
ISML attribute set to its defaultOff by default. A weak warning on scope="session" and other defaultsRemove the attribute

Best practice

InspectionMessageFixes
isset without scope<isset> without scope keeps total for the whole sessionAdd scope="page", Add scope="request", Add scope="session"
iscache settings<iscache> without type, Another <iscache> in this template has other settings, <isredirect> after <iscache>: the redirect is cached tooAdd type="relative", Remove this <iscache>
Template includes itselfThis template includes itself through product/tile → product/productTile. Needs a licenseOpen the template that closes the loop

Templates, routes and resources

These checks resolve names against other files, so they need a license:

InspectionLevelMessageFixes
Unresolved ISML templateErrorCannot resolve template 'product/loyaltyBanner'Create template, which asks for the cartridge: this one first, then the cartridge path
ErrorCannot resolve template 'product/Tile': the file is 'product/tile', and template paths are case-sensitiveChange to 'product/tile', in the path style you wrote
ErrorTemplate 'account/rewards' is not on the cartridge path of site RefArch; it exists in plugin_loyaltyNone. Add the cartridge to the site's cartridge path
Weak warningNo template matches 'product/components/*', for a path built from an expression, where * stands for the expressionNone
Unknown ISML custom tagWarningUnknown custom tag <isloyaltybage>: no <ismodule> declares itSee Custom Tags
Unresolved route in an ISML templateWarningCannot resolve route 'Loyalty-Shwo'. Only literal Controller-Action names are checkedChange to 'Loyalty-Show' for a close route
Unresolved Resource bundle or key in an ISML templateWarningCannot resolve bundle 'acount', Cannot resolve key 'heading.loyalty' in bundle 'account'Create key 'heading.loyalty' in bundle 'account', Use bundle 'common', which has the key

A created template starts from the ISML Template text in Settings › Editor › File and Code Templates and goes under templates/default/ of the cartridge you pick

Output encoding

B2C encodes ${} and <isprint> for HTML unless told otherwise. That's right in markup and wrong in a <script> block or CSS. These checks find where each value lands and report an encoding that doesn't fit:

InspectionMessageFixes
isprint with encoding offencoding="off" prints the value as it is into a string in a <script> block; expected "jsblock"Change to encoding="jsblock"
isprint encoding does not fit the output positionencoding="htmlcontent" does not fit a string in a <script> block; expected "jsblock", No encoding protects a value in <script> code outside a string literal; print it inside a string literalChange to encoding="jsblock"
HTML-encoded output in script or CSS${} uses HTML encoding, which does not protect a string in a <script> block; expected "jsblock"Wrap in <isprint encoding="jsblock">
Server-side ${} in a JavaScript template literalB2C evaluates ${name...} on the server, where 'name' is not defined; the template literal never sees it. Needs a licenseConvert the template literal to string concatenation

The encoding checks share two options. Expressions treated as safe lists expressions that are never reported, where * matches any text. Ignore string literals (on) skips ${'text'}. isprint with encoding off skips HTML and XML text, where encoding="off" usually prints trusted markup, unless you turn on Report HTML and XML text. HTML-encoded output in script or CSS reports values in CSS only with Report values in CSS, since no encoding protects them there

Template variables

These checks read scripts inside the template, so they wait until indexing ends:

InspectionMessageFixes
Unknown pdict memberNo render call of this template sets 'pdict.nextReward'. Needs a licenseChange to a close member name, Declare 'pdict.nextReward' with @pdict, Add 'nextReward' to the render model in Loyalty.js
Template variable used before its declaration'total' is used before the <isset> that declares itMove <isset> above the first use
Template variable used after isremove'total' is used after <isremove> removed itRemove <isremove>
Unused template variableTemplate variable 'total' is never read, also for loop variables and loop statusNone
Attribute expression type mismatch... is always true as a condition: test its size, or use empty(), <isloop> cannot iterate over ..., Expected a number, found ..., as weak warningsNone
Script syntax the compatibility mode does not supportCompatibility mode 21.2 does not support template literals (22.7 or later), No B2C compatibility mode supports optional chaining. Error, freeNone

Add to the render model adds the member to the object literal of the render call, keeping its layout and trailing comma, and leaves the caret after nextReward: in the controller. It's offered for up to three render calls that pass an object literal. Members are checked only in templates whose render calls are all known, see Scripting in ISML

Suppressing a problem

Alt+Enter on a problem, then the arrow next to a fix, offers Suppress for tag and Suppress for file. Both write a comment that B2C never sends to the browser:

<iscomment>noinspection IsmlIssetWithoutScope</iscomment>
<isset name="basket" value="${pdict.basket}" />

Before a tag, the comment covers that tag and everything inside it. As the first item of the file, it covers the whole file. It works for problems inside ${} and <isscript> too

HTML warnings the plugin hides

ISML templates are HTML with tags that run on the server, so plain HTML checks raise false alarms. The plugin filters them:

  • Closing tag matches nothing and Start tag has wrong closing tag are hidden when the tags pair as written across <isif> branches, such as a <div> opened in both branches and closed once after </isif>. A stray end tag is still reported
  • HTML parse errors next to ISML tags and ${} are hidden
  • HTML and XML inspections that would read an ISML value are suppressed, such as Unknown target on href="${URLUtils.url('Cart-Show')}"

On this page