Use replaceAll to replace all instances of search text
This commit is contained in:
parent
386893d8dd
commit
2bacc3b250
|
|
@ -103,7 +103,7 @@ describe('processInChunks', () => {
|
||||||
|
|
||||||
describe('replaceTextInFile', () => {
|
describe('replaceTextInFile', () => {
|
||||||
const testFilePath = path.join(__dirname, 'test-file.txt');
|
const testFilePath = path.join(__dirname, 'test-file.txt');
|
||||||
const testFileContent = '{0}, world!';
|
const testFileContent = '{0}, foo, {0}!';
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await fs.promises.writeFile(testFilePath, testFileContent);
|
await fs.promises.writeFile(testFilePath, testFileContent);
|
||||||
|
|
@ -114,10 +114,10 @@ describe('replaceTextInFile', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should replace all instances of the given text with the given value in the file', async () => {
|
it('should replace all instances of the given text with the given value in the file', async () => {
|
||||||
await replaceTextInFile(testFilePath, '{0}', 'Hello'); // Replace text with special characters
|
await replaceTextInFile(testFilePath, '{0}', 'run'); // Replace text with special characters
|
||||||
await replaceTextInFile(testFilePath, 'world', 'universe'); // Replace text with no special characters
|
await replaceTextInFile(testFilePath, 'foo', 'test'); // Replace text with letters
|
||||||
const updatedContent = await fs.promises.readFile(testFilePath, 'utf-8');
|
const updatedContent = await fs.promises.readFile(testFilePath, 'utf-8');
|
||||||
expect(updatedContent).toBe('Hello, universe!');
|
expect(updatedContent).toBe('run, test, run!');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not modify the file if the search text is not found', async () => {
|
it('should not modify the file if the search text is not found', async () => {
|
||||||
|
|
|
||||||
|
|
@ -1,92 +1,11 @@
|
||||||
require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap
|
require('./sourcemap-register.js');/******/ (() => { // webpackBootstrap
|
||||||
/******/ var __webpack_modules__ = ({
|
/******/ var __webpack_modules__ = ({
|
||||||
|
|
||||||
/***/ 3109:
|
|
||||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
||||||
const core_1 = __nccwpck_require__(2186);
|
|
||||||
const utils_1 = __nccwpck_require__(918);
|
|
||||||
// Entry point for the action
|
|
||||||
function run() {
|
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
try {
|
|
||||||
// Get the input parameters
|
|
||||||
const filesPattern = (0, core_1.getInput)('files');
|
|
||||||
const searchText = (0, core_1.getInput)('search-text');
|
|
||||||
const replaceText = (0, core_1.getInput)('replacement-text');
|
|
||||||
const excludePattern = (0, core_1.getInput)('exclude');
|
|
||||||
const inputEncoding = (0, core_1.getInput)('encoding');
|
|
||||||
const maxParallelism = (0, core_1.getInput)('max-parallelism');
|
|
||||||
// Validate the encoding
|
|
||||||
if (!(0, utils_1.isValidEncoding)(inputEncoding)) {
|
|
||||||
throw new Error(`Invalid encoding: ${inputEncoding}`);
|
|
||||||
}
|
|
||||||
// Validate that maxParallelism is a positive integer
|
|
||||||
if (!(0, utils_1.isPositiveInteger)(maxParallelism)) {
|
|
||||||
throw new Error(`Invalid max-parallelism: ${maxParallelism}`);
|
|
||||||
}
|
|
||||||
// Get the file paths that match the files pattern and do not match the exclude pattern
|
|
||||||
const filePaths = yield (0, utils_1.getFiles)(filesPattern, excludePattern);
|
|
||||||
// If no file paths were found, log a warning and exit
|
|
||||||
if (filePaths.length === 0) {
|
|
||||||
(0, core_1.warning)(`No files found for the given pattern.`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
(0, core_1.info)(`Found ${filePaths.length} files for the given pattern.`);
|
|
||||||
(0, core_1.info)(`Replacing "${searchText}" with "${replaceText}".`);
|
|
||||||
// Process the file paths in chunks, replacing the search text with the replace text in each file
|
|
||||||
// This is done to avoid opening too many files at once
|
|
||||||
const encoding = inputEncoding;
|
|
||||||
const chunkSize = parseInt(maxParallelism);
|
|
||||||
yield (0, utils_1.processInChunks)(filePaths, (filePath) => __awaiter(this, void 0, void 0, function* () {
|
|
||||||
(0, core_1.info)(`Replacing text in file ${filePath}`);
|
|
||||||
yield (0, utils_1.replaceTextInFile)(filePath, searchText, replaceText, encoding);
|
|
||||||
}), chunkSize);
|
|
||||||
(0, core_1.info)(`Done!`);
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
if (err instanceof Error) {
|
|
||||||
(0, core_1.setFailed)(err.message);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const errorMessage = 'An error occurred. Run in debug mode for additional info.';
|
|
||||||
(0, core_1.debug)(`${JSON.stringify(err)}`);
|
|
||||||
(0, core_1.setFailed)(errorMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
run();
|
|
||||||
|
|
||||||
|
|
||||||
/***/ }),
|
|
||||||
|
|
||||||
/***/ 918:
|
/***/ 918:
|
||||||
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
||||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
||||||
return new (P || (P = Promise))(function (resolve, reject) {
|
|
||||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
||||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
||||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
||||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
||||||
});
|
|
||||||
};
|
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
};
|
};
|
||||||
|
|
@ -128,15 +47,13 @@ exports.isValidEncoding = isValidEncoding;
|
||||||
* @returns A Promise that resolves to an array of file paths.
|
* @returns A Promise that resolves to an array of file paths.
|
||||||
* @throws An error if there is an error getting the files.
|
* @throws An error if there is an error getting the files.
|
||||||
*/
|
*/
|
||||||
function getFiles(filesPattern, exclude) {
|
async function getFiles(filesPattern, exclude) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
try {
|
try {
|
||||||
return yield (0, glob_1.glob)(filesPattern, { ignore: exclude });
|
return await (0, glob_1.glob)(filesPattern, { ignore: exclude });
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
throw new Error(`Error getting files: ${error}`);
|
throw new Error(`Error getting files: ${error}`);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
exports.getFiles = getFiles;
|
exports.getFiles = getFiles;
|
||||||
/**
|
/**
|
||||||
|
|
@ -146,8 +63,7 @@ exports.getFiles = getFiles;
|
||||||
* @param chunkSize The number of items to process at a time.
|
* @param chunkSize The number of items to process at a time.
|
||||||
* @returns A Promise that resolves when all items have been processed.
|
* @returns A Promise that resolves when all items have been processed.
|
||||||
*/
|
*/
|
||||||
function processInChunks(array, func, chunkSize) {
|
async function processInChunks(array, func, chunkSize) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
// Split the array into chunks
|
// Split the array into chunks
|
||||||
const chunks = Array(Math.ceil(array.length / chunkSize))
|
const chunks = Array(Math.ceil(array.length / chunkSize))
|
||||||
.fill(0)
|
.fill(0)
|
||||||
|
|
@ -155,9 +71,8 @@ function processInChunks(array, func, chunkSize) {
|
||||||
.map(begin => array.slice(begin, begin + chunkSize));
|
.map(begin => array.slice(begin, begin + chunkSize));
|
||||||
// Process each chunk
|
// Process each chunk
|
||||||
for (const chunk of chunks) {
|
for (const chunk of chunks) {
|
||||||
yield Promise.all(chunk.map(func));
|
await Promise.all(chunk.map(func));
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
exports.processInChunks = processInChunks;
|
exports.processInChunks = processInChunks;
|
||||||
/**
|
/**
|
||||||
|
|
@ -169,16 +84,14 @@ exports.processInChunks = processInChunks;
|
||||||
* @returns A Promise that resolves when the file has been modified.
|
* @returns A Promise that resolves when the file has been modified.
|
||||||
* @throws An error if there is an error reading or saving the file.
|
* @throws An error if there is an error reading or saving the file.
|
||||||
*/
|
*/
|
||||||
function replaceTextInFile(filePath_1, searchText_1, replacementText_1) {
|
async function replaceTextInFile(filePath, searchText, replacementText, encoding = 'utf8') {
|
||||||
return __awaiter(this, arguments, void 0, function* (filePath, searchText, replacementText, encoding = 'utf8') {
|
|
||||||
// Don't do anything if the search text is empty
|
// Don't do anything if the search text is empty
|
||||||
if (!searchText) {
|
if (!searchText) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const fileContent = yield readFileContent(filePath, encoding);
|
const fileContent = await readFileContent(filePath, encoding);
|
||||||
const updatedContent = fileContent.replace(searchText, replacementText);
|
const updatedContent = fileContent.replaceAll(searchText, replacementText);
|
||||||
yield saveFileContent(filePath, updatedContent);
|
await saveFileContent(filePath, updatedContent);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
exports.replaceTextInFile = replaceTextInFile;
|
exports.replaceTextInFile = replaceTextInFile;
|
||||||
/**
|
/**
|
||||||
|
|
@ -188,16 +101,14 @@ exports.replaceTextInFile = replaceTextInFile;
|
||||||
* @returns A Promise that resolves to the content of the file as a string.
|
* @returns A Promise that resolves to the content of the file as a string.
|
||||||
* @throws An error if there is an error reading the file.
|
* @throws An error if there is an error reading the file.
|
||||||
*/
|
*/
|
||||||
function readFileContent(filePath, encoding) {
|
async function readFileContent(filePath, encoding) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
try {
|
try {
|
||||||
const fileContentBuffer = yield fs_1.default.promises.readFile(filePath, encoding);
|
const fileContentBuffer = await fs_1.default.promises.readFile(filePath, encoding);
|
||||||
return fileContentBuffer.toString();
|
return fileContentBuffer.toString();
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
throw new Error(`Error reading file content: ${error}`);
|
throw new Error(`Error reading file content: ${error}`);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Saves the given content to the file at the given path.
|
* Saves the given content to the file at the given path.
|
||||||
|
|
@ -206,15 +117,13 @@ function readFileContent(filePath, encoding) {
|
||||||
* @returns A Promise that resolves when the file has been saved.
|
* @returns A Promise that resolves when the file has been saved.
|
||||||
* @throws An error if there is an error saving the file.
|
* @throws An error if there is an error saving the file.
|
||||||
*/
|
*/
|
||||||
function saveFileContent(filePath, content) {
|
async function saveFileContent(filePath, content) {
|
||||||
return __awaiter(this, void 0, void 0, function* () {
|
|
||||||
try {
|
try {
|
||||||
yield fs_1.default.promises.writeFile(filePath, content);
|
await fs_1.default.promises.writeFile(filePath, content);
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
throw new Error(`Error saving file content: ${error}`);
|
throw new Error(`Error saving file content: ${error}`);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -11088,13 +10997,68 @@ exports.LRUCache = LRUCache;
|
||||||
/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";
|
/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/";
|
||||||
/******/
|
/******/
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/******/
|
var __webpack_exports__ = {};
|
||||||
/******/ // startup
|
// This entry need to be wrapped in an IIFE because it need to be in strict mode.
|
||||||
/******/ // Load entry module and return exports
|
(() => {
|
||||||
/******/ // This entry module is referenced by other modules so it can't be inlined
|
"use strict";
|
||||||
/******/ var __webpack_exports__ = __nccwpck_require__(3109);
|
var exports = __webpack_exports__;
|
||||||
/******/ module.exports = __webpack_exports__;
|
|
||||||
/******/
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
||||||
|
const core_1 = __nccwpck_require__(2186);
|
||||||
|
const utils_1 = __nccwpck_require__(918);
|
||||||
|
// Entry point for the action
|
||||||
|
async function run() {
|
||||||
|
try {
|
||||||
|
// Get the input parameters
|
||||||
|
const filesPattern = (0, core_1.getInput)('files');
|
||||||
|
const searchText = (0, core_1.getInput)('search-text');
|
||||||
|
const replaceText = (0, core_1.getInput)('replacement-text');
|
||||||
|
const excludePattern = (0, core_1.getInput)('exclude');
|
||||||
|
const inputEncoding = (0, core_1.getInput)('encoding');
|
||||||
|
const maxParallelism = (0, core_1.getInput)('max-parallelism');
|
||||||
|
// Validate the encoding
|
||||||
|
if (!(0, utils_1.isValidEncoding)(inputEncoding)) {
|
||||||
|
throw new Error(`Invalid encoding: ${inputEncoding}`);
|
||||||
|
}
|
||||||
|
// Validate that maxParallelism is a positive integer
|
||||||
|
if (!(0, utils_1.isPositiveInteger)(maxParallelism)) {
|
||||||
|
throw new Error(`Invalid max-parallelism: ${maxParallelism}`);
|
||||||
|
}
|
||||||
|
// Get the file paths that match the files pattern and do not match the exclude pattern
|
||||||
|
const filePaths = await (0, utils_1.getFiles)(filesPattern, excludePattern);
|
||||||
|
// If no file paths were found, log a warning and exit
|
||||||
|
if (filePaths.length === 0) {
|
||||||
|
(0, core_1.warning)(`No files found for the given pattern.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
(0, core_1.info)(`Found ${filePaths.length} files for the given pattern.`);
|
||||||
|
(0, core_1.info)(`Replacing "${searchText}" with "${replaceText}".`);
|
||||||
|
// Process the file paths in chunks, replacing the search text with the replace text in each file
|
||||||
|
// This is done to avoid opening too many files at once
|
||||||
|
const encoding = inputEncoding;
|
||||||
|
const chunkSize = parseInt(maxParallelism);
|
||||||
|
await (0, utils_1.processInChunks)(filePaths, async (filePath) => {
|
||||||
|
(0, core_1.info)(`Replacing text in file ${filePath}`);
|
||||||
|
await (0, utils_1.replaceTextInFile)(filePath, searchText, replaceText, encoding);
|
||||||
|
}, chunkSize);
|
||||||
|
(0, core_1.info)(`Done!`);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
if (err instanceof Error) {
|
||||||
|
(0, core_1.setFailed)(err.message);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const errorMessage = 'An error occurred. Run in debug mode for additional info.';
|
||||||
|
(0, core_1.debug)(`${JSON.stringify(err)}`);
|
||||||
|
(0, core_1.setFailed)(errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
run();
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
module.exports = __webpack_exports__;
|
||||||
/******/ })()
|
/******/ })()
|
||||||
;
|
;
|
||||||
//# sourceMappingURL=index.js.map
|
//# sourceMappingURL=index.js.map
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -94,7 +94,7 @@ export async function replaceTextInFile(
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileContent = await readFileContent(filePath, encoding);
|
const fileContent = await readFileContent(filePath, encoding);
|
||||||
const updatedContent = fileContent.replace(searchText, replacementText);
|
const updatedContent = fileContent.replaceAll(searchText, replacementText);
|
||||||
await saveFileContent(filePath, updatedContent);
|
await saveFileContent(filePath, updatedContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,4 @@ Hello world!
|
||||||
This should be twenty-three: 23.
|
This should be twenty-three: 23.
|
||||||
This line has been changed: false.
|
This line has been changed: false.
|
||||||
This value comes from environment variables: environment
|
This value comes from environment variables: environment
|
||||||
|
Multiple occurrences in the same file: world
|
||||||
|
|
|
||||||
|
|
@ -3,3 +3,4 @@ Hello {0}!
|
||||||
This should be twenty-three: 23.
|
This should be twenty-three: 23.
|
||||||
This line has been changed: false.
|
This line has been changed: false.
|
||||||
This value comes from environment variables: _ENV_
|
This value comes from environment variables: _ENV_
|
||||||
|
Multiple occurrences in the same file: {0}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
"alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
"target": "ES2021", /* Specify ECMAScript target version. */
|
||||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||||
"outDir": "./lib", /* Redirect output structure to the directory. */
|
"outDir": "./lib", /* Redirect output structure to the directory. */
|
||||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue