index.js 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. 'use strict';
  2. const Transform = require('stream').Transform;
  3. const rs = require('replacestream');
  4. const istextorbinary = require('istextorbinary');
  5. const defaultOptions = {
  6. skipBinary: true
  7. }
  8. module.exports = function(search, _replacement, options = {}) {
  9. // merge options
  10. options = {
  11. ...defaultOptions,
  12. ...options
  13. }
  14. return new Transform({
  15. objectMode: true,
  16. /**
  17. * transformation
  18. * @param {import("vinyl")} file
  19. * @param {BufferEncoding} enc
  20. * @param {(error?: Error | null, data?: any) => void} callback
  21. */
  22. transform(file, enc, callback) {
  23. if (file.isNull()) {
  24. return callback(null, file);
  25. }
  26. let replacement = _replacement;
  27. if (typeof _replacement === 'function') {
  28. // Pass the vinyl file object as this.file
  29. replacement = _replacement.bind({ file: file });
  30. }
  31. function doReplace() {
  32. if (file.isStream()) {
  33. file.contents = file.contents.pipe(rs(search, replacement));
  34. return callback(null, file);
  35. }
  36. if (file.isBuffer()) {
  37. if (search instanceof RegExp) {
  38. file.contents = Buffer.from(String(file.contents).replace(search, replacement));
  39. } else {
  40. const chunks = String(file.contents).split(search);
  41. let result;
  42. if (typeof replacement === 'function') {
  43. // Start with the first chunk already in the result
  44. // Replacements will be added thereafter
  45. // This is done to avoid checking the value of i in the loop
  46. result = [ chunks[0] ];
  47. // The replacement function should be called once for each match
  48. for (let i = 1; i < chunks.length; i++) {
  49. // Add the replacement value
  50. result.push(replacement(search));
  51. // Add the next chunk
  52. result.push(chunks[i]);
  53. }
  54. result = result.join('');
  55. }
  56. else {
  57. result = chunks.join(replacement);
  58. }
  59. file.contents = Buffer.from(result);
  60. }
  61. return callback(null, file);
  62. }
  63. callback(null, file);
  64. }
  65. if (options.skipBinary) {
  66. if (!istextorbinary.isText(file.path, file.contents)) {
  67. callback(null, file);
  68. } else {
  69. doReplace();
  70. }
  71. return;
  72. }
  73. doReplace();
  74. }
  75. });
  76. };