diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..ebda902 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +.jekyll-cache diff --git a/docs/1.0/basic-usage.md b/docs/1.0/basic-usage.md new file mode 100644 index 0000000..7a50696 --- /dev/null +++ b/docs/1.0/basic-usage.md @@ -0,0 +1,47 @@ +--- +layout: default +title: Basic Usage +description: Basic usage of the CommonMark parser +--- + +Basic Usage +============== + +The `CommonMarkConverter` class provides a simple wrapper for converting Markdown to HTML: + +~~~php +convertToHtml('# Hello World!'); + +//

Hello World!

+~~~ + +Or if you want Github-Flavored Markdown: + +```php +convertToHtml('# Hello World!'); + +//

Hello World!

+``` + + +**Important:** See the [security](/2.0/security/) section for important details on avoiding security misconfigurations. + +[Additional customization](/2.0/customization/overview/) is also possible, and we have many handy [extensions](/2.0/extensions/) to enable additional syntax and features. + +## Supported Character Encodings + +Please note that only UTF-8 and ASCII encodings are supported. If your Markdown uses a different encoding please convert it to UTF-8 before running it through this library. + +## Return Value + +The `convertToHtml()` method actually returns an instance of `League\CommonMark\Output\RenderedContentInterface`. You can cast this (implicitly, as shown above, or explicitly) to a `string` or call `getContent()` to get the final HTML output. diff --git a/docs/1.0/changelog.md b/docs/1.0/changelog.md new file mode 100644 index 0000000..8fa9da8 --- /dev/null +++ b/docs/1.0/changelog.md @@ -0,0 +1,20 @@ +--- +layout: default +title: Changelog +description: Important changes made in recent releases +--- + +# Changelog + +All notable changes made in `2.x` releases are shown below. See the [full list of releases](/releases) for the complete changelog. + +{% assign releases = site.github.releases | where_exp: "r", "r.name >= '2.0'" | where_exp: "r", "r.name < '3.0'" %} + +{% for release in releases %} +## [{{ release.name }}]({{ release.html_url }}) - {{ release.published_at | date: "%Y-%m-%d" }} +{{ release.body | markdownify }} +{% endfor %} + +## Older Versions + +Please see the [full list of releases](/releases) for the complete changelog. diff --git a/docs/1.0/configuration.md b/docs/1.0/configuration.md new file mode 100644 index 0000000..4cfda4c --- /dev/null +++ b/docs/1.0/configuration.md @@ -0,0 +1,63 @@ +--- +layout: default +title: Configuration +--- + +Configuration +============= + +You can provide an array of configuration options to the `CommonMarkConverter` when creating it: + +~~~php + [ + 'block_separator' => "\n", + 'inner_separator' => "\n", + 'soft_break' => "\n", + ], + 'enable_em' => true, + 'enable_strong' => true, + 'use_asterisk' => true, + 'use_underscore' => true, + 'unordered_list_markers' => ['-', '*', '+'], + 'html_input' => 'escape', + 'allow_unsafe_links' => false, + 'max_nesting_level' => INF, +]); +~~~ + +Here's a list of currently-supported options: + +* `renderer` - Array of options for rendering HTML + * `block_separator` - String to use for separating renderer block elements + * `inner_separator` - String to use for separating inner block contents + * `soft_break` - String to use for rendering soft breaks +* `enable_em` - Disable `` parsing by setting to `false`; enable with `true` (default: `true`) +* `enable_strong` - Disable `` parsing by setting to `false`; enable with `true` (default: `true`) +* `use_asterisk` - Disable parsing of `*` for emphasis by setting to `false`; enable with `true` (default: `true`) +* `use_underscore` - Disable parsing of `_` for emphasis by setting to `false`; enable with `true` (default: `true`) +* `unordered_list_markers` - Array of characters that can be used to indicated a bulleted list (default: `["-", "*", "+"]`) +* `html_input` - How to handle HTML input. Set this option to one of the following strings: + - `strip` - Strip all HTML (equivalent to `'safe' => true`) + - `allow` - Allow all HTML input as-is (default value; equivalent to `'safe' => false) + - `escape` - Escape all HTML +* `allow_unsafe_links` - Remove risky link and image URLs by setting this to `false` (default: `true`) +* `max_nesting_level` - The maximum nesting level for blocks (default: infinite). Setting this to a positive integer can help protect against long parse times and/or segfaults if blocks are too deeply-nested. Added in 0.17. + +Additional configuration options are available for some of the [available extensions](/2.0/customization/extensions/) - refer to their individual documentation for more details. + +## Environment + +The configuration is ultimately passed to (and managed via) the `Environment`. If you're creating your own `Environment`, simply pass your config array into its constructor instead. + +The `Environment` also exposes three methods for managing the configuration: + +* `setConfig(array $config = [])` - Replace the current configuration with something else +* `mergeConfig(array $config = [])` - Recursively merge the current configuration with the given options +* `getConfig(string $key, $default = null)` - Returns the config value. For nested configs, use a `/`-separate path; for example: `renderer/soft_break` + +[Learn more about customizing the Environment](/2.0/customization/environment/) diff --git a/docs/1.0/index.md b/docs/1.0/index.md new file mode 100644 index 0000000..2aecf6e --- /dev/null +++ b/docs/1.0/index.md @@ -0,0 +1,46 @@ +--- +layout: default +title: Overview +--- + + + +# Overview + +[![Author](https://img.shields.io/badge/author-@colinodell-blue.svg?style=flat-square)](https://twitter.com/colinodell) +[![Latest Version](https://img.shields.io/packagist/v/league/commonmark.svg?style=flat-square)](https://packagist.org/packages/league/commonmark) +[![Total Downloads](https://img.shields.io/packagist/dt/league/commonmark.svg?style=flat-square)](https://packagist.org/packages/league/commonmark) +[![Software License](https://img.shields.io/badge/License-BSD--3-brightgreen.svg?style=flat-square)](LICENSE) +[![Build Status](https://img.shields.io/github/workflow/status/thephpleague/commonmark/Tests/latest.svg?style=flat-square)](https://github.com/thephpleague/commonmark/actions?query=workflow%3ATests+branch%3Alatest) +[![Coverage Status](https://img.shields.io/scrutinizer/coverage/g/thephpleague/commonmark.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/commonmark/code-structure) +[![Quality Score](https://img.shields.io/scrutinizer/g/thephpleague/commonmark.svg?style=flat-square)](https://scrutinizer-ci.com/g/thephpleague/commonmark) + +{{ site.data.project.highlights.description }} + +## Installation + +This library can be installed via Composer: + +~~~bash +composer require league/commonmark +~~~ + +See the [installation](/2.0/installation/) section for more details. + +## Basic Usage + +Simply instantiate the converter and start converting some Markdown to HTML! + +~~~php +convertToHtml('# Hello World!'); + +//

Hello World!

