Skip to content
This repository has been archived by the owner on Jan 10, 2020. It is now read-only.

Commit

Permalink
Merge branch 'roadrunner'
Browse files Browse the repository at this point in the history
Conflicts:
	componentbuild/shared/cssmodule.xml

Super fast builds with YUI Compressor server.
  • Loading branch information
reid committed Oct 20, 2010
2 parents cd712cf + 4ae244c commit 80bb5b7
Show file tree
Hide file tree
Showing 8 changed files with 2,077 additions and 1,095 deletions.
2 changes: 1 addition & 1 deletion componentbuild/3.x/module.xml
Expand Up @@ -95,7 +95,7 @@

<target name="-concatskins" if="component.skins.exist">
<concatsource destfile="${component.builddir}/assets/skins/sam/${component}.css" sourcedir="${component.assets.base}" sourcefiles="${component}-core.css, skins/sam/${component}-skin.css" />
<yuicompress src="${component.builddir}/assets/skins/sam/${component}.css" dest="${component.builddir}/assets/skins/sam/${component}.css" args="${yuicompressor.css.args.internal}" />
<yuicompress type="css" src="${component.builddir}/assets/skins/sam/${component}.css" dest="${component.builddir}/assets/skins/sam/${component}.css" args="${yuicompressor.css.args.internal}" />
</target>

<target name="-rollupcss" if="rollupskins">
Expand Down
2,839 changes: 1,777 additions & 1,062 deletions componentbuild/lib/jslint/fulljslint.js

Large diffs are not rendered by default.

117 changes: 117 additions & 0 deletions componentbuild/lib/jslint/jslint-node.js
@@ -0,0 +1,117 @@
/**
* Javascript Shell Script to Load and JSLint js files through Rhino Javascript Shell
* The jslint source file is expected as the first argument, followed by the list of JS files to JSLint
*
* e.g.
* java -j js.jar /tools/fulljslint.js testFile1.js testFile2.js testFile3.js
**/

JSLINT = require("./fulljslint").JSLINT;

(function(){ // Just to keep stuff seperate from JSLINT code

var PORT = parseInt(process.argv[2]) || 8081;

var OPTS = {
browser : true,
//laxLineEnd : true,
undef: true,
newcap: false
};

function test(js) {
var body = "", code = 200;

var success = JSLINT(js, OPTS);
if (success) {
return "OK";
} else {
for (var i=0; i < JSLINT.errors.length; ++i) {
var e = JSLINT.errors[i];
if (e) {
body += ("\t" + e.line + ", " + e.character + ": " + e.reason + "\n\t" + clean(e.evidence) + "\n");
}
}
body += "\n";

// Last item is null if JSLint hit a fatal error
if (JSLINT.errors && JSLINT.errors[JSLINT.errors.length-1] === null) {
code = 500;
}
return {
"content" : body,
"code" : code
};
}
}

function clean(str) {
var trimmed = "";
if (str) {
if(str.length <= 500) {
trimmed = str.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1");
} else {
trimmed = "[Code Evidence Omitted: Greater than 500 chars]";
}
}
return trimmed;
}

var qs = require("querystring");
var fs = require("fs");
var EventEmitter = require("events").EventEmitter;

var ticket = 0;

require("http").createServer(function (req, res) {
var data = "";
req.addListener("data", function (chunk) {
data += chunk;
});
var proc = new EventEmitter();
proc.addListener("end", function (code, body, die) {
res.writeHead(code, {"Content-type" : "text/plain"});
res.end(body);
if (die) process.exit(0);
});
req.addListener("end", function () {
ticket++;
var code = 200, body;
var die = "/kill" === req.url;
if (die) body = "Goodbye.";
else if (req.method === "POST") {
var query = qs.parse(data);
var files = query["files"].split("' '");
var failOnError = query["failonerror"] == "true";
var results = [];
files.forEach(function (file) {
fs.readFile(file, function (err, data) {
var diagnosis = test(data.toString("utf8"));
results.push(diagnosis.content);

code = (
failOnError &&
diagnosis.code !== 200
) ? diagnosis.code : code;

if (results.length == files.length) proc.emit("end", code, results.join("\n"));
});
});
} else {
body = "Ready.";
}
if (body) proc.emit("end", code, body, die);
});
}).listen(PORT, "127.0.0.1");

require("sys").puts("Server started on port " + PORT);

(function () {
var reap;
setInterval(function () {
if (reap == ticket) process.exit(0);
reap = ticket;
}, 10000);
})();
})();

Binary file not shown.
2 changes: 1 addition & 1 deletion componentbuild/shared/cssmodule.xml
Expand Up @@ -12,7 +12,7 @@
</target>

