Commit b88e21ab authored by Henrik Ingo's avatar Henrik Ingo
Browse files

New footnotes.module

parents
Loading
Loading
Loading
Loading

README.txt

0 → 100644
+33 −0
Changes for README.txt: 33 added lines, 0 removed lines.
Original line number Diff line number Diff line
// $Id$

The Footnotes module can be used to create automatically numbered footnotes
within a text. In the place, where you want to add a footnote, enclose the
footnote text within an fn tag: <fn>like this</fn>. The filter will take the
text within the tag and move it to a footnote at the bottom of the page. 
In it's place it will place a number which is also a link to the footnote.

There is also another filter which does the same with a Textile markup style.
Use it together with the Textile module.

The footnotes.module was created by henrik.ingo@avoinelama.fi. Enjoy!


INSTALL INSTRUCTIONS FOR FOOTNOTES.MODULE
----

1. Copy the contents of this module to modules/footnotes folder.
2. Login as site administrator.
3. Activate footnotes on the administer->modules page.
4. To use the footnotes filter in some input formats, go to administer->input formats.
5. For selected input formats, select configure and activate a suitable footnotes filter.

Note: Typically you want the footnotes filter to be pretty early in the chain. 
For instance the Footnotes Textile style filter outputs Textile markup, so it 
should definitively be before your Textile filter. If you need to lift the 
Footnotes filter higher up, click "rearrange".

KNOWN ISSUES
----

The filter tips don't show up below any input boxes in the Input formats section.
They do show up in administer->input formats
 No newline at end of file

footnotes.module

0 → 100644
+170 −0
Changes for footnotes.module: 170 added lines, 0 removed lines.
Original line number Diff line number Diff line
<?php
// $Id$

/**
 * @file
 * The Footnotes module is a filter that can be used to insert
 * automatically numbered footnotes into Drupal texts.
 *
 * Currently there are two filters. One is suitable for use primarily with html markup,
 * but can be used with any input format. The second filter outputs footnotes in 
 * Textile format. This means you should run this filter together and before the 
 * Textile filter.
 */

/**
 * Implementation of hook_help().
 *
 * Throughout Drupal, hook_help() is used to display help text at the top of
 * pages. Some other parts of drupal pages get explanatory text from these hooks
 * as well. We use it here to provide a description of the module on the
 * module administration page.
 */
function footnotes_help($section) {
  switch ($section) {
    case 'admin/modules#description':
      // This description is shown in the listing at admin/modules.
      return t('A filter to insert automatically numbered footnotes into Drupal texts.');
  }
}

/**
 * Implementation of hook_filter_tips().
 *
 * This hook allows filters to provide help text to users during the content
 * editing process. Short tips are provided on the content editing screen, while
 * long tips are provided on a separate linked page. Short tips are optional,
 * but long tips are highly recommended.
 */
function filter_example_filter_tips($delta, $format, $long = FALSE) {
  switch ($delta) {
    case 0:
      if ($long) {
        return t('You can insert footnotes directly into texts with <code>&lt;fn&gt;This text becomes a footnote.&lt;/fn&gt;</code>. This will be replaced with a running number (the footnote reference) and the text within the &lt;fn&gt; tags will be moved to the bottom of the page (the footnote).');
      }
      else {
        return t('Use &lt;fn&gt;...&lt;/fn&gt; to insert automatically numbered footnotes.');
      }
      break;

    case 1:
      if ($long) {
        return t('You can insert footnotes directly into texts with [# ...]. This will be replaced with a running number (the footnote reference) and the text within the [# ...] tags will be moved to the bottom of the page (the footnote). <em>This filter outputs footnotes in Textile format. You should use it together and before the Textile filter.');
      }
      else {
        return t('Use [# ...] to insert automatically numbered footnotes. Textile variant.');
      }
      break;
  }
}

/**
 * Implementation of hook_filter().
 *
 * The bulk of filtering work is done here. This hook is quite complicated, so
 * we'll discuss each operation it defines.
 */
function footnotes_filter($op, $delta = 0, $format = -1, $text = '') {
  // The "list" operation provides the module an opportunity to declare both how
  // many filters it defines and a human-readable name for each filter. Note that
  // the returned name should be passed through t() for translation.
  if ($op == 'list') {
    return array(
      0 => t('Footnotes &lt;fn&gt;'),
      1 => t('Footnotes Textile style'));
  }
//  if ($op == 'no cache') {
//    return true;
//  }
  // All operations besides "list" provide a $delta argument so we know which
  // filter they refer to. We'll switch on that argument now so that we can
  // discuss each filter in turn.
  switch ($delta) {

    // First is the html footnotes filter
    case 0:

      switch ($op) {
        // This description is shown in the administrative interface, unlike the
        // filter tips which are shown in the content editing interface.
        case 'description':
          return t('Use &lt;fn&gt;...&lt;/fn&gt; to insert automatically numbered footnotes.');

        // We don't need the "prepare" operation for this filter, but it's required
        // to at least return the input text as-is.
        //TODO: May need to escape <fn> if we use HTML filter too, but Footnotes could be first
        case 'prepare':
          return $text;

        // The actual filtering is performed here. The supplied text should be
        // returned, once any necessary substitutions have taken place.
        case 'process':
          $text = preg_replace_callback('|<fn>(.*?)</fn>|s', '_footnotes_replace_callback', $text);
          return $text . "\n<hr />\n" . _footnotes_replace_callback( NULL, 'output footer' );
      }
      break;

    // Textile version.
    case 1:

      switch ($op) {
        // This description is shown in the administrative interface, unlike the
        // filter tips which are shown in the content editing interface.
        case 'description':
          return t('Use [# ...] to insert automatically numbered footnotes in Textile markup.');

        // We don't need the "prepare" operation for this filter, but it's required
        // to at least return the input text as-is.
        case 'prepare':
          return $text;

        // The actual filtering is performed here. The supplied text should be
        // returned, once any necessary substitutions have taken place.
        case 'process':
          $text = preg_replace_callback('|\[# (.*?)\]|s', '_footnotes_replace_callback_textile', $text);
          return $text . "\n\n" . _footnotes_replace_callback_textile( NULL, 'output footer' );
      }
      break;
  }
}

function _footnotes_replace_callback( $matches, $op = '' ) {
  static $n = 0;
  static $store_matches = array();
  
  if( $op == 'output footer' ) {
    $str = '';
    for( $m = 1; $m <= $n; $m++ ){
      $str .= "<p><sup>$m</sup> " . $store_matches[ $m - 1 ] . " </p>\n\n";
    }
    $n = 0;
    $store_matches = array();
    return $str;
  }

  //default op: act as called by preg_replace_callback()
  array_push( $store_matches, $matches[1] );
  $n++;
  return '<sup>' . $n . '</sup>';  
}

function _footnotes_replace_callback_textile( $matches, $op = '' ) {
  static $n = 0;
  static $store_matches = array();
  
  if( $op == 'output footer' ) {
    $str = '';
    for( $m = 1; $m <= $n; $m++ ){
      $str .= "fn$m. " . $store_matches[ $m - 1 ] . "\n\n";
    }
    $n = 0;
    $store_matches = array();
    return $str;
  }

  //default op: act as called by preg_replace_callback()
  array_push( $store_matches, $matches[1] );
  $n++;
  return '[' . $n . ']';  
}
?>
 No newline at end of file