*/ /******************************************************************** * Drupal Hooks ********************************************************************/ /** * Implementation of hook_filter(). */ function textile_filter($op, $delta = 0, $format = -1, $text = '') { switch ($op) { case 'list': return array(t("Textile")); case 'description': return t('Allows content to be submitted using Textile, a simple, plain text syntax that is filtered into valid XHTML.'); case 'process': if (variable_get("textile_tags_$format", 0)) { return preg_replace_callback('{\[textile\](.*?)(\[/textile\]|$)}is', '_textile_process', $text); } else { return _textile_process(array(NULL, $text)); } case 'settings': $form = array(); $form['textile_settings'] = array( '#type' => 'fieldset', '#title' => t('Textile filter'), '#collapsible' => TRUE ); $form['textile_settings']["textile_tags_$format"] = array( '#type' => 'checkbox', '#title' => t('Use tags'), '#default_value' => variable_get("textile_tags_$format", 0), '#description' => t('If enabled, only text between [textile] and optional [/textile] tags will be processed. Otherwise, all text will be processed as Textile markup.') ); return $form; default: return $text; } } /** * Implementation of hook_filter_tips(). */ function textile_filter_tips($delta, $format, $long = FALSE) { if ($long) { return t('

Textile Help

Block modifier syntax:

CSS attributes can be applied to blocks (paragraphs, headers, etc.). CSS classes are specifed with "(class)"; CSS IDs are specified with "(#id)"; both can be specified with "(class#id)". An arbtirary CSS style can be applied by using "{style}". Finally, language attributes are applied using "[language]".

Additionally, alignment and indentation shorthands are provided. To left-align, right-align, center, and justify text, use "<", ">", "=", and "<>", respectively. "(" left-indents a block 1em for each occurrence, and ")" right-indents similarly.

Tables have additional options. "^", "-", and "~" specify top, middle, and bottom vertical alignment. The "_" attribute on a cell indicates that it is a table header.

The examples below illustrate these attributes.

textile input output

Headings

hx. (where x is 1 - 6)
h1. Heading

Heading

h2(class). Heading with class

Heading with class

Paragraphs

p=. Centered text

Centered text

p())(#id). Indented text with ID

Indented text with ID

Block quotes

bq(class#id). Quote with class and ID
Quote with class and ID
bq[en]. English quote
English quote

Ordered lists

{color: blue}# Attributes specified
# before the first item
# affect the whole list
  1. Attributes specified
  2. before the first item
  3. affect the whole list

Unordered lists

* Lists can have
## subitems or
## sublists
* too
  • Lists can have
    1. subitems or
    2. sublists
  • too

Footnotes

fnx. (where x is 1 - 100)
fn17. Footnote

17 Footnote

Tables

|_. A|_. B|_. C|
(dark). |very|simple|table|
|<. left|=. center|>. right|
|^{height:3em}. top|-. middle|~. bottom|
A B C
very simple table
left center right
top middle bottom

Phrase modifier syntax:

The class, ID, style, and language attributes described above also apply to the span phrase modifier as shown below.

textile input output
_emphasis_ emphasis
__italic__ italic
*strong* strong
**bold** bold
??citation?? citation
-delete text- deleted text
+inserted text+ inserted text
^superscript^ superscript
~subscript~ subscript
@code@ code
%(class)span% span
%{color:red;}span% span
==no textile== no textile
"link text":url link text
"link text(title)":url link text
!imageurl!
!imageurl(alt text)! alt text
!imageurl!:url
ABC(Always Be Closing) ABC
Footnote reference[17] Footnote reference17
'); } elseif (variable_get("textile_tags_$format", 0)) { return t('You can use Textile markup to format text between the [textile] and (optional) [/textile] tags.'); } else { return t('You can use Textile markup to format text.'); } } /** * Implementation of hook_help(). */ function textile_help($path = 'admin/help#textile', $arg) { switch ($path) { case 'admin/help#textile': return t('

The Textile module allows users to enter content using Textile, a simple, plain text syntax that is filtered into valid XHTML. The filter tips page provides syntax descriptions and examples.

'); } } /** * Implementation of hook_enable() * * Run a check for the library and set an error message if not present. */ function textile_enable() { if ($error = _textile_lib_check()) { drupal_set_message($error, 'error'); } } /******************************************************************** * Module Functions ********************************************************************/ /** * Performs the appropriate Textile filtering on the provided text. * * @param $matches * The array specifying the text to be filtered at * index 1. * * @return * A string containing the filtered text. * * @private */ function _textile_process($matches) { static $textile = NULL; if ($textile === NULL) { $path = drupal_get_path('module', 'textile'); include_once($path .'/classTextile.php'); $textile = new Textile(); //$textile->hu is the string that preceeds all relative URLs. //So I copied the part of url() implementation in common.inc //not tested in real non-Apache webserver yet $textile->hu = base_path() . ((strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === FALSE) ? 'index.php' : '') . ((bool)variable_get('clean_url', '0') ? '' : '?q='); } //should there be any encoding declaration of some sort? Can't find how to do it though return $textile->TextileThis($matches[1]); } /** * Checking that the classTextile.php library is installed, and if not return an error string. */ function _textile_lib_check() { $path = drupal_get_path('module', 'textile'); if (!file_exists($path .'/classTextile.php')) { return t('The classTextile.php library is missing. Drupal cannot use textile markup without this library. Please check the textile module INSTALL documentation for information on how to download this.', array('!url' => 'http://cvs.drupal.org/viewcvs/*checkout*/drupal/contributions/modules/textile/INSTALL.txt')); } }