+~~~ + + +**Important:** See the [basic usage](/2.0/basic-usage/) and [security](/2.0/security/) sections for important details. diff --git a/docs/1.0/installation.md b/docs/1.0/installation.md new file mode 100644 index 0000000..3488240 --- /dev/null +++ b/docs/1.0/installation.md @@ -0,0 +1,21 @@ +--- +layout: default +title: Installation +description: Instructions on how to install the league/commonmark library +--- + +# Installation + +The recommended installation method is via Composer. + +In your project root just run: + +~~~bash +composer require league/commonmark:^2.0 +~~~ + +Ensure that you’ve set up your project to [autoload Composer-installed packages](https://getcomposer.org/doc/00-intro.md#autoloading). + +## Versioning + +[SemVer](http://semver.org/) will be followed closely. **It's highly recommended that you use [Composer's caret operator](https://getcomposer.org/doc/articles/versions.md#caret) to ensure compatibility**; for example: `^2.0`. This is equivalent to `>=2.0 <3.0`. diff --git a/docs/1.0/security.md b/docs/1.0/security.md new file mode 100644 index 0000000..38d81aa --- /dev/null +++ b/docs/1.0/security.md @@ -0,0 +1,92 @@ +--- +layout: default +title: Security +description: How to configure league/commonmark against possible security issues when handling untrusted user input +--- + +Security +======== + +In order to be fully compliant with the CommonMark spec, certain security settings are disabled by default. You will want to configure these settings if untrusted users will be providing the Markdown content: + + - `html_input`: How to handle raw HTML + - `allow_unsafe_links`: Whether unsafe links are permitted + - `max_nesting_level`: Protected against long render times or segfaults + +Further information about each option can be found below. + +## HTML Input + +**All HTML input is unescaped by default.** This behavior ensures that league/commonmark is 100% compliant with the CommonMark spec. + +If you're developing an application which renders user-provided Markdown from potentially untrusted users, you are **strongly** encouraged to set the `html_input` option in your configuration to either `escape` or `strip`: + +### Example - Escape all raw HTML input: + +~~~php +use League\CommonMark\CommonMarkConverter; + +$converter = new CommonMarkConverter(['html_input' => 'escape']); +echo $converter->convertToHtml(''); + +// <script>alert("Hello XSS!");</script> +~~~ + +### Example - Strip all HTML from the input: +~~~php +use League\CommonMark\CommonMarkConverter; + +$converter = new CommonMarkConverter(['html_input' => 'strip']); +echo $converter->convertToHtml(''); + +// (empty output) +~~~ + +**Failing to set this option could make your site vulnerable to cross-site scripting (XSS) attacks!** + +See the [configuration](/2.0/configuration/) section for more information. + +## Unsafe Links + +Unsafe links are also allowed by default due to CommonMark spec compliance. An unsafe link is one that uses any of these protocols: + + - `javascript:` + - `vbscript:` + - `file:` + - `data:` (except for `data:image` in png, gif, jpeg, or webp format) + +To prevent these from being parsed and rendered, you should set the `allow_unsafe_links` option to `false`. + +## Nesting Level + +**No maximum nesting level is enforced by default.** Markdown content which is too deeply-nested (like 10,000 nested blockquotes: '> > > > > ...') [could result in long render times or segfaults](https://github.com/thephpleague/commonmark/issues/243#issuecomment-217580285). + +If you need to parse untrusted input, consider setting a reasonable `max_nesting_level` (perhaps 10-50) depending on your needs. Once this nesting level is hit, any subsequent Markdown will be rendered as plain text. + +### Example - Prevent deep nesting + +~~~php +use League\CommonMark\CommonMarkConverter; + +$markdown = str_repeat('> ', 10000) . ' Foo'; + +$converter = new CommonMarkConverter(['max_nesting_level' => 5]); +echo $converter->convertToHtml($markdown); + +//
+//
+//
+//
+//
+//

> > > > > > > ... Foo

