SlideShare a Scribd company logo
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
@colinodel
l
LEAGUE/COMMONMARK
A well-written, super-configurable
Markdown parser for PHP based on the
CommonMark spec.
@colinodel
l
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
@colinodel
l
HISTORY OF MARKDOWN
Hello ZendCon!
--------------
Markdown is **awesome**!
1. Foo
2. Bar
3. Baz
Wikipedia entry:
<https://en.wikipedia.org/wiki/Markdown> @colinodel
l
WHY IS IT SUCCESSFUL?
1. Syntax is visually-similar to the resulting
markup
2. Non-strict, forgiving parsing
3. Easily adaptable for different uses
@colinodel
l
68+ DIFFERENT FLAVORS
Source: https://github.com/markdown/markdown.github.com/wiki/Implementations
Actuarius
Blackfriday
BlueCloth
BlueFeather
cebe/markdown
CocoaMarkdown
CommonMark
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
@colinodel
l
https://xkcd.com/927/
@colinodel
l
WHY IS IT NEEDED?
*I love Markdown*
<p><em>I love Markdown</em></p>
@colinodel
l
WHY IS IT NEEDED?
*I *love* Markdown*
@colinodel
l
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/
@colinodel
l
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/
COMMONMARK IS…
A strongly defined, highly compatible specification of Markdown.
Written by people from Github, StackOverflow, Reddit, and others.
Spec includes:
 Strict rules (precedence, parsing order, handling edge cases)
 Specific definitions (ex: “whitespace”, “punctuation”)
 624 examples
@colinodel
l
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
@colinodel
l
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
@colinodel
l
ADDING LEAGUE/COMMONMARK
$ composer require league/commonmark:^0.15
<?php
$converter = new CommonMarkConverter();
echo $converter->convertToHtml('Hello **ZendCon!**');
@colinodel
l
INTEGRATIONS
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
@colinodel
l
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
@colinodel
l
CONVERSION PROCESS
<http://www.zendcon.com>
<a href="http://www.zendcon.com">
http://www.zendcon.com
</a>
@colinodel
l
CONVERSION PROCESS
<http://www.zendcon.com>
Markdow
n
Parse
@colinodel
l
<document>
<paragraph>
<link destination="http://www.zendcon.com">
<text>http://www.zendcon.com</text>
</link>
</paragraph>
</document>
CONVERSION PROCESS
Markdow
n
AST RenderParse
@colinodel
l
CONVERSION PROCESS
<a href="http://www.zendcon.com">
http://www.zendcon.com
</a>
Markdow
n
AST HTMLRenderParse
@colinodel
l
CONVERSION PROCESS
Markdow
n
AST HTMLRenderParse
Add your own custom parser, processor, or renderer
@colinodel
l
EXAMPLE 1: CUSTOM PARSER
<http://www.zendcon.com>
<a href="http://www.zendcon.com">
http://www.zendcon.com
</a>
<@colinodell>
<a href="https://twitter.com/colinodell">
@colinodell
</a>
@colinodel
l
class TwitterUsernameAutolinkParser extends AbstractInlineParser {
public function getCharacters() {
return ['<'];
}
public function parse(InlineParserContext $inlineContext) {
// TODO
}
}
@colinodel
l
CURSOR
Learning CommonMark with <@colinodell>!
public function getCharacters()
{
return ['<'];
}
@colinodel
l
class TwitterUsernameAutolinkParser extends AbstractInlineParser {
public function getCharacters() {
return ['<'];
}
public function parse(InlineParserContext $inlineContext) {
$cursor = $inlineContext->getCursor();
}
}
@colinodel
l
CURSOR
Learning CommonMark with <@colinodell>!
getCharacter()
getFirstNonSpaceCharacter(
)
getRemainder()
getLine()
getPosition()
advance()
advanceBy($count)
advanceBySpaceOrTab()
advanceWhileMatches($char
)
advanceToFirstNonSpace()
isIndented()
isAtEnd()
match($regex)
peek($count)
@colinodel
l
CURSOR
Learning CommonMark with <@colinodell>!
getCharacter()
getFirstNonSpaceCharacter(
)
getRemainder()
getLine()
getPosition()
advance()
advanceBy($count)
advanceBySpaceOrTab()
advanceWhileMatches($char
)
advanceToFirstNonSpace()
isIndented()
isAtEnd()
match($regex)
peek($count)
@colinodel
l
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_]+>/
@colinodel
l
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;
}
}
@colinodel
l
$environment = Environment::createCommonMarkEnvironment();
$environment->addInlineParser(
new TwitterHandleParser()
);
$converter = new CommonMarkConverter($environment);
$html = $converter->convertToHtml(
"Follow <@colinodell> on Twitter!"
);
@colinodel
l
EXAMPLE 2: CUSTOM AST PROCESSOR
<document>
<paragraph>
<link destination="http://www.zendcon.com">
<text>http://www.zendcon.com</text>
</link>
</paragraph>
</document>
<document>
<paragraph>
<link destination="https://bit.ly/foo">
<text>http://www.zendcon.com</text>
</link>
</paragraph>
</document>
@colinodel
l
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);
}
}
}
}
@colinodel
l
$environment = Environment::createCommonMarkEnvironment();
$environment->addDocumentProcessor(
new ShortenLinkProcessor()
);
$converter = new CommonMarkConverter($environment);
$html = $converter->convertToHtml(
"Schedule: <http://www.zendcon.com/schedule>"
);
EXAMPLE 2: CUSTOM AST PROCESSOR
@colinodel
l
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" />
@colinodel
l
EXAMPLE 3: CUSTOM RENDERER
class ImageHorizontalRuleRenderer implements BlockRendererInterface {
public function render(...) {
return new HtmlElement('img', ['src' => 'hr.png']);
}
}
@colinodel
l
$environment = Environment::createCommonMarkEnvironment();
$environment->addBlockRenderer(
LeagueCommonMarkBlockElementThematicBreak::class,
new ImageHorizontalRuleRenderer()
);
$converter = new CommonMarkConverter($environment);
$html = $converter->convertToHtml("Hello World!nn-----");
EXAMPLE 3: CUSTOM RENDERER
@colinodel
l
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()];
}
}
@colinodel
l
BUNDLING INTO AN EXTENSION
$environment = Environment::createCommonMarkEnvironment();
$environment->addExtension(new MyCustomExtension());
$converter = new CommonMarkConverter($environment);
$html = $converter->convertToHtml("...");
@colinodel
l
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
@colinodel
l
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
@colinodel
l
WELL-TESTED
 94% code coverage
 Functional tests
 All 624 spec examples
 Library of regression tests
 Unit tests
 Cursor
 Environment
 Utility classes
@colinodel
l
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
@colinodel
l
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
@colinodel
l
PERFORMANCE
0 20 40 60 80
Parsedown
cebe/markdown gfm
PHP Markdown Extra
league/commonmark
Time (ms)
league/commonmark is ~22-24ms slower
PHP 5.6 PHP 7.1
Tips:
• Choose library based on your
needs
• Cache rendered HTML (100%
boost)
• Use PHP 7 (50% boost)
• Optimize custom functionality
@colinodel
l
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
@colinodel
l
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
@colinodel
l
STABILITY
 Current version: 0.15.6
 Conforms to CommonMark spec 0.28
 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 are documented (see UPGRADING.md)
@colinodel
l
FEATURES
 100% compliance with the CommonMark spec
 Easy to implement
 Easy to customize
 Well-tested
 Decent performance
 (Relatively) stable
@colinodel
l
Installation & Documentation:
http://github.com/thephpleague/commonmark
Learn More About CommonMark:
http://commonmark.org
Slides / Feedback:
https://joind.in/talk/8da74
@colinodell

More Related Content

What's hot

Seaside - The Revenge of Smalltalk
Seaside - The Revenge of SmalltalkSeaside - The Revenge of Smalltalk
Seaside - The Revenge of Smalltalk
Lukas Renggli
 
Lecture3 php by okello erick
Lecture3 php by okello erickLecture3 php by okello erick
Lecture3 php by okello erick
okelloerick
 
Oracle Inter-Session Communication
Oracle Inter-Session CommunicationOracle Inter-Session Communication
Oracle Inter-Session Communication
Oren Nakdimon
 
