SlideShare a Scribd company logo
1 of 64
CommonMark
Markdown done right
Colin O’Dell
@colinodell
COLIN O’DELL
Creator & Maintainer of league/commonmark
Lead Web Developer at Unleashed Technologies
Author of PHP 7 Migration Guide e-book
@colinodell
TOPICS
Origins of Markdown
CommonMark Spec
league/commonmark Overview
Customizing league/commonmark
ORIGINS OF MARKDOWN
Created in March 2004 by John Gruber
Informal plain-text formatting language
Converts readable text to valid (X)HTML
Primary goal - readability
HISTORY OF MARKDOWN
Hello Nomad PHP!
----------------
Markdown is **awesome**!
1. Foo
2. Bar
3. Baz
Wikipedia entry:
<https://en.wikipedia.org/wiki/Markdown>
WHY IS IT SUCCESSFUL?
1. Syntax is visually-similar to the resulting
markup
2. Non-strict, forgiving parsing
3. Easily adaptable for different uses
67+ DIFFERENT FLAVORS
Source: https://github.com/markdown/markdown.github.com/wiki/Implementations
Actuarius
Blackfriday
BlueCloth
BlueFeather
cebe/markdown
CocoaMarkdown
Discount
ffi-sundown
GHMarkdownParser
Goskirt
Hoedown
Hoep
Knockoff
kramdown
Laika
libpandoc
Lowdown
lua-discount
Lunamark
markdown
markdown-clj
markdown-js
markdown-oo-php
markdown.bash
markdown.lua
markdown.pl
markdown4j
MarkdownDeep
MarkdownJ
MarkdownPapers
MarkdownSharp
marked
Maruku
md2html.awk
Misaka
Mistune
MMMarkdown
MoonShine
MultiMarkdown
node-discount
node-markdown
node-multimarkdown
OMD
Pandoc
Parsedown
Parsedown Extra
peg-markdown
peg-multimarkdown & fork
pegdown
PHP Markdown
PHP Markdown Extra
PHP-Sundown
Python-Discount
python-hoedown
Python-Markdown
Python-Markdown2
RDiscount
Redcarpet
RoboSkirt
Showdown
Sundown
Sundown HS
Sundown.net
text-markdown
texts.js
Txtmark
upskirt.go
https://xkcd.com/927/
COMMONMARK IS…
A strongly defined, highly compatible specification of Markdown.
Written by John MacFarlane
(in collaboration with people from Github, StackOverflow, Reddit, and others)
Spec includes:
 Strict rules (precedence, parsing order, handling edge cases)
 Specific definitions (ex: “whitespace”, “punctuation”)
 616 examples
WHY IS IT NEEDED?
*I love Markdown*
<p><em>I love Markdown</em></p>
WHY IS IT NEEDED?
*I *love* Markdown*
WHY IS IT NEEDED? Source: http://johnmacfarlane.net/babelmark2/
30%
WHY IS IT NEEDED?
*I *love* Markdown*
<p><em>I <em>love</em> Markdown</em></p>
*I *love* Markdown*
<p><em>I </em>love<em> Markdown</em></p>
*I *love* Markdown*
<p><em>I *love</em> Markdown*</p>
15%
33%
Source: http://johnmacfarlane.net/babelmark2/
WHY IS IT NEEDED?
1. > Hello
World!
------
Source: http://johnmacfarlane.net/babelmark2/
WHY IS IT NEEDED?
1. > Hello
World!
------
Source: http://johnmacfarlane.net/babelmark2/
WHY IS IT NEEDED?
1. > Hello
World!
------
Source: http://johnmacfarlane.net/babelmark2/
WHY IS IT NEEDED?
1. > Hello
World!
------
Source: http://johnmacfarlane.net/babelmark2/
WHY IS IT NEEDED?
1. > Hello
World!
------
Source: http://johnmacfarlane.net/babelmark2/
LEAGUE/COMMONMARK
A well-written, super-configurable
Markdown parser for PHP based on the
CommonMark spec.
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
ADDING LEAGUE/COMMONMARK
$ composer require league/commonmark:^0.14
<?php
$converter = new CommonMarkConverter();
echo $converter->convertToHtml('Hello **Nomad PHP!**');
INTEGRATIONS
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
CONVERSION PROCESS
<https://nomadphp.com>
<a href="https://nomadphp.com">
https://nomadphp.com
</a>
CONVERSION PROCESS
<https://nomadphp.com>
Markdow
n
Parse
<document>
<paragraph>
<link destination="https://nomadphp.com">
<text>https://nomadphp.com</text>
</link>
</paragraph>
</document>
CONVERSION PROCESS
Markdow
n
AST RenderParse
CONVERSION PROCESS
<a href="https://nomadphp.com">
https://nomadphp.com
</a>
Markdow
n
AST HTMLRenderParse
CONVERSION PROCESS
Markdow
n
AST HTMLRenderParse
Add your own custom parser, processor, or renderer
EXAMPLE 1: CUSTOM PARSER
<https://nomadphp.com>
<a href="https://nomadphp.com">
https://nomadphp.com
</a>
<@colinodell>
<a href="https://twitter.com/colinodell">
@colinodell
</a>
class TwitterUsernameAutolinkParser extends AbstractInlineParser {
public function getCharacters() {
return ['<'];
}
public function parse(InlineParserContext $inlineContext) {
$cursor = $inlineContext->getCursor();
}
}
CURSOR
Learning CommonMark with <@colinodell>!
getCharacter()
getFirstNonSpaceCharacter(
)
getRemainder()
getLine()
getPosition()
advance()
advanceBy($count)
advanceBySpaceOrTab()
advanceWhileMatches($char
)
advanceToFirstNonSpace()
isIndented()
isAtEnd()
match($regex)
peek($count)
CURSOR::ADVANCE()
Learning CommonMark with <@colinodell>!
getCharacter()
getFirstNonSpaceCharacter(
)
getRemainder()
getLine()
getPosition()
advance()
advanceBy($count)
advanceBySpaceOrTab()
advanceWhileMatches($char
)
advanceToFirstNonSpace()
isIndented()
isAtEnd()
match($regex)
peek($count)
CURSOR::ADVANCEBY(INT)
Learning CommonMark with <@colinodell>!
getCharacter()
getFirstNonSpaceCharacter(
)
getRemainder()
getLine()
getPosition()
advance()
advanceBy($count)
advanceBySpaceOrTab()
advanceWhileMatches($char
)
advanceToFirstNonSpace()
isIndented()
isAtEnd()
match($regex)
peek($count)
CURSOR::PEEK(INT)
Learning CommonMark with <@colinodell>!
getCharacter()
getFirstNonSpaceCharacter(
)
getRemainder()
getLine()
getPosition()
advance()
advanceBy($count)
advanceBySpaceOrTab()
advanceWhileMatches($char
)
advanceToFirstNonSpace()
isIndented()
isAtEnd()
match($regex)
peek($count)
CURSOR
Learning CommonMark with <@colinodell>!
public function getCharacters()
{
return ['<'];
}
CURSOR
Learning CommonMark with <@colinodell>!
getCharacter()
getFirstNonSpaceCharacter(
)
getRemainder()
getLine()
getPosition()
advance()
advanceBy($count)
advanceBySpaceOrTab()
advanceWhileMatches($char
)
advanceToFirstNonSpace()
isIndented()
isAtEnd()
match($regex)
peek($count)
CURSOR
Learning CommonMark with <@colinodell>!
getCharacter()
getFirstNonSpaceCharacter(
)
getRemainder()
getLine()
getPosition()
advance()
advanceBy($count)
advanceBySpaceOrTab()
advanceWhileMatches($char
)
advanceToFirstNonSpace()
isIndented()
isAtEnd()
match($regex)
peek($count)
/^<@[A-Za-z0-9_]+>/
CUSTOMIZING LEAGUE/COMMONMARK
class TwitterUsernameAutolinkParser extends AbstractInlineParser {
public function getCharacters() {
return ['<'];
}
public function parse(InlineParserContext $inlineContext) {
$cursor = $inlineContext->getCursor();
if ($match = $cursor->match('/^<@[A-Za-z0-9_]+>/')) {
// Remove the starting '<@' and ending '>' that were matched
$username = substr($match, 2, -1);
$profileUrl = 'https://twitter.com/' . $username;
$link = new Link($profileUrl, '@'.$username);
$inlineContext->getContainer()->appendChild($link);
return true;
}
return false;
}
}
$environment = Environment::createCommonMarkEnvironment();
$environment->addInlineParser(
new TwitterHandleParser()
);
$converter = new CommonMarkConverter($environment);
$html = $converter->convertToHtml(
"Follow <@colinodell> on Twitter!"
);
EXAMPLE 2: CUSTOM AST PROCESSOR
<document>
<paragraph>
<link destination="https://nomadphp.com">
<text>https://nomadphp.com</text>
</link>
</paragraph>
</document>
<document>
<paragraph>
<link destination="https://bit.ly/foo">
<text>https://nomadphp.com</text>
</link>
</paragraph>
</document>
class ShortenLinkProcessor implements DocumentProcessorInterface {
public function processDocument(Document $document) {
$walker = $document->walker();
while ($event = $walker->next()) {
if ($event->isEntering() && $event->getNode() instanceof Link) {
/** @var Link $linkNode */
$linkNode = $event->getNode();
$originalUrl = $linkNode->getUrl();
$shortUrl = $this->bitly->shorten($originalUrl);
$linkNode->setUrl($shortUrl);
}
}
}
}
$environment = Environment::createCommonMarkEnvironment();
$environment->addDocumentProcessor(
new ShortenLinkProcessor()
);
$converter = new CommonMarkConverter($environment);
$html = $converter->convertToHtml(
"Meetings: <https://nomadphp.com/upcoming/>"
);
EXAMPLE 2: CUSTOM AST PROCESSOR
EXAMPLE 3: CUSTOM RENDERER
<document>
<paragraph>
<text>Hello World!</text>
</paragraph>
<thematic_break />
</document>
<p>Hello World!</p>
<hr />
<p>Hello World!</p>
<img src="hr.png" />
EXAMPLE 3: CUSTOM RENDERER
class ImageHorizontalRuleRenderer implements BlockRendererInterface {
public function render(...) {
return new HtmlElement('img', ['src' => 'hr.png']);
}
}
$environment = Environment::createCommonMarkEnvironment();
$environment->addBlockRenderer(
LeagueCommonMarkBlockElementThematicBreak::class,
new ImageHorizontalRuleRenderer()
);
$converter = new CommonMarkConverter($environment);
$html = $converter->convertToHtml("Hello World!nn-----");
EXAMPLE 3: CUSTOM RENDERER
BUNDLING INTO AN EXTENSION
class MyCustomExtension extends Extension {
public function getInlineParsers() {
return [new TwitterUsernameAutolinkParser()];
}
public function getDocumentProcessors() {
return [new ShortenLinkProcessor()];
}
public function getBlockRenderers() {
return [new ImageHorizontalRuleRenderer()];
}
}
BUNDLING INTO AN EXTENSION
$environment = Environment::createCommonMarkEnvironment();
$environment->addExtension(new MyCustomExtension());
$converter = new CommonMarkConverter($environment);
$html = $converter->convertToHtml("...");
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
WELL-TESTED
 94% code coverage
 Functional tests
 All 616 spec examples
 Library of regression tests
 Unit tests
 Cursor
 Environment
 Utility classes
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
PERFORMANCE
0 20 40 60 80 100
Parsedown
PHP Markdown Extra
Time (ms)
league/commonmark is ~35-40ms
slower
PHP 5.6 PHP 7.0
Tips:
• Use PHP 7 (50-80% boost)
• Choose library based on your
needs
• Cache rendered HTML (100%
boost)
• Optimize custom functionality
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
STABILITY
 Current version: 0.15.0
 Conforms to CommonMark spec 0.26
 1.0.0 will be released once CommonMark spec is 1.0
 No major stability issues
 Backwards Compatibility Promise:
 No BC breaks to CommonMarkConverter class in 0.x
 Other BC breaks will be documented
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
Installation & Documentation:
http://github.com/thephpleague/commonmark
Learn More About CommonMark:
http://commonmark.org
Slides / Feedback:
https://joind.in/talk/22293
@colinodell