+//
+//
+//
+//
+~~~ + +See the [configuration](/2.0/configuration/) section for more information. + +## Additional Filtering + +Although this library does offer these security features out-of-the-box, some users may opt to also run the HTML output through additional filtering layers (like HTMLPurifier). If you do this, make sure you **thoroughly** test your additional post-processing steps and configure them to work properly with the types of HTML elements and attributes that converted Markdown might produce, otherwise, you may end up with weird behavior like missing images, broken links, mismatched HTML tags, etc. diff --git a/docs/1.0/upgrading.md b/docs/1.0/upgrading.md new file mode 100644 index 0000000..0fdb79a --- /dev/null +++ b/docs/1.0/upgrading.md @@ -0,0 +1,261 @@ +--- +layout: default +title: Upgrading from 1.5 to 2.0 +description: Guide to upgrading to newer versions of this library +--- + +# Upgrading from 1.5 to 2.0 + +## Minimum PHP Version + +The minimum supported PHP version was increased from 7.1 to 7.2. + +## `CommonMarkConverter` Return Type + +In 1.x, calling `convertToHtml()` would return a `string`. In 2.x this changed to return a `RenderedContentInterface`. To get the resulting HTML, either cast it to a `string` or call `->getContent()`. (This new interface extends from `Stringable` so you can type hint against that instead, if needed.) + +## Method Return Types + +Return types have been added to virtually all class and interface methods. If you implement or extend anything from this library, ensure you also have the proper return types added. + +## Classes/Namespaces Renamed + +Many classes now live in different namespaces, and some have also been renamed. Here's a quick guide showing their new locations: + +_(Note that the base namespace of `League\CommonMark` has been omitted from this table for brevity.)_ + +| Old Class Namespace/Name (1.x) | New Class Namespace/Name (2.0) | +| ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | +| `Util\ConfigurationAwareInterface` | `Configuration\ConfigurationAwareInterface` | +| `Util\ConfigurationInterface` | `Configuration\ConfigurationInterface` | +| `Util\Configuration` | `Configuration\Configuration` | +| `ConfigurableEnvironmentInterface` | `Environment\ConfigurableEnvironmentInterface` | +| `EnvironmentAwareInterface` | `Environment\EnvironmentAwareInterface` | +| `Environment` | `Environment\Environment` | +| `EnvironmentInterface` | `Environment\EnvironmentInterface` | +| `Extension\CommonMarkCoreExtension` | `Extension\CommonMark\CommonMarkCoreExtension` | +| `Delimiter\Processor\EmphasisDelimiterProcessor` | `Extension\CommonMark\Delimiter\Processor\EmphasisDelimiterProcessor` | +| `Block\Element\BlockQuote` | `Extension\CommonMark\Node\Block\BlockQuote` | +| `Block\Element\FencedCode` | `Extension\CommonMark\Node\Block\FencedCode` | +| `Block\Element\Heading` | `Extension\CommonMark\Node\Block\Heading` | +| `Block\Element\HtmlBlock` | `Extension\CommonMark\Node\Block\HtmlBlock` | +| `Block\Element\IndentedCode` | `Extension\CommonMark\Node\Block\IndentedCode` | +| `Block\Element\ListBlock` | `Extension\CommonMark\Node\Block\ListBlock` | +| `Block\Element\ListData` | `Extension\CommonMark\Node\Block\ListData` | +| `Block\Element\ListItem` | `Extension\CommonMark\Node\Block\ListItem` | +| `Block\Element\ThematicBreak` | `Extension\CommonMark\Node\Block\ThematicBreak` | +| `Inline\Element\AbstractWebResource` | `Extension\CommonMark\Node\Inline\AbstractWebResource` | +| `Inline\Element\Code` | `Extension\CommonMark\Node\Inline\Code` | +| `Inline\Element\Emphasis` | `Extension\CommonMark\Node\Inline\Emphasis` | +| `Inline\Element\HtmlInline` | `Extension\CommonMark\Node\Inline\HtmlInline` | +| `Inline\Element\Image` | `Extension\CommonMark\Node\Inline\Image` | +| `Inline\Element\Link` | `Extension\CommonMark\Node\Inline\Link` | +| `Inline\Element\Strong` | `Extension\CommonMark\Node\Inline\Strong` | +| `Block\Parser\BlockQuoteParser` | `Extension\CommonMark\Parser\Block\BlockQuoteParser` | +| `Block\Parser\FencedCodeParser` | `Extension\CommonMark\Parser\Block\FencedCodeParser` | +| `Block\Parser\ATXHeadingParser` and `Block\Parser\SetExtHeadingParser` | `Extension\CommonMark\Parser\Block\HeadingParser` | +| `Block\Parser\HtmlBlockParser` | `Extension\CommonMark\Parser\Block\HtmlBlockParser` | +| `Block\Parser\IndentedCodeParser` | `Extension\CommonMark\Parser\Block\IndentedCodeParser` | +| `Block\Parser\ListParser` | `Extension\CommonMark\Parser\Block\ListParser` | +| `Block\Parser\ThematicBreakParser` | `Extension\CommonMark\Parser\Block\ThematicBreakParser` | +| `Inline\Parser\AutolinkParser` | `Extension\CommonMark\Parser\Inline\AutolinkParser` | +| `Inline\Parser\BacktickParser` | `Extension\CommonMark\Parser\Inline\BacktickParser` | +| `Inline\Parser\BangParser` | `Extension\CommonMark\Parser\Inline\BangParser` | +| `Inline\Parser\CloseBracketParser` | `Extension\CommonMark\Parser\Inline\CloseBracketParser` | +| `Inline\Parser\EntityParser` | `Extension\CommonMark\Parser\Inline\EntityParser` | +| `Inline\Parser\EscapableParser` | `Extension\CommonMark\Parser\Inline\EscapableParser` | +| `Inline\Parser\HtmlInlineParser` | `Extension\CommonMark\Parser\Inline\HtmlInlineParser` | +| `Inline\Parser\OpenBracketParser` | `Extension\CommonMark\Parser\Inline\OpenBracketParser` | +| `Block\Renderer\BlockQuoteRenderer` | `Extension\CommonMark\Renderer\Block\BlockQuoteRenderer` | +| `Block\Renderer\FencedCodeRenderer` | `Extension\CommonMark\Renderer\Block\FencedCodeRenderer` | +| `Block\Renderer\HeadingRenderer` | `Extension\CommonMark\Renderer\Block\HeadingRenderer` | +| `Block\Renderer\HtmlBlockRenderer` | `Extension\CommonMark\Renderer\Block\HtmlBlockRenderer` | +| `Block\Renderer\IndentedCodeRenderer` | `Extension\CommonMark\Renderer\Block\IndentedCodeRenderer` | +| `Block\Renderer\ListBlockRenderer` | `Extension\CommonMark\Renderer\Block\ListBlockRenderer` | +| `Block\Renderer\ListItemRenderer` | `Extension\CommonMark\Renderer\Block\ListItemRenderer` | +| `Block\Renderer\ThematicBreakRenderer` | `Extension\CommonMark\Renderer\Block\ThematicBreakRenderer` | +| `Inline\Renderer\CodeRenderer` | `Extension\CommonMark\Renderer\Inline\CodeRenderer` | +| `Inline\Renderer\EmphasisRenderer` | `Extension\CommonMark\Renderer\Inline\EmphasisRenderer` | +| `Inline\Renderer\HtmlInlineRenderer` | `Extension\CommonMark\Renderer\Inline\HtmlInlineRenderer` | +| `Inline\Renderer\ImageRenderer` | `Extension\CommonMark\Renderer\Inline\ImageRenderer` | +| `Inline\Renderer\LinkRenderer` | `Extension\CommonMark\Renderer\Inline\LinkRenderer` | +| `Inline\Renderer\StrongRenderer` | `Extension\CommonMark\Renderer\Inline\StrongRenderer` | +| `Extension\TableOfContents\TableOfContents` | `Extension\TableOfContents\Node\TableOfContents` | +| `Block\Element\AbstractBlock` | `Node\Block\AbstractBlock` | +| `Block\Element\Document` | `Node\Block\Document` | +| `Block\Element\InlineContainerInterface` | `Node\Block\InlineContainerInterface` | +| `Block\Element\Paragraph` | `Node\Block\Paragraph` | +| `Block\Element\StringContainerInterface` | `Node\StringContainerInterface` | +| `Inline\Element\AbstractInline` | `Node\Inline\AbstractInline` | +| `Inline\Element\AbstractStringContainer` | `Node\Inline\AbstractStringContainer` | +| `Inline\AdjacentTextMerger` | `Node\Inline\AdjacentTextMerger` | +| `Inline\Element\Newline` | `Node\Inline\Newline` | +| `Inline\Element\Text` | `Node\Inline\Text` | +| `Block\Parser\BlockParserInterface` | `Parser\Block\BlockContinueParserInterface` and `Parser\Block\BlockStartParserInterface` | +| `Block\Parser\LazyParagraphParser` | `Parser\Block\ParagraphParser` | +| `Cursor` | `Parser\Cursor` | +| `DocParser` | `Parser\MarkdownParser` | +| `DocParserInterface` | `Parser\MarkdownParserInterface` | +| `Inline\Parser\InlineParserInterface` | `Parser\Inline\InlineParserInterface` | +| `Inline\Parser\NewlineParser` | `Parser\Inline\NewlineParser` | +| `InlineParserContext` | `Parser\InlineParserContext` | +| `InlineParserEngine` | `Parser\InlineParserEngine` | +| `Block\Renderer\DocumentRenderer` | `Renderer\Block\DocumentRenderer` | +| `Block\Renderer\ParagraphRenderer` | `Renderer\Block\ParagraphRenderer` | +| `HtmlRenderer` | `Renderer\HtmlRenderer` | +| `ElementRendererInterface` | `Renderer\HtmlRendererInterface` | +| `Inline\Renderer\NewlineRenderer` | `Renderer\Inline\NewlineRenderer` | +| `Inline\Renderer\TextRenderer` | `Renderer\Inline\TextRenderer` | +| `Block\Renderer\BlockRendererInterface` and `Inline\Renderer\InlineRendererInterface` | `Renderer\NodeRendererInterface` | +| `HtmlElement` | `Util\HtmlElement` | + +## New Block Parsing Approach + +We've completely changed how block parsing works in 2.0. In a nutshell, 1.x had parsing responsibilities split between +the parser and the node. But nodes should be "dumb" and not know anything about how they are parsed - they should only +know the bare minimum needed for rendering. + +As a result, 2.x has delegated the parsing responsibilities to two different interfaces: + +| Responsibility | Old Method (1.x) | New Method (2.0) | +| --------------------------------------------------------- | ------------------------------------------ | -------------------------------------------------------------- | +| Identifying the start of a block | `BlockParserInterface::parse()` | `BlockStartParserInterface::tryStart()` | +| Instantiating and configuring the new block | `BlockParserInterface::parse()` | `BlockContinueParserInterface::__construct()` | +| Determining if the block acts as a container | `AbstractBlock::isContainer()` | `BlockContinueParserInterface::isContainer()` | +| Determining if the block can have lazy continuation lines | `AbstractBlock::isCode()` | `BlockContinueParserInterface::canHaveLazyContinuationLines()` | +| Determining if the block can contain certain child blocks | `AbstractBlock::canContain()` | `BlockContinueParserInterface::canContain()` | +| Determining if the block continues on the next line | `AbstractBlock::matchesNextLine()` | `BlockContinueParserInterface::tryContinue()` | +| Adding the next line to the block | `AbstractBlock::handleRemainingContents()` | `BlockContinueParserInterface::addLine()` | +| Finalizing the block and its contents | `AbstractBlock::finalize()` | `BlockContinueParserInterface::closeBlock()` | + +As a result of making this change, the `addBlockParser()` method on `ConfigurableEnvironmentInterface` has changed to `addBlockStartParser()`. + +See [the block parsing documentation](/2.0/customization/block-parsing/) for more information on this new approach. + +## Rendering Changes + +This library no longer differentiates between block renderers and inline renderers - everything now uses "node renderers" which allow us to have a unified approach to rendering! As a result, the following changes were made, which you may need to change in your custom extensions: + +| Old Method/Interface (1.x) | New Method/Interface (2.0) | +| ------------------------------------------------------- | ------------------------------------------------- | +| `BlockRendererInterface` | `NodeRendererInterface` | +| `InlineRendererInterface` | `NodeRendererInterface` | +| `EnvironmentInterface::getBlockRenderersForClass()` | `EnvironmentInterface::getRenderersForClass()` | +| `EnvironmentInterface::getInlineRenderersForClass()` | `EnvironmentInterface::getRenderersForClass()` | +| `ConfigurableEnvironmentInterface::addBlockRenderer()` | `ConfigurableEnvironmentInterface::addRenderer()` | +| `ConfigurableEnvironmentInterface::addInlineRenderer()` | `ConfigurableEnvironmentInterface::addRenderer()` | +| `ElementRendererInterface::renderBlock()` | `ChildNodeRendererInterface::renderNodes()` | +| `ElementRendererInterface::renderBlocks()` | `ChildNodeRendererInterface::renderNodes()` | +| `ElementRendererInterface::renderInline()` | `ChildNodeRendererInterface::renderNodes()` | +| `ElementRendererInterface::renderInlines()` | `ChildNodeRendererInterface::renderNodes()` | +| `HtmlRenderer::renderBlock($document)` | `HtmlRenderer::renderDocument()` | + +Renderers now implement the unified `NodeRendererInterface` which has a similar (but slightly different) signature from +the old `BlockRendererInterface` and `InlineRendererInterface` interfaces: + +~~~php +/** + * @param Node $node + * @param ChildNodeRendererInterface $childRenderer + * + * @return HtmlElement|string|null + */ +public function render(Node $node, ChildNodeRendererInterface $childRenderer); +~~~ + +The element being rendered is still passed in the first argument, and the object that helps you render children is still +passed in the second argument. Note that blocks are no longer told whether they're being rendered in a tight list - if you +need to know about this, traverse up the `$node` AST yourself and check any `ListBlock` ancestor for tightness. + +## Removed Classes + +The following classes have been removed: + +| Class name in 1.x | Replacement / Notes | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------- | +| `AbstractStringContainerBlock` | Use `extends AbstractBlock implements StringContainerInterface` instead. Note the new method names. | +| `Context` | Use `MarkdownParserState` instead (has different methods but serves a similar purpose) | +| `ContextInterface` | Use `MarkdownParserStateInterface` instead (has different methods but serves a similar purpose) | +| `Converter` | Use `CommonMarkConverter` instead. Note that this has a different constructor but the same methods. | +| `ConverterInterface` | Use `MarkdownConverterInterface`. This interface has the same methods so it should be a drop-in replacement. | +| `UnmatchedBlockCloser` | No longer needed 2.x | + +## `EnvironmentInterface::HTML_INPUT_*` constants moved + +The following constants have been moved: + +| Old Location (1.x) | New Location (2.0) | +| ----------------------------------------- | -------------------- | +| `EnvironmentInterface::HTML_INPUT_ALLOW` | `HtmlFilter::ALLOW` | +| `EnvironmentInterface::HTML_INPUT_ESCAPE` | `HtmlFilter::ESCAPE` | +| `EnvironmentInterface::HTML_INPUT_STRIP` | `HtmlFilter::STRIP` | + +## Renamed Methods + +The following methods have been renamed: + +| Class | Old Name (1.x) | New Name (2.0) | +| -------------------------------------------------- | ------------------ | ----------------------- | +| `Environment` / `ConfigurableEnvironmentInterface` | `addBlockParser()` | `addBlockStartParser()` | +| `ReferenceMap` / `ReferenceMapInterface` | `addReference()` | `add()` | +| `ReferenceMap` / `ReferenceMapInterface` | `getReference()` | `get()` | +| `ReferenceMap` / `ReferenceMapInterface` | `listReferences()` | `getIterator()` | + +## Visibility Changes + +The following properties have had their visibility changed: + +| Property | Was (1.x) | Is Now (2.0) | Notes | +| ---------------------- | --------- | ------------ | ----------------------------------------- | +| `TableCell::$align` | `public` | `private` | Use `getAlign()` and `setAlign()` instead | +| `TableCell::$type` | `public` | `private` | Use `getType()` and `setType()` instead | +| `TableSection::$type` | `public` | `private` | Use `getType()` instead | + +## New approach to the `ReferenceParser` + +The `ReferenceParser` class in 1.x worked on complete paragraphs of text. This has been changed in 2.x to work in a more-gradual fashion, where parsing is done on-the-fly as new lines are added. +Whereas you may have previously called `parse()` on a `Cursor` once on something containing multiple lines, you should now call `parse()` on each line of text and then later call `getReferences()` +to check what has been parsed. + +## `Html5Entities` utility class removed + +Use the `Html5EntityDecoder` utility class instead. + +## `bin/commonmark` command + +This command was buggy to test and was relatively unpopular, so it has been removed. If you need this type of functionality, consider writing your own script with a Converter/Environment configured exactly how you want it. + +## `CommonMarkConverter::VERSION` constant + +This previously-deprecated constant was removed in 2.0 Use `\Composer\InstalledVersions` provided by composer-runtime-api instead. + +## `HeadingPermalinkRenderer::DEFAULT_INNER_CONTENTS` constant + +This previously-deprecated constant was removed in 2.0. Use `HeadingPermalinkRenderer::DEFAULT_SYMBOL` instead. + +## `heading_permalink/inner_contents` configuration option + +This previously-deprecated configuration option was removed in 2.0. Use `heading_permalink/symbol` instead. + +## `ArrayCollection` methods + +Several methods were removed from this class - here are the methods along with possible alternatives you can switch to: + +| Removed Method Name | Alternative | +| ------------------- | ---------------------------------------------------- | +| `add($value)` | `$collection[] = $value` | +| `set($key, $value)` | `$collection[$key] = $value` | +| `get($key)` | `$collection[$key]` | +| `remove($key)` | `unset($collection[$key])` | +| `isEmpty()` | `count($collection) === 0` | +| `contains($value)` | `in_array($value, $collection->toArray(), true)` | +| `indexOf($value)` | `array_search($value, $collection->toArray(), true)` | +| `containsKey($key)` | `isset($collection[$key])` | +| `replaceWith()` | (none provided) | +| `removeGaps()` | (none provided) | + +## Unused methods + +The following unused methods have been removed: + + - `Delimiter::setCanClose()` diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 0000000..1582173 --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +emoji.thephpleague.com diff --git a/docs/Gemfile b/docs/Gemfile new file mode 100644 index 0000000..21fcae2 --- /dev/null +++ b/docs/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' +gem 'jekyll' +gem 'jekyll-github-metadata' +gem 'jekyll-redirect-from' diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock new file mode 100644 index 0000000..408b226 --- /dev/null +++ b/docs/Gemfile.lock @@ -0,0 +1,83 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) + colorator (1.1.0) + concurrent-ruby (1.1.7) + em-websocket (0.5.1) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0.6.0) + eventmachine (1.2.7) + faraday (1.0.1) + multipart-post (>= 1.2, < 3) + ffi (1.13.1) + forwardable-extended (2.6.0) + http_parser.rb (0.6.0) + i18n (1.8.5) + concurrent-ruby (~> 1.0) + jekyll (4.1.1) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (~> 1.0) + jekyll-sass-converter (~> 2.0) + jekyll-watch (~> 2.0) + kramdown (~> 2.1) + kramdown-parser-gfm (~> 1.0) + liquid (~> 4.0) + mercenary (~> 0.4.0) + pathutil (~> 0.9) + rouge (~> 3.0) + safe_yaml (~> 1.0) + terminal-table (~> 1.8) + jekyll-github-metadata (2.13.0) + jekyll (>= 3.4, < 5.0) + octokit (~> 4.0, != 4.4.0) + jekyll-redirect-from (0.16.0) + jekyll (>= 3.3, < 5.0) + jekyll-sass-converter (2.1.0) + sassc (> 2.0.1, < 3.0) + jekyll-watch (2.2.1) + listen (~> 3.0) + kramdown (2.3.0) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.3) + listen (3.2.1) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + mercenary (0.4.0) + multipart-post (2.1.1) + octokit (4.18.0) + faraday (>= 0.9) + sawyer (~> 0.8.0, >= 0.5.3) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (4.0.5) + rb-fsevent (0.10.4) + rb-inotify (0.10.1) + ffi (~> 1.0) + rexml (3.2.4) + rouge (3.22.0) + safe_yaml (1.0.5) + sassc (2.4.0) + ffi (~> 1.9) + sawyer (0.8.2) + addressable (>= 2.3.5) + faraday (> 0.8, < 2.0) + terminal-table (1.8.0) + unicode-display_width (~> 1.1, >= 1.1.1) + unicode-display_width (1.7.0) + +PLATFORMS + ruby + +DEPENDENCIES + jekyll + jekyll-github-metadata + jekyll-redirect-from + +BUNDLED WITH + 2.1.4 diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..673187d --- /dev/null +++ b/docs/README.md @@ -0,0 +1,5 @@ +# Don't commit to this branch! + +This branch is automatically generated by Jekyll via Github Actions. + +To make changes, please go back to the `latest` branch and make changes within the `docs` folder. diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000..58cb8d7 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,6 @@ +--- +repository: unicorn-fail/emoji +permalink: pretty +plugins: + - jekyll-github-metadata + - jekyll-redirect-from diff --git a/docs/_data/images.yml b/docs/_data/images.yml new file mode 100644 index 0000000..6220c2b --- /dev/null +++ b/docs/_data/images.yml @@ -0,0 +1,9 @@ +# Path to project specific favicon.ico, leave blank to use default +favicon: + +# Path to project specific apple-touch-icon-precomposed.png, leave blank to use default +apple_touch: + +# Path to project logo +logo: + diff --git a/docs/_data/menu.yml b/docs/_data/menu.yml new file mode 100644 index 0000000..32b02cc --- /dev/null +++ b/docs/_data/menu.yml @@ -0,0 +1,14 @@ +version: + '1.0': + Getting Started: + 'Overview': '/1.0/' + 'Installation': '/1.0/installation/' + 'Changelog': '/1.0/changelog/' + Usage: + 'Basic Usage': '/1.0/basic-usage/' + 'Configuration': '/1.0/configuration/' + 'Security': '/1.0/security/' +upgrading: + Upgrading Guide: + Release Notes: '/releases/' +# From 1.x to 2.0: '/2.0/upgrading' diff --git a/docs/_data/project.yml b/docs/_data/project.yml new file mode 100644 index 0000000..8838f37 --- /dev/null +++ b/docs/_data/project.yml @@ -0,0 +1,29 @@ +title: Emoji +tagline: Emoji done right +description: Comprehensive PHP parser of emoticons, HTML entities, shortcodes and unicodes (emojis). +site_title: Emoji for PHP +google_analytics_tracking_id: #UA-137970568-1 +repository: emoji +default_version: '1.0' +releases: + next: + '1.1': + documentation_link: '/1.1/' + current: + '1.0': + documentation_link: '/1.0/' + previous: +# '1.0': +# documentation_link: '/1.0/' +author: + name: Mark Carver + twitter_account: _markcarver + website: https://github.com/markcarver +highlights: + description: "The PHP Emoji parser is a robust, based on the specification compliant Emojibase project." + features: + - The only PHP library fully compatible with the Emojibase and CLDR specs + - Feature 2 + - Feature 3 + - Easy-to-use API +composer: "$ composer require unicorn-fail/emoji" diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html new file mode 100644 index 0000000..a2926ed --- /dev/null +++ b/docs/_layouts/default.html @@ -0,0 +1,188 @@ +{% assign version = page.url | remove_first: "/" | split: "/" | first %} +{% assign upgrading = false %} +{% if version == '' or version == 'releases' %} + {% assign version = site.data.project.default_version %} + {% assign upgrading = true %} +{% endif %} +{% capture version_type %}{{ version|get_version_type }}{% endcapture %} +{% capture version_home %}/{{ version }}/{% endcapture %} + + + + + + + {% if page.description %} + + {% else if site.data.project.description %} + + {% endif %} + + {% if page.url == '/' %} + {{ site.data.project.site_title }} - {{ site.data.project.tagline }} + {% else %} + {{ page.title }} - {{ site.data.project.site_title }} + {% endif %} + + + + + + + {% if page.url == '/' %} + + {% else %} + + {% endif %} + {% if page.description %} + + {% else %} + + {% endif %} + + + + + + + + + + + +
+
+