<target name="minify">
<yuicompress src="${component.builddir}/${component.basefilename}.css" dest="${component.builddir}/${component.basefilename}-min.css" args="${yuicompressor.css.args.internal}" />
<yuicompress type="css" src="${component.builddir}/${component.basefilename}.css" dest="${component.builddir}/${component.basefilename}-min.css" args="${yuicompressor.css.args.internal}" />
</target>

<target name="lint">
Expand Down
150 changes: 122 additions & 28 deletions componentbuild/shared/macrolib.xml
Expand Up @@ -69,20 +69,86 @@
</sequential>
</macrodef>

<macrodef name="yuicompress">
<attribute name="src" />
<attribute name="dest" />
<attribute name="args" />

<sequential>
<echo level="info">Running yuicompressor on @{src}</echo>
<java jar="${yuicompressor.jar}" fork="true" failonerror="true">
<arg line="@{args} -o" />
<arg file="@{dest}" />
<arg file="@{src}" />
</java>
</sequential>
</macrodef>
<if>
<or>
<istrue value="${yuicompressor.online}"/>
<http url="${yuicompressor.url}" errorsBeginAt="500"/>
</or>
<then>
<property name="yuicompressor.online" value="true"/>
<macrodef name="yuicompress">
<attribute name="src" />
<attribute name="dest" />
<attribute name="args" /> <!-- not used by this task branch -->
<attribute name="type" default="js"/>
<sequential>
<property name="yuicompressor.output" value="@{dest}"/>
<property name="yuicompressor.file" value="@{src}"/>
<echo>If this web request fails, try building again with -Dyuicompressor.online=false or install the cURL executable into your PATH.</echo>
<exec executable="curl" input="@{src}" outputproperty="yuicompressor.result" failonerror="true">
<arg value="--silent"/>
<arg line="--data-urlencode "/>
<arg line="@${yuicompressor.file}"/>
<arg line="${yuicompressor.url}?type=@{type}"/>
</exec>
<script language="javascript">
<![CDATA[
var echo;
var project = self.getProject();
var res = project.getProperty("yuicompressor.result");
res = eval("(" + res + ")");
function w (str, level) {
var echo = project.createTask("echo");
echo.setMessage(str);
echo.perform();
}
if (!res.result) {
var fail = project.createTask("fail");
fail.setMessage("Failed to minify!");
fail.perform();
}
function notify (level, errors) {
for (var i = 0, l = errors.length; i < l; i++) {
w(errors[i], level);
}
}
notify("error", res.errors);
notify("warning", res.warnings);
project.setProperty("yuicompressor.script", res.result);
]]>
</script>
<echo file="@{dest}" message="${yuicompressor.script}"/>
<var name="yuicompressor.output" unset="true"/>
<var name="yuicompressor.script" unset="true"/>
<var name="yuicompressor.file" unset="true"/>
<var name="yuicompressor.result" unset="true"/>
</sequential>
</macrodef>
</then>
<else>
<echo level="info">Using forked yuicompressor, to speed up builds make sure the YUI Compressor server is started.</echo>
<macrodef name="yuicompress">
<attribute name="src" />
<attribute name="dest" />
<attribute name="args" />
<attribute name="type" default="js"/> <!-- not used by this task branch -->
<sequential>
<echo level="info">Running yuicompressor on @{src} with @{args}</echo>
<java jar="${yuicompressor.jar}" fork="true" failonerror="true">
<arg line="@{args} -o" />
<arg file="@{dest}" />
<arg file="@{src}" />
</java>
</sequential>
</macrodef>
</else>
</if>

<macrodef name="concatsource">
<attribute name="destfile" />
Expand Down Expand Up @@ -117,24 +183,52 @@

<macrodef name="jslint">
<element name="jsfiles" optional="false" />

<sequential>
<!--
Need to find a way to convert fileset to args (script?) to
avoid ' ', which will break for files with ' in them
Evaluates to the following java execution line...
java -r js.jar jslintconsole.js 'file1.js' 'file2.js' 'file3.js'
-->
<pathconvert pathsep="' '" property="jsfileargs">
<jsfiles />
</pathconvert>

<java jar="${rhino.jar}" fork="true" failonerror="true">
<arg file="${jslintconsole.js}" />
<arg value="${jslintsrc.js}" />
<arg line="'${jsfileargs}'" />
</java>

<if>
<or>
<istrue value="${node.online}"/>
<http url="${node.jslint.url}"/>
</or>
<then>
<property name="node.online" value="true"/>
<post to="${node.jslint.url}" property="node.jslint.response" failonerror="${lint.failonerror}">
<prop name="files" value="${jsfileargs}"/>
<prop name="failonerror" value="${lint.failonerror}"/>
</post>
<!-- Since Ant doesn't really failonerror for the post task,
handle this ourselves: -->
<if>
<not>
<isset property="node.jslint.response"/>
</not>
<then>
<fail>JSLint failed. To view lint output and continue the build, run ant with -Dlint.failonerror=false.</fail>
</then>
</if>
<!-- Clear property for next run: -->
<var name="node.jslint.response" unset="true"/>
</then>
<else>
<echo>Using Rhino. Install nodejs to improve jslint speed, or skip with -Dlint.skip=true</echo>
<!--
Need to find a way to convert fileset to args (script?) to
avoid ' ', which will break for files with ' in them
Evaluates to the following java execution line...
java -r js.jar jslintconsole.js 'file1.js' 'file2.js' 'file3.js'
-->

