From 4210cfd2d162adbab88911cc208913cd1aa4002d Mon Sep 17 00:00:00 2001 From: Oliver Becker Date: Mon, 11 Nov 2013 22:15:42 +0100 Subject: [PATCH] started data-uri implementation, added basic console formatting support --- build.gradle | 2 +- build/build.yml | 2 +- build/rhino-header.js | 41 ++++++++++++++++++++--- build/{rhino-path.js => rhino-modules.js} | 33 +++++++++++++++--- lib/less/functions.js | 12 ++++--- lib/less/rhino.js | 17 +++++++--- 6 files changed, 88 insertions(+), 19 deletions(-) rename build/{rhino-path.js => rhino-modules.js} (58%) diff --git a/build.gradle b/build.gradle index 3b8d9481..18b53b2b 100644 --- a/build.gradle +++ b/build.gradle @@ -50,7 +50,7 @@ task testRhino { } task testRhinoBase(type: RhinoTest) { - options = [ '--strict-math=true' ] + options = [ '--strict-math=true', '--relative-urls' ] } task testRhinoErrors(type: RhinoTest) { diff --git a/build/build.yml b/build/build.yml index 89e8f4e7..3879d2ba 100644 --- a/build/build.yml +++ b/build/build.yml @@ -20,7 +20,7 @@ lib: lib/less # ================================= prepend: browser: ['build/require.js', 'build/browser-header.js'] - rhino: ['build/require-rhino.js', 'build/rhino-header.js', 'build/rhino-path.js'] + rhino: ['build/require-rhino.js', 'build/rhino-header.js', 'build/rhino-modules.js'] append: amd: build/amd.js diff --git a/build/rhino-header.js b/build/rhino-header.js index ef81a51b..4da24ddd 100644 --- a/build/rhino-header.js +++ b/build/rhino-header.js @@ -3,8 +3,41 @@ else { less = window.less = {} } tree = less.tree = {}; less.mode = 'rhino'; -console = { - log: function(arg) { - java.lang.System.err.println(arg); +console = function() { + var stdout = java.lang.Systen.out; + var stderr = java.lang.System.err; + + function doLog(out, type) { + return function() { + var args = java.lang.reflect.Array.newInstance(java.lang.Object, arguments.length - 1); + var format = arguments[0]; + var conversionIndex = 0; + // need to look for %d (integer) conversions because in Javascript all numbers are doubles + for (var i = 1; i < arguments.length; i++) { + var arg = arguments[i]; + if (conversionIndex != -1) { + conversionIndex = format.indexOf('%', conversionIndex); + } + if (conversionIndex >= 0 && conversionIndex < format.length) { + var conversion = format.charAt(conversionIndex + 1); + if (conversion === 'd' && typeof arg === 'number') { + arg = new java.lang.Integer(new java.lang.Double(arg).intValue()); + } + conversionIndex++; + } + args[i-1] = arg; + } + try { + out.println(type + java.lang.String.format(format, args)); + } catch(ex) { + stderr.println(ex); + } + } } -}; + return { + log: doLog(stdout, ''), + info: doLog(stdout, 'INFO: '), + error: doLog(stderr, 'ERROR: '), + warn: doLog(stderr, 'WARN: ') + }; +}(); diff --git a/build/rhino-path.js b/build/rhino-modules.js similarity index 58% rename from build/rhino-path.js rename to build/rhino-modules.js index f79b0654..62c50391 100644 --- a/build/rhino-path.js +++ b/build/rhino-modules.js @@ -17,6 +17,11 @@ less._path = { } return result.join('/'); }, + dirname: function(p) { + var path = p.split('/'); + path.pop(); + return path.join('/'); + }, basename: function(p, ext) { var base = p.split('/').pop(); if (ext) { @@ -27,9 +32,29 @@ less._path = { } return base; }, - dirname: function(p) { - var path = p.split('/'); - path.pop(); - return path.join('/'); + extname: function(p) { + var index = p.lastIndexOf('.'); + return index > 0 ? p.substring(index) : ''; + } +}; + +less._fs = { + readFileSync: function(name) { + var file = new java.io.File(name); + var stream = new java.io.FileInputStream(file); + var buffer = []; + var c; + while ((c = stream.read()) != -1) { + buffer.push(c); + } + stream.close(); + return { + length: buffer.length, + toString: function(enc) { + if (enc === 'base64') { + return javax.xml.bind.DatatypeConverter.printBase64Binary(buffer); + } + } + }; } }; diff --git a/lib/less/functions.js b/lib/less/functions.js index aef28ead..fe686b91 100644 --- a/lib/less/functions.js +++ b/lib/less/functions.js @@ -447,15 +447,15 @@ tree.functions = { "data-uri": function(mimetypeNode, filePathNode) { - if (typeof window !== 'undefined' || less.mode == 'rhino') { // TODO rhino implementation + if (typeof window !== 'undefined') { return new tree.URL(filePathNode || mimetypeNode, this.currentFileInfo).eval(this.env); } var mimetype = mimetypeNode.value; var filePath = (filePathNode && filePathNode.value); - var fs = require("fs"), - path = require("path"), + var fs = require('fs') || less._fs, + path = require('path') || less._path, useBase64 = false; if (arguments.length < 2) { @@ -478,6 +478,9 @@ tree.functions = { } catch (ex) { mime = tree._mime; } + if (typeof mime === 'undefined') { + mime = tree._mime; + } mimetype = mime.lookup(filePath); @@ -605,7 +608,8 @@ tree._mime = { '.png' : 'image/png' }, lookup: function (filepath) { - var ext = require('path').extname(filepath), + var path = require('path') || less._path; + var ext = path.extname(filepath), type = tree._mime._types[ext]; if (type === undefined) { throw new Error('Optional dependency "mime" is required for ' + ext); diff --git a/lib/less/rhino.js b/lib/less/rhino.js index 62ca62b1..4f516100 100644 --- a/lib/less/rhino.js +++ b/lib/less/rhino.js @@ -86,14 +86,13 @@ function loadStyleSheet(sheet, callback, reload, remaining) { }); } -less.Parser.fileLoader = function (originalHref, currentFileInfo, callback, env, newVars) { +less.Parser.fileLoader = function (file, currentFileInfo, callback, env) { - if (currentFileInfo && currentFileInfo.currentDirectory && !/^\//.test(originalHref)) { - originalHref = less._path.join(currentFileInfo.currentDirectory, originalHref); + var href = file; + if (currentFileInfo && currentFileInfo.currentDirectory && !/^\//.test(file)) { + href = less._path.join(currentFileInfo.currentDirectory, file); } - var href = originalHref; - var path = less._path.dirname(href); var newFileInfo = { @@ -113,6 +112,14 @@ less.Parser.fileLoader = function (originalHref, currentFileInfo, callback, env, newFileInfo.relativeUrls = env.relativeUrls; } + var j = file.lastIndexOf('/'); + if(newFileInfo.relativeUrls && !/^(?:[a-z-]+:|\/)/.test(file) && j != -1) { + var relativeSubDirectory = file.slice(0, j+1); + newFileInfo.rootpath = newFileInfo.rootpath + relativeSubDirectory; // append (sub|sup) directory path of imported file + } + newFileInfo.currentDirectory = path; + newFileInfo.filename = href; + try { var data = readFile(href); } catch (e) {