normalize.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /*
  2. * css.normalize.js
  3. *
  4. * CSS Normalization
  5. *
  6. * CSS paths are normalized based on an optional basePath and the RequireJS config
  7. *
  8. * Usage:
  9. * normalize(css, fromBasePath, toBasePath);
  10. *
  11. * css: the stylesheet content to normalize
  12. * fromBasePath: the absolute base path of the css relative to any root (but without ../ backtracking)
  13. * toBasePath: the absolute new base path of the css relative to the same root
  14. *
  15. * Absolute dependencies are left untouched.
  16. *
  17. * Urls in the CSS are picked up by regular expressions.
  18. * These will catch all statements of the form:
  19. *
  20. * url(*)
  21. * url('*')
  22. * url("*")
  23. *
  24. * @import '*'
  25. * @import "*"
  26. *
  27. * (and so also @import url(*) variations)
  28. *
  29. * For urls needing normalization
  30. *
  31. */
  32. define(['require', 'module'], function(require, module) {
  33. // regular expression for removing double slashes
  34. // eg http://www.example.com//my///url/here -> http://www.example.com/my/url/here
  35. var slashes = /([^:])\/+/g
  36. var removeDoubleSlashes = function(uri) {
  37. return uri.replace(slashes, '$1/');
  38. }
  39. // given a relative URI, and two absolute base URIs, convert it from one base to another
  40. var protocolRegEx = /[^\:\/]*:\/\/([^\/])*/
  41. function convertURIBase(uri, fromBase, toBase) {
  42. if(uri.indexOf("data:") === 0)
  43. return uri;
  44. uri = removeDoubleSlashes(uri);
  45. // absolute urls are left in tact
  46. if (uri.match(/^\//) || uri.match(protocolRegEx))
  47. return uri;
  48. // if toBase specifies a protocol path, ensure this is the same protocol as fromBase, if not
  49. // use absolute path at fromBase
  50. var toBaseProtocol = toBase.match(protocolRegEx);
  51. var fromBaseProtocol = fromBase.match(protocolRegEx);
  52. if (fromBaseProtocol && (!toBaseProtocol || toBaseProtocol[1] != fromBaseProtocol[1] || toBaseProtocol[2] != fromBaseProtocol[2]))
  53. return absoluteURI(uri, fromBase);
  54. else {
  55. return relativeURI(absoluteURI(uri, fromBase), toBase);
  56. }
  57. };
  58. // given a relative URI, calculate the absolute URI
  59. function absoluteURI(uri, base) {
  60. if (uri.substr(0, 2) == './')
  61. uri = uri.substr(2);
  62. var baseParts = base.split('/');
  63. var uriParts = uri.split('/');
  64. baseParts.pop();
  65. while (curPart = uriParts.shift())
  66. if (curPart == '..')
  67. baseParts.pop();
  68. else
  69. baseParts.push(curPart);
  70. return baseParts.join('/');
  71. };
  72. // given an absolute URI, calculate the relative URI
  73. function relativeURI(uri, base) {
  74. // reduce base and uri strings to just their difference string
  75. var baseParts = base.split('/');
  76. baseParts.pop();
  77. base = baseParts.join('/') + '/';
  78. i = 0;
  79. while (base.substr(i, 1) == uri.substr(i, 1))
  80. i++;
  81. while (base.substr(i, 1) != '/')
  82. i--;
  83. base = base.substr(i + 1);
  84. uri = uri.substr(i + 1);
  85. // each base folder difference is thus a backtrack
  86. baseParts = base.split('/');
  87. var uriParts = uri.split('/');
  88. out = '';
  89. while (baseParts.shift())
  90. out += '../';
  91. // finally add uri parts
  92. while (curPart = uriParts.shift())
  93. out += curPart + '/';
  94. return out.substr(0, out.length - 1);
  95. };
  96. var normalizeCSS = function(source, fromBase, toBase, cssBase) {
  97. fromBase = removeDoubleSlashes(fromBase);
  98. toBase = removeDoubleSlashes(toBase);
  99. var urlRegEx = /@import\s*("([^"]*)"|'([^']*)')|url\s*\(\s*(\s*"([^"]*)"|'([^']*)'|[^\)]*\s*)\s*\)/ig;
  100. var result, url, source;
  101. while (result = urlRegEx.exec(source)) {
  102. url = result[3] || result[2] || result[5] || result[6] || result[4];
  103. var newUrl;
  104. if (cssBase && url.substr(0, 1) == '/')
  105. newUrl = cssBase + url;
  106. else
  107. newUrl = convertURIBase(url, fromBase, toBase);
  108. var quoteLen = result[5] || result[6] ? 1 : 0;
  109. source = source.substr(0, urlRegEx.lastIndex - url.length - quoteLen - 1) + newUrl + source.substr(urlRegEx.lastIndex - quoteLen - 1);
  110. urlRegEx.lastIndex = urlRegEx.lastIndex + (newUrl.length - url.length);
  111. }
  112. return source;
  113. };
  114. normalizeCSS.convertURIBase = convertURIBase;
  115. return normalizeCSS;
  116. });