2011-06-17

By Xyne

Xac Simple Web Framework

README

The rest of this page is just copied and pasted from the default index page included in Xac. It serves as a live guide when you point a server's docroot at the base directory in the downloaded archive.

Because it is directly copied and pasted, some links will not work and some files will be missing. This applies to the "Extras" section as well, where the RSS feed and table of latest contents will reflect those of the current site and not what you would see with the default Xac server.

You can grab the latest "release" from the nav tree to your right.

You can find a thread about this here.

About

Xac (xyne.archlinux.ca) is the simple custom web framework that I use on my site. The content is created in markdown and then converted to php using a toolchain including pandoc, source-highlight and my own tex2png. This enables simple markdown to include highlighted code blocks, mathematical formulae written in (La)TeX, and the output of php functions. The focus has been on ease of content management.

Please note that I am sharing this mostly because others have asked about it. This was never developed with distribution in mind and it should probably not be treated as a plug-n-play web framework. Use it as a starting point for whatever you want to do and tweak it as you see fit.

Disclaimer

This code is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See here and here for more information.

Usage

Content Management

Markdown Files

Content should we written in markdown and saved in the markdown directory (_markdown). The hierarchy of files within the markdown directory is how they will appear to the user when he or she visits the site. For example, if you want a page to appear at <your site>/foo/bar, you would save it to _markdown/foo/bar.txt.1

The markdown files are not visible to the user. They are only used to generate the php content with the update_content script located in _meta. You edit the markdown files in your preferred editor, then you cd into the document root and run the update script:

cd /path/to/docroot
./_meta/update_content .

The script:

  • creates or updates a content file in _content for each markdown file in _markdown
  • runs pandoc
  • runs post_pandoc.pl which:
    • tweaks pandoc's output (fixes bugs, adjusts references)
    • adds syntax highlighting with source-highlight
    • adds image generated by tex2png and image generated by tex2png images using tex2png, with auto-adjustment for vertical alignment
    • sanitizes the output for PHP inclusion

get.php is then able to load the content into the template file (/etc/xac/template.php) and display it.

Regular Files

Regular files are kept in _files and their relative path within _files determines where they appear on the server. For example, _files/a/b/c.txt can be accessed as <your site>/a/b/c.txt.

The hierarchies in _markdown and _files are thus combined to present a unified docroot to users. E.g. if you have _markdown/foo/bar.txt and _files/foo/baz.pdf, they will both appear to be in <your site>/foo/.

Index Files and Directories

Sometimes you will want to present a page written in markdown when a user navigates to a directory. Let's say that you have 3 scripts: foo.sh, bar.pl and baz.py. You place these in _files/scripts so that they appear at <your site>/scripts/. Now you want the user to see a page with explanations of what they do when he or she navigates to <your site>/scripts/. To do this, you would create a markdown page at _markdown/scripts/index.txt. All markdown pages named index.txt are hidden from the navigation tree and are shown when a user nagivates to that directory. You can see this yourself by visiting the scripts directory.

Another example is this page. It is saved as _markdown/index.txt so that it will be displayed when the user navigates to the server's document root. Notice that it doesn't appear in the list at the top right.2

If a user visits a directory without an index.txt file, get.php will default to a directory listing. You can see this by visiting the img directory. It is also possible to include a directory listing within a markdown page. See the markdown syntax section below for details.

Uploading and Caching

I currently run update_content on local files and then use lftp to mirror them to the server. This is mostly because I do not have full control over the server and what is installed on it. The following is an example mirror script that you can use with lftp:

open <your ftp server>
mirror --reverse --delete -p --parallel=10 --verbose  -L -x '^(.+/)?error_log$' -x '^_meta(/.*)?$' -x '^_dyn(/.*)?$' /path/to/the/local/docroot/ /

The site can then be mirrored with lftp -f /path/to/mirror_script.

Another thing that I should point out is that the generated pages are not cached. For a small site this is not an issue because the overhead of generating the files is negligible, but if you get slashdotted or your site regularly experiences high traffic then you will probably want caching.

