SmartHTML - a HTML preprocessor =============================== The idea for SmartHTML appeared in my mind after I saw Latte. A nicer language that outputs to HTML, that e.g. allows <>& directly. But Latte looked too much like Latex for me, and I thought -- hey, I can write something like this in Perl easily. It's assumed you already know HTML. The examples/ directory contains various examples of pages hosted on www.andreasen.org. Licence: Public Domain. Using SmartHTML =============== Just type some text. Normal text with paragraphs, no HTML tags (but feel free to use < and > and & as you would in normal text). End the file in .sl. Then run smart.pl on it: % smart.pl index.sl index.sl => index.shtml (3540 bytes) SmartHTML will turn your file into a HTML file (with Includes enabled; I use them on all my pages but if you prefer to use normal HTML, just change the suffix in the script). If you look at the file, you notice some standard HTML headers. SmartHTML writes them for you. It also creates all the HEAD, BODY etc. tags for you, and sets the background color to white. Then comes your text: you will notice that where you have broken up text in paragraphs using two newlines, SmartHTML has replaced that with the P tag. You will also notice that all those special characters that need to be escaped, < and > and & are automatically escaped. This is doubly useful for national characters. If you had several files in that directory, you could just say: smart.pl *.sl and they would be converted in turn. This is faster than running the preprocessor on it separately. Note: the modify time of the .shtml file will be set to the modify time of the .sl file. So, you don't need to make Makefiles to keep the dates of your .shtml files, just run SmartHTML every time. Tags ==== But you probably want to use some HTML tags too. Tags in SmartHTML look like texinfo: @tagname { stuff } We have an @-sign, which is followed directly by the tag name. Then we have {, the stuff this tags should affect, and }. Let's take a simple tag like "strong": I don't @strong {think} so. This will expand to the following HTML: I don't think so. As you can see, SmartHTML closed the tag correctly for you. Tags can also span over multiple lines, so if you want to make a whole paragraph strong, just do it: @strong { This is a test } As you might have guessed, most SmartHTML tags are named the same as the HTML counterparts, so you can use @b, @i etc. More are easily defined in the configuration file. The above example is one of a bi-tag: bi tags have a start an end. Some tags are unitags, like P (in earlier versions of HTML anyway) and LI. To use those, just leave out the { } stuff. For example, let's make an unnumbered list: @ul { @li 1 @li 2 @li 3 } Around this list, there will be a opening and closing UL tag. Each line will start with a LI tag. What is more useful is the fact that bi-tags can also be used like unitags: then they apply until the end of the line. For example: @h1 The beginning This declares a level 1 header - H1. Since you didn't put { } around it, it just goes on to the end of line. Defining your own tags ====================== When SmartHTML starts up, it reads the file /etc/smart.sl. That file contains a lot of the tag definitions for SmartHTML. The definition of a bi-tag looks like this: @bi b "b" This defines a tag named @b, which uses to open itself. Since the closing tag was not supplied, it's assumed to be . Lower down, you will see some complicated definitions for h1 through h3. These are @defines, covered later. But here you see one of the major strengths of SmartHTML: if you wanted to change the look of all your pages, you could just modify what @h1 to @h3 expands to. If you don't like my color scheme, considering commenting out (i.e. put # in front of) the long @h1 to @h3 tags, and use the small ones provided below. Even lower down, we have a uni tag: li @uni li "li" This is as straightforward as it can be: @li expands into
  • . Lower still we have escape codes: @escape < lt This will convert any < in the document to <. If you for some reason do NOT want a character to be escaped, put a \ before it. E.g. \< will guarantee that this < will come out as < when SmartHTML is finished with it, and will not be expanded into <. You should as far as possible not edit the /etc/smart.sl file: instead, edit the /etc/smart.local.sl file which contains local definitions for this machine. It is read in afterwards. Further customization on a per-user basis can be achieved by editing the file .smart.sl in your home directory. Also, SmartHTML will read in the file .smart.sl in the directory it starts in. After smart starts up, it reads the Perl script /etc/smart.local.pl if it exists. You can add your own custom Perl functions in there. URLs ==== A useful feature of SmartHTML is that of intelligent URL rewriting. To put a URL in your document use this syntax: @url {www.andreasen.org,Erwin's page} As you can see, we use a @url tag. It has two parameters, delimitered by ,. The first one is the URL: http:// is prepended to it automatically unless it contains @, in which case mailto: is prepended. If there already is a protocol specifier, e.g. ftp://, nothing is done. Then comes the description of the link, which is put between the and tags. @url can take a parameter called desc. For example: @url(desc=My page){http://www.andreasen.org} The desc= parameter is expanded into a Javascript mouseOver function, which displays "My page" when you move the mouse cursor over that link. Meta-quoting ============ Since 1.6 it's possible to specify a tag using a new type of quoting mechanism which takes priority over anything else. Specify {{ }} instead of the normal { }, and that particular tag will get expanded first. This is useful for example macros where you can define multiline macros now: @define(name=foo) {{ multiple lines of the foo macro }} Comments ======== Any line that starts with # is completely ignored. Head and Footer =============== SmartHTML will insert the file .header on top of every file in the same directory, and the file .footer at the bottom of it. You shouldn't define new tags here, since this is parsed once per file in that directory! Rather put those in the .smart.sl file in the directory smart is run from. More features ============= Sometimes, it is useful to go to the next line without making a paragraph. To do that, put . by itself on the line - it will be replaced with
    rather than

    Sometimes you want to give "parameters" to a tag. For example, take the @img tag which pulls in an image. You should always supply an ALT tag for that, which is done by doing: @img(alt=My little pony) {pony.jpg} So, put the extra parameters inside parens just after the tag name. You can put several parameters in there by delimitering them with commas. Note that SmartHTML will put "" around the parameters automatically. Some tags may use these arguments for other purposes (e.g. the @autotable). Creating defines ================ Most likely you often use repeating constructs in your HTML code. These can be very nicely put into a @define. For example: @define new "@img(alt=[New!]){/images/new.gif}" Remember to put quotes around the replacement text. Now, after defining this, you can say: @new{} anywhere in your code and have it replaced by this IMG tag, with ALT already set. If you change the location of your new.gif, you can edit in just that one place. Defines can also take parameters, for example: @define red "$" This makes a define which you can use @red {like that}. The parameter in this case, "like that" is inserted where $ is. Defines can also take parameters specified after (). When you put in e.g. @foo(arg=val), any occurrence of $arg in the macro body will be replaced by val. If you want your macro to expand not right away but when it's inserted or if it is over multiple lines you must use metaquotes. For example: @define(name=mymacro) {{ macro text goes here }} This is especially useful when the macro text contains something that expands to multiple lines. Without the meta-quoting, it would get expanded before the @define is lookd at, and would give problems. Template.pm =========== For use in CGI scripts, it is handy to separate generation of HTML and the code itself. Typically you would use a template file: normal HTML with placeholders for where the data is going to be. You can use SmartHTML just fine for that. Template.pm is a refinement of the methods I use to read in and parse templates. Template.pm is documented in comments in the beginning of the file. You can also view a small example of how it is used in the files templateExample.pl and loginTemplate.sl. Useful functions ================ There is a number of other time-saving functions available. @title This both sets the of the document, in its <HEAD> but also produces a level 1 heading at the beginning of the document. @code Useful for showing C code. Use meta-qoutes with that; it will take care of escaping { and }. @qtitle As above, "quiet title". This does NOT produce the heading. @exec Execute a program and puts in the results. If - is the first character error codes are ignored, otherwise compilation will abort on an error @include Parse the file and append results. You can choose to automatically append a certain string before and after every line. This is useful turning e.g. a file containing list items to actual list items without having to add @li at every line. Syntax is e.g. @include(prepend=%li) {file}. You need to use % rather than @ to stop it expanding before @include is expanded! @use file As above, but throw out any output (useful for config files) @raw Anything inside will not be parsed, so you can put raw HTML there @color Set color scheme. Currently only "white" is supported, and is the default too @set Set a variable. Takes the variable name as argument, so the syntax is @set(name) value. These variables are currently on set internally. @img an <img> tag. If you have the Image::Size module installed it (get it from www.cpan.org!) WIDTH= and HEIGHT= tags are automatically added. @meta Add a meta tag. E.g. @meta author erwin@andreasen.org @lastChange Inserts the date of the last change to the .sl file (e.g. Tue 13 Jan) @autotable @autotable(width=5) {cell1,cell2...} - creates a table that is 5 cells wide and puts the comma separated arguments in there @undef remove previously defined bi, unitag or define @name{name,desc} Add a name (A NAME= tag). First arg is the name, second is the description. This also adds the name to the table of contents for the current document (that table is generated whenever you use the @contents tag). Use + in front of the name to specify outline level. Take a look at the file index.sl for an example.