Skip to content

Commit

Permalink
Merge pull request #384 from thephpleague/docs
Browse files Browse the repository at this point in the history
More documentation improvements
  • Loading branch information
colinodell committed Oct 4, 2019
2 parents 4839e9f + 408f369 commit 80b0315
Show file tree
Hide file tree
Showing 10 changed files with 103 additions and 34 deletions.
2 changes: 2 additions & 0 deletions RELEASE_CHECKLIST.md
Expand Up @@ -22,5 +22,7 @@
- [ ] Create a signed tag locally and push it up. Tag should be named `xx.yy.zz`.
- [ ] Go to Github and add release notes from the relevant `CHANGELOG` section.
- [ ] Bump constraints in league/commonmark-extras (and other official extensions) and tag a new release of them
- [ ] Resync project on <https://libraries.io/packagist/league%2Fcommonmark/>
- [ ] Update release notes and supported branches on Tidelift
- [ ] ???
- [ ] PROFIT!!
8 changes: 5 additions & 3 deletions docs/1.0/basic-usage.md
Expand Up @@ -24,13 +24,13 @@ echo $converter->convertToHtml('# Hello World!');
<i class="fa fa-exclamation-triangle"></i>
**Important:** See the [security](/1.0/security/) section for important details on avoiding security misconfigurations.

The actual conversion process requires three steps:
The actual conversion process has three steps:

1. Create an `Environment`, adding whichever extensions/parser/renders you need
1. Creating an `Environment`, adding whichever extensions/parser/renders you need
2. Parsing the Markdown input into an AST
3. Rendering the AST document as HTML

You can do this yourself if you wish:
`CommonMarkConverter` handles this for you, but you can execute that process yourself if you wish:

~~~php
<?php
Expand All @@ -53,4 +53,6 @@ echo $htmlRenderer->renderBlock($document);

[Additional customization](/1.0/customization/overview/) is also possible.

## 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.
11 changes: 9 additions & 2 deletions docs/1.0/customization/block-parsing.md
Expand Up @@ -12,7 +12,13 @@ Block parsers should implement `BlockParserInterface` and implement the followin

## parse()

When parsing a new line, the `DocParser` iterates through all registered block parsers and calls their `parse()` method. Each parser must determine whether it can handle the given line; if so, it should parse the given block and return true.
~~~php
<?php

public function parse(ContextInterface $context, Cursor $cursor): bool;
~~~

When parsing a new line, the `DocParser` iterates through all registered block parsers and calls their `parse()` method. Each parser must determine whether it can handle the given line; if so, it should parse the given block and return `true`.

### Parameters

Expand All @@ -31,6 +37,7 @@ Returning `true` tells the engine that you've successfully parsed the block at t
## Tips

* For best performance, `return false` as soon as possible
* Your `parse()` method may be called thousands of times so be sure your code is optimized

## Block Elements

Expand All @@ -43,7 +50,7 @@ Block elements also play a role during the parsing process as they tell the unde
| Method | Purpose |
| ------------------------- | ----------------------------------------------------------------------------------------------------- |
| `canContain(...)` | Tell the engine whether a subsequent block can be added as a child of yours |
| `isCode()` | Returns whether this block represents `<code>` |
| `isCode()` | Returns whether this block represents an extra-greedy `<code>` block |
| `matchesNextLine(...)` | Returns whether this block continues onto the next line (some blocks are multi-line) |
| `shouldLastLineBeBlank()` | Returns whether the last line should be blank (primarily used by `ListItem` elements) |
| `finalize(...)` | Finalizes the block after all child items have been added, thus marking it as closed for modification |
Expand Down
23 changes: 21 additions & 2 deletions docs/1.0/customization/block-rendering.md
Expand Up @@ -14,6 +14,12 @@ All block renderers should implement `BlockRendererInterface` and its `render()`

## render()

~~~php
<?php

public function render(AbstractBlock $block, ElementRendererInterface $htmlRenderer, bool $inTightList = false);
~~~

The `HtmlRenderer` will call this method whenever a supported block element is encountered in the AST being rendered.

If the method can only handle certain block types, be sure to verify that you've been passed the correct type.
Expand All @@ -28,11 +34,24 @@ If the method can only handle certain block types, be sure to verify that you've

The method must return the final HTML representation of the block and any of its contents. This can be an `HtmlElement` object (preferred; castable to a string), a string of raw HTML, or `null` if it could not render (and perhaps another renderer should give it a try).

You are responsible for handling any escaping that may be necessary.
If you choose to return an HTML `string` you are responsible for handling any escaping that may be necessary.

#### `HtmlElement`

Instead of manually building the HTML output yourself, you can leverage the `HtmlElement` to generate that for you. For example:

~~~php
<?php

use League\CommonMark\HtmlElement;

$link = new HtmlElement('a', ['href' => 'https://github.com'], 'GitHub');
$img = new HtmlElement('img', ['src' => 'logo.jpg'], '', true);
~~~

## Designating Block Renderers

