Skip to content

feat: add support for eslint v9 #463

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/shiny-colts-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@intlify/eslint-plugin-vue-i18n": minor
---

feat: add support for eslint v9
37 changes: 36 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,42 @@ module.exports = {
rules: {
'object-shorthand': 'error',
'no-debugger': 'error',
'vue/multi-word-component-names': 'off'
'vue/multi-word-component-names': 'off',

'prefer-template': 'error',
'no-restricted-properties': [
'error',
{
object: 'context',
property: 'getSourceCode',
message: 'Use lib/utils/compat.ts'
},
{
object: 'context',
property: 'getFilename',
message: 'Use lib/utils/compat.ts'
},
{
object: 'context',
property: 'getPhysicalFilename',
message: 'Use lib/utils/compat.ts'
},
{
object: 'context',
property: 'getCwd',
message: 'Use lib/utils/compat.ts'
},
{
object: 'context',
property: 'getScope',
message: 'Use lib/utils/compat.ts'
},
{
object: 'context',
property: 'parserServices',
message: 'Use lib/utils/compat.ts'
}
]
},
overrides: [
{
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
eslint: [5, 6, 7, 8]
node: [16]
eslint: [5, 6, 7, 8, ^9.0.0-0]
node: [20]
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion docs/.vitepress/components/resource-group.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default {
return {
$resourceGroup: {
async set(fileName, code) {
Vue.set(data.fileContents, '/path/' + fileName, code)
Vue.set(data.fileContents, `/path/${fileName}`, code)

const timeSeq = ++waitSeq
await Vue.nextTick()
Expand Down
14 changes: 9 additions & 5 deletions lib/rules/key-format-style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { RuleContext, RuleListener } from '../types'
import { getCasingChecker } from '../utils/casing'
import type { LocaleMessage } from '../utils/locale-messages'
import { createRule } from '../utils/rule'
import { getFilename, getSourceCode } from '../utils/compat'
const debug = debugBuilder('eslint-plugin-vue-i18n:key-format-style')

const allowedCaseOptions = [
Expand All @@ -21,7 +22,8 @@ const allowedCaseOptions = [
type CaseOption = (typeof allowedCaseOptions)[number]

function create(context: RuleContext): RuleListener {
const filename = context.getFilename()
const filename = getFilename(context)
const sourceCode = getSourceCode(context)
const expectCasing: CaseOption = context.options[0] ?? 'camelCase'
const checker = getCasingChecker(expectCasing)
const allowArray: boolean = context.options[1]?.allowArray
Expand Down Expand Up @@ -115,7 +117,6 @@ function create(context: RuleContext): RuleListener {
if (cachedLoc) {
return cachedLoc
}
const sourceCode = context.getSourceCode()
return (cachedLoc = {
start: sourceCode.getLocFromIndex(offset + start),
end: sourceCode.getLocFromIndex(offset + end)
Expand Down Expand Up @@ -264,17 +265,20 @@ function create(context: RuleContext): RuleListener {
return createVisitorForYaml(targetLocaleMessage)
}
)
} else if (context.parserServices.isJSON || context.parserServices.isYAML) {
} else if (
sourceCode.parserServices.isJSON ||
sourceCode.parserServices.isYAML
) {
const localeMessages = getLocaleMessages(context)
const targetLocaleMessage = localeMessages.findExistLocaleMessage(filename)
if (!targetLocaleMessage) {
debug(`ignore ${filename} in key-format-style`)
return {}
}

if (context.parserServices.isJSON) {
if (sourceCode.parserServices.isJSON) {
return createVisitorForJson(targetLocaleMessage)
} else if (context.parserServices.isYAML) {
} else if (sourceCode.parserServices.isYAML) {
return createVisitorForYaml(targetLocaleMessage)
}
return {}
Expand Down
4 changes: 3 additions & 1 deletion lib/rules/no-deprecated-i18n-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ import { defineTemplateBodyVisitor } from '../utils/index'
import type { RuleContext, RuleListener } from '../types'
import type { AST as VAST } from 'vue-eslint-parser'
import { createRule } from '../utils/rule'
import { getSourceCode } from '../utils/compat'

function create(context: RuleContext): RuleListener {
return defineTemplateBodyVisitor(context, {
VElement(node: VAST.VElement) {
if (node.name !== 'i18n') {
return
}
const tokenStore = context.parserServices.getTemplateBodyTokenStore()
const sourceCode = getSourceCode(context)
const tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore()
const tagNameToken = tokenStore.getFirstToken(node.startTag)
context.report({
node: tagNameToken,
Expand Down
24 changes: 14 additions & 10 deletions lib/rules/no-duplicate-keys-in-locale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
import { joinPath } from '../utils/key-path'
import { getCwd } from '../utils/get-cwd'
import { createRule } from '../utils/rule'
import { getFilename, getSourceCode } from '../utils/compat'
const debug = debugBuilder('eslint-plugin-vue-i18n:no-duplicate-keys-in-locale')

interface DictData {
Expand All @@ -34,13 +35,14 @@ interface PathStack {
function getMessageFilepath(fullPath: string, context: RuleContext) {
const cwd = getCwd(context)
if (fullPath.startsWith(cwd)) {
return fullPath.replace(cwd + '/', './')
return fullPath.replace(`${cwd}/`, './')
}
return fullPath
}

function create(context: RuleContext): RuleListener {
const filename = context.getFilename()
const filename = getFilename(context)
const sourceCode = getSourceCode(context)
const options = (context.options && context.options[0]) || {}
const ignoreI18nBlock = Boolean(options.ignoreI18nBlock)

Expand Down Expand Up @@ -129,7 +131,7 @@ function create(context: RuleContext): RuleListener {
}
if (typeof value.value !== 'object') {
reportFiles.push(
'"' + getMessageFilepath(value.source.fullpath, context) + '"'
`"${getMessageFilepath(value.source.fullpath, context)}"`
)
} else {
nextOtherDictionaries.push({
Expand All @@ -145,7 +147,7 @@ function create(context: RuleContext): RuleListener {
message: `duplicate key '${keyPathStr}' in '${pathStack.locale}'. ${
reportFiles.length === 0
? last
: reportFiles.join(', ') + ', and ' + last
: `${reportFiles.join(', ')}, and ${last}`
} has the same key`,
loc: reportNode.loc
})
Expand Down Expand Up @@ -316,7 +318,7 @@ function create(context: RuleContext): RuleListener {
lm => lm !== targetLocaleMessage
)
return createVisitorForJson(
ctx.getSourceCode(),
getSourceCode(ctx),
targetLocaleMessage,
otherLocaleMessages
)
Expand All @@ -335,31 +337,33 @@ function create(context: RuleContext): RuleListener {
lm => lm !== targetLocaleMessage
)
return createVisitorForYaml(
ctx.getSourceCode(),
getSourceCode(ctx),
targetLocaleMessage,
otherLocaleMessages
)
}
)
} else if (context.parserServices.isJSON || context.parserServices.isYAML) {
} else if (
sourceCode.parserServices.isJSON ||
sourceCode.parserServices.isYAML
) {
const localeMessages = getLocaleMessages(context)
const targetLocaleMessage = localeMessages.findExistLocaleMessage(filename)
if (!targetLocaleMessage) {
debug(`ignore ${filename} in no-duplicate-keys-in-locale`)
return {}
}

const sourceCode = context.getSourceCode()
const otherLocaleMessages: LocaleMessage[] =
localeMessages.localeMessages.filter(lm => lm !== targetLocaleMessage)

if (context.parserServices.isJSON) {
if (sourceCode.parserServices.isJSON) {
return createVisitorForJson(
sourceCode,
targetLocaleMessage,
otherLocaleMessages
)
} else if (context.parserServices.isYAML) {
} else if (sourceCode.parserServices.isYAML) {
return createVisitorForYaml(
sourceCode,
targetLocaleMessage,
Expand Down
5 changes: 3 additions & 2 deletions lib/rules/no-dynamic-keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import { defineTemplateBodyVisitor, isStaticLiteral } from '../utils/index'
import type { RuleContext, RuleListener } from '../types'
import type { AST as VAST } from 'vue-eslint-parser'
import { createRule } from '../utils/rule'
import { getSourceCode } from '../utils/compat'

function getNodeName(context: RuleContext, node: VAST.Node): string {
if (node.type === 'Identifier') {
return node.name
}
const sourceCode = context.getSourceCode()
const sourceCode = getSourceCode(context)
if (
sourceCode.ast.range[0] <= node.range[0] &&
node.range[1] <= sourceCode.ast.range[1]
Expand All @@ -20,7 +21,7 @@ function getNodeName(context: RuleContext, node: VAST.Node): string {
.map(t => t.value)
.join('')
}
const tokenStore = context.parserServices.getTemplateBodyTokenStore()
const tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore()
return tokenStore
.getTokens(node)
.map(t => t.value)
Expand Down
8 changes: 5 additions & 3 deletions lib/rules/no-html-messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type { AST as YAMLAST } from 'yaml-eslint-parser'
import type { RuleContext, RuleListener } from '../types'
import { createRule } from '../utils/rule'
import type { DefaultTreeAdapterMap } from 'parse5'
import { getFilename, getSourceCode } from '../utils/compat'

const debug = debugBuilder('eslint-plugin-vue-i18n:no-html-messages')

Expand All @@ -25,7 +26,8 @@ function findHTMLNode(node: DocumentFragment): Element | undefined {
}

function create(context: RuleContext): RuleListener {
const filename = context.getFilename()
const filename = getFilename(context)
const sourceCode = getSourceCode(context)

/**
* @param {JSONLiteral} node
Expand Down Expand Up @@ -97,14 +99,14 @@ function create(context: RuleContext): RuleListener {
}
}
)
} else if (context.parserServices.isJSON) {
} else if (sourceCode.parserServices.isJSON) {
if (!getLocaleMessages(context).findExistLocaleMessage(filename)) {
return {}
}
return {
JSONLiteral: verifyJSONLiteral
}
} else if (context.parserServices.isYAML) {
} else if (sourceCode.parserServices.isYAML) {
if (!getLocaleMessages(context).findExistLocaleMessage(filename)) {
return {}
}
Expand Down
13 changes: 9 additions & 4 deletions lib/rules/no-missing-keys-in-other-locales.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import type {
import type { LocaleMessage, LocaleMessages } from '../utils/locale-messages'
import { joinPath } from '../utils/key-path'
import { createRule } from '../utils/rule'
import { getFilename, getSourceCode } from '../utils/compat'
const debug = debugBuilder(
'eslint-plugin-vue-i18n:no-missing-keys-in-other-locales'
)

function create(context: RuleContext): RuleListener {
const filename = context.getFilename()
const filename = getFilename(context)
const sourceCode = getSourceCode(context)
const ignoreLocales: string[] = context.options[0]?.ignoreLocales || []

function reportMissing(
Expand Down Expand Up @@ -307,17 +309,20 @@ function create(context: RuleContext): RuleListener {
return createVisitorForYaml(targetLocaleMessage, localeMessages)
}
)
} else if (context.parserServices.isJSON || context.parserServices.isYAML) {
} else if (
sourceCode.parserServices.isJSON ||
sourceCode.parserServices.isYAML
) {
const localeMessages = getLocaleMessages(context)
const targetLocaleMessage = localeMessages.findExistLocaleMessage(filename)
if (!targetLocaleMessage) {
debug(`ignore ${filename} in no-missing-keys-in-other-locales`)
return {}
}

if (context.parserServices.isJSON) {
if (sourceCode.parserServices.isJSON) {
return createVisitorForJson(targetLocaleMessage, localeMessages)
} else if (context.parserServices.isYAML) {
} else if (sourceCode.parserServices.isYAML) {
return createVisitorForYaml(targetLocaleMessage, localeMessages)
}
return {}
Expand Down
Loading