/** * @author Yosuke Ota * See LICENSE file in root directory for full license. */ 'use strict' const utils = require('../utils') const regexp = require('../utils/regexp') const casing = require('../utils/casing') /** * @typedef { { names: { [tagName in string]: Set }, regexps: { name: RegExp, attrs: Set }[], cache: { [tagName in string]: Set } } } TargetAttrs */ // https://dev.w3.org/html5/html-author/charref const DEFAULT_ALLOWLIST = [ '(', ')', ',', '.', '&', '+', '-', '=', '*', '/', '#', '%', '!', '?', ':', '[', ']', '{', '}', '<', '>', '\u00B7', // "·" '\u2022', // "•" '\u2010', // "‐" '\u2013', // "–" '\u2014', // "—" '\u2212', // "−" '|' ] const DEFAULT_ATTRIBUTES = { '/.+/': [ 'title', 'aria-label', 'aria-placeholder', 'aria-roledescription', 'aria-valuetext' ], input: ['placeholder'], img: ['alt'] } const DEFAULT_DIRECTIVES = ['v-text'] /** * Parse attributes option * @param {any} options * @returns {TargetAttrs} */ function parseTargetAttrs(options) { /** @type {TargetAttrs} */ const result = { names: {}, regexps: [], cache: {} } for (const tagName of Object.keys(options)) { /** @type { Set } */ const attrs = new Set(options[tagName]) if (regexp.isRegExp(tagName)) { result.regexps.push({ name: regexp.toRegExp(tagName), attrs }) } else { result.names[tagName] = attrs } } return result } /** * Get a string from given expression container node * @param {VExpressionContainer} value * @returns { string | null } */ function getStringValue(value) { const expression = value.expression if (!expression) { return null } if (expression.type !== 'Literal') { return null } if (typeof expression.value === 'string') { return expression.value } return null } module.exports = { meta: { type: 'suggestion', docs: { description: 'disallow the use of bare strings in `