minify-family.js 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. var stringify = require('postcss-value-parser').stringify;
  2. var uniqs = require('./uniqs')('monospace');
  3. // Note that monospace is missing intentionally from this list; we should not
  4. // remove instances of duplicated monospace keywords, it causes the font to be
  5. // rendered smaller in Chrome.
  6. var keywords = [
  7. 'sans-serif',
  8. 'serif',
  9. 'fantasy',
  10. 'cursive'
  11. ];
  12. function intersection(haystack, array) {
  13. return array.some(function (v) {
  14. return ~haystack.indexOf(v);
  15. });
  16. };
  17. module.exports = function (nodes, opts) {
  18. var family = [];
  19. var last = null;
  20. var i, max;
  21. nodes.forEach(function (node, index, nodes) {
  22. var value = node.value;
  23. if (node.type === 'string' || node.type === 'function') {
  24. family.push(node);
  25. } else if (node.type === 'word') {
  26. if (!last) {
  27. last = { type: 'word', value: '' };
  28. family.push(last);
  29. }
  30. last.value += node.value;
  31. } else if (node.type === 'space') {
  32. if (last && index !== nodes.length - 1) {
  33. last.value += ' ';
  34. }
  35. } else {
  36. last = null;
  37. }
  38. });
  39. family = family.map(function (node) {
  40. if (node.type === 'string') {
  41. if (
  42. !opts.removeQuotes ||
  43. intersection(node.value, keywords) ||
  44. /[0-9]/.test(node.value.slice(0, 1))
  45. ) {
  46. return stringify(node);
  47. }
  48. var escaped = node.value.split(/\s/).map(function (word, index, words) {
  49. var next = words[index + 1];
  50. if (next && /^[^a-z]/i.test(next)) {
  51. return word + '\\';
  52. }
  53. if (!/^[^a-z\d\xa0-\uffff_-]/i.test(word)) {
  54. return word.replace(/([^a-z\d\xa0-\uffff_-])/gi, '\\$1');
  55. }
  56. if (/^[^a-z]/i.test(word) && index < 1) {
  57. return '\\' + word;
  58. }
  59. return word;
  60. }).join(' ');
  61. if (escaped.length < node.value.length + 2) {
  62. return escaped;
  63. }
  64. }
  65. return stringify(node);
  66. });
  67. if (opts.removeAfterKeyword) {
  68. for (i = 0, max = family.length; i < max; i += 1) {
  69. if (~keywords.indexOf(family[i])) {
  70. family = family.slice(0, i + 1);
  71. break;
  72. }
  73. }
  74. }
  75. if (opts.removeDuplicates) {
  76. family = uniqs(family);
  77. }
  78. return [
  79. {
  80. type: 'word',
  81. value: family.join()
  82. }
  83. ];
  84. };