123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- 'use strict'
- const utils = require('../utils')
- const ALL_IRREGULARS =
- /[\f\v\u0085\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000\u2028\u2029]/u
- const IRREGULAR_WHITESPACE =
- /[\f\v\u0085\ufeff\u00a0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u202f\u205f\u3000]+/gmu
- const IRREGULAR_LINE_TERMINATORS = /[\u2028\u2029]/gmu
- module.exports = {
- meta: {
- type: 'problem',
- docs: {
- description: 'disallow irregular whitespace in `.vue` files',
- categories: undefined,
- url: 'https://eslint.vuejs.org/rules/no-irregular-whitespace.html',
- extensionRule: true,
- coreRuleUrl: 'https://eslint.org/docs/rules/no-irregular-whitespace'
- },
- schema: [
- {
- type: 'object',
- properties: {
- skipComments: {
- type: 'boolean',
- default: false
- },
- skipStrings: {
- type: 'boolean',
- default: true
- },
- skipTemplates: {
- type: 'boolean',
- default: false
- },
- skipRegExps: {
- type: 'boolean',
- default: false
- },
- skipHTMLAttributeValues: {
- type: 'boolean',
- default: false
- },
- skipHTMLTextContents: {
- type: 'boolean',
- default: false
- }
- },
- additionalProperties: false
- }
- ],
- messages: {
- disallow: 'Irregular whitespace not allowed.'
- }
- },
-
- create(context) {
-
-
- let errorIndexes = []
-
- const options = context.options[0] || {}
- const skipComments = !!options.skipComments
- const skipStrings = options.skipStrings !== false
- const skipRegExps = !!options.skipRegExps
- const skipTemplates = !!options.skipTemplates
- const skipHTMLAttributeValues = !!options.skipHTMLAttributeValues
- const skipHTMLTextContents = !!options.skipHTMLTextContents
- const sourceCode = context.getSourceCode()
-
- function removeWhitespaceError(node) {
- const [startIndex, endIndex] = node.range
- errorIndexes = errorIndexes.filter(
- (errorIndex) => errorIndex < startIndex || endIndex <= errorIndex
- )
- }
-
- function removeInvalidNodeErrorsInLiteral(node) {
- const shouldCheckStrings = skipStrings && typeof node.value === 'string'
- const shouldCheckRegExps = skipRegExps && Boolean(node.regex)
- if (shouldCheckStrings || shouldCheckRegExps) {
-
- if (ALL_IRREGULARS.test(sourceCode.getText(node))) {
- removeWhitespaceError(node)
- }
- }
- }
-
- function removeInvalidNodeErrorsInTemplateLiteral(node) {
- if (ALL_IRREGULARS.test(node.value.raw)) {
- removeWhitespaceError(node)
- }
- }
-
- function removeInvalidNodeErrorsInHTMLAttributeValue(node) {
- if (ALL_IRREGULARS.test(sourceCode.getText(node))) {
- removeWhitespaceError(node)
- }
- }
-
- function removeInvalidNodeErrorsInHTMLTextContent(node) {
- if (ALL_IRREGULARS.test(sourceCode.getText(node))) {
- removeWhitespaceError(node)
- }
- }
-
- function removeInvalidNodeErrorsInComment(node) {
- if (ALL_IRREGULARS.test(node.value)) {
- removeWhitespaceError(node)
- }
- }
-
- function checkForIrregularWhitespace() {
- const source = sourceCode.getText()
- let match
- while ((match = IRREGULAR_WHITESPACE.exec(source)) !== null) {
- errorIndexes.push(match.index)
- }
- while ((match = IRREGULAR_LINE_TERMINATORS.exec(source)) !== null) {
- errorIndexes.push(match.index)
- }
- }
- checkForIrregularWhitespace()
- if (!errorIndexes.length) {
- return {}
- }
- const bodyVisitor = utils.defineTemplateBodyVisitor(context, {
- ...(skipHTMLAttributeValues
- ? {
- 'VAttribute[directive=false] > VLiteral':
- removeInvalidNodeErrorsInHTMLAttributeValue
- }
- : {}),
- ...(skipHTMLTextContents
- ? { VText: removeInvalidNodeErrorsInHTMLTextContent }
- : {}),
-
- Literal: removeInvalidNodeErrorsInLiteral,
- ...(skipTemplates
- ? { TemplateElement: removeInvalidNodeErrorsInTemplateLiteral }
- : {})
- })
- return {
- ...bodyVisitor,
- Literal: removeInvalidNodeErrorsInLiteral,
- ...(skipTemplates
- ? { TemplateElement: removeInvalidNodeErrorsInTemplateLiteral }
- : {}),
- 'Program:exit'(node) {
- if (bodyVisitor['Program:exit']) {
- bodyVisitor['Program:exit'](node)
- }
- const templateBody = node.templateBody
- if (skipComments) {
-
- sourceCode.getAllComments().forEach(removeInvalidNodeErrorsInComment)
- if (templateBody) {
- templateBody.comments.forEach(removeInvalidNodeErrorsInComment)
- }
- }
-
- const [scriptStart, scriptEnd] = node.range
- const [templateStart, templateEnd] = templateBody
- ? templateBody.range
- : [0, 0]
- errorIndexes = errorIndexes.filter(
- (errorIndex) =>
- (scriptStart <= errorIndex && errorIndex < scriptEnd) ||
- (templateStart <= errorIndex && errorIndex < templateEnd)
- )
-
- errorIndexes.forEach((errorIndex) => {
- context.report({
- loc: sourceCode.getLocFromIndex(errorIndex),
- messageId: 'disallow'
- })
- })
- }
- }
- }
- }
|