More Related Content

Viewers also liked

Markdown可以做什麼
Markdown可以做什麼Markdown可以做什麼
Markdown可以做什麼Yen-lung Tsai
 
Write book in markdown
Write book in markdownWrite book in markdown
Write book in markdownLarry Cai
 
Unit Testing einer Zend-Framework 2 Anwendung
Unit Testing einer Zend-Framework 2 AnwendungUnit Testing einer Zend-Framework 2 Anwendung
Unit Testing einer Zend-Framework 2 AnwendungRalf Eggert
 
Markdown vs. WYSIWYG - Stop using the web like a word document
Markdown vs. WYSIWYG - Stop using the web like a word document Markdown vs. WYSIWYG - Stop using the web like a word document
Markdown vs. WYSIWYG - Stop using the web like a word document Zensations GmbH
 
markedj: The best of markdown processor on JVM
markedj: The best of markdown processor on JVMmarkedj: The best of markdown processor on JVM
markedj: The best of markdown processor on JVMtakezoe
 
Let's learning Markdown
Let's learning MarkdownLet's learning Markdown
Let's learning MarkdownWanqiang Ji
 
An introduction to knitr and R Markdown
An introduction to knitr and R MarkdownAn introduction to knitr and R Markdown
An introduction to knitr and R Markdownsahirbhatnagar
 
Markdown - friend or foe?
Markdown - friend or foe?Markdown - friend or foe?
Markdown - friend or foe?Ellis Pratt
 
How to make keynote like presentation with markdown
How to make keynote like presentation with markdownHow to make keynote like presentation with markdown
How to make keynote like presentation with markdownHiroaki NAKADA
 
Die Magie von Markdown
Die Magie von MarkdownDie Magie von Markdown
Die Magie von MarkdownHendrik Spree
 
Hacking the Web
Hacking the WebHacking the Web
Hacking the WebMike Crabb
 
What is mmd - Multi Markdown ?
What is mmd - Multi Markdown ?What is mmd - Multi Markdown ?
What is mmd - Multi Markdown ?Luc Vanrobays
 
The power of Markdown
The power of MarkdownThe power of Markdown
The power of MarkdownNadal Soler
 
26 Disruptive & Technology Trends 2016 - 2018
26 Disruptive & Technology Trends 2016 - 201826 Disruptive & Technology Trends 2016 - 2018
26 Disruptive & Technology Trends 2016 - 2018Brian Solis
 

Viewers also liked (19)

Markdown可以做什麼
Markdown可以做什麼Markdown可以做什麼
Markdown可以做什麼
 
Write book in markdown
Write book in markdownWrite book in markdown
Write book in markdown
 
Unit Testing einer Zend-Framework 2 Anwendung
Unit Testing einer Zend-Framework 2 AnwendungUnit Testing einer Zend-Framework 2 Anwendung
Unit Testing einer Zend-Framework 2 Anwendung
 
Markdownがアツい
MarkdownがアツいMarkdownがアツい
Markdownがアツい
 
Markdown vs. WYSIWYG - Stop using the web like a word document
Markdown vs. WYSIWYG - Stop using the web like a word document Markdown vs. WYSIWYG - Stop using the web like a word document
Markdown vs. WYSIWYG - Stop using the web like a word document
 
markedj: The best of markdown processor on JVM
markedj: The best of markdown processor on JVMmarkedj: The best of markdown processor on JVM
markedj: The best of markdown processor on JVM
 
Let's learning Markdown
Let's learning MarkdownLet's learning Markdown
Let's learning Markdown
 
Markdown – An Introduction
Markdown – An IntroductionMarkdown – An Introduction
Markdown – An Introduction
 
Markdown Slides [EN]
Markdown Slides [EN]Markdown Slides [EN]
Markdown Slides [EN]
 
An introduction to knitr and R Markdown
An introduction to knitr and R MarkdownAn introduction to knitr and R Markdown
An introduction to knitr and R Markdown
 
Take it easy with markdown
Take it easy with markdownTake it easy with markdown
Take it easy with markdown
 
Markdown - friend or foe?
Markdown - friend or foe?Markdown - friend or foe?
Markdown - friend or foe?
 
How to make keynote like presentation with markdown
How to make keynote like presentation with markdownHow to make keynote like presentation with markdown
How to make keynote like presentation with markdown
 
Die Magie von Markdown
Die Magie von MarkdownDie Magie von Markdown
Die Magie von Markdown
 
Hacking the Web
Hacking the WebHacking the Web
Hacking the Web
 
What is mmd - Multi Markdown ?
What is mmd - Multi Markdown ?What is mmd - Multi Markdown ?
What is mmd - Multi Markdown ?
 
The power of Markdown
The power of MarkdownThe power of Markdown
The power of Markdown
 
reveal.js 3.0.0
reveal.js 3.0.0reveal.js 3.0.0
reveal.js 3.0.0
 
26 Disruptive & Technology Trends 2016 - 2018
26 Disruptive & Technology Trends 2016 - 201826 Disruptive & Technology Trends 2016 - 2018
26 Disruptive & Technology Trends 2016 - 2018
 