+ +

+ + +
+
+ + + + +
+ +
+

Versions

+ +
+ + {% if upgrading == false %} + {% for section in site.data.menu.version[version] %} + + {% endfor %} + {% else %} + {% for section in site.data.menu.upgrading %} +

{{ section[0] }}

+
    + {% for link in section[1] %} +
  • + {{ link[0] }} +
  • + {% endfor %} +
+ {% endfor %} + {% endif %} +
+
+ {% if version_type == 'next' %} +

This is the documentation for the upcoming version {{ version }}. This is a work in progress

+ {% endif %} + + {% if version_type == 'previous' %} +

This is the documentation for version {{ version }}. Please consider upgrading your code to the latest stable version

+ {% endif %} + + {% if version_type == 'legacy' %} +

This is the documentation for the unsupported version {{ version }}. Please consider upgrading your code to the latest stable version

+ {% endif %} + + {{ content }} +
+ + +
+ + + + + + + + diff --git a/docs/_layouts/homepage.html b/docs/_layouts/homepage.html new file mode 100644 index 0000000..1784b19 --- /dev/null +++ b/docs/_layouts/homepage.html @@ -0,0 +1,176 @@ + + + + + + + + + + {{ site.data.project.site_title }} - {{ site.data.project.tagline }} + + + + + + + + + + + + + + + + + + +
+
+

