Return-Path: X-Original-To: apmail-couchdb-commits-archive@www.apache.org Delivered-To: apmail-couchdb-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 88DF810C64 for ; Mon, 8 Jul 2013 16:00:01 +0000 (UTC) Received: (qmail 22210 invoked by uid 500); 8 Jul 2013 15:59:56 -0000 Delivered-To: apmail-couchdb-commits-archive@couchdb.apache.org Received: (qmail 21933 invoked by uid 500); 8 Jul 2013 15:59:56 -0000 Mailing-List: contact commits-help@couchdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@couchdb.apache.org Delivered-To: mailing list commits@couchdb.apache.org Received: (qmail 21453 invoked by uid 99); 8 Jul 2013 15:59:55 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 08 Jul 2013 15:59:55 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 25C1888597C; Mon, 8 Jul 2013 15:59:55 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: garren@apache.org To: commits@couchdb.apache.org Date: Mon, 08 Jul 2013 16:00:06 -0000 Message-Id: <97e9739c8ecf4afd8188538fadb48f8a@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [13/21] working with less and css http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-css/example/www/popup.css ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-css/example/www/popup.css b/src/fauxton/assets/js/plugins/require-css/example/www/popup.css new file mode 100644 index 0000000..3d37293 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-css/example/www/popup.css @@ -0,0 +1,7 @@ +.popup { + width: 300px; + height: 300px; + padding: 20px; + background-color: green; + font-family: times; +} http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-css/example/www/popup.js ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-css/example/www/popup.js b/src/fauxton/assets/js/plugins/require-css/example/www/popup.js new file mode 100644 index 0000000..51ceea7 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-css/example/www/popup.js @@ -0,0 +1,3 @@ +define(['css!popup'], function() { + return ""; +}); http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-css/example/www/require-css ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-css/example/www/require-css b/src/fauxton/assets/js/plugins/require-css/example/www/require-css new file mode 120000 index 0000000..6581736 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-css/example/www/require-css @@ -0,0 +1 @@ +../../ \ No newline at end of file http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-css/example/www/style/style.css ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-css/example/www/style/style.css b/src/fauxton/assets/js/plugins/require-css/example/www/style/style.css new file mode 100755 index 0000000..7898dbf --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-css/example/www/style/style.css @@ -0,0 +1,6 @@ +/* module.css */ +/* used by app.js */ +@import '/test.css' +body { + font-family: sans-serif; +} http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-css/example/www/test.css ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-css/example/www/test.css b/src/fauxton/assets/js/plugins/require-css/example/www/test.css new file mode 100644 index 0000000..00e243d --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-css/example/www/test.css @@ -0,0 +1,3 @@ +body { + background-color: #fee; +} http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-css/example/www/test.html ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-css/example/www/test.html b/src/fauxton/assets/js/plugins/require-css/example/www/test.html new file mode 100644 index 0000000..f72d47b --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-css/example/www/test.html @@ -0,0 +1,28 @@ + + + + + + +

test

+ + + + \ No newline at end of file http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-css/example/www/text.js ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-css/example/www/text.js b/src/fauxton/assets/js/plugins/require-css/example/www/text.js new file mode 100755 index 0000000..38f6ca0 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-css/example/www/text.js @@ -0,0 +1,282 @@ +/** + * @license RequireJS text 1.0.8 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ +/*jslint regexp: true, plusplus: true, sloppy: true */ +/*global require: false, XMLHttpRequest: false, ActiveXObject: false, + define: false, window: false, process: false, Packages: false, + java: false, location: false */ + +(function () { + var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], + xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, + bodyRegExp = /]*>\s*([\s\S]+)\s*<\/body>/im, + hasLocation = typeof location !== 'undefined' && location.href, + defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''), + defaultHostName = hasLocation && location.hostname, + defaultPort = hasLocation && (location.port || undefined), + buildMap = []; + + define(function () { + var text, fs; + + text = { + version: '1.0.8', + + strip: function (content) { + //Strips declarations so that external SVG and XML + //documents can be added to a document without worry. Also, if the string + //is an HTML document, only the part inside the body tag is returned. + if (content) { + content = content.replace(xmlRegExp, ""); + var matches = content.match(bodyRegExp); + if (matches) { + content = matches[1]; + } + } else { + content = ""; + } + return content; + }, + + jsEscape: function (content) { + return content.replace(/(['\\])/g, '\\$1') + .replace(/[\f]/g, "\\f") + .replace(/[\b]/g, "\\b") + .replace(/[\n]/g, "\\n") + .replace(/[\t]/g, "\\t") + .replace(/[\r]/g, "\\r"); + }, + + createXhr: function () { + //Would love to dump the ActiveX crap in here. Need IE 6 to die first. + var xhr, i, progId; + if (typeof XMLHttpRequest !== "undefined") { + return new XMLHttpRequest(); + } else if (typeof ActiveXObject !== "undefined") { + for (i = 0; i < 3; i++) { + progId = progIds[i]; + try { + xhr = new ActiveXObject(progId); + } catch (e) {} + + if (xhr) { + progIds = [progId]; // so faster next time + break; + } + } + } + + return xhr; + }, + + /** + * Parses a resource name into its component parts. Resource names + * look like: module/name.ext!strip, where the !strip part is + * optional. + * @param {String} name the resource name + * @returns {Object} with properties "moduleName", "ext" and "strip" + * where strip is a boolean. + */ + parseName: function (name) { + var strip = false, index = name.indexOf("."), + modName = name.substring(0, index), + ext = name.substring(index + 1, name.length); + + index = ext.indexOf("!"); + if (index !== -1) { + //Pull off the strip arg. + strip = ext.substring(index + 1, ext.length); + strip = strip === "strip"; + ext = ext.substring(0, index); + } + + return { + moduleName: modName, + ext: ext, + strip: strip + }; + }, + + xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/, + + /** + * Is an URL on another domain. Only works for browser use, returns + * false in non-browser environments. Only used to know if an + * optimized .js version of a text resource should be loaded + * instead. + * @param {String} url + * @returns Boolean + */ + useXhr: function (url, protocol, hostname, port) { + var match = text.xdRegExp.exec(url), + uProtocol, uHostName, uPort; + if (!match) { + return true; + } + uProtocol = match[2]; + uHostName = match[3]; + + uHostName = uHostName.split(':'); + uPort = uHostName[1]; + uHostName = uHostName[0]; + + return (!uProtocol || uProtocol === protocol) && + (!uHostName || uHostName === hostname) && + ((!uPort && !uHostName) || uPort === port); + }, + + finishLoad: function (name, strip, content, onLoad, config) { + content = strip ? text.strip(content) : content; + if (config.isBuild) { + buildMap[name] = content; + } + onLoad(content); + }, + + load: function (name, req, onLoad, config) { + //Name has format: some.module.filext!strip + //The strip part is optional. + //if strip is present, then that means only get the string contents + //inside a body tag in an HTML string. For XML/SVG content it means + //removing the declarations so the content can be inserted + //into the current doc without problems. + + // Do not bother with the work if a build and text will + // not be inlined. + if (config.isBuild && !config.inlineText) { + onLoad(); + return; + } + + var parsed = text.parseName(name), + nonStripName = parsed.moduleName + '.' + parsed.ext, + url = req.toUrl(nonStripName), + useXhr = (config && config.text && config.text.useXhr) || + text.useXhr; + + //Load the text. Use XHR if possible and in a browser. + if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) { + text.get(url, function (content) { + text.finishLoad(name, parsed.strip, content, onLoad, config); + }); + } else { + //Need to fetch the resource across domains. Assume + //the resource has been optimized into a JS module. Fetch + //by the module name + extension, but do not include the + //!strip part to avoid file system issues. + req([nonStripName], function (content) { + text.finishLoad(parsed.moduleName + '.' + parsed.ext, + parsed.strip, content, onLoad, config); + }); + } + }, + + write: function (pluginName, moduleName, write, config) { + if (buildMap.hasOwnProperty(moduleName)) { + var content = text.jsEscape(buildMap[moduleName]); + write.asModule(pluginName + "!" + moduleName, + "define(function () { return '" + + content + + "';});\n"); + } + }, + + writeFile: function (pluginName, moduleName, req, write, config) { + var parsed = text.parseName(moduleName), + nonStripName = parsed.moduleName + '.' + parsed.ext, + //Use a '.js' file name so that it indicates it is a + //script that can be loaded across domains. + fileName = req.toUrl(parsed.moduleName + '.' + + parsed.ext) + '.js'; + + //Leverage own load() method to load plugin value, but only + //write out values that do not have the strip argument, + //to avoid any potential issues with ! in file names. + text.load(nonStripName, req, function (value) { + //Use own write() method to construct full module value. + //But need to create shell that translates writeFile's + //write() to the right interface. + var textWrite = function (contents) { + return write(fileName, contents); + }; + textWrite.asModule = function (moduleName, contents) { + return write.asModule(moduleName, fileName, contents); + }; + + text.write(pluginName, nonStripName, textWrite, config); + }, config); + } + }; + + if (text.createXhr()) { + text.get = function (url, callback) { + var xhr = text.createXhr(); + xhr.open('GET', url, true); + xhr.onreadystatechange = function (evt) { + //Do not explicitly handle errors, those should be + //visible via console output in the browser. + if (xhr.readyState === 4) { + callback(xhr.responseText); + } + }; + xhr.send(null); + }; + } else if (typeof process !== "undefined" && + process.versions && + !!process.versions.node) { + //Using special require.nodeRequire, something added by r.js. + fs = require.nodeRequire('fs'); + + text.get = function (url, callback) { + var file = fs.readFileSync(url, 'utf8'); + //Remove BOM (Byte Mark Order) from utf8 files if it is there. + if (file.indexOf('\uFEFF') === 0) { + file = file.substring(1); + } + callback(file); + }; + } else if (typeof Packages !== 'undefined') { + //Why Java, why is this so awkward? + text.get = function (url, callback) { + var encoding = "utf-8", + file = new java.io.File(url), + lineSeparator = java.lang.System.getProperty("line.separator"), + input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)), + stringBuffer, line, + content = ''; + try { + stringBuffer = new java.lang.StringBuffer(); + line = input.readLine(); + + // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324 + // http://www.unicode.org/faq/utf_bom.html + + // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK: + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 + if (line && line.length() && line.charAt(0) === 0xfeff) { + // Eat the BOM, since we've already found the encoding on this file, + // and we plan to concatenating this buffer with others; the BOM should + // only appear at the top of a file. + line = line.substring(1); + } + + stringBuffer.append(line); + + while ((line = input.readLine()) !== null) { + stringBuffer.append(lineSeparator); + stringBuffer.append(line); + } + //Make sure we return a JavaScript string and not a Java string. + content = String(stringBuffer.toString()); //String + } finally { + input.close(); + } + callback(content); + }; + } + + return text; + }); +}()); http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-css/normalize.js ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-css/normalize.js b/src/fauxton/assets/js/plugins/require-css/normalize.js new file mode 100644 index 0000000..4d81eb1 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-css/normalize.js @@ -0,0 +1,138 @@ +/* + * css.normalize.js + * + * CSS Normalization + * + * CSS paths are normalized based on an optional basePath and the RequireJS config + * + * Usage: + * normalize(css, fromBasePath, toBasePath); + * + * css: the stylesheet content to normalize + * fromBasePath: the absolute base path of the css relative to any root (but without ../ backtracking) + * toBasePath: the absolute new base path of the css relative to the same root + * + * Absolute dependencies are left untouched. + * + * Urls in the CSS are picked up by regular expressions. + * These will catch all statements of the form: + * + * url(*) + * url('*') + * url("*") + * + * @import '*' + * @import "*" + * + * (and so also @import url(*) variations) + * + * For urls needing normalization + * + */ + +define(['require', 'module'], function(require, module) { + + // regular expression for removing double slashes + // eg http://www.example.com//my///url/here -> http://www.example.com/my/url/here + var slashes = /([^:])\/+/g + var removeDoubleSlashes = function(uri) { + return uri.replace(slashes, '$1/'); + } + + // given a relative URI, and two absolute base URIs, convert it from one base to another + var protocolRegEx = /[^\:\/]*:\/\/([^\/])*/ + function convertURIBase(uri, fromBase, toBase) { + if(uri.indexOf("data:") === 0) + return uri; + uri = removeDoubleSlashes(uri); + // absolute urls are left in tact + if (uri.match(/^\//) || uri.match(protocolRegEx)) + return uri; + // if toBase specifies a protocol path, ensure this is the same protocol as fromBase, if not + // use absolute path at fromBase + var toBaseProtocol = toBase.match(protocolRegEx); + var fromBaseProtocol = fromBase.match(protocolRegEx); + if (fromBaseProtocol && (!toBaseProtocol || toBaseProtocol[1] != fromBaseProtocol[1] || toBaseProtocol[2] != fromBaseProtocol[2])) + return absoluteURI(uri, fromBase); + + else { + return relativeURI(absoluteURI(uri, fromBase), toBase); + } + }; + + // given a relative URI, calculate the absolute URI + function absoluteURI(uri, base) { + if (uri.substr(0, 2) == './') + uri = uri.substr(2); + + var baseParts = base.split('/'); + var uriParts = uri.split('/'); + + baseParts.pop(); + + while (curPart = uriParts.shift()) + if (curPart == '..') + baseParts.pop(); + else + baseParts.push(curPart); + + return baseParts.join('/'); + }; + + + // given an absolute URI, calculate the relative URI + function relativeURI(uri, base) { + + // reduce base and uri strings to just their difference string + var baseParts = base.split('/'); + baseParts.pop(); + base = baseParts.join('/') + '/'; + i = 0; + while (base.substr(i, 1) == uri.substr(i, 1)) + i++; + while (base.substr(i, 1) != '/') + i--; + base = base.substr(i + 1); + uri = uri.substr(i + 1); + + // each base folder difference is thus a backtrack + baseParts = base.split('/'); + var uriParts = uri.split('/'); + out = ''; + while (baseParts.shift()) + out += '../'; + + // finally add uri parts + while (curPart = uriParts.shift()) + out += curPart + '/'; + + return out.substr(0, out.length - 1); + }; + + var normalizeCSS = function(source, fromBase, toBase, cssBase) { + + fromBase = removeDoubleSlashes(fromBase); + toBase = removeDoubleSlashes(toBase); + + var urlRegEx = /@import\s*("([^"]*)"|'([^']*)')|url\s*\(\s*(\s*"([^"]*)"|'([^']*)'|[^\)]*\s*)\s*\)/ig; + var result, url, source; + + while (result = urlRegEx.exec(source)) { + url = result[3] || result[2] || result[5] || result[6] || result[4]; + var newUrl; + if (cssBase && url.substr(0, 1) == '/') + newUrl = cssBase + url; + else + newUrl = convertURIBase(url, fromBase, toBase); + var quoteLen = result[5] || result[6] ? 1 : 0; + source = source.substr(0, urlRegEx.lastIndex - url.length - quoteLen - 1) + newUrl + source.substr(urlRegEx.lastIndex - quoteLen - 1); + urlRegEx.lastIndex = urlRegEx.lastIndex + (newUrl.length - url.length); + } + + return source; + }; + + normalizeCSS.convertURIBase = convertURIBase; + + return normalizeCSS; +}); http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-css/package.json ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-css/package.json b/src/fauxton/assets/js/plugins/require-css/package.json new file mode 100644 index 0000000..c93f72f --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-css/package.json @@ -0,0 +1,5 @@ +{ + "volo": { + "type": "directory" + } +} http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-css/test/test.js ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-css/test/test.js b/src/fauxton/assets/js/plugins/require-css/test/test.js new file mode 100644 index 0000000..4c9864b --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-css/test/test.js @@ -0,0 +1,78 @@ +var requirejs = require('requirejs'); + +var passed = 0; +var failed = 0; +var assert = function(name, statement, val) { + if (statement === val) { + console.log(' ' + name + '... passed.'); + passed++; + } + else { + console.log(' ' + name + '... failed.\n ' + 'Expected "' + val + '" got "' + statement + '"\n'); + failed++; + } +} + +requirejs(['../css', '../normalize'], function(css, normalize) { + console.log('\n--- Starting Require CSS Tests ---'); + + console.log('\nTesting URL Base Conversions'); + assert( + 'Changing subfolder', + normalize.convertURIBase('test', '/one/two/', '/one/three/'), + '../two/test' + ); + assert( + 'Changing subfolder with backtrack', + normalize.convertURIBase('../test', '/one/two/', '/one/three/'), + '../test' + ); + assert( + 'Changing two subfolders with a folder', + normalize.convertURIBase('some/test', '/one/two/three/', '/one/four/five/'), + '../../two/three/some/test' + ); + assert( + 'Double forward slashes in relative URI', + normalize.convertURIBase('some//test', '/one/two/three/', '/one/two/four/'), + '../three/some/test' + ); + assert( + 'protocol base urls work', + normalize.convertURIBase('some/file', 'http://www.google.com:80/', 'http://www.google.com:80/sub/'), + '../some/file' + ); + assert( + 'absolute protocol paths work with base conversion', + normalize.convertURIBase('some/file', 'http://some.cdn.com/baseUrl/', 'baseUrl/'), + 'http://some.cdn.com/baseUrl/some/file' + ); + console.log('\nTesting Stylesheet Regular Expressions'); + assert( + '@import statements', + normalize('@import "test.css"', '/first/', '/second/'), + '@import "../first/test.css"' + ); + assert( + 'url includes', + normalize('background: url("../some/test.css")', '/first/one/', '/second/one/'), + 'background: url("../../first/some/test.css")' + ); + assert( + 'multiple url includes on the same line', + normalize('src: url("../fonts/font.eot") format("embedded-opentype"), url("../fonts/font.woff") format("woff");', '/base/', '/'), + 'src: url("fonts/font.eot") format("embedded-opentype"), url("fonts/font.woff") format("woff");' + ); + assert( + 'cssBase can apply to imports', + normalize('@import "/some-file"', '/first/', '/second/', 'http://www.my-website.com'), + '@import "http://www.my-website.com/some-file"' + ); + assert( + 'cssBase can apply to urls', + normalize('background: url(\'/absolute/source.jpg\');', 'asdf', 'qwer', '/basePath'), + 'background: url(\'/basePath/absolute/source.jpg\');' + ); + + console.log('\n--- Require CSS Tests Complete: ' + passed + ' passed, ' + failed + ' failed. ---\n'); +}); http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/LICENSE ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/LICENSE b/src/fauxton/assets/js/plugins/require-less/LICENSE new file mode 100644 index 0000000..e39e77c --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/LICENSE @@ -0,0 +1,10 @@ +MIT License +----------- + +Copyright (C) 2013 Guy Bedford + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/README.md ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/README.md b/src/fauxton/assets/js/plugins/require-less/README.md new file mode 100644 index 0000000..ebf5361 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/README.md @@ -0,0 +1,68 @@ +require-less +=========== + +Optimizable LESS requiring with RequireJS + +Based on the [require-css module](https://github.com/guybedford/require-css), read the documentation there for usage instructions. + +Basic Overview +-------------- + +Allows the construction of scripts that can require LESS files, using the simple RequireJS syntax: + +```javascript +define(['less!styles/main'], function() { + //code that requires the stylesheet: styles/main.less +}); +``` + +When run the in the browser, less is downloaded, parsed and injected. When running a build with the RequireJS optimizer, less is compiled into the build layers dynamically as css with compression support. + +Installation and Setup +---------------------- + +Download the require-less folder manually or use [volo](https://github.com/volojs/volo)(`npm install volo -g`): + +``` +volo add guybedford/require-less +``` + +Volo will automatically download [require-css](https://github.com/guybedford/require-css/zipball/master), which is a needed dependency. + +Then add the following package configuration in RequireJS: + +```javascript +packages: [ + { + name: 'css', + location: 'require-css', + main: 'css' + }, + { + name: 'less', + location: 'require-less', + main: 'less' + } +] +``` + +Builds +------ + +The RequireCSS build system is used to build LESS. The exact same options thus apply. + +Pending [r.js issue 289](https://github.com/jrburke/r.js/issues/289), the modules `require-css/css-builder` and `require-less/lessc` require a shallow exclude. + +Thus, add the following shallow exclusions in the r.js build configuration for each module if using `modules` for a layered build, or at the base-level build configuration if doing a file-based build: + +```javascript +{ + excludeShallow: ['css/css-builder', 'less/lessc-server', 'less/lessc'], + include: ['css'] +} +``` + +This shouldn't be necessary in future versions. + +Note also that the `css` module itself must be included at the beginning of the layer otherwise this will result in a separate HTTP request to CSS. + http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/bower.json ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/bower.json b/src/fauxton/assets/js/plugins/require-less/bower.json new file mode 100644 index 0000000..f2765f2 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/bower.json @@ -0,0 +1,4 @@ +{ + "name": "require-less", + "version": "0.0.6" +} http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/example/build.js ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/example/build.js b/src/fauxton/assets/js/plugins/require-less/example/build.js new file mode 100644 index 0000000..2eb3888 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/example/build.js @@ -0,0 +1,30 @@ +({ + appDir: 'www', + dir: 'www-built', + baseUrl: '.', + fileExclusionRegExp: /(^example)|(.git)$/, + packages: [ + { + name: 'css', + location: 'require-css', + main: 'css' + }, + { + name: 'less', + location: 'require-less', + main: 'less' + } + ], + modules: [ + { + name: 'core-components', + create: true, + include: ['css', 'components/component'], + excludeShallow: ['css/css-builder', 'less/lessc-server', 'less/lessc'] + }, + { + name: 'app', + exclude: ['core-components', 'less'] + } + ] +}) http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/example/setup.sh ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/example/setup.sh b/src/fauxton/assets/js/plugins/require-less/example/setup.sh new file mode 100755 index 0000000..a3e2e4f --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/example/setup.sh @@ -0,0 +1,3 @@ +cd www +ln -s ../../ require-less +ln -s ../../../require-css require-css http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/example/test.html ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/example/test.html b/src/fauxton/assets/js/plugins/require-less/example/test.html new file mode 100644 index 0000000..517024f --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/example/test.html @@ -0,0 +1,29 @@ + + + + + + + + +

test

+ http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/example/www/app.js ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/example/www/app.js b/src/fauxton/assets/js/plugins/require-less/example/www/app.js new file mode 100644 index 0000000..e9842ec --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/example/www/app.js @@ -0,0 +1,3 @@ +define(['components/component', 'less!less-style/style', 'css!css-style'], function(component) { + return 'uses the component!'; +}); http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/example/www/components/component.js ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/example/www/components/component.js b/src/fauxton/assets/js/plugins/require-less/example/www/components/component.js new file mode 100644 index 0000000..d56c016 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/example/www/components/component.js @@ -0,0 +1,3 @@ +define(['less!./component'], function() { + return {component: 'is here'}; +}); http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/example/www/components/component.less ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/example/www/components/component.less b/src/fauxton/assets/js/plugins/require-less/example/www/components/component.less new file mode 100644 index 0000000..2e677f7 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/example/www/components/component.less @@ -0,0 +1,5 @@ +/* component.less */ +@color: red; +body { + background-color: @color; +} http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/example/www/css-style.css ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/example/www/css-style.css b/src/fauxton/assets/js/plugins/require-less/example/www/css-style.css new file mode 100644 index 0000000..eea8230 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/example/www/css-style.css @@ -0,0 +1,3 @@ +body { + font-family: arial; +} http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/example/www/less-style/style.less ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/example/www/less-style/style.less b/src/fauxton/assets/js/plugins/require-less/example/www/less-style/style.less new file mode 100644 index 0000000..8a2d0d4 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/example/www/less-style/style.less @@ -0,0 +1,4 @@ +@import './test.less'; +h1 { + color: @mycolor; +} http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/example/www/less-style/test.less ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/example/www/less-style/test.less b/src/fauxton/assets/js/plugins/require-less/example/www/less-style/test.less new file mode 100644 index 0000000..487f922 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/example/www/less-style/test.less @@ -0,0 +1 @@ +@mycolor: #00f; http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/example/www/require-css ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/example/www/require-css b/src/fauxton/assets/js/plugins/require-less/example/www/require-css new file mode 120000 index 0000000..90c1e86 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/example/www/require-css @@ -0,0 +1 @@ +../../../require-css \ No newline at end of file http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/example/www/require-less ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/example/www/require-less b/src/fauxton/assets/js/plugins/require-less/example/www/require-less new file mode 120000 index 0000000..6581736 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/example/www/require-less @@ -0,0 +1 @@ +../../ \ No newline at end of file http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/example/www/test.html ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/example/www/test.html b/src/fauxton/assets/js/plugins/require-less/example/www/test.html new file mode 100644 index 0000000..a1849f7 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/example/www/test.html @@ -0,0 +1,29 @@ + + + + + + + + +

test

+ http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/example/www/text.js ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/example/www/text.js b/src/fauxton/assets/js/plugins/require-less/example/www/text.js new file mode 100644 index 0000000..38f6ca0 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/example/www/text.js @@ -0,0 +1,282 @@ +/** + * @license RequireJS text 1.0.8 Copyright (c) 2010-2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/requirejs for details + */ +/*jslint regexp: true, plusplus: true, sloppy: true */ +/*global require: false, XMLHttpRequest: false, ActiveXObject: false, + define: false, window: false, process: false, Packages: false, + java: false, location: false */ + +(function () { + var progIds = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0'], + xmlRegExp = /^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, + bodyRegExp = /]*>\s*([\s\S]+)\s*<\/body>/im, + hasLocation = typeof location !== 'undefined' && location.href, + defaultProtocol = hasLocation && location.protocol && location.protocol.replace(/\:/, ''), + defaultHostName = hasLocation && location.hostname, + defaultPort = hasLocation && (location.port || undefined), + buildMap = []; + + define(function () { + var text, fs; + + text = { + version: '1.0.8', + + strip: function (content) { + //Strips declarations so that external SVG and XML + //documents can be added to a document without worry. Also, if the string + //is an HTML document, only the part inside the body tag is returned. + if (content) { + content = content.replace(xmlRegExp, ""); + var matches = content.match(bodyRegExp); + if (matches) { + content = matches[1]; + } + } else { + content = ""; + } + return content; + }, + + jsEscape: function (content) { + return content.replace(/(['\\])/g, '\\$1') + .replace(/[\f]/g, "\\f") + .replace(/[\b]/g, "\\b") + .replace(/[\n]/g, "\\n") + .replace(/[\t]/g, "\\t") + .replace(/[\r]/g, "\\r"); + }, + + createXhr: function () { + //Would love to dump the ActiveX crap in here. Need IE 6 to die first. + var xhr, i, progId; + if (typeof XMLHttpRequest !== "undefined") { + return new XMLHttpRequest(); + } else if (typeof ActiveXObject !== "undefined") { + for (i = 0; i < 3; i++) { + progId = progIds[i]; + try { + xhr = new ActiveXObject(progId); + } catch (e) {} + + if (xhr) { + progIds = [progId]; // so faster next time + break; + } + } + } + + return xhr; + }, + + /** + * Parses a resource name into its component parts. Resource names + * look like: module/name.ext!strip, where the !strip part is + * optional. + * @param {String} name the resource name + * @returns {Object} with properties "moduleName", "ext" and "strip" + * where strip is a boolean. + */ + parseName: function (name) { + var strip = false, index = name.indexOf("."), + modName = name.substring(0, index), + ext = name.substring(index + 1, name.length); + + index = ext.indexOf("!"); + if (index !== -1) { + //Pull off the strip arg. + strip = ext.substring(index + 1, ext.length); + strip = strip === "strip"; + ext = ext.substring(0, index); + } + + return { + moduleName: modName, + ext: ext, + strip: strip + }; + }, + + xdRegExp: /^((\w+)\:)?\/\/([^\/\\]+)/, + + /** + * Is an URL on another domain. Only works for browser use, returns + * false in non-browser environments. Only used to know if an + * optimized .js version of a text resource should be loaded + * instead. + * @param {String} url + * @returns Boolean + */ + useXhr: function (url, protocol, hostname, port) { + var match = text.xdRegExp.exec(url), + uProtocol, uHostName, uPort; + if (!match) { + return true; + } + uProtocol = match[2]; + uHostName = match[3]; + + uHostName = uHostName.split(':'); + uPort = uHostName[1]; + uHostName = uHostName[0]; + + return (!uProtocol || uProtocol === protocol) && + (!uHostName || uHostName === hostname) && + ((!uPort && !uHostName) || uPort === port); + }, + + finishLoad: function (name, strip, content, onLoad, config) { + content = strip ? text.strip(content) : content; + if (config.isBuild) { + buildMap[name] = content; + } + onLoad(content); + }, + + load: function (name, req, onLoad, config) { + //Name has format: some.module.filext!strip + //The strip part is optional. + //if strip is present, then that means only get the string contents + //inside a body tag in an HTML string. For XML/SVG content it means + //removing the declarations so the content can be inserted + //into the current doc without problems. + + // Do not bother with the work if a build and text will + // not be inlined. + if (config.isBuild && !config.inlineText) { + onLoad(); + return; + } + + var parsed = text.parseName(name), + nonStripName = parsed.moduleName + '.' + parsed.ext, + url = req.toUrl(nonStripName), + useXhr = (config && config.text && config.text.useXhr) || + text.useXhr; + + //Load the text. Use XHR if possible and in a browser. + if (!hasLocation || useXhr(url, defaultProtocol, defaultHostName, defaultPort)) { + text.get(url, function (content) { + text.finishLoad(name, parsed.strip, content, onLoad, config); + }); + } else { + //Need to fetch the resource across domains. Assume + //the resource has been optimized into a JS module. Fetch + //by the module name + extension, but do not include the + //!strip part to avoid file system issues. + req([nonStripName], function (content) { + text.finishLoad(parsed.moduleName + '.' + parsed.ext, + parsed.strip, content, onLoad, config); + }); + } + }, + + write: function (pluginName, moduleName, write, config) { + if (buildMap.hasOwnProperty(moduleName)) { + var content = text.jsEscape(buildMap[moduleName]); + write.asModule(pluginName + "!" + moduleName, + "define(function () { return '" + + content + + "';});\n"); + } + }, + + writeFile: function (pluginName, moduleName, req, write, config) { + var parsed = text.parseName(moduleName), + nonStripName = parsed.moduleName + '.' + parsed.ext, + //Use a '.js' file name so that it indicates it is a + //script that can be loaded across domains. + fileName = req.toUrl(parsed.moduleName + '.' + + parsed.ext) + '.js'; + + //Leverage own load() method to load plugin value, but only + //write out values that do not have the strip argument, + //to avoid any potential issues with ! in file names. + text.load(nonStripName, req, function (value) { + //Use own write() method to construct full module value. + //But need to create shell that translates writeFile's + //write() to the right interface. + var textWrite = function (contents) { + return write(fileName, contents); + }; + textWrite.asModule = function (moduleName, contents) { + return write.asModule(moduleName, fileName, contents); + }; + + text.write(pluginName, nonStripName, textWrite, config); + }, config); + } + }; + + if (text.createXhr()) { + text.get = function (url, callback) { + var xhr = text.createXhr(); + xhr.open('GET', url, true); + xhr.onreadystatechange = function (evt) { + //Do not explicitly handle errors, those should be + //visible via console output in the browser. + if (xhr.readyState === 4) { + callback(xhr.responseText); + } + }; + xhr.send(null); + }; + } else if (typeof process !== "undefined" && + process.versions && + !!process.versions.node) { + //Using special require.nodeRequire, something added by r.js. + fs = require.nodeRequire('fs'); + + text.get = function (url, callback) { + var file = fs.readFileSync(url, 'utf8'); + //Remove BOM (Byte Mark Order) from utf8 files if it is there. + if (file.indexOf('\uFEFF') === 0) { + file = file.substring(1); + } + callback(file); + }; + } else if (typeof Packages !== 'undefined') { + //Why Java, why is this so awkward? + text.get = function (url, callback) { + var encoding = "utf-8", + file = new java.io.File(url), + lineSeparator = java.lang.System.getProperty("line.separator"), + input = new java.io.BufferedReader(new java.io.InputStreamReader(new java.io.FileInputStream(file), encoding)), + stringBuffer, line, + content = ''; + try { + stringBuffer = new java.lang.StringBuffer(); + line = input.readLine(); + + // Byte Order Mark (BOM) - The Unicode Standard, version 3.0, page 324 + // http://www.unicode.org/faq/utf_bom.html + + // Note that when we use utf-8, the BOM should appear as "EF BB BF", but it doesn't due to this bug in the JDK: + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 + if (line && line.length() && line.charAt(0) === 0xfeff) { + // Eat the BOM, since we've already found the encoding on this file, + // and we plan to concatenating this buffer with others; the BOM should + // only appear at the top of a file. + line = line.substring(1); + } + + stringBuffer.append(line); + + while ((line = input.readLine()) !== null) { + stringBuffer.append(lineSeparator); + stringBuffer.append(line); + } + //Make sure we return a JavaScript string and not a Java string. + content = String(stringBuffer.toString()); //String + } finally { + input.close(); + } + callback(content); + }; + } + + return text; + }); +}()); http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/less-builder.js ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/less-builder.js b/src/fauxton/assets/js/plugins/require-less/less-builder.js new file mode 100644 index 0000000..b296f92 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/less-builder.js @@ -0,0 +1,42 @@ +define(['css/css-builder', './lessc-server', 'require'], function(css, lessc, req) { + var less = {}; + + var baseParts = req.toUrl('base_url').split('/'); + baseParts.pop(); + var baseUrl = baseParts.join('/'); + + // include the base url as a path + var parser = new lessc.Parser({ + paths: [baseUrl + '/'] + }); + + var parseLess = function(less) { + var CSS; + parser.parse(less, function(err, tree) { + if (err) + throw err; + CSS = tree.toCSS(); + }); + return CSS; + } + + less.normalize = function(name, normalize) { + if (name.substr(name.length - 5, 5) == '.less') + name = name.substr(0, name.length - 5); + return normalize(name); + } + + less.load = function(name, req, load, config) { + css.load(name, req, load, config, parseLess); + } + + less.write = function(pluginName, moduleName, write) { + css.write(pluginName, moduleName, write, parseLess); + } + + less.onLayerEnd = function(write, data) { + css.onLayerEnd(write, data, true); + } + + return less; +}); http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/less.js ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/less.js b/src/fauxton/assets/js/plugins/require-less/less.js new file mode 100644 index 0000000..b7e0ae2 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/less.js @@ -0,0 +1,46 @@ +define(['css', 'require'], function(css, require) { + + var less = {}; + + less.pluginBuilder = './less-builder'; + + if (typeof window == 'undefined') { + less.load = function(n, r, load) { load(); } + return less; + } + + //copy api methods from the css plugin + less.normalize = function(name, normalize) { + if (name.substr(name.length - 5, 5) == '.less') + name = name.substr(0, name.length - 5); + + name = normalize(name); + + return name; + } + + less.parse = function(less, callback) { + require(['./lessc'], function(lessc) { + var css; + var parser = new lessc.Parser(); + parser.parse(less, function(err, tree) { + if (err) + throw err; + try { + css = tree.toCSS(); + } + catch(e) { + throw new Error("LESS parse error: " + e.type + ", " + e.message); + } + //instant callback luckily for builds + callback(css); + }); + }); + } + + less.load = function(lessId, req, load, config) { + css.load(lessId, req, load, config, less.parse); + } + + return less; +}); http://git-wip-us.apache.org/repos/asf/couchdb/blob/4d06c100/src/fauxton/assets/js/plugins/require-less/lessc-server.js ---------------------------------------------------------------------- diff --git a/src/fauxton/assets/js/plugins/require-less/lessc-server.js b/src/fauxton/assets/js/plugins/require-less/lessc-server.js new file mode 100644 index 0000000..7866de4 --- /dev/null +++ b/src/fauxton/assets/js/plugins/require-less/lessc-server.js @@ -0,0 +1,96 @@ +define(['./lessc'], function(less) { + + if (['node', 'rhino'].indexOf(less.mode) == -1) { + throw new Error('Environment not supported by require-less builder: ' + less.mode); + } + + var readFile = (function() { + if (less.mode === 'node') { + var fs = require.nodeRequire('fs'); + var path = require.nodeRequire('path'); + return function(pathname) { + return fs.readFileSync(pathname, 'utf-8'); + }; + } else if (less.mode === 'rhino') { + return function(pathname) { + return readFile(pathname, 'UTF-8'); + }; + } + }()); + + var checkPath = (function() { + if (less.mode === 'node') { + var fs = require.nodeRequire('fs'); + var path = require.nodeRequire('path'); + return function(pathname, file) { + try { + pathname = path.join(pathname, file); + fs.statSync(pathname); + return pathname; + } catch (e) { + return null; + } + }; + } else if (less.mode === 'rhino') { + return function(pathname, file) { + var f = new java.io.File(pathname, file); + if (f.isFile()) { + return f.getPath(); + } else { + return null; + } + }; + } + }()); + + less.Parser.importer = function (file, paths, callback, env) { + var pathname, data; + + // TODO: Undo this at some point, + // or use different approach. + var paths = [].concat(paths); + paths.push('.'); + + for (var i = 0; i < paths.length; i++) { + pathname = checkPath(paths[i], file); + if (pathname != null) { + break; + } + } + + paths = paths.slice(0, paths.length - 1); + + if (!pathname) { + if (typeof(env.errback) === "function") { + env.errback(file, paths, callback); + } else { + callback({ type: 'File', message: "'" + file + "' wasn't found.\n" }); + } + return; + } + + function parseFile(e, data) { + if (e) return callback(e); + env.contents = env.contents || {}; + env.contents[pathname] = data; // Updating top importing parser content cache. + new(less.Parser)({ + paths: [path.dirname(pathname)].concat(paths), + filename: pathname, + contents: env.contents, + files: env.files, + syncImport: env.syncImport, + dumpLineNumbers: env.dumpLineNumbers + }).parse(data, function (e, root) { + callback(e, root, pathname); + }); + }; + + try { + readFile(pathname); + parseFile(null, data); + } catch (e) { + parseFile(e); + } + } + return less; +}); \ No newline at end of file