All notable changes to this project will be documented in this file. Updates should follow the Keep a CHANGELOG principles.
Upgrading from 1.x? See https://commonmark.thephpleague.com/2.0/upgrading/ for additional information.
2.4.0 - 2023-03-24
- Added generic
CommonMarkException
marker interface for all exceptions thrown by the library - Added several new specific exception types implementing that marker interface:
AlreadyInitializedException
InvalidArgumentException
IOException
LogicException
MissingDependencyException
NoMatchingRendererException
ParserLogicException
- Added more configuration options to the Heading Permalinks extension (#939):
heading_permalink/apply_id_to_heading
- Whentrue
, theid
attribute will be applied to the heading element itself instead of the<a>
tagheading_permalink/heading_class
- class to apply to the heading elementheading_permalink/insert
- now acceptsnone
to prevent the creation of the<a>
link
- Added new
table/alignment_attributes
configuration option to control how table cell alignment is rendered (#959)
- Change several thrown exceptions from
RuntimeException
toLogicException
(or something extending it), including:CallbackGenerator
s that fail to set a URL or return an expected valueMarkdownParser
when deactivating the last block parser or attempting to get an active block parser when they've all been closed- Adding items to an already-initialized
Environment
- Rendering a
Node
when no renderer has been registered for it
HeadingPermalinkProcessor
now throwsInvalidConfigurationException
instead ofRuntimeException
when invalid config values are given.HtmlElement::setAttribute()
no longer requires the second parameter for boolean attributes- Several small micro-optimizations
- Changed Strikethrough to only allow 1 or 2 tildes per the updated GFM spec
- Fixed inaccurate
@throws
docblocks throughout the codebase, includingConverterInterface
,MarkdownConverter
, andMarkdownConverterInterface
.- These previously suggested that only
\RuntimeException
s were thrown, which was inaccurate as\LogicException
s were also possible.
- These previously suggested that only
2.3.9 - 2023-02-15
- Fixed autolink extension not detecting some URIs with underscores (#956)
2.3.8 - 2022-12-10
- Fixed parsing issues when
mb_internal_encoding()
is set to something other thanUTF-8
(#951)
2.3.7 - 2022-11-03
- Fixed
TaskListItemMarkerRenderer
not including HTML attributes set on the node by other extensions (#947)
2.3.6 - 2022-10-30
- Fixed unquoted attribute parsing when closing curly brace is followed by certain characters (like a
.
) (#943)
2.3.5 - 2022-07-29
- Fixed error using
InlineParserEngine
when no inline parsers are registered in theEnvironment
(#908)
2.3.4 - 2022-07-17
- Made a number of small tweaks to the embed extension's parsing behavior to fix #898:
- Changed
EmbedStartParser
to always capture embed-like lines in container blocks, regardless of parent block type - Changed
EmbedProcessor
to also removeEmbed
blocks that aren't direct children of theDocument
- Increased the priority of
EmbedProcessor
to1010
- Changed
- Fixed
EmbedExtension
not parsing embeds following a list block (#898)
2.3.3 - 2022-06-07
- Fixed
DomainFilteringAdapter
not reindexing the embed list (#884, #885)
2.3.2 - 2022-06-03
- Fixed FootnoteExtension stripping extra characters from tab-indented footnotes (#881)
2.2.5 - 2022-06-03
- Fixed FootnoteExtension stripping extra characters from tab-indented footnotes (#881)
2.3.1 - 2022-05-14
- Fixed AutolinkExtension not ignoring trailing strikethrough syntax (#867)
2.2.4 - 2022-05-14
- Fixed AutolinkExtension not ignoring trailing strikethrough syntax (#867)
2.3.0 - 2022-04-07
- Added new
EmbedExtension
(#805) - Added
DocumentRendererInterface
as a replacement for the now-deprecatedMarkdownRendererInterface
- Deprecated
MarkdownRendererInterface
; useDocumentRendererInterface
instead
2.2.3 - 2022-02-26
- Fixed front matter parsing with Windows line endings (#821)
2.1.3 - 2022-02-26
- Fixed front matter parsing with Windows line endings (#821)
2.0.4 - 2022-02-26
- Fixed front matter parsing with Windows line endings (#821)
2.2.2 - 2022-02-13
- Fixed double-escaping of image alt text (#806, #810)
- Fixed Psalm typehints for event class names
2.2.1 - 2022-01-25
- Fixed
symfony/deprecation-contracts
constraint
- Removed deprecation trigger from
MarkdownConverterInterface
to reduce noise
2.2.0 - 2022-01-22
- Added new
ConverterInterface
- Added new
MarkdownToXmlConverter
class - Added new
HtmlDecorator
class which can wrap existing renderers with additional HTML tags - Added new
table/wrap
config to apply an optional wrapping/container element around a table (#780)
HtmlElement
contents can now consist of anyStringable
, not justHtmlElement
andstring
- Deprecated
MarkdownConverterInterface
and itsconvertToHtml()
method; useConverterInterface
andconvert()
instead
2.1.2 - 2022-02-13
- Fixed double-escaping of image alt text (#806, #810)
- Fixed Psalm typehints for event class names
2.1.1 - 2022-01-02
- Added missing return type to
Environment::dispatch()
to fix deprecation warning (#778)
2.1.0 - 2021-12-05
- Added support for ext-yaml in FrontMatterExtension (#715)
- Added support for symfony/yaml v6.0 in FrontMatterExtension (#739)
- Added new
heading_permalink/aria_hidden
config option (#741)
- Fixed PHP 8.1 deprecation warning (#759, #762)
2.0.3 - 2022-02-13
- Fixed double-escaping of image alt text (#806, #810)
- Fixed Psalm typehints for event class names
2.0.2 - 2021-08-14
- Bumped minimum version of league/config to support PHP 8.1
- Fixed ability to register block parsers that identify lines starting with letters (#706)
2.0.1 - 2021-07-31
- Fixed nested autolinks (#689)
- Fixed description lists being parsed incorrectly (#692)
- Fixed Table of Contents not respecting Heading Permalink prefixes (#690)
2.0.0 - 2021-07-24
No changes were introduced since the previous RC2 release. See all entries below for a list of changes between 1.x and 2.0.
2.0.0-rc2 - 2021-07-17
- Fixed Mentions inside of links creating nested links against the spec's rules (#688)
2.0.0-rc1 - 2021-07-10
No changes were introduced since the previous release.
2.0.0-beta3 - 2021-07-03
- Any leading UTF-8 BOM will be stripped from the input
- The
getEnvironment()
method ofCommonMarkConverter
andGithubFlavoredMarkdownConverter
will always return the concrete, configurableEnvironment
for upgrading convenience - Optimized AST iteration
- Lots of small micro-optimizations
2.0.0-beta2 - 2021-06-27
- Added new
Node::iterator()
method andNodeIterator
class for faster AST iteration (#683, #684)
- Made compatible with CommonMark spec 0.30.0
- Optimized link label parsing
- Optimized AST iteration for a 50% performance boost in some event listeners (#683, #684)
- Fixed processing instructions with EOLs
- Fixed case-insensitive matching for HTML tag types
- Fixed type 7 HTML blocks incorrectly interrupting lazy paragraphs
- Fixed newlines in reference labels not collapsing into spaces
- Fixed link label normalization with escaped newlines
- Fixed unnecessary AST iteration when no default attributes are configured
2.0.0-beta1 - 2021-06-20
- Added three new extensions:
FrontMatterExtension
(see documentation)DescriptionListExtension
(see documentation)DefaultAttributesExtension
(see documentation)
- Added new
XmlRenderer
to simplify AST debugging (see documentation) (#431) - Added the ability to configure disallowed raw HTML tags (#507)
- Added the ability for Mentions to use multiple characters for their symbol (#514, #550)
- Added the ability to delegate event dispatching to PSR-14 compliant event dispatcher libraries
- Added new configuration options:
- Added
heading_permalink/min_heading_level
andheading_permalink/max_heading_level
options to control which headings get permalinks (#519) - Added
heading_permalink/fragment_prefix
to allow customizing the URL fragment prefix (#602) - Added
footnote/backref_symbol
option for customizing backreference link appearance (#522) - Added
slug_normalizer/max_length
option to control the maximum length of generated URL slugs - Added
slug_normalizer/unique
option to control whether unique slugs should be generated per-document or per-environment
- Added
- Added purity markers throughout the codebase (verified with Psalm)
- Added
Query
class to simplify Node traversal when looking to take action on certain Nodes - Added new
HtmlFilter
andStringContainerHelper
utility classes - Added new
AbstractBlockContinueParser
class to simplify the creation of custom block parsers - Added several new classes and interfaces:
BlockContinue
BlockContinueParserInterface
BlockContinueParserWithInlinesInterface
BlockStart
BlockStartParserInterface
ChildNodeRendererInterface
ConfigurableExtensionInterface
CursorState
DashParser
(extracted fromPunctuationParser
)DelimiterParser
DocumentBlockParser
DocumentPreRenderEvent
DocumentRenderedEvent
EllipsesParser
(extracted fromPunctuationParser
)ExpressionInterface
FallbackNodeXmlRenderer
InlineParserEngineInterface
InlineParserMatch
MarkdownParserState
MarkdownParserStateInterface
MarkdownRendererInterface
Query
RawMarkupContainerInterface
ReferenceableInterface
RenderedContent
RenderedContentInterface
ReplaceUnpairedQuotesListener
SpecReader
TableOfContentsRenderer
UniqueSlugNormalizer
UniqueSlugNormalizerInterface
XmlRenderer
XmlNodeRendererInterface
- Added several new methods:
Cursor::getCurrentCharacter()
Environment::createDefaultConfiguration()
Environment::setEventDispatcher()
EnvironmentInterface::getExtensions()
EnvironmentInterface::getInlineParsers()
EnvironmentInterface::getSlugNormalizer()
FencedCode::setInfo()
Heading::setLevel()
HtmlRenderer::renderDocument()
InlineParserContext::getFullMatch()
InlineParserContext::getFullMatchLength()
InlineParserContext::getMatches()
InlineParserContext::getSubMatches()
LinkParserHelper::parsePartialLinkLabel()
LinkParserHelper::parsePartialLinkTitle()
Node::assertInstanceOf()
RegexHelper::isLetter()
StringContainerInterface::setLiteral()
TableCell::getType()
TableCell::setType()
TableCell::getAlign()
TableCell::setAlign()
- Changed the converter return type
CommonMarkConverter::convertToHtml()
now returns an instance ofRenderedContentInterface
. This can be cast to a string for backward compatibility with 1.x.
- Table of Contents items are no longer wrapped with
<p>
tags (#613) - Heading Permalinks now link to element IDs instead of using
name
attributes (#602) - Heading Permalink IDs and URL fragments now have a
content
prefix by default (#602) - Changes to configuration options:
enable_em
has been renamed tocommonmark/enable_em
enable_strong
has been renamed tocommonmark/enable_strong
use_asterisk
has been renamed tocommonmark/use_asterisk
use_underscore
has been renamed tocommonmark/use_underscore
unordered_list_markers
has been renamed tocommonmark/unordered_list_markers
mentions/*/symbol
has been renamed tomentions/*/prefix
mentions/*/regex
has been renamed tomentions/*/pattern
and requires partial regular expressions (without delimiters or flags)max_nesting_level
now defaults toPHP_INT_MAX
and no longer supports floatsheading_permalink/slug_normalizer
has been renamed toslug_normalizer/instance
- Event dispatching is now fully PSR-14 compliant
- Moved and renamed several classes - see the full list here
- The
HeadingPermalinkExtension
andFootnoteExtension
were modified to ensure they never produce a slug which conflicts with slugs created by the other extension SlugNormalizer::normalizer()
now supports optional prefixes and max length options passed in via the$context
argument- The
AbstractBlock::$data
andAbstractInline::$data
arrays were replaced with aData
array-like object on the baseNode
class - Implemented a new approach to block parsing. This was a massive change, so here are the highlights:
- Functionality previously found in block parsers and node elements has moved to block parser factories and block parsers, respectively (more details)
ConfigurableEnvironmentInterface::addBlockParser()
is nowEnvironmentBuilderInterface::addBlockParserFactory()
ReferenceParser
was re-implemented and works completely different than before- The paragraph parser no longer needs to be added manually to the environment
- Implemented a new approach to inline parsing where parsers can now specify longer strings or regular expressions they want to parse (instead of just single characters):
InlineParserInterface::getCharacters()
is nowgetMatchDefinition()
and returns an instance ofInlineParserMatch
InlineParserContext::__construct()
now requires the contents to be provided as aCursor
instead of astring
- Implemented delimiter parsing as a special type of inline parser (via the new
DelimiterParser
class) - Changed block and inline rendering to use common methods and interfaces
BlockRendererInterface
andInlineRendererInterface
were replaced byNodeRendererInterface
with slightly different parameters. All core renderers now implement this interface.ConfigurableEnvironmentInterface::addBlockRenderer()
andaddInlineRenderer()
were combined intoEnvironmentBuilderInterface::addRenderer()
EnvironmentInterface::getBlockRenderersForClass()
andgetInlineRenderersForClass()
are now justgetRenderersForClass()
- Completely refactored the Configuration implementation
- All configuration-specific classes have been moved into a new
league/config
package with a new namespace Configuration
objects must now be configured with a schema and all options must match that schema - arbitrary keys are no longer permittedConfiguration::__construct()
no longer accepts the default configuration values - useConfiguration::merge()
insteadConfigurationInterface
now only contains aget(string $key)
; this method no longer allows arbitrary default values to be returned if the option is missingConfigurableEnvironmentInterface
was renamed toEnvironmentBuilderInterface
ExtensionInterface::register()
now requires anEnvironmentBuilderInterface
param instead ofConfigurableEnvironmentInterface
- All configuration-specific classes have been moved into a new
- Added missing return types to virtually every class and interface method
- Re-implemented the GFM Autolink extension using the new inline parser approach instead of document processors
EmailAutolinkProcessor
is nowEmailAutolinkParser
UrlAutolinkProcessor
is nowUrlAutolinkParser
HtmlElement
can now properly handle array (i.e.class
) and boolean (i.e.checked
) attribute valuesHtmlElement
automatically flattens any attributes with array values into space-separated strings, removing duplicate entries- Combined separate classes/interfaces into one:
DisallowedRawHtmlRenderer
replacesDisallowedRawHtmlBlockRenderer
andDisallowedRawHtmlInlineRenderer
NodeRendererInterface
replacesBlockRendererInterface
andInlineRendererInterface
- Renamed the following methods:
Environment
andConfigurableEnvironmentInterface
:addBlockParser()
is nowaddBlockStartParser()
ReferenceMap
andReferenceMapInterface
:addReference()
is nowadd()
getReference()
is nowget()
listReferences()
is nowgetIterator()
- Various node (block/inline) classes:
getContent()
is nowgetLiteral()
setContent()
is nowsetLiteral()
- Moved and renamed the following constants:
EnvironmentInterface::HTML_INPUT_ALLOW
is nowHtmlFilter::ALLOW
EnvironmentInterface::HTML_INPUT_ESCAPE
is nowHtmlFilter::ESCAPE
EnvironmentInterface::HTML_INPUT_STRIP
is nowHtmlFilter::STRIP
TableCell::TYPE_HEAD
is nowTableCell::TYPE_HEADER
TableCell::TYPE_BODY
is nowTableCell::TYPE_DATA
- Changed the visibility of the following properties:
AttributesInline::$attributes
is nowprivate
AttributesInline::$block
is nowprivate
TableCell::$align
is nowprivate
TableCell::$type
is nowprivate
TableSection::$type
is nowprivate
- Several methods which previously returned
$this
now returnvoid
Delimiter::setPrevious()
Node::replaceChildren()
Context::setTip()
Context::setContainer()
Context::setBlocksParsed()
AbstractStringContainer::setContent()
AbstractWebResource::setUrl()
- Several classes are now marked
final
:ArrayCollection
Emphasis
FencedCode
Heading
HtmlBlock
HtmlElement
HtmlInline
IndentedCode
Newline
Strikethrough
Strong
Text
Heading
nodes no longer directly contain a copy of their inner textStringContainerInterface
can now be used for inlines, not just blocksArrayCollection
only supports integer keysHtmlElement
now implementsStringable
Cursor::saveState()
andCursor::restoreState()
now useCursorState
objects instead of arraysNodeWalker::next()
now enters, traverses any children, and leaves all elements which may have children (basically all blocks plus any inlines with children). Previously, it only did this for elements explicitly marked as "containers".InvalidOptionException
was removed- Anything with a
getReference(): ReferenceInterface
method now implementsReferencableInterface
- The
SmartPunct
extension now replaces all unpairedQuote
elements withText
elements towards the end of parsing, making theQuoteRenderer
unnecessary - Several changes made to the Footnote extension:
- Footnote identifiers can no longer contain spaces
- Anonymous footnotes can now span subsequent lines
- Footnotes can now contain multiple lines of content, including sub-blocks, by indenting them
- Footnote event listeners now have numbered priorities (but still execute in the same order)
- Footnotes must now be separated from previous content by a blank line
- The line numbers (keys) returned via
MarkdownInput::getLines()
now start at 1 instead of 0 DelimiterProcessorCollectionInterface
now extendsCountable
RegexHelper::PARTIAL_
constants must always be used in case-insensitive contextsHeadingPermalinkProcessor
no longer accepts text normalizers via the constructor - these must be provided via configuration instead- Blocks which can't contain inlines will no longer be asked to render inlines
AnonymousFootnoteRefParser
andHeadingPermalinkProcessor
now implementEnvironmentAwareInterface
instead ofConfigurationAwareInterface
- The second argument to
TextNormalizerInterface::normalize()
must now be an array - The
title
attribute forLink
andImage
nodes is now stored using a dedicated property instead of stashing it in$data
ListData::$delimiter
now returns eitherListBlock::DELIM_PERIOD
orListBlock::DELIM_PAREN
instead of the literal delimiter
- Fixed parsing of footnotes without content
- Fixed rendering of orphaned footnotes and footnote refs
- Fixed some URL autolinks breaking too early (#492)
- Fixed
AbstractStringContainer
not actually beingabstract
- Removed support for PHP 7.1, 7.2, and 7.3 (#625, #671)
- Removed all previously-deprecated functionality:
- Removed the ability to pass custom
Environment
instances into theCommonMarkConverter
andGithubFlavoredMarkdownConverter
constructors - Removed the
Converter
class andConverterInterface
- Removed the
bin/commonmark
script - Removed the
Html5Entities
utility class - Removed the
InlineMentionParser
(useMentionParser
instead) - Removed
DefaultSlugGenerator
andSlugGeneratorInterface
from theExtension/HeadingPermalink/Slug
sub-namespace (use the new ones under./SlugGenerator
instead) - Removed the following
ArrayCollection
methods:add()
set()
get()
remove()
isEmpty()
contains()
indexOf()
containsKey()
replaceWith()
removeGaps()
- Removed the
ConfigurableEnvironmentInterface::setConfig()
method - Removed the
ListBlock::TYPE_UNORDERED
constant - Removed the
CommonMarkConverter::VERSION
constant - Removed the
HeadingPermalinkRenderer::DEFAULT_INNER_CONTENTS
constant - Removed the
heading_permalink/inner_contents
configuration option
- Removed the ability to pass custom
- Removed now-unused classes:
AbstractStringContainerBlock
BlockRendererInterface
Context
ContextInterface
Converter
ConverterInterface
InlineRendererInterface
PunctuationParser
(was split into two classes:DashParser
andEllipsesParser
)QuoteRenderer
UnmatchedBlockCloser
- Removed the following methods, properties, and constants:
AbstractBlock::$open
AbstractBlock::$lastLineBlank
AbstractBlock::isContainer()
AbstractBlock::canContain()
AbstractBlock::isCode()
AbstractBlock::matchesNextLine()
AbstractBlock::endsWithBlankLine()
AbstractBlock::setLastLineBlank()
AbstractBlock::shouldLastLineBeBlank()
AbstractBlock::isOpen()
AbstractBlock::finalize()
AbstractBlock::getData()
AbstractInline::getData()
ConfigurableEnvironmentInterface::addBlockParser()
ConfigurableEnvironmentInterface::mergeConfig()
Delimiter::setCanClose()
EnvironmentInterface::getConfig()
EnvironmentInterface::getInlineParsersForCharacter()
EnvironmentInterface::getInlineParserCharacterRegex()
HtmlRenderer::renderBlock()
HtmlRenderer::renderBlocks()
HtmlRenderer::renderInline()
HtmlRenderer::renderInlines()
Node::isContainer()
RegexHelper::matchAll()
(use the newmatchFirst()
method instead)RegexHelper::REGEX_WHITESPACE
- Removed the second
$contents
argument from theHeading
constructor
The following things have been deprecated and will not be supported in v3.0:
Environment::mergeConfig()
(set configuration before instantiation instead)Environment::createCommonMarkEnvironment()
andEnvironment::createGFMEnvironment()
- Alternative 1: Use
CommonMarkConverter
orGithubFlavoredMarkdownConverter
if you don't need to customize the environment - Alternative 2: Instantiate a new
Environment
and add the necessary extensions yourself
- Alternative 1: Use