How to upgrade your application with no downtime (using edition-based redefin...
How to upgrade your application with no downtime (using edition-based redefin...How to upgrade your application with no downtime (using edition-based redefin...
How to upgrade your application with no downtime (using edition-based redefin...
Oren Nakdimon
 
topic_perlcgi
topic_perlcgitopic_perlcgi
topic_perlcgi
tutorialsruby
 
Indexes and Indexing in Oracle 12c
Indexes and Indexing in Oracle 12cIndexes and Indexing in Oracle 12c
Indexes and Indexing in Oracle 12c
Oren Nakdimon
 
Bpel4 Ws 1.1 To Ws Bpel 2.0
Bpel4 Ws 1.1 To Ws Bpel 2.0Bpel4 Ws 1.1 To Ws Bpel 2.0
Bpel4 Ws 1.1 To Ws Bpel 2.0
Alexandre de Castro Alves
 
Drupal users group_symfony2
Drupal users group_symfony2Drupal users group_symfony2
Drupal users group_symfony2
Brian Zitzow
 
R3 tosrm attach
R3 tosrm attachR3 tosrm attach
R3 tosrm attach
Faina Fridman
 
Write Less (code) With More (Oracle Database 12c New Features)
Write Less (code) With More (Oracle Database 12c New Features)Write Less (code) With More (Oracle Database 12c New Features)
Write Less (code) With More (Oracle Database 12c New Features)
Oren Nakdimon
 
XML-Free Programming
XML-Free ProgrammingXML-Free Programming
XML-Free Programming
Stephen Chin
 

What's hot (11)

Seaside - The Revenge of Smalltalk
Seaside - The Revenge of SmalltalkSeaside - The Revenge of Smalltalk
Seaside - The Revenge of Smalltalk
 
Lecture3 php by okello erick
Lecture3 php by okello erickLecture3 php by okello erick
Lecture3 php by okello erick
 
Oracle Inter-Session Communication
Oracle Inter-Session CommunicationOracle Inter-Session Communication
Oracle Inter-Session Communication
 
How to upgrade your application with no downtime (using edition-based redefin...
How to upgrade your application with no downtime (using edition-based redefin...How to upgrade your application with no downtime (using edition-based redefin...
How to upgrade your application with no downtime (using edition-based redefin...
 
topic_perlcgi
topic_perlcgitopic_perlcgi
topic_perlcgi
 
Indexes and Indexing in Oracle 12c
Indexes and Indexing in Oracle 12cIndexes and Indexing in Oracle 12c
Indexes and Indexing in Oracle 12c
 
Bpel4 Ws 1.1 To Ws Bpel 2.0
Bpel4 Ws 1.1 To Ws Bpel 2.0Bpel4 Ws 1.1 To Ws Bpel 2.0
Bpel4 Ws 1.1 To Ws Bpel 2.0
 
Drupal users group_symfony2
Drupal users group_symfony2Drupal users group_symfony2
Drupal users group_symfony2
 
R3 tosrm attach
R3 tosrm attachR3 tosrm attach
R3 tosrm attach
 
Write Less (code) With More (Oracle Database 12c New Features)
Write Less (code) With More (Oracle Database 12c New Features)Write Less (code) With More (Oracle Database 12c New Features)
Write Less (code) With More (Oracle Database 12c New Features)
 
XML-Free Programming
XML-Free ProgrammingXML-Free Programming
XML-Free Programming
 

Similar to CommonMark: Markdown Done Right - ZendCon 2017

CommonMark: Markdown Done Right
CommonMark: Markdown Done RightCommonMark: Markdown Done Right
CommonMark: Markdown Done Right
Colin O'Dell
 
ngManila - Codename: Fireball - Hello World in Angular
ngManila - Codename: Fireball - Hello World in AngularngManila - Codename: Fireball - Hello World in Angular
ngManila - Codename: Fireball - Hello World in Angular
ngmanila
 
Introduction to league/commonmark
Introduction to league/commonmarkIntroduction to league/commonmark
Introduction to league/commonmark
Colin O'Dell
 
Serverless, The Middy Way - Workshop
Serverless, The Middy Way - WorkshopServerless, The Middy Way - Workshop
Serverless, The Middy Way - Workshop
Luciano Mammino
 
Import golang; struct microservice
Import golang; struct microserviceImport golang; struct microservice
Import golang; struct microservice
Giulio De Donato
 
Mojolicious
MojoliciousMojolicious
Mojolicious
Marcus Ramberg
 
MongoDB and Node.js
MongoDB and Node.jsMongoDB and Node.js
MongoDB and Node.js
Norberto Leite
 
Mojolicious - A new hope
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hope
Marcus Ramberg
 
Php Documentor The Beauty And The Beast
Php Documentor The Beauty And The BeastPhp Documentor The Beauty And The Beast
Php Documentor The Beauty And The Beast
Bastian Feder
 
AWS re:Invent 2016: Amazon ECR Deep Dive on Image Optimization (CON401)
AWS re:Invent 2016: Amazon ECR Deep Dive on Image Optimization (CON401)AWS re:Invent 2016: Amazon ECR Deep Dive on Image Optimization (CON401)
AWS re:Invent 2016: Amazon ECR Deep Dive on Image Optimization (CON401)
Amazon Web Services
 
Automatisation in development and testing - within budget
Automatisation in development and testing - within budgetAutomatisation in development and testing - within budget
Automatisation in development and testing - within budget
David Lukac
 
SH 1 - SES 4 - Microservices - Andrew Morgan TLV.pptx
SH 1 - SES 4 - Microservices - Andrew Morgan TLV.pptxSH 1 - SES 4 - Microservices - Andrew Morgan TLV.pptx
SH 1 - SES 4 - Microservices - Andrew Morgan TLV.pptx
MongoDB
 
Remote Config REST API and Versioning
Remote Config REST API and VersioningRemote Config REST API and Versioning
Remote Config REST API and Versioning
Jumpei Matsuda
 
Webinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.jsWebinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.js
MongoDB
 
Webinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.jsWebinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.js
MongoDB
 
Building full-stack Node.js web apps with Visual Studio Code
Building full-stack Node.js web apps with Visual Studio CodeBuilding full-stack Node.js web apps with Visual Studio Code
Building full-stack Node.js web apps with Visual Studio Code
Microsoft Tech Community
 
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
Antonio Peric-Mazar
 
Powering Microservices with Docker, Kubernetes, Kafka, and MongoDB
Powering Microservices with Docker, Kubernetes, Kafka, and MongoDBPowering Microservices with Docker, Kubernetes, Kafka, and MongoDB
Powering Microservices with Docker, Kubernetes, Kafka, and MongoDB
MongoDB
 
The Berkshelf Way
The Berkshelf WayThe Berkshelf Way
The Berkshelf Way
Chef Software, Inc.
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
Hugo Hamon
 

Similar to CommonMark: Markdown Done Right - ZendCon 2017 (20)

CommonMark: Markdown Done Right
CommonMark: Markdown Done RightCommonMark: Markdown Done Right
CommonMark: Markdown Done Right
 
ngManila - Codename: Fireball - Hello World in Angular
ngManila - Codename: Fireball - Hello World in AngularngManila - Codename: Fireball - Hello World in Angular
ngManila - Codename: Fireball - Hello World in Angular
 
Introduction to league/commonmark
Introduction to league/commonmarkIntroduction to league/commonmark
Introduction to league/commonmark
 
Serverless, The Middy Way - Workshop
Serverless, The Middy Way - WorkshopServerless, The Middy Way - Workshop
Serverless, The Middy Way - Workshop
 
Import golang; struct microservice
Import golang; struct microserviceImport golang; struct microservice
Import golang; struct microservice
 
Mojolicious
MojoliciousMojolicious
Mojolicious
 
MongoDB and Node.js
MongoDB and Node.jsMongoDB and Node.js
MongoDB and Node.js
 
Mojolicious - A new hope
Mojolicious - A new hopeMojolicious - A new hope
Mojolicious - A new hope
 
Php Documentor The Beauty And The Beast
Php Documentor The Beauty And The BeastPhp Documentor The Beauty And The Beast
Php Documentor The Beauty And The Beast
 
AWS re:Invent 2016: Amazon ECR Deep Dive on Image Optimization (CON401)
AWS re:Invent 2016: Amazon ECR Deep Dive on Image Optimization (CON401)AWS re:Invent 2016: Amazon ECR Deep Dive on Image Optimization (CON401)
AWS re:Invent 2016: Amazon ECR Deep Dive on Image Optimization (CON401)
 
Automatisation in development and testing - within budget
Automatisation in development and testing - within budgetAutomatisation in development and testing - within budget
Automatisation in development and testing - within budget
 
SH 1 - SES 4 - Microservices - Andrew Morgan TLV.pptx
SH 1 - SES 4 - Microservices - Andrew Morgan TLV.pptxSH 1 - SES 4 - Microservices - Andrew Morgan TLV.pptx
SH 1 - SES 4 - Microservices - Andrew Morgan TLV.pptx
 
Remote Config REST API and Versioning
Remote Config REST API and VersioningRemote Config REST API and Versioning
Remote Config REST API and Versioning
 
Webinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.jsWebinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.js
 
Webinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.jsWebinar: Building Your First App in Node.js
Webinar: Building Your First App in Node.js
 
Building full-stack Node.js web apps with Visual Studio Code
Building full-stack Node.js web apps with Visual Studio CodeBuilding full-stack Node.js web apps with Visual Studio Code
Building full-stack Node.js web apps with Visual Studio Code
 
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
 
Powering Microservices with Docker, Kubernetes, Kafka, and MongoDB
Powering Microservices with Docker, Kubernetes, Kafka, and MongoDBPowering Microservices with Docker, Kubernetes, Kafka, and MongoDB
Powering Microservices with Docker, Kubernetes, Kafka, and MongoDB
 
The Berkshelf Way
The Berkshelf WayThe Berkshelf Way
The Berkshelf Way
 
Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2Build powerfull and smart web applications with Symfony2
Build powerfull and smart web applications with Symfony2
 

More from Colin O'Dell

Demystifying Unicode - Longhorn PHP 2021
Demystifying Unicode - Longhorn PHP 2021Demystifying Unicode - Longhorn PHP 2021
Demystifying Unicode - Longhorn PHP 2021
Colin 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 2021
Colin 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 2019
Colin O'Dell
 
Debugging Effectively - ConFoo Montreal 2019
Debugging Effectively - ConFoo Montreal 2019Debugging Effectively - ConFoo Montreal 2019
Debugging Effectively - ConFoo Montreal 2019
Colin 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] 2018
Colin 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] 2018
Colin O'Dell
 
Debugging Effectively - DrupalCon Nashville 2018
Debugging Effectively - DrupalCon Nashville 2018Debugging Effectively - DrupalCon Nashville 2018
Debugging Effectively - DrupalCon Nashville 2018
Colin 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 2017
Colin O'Dell
 
Debugging Effectively - All Things Open 2017
Debugging Effectively - All Things Open 2017Debugging Effectively - All Things Open 2017
Debugging Effectively - All Things Open 2017
Colin 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 2017
Colin O'Dell
 
Debugging Effectively - PHP UK 2017
Debugging Effectively - PHP UK 2017Debugging Effectively - PHP UK 2017
Debugging Effectively - PHP UK 2017
Colin O'Dell
 
Debugging Effectively - SunshinePHP 2017
Debugging Effectively - SunshinePHP 2017Debugging Effectively - SunshinePHP 2017
Debugging Effectively - SunshinePHP 2017
Colin 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] 2016
Colin 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] 2016
Colin O'Dell
 
Debugging Effectively - ZendCon 2016
Debugging Effectively - ZendCon 2016Debugging Effectively - ZendCon 2016
Debugging Effectively - ZendCon 2016
Colin 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 2016
Colin 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 2016
Colin O'Dell
 
Debugging Effectively - DrupalCon Europe 2016
Debugging Effectively - DrupalCon Europe 2016Debugging Effectively - DrupalCon Europe 2016
Debugging Effectively - DrupalCon Europe 2016
Colin 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/16
Colin O'Dell
 
Debugging Effectively
Debugging EffectivelyDebugging Effectively
Debugging Effectively
Colin 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

Beginner's Guide to Observability@Devoxx PL 2024
Beginner's  Guide to Observability@Devoxx PL 2024Beginner's  Guide to Observability@Devoxx PL 2024
Beginner's Guide to Observability@Devoxx PL 2024
michniczscribd
 
Software Test Automation - A Comprehensive Guide on Automated Testing.pdf
Software Test Automation - A Comprehensive Guide on Automated Testing.pdfSoftware Test Automation - A Comprehensive Guide on Automated Testing.pdf
Software Test Automation - A Comprehensive Guide on Automated Testing.pdf
kalichargn70th171
 
Microsoft-Power-Platform-Adoption-Planning.pptx
Microsoft-Power-Platform-Adoption-Planning.pptxMicrosoft-Power-Platform-Adoption-Planning.pptx
Microsoft-Power-Platform-Adoption-Planning.pptx
jrodriguezq3110
 
Alluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio Webinar | 10x Faster Trino Queries on Your Data PlatformAlluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio, Inc.
 
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
Luigi Fugaro
 
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom KittEnhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Peter Caitens
 
美洲杯赔率投注网【​网址​🎉3977·EE​🎉】
美洲杯赔率投注网【​网址​🎉3977·EE​🎉】美洲杯赔率投注网【​网址​🎉3977·EE​🎉】
美洲杯赔率投注网【​网址​🎉3977·EE​🎉】
widenerjobeyrl638
 
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptxMigration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
ervikas4
 
Orca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container OrchestrationOrca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container Orchestration
Pedro J. Molina
 
Going AOT: Everything you need to know about GraalVM for Java applications
Going AOT: Everything you need to know about GraalVM for Java applicationsGoing AOT: Everything you need to know about GraalVM for Java applications
Going AOT: Everything you need to know about GraalVM for Java applications
Alina Yurenko
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Paul Brebner
 
Modelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - AmsterdamModelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - Amsterdam
Alberto Brandolini
 
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSISDECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
Tier1 app
 
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptxOperational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
sandeepmenon62
 
What is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdfWhat is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdf
kalichargn70th171
 
14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision
ShulagnaSarkar2
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
gapen1
 
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
Bert Jan Schrijver
 
Ensuring Efficiency and Speed with Practical Solutions for Clinical Operations
Ensuring Efficiency and Speed with Practical Solutions for Clinical OperationsEnsuring Efficiency and Speed with Practical Solutions for Clinical Operations
Ensuring Efficiency and Speed with Practical Solutions for Clinical Operations
OnePlan Solutions
 

Recently uploaded (20)

Beginner's Guide to Observability@Devoxx PL 2024
Beginner's  Guide to Observability@Devoxx PL 2024Beginner's  Guide to Observability@Devoxx PL 2024
Beginner's Guide to Observability@Devoxx PL 2024
 
Software Test Automation - A Comprehensive Guide on Automated Testing.pdf
Software Test Automation - A Comprehensive Guide on Automated Testing.pdfSoftware Test Automation - A Comprehensive Guide on Automated Testing.pdf
Software Test Automation - A Comprehensive Guide on Automated Testing.pdf
 
Microsoft-Power-Platform-Adoption-Planning.pptx
Microsoft-Power-Platform-Adoption-Planning.pptxMicrosoft-Power-Platform-Adoption-Planning.pptx
Microsoft-Power-Platform-Adoption-Planning.pptx
 
Alluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio Webinar | 10x Faster Trino Queries on Your Data PlatformAlluxio Webinar | 10x Faster Trino Queries on Your Data Platform
Alluxio Webinar | 10x Faster Trino Queries on Your Data Platform
 
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
WMF 2024 - Unlocking the Future of Data Powering Next-Gen AI with Vector Data...
 
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom KittEnhanced Screen Flows UI/UX using SLDS with Tom Kitt
Enhanced Screen Flows UI/UX using SLDS with Tom Kitt
 
美洲杯赔率投注网【​网址​🎉3977·EE​🎉】
美洲杯赔率投注网【​网址​🎉3977·EE​🎉】美洲杯赔率投注网【​网址​🎉3977·EE​🎉】
美洲杯赔率投注网【​网址​🎉3977·EE​🎉】
 
bgiolcb
bgiolcbbgiolcb
bgiolcb
 
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptxMigration From CH 1.0 to CH 2.0 and  Mule 4.6 & Java 17 Upgrade.pptx
Migration From CH 1.0 to CH 2.0 and Mule 4.6 & Java 17 Upgrade.pptx
 
Orca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container OrchestrationOrca: Nocode Graphical Editor for Container Orchestration
Orca: Nocode Graphical Editor for Container Orchestration
 
Going AOT: Everything you need to know about GraalVM for Java applications
Going AOT: Everything you need to know about GraalVM for Java applicationsGoing AOT: Everything you need to know about GraalVM for Java applications
Going AOT: Everything you need to know about GraalVM for Java applications
 
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
Why Apache Kafka Clusters Are Like Galaxies (And Other Cosmic Kafka Quandarie...
 
Modelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - AmsterdamModelling Up - DDDEurope 2024 - Amsterdam
Modelling Up - DDDEurope 2024 - Amsterdam
 
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSISDECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
DECODING JAVA THREAD DUMPS: MASTER THE ART OF ANALYSIS
 
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptxOperational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
Operational ease MuleSoft and Salesforce Service Cloud Solution v1.0.pptx
 
What is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdfWhat is Continuous Testing in DevOps - A Definitive Guide.pdf
What is Continuous Testing in DevOps - A Definitive Guide.pdf
 
14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision14 th Edition of International conference on computer vision
14 th Edition of International conference on computer vision
 
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
如何办理(hull学位证书)英国赫尔大学毕业证硕士文凭原版一模一样
 
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
J-Spring 2024 - Going serverless with Quarkus, GraalVM native images and AWS ...
 
Ensuring Efficiency and Speed with Practical Solutions for Clinical Operations
Ensuring Efficiency and Speed with Practical Solutions for Clinical OperationsEnsuring Efficiency and Speed with Practical Solutions for Clinical Operations
Ensuring Efficiency and Speed with Practical Solutions for Clinical Operations
 

CommonMark: Markdown Done Right - ZendCon 2017

  • 2. COLIN O’DELL Creator & Maintainer of league/commonmark Lead Web Developer at Unleashed Technologies Author of PHP 7 Migration Guide e-book @colinodel l
  • 3. LEAGUE/COMMONMARK A well-written, super-configurable Markdown parser for PHP based on the CommonMark spec. @colinodel l
  • 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 @colinodel l
  • 5. HISTORY OF MARKDOWN Hello ZendCon! -------------- Markdown is **awesome**! 1. Foo 2. Bar 3. Baz Wikipedia entry: <https://en.wikipedia.org/wiki/Markdown> @colinodel l
  • 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 @colinodel l
  • 7. 68+ DIFFERENT FLAVORS Source: https://github.com/markdown/markdown.github.com/wiki/Implementations Actuarius Blackfriday BlueCloth BlueFeather cebe/markdown CocoaMarkdown CommonMark 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 @colinodel l
  • 9. WHY IS IT NEEDED? *I love Markdown* <p><em>I love Markdown</em></p> @colinodel l
  • 10. WHY IS IT NEEDED? *I *love* Markdown* @colinodel l
  • 11. WHY IS IT NEEDED? Source: http://johnmacfarlane.net/babelmark2/
  • 12. 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/ @colinodel l
  • 13. WHY IS IT NEEDED? 1. > Hello World! ------ Source: http://johnmacfarlane.net/babelmark2/
  • 14. WHY IS IT NEEDED? 1. > Hello World! ------ Source: http://johnmacfarlane.net/babelmark2/
  • 15. WHY IS IT NEEDED? 1. > Hello World! ------ Source: http://johnmacfarlane.net/babelmark2/
  • 16. WHY IS IT NEEDED? 1. > Hello World! ------ Source: http://johnmacfarlane.net/babelmark2/
  • 17. WHY IS IT NEEDED? 1. > Hello World! ------ Source: http://johnmacfarlane.net/babelmark2/
  • 18. COMMONMARK IS… A strongly defined, highly compatible specification of Markdown. Written by people from Github, StackOverflow, Reddit, and others. Spec includes:  Strict rules (precedence, parsing order, handling edge cases)  Specific definitions (ex: “whitespace”, “punctuation”)  624 examples @colinodel l
  • 19.
  • 20.
  • 21.
  • 22.
  • 23. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable @colinodel l
  • 24. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable @colinodel l
  • 25. ADDING LEAGUE/COMMONMARK $ composer require league/commonmark:^0.15 <?php $converter = new CommonMarkConverter(); echo $converter->convertToHtml('Hello **ZendCon!**'); @colinodel l
  • 27. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable @colinodel l
  • 28. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable @colinodel l
  • 33. CONVERSION PROCESS Markdow n AST HTMLRenderParse Add your own custom parser, processor, or renderer @colinodel l
  • 34. EXAMPLE 1: CUSTOM PARSER <http://www.zendcon.com> <a href="http://www.zendcon.com"> http://www.zendcon.com </a> <@colinodell> <a href="https://twitter.com/colinodell"> @colinodell </a> @colinodel l
  • 35. class TwitterUsernameAutolinkParser extends AbstractInlineParser { public function getCharacters() { return ['<']; } public function parse(InlineParserContext $inlineContext) { // TODO } } @colinodel l
  • 36. CURSOR Learning CommonMark with <@colinodell>! public function getCharacters() { return ['<']; } @colinodel l
  • 37. class TwitterUsernameAutolinkParser extends AbstractInlineParser { public function getCharacters() { return ['<']; } public function parse(InlineParserContext $inlineContext) { $cursor = $inlineContext->getCursor(); } } @colinodel l
  • 38. CURSOR Learning CommonMark with <@colinodell>! getCharacter() getFirstNonSpaceCharacter( ) getRemainder() getLine() getPosition() advance() advanceBy($count) advanceBySpaceOrTab() advanceWhileMatches($char ) advanceToFirstNonSpace() isIndented() isAtEnd() match($regex) peek($count) @colinodel l
  • 39. CURSOR Learning CommonMark with <@colinodell>! getCharacter() getFirstNonSpaceCharacter( ) getRemainder() getLine() getPosition() advance() advanceBy($count) advanceBySpaceOrTab() advanceWhileMatches($char ) advanceToFirstNonSpace() isIndented() isAtEnd() match($regex) peek($count) @colinodel l
  • 40. 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_]+>/ @colinodel l
  • 41. 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; } } @colinodel l
  • 42. $environment = Environment::createCommonMarkEnvironment(); $environment->addInlineParser( new TwitterHandleParser() ); $converter = new CommonMarkConverter($environment); $html = $converter->convertToHtml( "Follow <@colinodell> on Twitter!" ); @colinodel l
  • 43. EXAMPLE 2: CUSTOM AST PROCESSOR <document> <paragraph> <link destination="http://www.zendcon.com"> <text>http://www.zendcon.com</text> </link> </paragraph> </document> <document> <paragraph> <link destination="https://bit.ly/foo"> <text>http://www.zendcon.com</text> </link> </paragraph> </document> @colinodel l
  • 44. 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); } } } } @colinodel l
  • 45. $environment = Environment::createCommonMarkEnvironment(); $environment->addDocumentProcessor( new ShortenLinkProcessor() ); $converter = new CommonMarkConverter($environment); $html = $converter->convertToHtml( "Schedule: <http://www.zendcon.com/schedule>" ); EXAMPLE 2: CUSTOM AST PROCESSOR @colinodel l
  • 46. 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" /> @colinodel l
  • 47. EXAMPLE 3: CUSTOM RENDERER class ImageHorizontalRuleRenderer implements BlockRendererInterface { public function render(...) { return new HtmlElement('img', ['src' => 'hr.png']); } } @colinodel l
  • 48. $environment = Environment::createCommonMarkEnvironment(); $environment->addBlockRenderer( LeagueCommonMarkBlockElementThematicBreak::class, new ImageHorizontalRuleRenderer() ); $converter = new CommonMarkConverter($environment); $html = $converter->convertToHtml("Hello World!nn-----"); EXAMPLE 3: CUSTOM RENDERER @colinodel l
  • 49. 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()]; } } @colinodel l
  • 50. BUNDLING INTO AN EXTENSION $environment = Environment::createCommonMarkEnvironment(); $environment->addExtension(new MyCustomExtension()); $converter = new CommonMarkConverter($environment); $html = $converter->convertToHtml("..."); @colinodel l
  • 51. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable @colinodel l
  • 52. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable @colinodel l
  • 53. WELL-TESTED  94% code coverage  Functional tests  All 624 spec examples  Library of regression tests  Unit tests  Cursor  Environment  Utility classes @colinodel l
  • 54. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable @colinodel l
  • 55. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable @colinodel l
  • 56. PERFORMANCE 0 20 40 60 80 Parsedown cebe/markdown gfm PHP Markdown Extra league/commonmark Time (ms) league/commonmark is ~22-24ms slower PHP 5.6 PHP 7.1 Tips: • Choose library based on your needs • Cache rendered HTML (100% boost) • Use PHP 7 (50% boost) • Optimize custom functionality @colinodel l
  • 57. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable @colinodel l
  • 58. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable @colinodel l
  • 59. STABILITY  Current version: 0.15.6  Conforms to CommonMark spec 0.28  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 are documented (see UPGRADING.md) @colinodel l
  • 60. FEATURES  100% compliance with the CommonMark spec  Easy to implement  Easy to customize  Well-tested  Decent performance  (Relatively) stable @colinodel l
  • 61. Installation & Documentation: http://github.com/thephpleague/commonmark Learn More About CommonMark: http://commonmark.org Slides / Feedback: https://joind.in/talk/8da74 @colinodell

