Skip to content
Merged
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
19 changes: 15 additions & 4 deletions lib/ical/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -287,11 +287,22 @@ ICAL.helpers = {
*/
foldline: function foldline(aLine) {
var result = "";
var line = aLine || "";

var line = aLine || "", pos = 0, line_length = 0;
//pos counts position in line for the UTF-16 presentation
//line_length counts the bytes for the UTF-8 presentation
while (line.length) {
result += ICAL.newLineChar + " " + line.substr(0, ICAL.foldLength);
line = line.substr(ICAL.foldLength);
var cp = line.codePointAt(pos);
if (cp < 128) ++line_length;
else if (cp < 2048) line_length += 2;//needs 2 UTF-8 bytes
else if (cp < 65536) line_length += 3;
else line_length += 4; //cp is less than 1114112
if (line_length < ICAL.foldLength + 1)
pos += cp > 65535 ? 2 : 1;
else {
result += ICAL.newLineChar + " " + line.substring(0, pos);
line = line.substring(pos);
pos = line_length = 0;
}
}
return result.substr(ICAL.newLineChar.length + 1);
},
Expand Down
6 changes: 6 additions & 0 deletions test/stringify_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,12 @@ suite('ICAL.stringify', function() {
assert.equal(ICAL.stringify.property(subject.toJSON(), ICAL.design.icalendar, false), "DESCRIPTION:foo" + N + "bar");
assert.equal(ICAL.stringify.property(subject.toJSON(), ICAL.design.icalendar, true), "DESCRIPTION:foobar");

var utf16_muscle = '\uD83D\uDCAA'; //in UTF-8 this is F0 DF 92 AA. If space/new line is inserted between the surrogates, then the JS Engine substitutes each stand-alone surrogate with REPLACEMENT CHARACTER 0xEF 0xBF 0xBD
subject.setValue(utf16_muscle);
assert.equal(ICAL.stringify.property(subject.toJSON(), ICAL.design.icalendar, false), "DESCRIPTION:" + N + utf16_muscle);//verify new line is after ':', as otherwise the whole line is longer than ICAL.foldLength
subject.setValue('aa' + utf16_muscle + utf16_muscle + 'a' + utf16_muscle + utf16_muscle);
assert.equal(ICAL.stringify.property(subject.toJSON(), ICAL.design.icalendar, false), "DESCRIPTION:aa" + N + utf16_muscle + utf16_muscle + 'a' + utf16_muscle + N + utf16_muscle);//verify that the utf16_muscle is moved as whole to a new line as it is 4 UTF-8 bytes

ICAL.foldLength = oldLength;
});
});
Expand Down