I've considered adding it a few times but because of the number of dynamic sources for some pages and the low level of traffic the site gets, it just hasn't been worth it. If you want to submit code to enable caching, please do.

Scalability, Reliability, Etc

This wasn't written with large-scale application in mind. It's a hacked-together content management system for a small site. It works for me and that's all that I'm really concerned about at this point. I share it in the hopes that it will be useful but without any guarantee whatsoever. It might work wonderfully for a large site or it might make your server cry.

Markdown Syntax

You can learn markdown syntax by reading the guide at Daring Fireball followed by the Pandoc User Guide. The rest of this section describes additional features added by the post_pandoc.pl script.

Delimited Code Blocks and Syntax Highlighting

Syntax highlighting is provided by GNU Source-highlight using Pandoc's Delimited Code Blocks. Pandoc can be compiled with support for syntax highlighting but it was too tedious when I looked into it and I prefer to use standard packages to simplify updates. source-highlight is good and supports many languages.

The input language is specified using Pandoc's syntax. Here's an example using the options parser in tex2png:

while getopts "c:d:fho:p:s:t:T" flag; do
  case "$flag" in
    c) content="$OPTARG" ;;
    d) outputdir="${OPTARG/%\/}" ;;
    f) full="true" ;;
    h) display_help ;;
    o) imgpath="$OPTARG" ;;
    p) page="$OPTARG" ;;
    s) size="$OPTARG" ;;
    t) tmpdir="$OPTARG" ;;
    T) tight="true" ;;
  esac
done

That was generated by this:

~~~~~~~~~~{.shell}
while getopts "c:d:fho:p:s:t:T" flag; do
  case "$flag" in
    c) content="$OPTARG" ;;
    d) outputdir="${OPTARG/%\/}" ;;
    f) full="true" ;;
    h) display_help ;;
    o) imgpath="$OPTARG" ;;
    p) page="$OPTARG" ;;
    s) size="$OPTARG" ;;
    t) tmpdir="$OPTARG" ;;
    T) tight="true" ;;
  esac
done
~~~~~~~~~~

Note that the language name must be one which source-highlight recognizes.

Highlighting can be configured with etc/template_code.css.

Inserting PHP Functions

etc/template_config.php contains an array named allowed_inserts which specifies which functions may be included in the markdown files. These functions are specified using HTML comments. To insert the function "foo", you would include <!-- foo --> in the markdown. <!-- foo --> will then be replaced with the output of the PHP function "foo()". It is also possible to use *!-- foo --*. This was added to circumvent issues with Pandoc processing in some contexts.

You cannot pass arguments to these functions with one exception. Adding "path" to the comment, e.g. <!-- foo path -->, will pass the requested path to "foo", i.e. "foo(<path>)". This can be used for page-specific functions such as directory listings. Here's an example:

FileSizeLast Modified
scripts/4.00 KiB2010-05-20 14:33 GMT
xac-2011-06-17-1.tar.xz69.66 KiB2011-06-17 07:25 GMT

This was generated with

<!-- get_directory_table path -->

image generated by tex2png and image generated by tex2png

Anything that pandoc encloses in <EQ> tags when using the --gladtex option will be replaced with an image. This is intended for the insertion of mathematical formulae using "$". The images are generated using tex2png.

For example, the equation image generated by tex2png was generated automatically from the following:3

$\phi_n(\kappa) =
 \frac{1}{4\pi^2\kappa^2} \int_0^\infty
 \frac{\sin(\kappa R)}{\kappa R}
 \frac{\partial}{\partial R}
 \left[R^2\frac{\partial D_n(R)}{\partial R}\right]\,dR$

You can see the markdown by navigating to markdown_example.txt, which is just a symlink in _files to the markdown source of this page.

It is also possible to use custom <script> tags to embed (La)TeX. This is useful when you wish to use TeX formatting outside of the math environment. The template follows this format:

