index.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*!
  2. * strip-comments <https://github.com/jonschlinkert/strip-comments>
  3. *
  4. * Copyright (c) 2014-2016, 2018, Jon Schlinkert.
  5. * Released under the MIT License.
  6. */
  7. 'use strict';
  8. const assign = Object.assign;
  9. const extract = require('babel-extract-comments');
  10. /**
  11. * Strip all code comments from the given `input`, including protected
  12. * comments that start with `!`, unless disabled by setting `options.keepProtected`
  13. * to true.
  14. *
  15. * ```js
  16. * const str = strip('const foo = "bar";// this is a comment\n /* me too *\/');
  17. * console.log(str);
  18. * // => 'const foo = "bar";'
  19. * ```
  20. * @name strip
  21. * @param {String} `input` string from which to strip comments
  22. * @param {Object} `options` optional options, passed to [extract-comments][extract-comments]
  23. * @option {Boolean} [options] `line` if `false` strip only block comments, default `true`
  24. * @option {Boolean} [options] `block` if `false` strip only line comments, default `true`
  25. * @option {Boolean} [options] `keepProtected` Keep ignored comments (e.g. `/*!` and `//!`)
  26. * @option {Boolean} [options] `preserveNewlines` Preserve newlines after comments are stripped
  27. * @return {String} modified input
  28. * @api public
  29. */
  30. function strip(input, options) {
  31. return stripComments(input, assign({ block: true, line: true }, options));
  32. }
  33. /**
  34. * Strip only block comments.
  35. *
  36. * ```js
  37. * const strip = require('..');
  38. * const str = strip.block('const foo = "bar";// this is a comment\n /* me too *\/');
  39. * console.log(str);
  40. * // => 'const foo = "bar";// this is a comment'
  41. * ```
  42. * @name .block
  43. * @param {String} `input` string from which to strip comments
  44. * @param {Object} `options` pass `opts.keepProtected: true` to keep ignored comments (e.g. `/*!`)
  45. * @return {String} modified string
  46. * @api public
  47. */
  48. strip.block = function(input, options) {
  49. return stripComments(input, assign({ block: true }, options));
  50. };
  51. /**
  52. * Strip only line comments.
  53. *
  54. * ```js
  55. * const str = strip.line('const foo = "bar";// this is a comment\n /* me too *\/');
  56. * console.log(str);
  57. * // => 'const foo = "bar";\n/* me too *\/'
  58. * ```
  59. * @name .line
  60. * @param {String} `input` string from which to strip comments
  61. * @param {Object} `options` pass `opts.keepProtected: true` to keep ignored comments (e.g. `//!`)
  62. * @return {String} modified string
  63. * @api public
  64. */
  65. strip.line = function(input, options) {
  66. return stripComments(input, assign({ line: true }, options));
  67. };
  68. /**
  69. * Strip the first comment from the given `input`. Or, if `opts.keepProtected` is true,
  70. * the first non-protected comment will be stripped.
  71. *
  72. * ```js
  73. * const output = strip.first(input, { keepProtected: true });
  74. * console.log(output);
  75. * // => '//! first comment\nfoo; '
  76. * ```
  77. * @name .first
  78. * @param {String} `input`
  79. * @param {Object} `options` pass `opts.keepProtected: true` to keep comments with `!`
  80. * @return {String}
  81. * @api public
  82. */
  83. strip.first = function(input, options) {
  84. const opts = assign({ block: true, line: true, first: true }, options);
  85. return stripComments(input, opts);
  86. };
  87. /**
  88. * Strip comments
  89. */
  90. function stripComments(input, options) {
  91. if (typeof input !== 'string') {
  92. throw new TypeError('expected a string');
  93. }
  94. // strip all by default, including `ingored` comments.
  95. const defaults = {
  96. // we shouldn't care about this here since our goal is to strip comments,
  97. // not transpiling, and this has been a common cause of parsing issues
  98. allowReturnOutsideFunction: true,
  99. block: false,
  100. line: false,
  101. safe: false,
  102. first: false,
  103. plugins: []
  104. };
  105. const opts = assign({}, defaults, options);
  106. opts.plugins.push('objectRestSpread');
  107. if (typeof opts.keepProtected !== 'boolean') {
  108. opts.keepProtected = opts.safe;
  109. }
  110. try {
  111. const comments = extract(input, opts);
  112. let pos = { start: 0, end: 0, removed: 0 };
  113. if (!comments) return input;
  114. for (const comment of comments) {
  115. if (typeof opts.filter === 'function' && opts.filter(comment, opts) === false) {
  116. continue;
  117. }
  118. input = remove(input, comment, opts, pos);
  119. if (opts.first === true && !isProtected(comment, opts)) {
  120. break;
  121. }
  122. }
  123. } catch (err) {
  124. if (options.silent !== true) {
  125. throw err;
  126. }
  127. }
  128. return input;
  129. }
  130. /**
  131. * Remove a single comment from the given string.
  132. */
  133. function remove(str, comment, options, pos) {
  134. let nl = '';
  135. if (isProtected(comment, options)) {
  136. return str;
  137. }
  138. if (options && options.preserveNewlines) {
  139. nl = comment.value.replace(/[^\r\n]/g, '');
  140. }
  141. if (comment.type === 'CommentLine' && options.line === true) {
  142. const before = str.slice(0, comment.start - pos.removed);
  143. const after = str.slice(comment.end - pos.removed);
  144. pos.removed += comment.end - comment.start - nl.length;
  145. return before + nl + after;
  146. }
  147. if (comment.type === 'CommentBlock' && options.block === true) {
  148. const before = str.slice(0, comment.start - pos.removed);
  149. const after = str.slice(comment.end - pos.removed);
  150. pos.removed += comment.end - comment.start - nl.length;
  151. return before + nl + after;
  152. }
  153. return str;
  154. }
  155. function isProtected(comment, options) {
  156. return options && options.keepProtected === true && /^\*?!/.test(comment.value);
  157. }
  158. module.exports = strip;