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