Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 46 additions & 8 deletions Michelf/Markdown.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ public static function defaultTransform($text) {
# Optional filter function for URLs
public $url_filter_func = null;

# Optional header id="" generation callback function.
public $header_id_func = null;

### Parser Implementation ###

Expand Down Expand Up @@ -773,21 +775,46 @@ protected function doHeaders($text) {

return $text;
}

protected function _doHeaders_callback_setext($matches) {
# Terrible hack to check we haven't found an empty list item.
if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1]))
return $matches[0];

$level = $matches[2]{0} == '=' ? 1 : 2;
$block = "<h$level>".$this->runSpanGamut($matches[1])."</h$level>";

# id attribute generation
$idAtt = $this->_generateIdFromHeaderValue($matches[1]);

$block = "<h$level$idAtt>".$this->runSpanGamut($matches[1])."</h$level>";
return "\n" . $this->hashBlock($block) . "\n\n";
}
protected function _doHeaders_callback_atx($matches) {

# id attribute generation
$idAtt = $this->_generateIdFromHeaderValue($matches[2]);

$level = strlen($matches[1]);
$block = "<h$level>".$this->runSpanGamut($matches[2])."</h$level>";
$block = "<h$level$idAtt>".$this->runSpanGamut($matches[2])."</h$level>";
return "\n" . $this->hashBlock($block) . "\n\n";
}

protected function _generateIdFromHeaderValue($headerValue) {

# if a header_id_func property is set, we can use it to automatically
# generate an id attribute.
#
# This method returns a string in the form id="foo", or an empty string
# otherwise.
if (!is_callable($this->header_id_func)) {
return "";
}
$idValue = call_user_func($this->header_id_func, $headerValue);
if (!$idValue) return "";

return ' id="' . $this->encodeAttribute($idValue) . '"';

}

protected function doLists($text) {
#
Expand Down Expand Up @@ -1682,14 +1709,17 @@ protected function teardown() {
# Expression to use when parsing in a context when no capture is desired
protected $id_class_attr_nocatch_re = '\{(?:[ ]*[#.a-z][-_:a-zA-Z0-9=]+){1,}[ ]*\}';

protected function doExtraAttributes($tag_name, $attr) {
protected function doExtraAttributes($tag_name, $attr, $defaultIdValue = null) {
#
# Parse attributes caught by the $this->id_class_attr_catch_re expression
# and return the HTML-formatted list of attributes.
#
# Currently supported attributes are .class and #id.
#
if (empty($attr)) return "";
# In addition, this method also supports supplying a default Id value,
# which will be used to populate the id attribute in case it was not
# overridden.
if (empty($attr) && !$defaultIdValue) return "";

# Split on components
preg_match_all('/[#.a-z][-_:a-zA-Z0-9=]+/', $attr, $matches);
Expand All @@ -1710,13 +1740,15 @@ protected function doExtraAttributes($tag_name, $attr) {
}
}

if (!$id) $id = $defaultIdValue;

# compose attributes as string
$attr_str = "";
if (!empty($id)) {
$attr_str .= ' id="'.$id.'"';
$attr_str .= ' id="'.$this->encodeAttribute($id) .'"';
}
if (!empty($classes)) {
$attr_str .= ' class="'.implode(" ", $classes).'"';
$attr_str .= ' class="'. implode(" ", $classes) . '"';
}
if (!$this->no_markup && !empty($attributes)) {
$attr_str .= ' '.implode(" ", $attributes);
Expand Down Expand Up @@ -2529,14 +2561,20 @@ protected function doHeaders($text) {
protected function _doHeaders_callback_setext($matches) {
if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
return $matches[0];

$level = $matches[3]{0} == '=' ? 1 : 2;
$attr = $this->doExtraAttributes("h$level", $dummy =& $matches[2]);

$defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[1]) : null;

$attr = $this->doExtraAttributes("h$level", $dummy =& $matches[2], $defaultId);
$block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";
return "\n" . $this->hashBlock($block) . "\n\n";
}
protected function _doHeaders_callback_atx($matches) {
$level = strlen($matches[1]);
$attr = $this->doExtraAttributes("h$level", $dummy =& $matches[3]);

$defaultId = is_callable($this->header_id_func) ? call_user_func($this->header_id_func, $matches[2]) : null;
$attr = $this->doExtraAttributes("h$level", $dummy =& $matches[3], $defaultId);
$block = "<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";
return "\n" . $this->hashBlock($block) . "\n\n";
}
Expand Down