Similar to CommonMark: Markdown done right - Nomad PHP September 2016

CommonMark: Markdown Done Right
CommonMark: Markdown Done RightCommonMark: Markdown Done Right
CommonMark: Markdown Done RightColin O'Dell
 
Introduction to league/commonmark
Introduction to league/commonmarkIntroduction to league/commonmark
Introduction to league/commonmarkColin O'Dell
 
Building dynamic websites with Mod perl and apache
Building dynamic websites with Mod perl and apacheBuilding dynamic websites with Mod perl and apache
Building dynamic websites with Mod perl and apacheKamal Nayan
 
Custom post-framworks
Custom post-framworksCustom post-framworks
Custom post-framworkswcto2017
 
Custom post-framworks
Custom post-framworksCustom post-framworks
Custom post-framworksKiera Howe
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2Hugo Hamon
 
Symfony2 for Midgard Developers
Symfony2 for Midgard DevelopersSymfony2 for Midgard Developers
Symfony2 for Midgard DevelopersHenri Bergius
 
Mojolicious - A new hope
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hopeMarcus Ramberg
 
Eclipse Pdt2.0 26.05.2009
Eclipse Pdt2.0 26.05.2009Eclipse Pdt2.0 26.05.2009
Eclipse Pdt2.0 26.05.2009Bastian Feder
 
Improving QA on PHP projects - confoo 2011
Improving QA on PHP projects - confoo 2011Improving QA on PHP projects - confoo 2011
Improving QA on PHP projects - confoo 2011Michelangelo van Dam
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSBuilding Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSAntonio Peric-Mazar
 
Php Development With Eclipde PDT
Php Development With Eclipde PDTPhp Development With Eclipde PDT
Php Development With Eclipde PDTBastian Feder
 
DEV Čtvrtkon #76 - Makefile
DEV Čtvrtkon #76 - MakefileDEV Čtvrtkon #76 - Makefile
DEV Čtvrtkon #76 - MakefileCtvrtkoncz
 

Similar to CommonMark: Markdown done right - Nomad PHP September 2016 (20)

CommonMark: Markdown Done Right
CommonMark: Markdown Done RightCommonMark: Markdown Done Right
CommonMark: Markdown Done Right
 
Introduction to league/commonmark
Introduction to league/commonmarkIntroduction to league/commonmark
Introduction to league/commonmark
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
Building dynamic websites with Mod perl and apache
Building dynamic websites with Mod perl and apacheBuilding dynamic websites with Mod perl and apache
Building dynamic websites with Mod perl and apache
 
Rebuilding our Foundation
Rebuilding our FoundationRebuilding our Foundation
Rebuilding our Foundation
 
Custom post-framworks
Custom post-framworksCustom post-framworks
Custom post-framworks
 
Custom post-framworks
Custom post-framworksCustom post-framworks
Custom post-framworks
 
Speed up your developments with Symfony2
Speed up your developments with Symfony2Speed up your developments with Symfony2
Speed up your developments with Symfony2
 
Symfony2 for Midgard Developers
Symfony2 for Midgard DevelopersSymfony2 for Midgard Developers
Symfony2 for Midgard Developers
 
Mojolicious - A new hope
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hope
 
Eclipse Pdt2.0 26.05.2009
Eclipse Pdt2.0 26.05.2009Eclipse Pdt2.0 26.05.2009
Eclipse Pdt2.0 26.05.2009
 
Improving QA on PHP projects - confoo 2011
Improving QA on PHP projects - confoo 2011Improving QA on PHP projects - confoo 2011
Improving QA on PHP projects - confoo 2011
 
The Berkshelf Way
The Berkshelf WayThe Berkshelf Way
The Berkshelf Way
 
Building Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJSBuilding Single Page Application (SPA) with Symfony2 and AngularJS
Building Single Page Application (SPA) with Symfony2 and AngularJS
 
Php Development With Eclipde PDT
Php Development With Eclipde PDTPhp Development With Eclipde PDT
Php Development With Eclipde PDT
 
Don't screw it up! How to build durable API
Don't screw it up! How to build durable API Don't screw it up! How to build durable API
Don't screw it up! How to build durable API
 
DEV Čtvrtkon #76 - Makefile
DEV Čtvrtkon #76 - MakefileDEV Čtvrtkon #76 - Makefile
DEV Čtvrtkon #76 - Makefile
 
MariaDB pres at LeMUG
MariaDB pres at LeMUGMariaDB pres at LeMUG
MariaDB pres at LeMUG
 
Php Power Tools
Php Power ToolsPhp Power Tools
Php Power Tools
 
PHP 5 Sucks. PHP 5 Rocks.
PHP 5 Sucks. PHP 5 Rocks.PHP 5 Sucks. PHP 5 Rocks.
PHP 5 Sucks. PHP 5 Rocks.
 

More from Colin O'Dell

Demystifying Unicode - Longhorn PHP 2021
Demystifying Unicode - Longhorn PHP 2021Demystifying Unicode - Longhorn PHP 2021
Demystifying Unicode - Longhorn PHP 2021Colin O'Dell
 
Releasing High Quality Packages - Longhorn PHP 2021
Releasing High Quality Packages - Longhorn PHP 2021Releasing High Quality Packages - Longhorn PHP 2021
Releasing High Quality Packages - Longhorn PHP 2021Colin O'Dell
 
Releasing High Quality PHP Packages - ConFoo Montreal 2019
Releasing High Quality PHP Packages - ConFoo Montreal 2019Releasing High Quality PHP Packages - ConFoo Montreal 2019
Releasing High Quality PHP Packages - ConFoo Montreal 2019Colin O'Dell
 