When registering your render, you must tell the `Environment` which block element class your renderer should handle. For example:
When registering your renderer, you must tell the `Environment` which block element class your renderer should handle. For example:

~~~php
<?php
Expand Down
7 changes: 4 additions & 3 deletions docs/1.0/customization/cursor.md
Expand Up @@ -8,23 +8,23 @@ redirect_from: /0.20/customization/cursor/
Cursor
======

At it's core, a `Cursor` is just a fancy string that remembers your current position as you parse it It contains a set of highly-optimized methods making it easy to parse characters, match regular expressions, and more.
A `Cursor` is essentially a fancy string wrapper that remembers your current position as you parse it. It contains a set of highly-optimized methods making it easy to parse characters, match regular expressions, and more.

## Supported Encodings

As of now, only UTF-8 (and, by extension, ASCII) encoding is supported.

## Usage

Instantiating a new `Cursor` is as simple as this:
Instantiating a new `Cursor` is as simple as:

```php
use League\CommonMark\Cursor;

$cursor = new Cursor('Hello World!');
```

Or, if you're creating a custom [block parser](/1.0/customization/block-parsing/) or [inline renderer](/0.20/customization/inline-parsing/), a pre-configured `Cursor` will be provided to you with (with the `Cursor` already set to the current `position` trying to be parsed).
Or, if you're creating a custom [block parser](/1.0/customization/block-parsing/) or [inline parser](/1.0/customization/inline-parsing/), a pre-configured `Cursor` will be provided to you with (with the `Cursor` already set to the current `position` trying to be parsed).

## Methods

