Skip to content

Commit dbaa9ab

Browse files
committed
mv delite/css to requirejs-dplugins/css
1 parent b0a854d commit dbaa9ab

File tree

17 files changed

+484
-1
lines changed

17 files changed

+484
-1
lines changed

bower.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"version": "0.2.3",
44
"description": "AMD plugins for RequireJS",
55
"dependencies": {
6+
"dojo": ">=1.9.1",
67
"requirejs": "2.1.x"
78
},
89
"keywords": [

css.js

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
/**
2+
* CSS loading plugin for widgets.
3+
*
4+
* This plugin will load and wait for a css file. This can be handy to load the css
5+
* specific to a widget.
6+
*
7+
* This plugin uses the link load event and a work-around on old webkit browsers.
8+
* The work-around watches a stylesheet until its rules are
9+
* available (not null or undefined).
10+
*
11+
* This plugin will return the path of the inserted css file relative to requirejs baseUrl.
12+
*
13+
* @example:
14+
* To load the css file `myproj/comp.css`:
15+
* ```
16+
* require(["requirejs-dplugins/css!myproj/comp.css"], function (){
17+
* // Code placed here will wait for myproj/comp.css before running.
18+
* });
19+
* ```
20+
*
21+
* Or as a widget dependency:
22+
* ```
23+
* define(["requirejs-dplugins/css!myproj/comp.css"], function (){
24+
* // My widget factory
25+
* });
26+
* ```
27+
*
28+
* @module requirejs-dplugins/css
29+
*/
30+
31+
define([
32+
"./has",
33+
"dojo/Deferred",
34+
"module"
35+
], function (has, Deferred, module) {
36+
"use strict";
37+
38+
has.add("event-link-onload-api", function (global) {
39+
var wk = global.navigator.userAgent.match(/AppleWebKit\/([\d.]+)/);
40+
return !wk || parseInt(wk[1], 10) > 535;
41+
});
42+
var cache = {},
43+
lastInsertedLink;
44+
45+
/**
46+
* Return a promise that resolves when the specified link has finished loading.
47+
* @param {HTMLLinkElement} link - The link element to be notified for.
48+
* @returns {module:dojo/promise/Promise} - A promise.
49+
*/
50+
var listenOnLoad = function (link) {
51+
var def = new Deferred(),
52+
loadHandler = has("event-link-onload-api") ?
53+
function () {
54+
// We're using "readystatechange" because IE happily support both
55+
link.onreadystatechange = link.onload = function () {
56+
if (!link.readyState || link.readyState === "complete") {
57+
link.onreadystatechange = link.onload = null;
58+
def.resolve();
59+
}
60+
};
61+
} :
62+
function () {
63+
// watches a stylesheet for loading signs.
64+
var sheet = link.sheet || link.styleSheet,
65+
styleSheets = document.styleSheets;
66+
if (sheet && Array.prototype.lastIndexOf.call(styleSheets, sheet) !== -1) {
67+
def.resolve();
68+
} else {
69+
setTimeout(loadHandler, 25);
70+
}
71+
};
72+
73+
loadHandler();
74+
return def.promise;
75+
};
76+
77+
var loadCss = {
78+
id: module.id,
79+
80+
/*jshint maxcomplexity: 11*/
81+
/**
82+
* Loads a css file.
83+
* @param {string} path - The css file to load.
84+
* @param {Function} require - A local require function to use to load other modules.
85+
* @param {Function} callback - A function to call when the specified stylesheets have been loaded.
86+
* @method
87+
*/
88+
load: function (path, require, callback) {
89+
if (has("builder")) {
90+
buildFunctions.addOnce(loadList, path);
91+
callback();
92+
return;
93+
}
94+
95+
// Replace single css bundles by corresponding layer.
96+
var config = module.config();
97+
if (config.layersMap) {
98+
path = config.layersMap[path] || path;
99+
}
100+
101+
var head = document.head || document.getElementsByTagName("head")[0],
102+
url = require.toUrl(path),
103+
link;
104+
105+
// if the url has not already been injected/loaded, create a new promise.
106+
if (!cache[url]) {
107+
// hook up load detector(s)
108+
link = document.createElement("link");
109+
link.rel = "stylesheet";
110+
link.type = "text/css";
111+
link.href = url;
112+
head.insertBefore(link, lastInsertedLink ? lastInsertedLink.nextSibling : head.firstChild);
113+
lastInsertedLink = link;
114+
cache[url] = listenOnLoad(link);
115+
}
116+
117+
cache[url].then(function () {
118+
// The stylesheet has been loaded, so call the callback
119+
callback(path);
120+
});
121+
}
122+
};
123+
124+
if (has("builder")) {
125+
// build variables
126+
var loadList = [],
127+
writePluginFiles;
128+
129+
var buildFunctions = {
130+
/**
131+
* Write the layersMap configuration to the corresponding modules layer.
132+
* The configuration will look like this:
133+
* ```js
134+
* require.config({
135+
* config: {
136+
* "requirejs-dplugins/css": {
137+
* layersMap: {
138+
* "module1.css": "path/to/layer.css",
139+
* "module2.css": "path/to/layer.css"
140+
* }
141+
* }
142+
* }
143+
* });
144+
* ```
145+
*
146+
* @param {Function} write - This function takes a string as argument
147+
* and writes it to the modules layer.
148+
* @param {string} mid - Current module id.
149+
* @param {string} dest - Current css layer path.
150+
* @param {Array} loadList - List of css files contained in current css layer.
151+
*/
152+
writeConfig: function (write, mid, dest, loadList) {
153+
var cssConf = {
154+
config: {}
155+
};
156+
cssConf.config[mid] = {
157+
layersMap: {}
158+
};
159+
loadList.forEach(function (path) {
160+
cssConf.config[mid].layersMap[path] = dest;
161+
});
162+
163+
write("require.config(" + JSON.stringify(cssConf) + ");");
164+
},
165+
166+
/**
167+
* Concat and optimize all css files required by a modules layer and write the result.
168+
* The node module `clean-css` is responsible for optimizing the css and correcting
169+
* images paths.
170+
*
171+
* @param {Function} writePluginFiles - The write function provided by the builder to `writeFile`.
172+
* and writes it to the modules layer.
173+
* @param {string} dest - Current css layer path.
174+
* @param {Array} loadList - List of css files contained in current css layer.
175+
*/
176+
writeLayer: function (writePluginFiles, dest, loadList) {
177+
function tryRequire(paths) {
178+
var module;
179+
var path = paths.shift();
180+
if (path) {
181+
try {
182+
// This is a node-require so it is synchronous.
183+
module = require.nodeRequire(path);
184+
} catch (e) {
185+
return tryRequire(paths);
186+
}
187+
}
188+
return module;
189+
}
190+
191+
var path = require.getNodePath(require.toUrl(module.id).replace(/[^\/]*$/, "node_modules/clean-css"));
192+
var CleanCSS = tryRequire([path, "clean-css"]);
193+
194+
if (CleanCSS) {
195+
var result = "";
196+
loadList = loadList.map(require.toUrl)
197+
.filter(function (path) {
198+
var fs = require.nodeRequire("fs");
199+
if (!fs.existsSync(path)) {
200+
console.log(">> Css file '" + path + "' was not found.");
201+
return false;
202+
}
203+
return true;
204+
});
205+
loadList.forEach(function (src) {
206+
result += new CleanCSS({
207+
relativeTo: "./",
208+
target: dest
209+
}).minify("@import url(" + src + ");");
210+
});
211+
212+
writePluginFiles(dest, result);
213+
} else {
214+
console.log(">> Node module clean-css not found. Skipping CSS inlining. If you want CSS inlining" +
215+
" run 'npm install clean-css' in your console.");
216+
}
217+
},
218+
219+
/**
220+
* Add the string to `ary` if it's not already in it.
221+
* @param {Array} ary - Destination array.
222+
* @param {string} element - Element to add.
223+
*/
224+
addOnce: function (ary, element) {
225+
if (ary.indexOf(element) === -1) {
226+
ary.push(element);
227+
}
228+
}
229+
};
230+
231+
loadCss.writeFile = function (pluginName, resource, require, write) {
232+
writePluginFiles = write;
233+
};
234+
235+
loadCss.onLayerEnd = function (write, data) {
236+
if (data.name && data.path) {
237+
var dest = data.path.replace(/^(?:\.\/)?(([^\/]*\/)*)[^\/]*$/, "$1css/layer.css");
238+
var destMid = data.name.replace(/^(([^\/]*\/)*)[^\/]*$/, "$1css/layer.css");
239+
240+
// Write layer file
241+
buildFunctions.writeLayer(writePluginFiles, dest, loadList);
242+
// Write css config on the layer
243+
buildFunctions.writeConfig(write, module.id, destMid, loadList);
244+
// Reset loadList
245+
loadList = [];
246+
}
247+
};
248+
249+
// Expose build functions to be used by delite/theme
250+
loadCss.buildFunctions = buildFunctions;
251+
}
252+
253+
return loadCss;
254+
});

docs/css.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
---
2+
layout: default
3+
title: requirejs-dplugins/css
4+
---
5+
6+
# requirejs-dplugins/css!
7+
8+
This plugin will load and wait for a css file. This can be handy to load the css
9+
specific to a widget.
10+
11+
CSS loaded with this plugin can be overwritten by user-defined style sheet, using `<link>` or `<style>` tag.
12+
13+
This plugin will return the path of the inserted css file relative to requirejs baseUrl.
14+
15+
## Example
16+
17+
To load the css file `myproj/comp.css` you can use:
18+
```
19+
require(["requirejs-dplugins/css!myproj/comp.css"], function (){
20+
// Code placed here will wait for myproj/comp.css before running.
21+
});
22+
```
23+
24+
Or as a widget dependency:
25+
26+
```
27+
define(["requirejs-dplugins/css!myproj/comp.css"], function (){
28+
// My widget factory
29+
});
30+
```
31+

tests/all.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Listing of all the plugin tests
22
define([
3+
"./css",
34
"./has",
45
"./i18n"
56
]);

0 commit comments

Comments
 (0)