Something went wrong. Try again.
hardened bluesky app fork with microcosm
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111'use strict'
/** * @type {import('eslint').Rule.RuleModule} */module.exports = { meta: { type: 'problem', docs: { description: 'Enforce that Lingui _() function is called with msg`` template literal or plural/select macros', recommended: true, }, fixable: 'code', messages: { missingMsg: 'Lingui _() must be called with msg`...` or msg({...}) or plural/select/selectOrdinal. Example: _(msg`Hello`)', }, schema: [], },
create(context) { // Valid Lingui macro functions that can be passed to _() const VALID_MACRO_FUNCTIONS = new Set([ 'msg', 'plural', 'select', 'selectOrdinal', ])
/** * Escape backticks and backslashes for template literal */ function escapeForTemplateLiteral(str) { return str.replace(/\\`/g, '`').replace(/`/g, '\\`') }
/** * Try to get a fixer for the given argument * Returns null if we can't safely fix it */ function getFixer(firstArg) { const sourceCode = context.sourceCode ?? context.getSourceCode()
// Fix string literals: _('foo') -> _(msg`foo`) if (firstArg.type === 'Literal' && typeof firstArg.value === 'string') { const escaped = escapeForTemplateLiteral(firstArg.value) return function (fixer) { return fixer.replaceText(firstArg, 'msg`' + escaped + '`') } }
// Fix untagged template literals: _(`foo`) -> _(msg`foo`) if (firstArg.type === 'TemplateLiteral') { const text = sourceCode.getText(firstArg) return function (fixer) { return fixer.replaceText(firstArg, 'msg' + text) } }
return null }
return { CallExpression(node) { // Check if this is a call to _() if (node.callee.type !== 'Identifier' || node.callee.name !== '_') { return }
// Must have at least one argument if (node.arguments.length === 0) { context.report({ node, messageId: 'missingMsg', }) return }
const firstArg = node.arguments[0]
// Valid: _(msg`...`) if ( firstArg.type === 'TaggedTemplateExpression' && firstArg.tag.type === 'Identifier' && firstArg.tag.name === 'msg' ) { return }
// Valid: _(msg(...)), _(plural(...)), _(select(...)), _(selectOrdinal(...)) if ( firstArg.type === 'CallExpression' && firstArg.callee.type === 'Identifier' && VALID_MACRO_FUNCTIONS.has(firstArg.callee.name) ) { return }
// Everything else is invalid const fix = getFixer(firstArg) context.report({ node, messageId: 'missingMsg', fix, }) }, } },}