| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- /**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- /**
- * @fileoverview Rule to warn about translation template variables
- * @author Apache
- */
- //------------------------------------------------------------------------------
- // Rule Definition
- //------------------------------------------------------------------------------
- /** @type {import('eslint').Rule.RuleModule} */
- module.exports = {
- rules: {
- 'no-template-vars': {
- create(context) {
- function handler(node) {
- if (node.arguments.length) {
- const firstArgs = node.arguments[0];
- if (
- firstArgs.type === 'TemplateLiteral' &&
- firstArgs.expressions.length
- ) {
- context.report({
- node,
- message:
- "Don't use variables in translation string templates. Flask-babel is a static translation service, so it can't handle strings that include variables",
- });
- }
- }
- }
- return {
- "CallExpression[callee.name='t']": handler,
- "CallExpression[callee.name='tn']": handler,
- };
- },
- },
- 'sentence-case-buttons': {
- create(context) {
- function isTitleCase(str) {
- // Match "Delete Dataset", "Create Chart", etc. (2+ title-cased words)
- return /^[A-Z][a-z]+(\s+[A-Z][a-z]*)+$/.test(str);
- }
- function isButtonContext(node) {
- const { parent } = node;
- if (!parent) return false;
- // Check for button-specific props
- if (parent.type === 'Property') {
- const key = parent.key.name;
- return [
- 'primaryButtonName',
- 'secondaryButtonName',
- 'confirmButtonText',
- 'cancelButtonText',
- ].includes(key);
- }
- // Check for Button components
- if (parent.type === 'JSXExpressionContainer') {
- const jsx = parent.parent;
- if (jsx?.type === 'JSXElement') {
- const elementName = jsx.openingElement.name.name;
- return elementName === 'Button';
- }
- }
- return false;
- }
- function handler(node) {
- if (node.arguments.length) {
- const firstArg = node.arguments[0];
- if (
- firstArg.type === 'Literal' &&
- typeof firstArg.value === 'string'
- ) {
- const text = firstArg.value;
- if (isButtonContext(node) && isTitleCase(text)) {
- const sentenceCase = text
- .toLowerCase()
- .replace(/^\w/, c => c.toUpperCase());
- context.report({
- node: firstArg,
- message: `Button text should use sentence case: "${text}" should be "${sentenceCase}"`,
- });
- }
- }
- }
- }
- return {
- "CallExpression[callee.name='t']": handler,
- "CallExpression[callee.name='tn']": handler,
- };
- },
- },
- },
- };
|