Blame view

node_modules/style-loader/lib/urls.js 2.94 KB
aaac7fed   liuqimichale   add
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  
  /**
   * When source maps are enabled, `style-loader` uses a link element with a data-uri to
   * embed the css on the page. This breaks all relative urls because now they are relative to a
   * bundle instead of the current page.
   *
   * One solution is to only use full urls, but that may be impossible.
   *
   * Instead, this function "fixes" the relative urls to be absolute according to the current page location.
   *
   * A rudimentary test suite is located at `test/fixUrls.js` and can be run via the `npm test` command.
   *
   */
  
  module.exports = function (css) {
    // get current location
    var location = typeof window !== "undefined" && window.location;
  
    if (!location) {
      throw new Error("fixUrls requires window.location");
    }
  
  	// blank or null?
  	if (!css || typeof css !== "string") {
  	  return css;
    }
  
    var baseUrl = location.protocol + "//" + location.host;
    var currentDir = baseUrl + location.pathname.replace(/\/[^\/]*$/, "/");
  
  	// convert each url(...)
  	/*
  	This regular expression is just a way to recursively match brackets within
  	a string.
  
  	 /url\s*\(  = Match on the word "url" with any whitespace after it and then a parens
  	   (  = Start a capturing group
  	     (?:  = Start a non-capturing group
  	         [^)(]  = Match anything that isn't a parentheses
  	         |  = OR
  	         \(  = Match a start parentheses
  	             (?:  = Start another non-capturing groups
  	                 [^)(]+  = Match anything that isn't a parentheses
  	                 |  = OR
  	                 \(  = Match a start parentheses
  	                     [^)(]*  = Match anything that isn't a parentheses
  	                 \)  = Match a end parentheses
  	             )  = End Group
                *\) = Match anything and then a close parens
            )  = Close non-capturing group
            *  = Match anything
         )  = Close capturing group
  	 \)  = Match a close parens
  
  	 /gi  = Get all matches, not the first.  Be case insensitive.
  	 */
  	var fixedCss = css.replace(/url\s*\(((?:[^)(]|\((?:[^)(]+|\([^)(]*\))*\))*)\)/gi, function(fullMatch, origUrl) {
  		// strip quotes (if they exist)
  		var unquotedOrigUrl = origUrl
  			.trim()
  			.replace(/^"(.*)"$/, function(o, $1){ return $1; })
  			.replace(/^'(.*)'$/, function(o, $1){ return $1; });
  
  		// already a full url? no change
  		if (/^(#|data:|http:\/\/|https:\/\/|file:\/\/\/|\s*$)/i.test(unquotedOrigUrl)) {
  		  return fullMatch;
  		}
  
  		// convert the url to a full url
  		var newUrl;
  
  		if (unquotedOrigUrl.indexOf("//") === 0) {
  		  	//TODO: should we add protocol?
  			newUrl = unquotedOrigUrl;
  		} else if (unquotedOrigUrl.indexOf("/") === 0) {
  			// path should be relative to the base url
  			newUrl = baseUrl + unquotedOrigUrl; // already starts with '/'
  		} else {
  			// path should be relative to current directory
  			newUrl = currentDir + unquotedOrigUrl.replace(/^\.\//, ""); // Strip leading './'
  		}
  
  		// send back the fixed url(...)
  		return "url(" + JSON.stringify(newUrl) + ")";
  	});
  
  	// send back the fixed css
  	return fixedCss;
  };