{{ site.data.project.title }}

+

{{ site.data.project.tagline }}

+

{{ site.data.project.composer }}

+ +

{{ site.data.project.support }}

+
+
+ +
+
+ Author + Latest Version + Total Downloads + Software License + Build Status + Coverage Status + Quality Score +
+
+
+
+

Highlights

+
+

{{ site.data.project.highlights.description }}

+
+
+
+
    + {% for feature in site.data.project.highlights.features %} +
  1. {{ feature }}

  2. + {% endfor %} +
+
+
+
+ +
+
+

Used By

+ +
+
+ +
+
+{{ content }} +
+
+ +
+
+

Sponsors

+

We'd like to extend our sincere thanks the following sponsors who support ongoing development of this project:

+ +

+ Are you interested in sponsoring development of this project?
+ See https://www.colinodell.com/sponsor for a list of ways to contribute! +

+
+
+ + + + +
+ + + + + + diff --git a/docs/_layouts/redirect.html b/docs/_layouts/redirect.html new file mode 100644 index 0000000..8d34339 --- /dev/null +++ b/docs/_layouts/redirect.html @@ -0,0 +1,51 @@ + + + + + + + + + + {{ site.data.project.site_title }} - {{ site.data.project.tagline }} + + + + + + + + + + +
+
+

