Skip to content

Commit

Permalink
Merge branch 'v2'
Browse files Browse the repository at this point in the history
# Conflicts:
#	CHANGELOG.md
  • Loading branch information
angrybrad committed Jun 22, 2023
2 parents 897282f + e8eb89f commit 1c8cebd
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 9 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Release Notes for Anchors

## Unreleased

- 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
- Added the `@anchors` GraphQL directive. ([#18](https://github.com/craftcms/anchors/issues/18))

Expand All @@ -16,6 +20,7 @@
- The `parser` component can now be configured via `craft\services\Plugins::$pluginConfigs`.

## 2.4.0 - 2022-12-16

- Removed unnecessary tab spots. ([#21](https://github.com/craftcms/anchors/issues/21))
- Fixed a bug where headings that spanned multiple lines were ignored. ([#20](https://github.com/craftcms/anchors/issues/20))

Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,14 @@ If you are displaying content in a different language than the current site, use
{{ entry.body|anchors(language=entry.site.language) }}
```

By default, `anchors` filter will lowercase words that are all uppercase and lowercase the first letter in any other case.

If you want the anchors to always be lowercase, you can use the `lowercase` argument:

```twig
{{ entry.body|anchors(lowercase=true) }}
```

## Configuration

To configure Anchors, create a new `anchors.php` file within the `config/` folder, which returns an array.
Expand Down
24 changes: 17 additions & 7 deletions src/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,17 @@ class Parser extends Component
* @param string $html The HTML to parse
* @param string|string[] $tags The tags to add anchor links to.
* @param string|null $language The content language, used when converting non-ASCII characters to ASCII
* @param bool $lowercase Whether to always lowercase the entire anchor name
* @return string The parsed HTML.
*/
public function parseHtml(string $html, $tags = 'h1,h2,h3', ?string $language = null): string
public function parseHtml(string $html, $tags = 'h1,h2,h3', ?string $language = null, bool $lowercase = false): string
{
if (is_string($tags)) {
$tags = StringHelper::split($tags);
}

return preg_replace_callback('/<(' . implode('|', $tags) . ')([^>]*)>\s*([\w\W]+?)\s*<\/\1>/', function(array $match) use ($language) {
$anchorName = $this->generateAnchorName($match[3], $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);
$heading = preg_replace('/\s+/', ' ', strip_tags(str_replace(['&nbsp;', ' '], ' ', $match[3])));
$link = Html::tag('a', $this->anchorLinkText, [
'class' => $this->anchorLinkClass,
Expand All @@ -88,10 +89,15 @@ public function parseHtml(string $html, $tags = 'h1,h2,h3', ?string $language =
*
* @param string $heading
* @param string|null $language
* @param bool $lowercase
* @return string The generated anchor name.
*/
public function generateAnchorName(string $heading, string $language = null): string
public function generateAnchorName(string $heading, string $language = null, bool $lowercase = false): string
{
// decode html entities into chars
// see https://github.com/craftcms/anchors/issues/31 for details
$heading = htmlspecialchars_decode($heading, ENT_QUOTES);

// Remove HTML tags
$heading = preg_replace('/<(.*?)>/', '', $heading);

Expand All @@ -110,11 +116,15 @@ public function generateAnchorName(string $heading, string $language = null): st

// Turn them into camelCase
foreach ($words as $i => $word) {
// Special case if the whole word is capitalized
if (strtoupper($word) === $word) {
if ($lowercase === true) {
$words[$i] = strtolower($word);
} else {
$words[$i] = lcfirst($word);
// Special case if the whole word is capitalized
if (strtoupper($word) === $word) {
$words[$i] = strtolower($word);
} else {
$words[$i] = lcfirst($word);
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/TwigExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ public function getFilters(): array
* @param mixed $html The HTML to parse.
* @param string|string[] $tags The HTML tags to check for.
* @param string|null $language The content language, used when converting non-ASCII characters to ASCII
* @param bool $lowercase Whether to always lowercase the entire anchor name
* @return string The parsed string.
*/
public function anchorsFilter($html, $tags = 'h1,h2,h3', ?string $language = null): string
public function anchorsFilter($html, $tags = 'h1,h2,h3', ?string $language = null, bool $lowercase = false): string
{
return Plugin::getInstance()->getParser()->parseHtml((string)$html, $tags, $language);
return Plugin::getInstance()->getParser()->parseHtml((string)$html, $tags, $language, $lowercase);
}
}

0 comments on commit 1c8cebd

Please sign in to comment.