Debugging Effectively - ConFoo Montreal 2019
Debugging Effectively - ConFoo Montreal 2019Debugging Effectively - ConFoo Montreal 2019
Debugging Effectively - ConFoo Montreal 2019Colin O'Dell
 
Automating Deployments with Deployer - php[world] 2018
Automating Deployments with Deployer - php[world] 2018Automating Deployments with Deployer - php[world] 2018
Automating Deployments with Deployer - php[world] 2018Colin O'Dell
 
Releasing High-Quality Packages - php[world] 2018
Releasing High-Quality Packages - php[world] 2018Releasing High-Quality Packages - php[world] 2018
Releasing High-Quality Packages - php[world] 2018Colin O'Dell
 
Debugging Effectively - DrupalCon Nashville 2018
Debugging Effectively - DrupalCon Nashville 2018Debugging Effectively - DrupalCon Nashville 2018
Debugging Effectively - DrupalCon Nashville 2018Colin O'Dell
 
Rise of the Machines: PHP and IoT - ZendCon 2017
Rise of the Machines: PHP and IoT - ZendCon 2017Rise of the Machines: PHP and IoT - ZendCon 2017
Rise of the Machines: PHP and IoT - ZendCon 2017Colin O'Dell
 
Debugging Effectively - All Things Open 2017
Debugging Effectively - All Things Open 2017Debugging Effectively - All Things Open 2017
Debugging Effectively - All Things Open 2017Colin O'Dell
 
Hacking Your Way To Better Security - DrupalCon Baltimore 2017
Hacking Your Way To Better Security - DrupalCon Baltimore 2017Hacking Your Way To Better Security - DrupalCon Baltimore 2017
Hacking Your Way To Better Security - DrupalCon Baltimore 2017Colin O'Dell
 
Debugging Effectively - PHP UK 2017
Debugging Effectively - PHP UK 2017Debugging Effectively - PHP UK 2017
Debugging Effectively - PHP UK 2017Colin O'Dell
 
Debugging Effectively - SunshinePHP 2017
Debugging Effectively - SunshinePHP 2017Debugging Effectively - SunshinePHP 2017
Debugging Effectively - SunshinePHP 2017Colin O'Dell
 
Automating Your Workflow with Gulp.js - php[world] 2016
Automating Your Workflow with Gulp.js - php[world] 2016Automating Your Workflow with Gulp.js - php[world] 2016
Automating Your Workflow with Gulp.js - php[world] 2016Colin O'Dell
 
Rise of the Machines: PHP and IoT - php[world] 2016
Rise of the Machines: PHP and IoT - php[world] 2016Rise of the Machines: PHP and IoT - php[world] 2016
Rise of the Machines: PHP and IoT - php[world] 2016Colin O'Dell
 
Debugging Effectively - ZendCon 2016
Debugging Effectively - ZendCon 2016Debugging Effectively - ZendCon 2016
Debugging Effectively - ZendCon 2016Colin O'Dell
 
Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016Colin O'Dell
 
Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016Colin O'Dell
 
Debugging Effectively - DrupalCon Europe 2016
Debugging Effectively - DrupalCon Europe 2016Debugging Effectively - DrupalCon Europe 2016
Debugging Effectively - DrupalCon Europe 2016Colin O'Dell
 
Debugging Effectively - Frederick Web Tech 9/6/16
Debugging Effectively - Frederick Web Tech 9/6/16Debugging Effectively - Frederick Web Tech 9/6/16
Debugging Effectively - Frederick Web Tech 9/6/16Colin O'Dell
 
Debugging Effectively
Debugging EffectivelyDebugging Effectively
Debugging EffectivelyColin O'Dell
 

More from Colin O'Dell (20)

Demystifying Unicode - Longhorn PHP 2021
Demystifying Unicode - Longhorn PHP 2021Demystifying Unicode - Longhorn PHP 2021
Demystifying Unicode - Longhorn PHP 2021
 
Releasing High Quality Packages - Longhorn PHP 2021
Releasing High Quality Packages - Longhorn PHP 2021Releasing High Quality Packages - Longhorn PHP 2021
Releasing High Quality Packages - Longhorn PHP 2021
 
Releasing High Quality PHP Packages - ConFoo Montreal 2019
Releasing High Quality PHP Packages - ConFoo Montreal 2019Releasing High Quality PHP Packages - ConFoo Montreal 2019
Releasing High Quality PHP Packages - ConFoo Montreal 2019
 
Debugging Effectively - ConFoo Montreal 2019
Debugging Effectively - ConFoo Montreal 2019Debugging Effectively - ConFoo Montreal 2019
Debugging Effectively - ConFoo Montreal 2019
 
Automating Deployments with Deployer - php[world] 2018
Automating Deployments with Deployer - php[world] 2018Automating Deployments with Deployer - php[world] 2018
Automating Deployments with Deployer - php[world] 2018
 
Releasing High-Quality Packages - php[world] 2018
Releasing High-Quality Packages - php[world] 2018Releasing High-Quality Packages - php[world] 2018
Releasing High-Quality Packages - php[world] 2018
 
Debugging Effectively - DrupalCon Nashville 2018
Debugging Effectively - DrupalCon Nashville 2018Debugging Effectively - DrupalCon Nashville 2018
Debugging Effectively - DrupalCon Nashville 2018
 
Rise of the Machines: PHP and IoT - ZendCon 2017
Rise of the Machines: PHP and IoT - ZendCon 2017Rise of the Machines: PHP and IoT - ZendCon 2017
Rise of the Machines: PHP and IoT - ZendCon 2017
 
Debugging Effectively - All Things Open 2017
Debugging Effectively - All Things Open 2017Debugging Effectively - All Things Open 2017
Debugging Effectively - All Things Open 2017
 
Hacking Your Way To Better Security - DrupalCon Baltimore 2017
Hacking Your Way To Better Security - DrupalCon Baltimore 2017Hacking Your Way To Better Security - DrupalCon Baltimore 2017
Hacking Your Way To Better Security - DrupalCon Baltimore 2017
 
