Because I've been bringing a lot of my old Visual Basic code online recently I was looking for a way to easily display Visual Basic code on a webpage. I needed something that could take my existing Visual Basic code, convert it to HTML, apply color coding to it (which is technically called syntax highlighting), and then display it in valid XHTML. I was preferably looking for something written in PHP rather than relying on an external program, website, or VB Add-In. Since I couldn't find anything satisfactory on the web I decided to write my own.
A quick Google search for "visual basic to html converter" yielded almost no relevant results for what I was looking for. A Google search for "vb2html" yielded slightly more relevant results, and a Google search for "syntax highlighting in php" yielded the most relevant results. That connected me with a product called GeSHi, which is pretty much exactly was I was looking for. GeSHi is a Generic Syntax Highlighter written in PHP that can convert code written in almost any programming language to color-coded HTML. I downloaded it and tried it out and it really is pretty amazing in terms of what it can do. However, I didn't like the built-in color schemes so I tried to modify them but I got stuck when I tried to set different colors for different bracket styles. I wanted parentheses ( ) to apear in one color, square brackets [ ] to appear in different color, and curly brackets { } appear in a third color, but GeSHi would always display them in the same color. Maybe I was just editing the config file the wrong way, but if it is possible I think they should have an online generator that makes config files for you where you can just point and click the colors you want and it writes the config file for you. Another thing I didn't like about GeSHi is that since it uses a lot of regular expression matching it slightly slows down your script's execution time. I wanted something that was small, fast, simple and that only worked for converting vb to html.
Since I couldn't find exactly what I was looking for I decided to write my own. My script doesn't use regular expression matching. It just goes line-by-line through the code, colors what needs to be colored, and then wraps everything in a <pre> tag. It can take any file as input but it only processes vb source files (.frm, .cls, .bas, and .ctl). It then outputs color-coded XHTML using CSS for styling. I also tried to make it SEO friendly by telling search robots to index the page if you passed it a valid file and not to index the page if you passed it an invalid file.
Download vb2html.zip (Mar 01, 2009)
<?php
putenv("TZ=US/Pacific");
header('Content-type: text/html; charset=iso-8859-1');
header('Last-Modified: ' . gmdate("D, d M Y H:i:s", filemtime($_SERVER[DOCUMENT_ROOT] . $_SERVER['PHP_SELF'])) . ' GMT');
set_time_limit(60); // Allow the script to run for 60 seconds
$file_exists = false;
$page_title = "Invalid file specified";
$index_follow = "noindex,nofollow";
if (isset($_GET['file'])) {
if (strlen($_GET['file']) > 0) {
if (file_exists($_GET['file'])) {
$the_extension = strtolower(substr($_GET['file'], -4));
if (($the_extension == ".frm") || ($the_extension == ".bas") || ($the_extension == ".cls") || ($the_extension == ".ctl")) {
$page_title = basename($_GET['file']);
$file_exists = true;
$index_follow = "index,follow";
}
}
}
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<meta http-equiv="content-style-type" content="text/css" />
<meta http-equiv="content-script-type" content="text/javascript" />
<meta name="keywords" content="" />
<meta name="description" content="" />
<meta name="date" content="<?php echo date("Y-m-d\TH:i:s-08:00", filemtime($_SERVER[DOCUMENT_ROOT] . $_SERVER['PHP_SELF'])); ?>" />
<meta name="rating" content="general" />
<meta name="robots" content="<?php echo $index_follow; ?>" />
<title><?php echo $page_title; ?></title>
<style type="text/css">
/* <![CDATA[ */
html, body, form, ul, ol, li, p, pre, h1, h2, h3, h4, h5, h6, label { font: small monospace; margin: 0px; padding: 0px; color: #000000; }
body { margin: 10px; white-space: nowrap; }
img { border-width: 0px; border-style: none; }
.c { color: #008000 !important; }
.b { color: #000080; }
/* ]]> */
</style>
</head>
<body>
<?php
if ($file_exists == true) {
$big_string = file_get_contents($_GET['file']);
$big_string = htmlspecialchars($big_string, ENT_NOQUOTES);
$big_string = str_replace(array(chr(163),chr(128),chr(165),"\r\n","\r"), array("£","€","¥","\n","\n"), $big_string) ;
echo "<pre>\r\n";
$the_lines = explode("\n", $big_string);
foreach ($the_lines as $one_line) {
$first_part_of_line = $one_line;
$second_part_of_line = "";
$comment_starts_at_char = strpos($one_line, "'"); // look for vb comments
if ($comment_starts_at_char !== false) { // comment found
$first_part_of_line = substr($one_line, 0, $comment_starts_at_char);
$second_part_of_line = "<span class=\"c\">" . substr($one_line, $comment_starts_at_char) . "</span>";
}
$the_words = explode(" ", $first_part_of_line);
$num_words = count($the_words);
$first_part_of_line = "";
for ($i=0;$i<$num_words;$i++) {
$w = $the_words[$i];
$is_vb_keyword = false;
$has_extra_char = false;
if ((substr($the_words[$i], -1) == ",") || (substr($the_words[$i], -1) == ")")) { $has_extra_char = true; }
if ($has_extra_char == true) { $w = substr($the_words[$i], 0, -1); }
switch ($w) {
case "And":
case "As":
case "Access":
case "Between":
case "Binary":
case "Boolean":
case "By":
case "ByRef":
case "Byte":
case "ByVal":
case "Call":
case "Case":
case "Close":
case "Compare":
case "Const":
case "Control":
case "Create":
case "Currency":
case "Date":
case "Debug.Print":
case "Decimal":
case "Declare":
case "DefBool":
case "DefDate":
case "DefDbl":
case "DefInt":
case "DefLng":
case "DefObj":
case "DefStr":
case "DefVar":
case "Dim":
case "Do":
case "Double":
case "Each":
case "Else":
case "ElseIf":
case "End":
case "Erase":
case "Error":
case "Execute":
case "Exists":
case "Exit":
case "Explicit":
case "False":
case "For":
case "Form":
case "From":
case "Function":
case "Get":
case "GoTo":
case "If":
case "In":
case "Input":
case "Integer":
case "LBound":
case "Let":
case "Line":
case "Like":
case "Long":
case "Loop":
case "New":
case "Next":
case "Not":
case "Null":
case "On":
case "Or":
case "Open":
case "Option":
case "Optional":
case "Output":
case "Preserve":
case "Primary":
case "Print":
case "Private":
case "Procedure":
case "Property":
case "Public":
case "Read":
case "ReDim":
case "Recordset":
case "Reset":
case "Resume":
case "Select":
case "Set":
case "Single":
case "String":
case "Sub":
case "To":
case "TableDef":
case "Then":
case "True":
case "Until":
case "UBound":
case "Variant":
case "Wend":
case "While":
case "With":
case "WithEvents":
$is_vb_keyword = true; break;
default:
$is_vb_keyword = false; break;
}
if ($is_vb_keyword) {
if ($has_extra_char) { $the_words[$i] = '<span class="b">' . $w . '</span>' . substr($the_words[$i], -1); }
else { $the_words[$i] = '<span class="b">' . $the_words[$i] . '</span>'; }
}
$first_part_of_line .= $the_words[$i] . " ";
if ($i == ($num_words-1)) { $first_part_of_line = substr($first_part_of_line, 0, -1); } // remove extra space
}
echo $first_part_of_line . $second_part_of_line . "\r\n";
}
echo "</pre>\r\n";
}
else {
echo "Invalid file specified.\r\n";
}
?>
</body>
</html>