Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ module.exports = function() {
var refs = currentRef.split('\n');
if (refs.indexOf(newRef) === -1) {
refs.push(newRef);
context[translate.msgid].comments.reference = refs.sort().join('\n');
context[translate.msgid].comments.reference = refs
.sort(utils.compareReferenceLines)
.join('\n');
}
} else if (typeof translate.msgid !== 'undefined') {
// Do not add translation if msgid is undefined.
Expand Down
113 changes: 113 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ var babel = require('@babel/core');

var fs = require('fs');
var plugin = require('../index.js');
var utils = require('../utils.js');

describe('babel-gettext-extractor', function() {
describe('#extract()', function() {
Expand Down Expand Up @@ -212,3 +213,115 @@ describe('babel-gettext-extractor', function() {
});
});
});

describe('utils', function() {
describe('#sortObjectKeysByRef()', function() {
it('Should sort source file line numbers as numbers', function() {
const unordered = {
a: { comments: { reference: 'path.js:20' } },
b: { comments: { reference: 'path.js:100' } },
};

const ordered = utils.sortObjectKeysByRef(unordered);
const keys = Array.from(Object.keys(ordered));
assert(keys[0] === 'a');
assert(keys[1] === 'b');
});

it('Should read line number from reference after the last colon', function() {
const unordered = {
a: { comments: { reference: 'path:with-colon.js:20' } },
b: { comments: { reference: 'path:with-colon.js:100' } },
};

const ordered = utils.sortObjectKeysByRef(unordered);
const keys = Array.from(Object.keys(ordered));
assert(keys[0] === 'a');
assert(keys[1] === 'b');
});

it('Should compare paths before line numbers', function() {
const unordered = {
a: { comments: { reference: 'path-a.js:20' } },
b: { comments: { reference: 'path-b.js:10' } },
};

const ordered = utils.sortObjectKeysByRef(unordered);
const keys = Array.from(Object.keys(ordered));
assert(keys[0] === 'a');
assert(keys[1] === 'b');
});

it('Should compare paths case-insensitively', function() {
const unordered = {
a: { comments: { reference: 'path-a.js:10' } },
b: { comments: { reference: 'path-B.js:10' } },
};

const ordered = utils.sortObjectKeysByRef(unordered);
const keys = Array.from(Object.keys(ordered));
assert(keys[0] === 'a');
assert(keys[1] === 'b');
});

it('Should treat reference with no colon as all path', function() {
const unordered = {
a: { comments: { reference: 'path-a.js' } },
b: { comments: { reference: 'path-b.js' } },
};

const ordered = utils.sortObjectKeysByRef(unordered);
const keys = Array.from(Object.keys(ordered));
assert(keys[0] === 'a');
assert(keys[1] === 'b');
});

it('Should treat reference with a colon suffix as all path', function() {
const unordered = {
a: { comments: { reference: 'path-a.js:' } },
b: { comments: { reference: 'path-b.js:' } },
};

const ordered = utils.sortObjectKeysByRef(unordered);
const keys = Array.from(Object.keys(ordered));
assert(keys[0] === 'a');
assert(keys[1] === 'b');
});

it('Should treat reference with a non-numeric part after the colon as all path', function() {
const unordered = {
a: { comments: { reference: 'path-a.js:not-a-number' } },
b: { comments: { reference: 'path-b.js:not-a-number' } },
};

const ordered = utils.sortObjectKeysByRef(unordered);
const keys = Array.from(Object.keys(ordered));
assert(keys[0] === 'a');
assert(keys[1] === 'b');
});

it('Should compare references line by line', function() {
const unordered = {
a: { comments: { reference: 'path.js:20\npath.js:820' } },
b: { comments: { reference: 'path.js:20\npath.js:453' } },
};

const ordered = utils.sortObjectKeysByRef(unordered);
const keys = Array.from(Object.keys(ordered));
assert(keys[0] === 'b');
assert(keys[1] === 'a');
});

it('Should sort the reference with more lines first if common lines are all equal', function() {
const unordered = {
a: { comments: { reference: 'path.js:20\npath.js:30' } },
b: { comments: { reference: 'path.js:20\npath.js:30\npath.js:40' } },
};

const ordered = utils.sortObjectKeysByRef(unordered);
const keys = Array.from(Object.keys(ordered));
assert(keys[0] === 'b');
assert(keys[1] === 'a');
});
});
});
56 changes: 52 additions & 4 deletions utils.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,39 @@
function splitReferenceLine(reference) {
const index = reference.lastIndexOf(':');
if (index === -1 || index === reference.length - 1) {
return { path: reference.toLowerCase(), lineNumber: 0 };
}

const lineNumber = parseInt(reference.substring(index + 1), 10);
if (Number.isNaN(lineNumber)) {
return { path: reference.toLowerCase(), lineNumber: 0 };
}

return {
path: reference.substring(0, index).toLowerCase(),
lineNumber,
};
}

function compareReferenceLines(a, b) {
const refA = splitReferenceLine(a);
const refB = splitReferenceLine(b);
if (refA.path < refB.path) {
return -1;
}
if (refA.path > refB.path) {
return 1;
}
if (refA.lineNumber < refB.lineNumber) {
return -1;
}
if (refA.lineNumber > refB.lineNumber) {
return 1;
}

return 0;
}

/*
* Sorts the object keys by the file reference.
* There's no guarantee of key iteration in order prior to es6
Expand All @@ -6,14 +42,25 @@
function sortObjectKeysByRef(unordered) {
const ordered = {};
Object.keys(unordered).sort((a, b) => {
const refA = unordered[a].comments.reference.toLowerCase();
const refB = unordered[b].comments.reference.toLowerCase();
if (refA < refB) {
const refALines = unordered[a].comments.reference.split('\n');
const refBLines = unordered[b].comments.reference.split('\n');

let line = 0;
while (line < refALines.length && line < refBLines.length) {
const result = compareReferenceLines(refALines[line], refBLines[line]);
if (result !== 0) {
return result;
}
line += 1;
}

if (line < refALines.length) {
return -1;
}
if (refA > refB) {
if (line < refBLines.length) {
return 1;
}

return 0;
}).forEach(function(key) {
ordered[key] = unordered[key];
Expand All @@ -31,4 +78,5 @@ function stripIndent(str) {
module.exports = {
stripIndent: stripIndent,
sortObjectKeysByRef: sortObjectKeysByRef,
compareReferenceLines: compareReferenceLines,
};