Skip to content

Commit

Permalink
Amend: Isolate iconv in codec objects, test separately
Browse files Browse the repository at this point in the history
  • Loading branch information
erikkemperman committed Nov 10, 2017
1 parent fdf81fc commit f6b1555
Show file tree
Hide file tree
Showing 13 changed files with 312 additions and 43 deletions.
88 changes: 85 additions & 3 deletions lib/codecs.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,95 @@
'use strict';

/* eslint-disable new-cap */

var iconv = require('iconv-lite');
var through = require('through2');

var DEFAULT_ENCODING = require('./constants').DEFAULT_ENCODING;

function Codec(codec, encoding) {
this.codec = codec;
this.enc = codec.enc || encoding;
this.bomAware = codec.bomAware || false;
}


var cache = {
utf8: iconv.getCodec('utf8'),
function getEncoder(codec) {
return new codec.encoder(null, codec);
}

Codec.prototype.encode = function(str) {
var encoder = getEncoder(this.codec);
var buf = encoder.write(str);
var end = encoder.end();
return end && end.length > 0 ? Buffer.concat(buf, end) : buf;
};

Codec.prototype.encodeStream = function() {
var encoder = getEncoder(this.codec);
return through(
{ decodeStrings: false },
function(str, enc, cb) {
var buf = encoder.write(str);
if (buf && buf.length) {
this.push(buf);
}
cb();
},
function(cb) {
var buf = encoder.end();
if (buf && buf.length) {
this.push(buf);
}
cb();
}
);
};


function getDecoder(codec) {
return new codec.decoder(null, codec);
}

Codec.prototype.decode = function(buf) {
var decoder = getDecoder(this.codec);
var str = decoder.write(buf);
var end = decoder.end();
return end ? str + end : str;
};

Codec.prototype.decodeStream = function() {
var decoder = getDecoder(this.codec);
return through(
{ encoding: DEFAULT_ENCODING },
function(buf, enc, cb) {
var str = decoder.write(buf);
if (str && str.length) {
this.push(str, DEFAULT_ENCODING);
}
cb();
},
function(cb) {
var str = decoder.end();
if (str && str.length) {
this.push(str, DEFAULT_ENCODING);
}
cb();
}
);
};


var cache = {};

function getCodec(encoding) {
var codec = cache[encoding];
if (!!codec || !encoding || cache.hasOwnProperty(encoding)) {
return codec;
}

try {
codec = iconv.getCodec(encoding);
codec = new Codec(iconv.getCodec(encoding), encoding);
} catch (err) {
// Unsupported codec
}
Expand All @@ -20,4 +98,8 @@ function getCodec(encoding) {
return codec;
}


// Pre-load default encoding
getCodec(DEFAULT_ENCODING);

module.exports = getCodec;
1 change: 1 addition & 0 deletions lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
module.exports = {
MASK_MODE: parseInt('7777', 8),
DEFAULT_FILE_MODE: parseInt('0666', 8),
DEFAULT_ENCODING: 'utf8',
};
4 changes: 3 additions & 1 deletion lib/dest/options.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

var DEFAULT_ENCODING = require('../constants').DEFAULT_ENCODING;

var config = {
cwd: {
type: 'string',
Expand Down Expand Up @@ -27,7 +29,7 @@ var config = {
},
encoding: {
type: ['string', 'boolean'],
default: 'utf8',
default: DEFAULT_ENCODING,
},
sourcemaps: {
type: ['string', 'boolean'],
Expand Down
9 changes: 4 additions & 5 deletions lib/dest/write-contents/write-buffer.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
'use strict';

var iconv = require('iconv-lite');

var fo = require('../../file-operations');
var getCodec = require('../../codecs');
var DEFAULT_ENCODING = require('../../constants').DEFAULT_ENCODING;

function writeBuffer(file, optResolver, onWritten) {
var encoding = optResolver.resolve('encoding', file);
Expand All @@ -19,9 +18,9 @@ function writeBuffer(file, optResolver, onWritten) {

var contents = file.contents;

if (encoding && codec.enc !== 'utf8') {
contents = iconv.decode(contents, 'utf8', { stripBOM: false });
contents = iconv.encode(contents, encoding);
if (encoding && codec.enc !== DEFAULT_ENCODING) {
contents = getCodec(DEFAULT_ENCODING).decode(contents);
contents = codec.encode(contents);
}

fo.writeFile(file.path, contents, opt, onWriteFile);
Expand Down
9 changes: 4 additions & 5 deletions lib/dest/write-contents/write-stream.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
'use strict';

var iconv = require('iconv-lite');

var fo = require('../../file-operations');
var getCodec = require('../../codecs');
var DEFAULT_ENCODING = require('../../constants').DEFAULT_ENCODING;
var readStream = require('../../src/read-contents/read-stream');

function writeStream(file, optResolver, onWritten) {
Expand All @@ -24,10 +23,10 @@ function writeStream(file, optResolver, onWritten) {

var contents = file.contents;

if (encoding && encoding.enc !== 'utf8') {
if (encoding && encoding.enc !== DEFAULT_ENCODING) {
contents = contents
.pipe(iconv.decodeStream('utf8', { stripBOM: false }))
.pipe(iconv.encodeStream(encoding));
.pipe(getCodec(DEFAULT_ENCODING).decodeStream())
.pipe(codec.encodeStream());
}

file.contents.once('error', onComplete);
Expand Down
4 changes: 3 additions & 1 deletion lib/src/options.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict';

var DEFAULT_ENCODING = require('../constants').DEFAULT_ENCODING;

var config = {
buffer: {
type: 'boolean',
Expand All @@ -18,7 +20,7 @@ var config = {
},
encoding: {
type: ['string', 'boolean'],
default: 'utf8',
default: DEFAULT_ENCODING,
},
sourcemaps: {
type: 'boolean',
Expand Down
8 changes: 4 additions & 4 deletions lib/src/read-contents/read-buffer.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'use strict';

var fs = require('graceful-fs');
var iconv = require('iconv-lite');
var removeBomBuffer = require('remove-bom-buffer');

var getCodec = require('../../codecs');
var DEFAULT_ENCODING = require('../../constants').DEFAULT_ENCODING;

function bufferFile(file, optResolver, onRead) {
var encoding = optResolver.resolve('encoding', file);
Expand All @@ -23,10 +23,10 @@ function bufferFile(file, optResolver, onRead) {
if (encoding) {
var removeBOM = codec.bomAware && optResolver.resolve('removeBOM', file);

if (codec.enc !== 'utf8') {
contents = iconv.decode(contents, encoding, { stripBOM: false });
if (codec.enc !== DEFAULT_ENCODING) {
contents = codec.decode(contents);
removeBOM = removeBOM && contents[0] === '\ufeff';
contents = iconv.encode(contents, 'utf8');
contents = getCodec(DEFAULT_ENCODING).encode(contents);
}

if (removeBOM) {
Expand Down
8 changes: 4 additions & 4 deletions lib/src/read-contents/read-stream.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
'use strict';

var fs = require('graceful-fs');
var iconv = require('iconv-lite');
var removeBomStream = require('remove-bom-stream');
var lazystream = require('lazystream');

var getCodec = require('../../codecs');
var DEFAULT_ENCODING = require('../../constants').DEFAULT_ENCODING;

function streamFile(file, optResolver, onRead) {
var encoding = optResolver.resolve('encoding', file);
Expand All @@ -22,10 +22,10 @@ function streamFile(file, optResolver, onRead) {
if (encoding) {
var removeBOM = codec.bomAware && optResolver.resolve('removeBOM', file);

if (codec.enc !== 'utf8') {
if (codec.enc !== DEFAULT_ENCODING) {
contents = contents
.pipe(iconv.decodeStream(encoding, { stripBOM: false }))
.pipe(iconv.encodeStream('utf8'));
.pipe(codec.decodeStream())
.pipe(getCodec(DEFAULT_ENCODING).encodeStream());
}

if (removeBOM) {
Expand Down
Loading

0 comments on commit f6b1555

Please sign in to comment.