index.js 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. var shorterNames = require('./shorter-css-color-names');
  2. var REGEX = {
  3. whitespace: /\s+/g,
  4. urlHexPairs: /%[\dA-F]{2}/g,
  5. quotes: /"/g,
  6. }
  7. function collapseWhitespace(str) {
  8. return str.trim().replace(REGEX.whitespace, ' ');
  9. }
  10. function dataURIPayload(string) {
  11. return encodeURIComponent(string)
  12. .replace(REGEX.urlHexPairs, specialHexEncode);
  13. }
  14. // `#` gets converted to `%23`, so quite a few CSS named colors are shorter than
  15. // their equivalent URL-encoded hex codes.
  16. function colorCodeToShorterNames(string) {
  17. Object.keys(shorterNames).forEach(function(key) {
  18. if (shorterNames[key].test(string)) {
  19. string = string.replace(shorterNames[key], key);
  20. }
  21. });
  22. return string;
  23. }
  24. function specialHexEncode(match) {
  25. switch (match) { // Browsers tolerate these characters, and they're frequent
  26. case '%20': return ' ';
  27. case '%3D': return '=';
  28. case '%3A': return ':';
  29. case '%2F': return '/';
  30. default: return match.toLowerCase(); // compresses better
  31. }
  32. }
  33. function svgToTinyDataUri(svgString) {
  34. if (typeof svgString !== 'string') {
  35. throw new TypeError('Expected a string, but received ' + typeof svgString);
  36. }
  37. // Strip the Byte-Order Mark if the SVG has one
  38. if (svgString.charCodeAt(0) === 0xfeff) { svgString = svgString.slice(1) }
  39. var body = colorCodeToShorterNames(collapseWhitespace(svgString))
  40. .replace(REGEX.quotes, "'");
  41. return 'data:image/svg+xml,' + dataURIPayload(body);
  42. }
  43. svgToTinyDataUri.toSrcset = function toSrcset(svgString) {
  44. return svgToTinyDataUri(svgString).replace(/ /g, '%20');
  45. }
  46. module.exports = svgToTinyDataUri;