Reference

Overview

Chili is syntax highlighting for the browser. You just put the code you want highlighted in a code tag AS IS, and Chili will highlight all the items of the language the code is written in.

The process is driven by two files per each language: a recipe and a stylesheet. A recipe is a list of regular expressions, where each one describes a type of item and is associated to a stylesheet class. All the stylesheet classes that appear in a recipe should in turn de defined all in a separate stylesheet.

While stylesheets only provide style (colors and alike), recipes are the real value: they provide comprehension.

Recommendations
  1. Regular Expressions are a sharp tool, but need extra attention on your side. If you find that something does not come out as expected, maybe the recipe is wrong.
    1. Expresso – A very useful free program for building regular expressions:
      http://www.ultrapico.com/Expresso.htm
    2. RegExp Toolkit – An online tester for javascript regular expressions:
      http://www.xaprb.com/demos/rx-toolkit/
    3. Regular Expressions – A whole site dedicated to regular expressions:
      http://www.regular-expressions.info/
  2. HTML requires that any text introduced into a page as content be escaped. Replace at least any & by {[79.entity(79.amp)]} and any < by {[79.entity(79.lt)]} in this order. If you want to highlight HTML you also need to escape any > with {[79.entity(79.gt)]}.
    1. Postable – A very useful free web utility for escaping text for HTML:
      http://www.elliotswan.com/postable/
Tested on

IE 6 – PC: pass
IE 7 – PC: pass
Firefox 1.5 – PC: pass
Firefox 2.0 – PC: pass
Mozilla 1.7 – PC: pass
Opera 9.1 – PC: pass
Safari – Mac: pass

if it works for you and your configuration is not listed here please send me a note

Configuration Options
  • recipeFolder: “”
    this is the folder where the recipe will be downloaded from. It can be absolute or relative to the folder of the page. If it is “” then the folder of the page will be used
  • stylesheetFolder: “”
    this is the folder where the stylesheet will be downloaded from. It can be absolute or relative to the folder of the page. If it is “” then the folder of the page will be used
  • defaultReplacement: ‘{[.replacement /enzymes/html.php]}’
    this is the default replacement for the matching text, used if a step does not define its own replacement. $$ is all the matched text, $0 is the <recipeName>, and $1, $2, … are all the submatches of the step. Use $ to represent a $
  • elementPath: “code”
    see the “Elements selection” appendix
  • elementClass: “”
    see the “Elements selection” appendix
  • replaceSpace: “{[82.wrap_entity(82.160)]}”
    this is a workaround for IE, but is applied to all browsers. Use “” for not replacing
  • replaceTab: “{[82.wrap_entity(82.160)]}{[82.wrap_entity(82.160)]}{[82.wrap_entity(82.160)]}{[82.wrap_entity(82.160)]}”
    this is a workaround for FF, but is applied to all browsers. Use “” for not replacing
  • replaceNewLine: “{[82.wrap_entity(82.160)]}{[.br /enzymes/html.php]}”
    this is a workaround for IE, but is applied to all browsers. Use “” for not replacing
  • recipeLoading: “true”
    set this to true for a Dynamic Setup and to false for a Static Setup (preventing dynamic download of recipes)
  • stylesheetLoading: “true”
    set this to false for preventing dynamic download of stylesheets

Formats

  • <x> is the name of a production rule
  • <x?> means “an optional <x>”
  • <x*> means “any number of <x>”
  • all other chars represent themselves and white space is a beautifier
Recipes
{[79.recipes /enzymes/html.php]}
Stylesheets
{[79.stylesheets /enzymes/html.php]}

{[1.get(1.page)]}

Appendices

Once upon a time

I began fixing a bug in Code Highlighter 0.4, and I ended up with a new piece of software which is quite different from its parent.

The code of Code Highlighter has been reverse engineered, fixed, documented, simplified, adapted to jQuery, improved, and put through an extensive refactoring, including a bizarre renaming based on a cooking metaphore. To honour its roots, my script takes its name from its parent, Code HIghLIghter.

Aknowledgements

Dan Webb’s Code Highlighter 0.4 gave me the script I began working on. Its styleSets format for describing the syntax of a language was dropped from Chili 1.5.

Dean Edwards’ star-light 1.0.2 gave me the parsing engine. Actually Code Highlighter itself is a simplification of star-light. I don’t know wether the parsing engine was a Dean Edwards invention or not, but if you do, please send me a note and I’ll be glad to update this section.

