doc: fix 404s for syntax highlighting js
authorPhil Hughes <me@iamphill.com>
Wed, 14 Jan 2015 16:29:52 +0000 (16:29 +0000)
committerChris Dickinson <christopher.s.dickinson@gmail.com>
Thu, 15 Jan 2015 18:09:24 +0000 (10:09 -0800)
Updated Makefile to remove special casing for those files, and
moved the files to doc/api_assets.

Fixes: https://github.com/iojs/iojs.github.io/issues/51
PR-URL: https://github.com/iojs/io.js/pull/409
Reviewed-By: Chris Dickinson <christopher.s.dickinson@gmail.com>
Makefile
doc/api_assets/sh_javascript.min.js [moved from doc/sh_javascript.min.js with 100% similarity]
doc/api_assets/sh_main.js [moved from doc/sh_main.js with 96% similarity]
doc/template.html

index 0072973..2d22a12 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -188,11 +188,7 @@ apidoc_dirs = out/doc out/doc/api/ out/doc/api/assets
 
 apiassets = $(subst api_assets,api/assets,$(addprefix out/,$(wildcard doc/api_assets/*)))
 
-website_files = \
-       out/doc/sh_main.js    \
-       out/doc/sh_javascript.min.js
-
-doc: $(apidoc_dirs) $(website_files) $(apiassets) $(apidocs) tools/doc/ $(NODE_EXE)
+doc: $(apidoc_dirs) $(apiassets) $(apidocs) tools/doc/ $(NODE_EXE)
 
 $(apidoc_dirs):
        mkdir -p $@
similarity index 96%
rename from doc/sh_main.js
rename to doc/api_assets/sh_main.js
index 2790569..fa9d8ef 100644 (file)
-/*\r
-SHJS - Syntax Highlighting in JavaScript\r
-Copyright (C) 2007, 2008 gnombat@users.sourceforge.net\r
-License: http://shjs.sourceforge.net/doc/gplv3.html\r
-*/\r
-\r
-if (! this.sh_languages) {\r
-  this.sh_languages = {};\r
-}\r
-var sh_requests = {};\r
-\r
-function sh_isEmailAddress(url) {\r
-  if (/^mailto:/.test(url)) {\r
-    return false;\r
-  }\r
-  return url.indexOf('@') !== -1;\r
-}\r
-\r
-function sh_setHref(tags, numTags, inputString) {\r
-  var url = inputString.substring(tags[numTags - 2].pos, tags[numTags - 1].pos);\r
-  if (url.length >= 2 && url.charAt(0) === '<' && url.charAt(url.length - 1) === '>') {\r
-    url = url.substr(1, url.length - 2);\r
-  }\r
-  if (sh_isEmailAddress(url)) {\r
-    url = 'mailto:' + url;\r
-  }\r
-  tags[numTags - 2].node.href = url;\r
-}\r
-\r
-/*\r
-Konqueror has a bug where the regular expression /$/g will not match at the end\r
-of a line more than once:\r
-\r
-  var regex = /$/g;\r
-  var match;\r
-\r
-  var line = '1234567890';\r
-  regex.lastIndex = 10;\r
-  match = regex.exec(line);\r
-\r
-  var line2 = 'abcde';\r
-  regex.lastIndex = 5;\r
-  match = regex.exec(line2);  // fails\r
-*/\r
-function sh_konquerorExec(s) {\r
-  var result = [''];\r
-  result.index = s.length;\r
-  result.input = s;\r
-  return result;\r
-}\r
-\r
-/**\r
-Highlights all elements containing source code in a text string.  The return\r
-value is an array of objects, each representing an HTML start or end tag.  Each\r
-object has a property named pos, which is an integer representing the text\r
-offset of the tag. Every start tag also has a property named node, which is the\r
-DOM element started by the tag. End tags do not have this property.\r
-@param  inputString  a text string\r
-@param  language  a language definition object\r
-@return  an array of tag objects\r
-*/\r
-function sh_highlightString(inputString, language) {\r
-  if (/Konqueror/.test(navigator.userAgent)) {\r
-    if (! language.konquered) {\r
-      for (var s = 0; s < language.length; s++) {\r
-        for (var p = 0; p < language[s].length; p++) {\r
-          var r = language[s][p][0];\r
-          if (r.source === '$') {\r
-            r.exec = sh_konquerorExec;\r
-          }\r
-        }\r
-      }\r
-      language.konquered = true;\r
-    }\r
-  }\r
-\r
-  var a = document.createElement('a');\r
-  var span = document.createElement('span');\r
-\r
-  // the result\r
-  var tags = [];\r
-  var numTags = 0;\r
-\r
-  // each element is a pattern object from language\r
-  var patternStack = [];\r
-\r
-  // the current position within inputString\r
-  var pos = 0;\r
-\r
-  // the name of the current style, or null if there is no current style\r
-  var currentStyle = null;\r
-\r
-  var output = function(s, style) {\r
-    var length = s.length;\r
-    // this is more than just an optimization - we don't want to output empty <span></span> elements\r
-    if (length === 0) {\r
-      return;\r
-    }\r
-    if (! style) {\r
-      var stackLength = patternStack.length;\r
-      if (stackLength !== 0) {\r
-        var pattern = patternStack[stackLength - 1];\r
-        // check whether this is a state or an environment\r
-        if (! pattern[3]) {\r
-          // it's not a state - it's an environment; use the style for this environment\r
-          style = pattern[1];\r
-        }\r
-      }\r
-    }\r
-    if (currentStyle !== style) {\r
-      if (currentStyle) {\r
-        tags[numTags++] = {pos: pos};\r
-        if (currentStyle === 'sh_url') {\r
-          sh_setHref(tags, numTags, inputString);\r
-        }\r
-      }\r
-      if (style) {\r
-        var clone;\r
-        if (style === 'sh_url') {\r
-          clone = a.cloneNode(false);\r
-        }\r
-        else {\r
-          clone = span.cloneNode(false);\r
-        }\r
-        clone.className = style;\r
-        tags[numTags++] = {node: clone, pos: pos};\r
-      }\r
-    }\r
-    pos += length;\r
-    currentStyle = style;\r
-  };\r
-\r
-  var endOfLinePattern = /\r\n|\r|\n/g;\r
-  endOfLinePattern.lastIndex = 0;\r
-  var inputStringLength = inputString.length;\r
-  while (pos < inputStringLength) {\r
-    var start = pos;\r
-    var end;\r
-    var startOfNextLine;\r
-    var endOfLineMatch = endOfLinePattern.exec(inputString);\r
-    if (endOfLineMatch === null) {\r
-      end = inputStringLength;\r
-      startOfNextLine = inputStringLength;\r
-    }\r
-    else {\r
-      end = endOfLineMatch.index;\r
-      startOfNextLine = endOfLinePattern.lastIndex;\r
-    }\r
-\r
-    var line = inputString.substring(start, end);\r
-\r
-    var matchCache = [];\r
-    for (;;) {\r
-      var posWithinLine = pos - start;\r
-\r
-      var stateIndex;\r
-      var stackLength = patternStack.length;\r
-      if (stackLength === 0) {\r
-        stateIndex = 0;\r
-      }\r
-      else {\r
-        // get the next state\r
-        stateIndex = patternStack[stackLength - 1][2];\r
-      }\r
-\r
-      var state = language[stateIndex];\r
-      var numPatterns = state.length;\r
-      var mc = matchCache[stateIndex];\r
-      if (! mc) {\r
-        mc = matchCache[stateIndex] = [];\r
-      }\r
-      var bestMatch = null;\r
-      var bestPatternIndex = -1;\r
-      for (var i = 0; i < numPatterns; i++) {\r
-        var match;\r
-        if (i < mc.length && (mc[i] === null || posWithinLine <= mc[i].index)) {\r
-          match = mc[i];\r
-        }\r
-        else {\r
-          var regex = state[i][0];\r
-          regex.lastIndex = posWithinLine;\r
-          match = regex.exec(line);\r
-          mc[i] = match;\r
-        }\r
-        if (match !== null && (bestMatch === null || match.index < bestMatch.index)) {\r
-          bestMatch = match;\r
-          bestPatternIndex = i;\r
-          if (match.index === posWithinLine) {\r
-            break;\r
-          }\r
-        }\r
-      }\r
-\r
-      if (bestMatch === null) {\r
-        output(line.substring(posWithinLine), null);\r
-        break;\r
-      }\r
-      else {\r
-        // got a match\r
-        if (bestMatch.index > posWithinLine) {\r
-          output(line.substring(posWithinLine, bestMatch.index), null);\r
-        }\r
-\r
-        var pattern = state[bestPatternIndex];\r
-\r
-        var newStyle = pattern[1];\r
-        var matchedString;\r
-        if (newStyle instanceof Array) {\r
-          for (var subexpression = 0; subexpression < newStyle.length; subexpression++) {\r
-            matchedString = bestMatch[subexpression + 1];\r
-            output(matchedString, newStyle[subexpression]);\r
-          }\r
-        }\r
-        else {\r
-          matchedString = bestMatch[0];\r
-          output(matchedString, newStyle);\r
-        }\r
-\r
-        switch (pattern[2]) {\r
-        case -1:\r
-          // do nothing\r
-          break;\r
-        case -2:\r
-          // exit\r
-          patternStack.pop();\r
-          break;\r
-        case -3:\r
-          // exitall\r
-          patternStack.length = 0;\r
-          break;\r
-        default:\r
-          // this was the start of a delimited pattern or a state/environment\r
-          patternStack.push(pattern);\r
-          break;\r
-        }\r
-      }\r
-    }\r
-\r
-    // end of the line\r
-    if (currentStyle) {\r
-      tags[numTags++] = {pos: pos};\r
-      if (currentStyle === 'sh_url') {\r
-        sh_setHref(tags, numTags, inputString);\r
-      }\r
-      currentStyle = null;\r
-    }\r
-    pos = startOfNextLine;\r
-  }\r
-\r
-  return tags;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// DOM-dependent functions\r
-\r
-function sh_getClasses(element) {\r
-  var result = [];\r
-  var htmlClass = element.className;\r
-  if (htmlClass && htmlClass.length > 0) {\r
-    var htmlClasses = htmlClass.split(' ');\r
-    for (var i = 0; i < htmlClasses.length; i++) {\r
-      if (htmlClasses[i].length > 0) {\r
-        result.push(htmlClasses[i]);\r
-      }\r
-    }\r
-  }\r
-  return result;\r
-}\r
-\r
-function sh_addClass(element, name) {\r
-  var htmlClasses = sh_getClasses(element);\r
-  for (var i = 0; i < htmlClasses.length; i++) {\r
-    if (name.toLowerCase() === htmlClasses[i].toLowerCase()) {\r
-      return;\r
-    }\r
-  }\r
-  htmlClasses.push(name);\r
-  element.className = htmlClasses.join(' ');\r
-}\r
-\r
-/**\r
-Extracts the tags from an HTML DOM NodeList.\r
-@param  nodeList  a DOM NodeList\r
-@param  result  an object with text, tags and pos properties\r
-*/\r
-function sh_extractTagsFromNodeList(nodeList, result) {\r
-  var length = nodeList.length;\r
-  for (var i = 0; i < length; i++) {\r
-    var node = nodeList.item(i);\r
-    switch (node.nodeType) {\r
-    case 1:\r
-      if (node.nodeName.toLowerCase() === 'br') {\r
-        var terminator;\r
-        if (/MSIE/.test(navigator.userAgent)) {\r
-          terminator = '\r';\r
-        }\r
-        else {\r
-          terminator = '\n';\r
-        }\r
-        result.text.push(terminator);\r
-        result.pos++;\r
-      }\r
-      else {\r
-        result.tags.push({node: node.cloneNode(false), pos: result.pos});\r
-        sh_extractTagsFromNodeList(node.childNodes, result);\r
-        result.tags.push({pos: result.pos});\r
-      }\r
-      break;\r
-    case 3:\r
-    case 4:\r
-      result.text.push(node.data);\r
-      result.pos += node.length;\r
-      break;\r
-    }\r
-  }\r
-}\r
-\r
-/**\r
-Extracts the tags from the text of an HTML element. The extracted tags will be\r
-returned as an array of tag objects. See sh_highlightString for the format of\r
-the tag objects.\r
-@param  element  a DOM element\r
-@param  tags  an empty array; the extracted tag objects will be returned in it\r
-@return  the text of the element\r
-@see  sh_highlightString\r
-*/\r
-function sh_extractTags(element, tags) {\r
-  var result = {};\r
-  result.text = [];\r
-  result.tags = tags;\r
-  result.pos = 0;\r
-  sh_extractTagsFromNodeList(element.childNodes, result);\r
-  return result.text.join('');\r
-}\r
-\r
-/**\r
-Merges the original tags from an element with the tags produced by highlighting.\r
-@param  originalTags  an array containing the original tags\r
-@param  highlightTags  an array containing the highlighting tags - these must not overlap\r
-@result  an array containing the merged tags\r
-*/\r
-function sh_mergeTags(originalTags, highlightTags) {\r
-  var numOriginalTags = originalTags.length;\r
-  if (numOriginalTags === 0) {\r
-    return highlightTags;\r
-  }\r
-\r
-  var numHighlightTags = highlightTags.length;\r
-  if (numHighlightTags === 0) {\r
-    return originalTags;\r
-  }\r
-\r
-  var result = [];\r
-  var originalIndex = 0;\r
-  var highlightIndex = 0;\r
-\r
-  while (originalIndex < numOriginalTags && highlightIndex < numHighlightTags) {\r
-    var originalTag = originalTags[originalIndex];\r
-    var highlightTag = highlightTags[highlightIndex];\r
-\r
-    if (originalTag.pos <= highlightTag.pos) {\r
-      result.push(originalTag);\r
-      originalIndex++;\r
-    }\r
-    else {\r
-      result.push(highlightTag);\r
-      if (highlightTags[highlightIndex + 1].pos <= originalTag.pos) {\r
-        highlightIndex++;\r
-        result.push(highlightTags[highlightIndex]);\r
-        highlightIndex++;\r
-      }\r
-      else {\r
-        // new end tag\r
-        result.push({pos: originalTag.pos});\r
-\r
-        // new start tag\r
-        highlightTags[highlightIndex] = {node: highlightTag.node.cloneNode(false), pos: originalTag.pos};\r
-      }\r
-    }\r
-  }\r
-\r
-  while (originalIndex < numOriginalTags) {\r
-    result.push(originalTags[originalIndex]);\r
-    originalIndex++;\r
-  }\r
-\r
-  while (highlightIndex < numHighlightTags) {\r
-    result.push(highlightTags[highlightIndex]);\r
-    highlightIndex++;\r
-  }\r
-\r
-  return result;\r
-}\r
-\r
-/**\r
-Inserts tags into text.\r
-@param  tags  an array of tag objects\r
-@param  text  a string representing the text\r
-@return  a DOM DocumentFragment representing the resulting HTML\r
-*/\r
-function sh_insertTags(tags, text) {\r
-  var doc = document;\r
-\r
-  var result = document.createDocumentFragment();\r
-  var tagIndex = 0;\r
-  var numTags = tags.length;\r
-  var textPos = 0;\r
-  var textLength = text.length;\r
-  var currentNode = result;\r
-\r
-  // output one tag or text node every iteration\r
-  while (textPos < textLength || tagIndex < numTags) {\r
-    var tag;\r
-    var tagPos;\r
-    if (tagIndex < numTags) {\r
-      tag = tags[tagIndex];\r
-      tagPos = tag.pos;\r
-    }\r
-    else {\r
-      tagPos = textLength;\r
-    }\r
-\r
-    if (tagPos <= textPos) {\r
-      // output the tag\r
-      if (tag.node) {\r
-        // start tag\r
-        var newNode = tag.node;\r
-        currentNode.appendChild(newNode);\r
-        currentNode = newNode;\r
-      }\r
-      else {\r
-        // end tag\r
-        currentNode = currentNode.parentNode;\r
-      }\r
-      tagIndex++;\r
-    }\r
-    else {\r
-      // output text\r
-      currentNode.appendChild(doc.createTextNode(text.substring(textPos, tagPos)));\r
-      textPos = tagPos;\r
-    }\r
-  }\r
-\r
-  return result;\r
-}\r
-\r
-/**\r
-Highlights an element containing source code.  Upon completion of this function,\r
-the element will have been placed in the "sh_sourceCode" class.\r
-@param  element  a DOM <pre> element containing the source code to be highlighted\r
-@param  language  a language definition object\r
-*/\r
-function sh_highlightElement(element, language) {\r
-  sh_addClass(element, 'sh_sourceCode');\r
-  var originalTags = [];\r
-  var inputString = sh_extractTags(element, originalTags);\r
-  var highlightTags = sh_highlightString(inputString, language);\r
-  var tags = sh_mergeTags(originalTags, highlightTags);\r
-  var documentFragment = sh_insertTags(tags, inputString);\r
-  while (element.hasChildNodes()) {\r
-    element.removeChild(element.firstChild);\r
-  }\r
-  element.appendChild(documentFragment);\r
-}\r
-\r
-function sh_getXMLHttpRequest() {\r
-  if (window.ActiveXObject) {\r
-    return new ActiveXObject('Msxml2.XMLHTTP');\r
-  }\r
-  else if (window.XMLHttpRequest) {\r
-    return new XMLHttpRequest();\r
-  }\r
-  throw 'No XMLHttpRequest implementation available';\r
-}\r
-\r
-function sh_load(language, element, prefix, suffix) {\r
-  if (language in sh_requests) {\r
-    sh_requests[language].push(element);\r
-    return;\r
-  }\r
-  sh_requests[language] = [element];\r
-  var request = sh_getXMLHttpRequest();\r
-  var url = prefix + 'sh_' + language + suffix;\r
-  request.open('GET', url, true);\r
-  request.onreadystatechange = function () {\r
-    if (request.readyState === 4) {\r
-      try {\r
-        if (! request.status || request.status === 200) {\r
-          eval(request.responseText);\r
-          var elements = sh_requests[language];\r
-          for (var i = 0; i < elements.length; i++) {\r
-            sh_highlightElement(elements[i], sh_languages[language]);\r
-          }\r
-        }\r
-        else {\r
-          throw 'HTTP error: status ' + request.status;\r
-        }\r
-      }\r
-      finally {\r
-        request = null;\r
-      }\r
-    }\r
-  };\r
-  request.send(null);\r
-}\r
-\r
-/**\r
-Highlights all elements containing source code on the current page. Elements\r
-containing source code must be "pre" elements with a "class" attribute of\r
-"sh_LANGUAGE", where LANGUAGE is a valid language identifier; e.g., "sh_java"\r
-identifies the element as containing "java" language source code.\r
-*/\r
-function highlight(prefix, suffix, tag) {\r
-  var nodeList = document.getElementsByTagName(tag);\r
-  for (var i = 0; i < nodeList.length; i++) {\r
-    var element = nodeList.item(i);\r
-    var htmlClasses = sh_getClasses(element);\r
-    var highlighted = false;\r
-    var donthighlight = false;\r
-    for (var j = 0; j < htmlClasses.length; j++) {\r
-      var htmlClass = htmlClasses[j].toLowerCase();\r
-      if (htmlClass === 'sh_none') {\r
-        donthighlight = true\r
-        continue;\r
-      }\r
-      if (htmlClass.substr(0, 3) === 'sh_') {\r
-        var language = htmlClass.substring(3);\r
-        if (language in sh_languages) {\r
-          sh_highlightElement(element, sh_languages[language]);\r
-          highlighted = true;\r
-        }\r
-        else if (typeof(prefix) === 'string' && typeof(suffix) === 'string') {\r
-          sh_load(language, element, prefix, suffix);\r
-        }\r
-        else {\r
-          throw 'Found <' + tag + '> element with class="' + htmlClass + '", but no such language exists';\r
-        }\r
-        break;\r
-      }\r
-    }\r
-    if (highlighted === false && donthighlight == false) {\r
-      sh_highlightElement(element, sh_languages["javascript"]);\r
-    }\r
-  }\r
-}\r
-\r
-\r
-\r
-function sh_highlightDocument(prefix, suffix) {\r
-  highlight(prefix, suffix, 'tt');\r
-  highlight(prefix, suffix, 'code');\r
-  highlight(prefix, suffix, 'pre');\r
-}\r
+/*
+SHJS - Syntax Highlighting in JavaScript
+Copyright (C) 2007, 2008 gnombat@users.sourceforge.net
+License: http://shjs.sourceforge.net/doc/gplv3.html
+*/
+
+if (! this.sh_languages) {
+  this.sh_languages = {};
+}
+var sh_requests = {};
+
+function sh_isEmailAddress(url) {
+  if (/^mailto:/.test(url)) {
+    return false;
+  }
+  return url.indexOf('@') !== -1;
+}
+
+function sh_setHref(tags, numTags, inputString) {
+  var url = inputString.substring(tags[numTags - 2].pos, tags[numTags - 1].pos);
+  if (url.length >= 2 && url.charAt(0) === '<' && url.charAt(url.length - 1) === '>') {
+    url = url.substr(1, url.length - 2);
+  }
+  if (sh_isEmailAddress(url)) {
+    url = 'mailto:' + url;
+  }
+  tags[numTags - 2].node.href = url;
+}
+
+/*
+Konqueror has a bug where the regular expression /$/g will not match at the end
+of a line more than once:
+
+  var regex = /$/g;
+  var match;
+
+  var line = '1234567890';
+  regex.lastIndex = 10;
+  match = regex.exec(line);
+
+  var line2 = 'abcde';
+  regex.lastIndex = 5;
+  match = regex.exec(line2);  // fails
+*/
+function sh_konquerorExec(s) {
+  var result = [''];
+  result.index = s.length;
+  result.input = s;
+  return result;
+}
+
+/**
+Highlights all elements containing source code in a text string.  The return
+value is an array of objects, each representing an HTML start or end tag.  Each
+object has a property named pos, which is an integer representing the text
+offset of the tag. Every start tag also has a property named node, which is the
+DOM element started by the tag. End tags do not have this property.
+@param  inputString  a text string
+@param  language  a language definition object
+@return  an array of tag objects
+*/
+function sh_highlightString(inputString, language) {
+  if (/Konqueror/.test(navigator.userAgent)) {
+    if (! language.konquered) {
+      for (var s = 0; s < language.length; s++) {
+        for (var p = 0; p < language[s].length; p++) {
+          var r = language[s][p][0];
+          if (r.source === '$') {
+            r.exec = sh_konquerorExec;
+          }
+        }
+      }
+      language.konquered = true;
+    }
+  }
+
+  var a = document.createElement('a');
+  var span = document.createElement('span');
+
+  // the result
+  var tags = [];
+  var numTags = 0;
+
+  // each element is a pattern object from language
+  var patternStack = [];
+
+  // the current position within inputString
+  var pos = 0;
+
+  // the name of the current style, or null if there is no current style
+  var currentStyle = null;
+
+  var output = function(s, style) {
+    var length = s.length;
+    // this is more than just an optimization - we don't want to output empty <span></span> elements
+    if (length === 0) {
+      return;
+    }
+    if (! style) {
+      var stackLength = patternStack.length;
+      if (stackLength !== 0) {
+        var pattern = patternStack[stackLength - 1];
+        // check whether this is a state or an environment
+        if (! pattern[3]) {
+          // it's not a state - it's an environment; use the style for this environment
+          style = pattern[1];
+        }
+      }
+    }
+    if (currentStyle !== style) {
+      if (currentStyle) {
+        tags[numTags++] = {pos: pos};
+        if (currentStyle === 'sh_url') {
+          sh_setHref(tags, numTags, inputString);
+        }
+      }
+      if (style) {
+        var clone;
+        if (style === 'sh_url') {
+          clone = a.cloneNode(false);
+        }
+        else {
+          clone = span.cloneNode(false);
+        }
+        clone.className = style;
+        tags[numTags++] = {node: clone, pos: pos};
+      }
+    }
+    pos += length;
+    currentStyle = style;
+  };
+
+  var endOfLinePattern = /\r\n|\r|\n/g;
+  endOfLinePattern.lastIndex = 0;
+  var inputStringLength = inputString.length;
+  while (pos < inputStringLength) {
+    var start = pos;
+    var end;
+    var startOfNextLine;
+    var endOfLineMatch = endOfLinePattern.exec(inputString);
+    if (endOfLineMatch === null) {
+      end = inputStringLength;
+      startOfNextLine = inputStringLength;
+    }
+    else {
+      end = endOfLineMatch.index;
+      startOfNextLine = endOfLinePattern.lastIndex;
+    }
+
+    var line = inputString.substring(start, end);
+
+    var matchCache = [];
+    for (;;) {
+      var posWithinLine = pos - start;
+
+      var stateIndex;
+      var stackLength = patternStack.length;
+      if (stackLength === 0) {
+        stateIndex = 0;
+      }
+      else {
+        // get the next state
+        stateIndex = patternStack[stackLength - 1][2];
+      }
+
+      var state = language[stateIndex];
+      var numPatterns = state.length;
+      var mc = matchCache[stateIndex];
+      if (! mc) {
+        mc = matchCache[stateIndex] = [];
+      }
+      var bestMatch = null;
+      var bestPatternIndex = -1;
+      for (var i = 0; i < numPatterns; i++) {
+        var match;
+        if (i < mc.length && (mc[i] === null || posWithinLine <= mc[i].index)) {
+          match = mc[i];
+        }
+        else {
+          var regex = state[i][0];
+          regex.lastIndex = posWithinLine;
+          match = regex.exec(line);
+          mc[i] = match;
+        }
+        if (match !== null && (bestMatch === null || match.index < bestMatch.index)) {
+          bestMatch = match;
+          bestPatternIndex = i;
+          if (match.index === posWithinLine) {
+            break;
+          }
+        }
+      }
+
+      if (bestMatch === null) {
+        output(line.substring(posWithinLine), null);
+        break;
+      }
+      else {
+        // got a match
+        if (bestMatch.index > posWithinLine) {
+          output(line.substring(posWithinLine, bestMatch.index), null);
+        }
+
+        var pattern = state[bestPatternIndex];
+
+        var newStyle = pattern[1];
+        var matchedString;
+        if (newStyle instanceof Array) {
+          for (var subexpression = 0; subexpression < newStyle.length; subexpression++) {
+            matchedString = bestMatch[subexpression + 1];
+            output(matchedString, newStyle[subexpression]);
+          }
+        }
+        else {
+          matchedString = bestMatch[0];
+          output(matchedString, newStyle);
+        }
+
+        switch (pattern[2]) {
+        case -1:
+          // do nothing
+          break;
+        case -2:
+          // exit
+          patternStack.pop();
+          break;
+        case -3:
+          // exitall
+          patternStack.length = 0;
+          break;
+        default:
+          // this was the start of a delimited pattern or a state/environment
+          patternStack.push(pattern);
+          break;
+        }
+      }
+    }
+
+    // end of the line
+    if (currentStyle) {
+      tags[numTags++] = {pos: pos};
+      if (currentStyle === 'sh_url') {
+        sh_setHref(tags, numTags, inputString);
+      }
+      currentStyle = null;
+    }
+    pos = startOfNextLine;
+  }
+
+  return tags;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DOM-dependent functions
+
+function sh_getClasses(element) {
+  var result = [];
+  var htmlClass = element.className;
+  if (htmlClass && htmlClass.length > 0) {
+    var htmlClasses = htmlClass.split(' ');
+    for (var i = 0; i < htmlClasses.length; i++) {
+      if (htmlClasses[i].length > 0) {
+        result.push(htmlClasses[i]);
+      }
+    }
+  }
+  return result;
+}
+
+function sh_addClass(element, name) {
+  var htmlClasses = sh_getClasses(element);
+  for (var i = 0; i < htmlClasses.length; i++) {
+    if (name.toLowerCase() === htmlClasses[i].toLowerCase()) {
+      return;
+    }
+  }
+  htmlClasses.push(name);
+  element.className = htmlClasses.join(' ');
+}
+
+/**
+Extracts the tags from an HTML DOM NodeList.
+@param  nodeList  a DOM NodeList
+@param  result  an object with text, tags and pos properties
+*/
+function sh_extractTagsFromNodeList(nodeList, result) {
+  var length = nodeList.length;
+  for (var i = 0; i < length; i++) {
+    var node = nodeList.item(i);
+    switch (node.nodeType) {
+    case 1:
+      if (node.nodeName.toLowerCase() === 'br') {
+        var terminator;
+        if (/MSIE/.test(navigator.userAgent)) {
+          terminator = '\r';
+        }
+        else {
+          terminator = '\n';
+        }
+        result.text.push(terminator);
+        result.pos++;
+      }
+      else {
+        result.tags.push({node: node.cloneNode(false), pos: result.pos});
+        sh_extractTagsFromNodeList(node.childNodes, result);
+        result.tags.push({pos: result.pos});
+      }
+      break;
+    case 3:
+    case 4:
+      result.text.push(node.data);
+      result.pos += node.length;
+      break;
+    }
+  }
+}
+
+/**
+Extracts the tags from the text of an HTML element. The extracted tags will be
+returned as an array of tag objects. See sh_highlightString for the format of
+the tag objects.
+@param  element  a DOM element
+@param  tags  an empty array; the extracted tag objects will be returned in it
+@return  the text of the element
+@see  sh_highlightString
+*/
+function sh_extractTags(element, tags) {
+  var result = {};
+  result.text = [];
+  result.tags = tags;
+  result.pos = 0;
+  sh_extractTagsFromNodeList(element.childNodes, result);
+  return result.text.join('');
+}
+
+/**
+Merges the original tags from an element with the tags produced by highlighting.
+@param  originalTags  an array containing the original tags
+@param  highlightTags  an array containing the highlighting tags - these must not overlap
+@result  an array containing the merged tags
+*/
+function sh_mergeTags(originalTags, highlightTags) {
+  var numOriginalTags = originalTags.length;
+  if (numOriginalTags === 0) {
+    return highlightTags;
+  }
+
+  var numHighlightTags = highlightTags.length;
+  if (numHighlightTags === 0) {
+    return originalTags;
+  }
+
+  var result = [];
+  var originalIndex = 0;
+  var highlightIndex = 0;
+
+  while (originalIndex < numOriginalTags && highlightIndex < numHighlightTags) {
+    var originalTag = originalTags[originalIndex];
+    var highlightTag = highlightTags[highlightIndex];
+
+    if (originalTag.pos <= highlightTag.pos) {
+      result.push(originalTag);
+      originalIndex++;
+    }
+    else {
+      result.push(highlightTag);
+      if (highlightTags[highlightIndex + 1].pos <= originalTag.pos) {
+        highlightIndex++;
+        result.push(highlightTags[highlightIndex]);
+        highlightIndex++;
+      }
+      else {
+        // new end tag
+        result.push({pos: originalTag.pos});
+
+        // new start tag
+        highlightTags[highlightIndex] = {node: highlightTag.node.cloneNode(false), pos: originalTag.pos};
+      }
+    }
+  }
+
+  while (originalIndex < numOriginalTags) {
+    result.push(originalTags[originalIndex]);
+    originalIndex++;
+  }
+
+  while (highlightIndex < numHighlightTags) {
+    result.push(highlightTags[highlightIndex]);
+    highlightIndex++;
+  }
+
+  return result;
+}
+
+/**
+Inserts tags into text.
+@param  tags  an array of tag objects
+@param  text  a string representing the text
+@return  a DOM DocumentFragment representing the resulting HTML
+*/
+function sh_insertTags(tags, text) {
+  var doc = document;
+
+  var result = document.createDocumentFragment();
+  var tagIndex = 0;
+  var numTags = tags.length;
+  var textPos = 0;
+  var textLength = text.length;
+  var currentNode = result;
+
+  // output one tag or text node every iteration
+  while (textPos < textLength || tagIndex < numTags) {
+    var tag;
+    var tagPos;
+    if (tagIndex < numTags) {
+      tag = tags[tagIndex];
+      tagPos = tag.pos;
+    }
+    else {
+      tagPos = textLength;
+    }
+
+    if (tagPos <= textPos) {
+      // output the tag
+      if (tag.node) {
+        // start tag
+        var newNode = tag.node;
+        currentNode.appendChild(newNode);
+        currentNode = newNode;
+      }
+      else {
+        // end tag
+        currentNode = currentNode.parentNode;
+      }
+      tagIndex++;
+    }
+    else {
+      // output text
+      currentNode.appendChild(doc.createTextNode(text.substring(textPos, tagPos)));
+      textPos = tagPos;
+    }
+  }
+
+  return result;
+}
+
+/**
+Highlights an element containing source code.  Upon completion of this function,
+the element will have been placed in the "sh_sourceCode" class.
+@param  element  a DOM <pre> element containing the source code to be highlighted
+@param  language  a language definition object
+*/
+function sh_highlightElement(element, language) {
+  sh_addClass(element, 'sh_sourceCode');
+  var originalTags = [];
+  var inputString = sh_extractTags(element, originalTags);
+  var highlightTags = sh_highlightString(inputString, language);
+  var tags = sh_mergeTags(originalTags, highlightTags);
+  var documentFragment = sh_insertTags(tags, inputString);
+  while (element.hasChildNodes()) {
+    element.removeChild(element.firstChild);
+  }
+  element.appendChild(documentFragment);
+}
+
+function sh_getXMLHttpRequest() {
+  if (window.ActiveXObject) {
+    return new ActiveXObject('Msxml2.XMLHTTP');
+  }
+  else if (window.XMLHttpRequest) {
+    return new XMLHttpRequest();
+  }
+  throw 'No XMLHttpRequest implementation available';
+}
+
+function sh_load(language, element, prefix, suffix) {
+  if (language in sh_requests) {
+    sh_requests[language].push(element);
+    return;
+  }
+  sh_requests[language] = [element];
+  var request = sh_getXMLHttpRequest();
+  var url = prefix + 'sh_' + language + suffix;
+  request.open('GET', url, true);
+  request.onreadystatechange = function () {
+    if (request.readyState === 4) {
+      try {
+        if (! request.status || request.status === 200) {
+          eval(request.responseText);
+          var elements = sh_requests[language];
+          for (var i = 0; i < elements.length; i++) {
+            sh_highlightElement(elements[i], sh_languages[language]);
+          }
+        }
+        else {
+          throw 'HTTP error: status ' + request.status;
+        }
+      }
+      finally {
+        request = null;
+      }
+    }
+  };
+  request.send(null);
+}
+
+/**
+Highlights all elements containing source code on the current page. Elements
+containing source code must be "pre" elements with a "class" attribute of
+"sh_LANGUAGE", where LANGUAGE is a valid language identifier; e.g., "sh_java"
+identifies the element as containing "java" language source code.
+*/
+function highlight(prefix, suffix, tag) {
+  var nodeList = document.getElementsByTagName(tag);
+  for (var i = 0; i < nodeList.length; i++) {
+    var element = nodeList.item(i);
+    var htmlClasses = sh_getClasses(element);
+    var highlighted = false;
+    var donthighlight = false;
+    for (var j = 0; j < htmlClasses.length; j++) {
+      var htmlClass = htmlClasses[j].toLowerCase();
+      if (htmlClass === 'sh_none') {
+        donthighlight = true
+        continue;
+      }
+      if (htmlClass.substr(0, 3) === 'sh_') {
+        var language = htmlClass.substring(3);
+        if (language in sh_languages) {
+          sh_highlightElement(element, sh_languages[language]);
+          highlighted = true;
+        }
+        else if (typeof(prefix) === 'string' && typeof(suffix) === 'string') {
+          sh_load(language, element, prefix, suffix);
+        }
+        else {
+          throw 'Found <' + tag + '> element with class="' + htmlClass + '", but no such language exists';
+        }
+        break;
+      }
+    }
+    if (highlighted === false && donthighlight == false) {
+      sh_highlightElement(element, sh_languages["javascript"]);
+    }
+  }
+}
+
+
+
+function sh_highlightDocument(prefix, suffix) {
+  highlight(prefix, suffix, 'tt');
+  highlight(prefix, suffix, 'code');
+  highlight(prefix, suffix, 'pre');
+}
index 001c6f6..7d32a5b 100644 (file)
@@ -45,8 +45,8 @@
   <div id="footer">
   </div>
 
-  <script src="../sh_main.js"></script>
-  <script src="../sh_javascript.min.js"></script>
+  <script src="assets/sh_main.js"></script>
+  <script src="assets/sh_javascript.min.js"></script>
   <script>highlight(undefined, undefined, 'pre');</script>
 </body>
 </html>