bucephalus.org
January 2011
ElephantMark is a simple method to generate HTML documents from PHP files by using the plain Markdown text formatting syntax.
elephantmark.php
is the script that converts PHP files into HTML documents.
It can be used online on a web server and offline, on the Command Line Interface.
Table of contents:
elephantmark.php
- the document generator
elephantmark.php
By modifying the PHP comment delimiters (i.e. //
or /*
and */
), ordinary PHP comments turn into
Markdown text parts. These parts are converted into HTML.
ElephantMark comprises just three simple syntax rules:
The Markdown block rule
A Markdown block has the form
/***
... there is the markdown text part ...
***/
It starts after a single line beginning with /***
and ends before a single line that
begins with ***/
.
For example, this PHP comment with Markdown code
/***
__Markdown__ is a great way to produce HTML, but with less effort. Check out the
[Wikipedia entry on Markdown](http://en.wikipedia.org/wiki/Markdown).
***/
will turn into
<p>
<strong>Markdown</strong> is a great way to produce HTML, but with less effort.
Check out the <a href="http://en.wikipedia.org/wiki/Markdown">Wikipedia entry on Markdown</a>.
</p>
after conversion.
The Markdown line rule
A Markdown line has the form
// // ... this line is markdown ...
Everything after the // //
(i.e. two slash, one space, two slash, one space)
is considered Markdown and converted accordingly.
Note, that the Markdown really starts after a space symbol, not directly after the last slash. For example, a line beginning with
// // # Third chapter ...
will turn into
<h1>Third chapter ...</h1>
But if it begins as
// //# Third chapter ...
the whole line will be ignored and not recognized as a Markup line.
The literal block rule
A literal block has the form
// // //
... php code ...
// // //
The beginning and end of a literal block is indicated by a line that begins with // // //
.
Everything between these delimiter lines is considered literal PHP code and will be displayed as such.
For example
// // //
function triple($n) {
return 3 * $n;
}
// // //
will after the conversion appear as
<pre><code>function triple($n) {
return 3 * $n;
}
</code></pre>
Note, that everything else in a line that begins with // // //
is cut off. This means, we can use
additional comments to help structuring literal blocks.
We could have written our previous example as
// // // start of the literal block
function triple($n) {
return 3 * $n;
}
// // // end of the literal block
and we would still have obtained the same HTML result after the conversion.
You should not try to nest these three rules in any way. For example, don't put a literal block inside a Markdown block, etc.
Everything else, i.e. all code of the PHP file, which is not in a Markdown block, on a Markdown line or inside a literal block, is ignored by ElephantMark and will not appear after the conversion.
A small PHP script with ElephantMark is given by the example.php
file with the following content:
<?php
// // ## The description
/***
This `example.php` script is the PHP version for
[the standard first program](http://en.wikipedia.org/wiki/Hello_world)
in computer language tutorials.
***/
// // ## The implementation
// // //
echo "Hello world!";
// // //
?>
The result after the conversion of example.php
will then be a HTML document comprising:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
</head>
<body>
<h2>The description</h2>
<p>
This <code>example.php</code> script is the PHP version for
<a href="http://en.wikipedia.org/wiki/Hello_world">the standard first program</a>
in computer language tutorials.
</p>
<h2>The implementation</h2>
<pre><code>echo "Hello world!";
</code></pre>
</body>
</html>
Here you can see how this document looks in your browser.
elephantmark.php
- the document generatorWith the PHP script file elephantmark.php
we can generate the HTML documentation from a PHP file
with ElephantMark comments either offline
(using the command line interface or CLI)
or online on a web server.
Next to a working installation of PHP itself, we need two PHP files:
markdown.php
This is the PHP version of the Markdown-to-HTML converter. It is written by Michel Fortin and available wrapped in a ZIP file:
http://michelf.com/docs/projets/php/markdown-extra-1.2.4.zip
elephantmark.php
This is the PHP script that converts ElephantMark enriched PHP source code into a HTML document. It is also wrapped in a ZIP file and free for download:
Suppose, we want to generate the HTML documentation from the previous example.php
file.
Make sure, the three files markdown.php
, elephantmark.php
and example.php
are all placed in
the current working directory.
Optionally, you can use a CSS stylesheet into the HTML document. In that case, make sure the according file,
say mystyle.css
is placed into the current directory, too.
The full syntax of the command is
php elephantmark.php PHPFILE TITLE CSSFILE
where the three arguments PHPFILE
, TITLE
and CSSFILE
are optional.
To save the generated document in a separate HTMLFILE
, use the universal >
to redirect the output
php elephantmark.php PHPFILE TITLE CSSFILE > HTMLFILE
The effect of a call with 0, 1, 2 or 3 arguments is then as follows:
php elephantmark.php
generates this very documentation.
php elephantmark.php > mymanual.html
generates this document and saves it in mymanual.html
.
php elephantmark.php example.php
converts the ElephantMark-enriched PHP code in example.php
into a HTML document.
php elephantmark.php example.php "My first project"
generates a HTML document from example.php
with the following title in its <head>
part:
<title>My first project</title>
php elephantmark.php example.php "My first pretty project" mystyle.css
adds the CSS of mystyle.css
inside a <style>
tag
<style type="text/css">
... the content of mystyle.css ...
</style>
If you like to add the CSS stylesheet but don't care about the title, you can call
php elephantmark.php example.php "" mystyle.css
elephantmark.php
can also be used on a web server by attaching extra parameters php
, title
and css
as a query to the URL.
The general syntax for the online document generation is then
http://www.example.com/mypath/elephantmark.php?php=PHPFILE&title=TITLE&css=CSSFILE
As usual, the query string is attached with a ?
and the key=VALUE
pairs are separated by &
.
Note, that each one of the three parameters php=PHPFILE
, title=TITLE
, css=CSSFILE
is optional.
Suppose, you want to generate the documentation for the example.php
file.
Make sure, the three files markdown.php
, elephantmark.php
and example.php
are then in the same
working directory.
If you wish to add the stylesheet, place mystyle.css
there as well.
When you now call
http://www.example.com/mypath/elephantmark.php?php=example.php&title=Hello&css=stylesheet.css
you will see a HTML document, which has the form
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>Hello</title>
<style type="text/css">
... content of mystyle.css ...
</style>
</head>
<body>
... converted content of example.php ...
</body>
</html>
If the TITLE
string uses spaces or other characters that are not allowed in URLs, then they should be
percent-encoded:
a space is then a %20
, etc.
So, strictly speaking, if I want my HTML document to have the title My first example
, I should add
title=My%20first%20example
.
However, I realize, that my SeaMonkey browser doesn't need this URL-encoding.
It works fine, when I simply write title=My first example
in the URL.
Leaving the whole query and just calling
http://www.example.com/mypath/elephantmark.php
generates the document you are reading just now, i.e. it is just an abbreviation for
http://www.example.com/mypath/elephantmark.php?php=elephantmark.php
elephantmark.php
As a user of ElephantMark, you will not need this, although this appendix can serve as a nice example itself. It contains a full listing of all PHP code in this file, all relevant code units are displayed in this documentation by wrapping them in literal blocks, as described earlier. Some functions are not properly implemented, yet, although the whole thing itself normally works fine, at least for me.
The Markup-to-HTML conversion is done with the Markdown()
function, which is part of the
markdown.php
script, written by Michel Fortin.
We only need Markdown()
in the implementation of the generate()
function, below.
include "markdown.php";
php2markdown()
This is the main function that turns ElephantMarked PHP code into Markdown text. Here is where the three syntax rules are implemented.
function php2markdown ($phpCode) {
$phpRows = explode ("\n", $phpCode);
$markdown = '';
$mode = 'PHP'; // $mode is one of the following: 'PHP', 'MARKDOWN', 'LITERAL'
foreach ($phpRows as $phpRow) {
if ($mode == 'PHP') {
if (substr ($phpRow, 0, 4) == '/***') {
$mode = 'MARKDOWN';
} elseif (substr ($phpRow, 0, 8) == '// // //') {
$mode = 'LITERAL';
$markdown .= "\n";
} elseif ($phpRow == '// //' || $phpRow == '// // ') {
$markdown .= "\n";
} elseif (substr ($phpRow, 0, 6) == '// // ') {
$markdown .= substr ($phpRow, 6) . "\n";
}
} elseif ($mode == 'MARKDOWN') {
if (substr ($phpRow, 0, 4) == '***/') {
$mode = 'PHP';
} else {
$markdown .= $phpRow . "\n";
}
} elseif ($mode == 'LITERAL') {
if (substr ($phpRow, 0, 8) == '// // //') {
$mode = 'PHP';
} else {
$markdown .= ' ' . $phpRow . "\n";
// four initial spaces in a line means code block in Markdown
}
} else {
trigger_error ("UNDEFINED MODE; SOMETHING WENT WRONG!");
}
}
return $markdown;
}
phpCodeContent()
This function is supposed to extract the code between PHP tags <?php ... ?>
and cuts off everything else.
For example,
$html = '<h1>Begin</h1> <?php echo "Hi there!"; ?> <h1>End</h1> <?php echo "Bye"; ?>';
echo phpCodeContent($html);
should return the string
'echo "Hi there!"; echo "Bye";'
This is a little complicated to implement properly, because cases where the delimiters appear inside a string etc. have to be considered carefully.
My implementation here is just a dummy one, which works fine for me in normal contexts. Certainly some homework for future improvements.
function phpCodeContent ($code) {
return $code;
}
htmlDocument()
takes HTML content, a document title and an optional stylesheet and wraps that in a proper HTML document form.
function htmlDocument ($html, $title, $css) {
// if $css is a nonempty string, it is wrapped in a style tag
if ($css) {
$css = "<style type=\"text/css\">\n"
. "<!--\n"
. $css
. "-->\n"
. "</style>\n";
}
// the $title, the $css code and the $html content are wrapped into a HTML document and
$doc = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n"
. "<html>\n"
. "<head>\n"
. "<title>" . $title . "</title>\n"
. $css
. "</head>\n"
. "<body>\n"
. $html
. "</body>\n"
. "</html>\n";
return $doc;
}
generate()
is the main function that integrates all previous steps into a whole.
function generate ($phpFile, $title, $cssFile) {
// 1. determine $php, the PHP source code
if ($phpFile) {
if (! file_exists ($phpFile))
trigger_error ( "The requested PHP file $phpFile does not exist.\n" );
} else {
$phpFile = 'elephantmark.php';
}
$php = file_get_contents ($phpFile);
// 2. determine $css, the CSS source code
if ($cssFile) {
if (file_exists ($cssFile)) {
$css = file_get_contents ($cssFile);
} else {
trigger_error ( "The requested CSS file $cssFile does not exist.\n" );
}
}
// 3. generate the documentation
$php = phpCodeContent ($php); // extract the PHP blocks
$markdown = php2markdown ($php); // generate the Markdown
$html = Markdown ($markdown); // convert into HTML with the function provided by Michel Fortin
$doc = htmlDocument ($html, $title, $css); // wrap the HTML into a HTML document with the optional CSS
return $doc;
}
scriptIsOnline()
This is just an auxiliary function to determine if the elephantmark.php
script was called from the CLI or
on the web server.
There must be more elegant ways to obtain the same answer, but it seems to do the job.
function scriptIsOnline () {
if ($_SERVER['argc'] == 0) { return TRUE; }
elseif ($_SERVER['argc'] == 1 && $_SERVER['QUERY_STRING']) { return TRUE; }
else { return FALSE; }
}
if (scriptIsOnline())
echo generate ($_GET['php'], $_GET['title'], $_GET['css']);
else
echo generate ($_SERVER['argv'][1], $_SERVER['argv'][2], $_SERVER['argv'][3]);
displays the (converted) content of elephantmark.php
. Of course, this is the content processed by PHP.
To obtain the whole source code of elephantmark.php
itself, download
http://www.bucephalus.org/ElephantMark/elephantmark-1.zip
and unpack the file from the ZIP archive.
http://www-bucephalus-org.blogspot.com/2011/01/elephantmark.html
for comments and additional info related to ElephantMark.
http://daringfireball.net/projects/markdown
the home and origin of Markdown by John Gruber.
http://michelf.com/projects/php-markdown
the PHP version of the original Markdown converter by John Gruber, written by Michel Fortin.
http://johnmacfarlane.net/pandoc
the home of pandoc, written by John MacFarlane. This is a great universal document converter, where Markdown is just one of the many formats.