npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

hardcode-string-detector

v0.4.2

Published

A CLI tool to detect hardcoded strings in your project based on hcs_config.json tasks.

Readme

Hard Code String Extractor (hcs)

NPM Version License: MIT

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.

Why Use This Tool?

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.

Features

  • Configurable Scanning: Define multiple scan tasks, each targeting different directories and file types.
  • Broad File Support: Scans JavaScript, JSX, TypeScript, and TSX files by default (configurable).
  • Flexible Detection Rules:
    • Identifies strings in JSX text content (<div>Hardcoded Text</div>).
    • Finds string literals within JSX expressions (<p>{"Hardcoded Expression"}</p>).
    • 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.

Installation

You can install hard-code-string-extractor globally to use the hcs command anywhere:

npm install -g hard-code-string-extractor

Or you can install it locally in your project:

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

Run all tasks defined in hcs_config.json

hcs

Run only the "FrontendScan" and "MobileScan" tasks

hcs FrontendScan MobileScan The tool will generate JSON output files as specified in each task's configuration.

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

{
  "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

hcs

Run a specific task

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:

// package.json
{
  "name": "hard-code-string-extractor",
  "version": "0.3.0", // Or your current version
  "description": "A CLI tool to detect hardcoded strings in your project.",
  "main": "index.js", // Your main script file
  "bin": {
    "hard-code-string-extractor": "./index.js",
    "hcs": "./index.js"
  },
  // ... other fields like author, license, dependencies, scripts
}
This tells npm to create a symlink for hcs (and hard-code-string-extractor) to your index.js script when the package is installed globally. Make sure index.js has the shebang #!/usr/bin/env node at the very top.