Debugging Effectively - PHP UK 2017
Debugging Effectively - PHP UK 2017Debugging Effectively - PHP UK 2017
Debugging Effectively - PHP UK 2017
 
Debugging Effectively - SunshinePHP 2017
Debugging Effectively - SunshinePHP 2017Debugging Effectively - SunshinePHP 2017
Debugging Effectively - SunshinePHP 2017
 
Automating Your Workflow with Gulp.js - php[world] 2016
Automating Your Workflow with Gulp.js - php[world] 2016Automating Your Workflow with Gulp.js - php[world] 2016
Automating Your Workflow with Gulp.js - php[world] 2016
 
Rise of the Machines: PHP and IoT - php[world] 2016
Rise of the Machines: PHP and IoT - php[world] 2016Rise of the Machines: PHP and IoT - php[world] 2016
Rise of the Machines: PHP and IoT - php[world] 2016
 
Debugging Effectively - ZendCon 2016
Debugging Effectively - ZendCon 2016Debugging Effectively - ZendCon 2016
Debugging Effectively - ZendCon 2016
 
Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016Hacking Your Way to Better Security - ZendCon 2016
Hacking Your Way to Better Security - ZendCon 2016
 
Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016Hacking Your Way to Better Security - PHP South Africa 2016
Hacking Your Way to Better Security - PHP South Africa 2016
 
Debugging Effectively - DrupalCon Europe 2016
Debugging Effectively - DrupalCon Europe 2016Debugging Effectively - DrupalCon Europe 2016
Debugging Effectively - DrupalCon Europe 2016
 
Debugging Effectively - Frederick Web Tech 9/6/16
Debugging Effectively - Frederick Web Tech 9/6/16Debugging Effectively - Frederick Web Tech 9/6/16
Debugging Effectively - Frederick Web Tech 9/6/16
 
Debugging Effectively
Debugging EffectivelyDebugging Effectively
Debugging Effectively
 

Recently uploaded

Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphNeo4j
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 

Recently uploaded (20)

Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge GraphSIEMENS: RAPUNZEL – A Tale About Knowledge Graph
SIEMENS: RAPUNZEL – A Tale About Knowledge Graph
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 

