Skip to content

Commit 1a3d878

Browse files
realitykingMalte Legenhausen
authored andcommitted
Drop support for Node.js < 4; switch from underscore to lodash (html-to-text#150)
* Drop support for Node.js < 4 * Update mocha to version 5 * Update eslint to version 4.18.2 * Replace some uses of underscore with native ES5/ES6 methods. * Switch from underscore to lodash * Fixes html-to-text#13 * Replace underscore.string with native ES5/ES6 methods and lodash.
1 parent b5d0ea1 commit 1a3d878

File tree

7 files changed

+76
-67
lines changed

7 files changed

+76
-67
lines changed

.codeclimate.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ engines:
44
config:
55
languages:
66
- javascript
7-
eslint:
7+
eslint-4:
88
enabled: true
99
fixme:
1010
enabled: true

.eslintrc.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
ecmaFeatures:
2-
modules: true
3-
jsx: false
4-
51
env:
62
amd: false
73
browser: false
@@ -140,7 +136,7 @@ rules:
140136
func-style: 0
141137
id-length: 0
142138
id-match: 0
143-
indent: [2, 2, { "SwitchCase": 1 }]
139+
indent-legacy: [2, 2, { "SwitchCase": 1 }]
144140
jsx-quotes: 0
145141
key-spacing: 0
146142
linebreak-style: 0

.travis.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ after_success:
99

1010
language: node_js
1111
node_js:
12-
- "4.7.3"
13-
- "6.9.5"
12+
- "4"
13+
- "6"
14+
- "8"

lib/formatter.js

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
var _ = require('underscore');
2-
var _s = require('underscore.string');
1+
var max = require('lodash/max');
2+
var compact = require('lodash/compact');
3+
var times = require('lodash/times');
4+
5+
var trimStart = require('lodash/trimStart');
6+
var padEnd = require('lodash/padEnd');
7+
38
var he = require('he');
49

510
var helper = require('./helper');
@@ -11,7 +16,7 @@ function formatText(elem, options) {
1116
if (options.isInPre) {
1217
return text;
1318
} else {
14-
return helper.wordwrap(elem.trimLeadingSpace ? _s.lstrip(text) : text, options);
19+
return helper.wordwrap(elem.trimLeadingSpace ? trimStart(text) : text, options);
1520
}
1621
}
1722

@@ -68,7 +73,7 @@ function formatAnchor(elem, fn, options) {
6873
text = '';
6974
}
7075

71-
var result = elem.trimLeadingSpace ? _s.lstrip(text) : text;
76+
var result = elem.trimLeadingSpace ? trimStart(text) : text;
7277

7378
if (!options.ignoreHref) {
7479
// Get the href, if present
@@ -80,7 +85,7 @@ function formatAnchor(elem, fn, options) {
8085
if (options.linkHrefBaseUrl && href.indexOf('/') === 0) {
8186
href = options.linkHrefBaseUrl + href;
8287
}
83-
if (!options.hideLinkHrefIfSameAsText || href !== _s.replaceAll(result, '\n', '')) {
88+
if (!options.hideLinkHrefIfSameAsText || href !== helper.replaceAll(result, '\n', '')) {
8489
if (!options.noLinkBrackets) {
8590
result += ' [' + href + ']';
8691
} else {
@@ -97,19 +102,19 @@ function formatAnchor(elem, fn, options) {
97102
}
98103

99104
function formatHorizontalLine(elem, fn, options) {
100-
return '\n' + _s.repeat('-', options.wordwrap) + '\n\n';
105+
return '\n' + '-'.repeat(options.wordwrap) + '\n\n';
101106
}
102107

103108
function formatListItem(prefix, elem, fn, options) {
104-
options = _.clone(options);
109+
options = Object.assign({}, options);
105110
// Reduce the wordwrap for sub elements.
106111
if (options.wordwrap) {
107112
options.wordwrap -= prefix.length;
108113
}
109114
// Process sub elements.
110115
var text = fn(elem.children, options);
111116
// Replace all line breaks with line break + prefix spacing.
112-
text = text.replace(/\n/g, '\n' + _s.repeat(' ', prefix.length));
117+
text = text.replace(/\n/g, '\n' + ' '.repeat(prefix.length));
113118
// Add first prefix and line break at the end.
114119
return prefix + text + '\n';
115120
}
@@ -122,7 +127,7 @@ function formatUnorderedList(elem, fn, options) {
122127
var nonWhiteSpaceChildren = (elem.children || []).filter(function(child) {
123128
return child.type !== 'text' || !whiteSpaceRegex.test(child.data);
124129
});
125-
_.each(nonWhiteSpaceChildren, function(elem) {
130+
nonWhiteSpaceChildren.forEach(function(elem) {
126131
result += formatListItem(prefix, elem, fn, options);
127132
});
128133
return result + '\n';
@@ -152,12 +157,12 @@ function formatOrderedList(elem, fn, options) {
152157
var start = Number(elem.attribs.start || '1') - 1;
153158
// Calculate the maximum length to i.
154159
var maxLength = (nonWhiteSpaceChildren.length + start).toString().length;
155-
_.each(nonWhiteSpaceChildren, function(elem, i) {
160+
nonWhiteSpaceChildren.forEach(function(elem, i) {
156161
// Use different function depending on type
157162
var index = typeFunction(start, i);
158163
// Calculate the needed spacing for nice indentation.
159164
var spacing = maxLength - index.toString().length;
160-
var prefix = ' ' + index + '. ' + _s.repeat(' ', spacing);
165+
var prefix = ' ' + index + '. ' + ' '.repeat(spacing);
161166
result += formatListItem(prefix, elem, fn, options);
162167
});
163168
}
@@ -167,24 +172,24 @@ function formatOrderedList(elem, fn, options) {
167172
function tableToString(table) {
168173
// Determine space width per column
169174
// Convert all rows to lengths
170-
var widths = _.map(table, function(row) {
171-
return _.map(row, function(col) {
175+
var widths = table.map(function(row) {
176+
return row.map(function(col) {
172177
return col.length;
173178
});
174179
});
175180
// Invert rows with colums
176181
widths = helper.arrayZip(widths);
177182
// Determine the max values for each column
178-
widths = _.map(widths, function(col) {
179-
return _.max(col);
183+
widths = widths.map(function(col) {
184+
return max(col);
180185
});
181186

182187
// Build the table
183188
var text = '';
184-
_.each(table, function(row) {
189+
table.forEach(function(row) {
185190
var i = 0;
186-
_.each(row, function(col) {
187-
text += _s.rpad(_s.strip(col), widths[i++], ' ') + ' ';
191+
row.forEach(function(col) {
192+
text += padEnd(col.trim(), widths[i++], ' ') + ' ';
188193
});
189194
text += '\n';
190195
});
@@ -193,7 +198,7 @@ function tableToString(table) {
193198

194199
function formatTable(elem, fn, options) {
195200
var table = [];
196-
_.each(elem.children, tryParseRows);
201+
elem.children.forEach(tryParseRows);
197202
return tableToString(table);
198203

199204
function tryParseRows(elem) {
@@ -205,27 +210,27 @@ function formatTable(elem, fn, options) {
205210
case "tbody":
206211
case "tfoot":
207212
case "center":
208-
_.each(elem.children, tryParseRows);
213+
elem.children.forEach(tryParseRows);
209214
return;
210215

211216
case 'tr':
212217
var rows = [];
213-
_.each(elem.children, function(elem) {
214-
var tokens, times;
218+
elem.children.forEach(function(elem) {
219+
var tokens, count;
215220
if (elem.type === 'tag') {
216221
switch (elem.name.toLowerCase()) {
217222
case 'th':
218223
tokens = formatHeading(elem, fn, options).split('\n');
219-
rows.push(_.compact(tokens));
224+
rows.push(compact(tokens));
220225
break;
221226

222227
case 'td':
223228
tokens = fn(elem.children, options).split('\n');
224-
rows.push(_.compact(tokens));
229+
rows.push(compact(tokens));
225230
// Fill colspans with empty values
226231
if (elem.attribs && elem.attribs.colspan) {
227-
times = elem.attribs.colspan - 1 || 0;
228-
_.times(times, function() {
232+
count = elem.attribs.colspan - 1 || 0;
233+
times(count, function() {
229234
rows.push(['']);
230235
});
231236
}
@@ -234,8 +239,8 @@ function formatTable(elem, fn, options) {
234239
}
235240
});
236241
rows = helper.arrayZip(rows);
237-
_.each(rows, function(row) {
238-
row = _.map(row, function(col) {
242+
rows.forEach(function(row) {
243+
row = row.map(function(col) {
239244
return col || '';
240245
});
241246
table.push(row);

lib/helper.js

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
var _ = require('underscore');
2-
var _s = require('underscore.string');
1+
var zip = require('lodash/zip');
2+
var trimEnd = require('lodash/trimEnd');
33

44
// Split a long word up to fit within the word wrap limit. Use either a
55
// character to split looking back from the word wrap limit, or
@@ -55,16 +55,16 @@ exports.wordwrap = function wordwrap(text, options) {
5555
var length = options.lineCharCount;
5656

5757
// Preserve leading space
58-
var result = _s.startsWith(text, ' ') ? ' ' : '';
58+
var result = text.startsWith(' ') ? ' ' : '';
5959
length += result.length;
6060
var buffer = [];
6161
// Split the text into words, decide to preserve new lines or not.
6262
var words = preserveNewlines
6363
? text.replace(/\n/g, '\n ').split(/\ +/)
64-
: _s.words(text);
64+
: text.trim().split(/\s+/);
6565

6666
// Determine where to end line word by word.
67-
_.each(words, function(word) {
67+
words.forEach(function(word) {
6868
// Add buffer to result if we can't fit any more words in the buffer.
6969
if ((max || max === 0) && length > 0 && ((length + word.length > max) || (length + word.indexOf('\n') > max))) {
7070
// Concat buffer and add it to the result
@@ -101,17 +101,17 @@ exports.wordwrap = function wordwrap(text, options) {
101101
result += buffer.join(' ');
102102

103103
// Preserve trailing space
104-
if (!_s.endsWith(text, ' ')) {
105-
result = _s.rtrim(result);
106-
} else if (!_s.endsWith(result, ' ')) {
104+
if (!text.endsWith(' ')) {
105+
result = trimEnd(result);
106+
} else if (!result.endsWith(' ')) {
107107
result = result + ' ';
108108
}
109109

110110
return result;
111111
};
112112

113113
exports.arrayZip = function arrayZip(array) {
114-
return _.zip.apply(_, array);
114+
return zip.apply(null, array);
115115
};
116116

117117
exports.splitCssSearchTag = function splitCssSearchTag(tagString) {
@@ -131,3 +131,9 @@ exports.splitCssSearchTag = function splitCssSearchTag(tagString) {
131131

132132
return splitTag;
133133
};
134+
135+
exports.replaceAll = function replaceAll(str, find, replace) {
136+
var reg = new RegExp(find, 'g');
137+
138+
return str.replace(reg, replace);
139+
};

lib/html-to-text.js

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
var fs = require('fs');
22
var util = require('util');
33

4-
var _ = require('underscore');
5-
var _s = require('underscore.string');
4+
var includes = require('lodash/includes');
5+
var trimEnd = require('lodash/trimEnd');
66
var htmlparser = require('htmlparser2');
77

88
var helper = require('./helper');
@@ -15,8 +15,7 @@ var SKIP_TYPES = [
1515
];
1616

1717
function htmlToText(html, options) {
18-
options = options || {};
19-
_.defaults(options, {
18+
options = Object.assign({
2019
wordwrap: 80,
2120
tables: [],
2221
preserveNewlines: false,
@@ -38,7 +37,7 @@ function htmlToText(html, options) {
3837
forceWrapOnLimit: false
3938
},
4039
unorderedListItemPrefix: ' * '
41-
});
40+
}, options || {});
4241

4342
var handler = new htmlparser.DefaultHandler(function (error, dom) {
4443

@@ -54,7 +53,7 @@ function htmlToText(html, options) {
5453
for (var idx = 0; idx < baseElements.length; ++idx) {
5554
result += walk(filterBody(handler.dom, options, baseElements[idx]), options);
5655
}
57-
return _s.rtrim(result);
56+
return trimEnd(result);
5857
}
5958

6059
function filterBody(dom, options, baseElement) {
@@ -64,7 +63,7 @@ function filterBody(dom, options, baseElement) {
6463

6564
function walk(dom) {
6665
if (result) return;
67-
_.each(dom, function(elem) {
66+
dom.forEach(function(elem) {
6867
if (result) return;
6968
if (elem.name === splitTag.element) {
7069
var documentClasses = elem.attribs && elem.attribs.class ? elem.attribs.class.split(" ") : [];
@@ -91,28 +90,31 @@ function containsTable(attr, tables) {
9190
}
9291
function checkPrefix(prefix) {
9392
return function(key) {
94-
return _s.startsWith(key, prefix);
93+
return key.startsWith(prefix);
9594
};
9695
}
9796
function filterByPrefix(tables, prefix) {
98-
return _(tables).chain()
97+
return tables
9998
.filter(checkPrefix(prefix))
100-
.map(removePrefix)
101-
.value();
99+
.map(removePrefix);
102100
}
103101
var classes = filterByPrefix(tables, '.');
104102
var ids = filterByPrefix(tables, '#');
105-
return attr && (_.include(classes, attr['class']) || _.include(ids, attr['id']));
103+
return attr && (includes(classes, attr['class']) || includes(ids, attr['id']));
106104
}
107105

108106
function walk(dom, options, result) {
109107
if (arguments.length < 3) {
110108
result = '';
111109
}
112110
var whiteSpaceRegex = /\s$/;
113-
var format = _.assign({}, defaultFormat, options.format);
111+
var format = Object.assign({}, defaultFormat, options.format);
112+
113+
if (!dom) {
114+
return result;
115+
}
114116

115-
_.each(dom, function(elem) {
117+
dom.forEach(function(elem) {
116118
switch(elem.type) {
117119
case 'tag':
118120
switch(elem.name.toLowerCase()) {
@@ -149,7 +151,7 @@ function walk(dom, options, result) {
149151
result += format.orderedList(elem, walk, options);
150152
break;
151153
case 'pre':
152-
var newOptions = _(options).clone();
154+
var newOptions = Object.assign({}, options);
153155
newOptions.isInPre = true;
154156
result += format.paragraph(elem, walk, newOptions);
155157
break;
@@ -171,7 +173,7 @@ function walk(dom, options, result) {
171173
}
172174
break;
173175
default:
174-
if (!_.include(SKIP_TYPES, elem.type)) {
176+
if (!includes(SKIP_TYPES, elem.type)) {
175177
result = walk(elem.children || [], options, result);
176178
}
177179
}

0 commit comments

Comments
 (0)