UNPKG

2.94 kBJavaScriptView Raw
1// Alert: this file will be used in users' app for ext:css plugin,
2// use plain ES5 JavaScript Syntax.
3var cssUrlMatcher = /url\s*\(\s*(?!['"]data)([^) ]+)\s*\)/gi;
4
5// copied from aurelia-templating-resources css-resource
6// This behaves differently from webpack's style-loader.
7// Here we change './hello.png' to 'foo/hello.png' if base address is 'foo/bar'.
8// Note 'foo/hello.png' is technically a relative path in css.
9// We inject css into a style tag on html head, it means the 'foo/hello.png'
10// is related to current url (not css url on link tag), or <base> tag in html
11// head (which is recommended setup of aurelia-router if not using hash).
12function fixupCSSUrls(address, css) {
13 if (typeof css !== 'string') {
14 throw new Error(`Failed loading required CSS file: ${address}`);
15 }
16
17 return css.replace(cssUrlMatcher, function(match, p1) {
18 var quote = p1.charAt(0);
19 if (quote === '\'' || quote === '"') {
20 p1 = p1.substr(1, p1.length - 2);
21 }
22 var absolutePath = absoluteModuleId(address, p1);
23 if (absolutePath === p1) {
24 return match;
25 }
26 return 'url(\'' + absolutePath + '\')';
27 });
28}
29
30function absoluteModuleId(baseId, moduleId) {
31 if (moduleId[0] !== '.') return moduleId;
32
33 var parts = baseId.split('/');
34 parts.pop();
35
36 var mParts = moduleId.split('/');
37 var p;
38
39 for (p of mParts) {
40 if (p === '.') continue;
41 if (p === '..') {
42 parts.pop();
43 continue;
44 }
45 parts.push(p);
46 }
47
48 return parts.join('/');
49}
50
51// copied from aurelia-pal-browser DOM.injectStyles
52function injectCSS(css, id) {
53 if (typeof document === 'undefined' || !css) return;
54 css = fixupCSSUrls(id, css);
55
56 if (id) {
57 var oldStyle = document.getElementById(id);
58 if (oldStyle) {
59 var isStyleTag = oldStyle.tagName.toLowerCase() === 'style';
60
61 if (isStyleTag) {
62 oldStyle.innerHTML = css;
63 return;
64 }
65
66 throw new Error('The provided id does not indicate a style tag.');
67 }
68 }
69
70 var node = document.createElement('style');
71 node.innerHTML = css;
72 node.type = 'text/css';
73
74 if (id) {
75 node.id = id;
76 }
77
78 document.head.appendChild(node);
79}
80
81// dumber-module-loader plugin ext:css
82function load(name, req, load) {
83 req(['text!' + name], function(text) {
84 var result = splitCssModuleExports(text);
85 injectCSS(result.css, name);
86 // When css-module is in use, the module exports will be
87 // a map of tokens. Otherwise, export original css string.
88 load(result.exportTokens || result.css);
89 });
90}
91
92function splitCssModuleExports(text) {
93 if (!text) return {css: ''};
94 var m = text.match(/\n\/\*\s*dumber-css-module:\s*(.+?)\s*\*\/\s*$/);
95 if (!m) return {css: text};
96 var css = text.slice(0, m.index);
97 var exportTokens = JSON.parse(m[1]);
98 return {css, exportTokens};
99}
100
101exports.fixupCSSUrls = fixupCSSUrls;
102exports.injectCSS = injectCSS;
103exports.splitCssModuleExports = splitCssModuleExports;
104exports.load = load;