diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php
index 25fe909d7a..2f7ba09ae0 100644
--- a/.phpstorm.meta.php
+++ b/.phpstorm.meta.php
@@ -27,7 +27,7 @@
expectedArguments(\League\CommonMark\Node\Inline\Newline::__construct(), 0, argumentsSet('league_commonmark_newline_types'));
expectedReturnValues(\League\CommonMark\Node\Inline\Newline::getType(), argumentsSet('league_commonmark_newline_types'));
- registerArgumentsSet('league_commonmark_options', 'renderer', 'renderer/block_separator', 'renderer/inner_separator', 'renderer/soft_break', 'enable_em', 'enable_strong', 'use_asterisk', 'use_underscore', 'unordered_list_markers', 'html_input', 'allow_unsafe_links', 'max_nesting_level', 'disallowed_raw_html', 'disallowed_raw_html/disallowed_tags', 'external_link', 'external_link/nofollow', 'external_link/noopener', 'external_link/noreferrer', 'footnote', 'footnote/backref_class', 'footnote/container_add_hr', 'footnote/container_class', 'footnote/ref_class', 'footnote/ref_id_prefix', 'footnote/footnote_class', 'footnote/footnote_id_prefix', 'heading_permalink', 'heading_permalink/html_class', 'heading_permalink/id_prefix', 'heading_permalink/inner_contents', 'heading_permalink/insert', 'heading_permalink/slug_normalizer', 'heading_permalink/symbol', 'heading_permalink/title', 'table_of_contents', 'table_of_contents/style', 'table_of_contents/normalize', 'table_of_contents/position', 'table_of_contents/html_class', 'table_of_contents/min_heading_level', 'table_of_contents/max_heading_level', 'table_of_contents/placeholder');
+ registerArgumentsSet('league_commonmark_options', 'renderer', 'renderer/block_separator', 'renderer/inner_separator', 'renderer/soft_break', 'enable_em', 'enable_strong', 'use_asterisk', 'use_underscore', 'unordered_list_markers', 'html_input', 'allow_unsafe_links', 'max_nesting_level', 'disallowed_raw_html', 'disallowed_raw_html/disallowed_tags', 'external_link', 'external_link/nofollow', 'external_link/noopener', 'external_link/noreferrer', 'footnote', 'footnote/backref_class', 'footnote/container_add_hr', 'footnote/container_class', 'footnote/ref_class', 'footnote/ref_id_prefix', 'footnote/footnote_class', 'footnote/footnote_id_prefix', 'heading_permalink', 'heading_permalink/html_class', 'heading_permalink/id_prefix', 'heading_permalink/inner_contents', 'heading_permalink/insert', 'heading_permalink/levels', 'heading_permalink/slug_normalizer', 'heading_permalink/symbol', 'heading_permalink/title', 'table_of_contents', 'table_of_contents/style', 'table_of_contents/normalize', 'table_of_contents/position', 'table_of_contents/html_class', 'table_of_contents/min_heading_level', 'table_of_contents/max_heading_level', 'table_of_contents/placeholder');
expectedArguments(\League\CommonMark\Environment\EnvironmentInterface::getConfig(), 0, argumentsSet('league_commonmark_options'));
expectedArguments(\League\CommonMark\Configuration\ConfigurationInterface::get(), 0, argumentsSet('league_commonmark_options'));
expectedArguments(\League\CommonMark\Configuration\ConfigurationInterface::set(), 0, argumentsSet('league_commonmark_options'));
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4109be9f78..006eed518a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@ See for detailed informatio
### Added
- Added the ability to configure disallowed raw HTML tags (#507)
+ - Added `heading_permalink/levels` option to control which headings get permalinks (#519)
- Added new `HtmlFilter` and `StringContainerHelper` utility classes
- Added new `AbstractBlockContinueParser` class to simplify the creation of custom block parsers
- Added several new classes and interfaces:
diff --git a/docs/2.0/extensions/heading-permalinks.md b/docs/2.0/extensions/heading-permalinks.md
index 66b9e8347d..f2b812bd7b 100644
--- a/docs/2.0/extensions/heading-permalinks.md
+++ b/docs/2.0/extensions/heading-permalinks.md
@@ -45,6 +45,7 @@ $config = [
'html_class' => 'heading-permalink',
'id_prefix' => 'user-content',
'insert' => 'before',
+ 'levels' => [1, 2, 3, 4, 5, 6],
'title' => 'Permalink',
'symbol' => HeadingPermalinkRenderer::DEFAULT_SYMBOL,
'slug_normalizer' => new SlugNormalizer(),
@@ -72,6 +73,10 @@ This should be a `string` you want prepended to HTML IDs. This prevents generat
This controls whether the anchor is added to the beginning of the `
`, `` etc. tag or to the end. Can be set to either `'before'` or `'after'`.
+### `levels`
+
+This controls which heading levels should get permalinks. For example, if you only want links for ``, ``, and `` tags, you can set this option to `[1, 2, 3]`.
+
### `symbol`
This option sets the symbol used to display the permalink on the document. This defaults to `\League\CommonMark\Extension\HeadingPermalink\HeadingPermalinkRenderer::DEFAULT_SYMBOL = '¶'`.
diff --git a/src/Extension/HeadingPermalink/HeadingPermalinkProcessor.php b/src/Extension/HeadingPermalink/HeadingPermalinkProcessor.php
index 884b02e62e..9c72a8dbbf 100644
--- a/src/Extension/HeadingPermalink/HeadingPermalinkProcessor.php
+++ b/src/Extension/HeadingPermalink/HeadingPermalinkProcessor.php
@@ -58,11 +58,13 @@ public function __invoke(DocumentParsedEvent $e): void
{
$this->useNormalizerFromConfigurationIfProvided();
+ $levels = $this->config->get('heading_permalink/levels', [1, 2, 3, 4, 5, 6]);
+
$walker = $e->getDocument()->walker();
while ($event = $walker->next()) {
$node = $event->getNode();
- if ($node instanceof Heading && $event->isEntering()) {
+ if ($node instanceof Heading && $event->isEntering() && \in_array($node->getLevel(), $levels, true)) {
$this->addHeadingLink($node);
}
}
diff --git a/tests/functional/Extension/HeadingPermalink/HeadingPermalinkExtensionTest.php b/tests/functional/Extension/HeadingPermalink/HeadingPermalinkExtensionTest.php
index b410ca6987..0c4c15ec8f 100644
--- a/tests/functional/Extension/HeadingPermalink/HeadingPermalinkExtensionTest.php
+++ b/tests/functional/Extension/HeadingPermalink/HeadingPermalinkExtensionTest.php
@@ -127,4 +127,33 @@ public function testHeadingPermalinksWithInvalidInsertConfigurationValue(): void
$converter = new CommonMarkConverter($config, $environment);
$converter->convertToHtml('# This will fail');
}
+
+ public function testWithCustomLevels(): void
+ {
+ $environment = Environment::createCommonMarkEnvironment();
+ $environment->addExtension(new HeadingPermalinkExtension());
+
+ $config = [
+ 'heading_permalink' => [
+ 'levels' => [2, 3],
+ ],
+ ];
+
+ $converter = new CommonMarkConverter($config, $environment);
+
+ $input = <<1
+
+
+4
+EOT;
+
+ $this->assertEquals($expected, \trim($converter->convertToHtml($input)));
+ }
}