charset.js 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. module.exports = preferredCharsets;
  2. preferredCharsets.preferredCharsets = preferredCharsets;
  3. function parseAcceptCharset(accept) {
  4. return accept.split(',').map(function(e) {
  5. return parseCharset(e.trim());
  6. }).filter(function(e) {
  7. return e && e.q > 0;
  8. });
  9. }
  10. function parseCharset(s) {
  11. var match = s.match(/^\s*(\S+?)\s*(?:;(.*))?$/);
  12. if (!match) return null;
  13. var charset = match[1];
  14. var q = 1;
  15. if (match[2]) {
  16. var params = match[2].split(';')
  17. for (var i = 0; i < params.length; i ++) {
  18. var p = params[i].trim().split('=');
  19. if (p[0] === 'q') {
  20. q = parseFloat(p[1]);
  21. break;
  22. }
  23. }
  24. }
  25. return {
  26. charset: charset,
  27. q: q
  28. };
  29. }
  30. function getCharsetPriority(charset, accepted) {
  31. return (accepted.filter(function(a) {
  32. return specify(charset, a);
  33. }).sort(function (a, b) {
  34. // revsort
  35. return a.q === b.q ? 0 : a.q > b.q ? -1 : 1;
  36. })[0] || {q:0}).q;
  37. }
  38. function specify(charset, spec) {
  39. if (spec.charset === '*' || spec.charset === charset) {
  40. return spec;
  41. }
  42. };
  43. function preferredCharsets(accept, provided) {
  44. accept = parseAcceptCharset(accept || '');
  45. if (provided) {
  46. return provided.map(function(type) {
  47. return [type, getCharsetPriority(type, accept)];
  48. }).filter(function(pair) {
  49. return pair[1] > 0;
  50. }).sort(function(a, b) {
  51. // revsort
  52. return a[1] === b[1] ? 0 : a[1] > b[1] ? -1 : 1;
  53. }).map(function(pair) {
  54. return pair[0];
  55. });
  56. } else {
  57. return accept.sort(function (a, b) {
  58. // revsort
  59. return a.q < b.q ? 1 : -1;
  60. }).map(function(type) {
  61. return type.charset;
  62. });
  63. }
  64. }