Editor's Notes

  1. So what is league/commonmark?
  2. 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. OUT: Now I’ve mentioned the word CommonMark a few times, but what is that?
  3. In collaboration with Aaron Swartz
  4. 2. Informal; not like XML and XHTML which reject data simply because it fails to adhere to strict, unforgiving standards
  5. Straight-forward example of emphasizing text
  6. What happens if we add two asterisks?
  7. Babelmark2 John MacFarlane, CommonMark spec maintainer Like 3V4L, but for Markdown
  8. 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%)
  9. 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
  10. Actually 15 different ways that parsers interpret this 1/4 OUTRO: The CommonMark standard is designed to eliminate this ambiguity so that your Markdown is handled in a logical, predictable fashion
  11. 2/4
  12. 3/4
  13. 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
  14. We’re all familiar with the usual markdown syntax This specification dictates exactly how compliant parsers should handle Markdown input It includes Look at the spec
  15. What’s really cool: - Examples can easily be parsed out and tested against by our Markdown library!
  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()
  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. 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()
  26. 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 DESCRIBE METHODS HOW TO IMPLEMENT OUR TWITTER AUTOLINK PARSER?
  27. WE COULD TRY THIS
  28. BETTER
  29. 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
  30. 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
  31. What if we wanted to automatically shorten URLs with a service like bitly?
  32. Guaranteed to be compatible with all other CommonMark parsers in other languages
  33. Blinking your eye is 100ms
  34. 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!