You are here

headinganchors.module in Table of Contents 5.2

Same filename and directory in other branches
  1. 5 headinganchors.module
  2. 6.2 headinganchors.module

This is a module which takes headings and adds id attributes to them to allow them to be linked to in a URL. The following rules are used to create an attribute:

  • All non alphanumerics are removed
  • Case is preserved to allow for some measure of readability
  • HTML tags are stripped from in the middle of heading tags for the anchors
  • Existing id's are left aline

Example: <h2>I Link To <a href="http://www.csaonline.ca/">csaonline.ca</a></h2> becomes: <h2 id="ILinkTocsaonline.ca">I Link To <a href="http://www.csaonline.ca/">csaonline.ca</a></h2> and can be referenced with /url#ILinkTocsaonline.ca

This module was built from the filter example on the Drupal website.

File

headinganchors.module
View source
<?php

/**
 * @file
 * This is a module which takes headings and adds id attributes to them
 * to allow them to be linked to in a URL. The following rules are used to create an
 * attribute:
 * - All non alphanumerics are removed
 * - Case is preserved to allow for some measure of readability
 * - HTML tags are stripped from in the middle of heading tags for the anchors
 * - Existing id's are left aline
 *
 * Example: <h2>I Link To <a href="http://www.csaonline.ca/">csaonline.ca</a></h2>
 * becomes:
 * <h2 id="ILinkTocsaonline.ca">I Link To <a href="http://www.csaonline.ca/">csaonline.ca</a></h2>
 * and can be referenced with /url#ILinkTocsaonline.ca
 *
 * This module was built from the filter example on the Drupal website.
 */

/**
 * Implementation of hook_help().
 *
 */
function headinganchors_help($section) {
  switch ($section) {
    case 'admin/modules#description':

      // This description is shown in the listing at admin/modules.
      return t('A module to create named anchors based on HTML headings.');
  }
}

/**
 * Implementation of hook_filter_tips().
 */
function headinganchors_filter_tips($format, $long = FALSE) {
  if ($long) {
    return t('Every instance heading tags will be modified to include an id attribute for anchor linking.');
  }
  else {
    return t('Insert heading anchors automatically.');
  }
}

/**
 * Implementation of hook_filter().
 *
 * The bulk of filtering work is done here.
 */
function headinganchors_filter($op, $delta = 0, $format = -1, $text = '') {
  if ($op == 'list') {
    return array(
      0 => t('Headings to Anchors'),
    );
  }

  // We currently only define one filter, so we don't need to switch on $delta
  switch ($op) {

    // Admin interface description
    case 'description':
      return t('Inserts named anchors for heading tags automatically.');
    case 'no cache':
      return FALSE;

    // Need to find out if this is required
    case 'prepare':
      return $text;

    // Here, we pull out the required information and add the anchor
    case 'process':

      // transform headers into anchors, max <h6>, case insensitive
      $matches = array();
      preg_match_all("/<h([1-6])([^>]*)>(.*?)<\\/h[1-6]>/is", $text, $matches, PREG_PATTERN_ORDER);
      $count = 0;
      $anchors = array();
      foreach ($matches[0] as $match) {

        // get level and heading
        $level = $matches[1][$count];
        $attributes = $matches[2][$count];
        $heading = $matches[3][$count];

        // check for existing id and use that if found
        if (preg_match('/id="(.*?)"/i', $attributes, $existing_id)) {
          $anchor = $existing_id[1];

          // remove the existing id, it will be added back later
          $attributes = preg_replace('/\\s*id="(.*?)"\\s*/i', '', $attributes);

          // if no id found, create one
        }
        else {

          // sanitize ID text & remove leading digits (invalid on IDs)
          $anchor = preg_replace("/&amp;/", "", strip_tags($matches[3][$count]));
          $anchor = preg_replace("/[^A-Za-z0-9]/", "", $anchor);
          $anchor = preg_replace("/^[0-9]+/", "", $anchor);
        }

        // Look for duplicate ID's, and add -number to make them unique
        if (array_key_exists($anchor, $anchors)) {
          $anchors[$anchor]++;
        }
        else {
          $anchors[$anchor] = 1;
        }
        if ($anchors[$anchor] > 1) {
          $anchor .= "-" . $anchors[$anchor];
        }
        $pattern = "/<h" . $level . preg_quote($attributes, '/') . ">" . preg_quote($heading, '/') . "<\\/h" . $level . ">/i";

        // append everything together to create the new heading
        $replacement = "<h" . $level . $attributes . " id=\"" . $anchor . "\">" . str_replace('$', '\\$', $heading) . "</h" . $level . ">";

        // replace the header in the text
        // Limit of one so that identical headers are only replaced one at a time
        $text = preg_replace($pattern, $replacement, $text, 1);
        $count++;
      }
      return $text;
  }
}

Functions

Namesort descending Description
headinganchors_filter Implementation of hook_filter().
headinganchors_filter_tips Implementation of hook_filter_tips().
headinganchors_help Implementation of hook_help().