[javascriptlint-commit] SF.net SVN: javascriptlint:[276] trunk
Status: Beta
Brought to you by:
matthiasmiller
From: <mat...@us...> - 2009-10-08 13:54:36
|
Revision: 276 http://javascriptlint.svn.sourceforge.net/javascriptlint/?rev=276&view=rev Author: matthiasmiller Date: 2009-10-08 13:54:28 +0000 (Thu, 08 Oct 2009) Log Message: ----------- www: implement the online lint Modified Paths: -------------- trunk/www/online_lint.php trunk/www.py Added Paths: ----------- trunk/www/_jsl_online.inc trunk/www/_lint_front.inc Added: trunk/www/_jsl_online.inc =================================================================== --- trunk/www/_jsl_online.inc (rev 0) +++ trunk/www/_jsl_online.inc 2009-10-08 13:54:28 UTC (rev 276) @@ -0,0 +1,221 @@ +<?php + /* This script assumes the following configuration settings: + * +output-format __LINE__,__COL__,__ERROR_NAME__,__ERROR_PREFIX__,__ERROR_MSGENC__ + * + * Example Code: + * require_once("_jsl_online.php"); + * $engine = new JSLEngine('.priv/jsl', '.priv/jsl.server.conf'); + * $result = $engine->Lint($g_sScript); + * if ($result === true) + * OutputLintHTML($engine); + * else + * echo '<b>' . htmlentities($result) . '</b>'; + * + * Suggestions or revisions can be sent to In...@Ja... + */ + + class JSLMessage { + var $_line; + var $_char; + var $_errname; + var $_type; + var $_message; + + function JSLMessage($line) { + $info = explode(",", $line); + if (count($info) >= 4) { + $this->_line = ($info[0]*1); + $this->_char = is_numeric($info[1]) ? ($info[1]*1) : -1; + $this->_errname = $info[2]; + $this->_type = $info[3]; + $this->_message = implode(",", array_slice($info, 4)); + } + } + + function getLine() { return $this->_line; } + function getChar() { return $this->_char; } + function getErrName() { return $this->_errname; } + function getType() { return $this->_type; } + function getMessage() { return $this->_message; } + } + + class JSLEngine { + var $_binarypath, $_confpath; + var $_scriptlines, $_scriptmsgsGeneral, $_scriptmsgsSpecific; + + function JSLEngine($binarypath, $confpath) { + $this->_binarypath = $binarypath; + $this->_confpath = $confpath; + + $this->_scriptlines = Array(); + $this->_scriptmsgsGeneral = Array(); + $this->_scriptmsgsSpecific = Array(); + } + + /* returns error on failure; returns true on success */ + function Lint($code, $maxCodeLengthKB=128) { + if (strlen($code) > $maxCodeLengthKB*1024) + return 'Please limit scripts to ' . $maxCodeLengthKB . 'KB'; + + if (!$this->_launchLintBinary($code, $output)) + return 'The JavaScript Lint online service is currently unavailable.'; + + /* parse the script */ + $this->_scriptlines = explode("\n", str_replace("\r\n", "\n", $code)); + + /* parse the output */ + $output_lines = explode("\n", str_replace("\r\n", "\n", $output)); + foreach ($output_lines as $line) { + /* skip blank lines */ + if (strlen($line) > 0) { + /* store in associative array by 0-based line number */ + $msg = new JSLMessage($line); + + if ($msg->getChar() == -1) + $this->_scriptmsgsGeneral[$msg->getLine()-1][] = $msg; + else + $this->_scriptmsgsSpecific[$msg->getLine()-1][] = $msg; + } + } + + return true; + } + + function getNumLines() { + return count($this->_scriptlines); + } + + function getLineText($i) { + return $this->_scriptlines[$i]; + } + + function getLineMessages($i) { + /* messages that do not point to a specific character should come first */ + if (isset($this->_scriptmsgsGeneral[$i]) && + isset($this->_scriptmsgsSpecific[$i])) { + return array_merge($this->_scriptmsgsGeneral[$i], $this->_scriptmsgsSpecific[$i]); + } + + if (isset($this->_scriptmsgsGeneral[$i])) + return $this->_scriptmsgsGeneral[$i]; + + if (isset($this->_scriptmsgsSpecific[$i])) + return $this->_scriptmsgsSpecific[$i]; + + return Array(); + } + + /* assumes path and that SERVER_SOFTWARE env is set */ + function _launchLintBinary($input, &$output) { + $descriptorspec = array( + 0 => array("pipe", "r"), // stdin is a pipe that the child will read from + 1 => array("pipe", "w"), // stdout is a pipe that the child will write to + 2 => array("pipe", "w") + ); + + /* launch process */ + $path = escapeshellcmd($this->_binarypath) . ' --nologo --nosummary --stdin -context --conf ' . escapeshellarg($this->_confpath); + $process = proc_open($path, $descriptorspec, $pipes); + if (!is_resource($process)) + return false; + + // $pipes now looks like this: + // 0 => writeable handle connected to child stdin + // 1 => readable handle connected to child stdout + // 2 => readable handle connected to child stdout + fwrite($pipes[0], $input); + fclose($pipes[0]); + + $output = ''; + while (!feof($pipes[1])) + $output .= fgets($pipes[1], 1024); + fclose($pipes[1]); + fclose($pipes[2]); + + // It is important that you close any pipes before calling + // proc_close in order to avoid a deadlock + $return_value = proc_close($process); + return true; + } + }; + + function getEncodedText($text) + { + $enc = htmlentities($text); + $enc = str_replace("\n", '<br/>', $enc); + $enc = str_replace(' ', ' ', $enc); + return $enc; + } + + function OutputLintHTML($engine) + { +?> + <style type="text/css"> + div#code + { + color: #999; + font-family: monospace; + } + div#code div + { + color: black; + background-color: #EEE; + } + div#code div span + { + font-weight: bold; + font-family: Arial; + white-space: auto; + font-size: .9em; + color: #F00; + } + </style> +<?php + + /* output script */ + $hasWarnedSemicolon = false; + + $numlines = $engine->getNumLines(); + $widthOfLineNo = strlen($numlines); + $lineNoSpacer = str_pad("", $widthOfLineNo, " ") . ' '; + + echo '<div id="code">'; + for ($lineno = 0; $lineno < $numlines; $lineno++) + { + /* format code */ + $text = $engine->getLineText($lineno); + $text = str_replace("\t", str_pad("", 4/*tab width*/, " "), $text); + echo getEncodedText(str_pad($lineno+1, $widthOfLineNo, " ", STR_PAD_LEFT) . ' ' . $text . "\n"); + + /* show errors */ + $errors = $engine->getLineMessages($lineno); + foreach ($errors as $Error) { + /* only show this warning once */ + if (strcasecmp($Error->getErrName(), "missing_semicolon") == 0) { + if ($hasWarnedSemicolon) + continue; + $hasWarnedSemicolon = true; + } + + echo '<div>'; + + /* point to the error position, if available */ + if ($Error->getChar() > -1) + echo getEncodedText($lineNoSpacer . str_pad("", $Error->getChar()-1, "=") . "^\n"); + + /* output error type/message */ + echo getEncodedText($lineNoSpacer) . '<span>'; + if ($Error->getType()) + echo getEncodedText($Error->getType() . ': '); + echo getEncodedText($Error->getMessage()); + echo '</span>' . getEncodedText("\n"); + + echo '</div>'; + } + + if ($lineno % 1000 == 0) + flush(); + } + echo '</div>'; + } +?> Property changes on: trunk/www/_jsl_online.inc ___________________________________________________________________ Added: svn:eol-style + native Added: trunk/www/_lint_front.inc =================================================================== --- trunk/www/_lint_front.inc (rev 0) +++ trunk/www/_lint_front.inc 2009-10-08 13:54:28 UTC (rev 276) @@ -0,0 +1,64 @@ +<?php + // Get the posted script/URL + if (isset($_POST['script'])) + $_Script = stripslashes($_POST['script']); + else + $_Script = ""; + + function _DownloadURL($url) { + $cUrl = curl_init(); + curl_setopt($cUrl, CURLOPT_URL, $url); + curl_setopt($cUrl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($cUrl, CURLOPT_TIMEOUT, 5); + $PageContent = curl_exec($cUrl); + if (curl_errno($cUrl)) + return false; + return $PageContent; + } + + function _OutputError($error) { + echo '<p style="color: #F00; font-weight: bold">' . htmlentities($error) . '</p>'; + } + + function _isURL($url) { + if (strstr($url, "\n") !== FALSE) + return false; + if (strstr($url, "\r\n") !== FALSE) + return false; + if (!preg_match('!^((ht|f)tps?\:\/\/)?([\w\-]+\.)+([\w]{2,5})((/(.*))?)$!i', $url)) + return false; + return true; + } + + function outputscript() { + global $_Script; + echo htmlentities($_Script); + } + + function outputlint() { + global $_Script; + if (strlen($_Script) > 0) { + // set up the new engine + require_once("_jsl_online.inc"); + $engine = new JSLEngine('../jsl-cgi-bin/jsl', '../jsl-cgi-bin/jsl.server.conf'); + + if (_isURL(trim($_Script))) { + // Download and lint the URL + $code = _DownloadURL(trim($_Script)); + if ($code !== false) + $result = $engine->Lint($code); + else + $result = "The URL could not be downloaded: " . $_Script; + } + else + $result = $engine->Lint($_Script); + + // output the results + if ($result === true) + OutputLintHTML($engine); + else + _OutputError($result); + } + } +?> + Property changes on: trunk/www/_lint_front.inc ___________________________________________________________________ Added: svn:eol-style + native Modified: trunk/www/online_lint.php =================================================================== --- trunk/www/online_lint.php 2009-10-08 13:31:52 UTC (rev 275) +++ trunk/www/online_lint.php 2009-10-08 13:54:28 UTC (rev 276) @@ -3,6 +3,8 @@ @title=The Online Lint --> +<?php require('_lint_front.inc') ?> + Online Lint =========== @@ -14,10 +16,12 @@ <form method="POST" action=""> <p>Paste your JavaScript, HTML, or URL into the box below:</p> <p> - <textarea name="script" rows="15" cols="75" style="width: 100%"></textarea> + <textarea name="script" rows="15" cols="75" style="width: 100%"><?php outputscript(); ?></textarea> </p> <p> <input type="submit" value="Lint"/> +</p> -</p> +<?php outputlint(); ?> + </form> Modified: trunk/www.py =================================================================== --- trunk/www.py 2009-10-08 13:31:52 UTC (rev 275) +++ trunk/www.py 2009-10-08 13:54:28 UTC (rev 276) @@ -267,6 +267,8 @@ return 'image/gif', source elif path.endswith('.png'): return 'image/png', source + elif path.endswith('.inc'): + return 'text/plain', source elif path.endswith('.rss'): settings, source = _preprocess(path) return 'text/xml', _gen_rss(host, path, source, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |