Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
# Conflicts:
#	CHANGELOG.md
#	src/Parser.php
  • Loading branch information
angrybrad committed Jun 26, 2023
2 parents 1c8cebd + dc5e96d commit 578c280
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- Added the `useAdditionalTagToAnchorTo` config setting which allows you to opt out of a tag being added and used to link to, in favour of using heading's id. ([#21](https://github.com/craftcms/anchors/issues/21))
- Fixed a couple of URL formatting bugs around case sensitivity and punctuation. ([#31](https://github.com/craftcms/anchors/issues/31))

## 3.2.0 - 2023-01-09
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ The following config settings are supported:
- `anchorLinkClass` – The class name that should be given to anchor links. (Default is `'anchor'`.)
- `anchorLinkText` – The visible text that anchor links should have. (Default is `'#'`'.)
- `anchorLinkTitleText` – The title/alt text that anchor links should have. If `{heading}` is included, it will be replaced with the heading text the link is associated with. (Default is `'Direct link to {heading}'`.)
- `useAdditionalTagToAnchorTo` – Whether to render an additional tag above the heading and use it to scroll to when the anchor link is clicked. If set to `false`, anchor id is added to the heading. (Default is `true`.)

## Plugin API

Expand Down
50 changes: 44 additions & 6 deletions src/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ class Parser extends Component
*/
public $anchorLinkTitleText;

/**
* @var bool|null
* @since 3.3.0
*/
public $useAdditionalTagToAnchorTo;

// Public Methods
// =========================================================================

Expand All @@ -64,7 +70,20 @@ public function parseHtml(string $html, $tags = 'h1,h2,h3', ?string $language =
}

return preg_replace_callback('/<(' . implode('|', $tags) . ')([^>]*)>\s*([\w\W]+?)\s*<\/\1>/', function(array $match) use ($language, $lowercase) {
$anchorName = $this->generateAnchorName($match[3], $language, $lowercase);
$headingHasId = false;
// try to get id from the heading tag only if we're not supposed to use additional tag to anchor to
if (!$this->useAdditionalTagToAnchorTo && !empty($match[2])) {
$anchorName = $this->getIdFromHeading($match[2]);
if (!empty($anchorName)) {
$headingHasId = true;
}
}

// if we still don't have the name for the anchor - generate it
if (empty($anchorName)) {
$anchorName = $this->generateAnchorName($match[3], $language, $lowercase);
}

$heading = preg_replace('/\s+/', ' ', strip_tags(str_replace(['&nbsp;', ' '], ' ', $match[3])));
$link = Html::tag('a', $this->anchorLinkText, [
'class' => $this->anchorLinkClass,
Expand All @@ -74,11 +93,12 @@ public function parseHtml(string $html, $tags = 'h1,h2,h3', ?string $language =
]);

return
Html::tag('span', '', [
'class' => $this->anchorClass,
'id' => $anchorName,
]) .
"<$match[1]$match[2]>" .
($this->useAdditionalTagToAnchorTo ?
Html::tag('span', '', [
'class' => $this->anchorClass,
'id' => $anchorName,
]) : '') .
"<$match[1]$match[2]" . (!$this->useAdditionalTagToAnchorTo && !$headingHasId ? " id=\"$anchorName\"" : "") . ">" .
($this->anchorLinkPosition === Settings::POS_BEFORE ? "$link $match[3]" : "$match[3] $link") .
"</$match[1]>";
}, $html);
Expand Down Expand Up @@ -131,4 +151,22 @@ public function generateAnchorName(string $heading, string $language = null, boo
// Put them together as the anchor name
return StringHelper::toAscii(implode('-', $words), $language);
}

/**
* Check if there's an id in the attributes. If there is one - return its value.
*
* @param $attributes
* @return string|null
*/
public function getIdFromHeading($attributes): ?string
{
$id = null;
preg_match('/id="(\w+)"/', $attributes, $match);

if (isset($match[1]) && !empty($match[1])) {
$id = trim($match[1]);
}

return $id;
}
}
1 change: 1 addition & 0 deletions src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public function init()
$parser->anchorLinkClass = $parser->anchorLinkClass ?? $settings->anchorLinkClass;
$parser->anchorLinkText = $parser->anchorLinkText ?? $settings->anchorLinkText;
$parser->anchorLinkTitleText = $parser->anchorLinkTitleText ?? $settings->anchorLinkTitleText;
$parser->useAdditionalTagToAnchorTo = $parser->useAdditionalTagToAnchorTo ?? $settings->useAdditionalTagToAnchorTo;

if (!Craft::$app->getRequest()->getIsCpRequest()) {
// Register the Twig extension
Expand Down
9 changes: 9 additions & 0 deletions src/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,13 @@ class Settings extends Model
* the link is associated with. (Default is 'Direct link to {heading}'.)
*/
public $anchorLinkTitleText = 'Direct link to {heading}';

/**
* @var bool Whether to render an additional tag above the heading
* and use it to scroll to when the anchor link is clicked.
* If set to 'false', anchor id is added to the heading itself.
* (Default is 'true'.)
* @since 3.3.0
*/
public $useAdditionalTagToAnchorTo = true;
}

0 comments on commit 578c280

Please sign in to comment.