diff --git a/.github/workflows/test-replace-tokens-action.yml b/.github/workflows/test-replace-tokens-action.yml index 0e8f8bb..20363b8 100644 --- a/.github/workflows/test-replace-tokens-action.yml +++ b/.github/workflows/test-replace-tokens-action.yml @@ -1,8 +1,6 @@ name: Test Action (Replace Tokens) on: - pull_request: - branches: [ main ] workflow_dispatch: jobs: @@ -34,6 +32,8 @@ jobs: npm run build --if-present npm test + # Readme Examples + - name: Replace Tokens ( <<<< Example 1 - Replace a token in a file. >>>> ) uses: abhinavminhas/replace-tokens@main with: diff --git a/README.md b/README.md index 963a616..9df43a2 100644 --- a/README.md +++ b/README.md @@ -12,9 +12,13 @@ - **Example:** ``` file1, file2 ``` - `replacements` **(Required)** - Token (to be replaced) & value comma-separated pairs (TOKEN=value). - **Example:** ``` key1=value1, key2=value2 ``` - - **Note:** _Values can be variables/secrets._ + - **Note:** + - _key & value pairs ignore leading & trailing whitespaces. Enclose within ```[]``` for such expressions._ + - _key (token) cannot have any ```=``` but value can. Use a different key (token) in such case._ + - _key, value or pairs can be CI/CD variables / secrets._ - `delimiter` **(Optional)** - Defines separator/delimiter to be used, default value is comma (``` , ```). - **Example:** ``` | ``` or ``` ; ``` or ``` : ``` or ``` - ``` etc. + - **Note:** _Ignores whitespaces._ ## Usage @@ -54,8 +58,7 @@ replacements: key1=value1, key2=value2 ``` -- **Example 5:** _Use a different separator than comma (``` , ```). Important use case is when the token to be replaced is itself a comma or contains a comma._ - - **Note:** _The delimiter is enclosed within single quotation marks in the below example since yml interprets | as "Literal Block Scalar", also required for other reserved keywords._ +- **Example 5:** _Use a different separator than comma (``` , ```)._ ``` - name: Replace Tokens uses: abhinavminhas/replace-tokens@main @@ -64,5 +67,6 @@ replacements: key1=value1 | key2=value2 delimiter: '|' ``` + - **Note:** _The delimiter is enclosed within single quotation marks in the above example since yml interprets ```|``` as "Literal Block Scalar", also required for other reserved keywords._ **Note:** _Implementation for above examples can be checked [here](https://github.com/abhinavminhas/replace-tokens/blob/main/.github/workflows/test-replace-tokens-action.yml)._ \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 38c2eaa..2e83376 100644 --- a/dist/index.js +++ b/dist/index.js @@ -2712,16 +2712,16 @@ exports["default"] = _default; const fs = __nccwpck_require__(147) async function replaceTokens(files, replacements, delimiter = ',') { - if (delimiter === null || delimiter === undefined || delimiter.length <= 0) { + if (delimiter === null || delimiter === undefined || delimiter.replace(/\s/g, '').length <= 0) { delimiter = ',' } else { delimiter = delimiter.replace(/\s/g, '') } - const fileNames = files.replace(/\s/g, '').split(delimiter) - const replacementValues = replacements.replace(/\s/g, '').split(delimiter) + const fileNames = files.split(delimiter).map(x => x.trim()) + const replacementValues = replacements.split(delimiter) console.log(`Total Files: ${fileNames.length}`) for (let file = 1; file <= fileNames.length; file++) { - let fileName = fileNames[file - 1] + const fileName = fileNames[file - 1] console.log(`File ${file}: ${fileName}`) let result = '' try { @@ -2731,10 +2731,15 @@ async function replaceTokens(files, replacements, delimiter = ',') { throw err } for (let i = 0; i < replacementValues.length; i++) { - let keyValuePair = replacementValues[i].split('=') - let key = keyValuePair[0] - let value = keyValuePair[1] - result = result.replace(key, value) + let [key, ...value] = replacementValues[i].split('=') + const keyValuePair = [key, value.join('=')] + if (keyValuePair.length === 2){ + let key = keyValuePair[0] ? keyValuePair[0].trim() : keyValuePair[0] + key = (key.match(/^\[/) && key.match(/\]$/)) ? key.slice(1, -1) : key + let value = keyValuePair[1] ? keyValuePair[1].trim() : keyValuePair[1] + value = (value.match(/^\[/) && value.match(/\]$/)) ? value.slice(1, -1) : value + result = result.replace(key, value) + } } console.log(`File ${file} (Replaced): ${fileName}`) try { diff --git a/src/replace.js b/src/replace.js index e4eaa7d..113eb3a 100644 --- a/src/replace.js +++ b/src/replace.js @@ -3,16 +3,16 @@ const fs = require('fs') async function replaceTokens(files, replacements, delimiter = ',') { - if (delimiter === null || delimiter === undefined || delimiter.length <= 0) { + if (delimiter === null || delimiter === undefined || delimiter.replace(/\s/g, '').length <= 0) { delimiter = ',' } else { delimiter = delimiter.replace(/\s/g, '') } - const fileNames = files.replace(/\s/g, '').split(delimiter) - const replacementValues = replacements.replace(/\s/g, '').split(delimiter) + const fileNames = files.split(delimiter).map(x => x.trim()) + const replacementValues = replacements.split(delimiter) console.log(`Total Files: ${fileNames.length}`) for (let file = 1; file <= fileNames.length; file++) { - let fileName = fileNames[file - 1] + const fileName = fileNames[file - 1] console.log(`File ${file}: ${fileName}`) let result = '' try { @@ -22,10 +22,15 @@ async function replaceTokens(files, replacements, delimiter = ',') { throw err } for (let i = 0; i < replacementValues.length; i++) { - let keyValuePair = replacementValues[i].split('=') - let key = keyValuePair[0] - let value = keyValuePair[1] - result = result.replace(key, value) + let [key, ...value] = replacementValues[i].split('=') + const keyValuePair = [key, value.join('=')] + if (keyValuePair.length === 2){ + let key = keyValuePair[0] ? keyValuePair[0].trim() : keyValuePair[0] + key = (key.match(/^\[/) && key.match(/\]$/)) ? key.slice(1, -1) : key + let value = keyValuePair[1] ? keyValuePair[1].trim() : keyValuePair[1] + value = (value.match(/^\[/) && value.match(/\]$/)) ? value.slice(1, -1) : value + result = result.replace(key, value) + } } console.log(`File ${file} (Replaced): ${fileName}`) try { diff --git a/test/replace.test.js b/test/replace.test.js index abb054f..545df61 100644 --- a/test/replace.test.js +++ b/test/replace.test.js @@ -28,6 +28,8 @@ before(async () => { fs.writeFileSync('./test/test-files/multiple_files_mutiple_tokens/file3.yml', content) content = 'name=file4\r\nkey=_KEY_\r\nsecret=_SECRET_' fs.writeFileSync('./test/test-files/multiple_files_mutiple_tokens/file4.txt', content) + content = '....' + fs.writeFileSync('./test/test-files/replacement_value_has_equal_to.txt', content) }) describe('REPLACE TOKENS TESTS', () => { @@ -146,30 +148,70 @@ describe('REPLACE TOKENS TESTS', () => { }) it('Test 7: Replace token, separator is null.', async () => { - await replace.replaceTokens('./test/test-files/single_file_replace_single_token.txt', "?=.", null) + await replace.replaceTokens('./test/test-files/single_file_replace_single_token.txt', ".=*", null) const data = fs.readFileSync('./test/test-files/single_file_replace_single_token.txt', 'utf8') expect(data).to.not.be.equals(undefined) - expect(data.includes('?')).to.be.equals(false) - expect(data.includes('.')).to.be.equals(true) + expect(data.includes('.')).to.be.equals(false) + expect(data.includes('*')).to.be.equals(true) }) it('Test 8: Replace token, separator is undefined.', async () => { - await replace.replaceTokens('./test/test-files/single_file_replace_single_token.txt', "?=.", undefined) + await replace.replaceTokens('./test/test-files/single_file_replace_single_token.txt', "*=;", undefined) const data = fs.readFileSync('./test/test-files/single_file_replace_single_token.txt', 'utf8') expect(data).to.not.be.equals(undefined) - expect(data.includes('?')).to.be.equals(false) - expect(data.includes('.')).to.be.equals(true) + expect(data.includes('*')).to.be.equals(false) + expect(data.includes(';')).to.be.equals(true) }) it('Test 9: Replace token, separator is blank.', async () => { - await replace.replaceTokens('./test/test-files/single_file_replace_single_token.txt', "?=.", '') + await replace.replaceTokens('./test/test-files/single_file_replace_single_token.txt', ";=#", '') + const data = fs.readFileSync('./test/test-files/single_file_replace_single_token.txt', 'utf8') + expect(data).to.not.be.equals(undefined) + expect(data.includes(';')).to.be.equals(false) + expect(data.includes('#')).to.be.equals(true) + }) + + it('Test 10: Replace token, separator is whitespaces.', async () => { + await replace.replaceTokens('./test/test-files/single_file_replace_single_token.txt', "#=::", ' ') + const data = fs.readFileSync('./test/test-files/single_file_replace_single_token.txt', 'utf8') + expect(data).to.not.be.equals(undefined) + expect(data.includes('#')).to.be.equals(false) + expect(data.includes('::')).to.be.equals(true) + }) + + it('Test 11: Replace token, filename with trailing spaces.', async () => { + await replace.replaceTokens(' ./test/test-files/single_file_replace_single_token.txt ', "::=?", '') + const data = fs.readFileSync('./test/test-files/single_file_replace_single_token.txt', 'utf8') + expect(data).to.not.be.equals(undefined) + expect(data.includes('::')).to.be.equals(false) + expect(data.includes('?')).to.be.equals(true) + }) + + it('Test 12: Replace token, replacement values with trailing spaces and whitespaces.', async () => { + await replace.replaceTokens('./test/test-files/single_file_replace_single_token.txt', "?=[ . . ]", '') const data = fs.readFileSync('./test/test-files/single_file_replace_single_token.txt', 'utf8') expect(data).to.not.be.equals(undefined) expect(data.includes('?')).to.be.equals(false) + expect(data.includes(' . . ')).to.be.equals(true) + }) + + it('Test 13: Replace token, replacement key with trailing spaces and whitespaces.', async () => { + await replace.replaceTokens('./test/test-files/single_file_replace_single_token.txt', "[ . . ]=.", '') + const data = fs.readFileSync('./test/test-files/single_file_replace_single_token.txt', 'utf8') + expect(data).to.not.be.equals(undefined) + expect(data.includes(' .. ')).to.be.equals(false) expect(data.includes('.')).to.be.equals(true) }) - it('Test 10: Replace token, file not found.', async () => { + it('Test 14: Replace token, replacement value has =.', async () => { + await replace.replaceTokens('./test/test-files/replacement_value_has_equal_to.txt', "....=====", '') + const data = fs.readFileSync('./test/test-files/replacement_value_has_equal_to.txt', 'utf8') + expect(data).to.not.be.equals(undefined) + expect(data.includes('....')).to.be.equals(false) + expect(data.includes('====')).to.be.equals(true) + }) + + it('Test 15: Replace token, file not found.', async () => { try { await replace.replaceTokens('./test/test-files/file_not_found.txt', "?=.") assert.fail('No Error') @@ -196,5 +238,6 @@ after(async () => { fs.writeFileSync('./test/test-files/multiple_files_mutiple_tokens/file2.csv', content) fs.writeFileSync('./test/test-files/multiple_files_mutiple_tokens/file3.yml', content) fs.writeFileSync('./test/test-files/multiple_files_mutiple_tokens/file4.txt', content) + fs.writeFileSync('./test/test-files/replacement_value_has_equal_to.txt', content) } }) \ No newline at end of file diff --git a/test/test-files/replacement_value_has_equal_to.txt b/test/test-files/replacement_value_has_equal_to.txt new file mode 100644 index 0000000..e69de29