Dan Webb’s site is hosted at: http://www.danwebb.net/
Dean Edwards’ site is hosted at: http://dean.edwards.name/

Elements selection

To control which elements get highlighted you need to configure the elementPath and elementClass options in ChiliBook.

elementPath is a jQuery element selector. elementClass is the generic class of the element selected by elementPath. Generic means that an element to be highlighted always need also a specific class for the language. If elementClass is not null then elementClass must appear in elementPath. A language class should not appear in elementPath.

Examples:

  • elementPath: “code”, elementClass: “”
    this will highlight all elements like <code class=”language”>
  • elementPath: “code.chili”, elementClass: “chili”
    this will highlight all elements like <code class=”language chili”> and <code class=”chili language”> but not elements like <code class=”language”>
  • elementPath: “.chili”, elementClass: “chili”
    this will highlight all elements like <code class=”chili language”> and <tt class=”chili language”> and…
Recipe name conflicts
  • Chili 1.0, 1.1, 1.2, 1.3, 1.4: the first recipe wins
  • Chili 1.5: name conflict check removed
  • Chili 1.6 and beyond
    • Dynamic Setup: the first recipe wins
    • Static Setup: the last recipe wins
Replacement format

The replacement format can be defined on a per step basis, or by the ChiliBook.defaultReplacement setting. If for a given step no replacement is explicitly provided (or it’s a null string) then the defaultReplacement is used.

It accepts $0 as the <stepName>, $1, $2, … as the submatches of each step, and $$ as its match. If a $ is needed then $ must be used in its place.

Dynamically loaded files

Starting from Chili 1.6 all the recipes and stylesheets are registered by URL as soon as they are requested, supposing the loading will succeed. Any subsequent request for a file with the same URL is ignored.

At the beginning all the DOM elements to highlight are selected and each found language generates a stylesheet and recipe request. Stylesheets are registered and loaded by Chili and automatically executed by the browser. Recipes are registered by Chili, then loaded by jQuery, then executed by Chili as soon as they are available. A recipe is executed by selecting again all the DOM elements with such a recipe and highlighting each in turn.

The simple and perfect clockwork of the parsing engine

Every time a match is found, String.replace delivers to chef() an array of arguments with all the submatches of the pattern generated by the use of parentheses. arguments[0] is always the global match, and submatches start at arguments[1]. The sequence of submatches follow a strict order: parents come before their children, recursively.

If a pattern like /(<step1>)|(<step2>)|…(<stepN>)/ matched, then one of them (be <stepM>) matched completely and the steps before it didn’t match at all (the steps after it were not tested).

Each failing step must have produced a sequence of submatches where the root is certainly empty (while nothing can be said about its descendants). On the other side, the matching <stepM> must have produced a sequence of submatches where the root is certainly non-empty.

To find the matching <stepM> in the arguments, is necessary to hop from one root to the next. Starting from arguments[1], we’ll hop one more time if the current arguments[j] is empty. The length of the hop must be the number of submatches of each step, which is given by the number of open parentheses in that step.

Version 1.1
This all was good till I found out that backreferences inside the pattern of a step didn’t work because of the many new parentheses added before. Renumbering any backreferences was the simple fix. This is done transparently, so that the recipe writer doesn’t need to worry about that.

Escaping madness

The scripts this one is based upon, are very different with respect to the escaping issue. Dean Edwards’ star-light script escapes and unescapes everything it touches, while Dan Webb’s Code Highlighter doesn’t escape or unescape anything. How can it be?

Really, most of the times Code Highlighter behaves nicely. But I think that start-light behaves nicely always (yet I didn’t tested it myself).

Unfortunately, a properly escaped content, and a good recipe are not enough for a perfect result. It’s clear: a recipe modifies an automatically unescaped content, which is supposed to be in mint conditions for it had been escaped before. But when the cooking is done, the code element has to be replaced by new content, which again needs to be escaped so that it will display nicely when automatically unescaped by the browser.

Actually, that new content has two mixed components: the old content and many new containers. Old content inside new containers must be escaped, as well old content outside any of them. But any container need to go as is. The structure of the new content makes it unviable a one shot escape.

Every matched content can be escaped while replacing, but the replace method does not provide any handle to the string that is being built meanwhile, with all the replacements in place. This means that all the unmatched content cannot be gotten at all, so the replace method cannot be used at full power, and the automatically replaced string must be discarded.

Nonetheless, the replace method provides a lot of information, that can be used to arrange things so that eveything gets done well and clean.

One Reply to “Reference”

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.