import { RuleOptions } from './common'; // common attributes in HTML that are typically fine as literals const commonHtmlAttributes = [ 'abbr', 'about', 'accept', 'acceptCharset', 'accessKey', 'action', 'align', 'allow', 'autoCapitalize', 'autoComplete', 'autoCorrect', 'autoFocus', 'autoSave', 'bgcolor', 'capture', 'cellPadding', 'cellSpacing', 'challenge', 'charSet', 'charset', 'cite', 'class', 'classID', 'className', 'cols', 'contentEditable', 'contentMenu', 'controlsList', 'coords', 'crossOrigin', 'data', 'datatype', 'dateTime', 'decoding', 'dir', 'dirName', 'download', 'encType', 'enterKeyHint', 'fetchPriority', 'for', 'frameBorder', 'headers', 'height', 'href', 'hrefLang', 'htmlFor', 'http-equiv', 'httpEquiv', 'id', 'imageSizes', 'imageSrcSet', 'inputMode', 'integrity', 'is', 'key', 'kind', 'lang', 'list', 'loading', 'manifest', 'max', 'media', 'method', 'min', 'name', 'nonce', 'pattern', 'ping', 'poster', 'prefix', 'preload', 'property', 'radioGroup', 'ref', 'referrerPolicy', 'rel', 'resource', 'rev', 'role', 'rows', 'rules', 'sandbox', 'scope', 'scrolling', 'shape', 'sizes', 'slot', 'src', 'step', 'style', 'summary', 'target', 'translate', 'type', 'typeof', 'unselectable', 'useMap', 'valign', 'value', 'vocab', 'width', 'wmode', ]; // SVG elements to ignore since they often taken in strings as props const svgElements = [ 'svg', 'animate', 'animateMotion', 'animateTransform', 'circle', 'clipPath', 'defs', 'desc', 'ellipse', 'feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence', 'filter', 'foreignObject', 'g', 'image', 'line', 'linearGradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialGradient', 'rect', 'stop', 'switch', 'symbol', 'text', 'textPath', 'tspan', 'use', 'view', ]; export const defaultNoAttributeStringLiteralsOptions: RuleOptions = { // by default, we only consider string literals with more than 3 word characters only: { valuePatterns: ['\\w{3,}'] }, ignores: { or: [ { attributes: [ ...commonHtmlAttributes, // common sanity keys 'context', 'i18nKey', 'intent', 'language', 'layout', 'path', 'portal', 'textOverflow', // sanity UI attributes that take in literal values 'align', 'as', 'autoCols', 'autoFlow', 'autoRows', 'column', 'columnEnd', 'columnStart', 'direction', 'display', 'flex', 'forwardedAs', 'height', 'justify', 'mode', 'overflow', 'placement', 'row', 'rowEnd', 'rowStart', 'scheme', 'sizing', 'tone', 'weight', 'wrap', ], attributePatterns: [ '^form\\w*', // formAction formEncType formMethod etc '^item\\w*', // itemID itemProp itemScope etc '^src\\w*', // srcLang srcDoc srcSet etc '^data-', // data-* attributes 'testid', // any sort of testid ], componentPatterns: [...svgElements, 'meta'], valuePatterns: [ '^data-', // data- attributes '^(\\/[\\S-]*)*$', // URLs starting with a leading slash, ], values: [ '_blank', 'after', 'auto', 'before', 'bleed', 'block', 'blue', 'border', 'bottom', 'bottom-end', 'bottom-start', 'brand', 'button', 'caution', 'center', 'collapsed', 'column', 'column-reverse', 'content', 'critical', 'cyan', 'dark', 'default', 'dialog', 'editing', 'error', 'expanded', 'false', 'file', 'fill', 'first', 'flex', 'flex-end', 'flex-start', 'fr', 'from', 'full', 'ghost', 'gray', 'green', 'grid', 'hidden', 'horizontal', 'image', 'inactive', 'info', 'inline-block', 'inside', 'left', 'left-end', 'left-start', 'light', 'magenta', 'max', 'min', 'none', 'nowrap', 'numeric', 'online', 'orange', 'outline', 'popover', 'positive', 'primary', 'purple', 'red', 'reset', 'right', 'right-end', 'right-start', 'row', 'row-reverse', 'second', 'sidebar', 'single', 'space-around', 'space-between', 'space-evenly', 'stretch', 'submit', 'test', 'to', 'top', 'top-end', 'top-start', 'topbar', 'transparent', 'true', 'viewport', 'visible', 'warning', 'wrap', 'wrap-reverse', 'yellow', ], }, // ignore aria-* attributes expect aria-label and others { and: [ { attributePatterns: ['^aria-'], }, { not: { attributes: [ 'aria-label', 'aria-placeholder', 'aria-valuetext', 'aria-description', 'aria-roledescription', ], }, }, ], }, ], }, }; export const defaultNoAttributeTemplateLiteralsOptions: RuleOptions = { only: { // by default we only consider quasi strings that contain a whitespace // character next to a word character e.g. `hello ` or ` world!` valuePatterns: ['(\\s\\w|\\w\\s)'], }, ignores: { attributes: commonHtmlAttributes, componentPatterns: [...svgElements, 'meta'], }, };