CommonMark: Markdown done right - Nomad PHP September 2016

  • 2. COLIN O’DELL Creator & Maintainer of league/commonmark Lead Web Developer at Unleashed Technologies Author of PHP 7 Migration Guide e-book @colinodell
  • 3. TOPICS Origins of Markdown CommonMark Spec league/commonmark Overview Customizing league/commonmark
  • 4. ORIGINS OF MARKDOWN Created in March 2004 by John Gruber Informal plain-text formatting language Converts readable text to valid (X)HTML Primary goal - readability
  • 5. HISTORY OF MARKDOWN Hello Nomad PHP! ---------------- Markdown is **awesome**! 1. Foo 2. Bar 3. Baz Wikipedia entry: <https://en.wikipedia.org/wiki/Markdown>
  • 6. WHY IS IT SUCCESSFUL? 1. Syntax is visually-similar to the resulting markup 2. Non-strict, forgiving parsing 3. Easily adaptable for different uses
  • 7. 67+ DIFFERENT FLAVORS Source: https://github.com/markdown/markdown.github.com/wiki/Implementations Actuarius Blackfriday BlueCloth BlueFeather cebe/markdown CocoaMarkdown Discount ffi-sundown GHMarkdownParser Goskirt Hoedown Hoep Knockoff kramdown Laika libpandoc Lowdown lua-discount Lunamark markdown markdown-clj markdown-js markdown-oo-php markdown.bash markdown.lua markdown.pl markdown4j MarkdownDeep MarkdownJ MarkdownPapers MarkdownSharp marked Maruku md2html.awk Misaka Mistune MMMarkdown MoonShine MultiMarkdown node-discount node-markdown node-multimarkdown OMD Pandoc Parsedown Parsedown Extra peg-markdown peg-multimarkdown & fork pegdown PHP Markdown PHP Markdown Extra PHP-Sundown Python-Discount python-hoedown Python-Markdown Python-Markdown2 RDiscount Redcarpet RoboSkirt Showdown Sundown Sundown HS Sundown.net text-markdown texts.js Txtmark upskirt.go
  • 9. COMMONMARK IS… A strongly defined, highly compatible specification of Markdown. Written by John MacFarlane (in collaboration with people from Github, StackOverflow, Reddit, and others) Spec includes:  Strict rules (precedence, parsing order, handling edge cases)  Specific definitions (ex: “whitespace”, “punctuation”)  616 examples
  • 10.
  • 11.
  • 12.
  • 13.
  • 14. WHY IS IT NEEDED? *I love Markdown* <p><em>I love Markdown</em></p>
  • 15. WHY IS IT NEEDED? *I *love* Markdown*
  • 16. WHY IS IT NEEDED? Source: http://johnmacfarlane.net/babelmark2/
  • 17. 30% WHY IS IT NEEDED? *I *love* Markdown* <p><em>I <em>love</em> Markdown</em></p> *I *love* Markdown* <p><em>I </em>love<em> Markdown</em></p> *I *love* Markdown* <p><em>I *love</em> Markdown*</p> 15% 33% Source: http://johnmacfarlane.net/babelmark2/
  • 18. WHY IS IT NEEDED? 1. > Hello World! ------ Source: http://johnmacfarlane.net/babelmark2/
  • 19. WHY IS IT NEEDED? 1. > Hello World! ------ Source: http://johnmacfarlane.net/babelmark2/
  • 20. WHY IS IT NEEDED? 1. > Hello World! ------ Source: http://johnmacfarlane.net/babelmark2/
  • 21. WHY IS IT NEEDED? 1. > Hello World! ------ Source: http://johnmacfarlane.net/babelmark2/
  • 22. WHY IS IT NEEDED? 1. > Hello World! ------ Source: http://johnmacfarlane.net/babelmark2/
  • 23. LEAGUE/COMMONMARK A well-written, super-configurable Markdown parser for PHP based on the CommonMark spec.
  • 24. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable
  • 25. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable
  • 26. ADDING LEAGUE/COMMONMARK $ composer require league/commonmark:^0.14 <?php $converter = new CommonMarkConverter(); echo $converter->convertToHtml('Hello **Nomad PHP!**');
  • 28. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable
  • 29. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable
  • 34. CONVERSION PROCESS Markdow n AST HTMLRenderParse Add your own custom parser, processor, or renderer
  • 35. EXAMPLE 1: CUSTOM PARSER <https://nomadphp.com> <a href="https://nomadphp.com"> https://nomadphp.com </a> <@colinodell> <a href="https://twitter.com/colinodell"> @colinodell </a>
  • 36. class TwitterUsernameAutolinkParser extends AbstractInlineParser { public function getCharacters() { return ['<']; } public function parse(InlineParserContext $inlineContext) { $cursor = $inlineContext->getCursor(); } }
  • 37. CURSOR Learning CommonMark with <@colinodell>! getCharacter() getFirstNonSpaceCharacter( ) getRemainder() getLine() getPosition() advance() advanceBy($count) advanceBySpaceOrTab() advanceWhileMatches($char ) advanceToFirstNonSpace() isIndented() isAtEnd() match($regex) peek($count)
  • 38. CURSOR::ADVANCE() Learning CommonMark with <@colinodell>! getCharacter() getFirstNonSpaceCharacter( ) getRemainder() getLine() getPosition() advance() advanceBy($count) advanceBySpaceOrTab() advanceWhileMatches($char ) advanceToFirstNonSpace() isIndented() isAtEnd() match($regex) peek($count)
  • 39. CURSOR::ADVANCEBY(INT) Learning CommonMark with <@colinodell>! getCharacter() getFirstNonSpaceCharacter( ) getRemainder() getLine() getPosition() advance() advanceBy($count) advanceBySpaceOrTab() advanceWhileMatches($char ) advanceToFirstNonSpace() isIndented() isAtEnd() match($regex) peek($count)
  • 40. CURSOR::PEEK(INT) Learning CommonMark with <@colinodell>! getCharacter() getFirstNonSpaceCharacter( ) getRemainder() getLine() getPosition() advance() advanceBy($count) advanceBySpaceOrTab() advanceWhileMatches($char ) advanceToFirstNonSpace() isIndented() isAtEnd() match($regex) peek($count)
  • 41. CURSOR Learning CommonMark with <@colinodell>! public function getCharacters() { return ['<']; }
  • 42. CURSOR Learning CommonMark with <@colinodell>! getCharacter() getFirstNonSpaceCharacter( ) getRemainder() getLine() getPosition() advance() advanceBy($count) advanceBySpaceOrTab() advanceWhileMatches($char ) advanceToFirstNonSpace() isIndented() isAtEnd() match($regex) peek($count)
  • 43. CURSOR Learning CommonMark with <@colinodell>! getCharacter() getFirstNonSpaceCharacter( ) getRemainder() getLine() getPosition() advance() advanceBy($count) advanceBySpaceOrTab() advanceWhileMatches($char ) advanceToFirstNonSpace() isIndented() isAtEnd() match($regex) peek($count) /^<@[A-Za-z0-9_]+>/
  • 44. CUSTOMIZING LEAGUE/COMMONMARK class TwitterUsernameAutolinkParser extends AbstractInlineParser { public function getCharacters() { return ['<']; } public function parse(InlineParserContext $inlineContext) { $cursor = $inlineContext->getCursor(); if ($match = $cursor->match('/^<@[A-Za-z0-9_]+>/')) { // Remove the starting '<@' and ending '>' that were matched $username = substr($match, 2, -1); $profileUrl = 'https://twitter.com/' . $username; $link = new Link($profileUrl, '@'.$username); $inlineContext->getContainer()->appendChild($link); return true; } return false; } }
  • 45. $environment = Environment::createCommonMarkEnvironment(); $environment->addInlineParser( new TwitterHandleParser() ); $converter = new CommonMarkConverter($environment); $html = $converter->convertToHtml( "Follow <@colinodell> on Twitter!" );
  • 46. EXAMPLE 2: CUSTOM AST PROCESSOR <document> <paragraph> <link destination="https://nomadphp.com"> <text>https://nomadphp.com</text> </link> </paragraph> </document> <document> <paragraph> <link destination="https://bit.ly/foo"> <text>https://nomadphp.com</text> </link> </paragraph> </document>
  • 47. class ShortenLinkProcessor implements DocumentProcessorInterface { public function processDocument(Document $document) { $walker = $document->walker(); while ($event = $walker->next()) { if ($event->isEntering() && $event->getNode() instanceof Link) { /** @var Link $linkNode */ $linkNode = $event->getNode(); $originalUrl = $linkNode->getUrl(); $shortUrl = $this->bitly->shorten($originalUrl); $linkNode->setUrl($shortUrl); } } } }
  • 48. $environment = Environment::createCommonMarkEnvironment(); $environment->addDocumentProcessor( new ShortenLinkProcessor() ); $converter = new CommonMarkConverter($environment); $html = $converter->convertToHtml( "Meetings: <https://nomadphp.com/upcoming/>" ); EXAMPLE 2: CUSTOM AST PROCESSOR
  • 49. EXAMPLE 3: CUSTOM RENDERER <document> <paragraph> <text>Hello World!</text> </paragraph> <thematic_break /> </document> <p>Hello World!</p> <hr /> <p>Hello World!</p> <img src="hr.png" />
  • 50. EXAMPLE 3: CUSTOM RENDERER class ImageHorizontalRuleRenderer implements BlockRendererInterface { public function render(...) { return new HtmlElement('img', ['src' => 'hr.png']); } }
  • 51. $environment = Environment::createCommonMarkEnvironment(); $environment->addBlockRenderer( LeagueCommonMarkBlockElementThematicBreak::class, new ImageHorizontalRuleRenderer() ); $converter = new CommonMarkConverter($environment); $html = $converter->convertToHtml("Hello World!nn-----"); EXAMPLE 3: CUSTOM RENDERER
  • 52. BUNDLING INTO AN EXTENSION class MyCustomExtension extends Extension { public function getInlineParsers() { return [new TwitterUsernameAutolinkParser()]; } public function getDocumentProcessors() { return [new ShortenLinkProcessor()]; } public function getBlockRenderers() { return [new ImageHorizontalRuleRenderer()]; } }
  • 53. BUNDLING INTO AN EXTENSION $environment = Environment::createCommonMarkEnvironment(); $environment->addExtension(new MyCustomExtension()); $converter = new CommonMarkConverter($environment); $html = $converter->convertToHtml("...");
  • 54. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable
  • 55. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable
  • 56. WELL-TESTED  94% code coverage  Functional tests  All 616 spec examples  Library of regression tests  Unit tests  Cursor  Environment  Utility classes
  • 57. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable
  • 58. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable
  • 59. PERFORMANCE 0 20 40 60 80 100 Parsedown PHP Markdown Extra Time (ms) league/commonmark is ~35-40ms slower PHP 5.6 PHP 7.0 Tips: • Use PHP 7 (50-80% boost) • Choose library based on your needs • Cache rendered HTML (100% boost) • Optimize custom functionality
  • 60. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable
  • 61. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable
  • 62. STABILITY  Current version: 0.15.0  Conforms to CommonMark spec 0.26  1.0.0 will be released once CommonMark spec is 1.0  No major stability issues  Backwards Compatibility Promise:  No BC breaks to CommonMarkConverter class in 0.x  Other BC breaks will be documented
  • 63. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable
  • 64. Installation & Documentation: http://github.com/thephpleague/commonmark Learn More About CommonMark: http://commonmark.org Slides / Feedback: https://joind.in/talk/22293 @colinodell

Editor's Notes

  1. So what is league/commonmark?
  2. In collaboration with Aaron Swartz
  3. 2. Informal; not like XML and XHTML which reject data simply because it fails to adhere to strict, unforgiving standards 3: LaTeX – academia for scientific and mathematic papers DocBook – technical documentation
  4. We’re all familiar with the usual markdown syntax This specification dictates exactly how compliant parsers should handle Markdown input It includes
  5. That’s cool, but do we really NEED a spec? Is Markdown really that complicated? Well, let’s look at an example
  6. Straight-forward example of emphasizing text
  7. What happens if we add two asterisks?
  8. Babelmark2 John MacFarlane, CommonMark spec maintainer Like 3V4L, but for Markdown
  9. Whole string emphasized with nested inner emphasis, as you’d expect Another approach some parsers take is two separate emphasis elements Kinda makes sense What’s really strange and unexpected 3 other ways of parsing this (22%)
  10. 1/5 Actually 15 different ways that parsers interpret this
  11. 2/5 Actually 15 different ways that parsers interpret this
  12. 3/5
  13. 4/5
  14. 5/5 Actually 15 different ways that parsers interpret this OUTRO: The CommonMark standard is designed to eliminate this ambiguity so that your Markdown is handled in a logical, predictable fashion
  15. The league/commonmark library It basically takes Markdown in and spits HTML out. And it does so in a way that’s compliant with the CommonMark spec.
  16. Several integrations for this library built by the community
  17. We have a URL we want to link to using the standard autolinking syntax Wrapped with a less-than and greater-than sign “A” tag with href and text label of the URL Show how our engine does this behind-the-scenes
  18. Start off with Markdown input Run it through the various sub-parsers which results in an Abstract Syntax Tree
  19. Also known as an AST Tree structure of PHP objects, each representing a certain type of element For easier visualization I’m showing what these PHP objects MIGHT look like if we showed their data as XML Once we’ve got the final AST, we pass that along to the renderers…
  20. …which convert the AST into HTML Now what’s really cool is that…
  21. You can hook into any of these three aspects, adding “your own custom…” THREE EXAMPLES Now let’s go back to our autolink example
  22. What if we wanted to add similar autolinking functionality, but for Twitter handles? For example, say we want to enclose the Twitter handle in a similar fashion… which results in a link to that profile page Let me show you how simple it is to add this feature
  23. Simply create a sub-parser Tell the main parser to stop whenever a less-than sign is encountered When encountered, control is transferred to parse() Cursor
  24. Cursor is a simple yet powerful wrapper around the current line Stores current line’s text and current position being parsed Because we’ve told the engine we’re interested in less-than characters…
  25. When control is passed into parse() method, we can use these specially-design methods to Parse the string at that location Cursor provides several high-optimized UTF-8 aware methods for Markdown parsing
  26. That’s it! Now the APIs and methods might be unfamiliar, but hopefully you can see how features can be added seemlesly with only a few lines of code
  27. Match this regular expression Extract just the username from the matched text That’s it! Now the APIs and methods might be unfamiliar, but hopefully you can see how features can be added seemlesly with only a few lines of code
  28. What if we wanted to automatically shorten URLs with a service like bitly?
  29. Guaranteed to be compatible with all other CommonMark parsers in other languages
  30. CONTEXT: Blinking your eye is 100ms
  31. You can find the library on Packagist under league/commonmark Installation instructions & documentation can be found Hopefully you find this library useful and can try it out in your next project. Thank you so much!