@frsource/frs-replace 4.1.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -201
- package/README.md +181 -236
- package/bin/cli.mjs +213 -0
- package/dist/async.d.ts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/sync.d.ts +3 -0
- package/dist/types.d.ts +27 -0
- package/dist/utils.d.ts +3 -0
- package/package.json +64 -42
- package/CHANGELOG.md +0 -186
- package/async.js +0 -1
- package/bin/cli.js +0 -148
- package/index.js +0 -4
- package/src/async.js +0 -104
- package/src/sync.js +0 -88
- package/src/utils.js +0 -22
- package/sync.js +0 -1
- package/yarn.lock +0 -4743
package/bin/cli.js
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
const replaceSync = require('../sync');
|
|
3
|
-
|
|
4
|
-
(
|
|
5
|
-
~process.argv.indexOf('--no-stdin')
|
|
6
|
-
? Promise.resolve()
|
|
7
|
-
: require('get-stdin')()
|
|
8
|
-
).then((stdin) => {
|
|
9
|
-
const isPiped = !!stdin
|
|
10
|
-
|
|
11
|
-
if (isPiped) {
|
|
12
|
-
process.argv.push('-c')
|
|
13
|
-
process.argv.push(stdin) // threat piped data as value for --content option
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const isContentPresent = ~process.argv.indexOf('--content') || ~process.argv.indexOf('-c')
|
|
17
|
-
const isHelpPresent = ~process.argv.indexOf('--help') || ~process.argv.indexOf('-h')
|
|
18
|
-
|
|
19
|
-
const argv = require('yargs')
|
|
20
|
-
.parserConfiguration({
|
|
21
|
-
'camel-case-expansion': false
|
|
22
|
-
})
|
|
23
|
-
.scriptName('frs-replace')
|
|
24
|
-
.usage('$0 <needle> <replacement> [options]', 'Replace matching parts of string with replacement string/function', (yargs) => {
|
|
25
|
-
yargs
|
|
26
|
-
.positional('needle', {
|
|
27
|
-
describe: 'String which is passed as a first parameter to RegExp constructor',
|
|
28
|
-
type: 'string',
|
|
29
|
-
demand: true
|
|
30
|
-
})
|
|
31
|
-
.positional('replacement', {
|
|
32
|
-
describe: 'String or path to replacement function file (see --replace-fn switch for details)',
|
|
33
|
-
type: 'string',
|
|
34
|
-
demand: true
|
|
35
|
-
})
|
|
36
|
-
.example('$0 a b -i foo.js -o foo_replaced.js',
|
|
37
|
-
'Replaces all "a" occurences with "b" from given foo.js and save result to foo_replaced.js')
|
|
38
|
-
.example('<read file> | $0 a b > <output-file-path>',
|
|
39
|
-
'Replaces all "a" occurences with "b" from stream and save it to output file')
|
|
40
|
-
.example('<read file> | $0 a b | <next-command>',
|
|
41
|
-
'Replaces all "a" occurences with "b" from stream and pass it through the stream to next command')
|
|
42
|
-
.example('$0 a b -i foo.js | <next-command>',
|
|
43
|
-
'Both pipe & options styles can be mixed together, here - getting input from "i" argument and passing output down the stream to next command')
|
|
44
|
-
.example('$0 a b --content abcd -o foo_replaced.js',
|
|
45
|
-
'Replace all "a" occurences with "b" in given "abcd" and save result (which is "bbcd") to foo_replaced.js')
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
.option('f')
|
|
49
|
-
.alias('f', 'flags')
|
|
50
|
-
.describe('f', 'RegExp flags used together with `needle` positional (supporting g, i & m)')
|
|
51
|
-
.nargs('f', 1)
|
|
52
|
-
.choices('f', ['', 'g', 'm', 'i', 'gm', 'gi', 'mi', 'mg', 'ig', 'im', 'gmi', 'gim', 'mig', 'mgi', 'igm', 'img'])
|
|
53
|
-
.default('f', 'g')
|
|
54
|
-
.coerce('f', arg => arg.trim())
|
|
55
|
-
.option('i', { demandOption: !isContentPresent && !isHelpPresent })
|
|
56
|
-
.alias('i', 'input')
|
|
57
|
-
.describe('i', 'Path to files or fast-glob pattern pointing to files to read & replace from')
|
|
58
|
-
.array('i')
|
|
59
|
-
|
|
60
|
-
.option('i-read-opts')
|
|
61
|
-
.describe('i-read-opts', 'Passed to fs.readFileSync when reading input file')
|
|
62
|
-
.default('i-read-opts', undefined, 'utf8') // will use node's default value
|
|
63
|
-
.implies('i-read-opts', 'i')
|
|
64
|
-
|
|
65
|
-
.option('i-glob-opts')
|
|
66
|
-
.describe('i-glob-opts', 'Passed to fast-glob.sync when resolving glob patterns')
|
|
67
|
-
.implies('i-glob-opts', 'i')
|
|
68
|
-
|
|
69
|
-
.option('stdin')
|
|
70
|
-
.describe('stdin', 'Wait for stdin input (should be set to false when used in non-interactive terminals)')
|
|
71
|
-
.boolean('stdin')
|
|
72
|
-
.default('stdin', true)
|
|
73
|
-
|
|
74
|
-
.option('c', { demandOption: isContentPresent })
|
|
75
|
-
.alias('c', 'content')
|
|
76
|
-
.describe('c', 'Content to be replaced (takes precedence over stream & file input)')
|
|
77
|
-
.string('c')
|
|
78
|
-
.nargs('c', 1)
|
|
79
|
-
|
|
80
|
-
.option('s')
|
|
81
|
-
.alias('s', 'strategy')
|
|
82
|
-
.describe('s', `output file generation strategy.
|
|
83
|
-
\`join\` - join all input files and saves single file using "output" option as it's path,
|
|
84
|
-
\`preserve-structure\` - when replacing files content copies them over to the directory specified by "output" option.
|
|
85
|
-
\`flatten\` - same as \`preserve-structure\` but flattens the directory structure`)
|
|
86
|
-
.nargs('s', 1)
|
|
87
|
-
.choices('s', ['join', 'flatten', 'preserve-structure'])
|
|
88
|
-
.default('s', 'join')
|
|
89
|
-
.coerce('s', arg => arg.trim())
|
|
90
|
-
|
|
91
|
-
.option('o')
|
|
92
|
-
.alias('o', 'output')
|
|
93
|
-
.describe('o', 'Output file name/path (replaces the file if it already exists and creates any intermediate directories if they don\'t already exist) or (when used together with `strategy` = `flatten` or `preserve-structure`) path to the output directory')
|
|
94
|
-
.string('o')
|
|
95
|
-
.nargs('o', 1)
|
|
96
|
-
|
|
97
|
-
.option('o-write-opts')
|
|
98
|
-
.describe('o-write-opts', 'Passed as options argument of write\'s .sync method')
|
|
99
|
-
.default('o-write-opts', undefined, 'utf8') // will use node's default value
|
|
100
|
-
.implies('o-write-opts', 'o')
|
|
101
|
-
|
|
102
|
-
.option('o-join-str')
|
|
103
|
-
.describe('o-join-str', 'String used when joining multiple files (use it together with either `output` or `stdout` option)')
|
|
104
|
-
.default('o-join-str', undefined, 'newline (\\n)') // will use node's default value
|
|
105
|
-
|
|
106
|
-
.option('stdout')
|
|
107
|
-
.describe('stdout', 'Force sending output on stdout')
|
|
108
|
-
.boolean('stdout')
|
|
109
|
-
.default('stdout', isPiped, 'true when piped input present, false otherwise')
|
|
110
|
-
|
|
111
|
-
.option('r')
|
|
112
|
-
.alias('r', 'replace-fn')
|
|
113
|
-
.describe('r', 'Treat replacement argument as path to file containing replacement function')
|
|
114
|
-
.boolean('r')
|
|
115
|
-
|
|
116
|
-
.help('h')
|
|
117
|
-
.alias('h', 'help')
|
|
118
|
-
|
|
119
|
-
.version('v')
|
|
120
|
-
.alias('v', 'version')
|
|
121
|
-
|
|
122
|
-
.epilog('Brought to you with open-source love by FRSource')
|
|
123
|
-
.argv
|
|
124
|
-
|
|
125
|
-
try {
|
|
126
|
-
const result = replaceSync({
|
|
127
|
-
input: argv.i,
|
|
128
|
-
inputReadOptions: argv['i-read-opts'],
|
|
129
|
-
inputGlobOptions: argv['i-glob-opts'],
|
|
130
|
-
content: argv.c,
|
|
131
|
-
strategy: argv.strategy,
|
|
132
|
-
output: argv.o,
|
|
133
|
-
outputWriteOptions: argv['o-write-opts'],
|
|
134
|
-
outputJoinString: argv['o-join-str'],
|
|
135
|
-
needle: new RegExp(argv.needle, argv.f),
|
|
136
|
-
replacement: argv.r ? require(require('path').resolve(argv.replacement)) : argv.replacement
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
if (argv.stdout) {
|
|
140
|
-
process.stdout.write(result[0][1])
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return process.exit()
|
|
144
|
-
} catch (e) /* istanbul ignore next */ {
|
|
145
|
-
process.stderr.write(e.toString())
|
|
146
|
-
return process.exit(1)
|
|
147
|
-
}
|
|
148
|
-
})
|
package/index.js
DELETED
package/src/async.js
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
const write = require('write')
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
const fastGlob = require('fast-glob')
|
|
5
|
-
const { writeError, getReplaceFn } = require('./utils')
|
|
6
|
-
|
|
7
|
-
const inputStrategyMap = {
|
|
8
|
-
join: (results, outputJoinString) =>
|
|
9
|
-
results.then(results => [
|
|
10
|
-
Promise.all(results).then(results => {
|
|
11
|
-
const len = results.length
|
|
12
|
-
let result = (results[0] && results[0][1]) || ''
|
|
13
|
-
for (let i = 1; i < len; ++i) {
|
|
14
|
-
result += outputJoinString + results[i][1]
|
|
15
|
-
}
|
|
16
|
-
return ['', result]
|
|
17
|
-
})
|
|
18
|
-
]),
|
|
19
|
-
flatten: results =>
|
|
20
|
-
results.then(results => results.map(async result => {
|
|
21
|
-
result = await result
|
|
22
|
-
result[0] = result[0].substring(result[0].lastIndexOf(path.sep))
|
|
23
|
-
return result
|
|
24
|
-
})),
|
|
25
|
-
'preserve-structure': results => results
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const multipleFilesOutput = (results, output, outputWriteOptions) => {
|
|
29
|
-
return results.then(results => results.map(
|
|
30
|
-
async result => {
|
|
31
|
-
result = await result
|
|
32
|
-
result[0] = path.join(output, result[0])
|
|
33
|
-
await write(result[0], result[1], outputWriteOptions)
|
|
34
|
-
return result
|
|
35
|
-
}
|
|
36
|
-
))
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const outputStrategyMap = {
|
|
40
|
-
join: (results, output, outputWriteOptions) =>
|
|
41
|
-
results.then(results => [
|
|
42
|
-
results[0].then(async result => {
|
|
43
|
-
await write(output, result[1], outputWriteOptions)
|
|
44
|
-
result[0] = output
|
|
45
|
-
return result
|
|
46
|
-
})
|
|
47
|
-
]),
|
|
48
|
-
flatten: multipleFilesOutput,
|
|
49
|
-
'preserve-structure': multipleFilesOutput
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
module.exports = async ({
|
|
53
|
-
input,
|
|
54
|
-
inputReadOptions = 'utf8',
|
|
55
|
-
inputGlobOptions,
|
|
56
|
-
content,
|
|
57
|
-
strategy = 'join',
|
|
58
|
-
output,
|
|
59
|
-
outputWriteOptions = 'utf8',
|
|
60
|
-
outputJoinString = '\n',
|
|
61
|
-
needle,
|
|
62
|
-
replacement
|
|
63
|
-
}) => {
|
|
64
|
-
let results
|
|
65
|
-
const replaceFn = getReplaceFn(needle, replacement)
|
|
66
|
-
|
|
67
|
-
if (content !== undefined) {
|
|
68
|
-
results = Promise.resolve([['', replaceFn(content)]])
|
|
69
|
-
} else if (input !== undefined) {
|
|
70
|
-
const fileStream = fastGlob.stream(input, inputGlobOptions)
|
|
71
|
-
const replacePromises = []
|
|
72
|
-
|
|
73
|
-
fileStream.on('error', writeError)
|
|
74
|
-
fileStream.on('data', path => replacePromises.push(new Promise((resolve, reject) =>
|
|
75
|
-
fs.readFile(path, inputReadOptions, (error, data) => {
|
|
76
|
-
/* istanbul ignore next */
|
|
77
|
-
if (error) return reject(error)
|
|
78
|
-
|
|
79
|
-
resolve([path, replaceFn(data)])
|
|
80
|
-
})
|
|
81
|
-
)))
|
|
82
|
-
results = new Promise(resolve =>
|
|
83
|
-
fileStream.once('end', () =>
|
|
84
|
-
resolve(replacePromises)
|
|
85
|
-
)
|
|
86
|
-
).catch(writeError)
|
|
87
|
-
} else {
|
|
88
|
-
writeError('at least one input source must be defined!')
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
if (!inputStrategyMap[strategy]) writeError('unsupported strategy used! Possible values are: "join", "preserve-structure" or "flatten"')
|
|
92
|
-
results = inputStrategyMap[strategy](results, outputJoinString)
|
|
93
|
-
|
|
94
|
-
if (output !== undefined) {
|
|
95
|
-
output = path.normalize(output)
|
|
96
|
-
if (typeof outputWriteOptions === 'string') {
|
|
97
|
-
outputWriteOptions = { encoding: outputWriteOptions }
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
results = outputStrategyMap[strategy](results, output, outputWriteOptions)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return results
|
|
104
|
-
}
|
package/src/sync.js
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
const write = require('write')
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
const fastGlob = require('fast-glob')
|
|
5
|
-
|
|
6
|
-
const { writeError, getReplaceFn } = require('./utils')
|
|
7
|
-
|
|
8
|
-
const inputStrategyMap = {
|
|
9
|
-
join: (results, len, outputJoinString) => {
|
|
10
|
-
let result = (results[0] && results[0][1]) || ''
|
|
11
|
-
for (let i = 1; i < len; ++i) {
|
|
12
|
-
result += outputJoinString + results[i][1]
|
|
13
|
-
}
|
|
14
|
-
return [[['', result]], 1]
|
|
15
|
-
},
|
|
16
|
-
flatten: (results, len) => {
|
|
17
|
-
for (let i = 0; i < len; ++i) {
|
|
18
|
-
const result = results[i]
|
|
19
|
-
result[0] = result[0].substring(result[0].lastIndexOf(path.sep))
|
|
20
|
-
}
|
|
21
|
-
return [results, len]
|
|
22
|
-
},
|
|
23
|
-
'preserve-structure': (...args) => args
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const multipleFilesOutputStrategy = (results, len, output, outputWriteOptions) => {
|
|
27
|
-
for (let i = 0; i < len; ++i) {
|
|
28
|
-
const result = results[i]
|
|
29
|
-
result[0] = path.join(output, result[0])
|
|
30
|
-
write.sync(result[0], result[1], outputWriteOptions)
|
|
31
|
-
}
|
|
32
|
-
return results
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const outputStrategyMap = {
|
|
36
|
-
join: (results, len, output, outputWriteOptions) => {
|
|
37
|
-
write.sync(output, results[0][1], outputWriteOptions)
|
|
38
|
-
results[0][0] = output
|
|
39
|
-
return results
|
|
40
|
-
},
|
|
41
|
-
flatten: multipleFilesOutputStrategy,
|
|
42
|
-
'preserve-structure': multipleFilesOutputStrategy
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
module.exports = ({
|
|
46
|
-
input,
|
|
47
|
-
inputReadOptions = 'utf8',
|
|
48
|
-
inputGlobOptions,
|
|
49
|
-
content,
|
|
50
|
-
strategy = 'join',
|
|
51
|
-
output,
|
|
52
|
-
outputWriteOptions = 'utf8',
|
|
53
|
-
outputJoinString = '\n',
|
|
54
|
-
needle,
|
|
55
|
-
replacement
|
|
56
|
-
}) => {
|
|
57
|
-
let results
|
|
58
|
-
const replaceFn = getReplaceFn(needle, replacement)
|
|
59
|
-
|
|
60
|
-
if (content !== undefined) {
|
|
61
|
-
results = [['', replaceFn(content)]]
|
|
62
|
-
} else if (input !== undefined) {
|
|
63
|
-
results = []
|
|
64
|
-
const files = fastGlob.sync(input, inputGlobOptions)
|
|
65
|
-
const len = files.length
|
|
66
|
-
for (let i = 0; i < len; ++i) {
|
|
67
|
-
const filePath = files[i]
|
|
68
|
-
results.push([filePath, replaceFn(fs.readFileSync(filePath, inputReadOptions))])
|
|
69
|
-
}
|
|
70
|
-
} else {
|
|
71
|
-
writeError('at least one input source must be defined!')
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
let len
|
|
75
|
-
if (!inputStrategyMap[strategy]) writeError('unsupported strategy used! Possible values are: "join", "preserve-structure" or "flatten"');
|
|
76
|
-
[results, len] = inputStrategyMap[strategy](results, results.length, outputJoinString)
|
|
77
|
-
|
|
78
|
-
if (output !== undefined) {
|
|
79
|
-
output = path.normalize(output)
|
|
80
|
-
if (typeof outputWriteOptions === 'string') {
|
|
81
|
-
outputWriteOptions = { encoding: outputWriteOptions }
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
results = outputStrategyMap[strategy](results, len, output, outputWriteOptions)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return results
|
|
88
|
-
}
|
package/src/utils.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
const writeError = msg => { throw new Error(`@frsource/frs-replace :: ${msg}`) }
|
|
2
|
-
|
|
3
|
-
const getReplaceFn = (needle, replacement) =>
|
|
4
|
-
typeof needle === 'string'
|
|
5
|
-
? content => {
|
|
6
|
-
const needleLen = needle.length
|
|
7
|
-
let result = ''
|
|
8
|
-
let i
|
|
9
|
-
let endIndex = 0
|
|
10
|
-
|
|
11
|
-
while ((i = content.indexOf(needle, endIndex)) !== -1) {
|
|
12
|
-
result += content.slice(endIndex, i) + replacement
|
|
13
|
-
endIndex = i + needleLen
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
result += content.slice(endIndex, content.length)
|
|
17
|
-
|
|
18
|
-
return result
|
|
19
|
-
}
|
|
20
|
-
: content => content.replace(needle, replacement)
|
|
21
|
-
|
|
22
|
-
module.exports = { writeError, getReplaceFn }
|
package/sync.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = require('./src/sync')
|