A CLI tool to detect hardcoded strings in your project based on hcs_config.json tasks.
npm install hardcode-string-detector

A command-line tool to scan your project for hardcoded strings, helping you identify text that needs to be internationalized (i18n) or managed more effectively.
Keeping track of hardcoded strings is crucial for:
* Internationalization (i18n): Easily spot text that needs to be moved to translation files.
* Maintainability: Manage UI text and other string literals from a central or configured perspective.
* Consistency: Ensure that user-facing strings are handled systematically.
hard-code-string-extractor (hcs) scans your codebase based on flexible configurations and outputs a JSON report detailing the found strings and their locations.
* Configurable Scanning: Define multiple scan tasks, each targeting different directories and file types. {"Hardcoded Expression"}
* Broad File Support: Scans JavaScript, JSX, TypeScript, and TSX files by default (configurable).
* Flexible Detection Rules:
* Identifies strings in JSX text content ().Hardcoded Text
* Finds string literals within JSX expressions ().
* Checks for strings in configurable JSX attributes (e.g., placeholder, alt, aria-label).
* Detects strings passed as arguments to specific, user-defined functions (e.g., Alert.alert("Title"), enqueueSnackbar("Message")).
* JSON Output: Generates a detected.json (or custom-named) file with findings, including:
* File path (relative to the scanned directory).
* Line and column number.
* The detected hardcoded string.
* Output paths are often clickable in modern terminals and IDEs like VS Code.
* Configuration via hcs_config.json: Manage all your scanning profiles and rules from a single JSON configuration file.
You can install hard-code-string-extractor globally to use the hcs command anywhere:
``bash`
npm install -g hard-code-string-extractor
Or you can install it locally in your project:
`bash`
npm install --save-dev hard-code-string-extractor
If installed locally, you can run it using npx hcs or by adding it to your package.json scripts.
Usage
The primary way to use the tool is by defining your scan configurations in an hcs_config.json file in your project root.
Bash
hcs [taskName1 taskName2 ...]
If you run hcs without any arguments, it will attempt to load hcs_config.json from the current directory and execute all tasks defined within it.
You can specify one or more task names as arguments to run only those specific tasks.
Example:
Bash
Configuration (hcs_config.json)
Create an hcs_config.json file in the root of your project to define global settings and specific scan tasks.
Structure:
json
{
"globalExtensions": ["js", "jsx", "ts", "tsx"],
"globalAttributes": ["placeholder", "title", "alt", "aria-label", "label", "data-tooltip"],
"globalTargetFunctions": [
{
"functionNameForDisplay": "Default: Alert.alert",
"calleeType": "MemberExpression", "objectName": "Alert", "propertyName": "alert",
"argumentChecks": [
{ "index": 0, "type": "StringLiteral", "description": "title" },
{ "index": 1, "type": "StringLiteral", "description": "message" }
]
}
],
"tasks": [
{
"name": "WebAppUI",
"scanDir": "./src/webapp",
"output": "reports/webapp_hardcoded.json",
"extensions": ["jsx", "tsx"],
"attributes": ["placeholder", "aria-label", "title"],
"targetFunctions": [
{
"functionNameForDisplay": "enqueueSnackbar (notistack)",
"calleeType": "Identifier", "identifierName": "enqueueSnackbar",
"argumentChecks": [
{ "index": 0, "type": "StringLiteral", "description": "message" }
]
},
{
"functionNameForDisplay": "customTranslateFunction",
"calleeType": "Identifier", "identifierName": "translate",
"argumentChecks": [
// This example rule helps find if you accidentally pass a literal string
// to your translate function instead of a key.
{ "index": 0, "type": "StringLiteral", "description": "translation_key_or_default_literal" }
]
}
]
},
{
"name": "MobileAppStrings",
"scanDir": "./src/mobile",
"output": "reports/mobile_hardcoded.json",
// Uses globalExtensions
"attributes": ["label", "hint", "accessibilityLabel"], // Overrides globalAttributes
"targetFunctions": [
// Inherits Alert.alert from globalTargetFunctions if merging logic is implemented,
// or if this list is empty, globalTargetFunctions could be used by default.
// Current script behavior: If task.targetFunctions exists, it's used exclusively.
// If task.targetFunctions is undefined, config.globalTargetFunctions is used.
// If that's also undefined, SCRIPT_DEFAULTS.targetFunctions is used.
// To combine, you'd explicitly list global ones here or modify the script's merging logic.
// For clarity, let's assume this task wants its own specific list plus the global Alert.alert.
// The script would need to be adjusted to merge globalTargetFunctions with task-specific ones if both are present.
// As implemented in the provided script, if a task defines targetFunctions, it replaces the global/default.
// To use global and add more:
// "targetFunctions": "USE_GLOBAL_AND_ADD_MORE" (requires script change) or manually copy global ones here.
// Let's assume for this example, it defines its own complete list for this task:
{
"functionNameForDisplay": "Alert.alert (Mobile)", // Potentially overriding a global one with more specific checks
"calleeType": "MemberExpression", "objectName": "Alert", "propertyName": "alert",
"argumentChecks": [
{ "index": 0, "type": "StringLiteral", "description": "title" },
{ "index": 1, "type": "StringLiteral", "description": "message" }
]
},
{
"functionNameForDisplay": "Snackbar.show (react-native-snackbar)",
"calleeType": "MemberExpression", "objectName": "Snackbar", "propertyName": "show",
"argumentChecks": [
{
"index": 0,
"type": "ObjectExpression",
"properties": [
{ "keyName": "text", "valueType": "StringLiteral", "description": "snackbar text" }
]
}
]
}
]
},
{
"name": "SharedLibraries",
"scanDir": "./packages/shared-utils/src",
"output": "reports/shared_libs_hardcoded.json",
"extensions": ["js", "ts"]
// Uses globalAttributes and globalTargetFunctions (or script defaults if globals are not set)
}
]
}
`
Configuration Fields:
- globalExtensions (Array<String>, optional): Default file extensions to scan if not specified per task.
- globalAttributes (Array<String>, optional): Default JSX attributes to check for hardcoded strings if not - specified per task.
- globalTargetFunctions (Array<Object>, optional): Default function call patterns to check if not specified per - task.
- tasks (Array<Object>, required): An array of scan task objects.
- name (String, required): A unique name for the task (used for selective execution).
- scanDir (String, required): The directory to scan for this task, relative to the project root.
- output (String, required): The output JSON file path for this task's results, relative to the project root.
- extensions (Array<String>, optional): Task-specific file extensions. Overrides globalExtensions.
- attributes (Array<String>, optional): Task-specific JSX attributes. Overrides globalAttributes.
- targetFunctions (Array<Object>, optional): Task-specific function call patterns. Overrides globalTargetFunctions.
- Each targetFunction object has:
- functionNameForDisplay (String): A descriptive name for the rule.
- calleeType (String): "Identifier" (e.g., myFunc()) or "MemberExpression" (e.g., object.myFunc()).
- identifierName (String, if calleeType is "Identifier"): The name of the function.
- objectName (String, if calleeType is "MemberExpression"): The name of the object (e.g., "Alert").
- propertyName (String, if calleeType is "MemberExpression"): The name of the property/method (e.g., "alert").
- argumentChecks (Array<Object>): Rules for checking arguments.
- index (Number): The 0-based index of the argument.
- type (String): Expected type of the argument, e.g., "StringLiteral" or "ObjectExpression".
- properties (Array<Object>, if type is "ObjectExpression"): Rules for checking object properties.
- keyName (String): The name of the object key.
- valueType (String): Expected type of the property's value (e.g., "StringLiteral").
- description (String, optional): A comment for the rule.
Output JSON Format
The output is a JSON object where keys are the location of the hardcoded string and values are the detected strings themselves:JSON
`json
{
"src/components/MyComponent.jsx:25:12": "Welcome to our application!",
"src/pages/HomePage.tsx:10:5": "Learn More",
"src/utils/toastHelper.js:5:22": "Operation successful"
}
`
The filePath:lineNumber:columnNumber format is often clickable in IDEs like VS Code, taking you directly to the source.Example Workflow
Create hcs_config.json in your project root with your desired tasks (see example above).
Run the extractor:
Bash
Run all tasks
`bash
hcs
`Run a specific task
`bash
hcs WebAppUI
`Review the output JSON files (e.g., reports/webapp_hardcoded.json).
Contributing
Contributions are welcome! Please feel free to open an issue or submit a pull request.
(TODO: Add contribution guidelines if you plan to open-source it formally).
License
This project is licensed under the MIT License - see the LICENSE.md file for details (You would need to create a LICENSE.md file with the MIT license text).
To make
hcs the short command for your CLI tool:When you publish your package to npm, you'll need to configure the
bin field in your package.json like this:``json