<java jar="${rhino.jar}" fork="true" failonerror="${jslint.failonerror}">
<arg file="${jslintconsole.js}" />
<arg value="${jslintsrc.js}" />
<arg line="'${jsfileargs}'" />
</java>
</else>
</if>
</sequential>
</macrodef>

Expand Down
15 changes: 12 additions & 3 deletions componentbuild/shared/properties.xml
Expand Up @@ -25,17 +25,19 @@
<property name="rhino.jar" location="${builddir}/lib/rhino/js.jar" />
<property name="jslintconsole.js" location="${builddir}/lib/jslint/jslint-console.js" />
<property name="jslintsrc.js" location="${builddir}/lib/jslint/fulljslint.js" />
<property name="yuicompressor.jar" location="${builddir}/lib/yuicompressor/yuicompressor-2.4.jar" />
<property name="yuicompressor.jar" location="${builddir}/lib/yuicompressor/yuicompressor-2.4.5pre.jar" />
<property name="yrb2jsonconsole.js" location="${builddir}/lib/yrb2json/yrb2json-console.js" />
<property name="yrb2jsonsrc.js" location="${builddir}/lib/yrb2json/yrb2json.js" />

<!-- YUI Compressor arguments for JS and CSS files -->
<property name="yuicompressor.css.args" value="--type css --line-break 6000" />
<property name="yuicompressor.js.args" value="--disable-optimizations --preserve-semi --line-break 6000" />

<property name="yuicompressor.js.charset" value="utf-8" />
<property name="yuicompressor.css.charset" value="utf-8" />

<property name="yuicompressor.js.args" value="--disable-optimizations --preserve-semi --line-break 6000" />
<property name="yuicompressor.css.args" value="--line-break 6000" />
<property name="yuicompressor.port" value="8091"/>

<!-- Enable/Disable YUI Compressor verbosity. NOTE: Checked in build files should not disable this flag -->
<property name="yuicompressor.js.verbose" value="true" />
<property name="yuicompressor.css.verbose" value="true" />
Expand Down Expand Up @@ -156,4 +158,11 @@
<isset property="component.cssfiles" />
</condition>

<!-- By default, jslint failure should fail the build.
This can be overridden on the command line. -->
<property name="lint.failonerror" value="true"/>

<property name="node.jslint.url" value="http://127.0.0.1:8081/"/>
<property name="yuicompressor.url" value="http://127.0.0.1:${yuicompressor.port}/compress"/>

</project>
47 changes: 47 additions & 0 deletions componentbuild/shared/targets.xml
Expand Up @@ -31,6 +31,53 @@
<tstamp/>
<mkdir dir="${component.builddir}" />
<createdetails />
<antcall target="-yuicompressor"/>
<antcall target="-lint-server"/>
</target>

<target name="-lint-server" description="Start JSLint Server" unless="lint.skip">
<antcall target="-node">
<param name="src" value="${builddir}/lib/jslint/jslint-node.js"/>
</antcall>
</target>

<target name="-node" description="Start NodeJS Server" unless="node.spawn">
<if>
<not>
<http url="${node.jslint.url}"/>
</not>
<then>
<echo level="info">Attempting to start NodeJS app at: ${src}</echo>
<exec executable="node" spawn="true">
<arg value="${src}"/>
</exec>
<!-- Don't fail if node doesn't exist, fails to start, etc.
We will fallback to the slow Rhino engine later. -->
</then>
</if>
<!-- Don't try to start again. -->
<property name="node.spawn" value="true"/>
</target>

<target name="-yuicompressor" description="Start YUI Compressor Server" unless="yuicompressor.spawn">
<if>
<not>
<http url="${yuicompressor.url}"/>
</not>
<then>
<echo level="info">Attempting to start YUI Compressor server.</echo>
<java classname="com.yahoo.platform.yui.compressor.Bootstrap" fork="true" spawn="true">
<arg line="--server"/>
<arg line="${yuicompressor.port}"/>
<arg line="${yuicompressor.js.args}"/>
<arg line="${yuicompressor.js.args.internal}"/>
<classpath>
<pathelement location="${yuicompressor.jar}"/>
</classpath>
</java>
</then>
</if>
<property name="yuicompressor.spawn" value="true"/>
</target>

<target name="clean" description="Clean Local Build Directory" unless="clean.skip">
Expand Down

0 comments on commit 80bb5b7

Please sign in to comment.