{"id":22897283,"url":"https://github.com/center-key/replacer-util","last_synced_at":"2026-05-31T12:00:46.167Z","repository":{"id":60945368,"uuid":"546550276","full_name":"center-key/replacer-util","owner":"center-key","description":"🔍 Find and replace strings or template outputs in text files (CLI for package.json scripts)","archived":false,"fork":false,"pushed_at":"2026-03-12T09:46:06.000Z","size":1278,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-12T16:29:22.712Z","etag":null,"topics":["cli","concatenate-files","npm","recursive","regex","replace","site-generator"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/center-key.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-10-06T08:56:45.000Z","updated_at":"2026-03-12T09:45:52.000Z","dependencies_parsed_at":"2024-04-17T09:45:27.476Z","dependency_job_id":"800ffbfe-4c0d-48fd-96c9-6e4b763a9cf7","html_url":"https://github.com/center-key/replacer-util","commit_stats":{"total_commits":67,"total_committers":1,"mean_commits":67.0,"dds":0.0,"last_synced_commit":"91e581393d2a581f181c2aa490411d2ab7698245"},"previous_names":[],"tags_count":53,"template":false,"template_full_name":null,"purl":"pkg:github/center-key/replacer-util","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/center-key%2Freplacer-util","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/center-key%2Freplacer-util/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/center-key%2Freplacer-util/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/center-key%2Freplacer-util/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/center-key","download_url":"https://codeload.github.com/center-key/replacer-util/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/center-key%2Freplacer-util/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33730241,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-31T02:00:06.040Z","response_time":95,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","concatenate-files","npm","recursive","regex","replace","site-generator"],"created_at":"2024-12-14T00:16:25.154Z","updated_at":"2026-05-31T12:00:46.160Z","avatar_url":"https://github.com/center-key.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# replacer-util\n\u003cimg src=https://centerkey.com/graphics/center-key-logo.svg align=right width=200 alt=logo\u003e\n\n_Find and replace strings, regex patterns, or template outputs in text files (CLI tool designed for use in npm package.json scripts)_\n\n[![License:MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/center-key/replacer-util/blob/main/LICENSE.txt)\n[![npm](https://img.shields.io/npm/v/replacer-util.svg)](https://www.npmjs.com/package/replacer-util)\n[![Build](https://github.com/center-key/replacer-util/actions/workflows/run-spec-on-push.yaml/badge.svg)](https://github.com/center-key/replacer-util/actions/workflows/run-spec-on-push.yaml)\n\n**replacer-util** searches for text to substitute with a replacement string or with values from your project's **package.json** file, such as the project version number.\u0026nbsp;\nIt can also insert path metadata and concatenate output to generate content such as an HTML file of `\u003ca\u003e` links.\u0026nbsp;\n**LiquidJS** powers the template outputs and enables **replacer-util** to act as a static site generator complete with filter formatters and `render` tags for including partials.\u0026nbsp;\n\n\u003cimg src=https://raw.githubusercontent.com/center-key/replacer-util/main/screenshot.png\nwidth=800 alt=screenshot\u003e\n\n## A) Setup\nInstall package for node:\n```shell\n$ npm install --save-dev replacer-util\n```\n\n## B) Usage\n### 1. Synopsis\n```\nreplacer [SOURCE] [TARGET]\n```\nParameters:\n* The **first** parameter is the *source* folder or file.\n* The **second** parameter is the *target* folder.\n\n### 2. npm package.json scripts\nRun `replacer` from the `\"scripts\"` section of your **package.json** file.\n\nExample **package.json** scripts:\n```json\n   \"scripts\": {\n      \"build-web\": \"replacer src/web --ext=.html dist/website\",\n      \"poetry\": \"replacer poems --find=human --replacement=robot dystopian-poems\"\n   },\n```\nIn addition to the `--find` and `--replacement` CLI flags, template outputs in the source files will be replaced with their corresponding template variable values.\u0026nbsp;\nThe template variable `package` points to the **package.json** object, enabling `{{package.version}}` in the source file to be replaced with the project's version number.\n\n### 3. Command-line npx\nExample terminal commands:\n```shell\n$ npm install --save-dev replacer-util\n$ npx replacer src/web ext=.html docs/api-manual\n```\nYou can also install **replacer-util** globally (`--global`) and then run it anywhere directly from the terminal.\n\n### 4. CLI flags\nCommand-line flags:\n| Flag              | Description                                           | Value      |\n| ----------------- | ----------------------------------------------------- | ---------- |\n| `--cd`            | Change working directory before starting search.      | **string** |\n| `--concat`        | Merge all files into one file in the target folder.   | **string** |\n| `--content`       | String to be used instead of the input file contents. | **string** |\n| `--exclude`       | Skip files containing the string in their path.       | **string** |\n| `--ext`           | Filter files by file extension, such as `.js`.\u003cbr\u003eUse a comma to specify multiple extensions. | **string** |\n| `--find`          | Text to search for in the source input files.         | **string** |\n| `--header`        | Prepend a line of text to each file.                  | **string** |\n| `--no-liquid`     | Turn off LiquidJS templating.                         | N/A        |\n| `--no-source-map` | Remove any `sourceMappingURL` comment directives.     | N/A        |\n| `--non-recursive` | Only read files in the source folder not subfolders.  | N/A        |\n| `--note`          | Place to add a comment only for humans.               | **string** |\n| `--quiet`         | Suppress informational messages.                      | N/A        |\n| `--regex`         | Pattern to search for in the source input files.      | **string** |\n| `--rename`        | New output filename.                                  | **string** |\n| `--replacement`   | Text to insert into the target output files.          | **string** |\n| `--summary`       | Only print out the single line summary message.       | N/A        |\n| `--title-sort`    | Ignore leading articles in `--concat` filenames.      | N/A        |\n| `--virtual-input` | Do not read any files, use `--content` instead.       | N/A        |\n\nTo avoid issues on the command line, problematic characters can be _\"escaped\"_ with safe strings as listed below.\n\nEscape characters:\n| Character | Safe stand-in string |\n| --------- | -------------------- |\n| `'`       | `{{apos}}`           |\n| `!`       | `{{bang}}`           |\n| `}`       | `{{close-curly}}`    |\n| `=`       | `{{equals}}`         |\n| `\u003e`       | `{{gt}}`             |\n| `#`       | `{{hash}}`           |\n| `\u003c`       | `{{lt}}`             |\n| `{`       | `{{open-curly}}`     |\n| `\\|`      | `{{pipe}}`           |\n| `\"`       | `{{quote}}`          |\n| `;`       | `{{semi}}`           |\n| ` `       | `{{space}}`          |\n\nAlternatively, escaping for the command line can be avoided with [macros](#9-macros) you define in your project's **package.json** file (see documentation below).\n\n### 5. Examples\n   - `replacer src build`\u003cbr\u003e\n   Recursively copies all the files in the **src** folder to the **build** folder using the data in **package.json** to update the template outputs.\n\n   - `replacer src/docs --ext=.md --find=Referer --replacement=Referrer output/fixed`\u003cbr\u003e\n   Fixes spelling error in markdown files.\n\n   - `replacer src/docs --ext=.md --find=Referer --replacement=Referrer --no-liquid output/fixed`\u003cbr\u003e\n   Same as previous example but disables LiquidJS templating (useful in case source files contain characters inadvertently interpreted at templating commands).\n\n   - `replacer web '--find=cat dog' '--replacement= cat{{pipe}}dog ' target`\u003cbr\u003e\n   `replacer web --find=cat\\ dog --replacement=\\ cat{{pipe}}dog\\  target`\u003cbr\u003e\n   `replacer web --find=cat{{space}}dog --replacement={{space}}cat{{pipe}}dog{{space}} target`\u003cbr\u003e\n   Replaces all occurances of the string `'cat dog'` with `' cat|dog '` (note the _3 different_ ways to _\"escape\"_ a space character).\n\n   - `replacer src --ext=.js --no-liquid --concat=bundle.js build`\u003cbr\u003e\n   Merges all JS files into **build/bundle.js**.\n\n   - `replacer app/widgets --ext=.less --content=@import{{space}}{{quote}}{{file.dir}}/{{file.name}}{{quote}}{{semi}} --concat=widgets.less app/style`\u003cbr\u003e\n   Creates a single LESS file that imports the LESS files of every widget component.\n\n   - `replacer app/widgets --ext=.less --content={{macro:less-import}} --concat=widgets.less app/style`\u003cbr\u003e\n   Identical to the previous command assuming the `less-import` macro is properly defined in the **package.json** file.\n\n   - `replacer src --summary build`\u003cbr\u003e\n   Displays the summary informaion but not informaion about individual files copied.\n\n   - `replacer src --regex=/^--/gm --replacement=🥕🥕🥕 build`\u003cbr\u003e\n   Finds double dashes at the start of lines and replace them with 3 carrots.\u0026nbsp;\n   Note the `g` and `m` [regex options](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#advanced_searching_with_flags).\n\n   - `replacer build/my-app.js --rename=my-app.browser.js build`\u003cbr\u003e\n   Copies **my-app.js** to **my-app.browser.js** without making and changes.\n\n   - `replacer src/web --ext=.html --rename=index.html dist/website`\u003cbr\u003e\n   Renames all HTML files, such as **src/web/about/about.html**, to **index.html** while preserving the folder structure.\n\n   - `replacer --cd=spec fixtures/web --find=insect --replacement=A.I. target/web`\u003cbr\u003e\n   Removes all insects.\u0026nbsp; See: [fixtures/web/mock1.html](spec/fixtures/web/mock1.html) and [target/web/mock1.html](spec/target/exclude/mock1.html)\n\n   - `replacer node_modules/chart.js/dist/chart.umd.js --no-source-map build/1-pre/libs`\u003cbr\u003e\n   Removes the `//# sourceMappingURL=chart.umd.js.map` line at the bottom of the **Chart.js** distribution file.\n\n   - `replacer . docs --rename=robots.txt --virtual-input --content={{hash}}{{space}}Allow{{space}}bots{{bang}}`\u003cbr\u003e\n   Creates a **robots.txt** file with the line `# Allow bots!` in the **docs** folder.\n\n   - `replacer --virtual-input . --rename=CNAME docs --content=example.com`\u003cbr\u003e\n   Creates a **CNAME** file with the line `example.com` in the **docs** folder.\n\nFor examples of using `replacer` as part of front-end build process, check out the `\"runScriptsConfig\"` section of:\u003cbr\u003e\nhttps://github.com/dna-dom/data-dashboard/blob/main/package.json\n\n\u003e [!NOTE]\n\u003e _Single quotes in commands are normalized so they work cross-platform and avoid the errors often encountered on Microsoft Windows._\n\n### 6. Template outputs and filter formatters\nThe source files are processed by LiquidJS, so you can use [template outputs](https://liquidjs.com/tutorials/intro-to-liquid.html#Outputs) and [filter formatters](https://liquidjs.com/filters/overview.html).\u0026nbsp;\nCustom variables are created with the [assign](ttps://liquidjs.com/tags/assign.html) tag.\n\nThree special variables are available by default:\n   * `file`    ([path](https://nodejs.org/api/path.html#pathparsepath) and date information about the source file)\n   * `package` (values from your project's **package.json** file)\n   * `webRoot` (relative path to root folder: `.`, `..`, `../..`, `../../..`, etc.)\n\nFor example, a TypeScript file with the lines:\n```typescript\nconst msg1: string = 'The current release of {{package.name | upcase}} is v{{package.version}}.';\nconst msg2: string = 'This file is: {{file.base}}';\n```\nwill be transformed into something like:\n```typescript\nconst msg1: string = 'The current release of MY-COOL-NPM-PACKAGE is v1.2.3.';\nconst msg2: string = 'This file is: my-app.ts';\n```\n\nExample outputs and formatters:\n| Source file text               | Example output value       | Note                                           |\n| ------------------------------ | -------------------------- | ---------------------------------------------- |\n| `{{package.name}}`             | `my-project`               | Value from `name` field in **package.json**    |\n| `{{package.version}}`          | `3.1.4`                    | Value from `version` field in **package.json** |\n| `{{package.version\\|size}}`    | `5`                        | Length of the version number string            |\n| `{{file.path}}`                | `src/web/sign-in.html`     | Full path to source file                       |\n| `{{file.folder}}`              | `web`                      | Name of parent folder of the source file       |\n| `{{file.base}}`                | `sign-in.html`             | Source filename with the file extension        |\n| `{{file.name}}`                | `sign-in`                  | Source filename without the file extension     |\n| `{{file.ext}}`                 | `.html`                    | File extension of the source file              |\n| `{{file.modified}}`            | `April 7, 2030`            | Formatted date of when file was last modifiled |\n| `{{file.date\\|date:\"%A\"}}`     | `Sunday`                   | Date object for when file was last modifiled   |\n| `{{file.timestamp}}`           | `2030-04-07T07:01:36.037Z` | Value for the `datetime` attribute of `\u003ctime\u003e` |\n| `\u003ca href={{webRoot}}\u003eHome\u003c/a\u003e` | `\u003ca href=../..\u003eHome\u003c/a\u003e`   | Link is relative to the source folder          |\n| `{{\"now\"\\|date:\"%Y-%m-%d\"}}`   | `2024-01-21`               | Build date timestamp                           |\n| `{{myVariable\\|upcase}}`       | `DARK MODE`                | Custom variable set with: `{% assign myVariable = 'dark mode' %}` |\n\n\u003e [!NOTE]\n\u003e _Use the `--no-liquid` flag if characters in your source files are inadvertently being interpreted as templating commands and causing errors._\n\n### 7. SemVer\nYour project's dependancies declared in **package.json** can be used to automatically keep your\nCDN links up-to-date.\n\nThree special filter formatters are available to support Semantic Versioning (SemVer):\n   * `version`\n   * `major-version`\n   * `minor-version`\n\nFor example, if your project declares a dependency of `^3.1.4` for **fetch-json**, the line:\n```html\n\u003cscript src=https://cdn.jsdelivr.net/npm/fetch-json@{{package.dependencies.fetch-json|minor-version}}/dist/fetch-json.min.js\u003e\u003c/script\u003e\n```\nwill be transformed into:\n```html\n\u003cscript src=https://cdn.jsdelivr.net/npm/fetch-json@3.5/dist/fetch-json.min.js\u003e\u003c/script\u003e\n```\n\u003e [!WARNING]\n\u003e _Some package names contain one or more of the characters `@`, `/`, and `.`, and these 3\ncharacters are not supported for replacement.\u0026nbsp; Use `-` in the package name instead._\n\nFor example, CDN links for the packages `\"@fortawesome/fontawesome-free\"` and `\"highlight.js\"` can be created with:\n```html\n\u003clink rel=stylesheet href=https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@{{package.devDependencies.-fortawesome-fontawesome-free|version}}/css/all.min.css\u003e\n\u003cscript src=https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@{{package.devDependencies.highlight-js|version}}/build/highlight.min.js\u003e\u003c/script\u003e\n```\n\n### 8. Last Updated\nThe special `file` varaible can be leveraged to create a \"Last Updated\" field that is\nautomatically populated with the date the source file was most recently modified.\n\nFor example, an HTML file with following lines:\n```html\n\u003cheader\u003e\n   \u003ch1\u003eMy Blog\u003c/h1\u003e\n   \u003ch2\u003e🚀 How to Watch a Rocket Launch 🚀\u003c/h2\u003e\n   \u003ctime datetime={{file.timestamp}}\u003e{{file.modified}}\u003c/time\u003e\n\u003c/header\u003e\n```\nwill be transformed into something similar to:\n```html\n\u003cheader\u003e\n   \u003ch1\u003eMy Blog\u003c/h1\u003e\n   \u003ch2\u003e🚀 How to Watch a Rocket Launch 🚀\u003c/h2\u003e\n   \u003ctime datetime=2030-04-07T07:01:36.037Z\u003eApril 7, 2030\u003c/time\u003e\n\u003c/header\u003e\n```\n**Note:**\u003cbr\u003e\nBe aware that `git checkout` deliberately resets file modification dates (`mtime`).\u0026nbsp;\nIf you use GitHub Actions to publish your website, you'll need to restore file modification dates with a script or tool.\u0026nbsp;\nOne tool that does this is [git-restore-mtime](https://github.com/marketplace/actions/git-restore-mtime):\n```yaml\n    steps:\n      - uses: actions/checkout@v6\n        with:\n          ref: main       #fetch the full git history of the \"main\"\n          fetch-depth: 0  #branch for git-restore-mtime-action below\n      - uses: chetan/git-restore-mtime-action@v2\n      - uses: actions/setup-node@v6\n      - run: npm install\n      - run: npm run publish\n```\nFor a working example, see: [publish-website.yaml](https://github.com/center-key/think-metric/blob/main/.github/workflows/publish-website.yaml)\n\n### 9. Macros\nDefine macros in your project's **package.json** file and use them to make commands more compact and readable.\n\nExample:\n```json\n   \"cliConfig\": {\n      \"macros\": {\n         \"less-import\": \"@import {{quote}}{{file.dir}}/{{file.name}}{{quote}};\"\n      }\n   },\n   \"scripts\": {\n      \"less-imports\": \"replacer app/widgets --ext=.less --content={{macro:less-import}} --concat=widgets.less app/style\"\n   },\n```\n\n## C) Application Code\nEven though **replacer-util** is primarily intended for build scripts, the package can be used programmatically in ESM and TypeScript projects.\n\nExample:\n``` typescript\nimport { replacer } from 'replacer-util';\n\nconst options = { extensions: ['.html', '.js'] };\nconst results = replacer.transform('src/web', 'docs/api-manual', options);\nconsole.info('Number of files copied:', results.count);\n```\n\nSee the **TypeScript Declarations** at the top of [replacer.ts](src/replacer.ts) for documentation.\n\n\u003cbr\u003e\n\n---\n**CLI Build Tools for package.json**\n   - 🎋 [add-dist-header](https://github.com/center-key/add-dist-header):\u0026nbsp; _Prepend a one-line banner comment (with license notice) to distribution files_\n   - 📄 [copy-file-util](https://github.com/center-key/copy-file-util):\u0026nbsp; _Copy or rename a file with optional package version number_\n   - 📂 [copy-folder-util](https://github.com/center-key/copy-folder-util):\u0026nbsp; _Recursively copy files from one folder to another folder_\n   - 🪺 [recursive-exec](https://github.com/center-key/recursive-exec):\u0026nbsp; _Run a command on each file in a folder and its subfolders_\n   - 🔍 [replacer-util](https://github.com/center-key/replacer-util):\u0026nbsp; _Find and replace strings or template outputs in text files_\n   - 🔢 [rev-web-assets](https://github.com/center-key/rev-web-assets):\u0026nbsp; _Revision web asset filenames with cache busting content hash fingerprints_\n   - 🚆 [run-scripts-util](https://github.com/center-key/run-scripts-util):\u0026nbsp; _Organize npm package.json scripts into groups of easy to manage commands_\n   - 🚦 [w3c-html-validator](https://github.com/center-key/w3c-html-validator):\u0026nbsp; _Check the markup validity of HTML files using the W3C validator_\n\nFeel free to submit questions at:\u003cbr\u003e\n[github.com/center-key/replacer-util/issues](https://github.com/center-key/replacer-util/issues)\n\n[MIT License](LICENSE.txt)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcenter-key%2Freplacer-util","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcenter-key%2Freplacer-util","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcenter-key%2Freplacer-util/lists"}