Expand All @@ -42,6 +42,7 @@ You can then call any of the following methods to parse the string within that `
| `peek(int $offset)` | Returns the character `$offset` chars away without changing the current `position` of the cursor |
| `getNextNonSpacePosition()` | Returns the position of the next character which is not a space or tab |
| `getNextNonSpaceCharacter()` | Returns the next character which isn't a space (or tab) |
| `advance()` | Moves the cursor forward by 1 character |
| `advanceBy(int $characters)` | Moves the cursor forward by `$characters` characters |
| `advanceBy(int $characters, true)` | Moves the cursor forward by `$characters` characters, handling tabs as columns |
| `advanceBySpaceOrTab()` | Advances forward one character (and returns `true`) if it's a space or tab; returns false otherwise |
Expand Down
63 changes: 47 additions & 16 deletions docs/1.0/customization/environment.md
Expand Up @@ -8,7 +8,7 @@ redirect_from: /0.20/customization/environment/
The Environment
===============

All parsers, renderers, etc. must be registered with the `Environment` class so that the library is aware of them.
The `Environment` contains all of the parsers, renderers, configurations, etc. that the library uses during the conversion process. You therefore must register all parsers, renderers, etc. with the `Environment` so that the library is aware of them.

A pre-configured `Environment` can be obtained like this:

Expand All @@ -20,10 +20,39 @@ use League\CommonMark;
$environment = Environment::createCommonMarkEnvironment();
~~~

All of the core renders, parsers, etc. will be pre-registered and ready to go.
All of the core renders, parsers, etc. needed to implement the CommonMark spec will be pre-registered and ready to go.

You can customize this default `Environment` (or even a new, empty one) using any of the methods below (from the `ConfigurableEnvironmentInterface` interface).
(These are the same methods used by `Environment::createCommonMarkEnvironment()` to register the standard functionality.)

## mergeConfig()

~~~php
<?php

public function mergeConfig(array $config = []);
~~~

Merges the given [configuration](/1.0/configuration/) settings into any existing ones.

## setConfig()

~~~php
<?php

public function setConfig(array $config = []);
~~~

Completely replaces the previous [configuration](/1.0/configuration/) settings with the new `$config` you provide.

## addExtension()

~~~php
<?php

public function addExtension(ExtensionInterface $extension);
~~~

Registers the given [extension](/1.0/customization/extensions/) with the environment. This is typically how you'd integrate third-party extensions with this library.

## addBlockParser()

Expand Down Expand Up @@ -61,41 +90,43 @@ Registers the given `InlineParserInterface` with the environment with the given

See [Inline Parsing](/1.0/customization/inline-parsing/) for details.

## addInlineProcessor()
## addInlineRenderer()

~~~php
<?php

public function addInlineProcessor(InlineProcessorInterface $processor);
public function addInlineRenderer(string $inlineClass, InlineRendererInterface $renderer, int $priority = 0);
~~~

Registers the given `InlineProcessorInterface` with the environment.
Registers an `InlineRendererInterface` to handle a specific type of inline (`$inlineClass`) with the given priority (a higher number will be executed earlier).
A single renderer can handle multiple inline classes, but you must register it separately for each type. (The same renderer instance can be re-used if desired.)

**TODO:** Add documentation for this.
See [Inline Rendering](/1.0/customization/inline-rendering/) for details.

## addInlineRenderer()
## addDelimiterProcessor()

~~~php
<?php

public function addInlineRenderer(string $inlineClass, InlineRendererInterface $renderer, int $priority = 0);
public function addDelimiterProcessor(DelimiterProcessorInterface $processor);
~~~

Registers an `InlineRendererInterface` to handle a specific type of inline (`$inlineClass`) with the given priority (a higher number will be executed earlier).
A single renderer can handle multiple inline classes, but you must register it separately for each type. (The same renderer instance can be re-used if desired.)
Registers the given `DelimiterProcessorInterface` with the environment.

See [Inline Rendering](/1.0/customization/inline-rendering/) for details.
See [Inline Parsing](/1.0/customization/delimiter-processing/) for details.

## addDocumentProcessor()
## addEventListener()

~~~php
<?php

public function addDocumentProcessor(DocumentProcessorInterface $processor, int $priority = 0);
public function addEventListener(string $eventClass, callable $listener, int $priority = 0);
~~~

Adds a new Document Processor which will [manipulate the AST](/1.0/customization/abstract-syntax-tree/) after parsing the document but before rendering it.
Registers the given event listener with the environment.

See [Event Dispatcher](/1.0/customization/event-dispatcher/) for details.

## Priority

Each of these methods allows you to specify a numeric `$priority`. In cases where multiple things are registered, the internal engine will attempt to use the higher-priority ones first, falling back to lower priority ones if the first one(s) were unable to handle things.
Several of these methods allows you to specify a numeric `$priority`. In cases where multiple things are registered, the internal engine will attempt to use the higher-priority ones first, falling back to lower priority ones if the first one(s) were unable to handle things.
4 changes: 2 additions & 2 deletions docs/1.0/customization/event-dispatcher.md
Expand Up @@ -35,7 +35,7 @@ public function addEventListener(string $eventClass, callable $listener, int $pr
The parameters for this method are:

1. The fully-qualified name of the event class you wish to observe
2. Any PHP callable to execute when that type of event is dispatched
2. Any [PHP callable](https://www.php.net/manual/en/language.types.callable.php) to execute when that type of event is dispatched
3. An optional priority (defaults to `0`)

For example:
Expand Down Expand Up @@ -70,7 +70,7 @@ Listeners may call any method on the event to get more information about the eve

This library supports the following default events which you can register listeners for:

### `DocumentParsedEvent`
### `League\CommonMark\Event\DocumentParsedEvent`

This event is dispatched once all other processing is done. This offers extensions the opportunity to inspect and modify the [Abstract Syntax Tree](/1.0/customization/abstract-syntax-tree/) prior to rendering.

Expand Down
3 changes: 1 addition & 2 deletions docs/1.0/customization/extensions.md
Expand Up @@ -8,7 +8,7 @@ redirect_from: /0.20/customization/extensions/
Extensions
==========

Extensions provide a way to group multiple related parsers, processors, and/or renderers together with pre-defined priorities. They are perfect for distributing your customizations as reusable, open-source packages that others can plug into their own projects!
Extensions provide a way to group related parsers, renderers, etc. together with pre-defined priorities, configuration settings, etc. They are perfect for distributing your customizations as reusable, open-source packages that others can plug into their own projects!

To create an extension, simply create a new class implementing `ExtensionInterface`. This has a single method where you're given a `ConfigurableEnvironmentInterface` to register whatever things you need to. For example:

Expand All @@ -19,7 +19,6 @@ final class EmojiExtension implements ExtensionInterface
{
$environment
->addInlineParser(new EmojiParser(), 20)
->addDocumentProcessor(new ReplaceUnicodeEmojiProcessor(), 0)
->addInlineRenderer(Emoji::class, new EmojiRenderer(), 0)
;
}
Expand Down
8 changes: 4 additions & 4 deletions docs/1.0/customization/overview.md
Expand Up @@ -34,6 +34,10 @@ otherwise you abort and the engine will try other parsers. If no parser succeed

Simple delimiter-based inlines (like emphasis, strikethrough, etc.) can be parsed without needing a dedicated inline parser by leveraging the new [Delimiter Processing](/1.0/customization/delimiter-processing/) functionality.

## AST manipulation

Once the [Abstract Syntax Tree](/1.0/customization/abstract-syntax-tree/) is parsed, you are free to access/manipulate it as needed before it's passed into the rendering engine.

## Customize HTML Output with Custom Renderers

Renders convert the parsed blocks/inlines from the AST representation into HTML. There are two types of renderers:
Expand All @@ -44,10 +48,6 @@ Renders convert the parsed blocks/inlines from the AST representation into HTML.
When registering these with the environment, you must tell it which block/inline classes it should handle. This allows you
to essentially "swap out" built-in renderers with your own.

## AST manipulation

Once the [Abstract Syntax Tree](/1.0/customization/abstract-syntax-tree/) is parsed, you are free to access/manipulate it as needed before it's passed into the rendering engine.

## Examples

Some examples of what's possible:
Expand Down
8 changes: 8 additions & 0 deletions docs/1.0/security.md
Expand Up @@ -8,6 +8,14 @@ redirect_from: /0.20/security/
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.
Expand Down

0 comments on commit 80b0315

Please sign in to comment.