<script type="text/latex">
latex_code
</script>

Everything between the opening and closing <script> tags will be passed to tex2png as content.

Here's an example followed by the markdown code used to generate it:

image generated by tex2png
<script type="text/latex">
$$\displaystyle\phi_n(\kappa) =
 \frac{1}{4\pi^2\kappa^2} \int_0^\infty
 \frac{\sin(\kappa R)}{\kappa R}
 \frac{\partial}{\partial R}
 \left[R^2\frac{\partial D_n(R)}{\partial R}\right]\,dR$$
</script>

Chemical Images

Images of chemicals can be inserted using custom <INCHI> tags if openbabel and imagemagick are installed.

Examples:

<INCHI>1S/C2H4O2/c1-2(3)4/h1H3,(H,3,4)</INCHI>

chemical image

<INCHI>1/C10H14N5O6P/c11-9-8-10(13-3-12-9)15(4-14-8)7-1-5(16)6(21-7)2-20-22(17,18)19/h3-7,16H,1-2H2,(H2,11,12,13)(H2,17,18,19)/t5-,6+,7+/m0/s1</INCHI>

chemical image

It is also possible to insert SVG images:

<INCHI type="svg">1/C10H14N5O6P/c11-9-8-10(13-3-12-9)15(4-14-8)7-1-5(16)6(21-7)2-20-22(17,18)19/h3-7,16H,1-2H2,(H2,11,12,13)(H2,17,18,19)/t5-,6+,7+/m0/s1</INCHI>

Your browser does not support SVG images.

<INCHI type="svg">1S/C38H44O2/c1-9-11-13-15-29-23-30(16-14-12-10-2)25-31(24-29)26-32-27-33(17-19-37(3,4)5)35(36-39-21-22-40-36)34(28-32)18-20-38(6,7)8/h23-25,27-28,36H,9-12,21-22,26H2,1-8H3</INCHI>

Your browser does not support SVG images.

The images are entirely determined by openbabel. At the time of writing, it seems that the "-genalias" option is not working as expected.

Verbatim Content

Sometimes it's desirable to avoid all Pandoc processing of some content, most often when you want to pass content through to the post_pandoc.pl script. To do this, use the custom VERBATIM XHTML tags in the markdown file.

<VERBATIM>
Raw XTHML or content for further processing.
</VERBATIM>

The opening and closing tags must each appear at the beginning of the line and they must be followed immediately by a newline.

Note that if the content will not be processed by post_pandoc.pl then it must be valid XHTML because it will be inserted directly into the final document.

See the Graphviz section for a real example of using the VERBATIM tags.

Graphviz

Graphviz diagrams can be inserted directly into the markdown pages using custom GRAPHVIZ tags. These must be wrapped in VERBATIM tags to prevent Pandoc from escaping the dot syntax for XHTML display.

<VERBATIM>
<GRAPHVIZ>
digraph "Xac Graphviz Example" {
  graph [bgcolor=transparent,splines=true, pad=0.2];
  node [style=filled]

  node [fillcolor="#aaaaff", shape=diamond]
  start [label="graphviz"]

  node [shape="ellipse",fillcolor="#cccccc"]
  useful_q [label="Is this useful?"]

  node [shape="diamond", fillcolor="#88cc33"]
  useful [label="Enjoy!"]

  node [shape="diamond", fillcolor="#cc3333"]
  useless [label="Then don't\nuse it. ;)"]

  edge [dir=forward, color="black", labelfloat=false]
  start -> useful_q
  useful_q:w -> useful [label="Surprisingly, yes!"]
  useful_q:e -> useless [label="LOL, no!"]

  overlap=false
}
</GRAPHVIZ>
</VERBATIM>
Your browser does not support SVG images.

The GRAPHVIZ tag may also specify a different layout engine using the type attribute, e.g.

<GRAPHVIZ type="neato">