{{ site.data.project.title }}

+

{{ site.data.project.tagline }}

+

{{ site.data.project.composer }}

+
+
+ +
+
+
+

Redirecting…

+
+ Click here if you are not redirected. + +
+
+
+
+ + + + diff --git a/docs/_plugins/versions.rb b/docs/_plugins/versions.rb new file mode 100644 index 0000000..e43a7d6 --- /dev/null +++ b/docs/_plugins/versions.rb @@ -0,0 +1,44 @@ +module Jekyll + module VersionFilter + def get_version_type(version) + releases = @context.registers[:site].data['project']['releases'] + + releases.each do |type, versions| + return type if versions.has_key?(version) + end + + return nil + end + + def get_documentation_link(v) + releases = @context.registers[:site].data['project']['releases'] + + releases.each do |type, versions| + versions.each do |version, info| + return info['documentation_link'] if version == v + end + end + + return nil + end + + def get_version_link(targetVersion, page) + defaultUrl = '/' + targetVersion + '/' + + menuByVersion = @context.registers[:site].data['menu']['version'] + return defaultUrl if not menuByVersion.has_key?(targetVersion) + + expectedUrl = page.gsub(/^\/[\d\.]+\//, defaultUrl) + + menuByVersion[targetVersion].each do |section, pages| + pages.each do |title, url| + return url if url == expectedUrl + end + end + + return defaultUrl + end + end +end + +Liquid::Template.register_filter(Jekyll::VersionFilter) diff --git a/docs/custom.css b/docs/custom.css new file mode 100644 index 0000000..0209030 --- /dev/null +++ b/docs/custom.css @@ -0,0 +1,385 @@ +html { + background:#f2f7fc; +} + +body { + min-width: 460px; +} + +blockquote { + border-left: 4px solid #ccc; + font-style:italic; + box-sizing: border-box; + padding:0 10px; +} + +header { + position:fixed; + height:4.5em; + z-index: 1; + border-bottom:1px solid #cfe4f9; + max-width: none; + width: 100%; + padding:0; + margin:0; + background:#fff; +} + +header .header-content:after { + content: ""; + display: table; + clear: both; +} + +header .title { + float: left; + text-align:left; + font-family: "Museo 100", sans-serif; + font-weight: bold; + margin:0; + padding:0; + width:400px; +} + +header .title a { + color:#ff4143; + text-decoration: none; +} + +header .search { + float:left; + text-align:right; + width:calc(100% - 480px); + padding-right:.3em; +} + +.banner { + max-width: 100%; +} + +#doc-search { + font-family: "Museo Sans 500", sans-serif; + font-weight: normal; + font-size: 16px; + border:1px solid #e8e8e8; + background-color:#f4f4f4; + padding:.5em 1em; + margin-left:.3em; + border-radius: .3em; +} + +header .versions { + float:left; + display:none; + font-family: "Museo Sans 500", sans-serif; + font-weight: normal; +} + +header .versions h2 { + font-family: "Museo Sans 500", sans-serif; + font-weight: normal; + font-size: 16px; + background:#1672ce; + color:#fff; + margin:0; + width: 75px; + text-align: center; + border-radius: .3em; + margin-bottom:.4em; + padding:.5em .3em; + cursor: pointer; +} + +header .versions ul { + display:none; + margin:0; + padding:0; + list-style:none; + width: 75px; +} + +header .versions .show { + display:block; +} + +header .versions li { + margin:0; + padding:0; + text-align: center; +} + +header .versions a { + display:block; + margin:0; + padding:.5em .3em; + text-decoration:none; + color:#1672ce; + background: #fff; + border:solid #c7c7c7; + border-width:0 1px 1px; +} + +header .versions a:hover { + background:#f1f1f1; +} + +header .versions li:first-of-type a { + border-top-width: 1px; + border-radius:.3em .3em 0 0; +} + +header .versions li:last-of-type a { + border-radius:0 0 .3em .3em; +} + +label[for=menu] { + position:fixed; + z-index: 2; + top:20px; + right:0; + display:inline-block; + box-sizing: border-box; + background:transparent; + color:#1672ce; + width:50px; + font-size:30px; + line-height: 1; + padding:0; + margin:0; +} + +label[for=menu]:hover { + background:transparent; + color:#1672ce; +} + +main { + padding-top:4em; + background:none; +} + +/* ---------- header automatic permalink -----------*/ + +.header-permalink { + text-decoration: none; + color:transparent; + font-size:.8em; + vertical-align: super; +} + +.header-permalink:hover, +h1:hover .header-permalink, +h2:hover .header-permalink, +h3:hover .header-permalink, +h4:hover .header-permalink, +h5:hover .header-permalink { + text-decoration: none; + color:#777; +} + +h4 { + font-variant: small-caps; + font-size:1em; +} + +main article p code, +main article li code, +main article div > code { + font-family: Consolas,Monaco,'Andale Mono',monospace; + font-size: 17px; + line-height: 100%; + color:#1672ce; + background: #fff; + border:none; +} + +main article p img { + box-sizing: border-box; + margin:.3em; + padding:0; + display: block; +} + +main article p a img { + box-sizing: border-box; + margin:0; + padding:0; + display:inline; +} + +footer { + border-top:1px solid #cfe4f9; + background:#fff; + max-width: none; + text-align:center; + color:#a1a1a1; +} + +footer span a { + color:#007ec6; +} + +main menu .menu-section { + border-bottom:1px dashed #cfe4f9; + padding-bottom:1em; +} + +main menu .menu-section:last-of-type { + border-bottom:none; +} + +main menu h2 { + margin-top:1.5em; + padding-left:.7em; + color:#2b3d50; + font-size:1em; + font-weight: bold; + text-transform: none; + box-shadow: none; +} + +main menu ul li a { + border-radius:.1em; + font-size:1em; + margin:.2em; + padding:.6em; + color:#1672ce; +} + +main menu ul li a:hover { + color:#1672ce; + padding:.6em; + background:transparent; + text-decoration: underline; +} + +main menu ul li.selected { + background: none; +} + +main menu ul li.selected a { + color:#fff; + background:#1672ce; + padding:.6em; +} + +main menu ul li.selected a:hover { + text-decoration: none; +} + +pre { + border-width:0 0 0 4px; + background: #fff; + width: fit-content; + max-width: 100%; +} + +main article table { + width: initial; + max-width: 100%; +} + +table { + border:1px solid #eee; + background: #fff; + box-shadow:0 6px 6px 0 rgba(80, 88, 94, .24); +} + +table th { + color:#fff; + background: #1672ce; +} + + +header .logo .name { + font-size: 2rem; + line-height: 100%; + margin: 0 !important; +} + +@media screen and (min-width: 768px) { + header .logo .name { + font-size: 2.5rem; + } +} + +@media screen and (min-width: 1024px) { + header .logo .name { + font-size: 3rem; + } +} + +header .logo em { + color: #777; + font-style: normal; +} + +@media screen and (max-width: 549px) { + header { + padding: 20px 0 25px 10px; + } + + menu { + text-align: center; + } + + header .logo { + text-align: left; + } +} + +@media screen and (min-width: 550px) { + header { + background:#fff; + } + + header .header-content { + box-sizing: border-box; + padding:1em; + } + + header .versions { + display: block; + } + + label[for=menu] { + display:none; + } + + main { + background: none; + } + + main menu { + border-right: 1px dashed #cfe4f9; + } + + main menu .versions-small { + display:none; + } + + main article p, + main article li { + font-size:.9em; + } +} + +@media screen and (max-width: 750px) { + #doc-search { + display: none; + } +} + +@media screen and (min-width: 850px) { + main article { + max-width: none; + } +} + +h2 code { + font-size: 0.8em; +} + +.features ul { + list-style-type: none; +} diff --git a/docs/custom.js b/docs/custom.js new file mode 100644 index 0000000..a84d855 --- /dev/null +++ b/docs/custom.js @@ -0,0 +1,18 @@ +(() => { + + const uri = new URL(location.href); + + document.querySelector('header nav h2').addEventListener('click', function () { + this.parentNode.querySelector('ul').classList.toggle('show'); + }, false); + + document.querySelectorAll("main h2[id]").forEach((header) => { + uri.hash = header.id; + let link = document.createElement("a"); + link.className = "header-permalink"; + link.title = "Permalink"; + link.href = uri.toString(); + link.innerHTML = "¶"; + header.appendChild(link); + }); +})(); \ No newline at end of file diff --git a/docs/homepage.css b/docs/homepage.css new file mode 100644 index 0000000..8e32775 --- /dev/null +++ b/docs/homepage.css @@ -0,0 +1,380 @@ +blockquote { + border-left: 4px solid #ccc; + font-style:italic; + box-sizing: border-box; + padding:0 10px; +} + +footer { + text-align: center; + color:#fff; +} + +pre { + border-width:0 0 0 4px; + background: #fff; +} + +main p code, +main li code, +main div > code { + font-family: Consolas,Monaco,'Andale Mono',monospace; + font-size: 17px; + line-height: 100%; + color:#1672ce; + background: #fff; + border:none; +} +/* -------- homepage css -----------------*/ + +.homepage header { + margin:0 auto; + padding:0 0 3em; + box-sizing: border-box; + background:#19242F url(//thephpleague.com/img/header_bg.png) no-repeat top center; + background-size: cover; + max-width: none; + color:#fff; + font-family: "Museo 300", sans-serif; +} + +.homepage header h1 { + margin:.3em auto; + font-family: "Museo 300", sans-serif; + line-height: 250%; + font-weight: normal; +} + +.homepage header h2 { + margin:0 auto; + font-family: "Museo 300", sans-serif; + color:#ff4043; + font-size:36px; + line-height:1.33; + font-weight:normal; +} + +.homepage .badge-list { + background: #fff; + padding: 3em 0 0 0; + text-align: center; +} + +.homepage .composer span { + padding:.3em 1em; + background-color:rgba(0, 0, 0, .3); + color:#fff; + font-size:.9rem; + font-family: Consolas, Monaco ,'Andale Mono', monospace; + line-height: 140%; + text-align: left; + white-space: pre; + word-wrap: normal; + word-spacing: normal; + hyphens: none; + display:inline-block; + border-radius: .3em; +} + +.homepage .hot-links { + margin:0 auto; + padding:0; + list-style:none; + width:300px; + display:flex; + align-content: top; + align-items: center; +} + +.homepage .hot-links li { + padding:0; + margin:0; +} + +.homepage .hot-links a { + display:block; + margin:0; + padding:1em; + width:150px; + border-radius:2px 0 0 2px; + text-decoration:none; + text-align:center; + font-weight:bold; + background:#fff; + color:#ff4043; +} + +.homepage .hot-links :last-child a { + border-radius:0 2px 2px 0; + background:#ff4043; + color:#fff; +} + +.homepage .hot-links:hover :last-child a { + color:#ff4043; +} + +.homepage .hot-links:hover a { + background:#fff; + color:#ff4043; +} + +.homepage .hot-links:hover a:hover { + background: #ff4043; + color: #fff; +} + +.homepage main { + color: #2b3d50; + font-family: "Museo 300", sans-serif; + line-height: 160%; + font-weight: normal; + background:#19242f; + width:auto; + right:auto; +} + +.homepage main > div { + margin:0 auto; + padding:3em 0; + box-sizing: border-box; +} + +.inner-content { + margin:0 auto; + padding:1em; + box-sizing: border-box; + text-align:center; +} + +.inner-content h1 { + color:#fff; + font-size:50px; + line-height:100%; + font-weight:normal; + font-family:"Museo Sans 300", sans-serif; + text-transform:uppercase; + margin:0; +} + +.inner-content:after { + content: ''; + display:table; + clear:both; +} + +.projects, +.sponsors { + color: #fff; +} + +.projects h2, +.sponsors h2 { + font-size:50px; + line-height:100%; + font-weight:normal; + font-family:"Museo Sans 300", sans-serif; + text-transform:uppercase; + margin: 0 0 1em 0; +} + +.project-logos { + display: flex; + flex-wrap: wrap; + align-items: center; + justify-content: center; +} + +.project-logos a { + display: block; + object-fit: contain; + margin: 0 16px; +} + +.project-logos img { + height: 70px; + max-width: 180px; +} + +.sponsors a { + color: #3399ff; +} +.sponsors ul { + list-style: none; + font-size: 1.1em; +} + +.features { + background: #F2F7FC; + border-bottom:1px solid #CFE4F9; + color:#666; + line-height: 1.5; + font-weight: normal; + font-variant: normal; + font-style: normal; + font-size: 18px; + font-family: "Museo 300", sans-serif; +} + +.features h1 { + color:#6abcdd; +} + +.features h2 { + color:#6abcdd; + font-weight: normal; +} + +.features p { + text-align: center; +} + +.features a { + color:#6abcdd; +} + +.highlights { + background:#fff; + border-bottom:1px solid #CFE4F9; +} + +.highlights .description { + color:#666; + line-height: 1.5; + font-weight: normal; + font-variant: normal; + font-style: normal; + font-size: 18px; + font-family: "Museo 300", sans-serif; + text-align: left; +} + +.highlights h1 { + color:#ff4043; + font-size: 36px; + line-height:115%; +} + +.highlights ol { + margin:0; + text-align:left; +} + +.highlights li { + margin:0 0 15px 0; + color:#666; + font-size:16px; + font-weight:bold; +} + +.highlights li p { + margin:0; + line-height: 1.4; + font-weight: normal; + font-variant: normal; + font-style: normal; + font-size: 18px; + font-family: "Museo 300", sans-serif; + color:#ff4043; +} + +.highlights a { + color:#ff4043; +} + +.questions { + padding:0; + background:#fff; + color:#666; + border-bottom:1px solid #CFE4F9; +} + +.questions h1 { + font-size:36px; + color:#ff4043; +} + +.questions a { + color:#6abcdd; +} + +.questions a:hover { + text-decoration: none; +} + +@media screen and (max-width: 549px) { + .homepage header h1 { + font-size:48px; + } + + .homepage .composer span { + font-size:1rem; + } +} + +@media screen and (min-width: 549px) { + .homepage header h1 { + margin:0 auto; + font-size:54px; + } + + .inner-content { + max-width:1000px; + } + + .homepage main { + width:initial; + right:initial; + } + + .highlights h1 { + font-size: 50px; + } + + .highlights li { + font-size:24px; + } + + .highlights li p { + font-size:20px; + } + + .highlights .column { + float:left; + width:45%; + } + + .highlights .one { + margin:0 10% 0 0; + } + + .documentation h1 { + font-size:50px; + } +} + +@media screen and (min-width:700px) { + .documentation .version { + float:left; + width:42%; + margin:2%; + max-width:289px; + } +} + +@media screen and (min-width: 910px) { + .documentation .version { + float:left; + width:30%; + margin:1%; + } + + .homepage header h1 { + margin:0 auto; + font-size:96px; + } +} + +#sponsors + p + ul { + list-style-type: none; +} diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..cdb0f79 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,44 @@ +--- +layout: homepage +--- + +{% assign version = site.data.project.default_version %} + +# Features + +## Easy Usage + +```php +use League\CommonMark\CommonMarkConverter; + +$converter = new CommonMarkConverter(); +echo $converter->convertToHtml('# Hello World!'); + +//

Hello World!

+``` + +## Security + +All CommonMark features are supported by default, including raw HTML and unsafe links, which you may want to disable using the `html_input` and `allow_unsafe_links` options: + +```php +use League\CommonMark\CommonMarkConverter; + +$converter = new CommonMarkConverter(['html_input' => 'escape', 'allow_unsafe_links' => false]); +echo $converter->convertToHtml('# Hello World!'); + +//

Hello World!

+``` + +## Included Extensions + +This project includes [several built-in extensions you can use](/{{ version }}/extensions/overview/) to enable additional features and syntax. + +## Customization + +This library allows you to add custom syntax, renderers, and more. Check out the [Customization](/{{ version }}/customization/overview/) section for more information. + +## Community Integrations & Extensions + +An updated list of pre-built integrations and extensions can be found in the [Related Packages](https://github.com/thephpleague/commonmark#%EF%B8%8F-related-packages) section of the `README`. + diff --git a/docs/releases.md b/docs/releases.md new file mode 100644 index 0000000..f324111 --- /dev/null +++ b/docs/releases.md @@ -0,0 +1,16 @@ +--- +layout: default +title: Release Notes +redirect_from: + - /changelog/ + - /upgrading/ + - /upgrading/changelog/ +--- + +# Release Notes + +{% assign releases = site.github.releases %} +{% for release in releases %} +## {{ release.name }} - {{ release.published_at | date: "%Y-%m-%d" }} +{{ release.body | replace:'```', '~~~' | markdownify }} +{% endfor %} diff --git a/docs/support.css b/docs/support.css new file mode 100644 index 0000000..8ceee51 --- /dev/null +++ b/docs/support.css @@ -0,0 +1,131 @@ +.support-banner-wrapper { + position: fixed; + bottom: 0; + left: 0; + right: 0; + margin: 1rem; +} + +.support-banner { + color: #fff; + background-color: #000; + box-shadow: 0 10px 15px -3px rgba(0,0,0,.1), 0 4px 6px -2px rgba(0,0,0,.05); + border-radius: 0.5rem; + + padding: 0.5rem 1rem; + margin: 0 auto; + width: 100%; + + justify-content: space-between; + -webkit-box-pack: justify; + + align-items: center; + -webkit-box-align: center; + + display: flex; + flex-wrap: wrap; + flex-direction: row; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + + z-index: 100; +} + +@media screen and (min-width: 1200px) { + .support-banner { + max-width: 1192px; + } +} + +.support-banner-left { + width: 0; + margin: 0; + + flex: 1 1 0%; + -webkit-box-flex: 1; +} + +.support-banner-right { + display: flex; + flex-shrink: 0; + width: auto; + margin-top: 0; + + order: 2; + -webkit-box-ordinal-group: 3; + + justify-content: space-between; + -webkit-box-pack: justify; + + align-items: center; + -webkit-box-align: center; +} + +.support-button { + width: auto; + padding: .5rem 1rem; + margin-right: .25rem; + text-align: center; + display: block; + border-radius: .25rem; + color: inherit; + text-decoration: inherit; +} + +.support-button-sponsor { + background-color: #d53f8c; +} + +.support-button-donate { + background-color: #38a169; +} + +.support-banner-close { + width: 1.5rem; + margin: 0 0 0 0.5rem; + font-size: .875rem; + height: 1.5rem; + + border: none; + border-radius: 9999px; + padding: 0; + line-height: inherit; + color: inherit; + cursor: pointer; + background-color: transparent; + background-image: none; + -webkit-appearance: button; + + overflow: visible; + text-transform: none; + + display: flex; + + justify-content: center; + -webkit-box-pack: center; + + align-items: center; + -webkit-box-align: center; + + order: 3; + -webkit-box-ordinal-group: 4; +} + +.hidden { + display: none; +} + +@media (min-width: 700px) { + .sm\:inline-block { + display: inline-block; + } +} + +@media (min-width: 1060px) { + .lg\:hidden { + display: none; + } + .lg\:inline-block { + display: inline-block; + } +}