shared.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. 'use strict';
  2. // Expose to the world
  3. module.exports.parseHeader = parseHeader;
  4. module.exports.generateHeader = generateHeader;
  5. module.exports.formatCharset = formatCharset;
  6. module.exports.foldLine = foldLine;
  7. /**
  8. * Parses a header string into an object of key-value pairs
  9. *
  10. * @param {String} str Header string
  11. * @return {Object} An object of key-value pairs
  12. */
  13. function parseHeader (str) {
  14. var lines = (str || '').split('\n');
  15. var headers = {};
  16. lines.forEach(function (line) {
  17. var parts = line.trim().split(':');
  18. var key = (parts.shift() || '').trim().toLowerCase();
  19. var value = parts.join(':').trim();
  20. if (!key) {
  21. return;
  22. }
  23. headers[key] = value;
  24. });
  25. return headers;
  26. }
  27. /**
  28. * Convert first letters after - to uppercase, other lowercase
  29. *
  30. * @param {String} str String to be updated
  31. * @return {String} A string with uppercase words
  32. */
  33. function upperCaseWords (str) {
  34. return (str || '')
  35. .toLowerCase()
  36. .trim()
  37. .replace(/^(MIME|POT?(?=-)|[a-z])|-[a-z]/gi, function (str) {
  38. return str.toUpperCase();
  39. });
  40. }
  41. /**
  42. * Joins a header object of key value pairs into a header string
  43. *
  44. * @param {Object} header Object of key value pairs
  45. * @return {String} Header string
  46. */
  47. function generateHeader (header) {
  48. var lines = [];
  49. Object.keys(header || {}).forEach(function (key) {
  50. if (key) {
  51. lines.push(upperCaseWords(key) + ': ' + (header[key] || '').trim());
  52. }
  53. });
  54. return lines.join('\n') + (lines.length ? '\n' : '');
  55. }
  56. /**
  57. * Normalizes charset name. Converts utf8 to utf-8, WIN1257 to windows-1257 etc.
  58. *
  59. * @param {String} charset Charset name
  60. * @return {String} Normalized charset name
  61. */
  62. function formatCharset (charset, defaultCharset) {
  63. return (charset || 'iso-8859-1').toString().toLowerCase()
  64. .replace(/^utf[-_]?(\d+)$/, 'utf-$1')
  65. .replace(/^win(?:dows)?[-_]?(\d+)$/, 'windows-$1')
  66. .replace(/^latin[-_]?(\d+)$/, 'iso-8859-$1')
  67. .replace(/^(us[-_]?)?ascii$/, 'ascii')
  68. .replace(/^charset$/, defaultCharset || 'iso-8859-1')
  69. .trim();
  70. }
  71. /**
  72. * Folds long lines according to PO format
  73. *
  74. * @param {String} str PO formatted string to be folded
  75. * @param {Number} [maxLen=76] Maximum allowed length for folded lines
  76. * @return {Array} An array of lines
  77. */
  78. function foldLine (str, maxLen) {
  79. maxLen = maxLen || 76;
  80. var lines = [];
  81. var curLine = '';
  82. var pos = 0;
  83. var len = str.length;
  84. var match;
  85. while (pos < len) {
  86. curLine = str.substr(pos, maxLen);
  87. // ensure that the line never ends with a partial escaping
  88. // make longer lines if needed
  89. while (curLine.substr(-1) === '\\' && pos + curLine.length < len) {
  90. curLine += str.charAt(pos + curLine.length);
  91. }
  92. // ensure that if possible, line breaks are done at reasonable places
  93. if ((match = /.*?\\n/.exec(curLine))) {
  94. // use everything before and including the first line break
  95. curLine = match[0];
  96. } else if (pos + curLine.length < len) {
  97. // if we're not at the end
  98. if ((match = /.*\s+/.exec(curLine)) && /[^\s]/.test(match[0])) {
  99. // use everything before and including the last white space character (if anything)
  100. curLine = match[0];
  101. } else if ((match = /.*[\x21-\x2f0-9\x5b-\x60\x7b-\x7e]+/.exec(curLine)) && /[^\x21-\x2f0-9\x5b-\x60\x7b-\x7e]/.test(match[0])) {
  102. // use everything before and including the last "special" character (if anything)
  103. curLine = match[0];
  104. }
  105. }
  106. lines.push(curLine);
  107. pos += curLine.length;
  108. }
  109. return lines;
  110. }