Dependencies

  • Server
    • Apache with mod_rewrite and PHP or equivalent
  • Local
    • Perl
    • Pandoc
    • GNU Source-highlight (optional, for syntax highlighting)
    • tex2png (optional, for (La)Tex images)
    • openbabel & imagemagick (optional, for chemical images)
    • graphviz (optional, for Graphviz diagrams)

Files and Directories

docroot/

.htaccess

Apache's mod_rewrite is used to funnel requests to get.php which is the main frontend to the server. It also enables requests to various files to pass through transparently. The rules are listed in .htaccess.

_content/

This contains the formatted content for inclusion in the template.

etc/

This is for PHP sources, configuration files, CSS and Javascript, RSS feeds, etc. (ha!)

_files/

This is a directory for all files that you want to serve directly but which belong to the site hierarchy, e.g. images, archives, music and videos. Files in this directory will appear in the navigation tree on the right alongside content pages.

get.php

The main frontend which handles requests and serves up the template.

_markdown/

The content pages in markdown format. These are not accessible via the server.

_meta/

A directory containing scripts for formatting the output. These do not need to be included on the server and will not be accessible by default if they are.

x/

This is a directory of all files that are not part of the hierarchy. All requests to files in this directory are passed through but requests to list directories are blocked. This is where you should place things such as form processors and other backend stuff.

docroot/etc/

xac_config.php
main configuration file

docroot/etc/xac

template_code.css

CSS for syntax highlighting

template_constants.php

constants for global configuration of paths (note that any changes must be manually applied to the content management scripts as well)

template_style.css.php

the main css file

template_functions.php

functions used by the template (e.g. nav tree generation)

template.php

the template into which content is inserted

Extras

The following are extra features included here as examples of what you can do with Xac. Some may be ready for a server while others may just be snippets to give you some ideas. See the comments in /etc/xac_config.php and /etc/xac/extra.php for details.

Simply remove the corresponding code and files for any feature that you do not wish to include on your site.

Configuration

This is just a simple example of how to let users configure the site. You must enable cookies for it to work.

The form only accepts hexadecimal color codes of the form "#xxxxxx", although this could easily be expanded. See the comments in /etc/xac_config.php.

The form posts to /x/set_color.php, which is a simple PHP page that processes the form and sets or unsets a cookie. The file is in /x/ because it is a backend script and not part of the site's content hierarchy.

The cookie is read by /etc/xac_config.php (via /etc/xac/extra.php) and used to generate the global CSS style sheet.

Note that the form can be included in any markdown page. See the markdown source for this page for reference .

RSS and Latest Changes

HTML

Here is an example of a table listing the latest content changes on the site. It could easily be changed to list the latest files as well.

WhatWhen
/home/miscellaneous/config2011-12-22 08:21 GMT
/home/projects/python3-xynexdg2011-07-13 16:30 GMT
/home/projects/python3-aur2011-07-04 03:46 GMT
/home/scripts/conky2011-07-01 10:44 GMT
/home/old_projects/paconky2011-07-01 10:10 GMT
/home/scripts/pacman2011-06-27 11:22 GMT
/home/notes/try_this/harmless_linux_pranks2011-06-18 00:08 GMT
/home/notes/haskell/hslua2011-06-17 07:32 GMT
/home/miscellaneous/xac/2011-06-17 07:25 GMT
/home/projects/tex2png2011-06-17 04:56 GMT
/home/2011-06-17 04:50 GMT
/home/scripts/openbox2011-06-16 04:43 GMT
/home/projects/obfilebrowser2011-06-16 04:30 GMT
/home/miscellaneous/xac2011-05-07 22:45 GMT
/home/projects/pacserve2011-05-07 22:44 GMT

RSS

Here is a link to the example RSS feed.


  1. Note the .txt extension. All markdown files are expected to have this extension.

  2. That's not entirely true. The file markdown_example.txt is a symlink in _files/ that points to _markdown/index.txt, which is what was used to generate this page.

  3. Unfortunately LaTeX math mode syntax highlighting is monochrome.