SlideShare a Scribd company logo
1 of 48
Download to read offline
My First Rails Plugin
     Marking up user content
The problem
Lots of websites invite
      user input.
Blogs
Forums
Wikis
‘Web 2.0’ sites
And they all have to
format it somehow.
There are some
existing solutions
‘Some HTML accepted’
Textile
Markdown
But asking users to pick
between them is confusing!
Some of the syntax is a
  bit unnatural too...
Textile
“Test”:http://www.test.com


# Ordered list
# Ordered list
Textile
Markdown
> This is a blockquote with two paragraphs. Lorem ipsum dolor sit amet,
> consectetuer adipiscing elit. Aliquam hendrerit mi posuere lectus.
> Vestibulum enim wisi, viverra nec, fringilla in, laoreet vitae, risus.
>
> Donec sit amet nisl. Aliquam semper ipsum sit amet velit. Suspendisse
> id sem consectetuer libero luctus adipiscing.


=> <blockquote><p>This is a blockquote with two paragraphs. Lorem ipsum
dolor sit amet, consectetuer adipiscing elit. Aliquam hendrerit mi
posuere lectus. Vestibulum enim wisi, viverra nec, fringilla in, laoreet
vitae, risus.</p></blockquote>
Users shouldn’t have to
think about the markup
        syntax!
Instead, interpret what
they’ve typed and make
   intelligent guesses!
I decided to write my
     own code...
...as a Ruby on Rails
        plugin
I want to support...
Paragraphs
Unordered lists
Ordered lists
Blockquotes
Code examples
Rails already has a
simple_format(text) helper
simple_format(text)

simple_format(“Hello.

Are you my mummy?”)

=> “<p>Hello.</p>

<p>Are you my mummy?</p>”
How does
simple_format work?
simple_format()
def simple_format(text, html_options={})
 start_tag = tag('p', html_options, true)

 text = text.to_s.dup
 text.gsub!(/rn?/, quot;nquot;)                     # rn and r -> n

 text.gsub!(/nn+/, quot;</p>nn#{start_tag}quot;)   # 2+ newline   -> paragraph
 text.gsub!(/([^n]n)(?=[^n])/, '1<br />') # 1 newline     -> br

 text.insert 0, start_tag
 text << quot;</p>quot;

end
So borrowing from
      that...
Dealing with newlines
def cleanup_newlines(text)
  text.gsub(/rn?/, quot;nquot;) # rn and r -> n
end
Block elements
Unordered list:   Blockquotes:
* Item            “To be, or not to
* Item            be.”
Ordered list:
1. Item
2. Item
Or
1) Item
2) Item
Block elements
def block_element_markup(text)
 blocks = text.split(quot;nnquot;)
 new_text = Array.new
 blocks.each do |block|
      # Work out what type of block element it is.
 end


 return new_text.join(quot;nnquot;)
end
Block elements
if block.match(/((^*s.*$n?)+)/)
  lines = Array.new
  block.each_line do |line|
      lines << line.gsub(/*s(.*)$/, '<li>1</li>')
  end
  new_text << content_tag(quot;ulquot;, quot;nquot; + lines.join(quot;quot;) + quot;nquot;)


elsif block.match(/((^d+[.)]s.*$n?)+)/)
  lines = Array.new
  block.each_line do |line|
      lines << line.gsub(/d+.s(.*)$/, '<li>1</li>')
  end
  new_text << content_tag(quot;olquot;, quot;nquot; + lines.join(quot;quot;) + quot;nquot;)


  ...
end
Block elements
elsif block.match(/^“.*”$/)
  new_text << content_tag(quot;blockquotequot;, content_tag(quot;pquot;, block.gsub(/
^“(.*)”$/, '1')))
  elsif block.match(/(^<code>.*</code>$)/)
  new_text << content_tag(quot;divquot;, block)
else
  new_text << content_tag(quot;pquot;, block)
end
Dealing with links...
def auto_link_urls(text, href_options = {})

  extra_options = tag_options(href_options.stringify_keys) || quot;quot;

  auto_link_re = %r{

   (                            # leading text

       <w+.*?>|                # leading HTML tag, or
       [^=!:'quot;/]|               # leading punctuation, or
       ^                        # beginning of line

   )

   (https?://|ftp://)                # protocol spec

   (

       [-w]+                   # subdomain or domain
       (?:.[-w]+)*            # remaining subdomains or domain
       (?::d+)?                # port
       (?:/(?:(?:[~w+@%-]|(?:[,.;:][^s$]))+)?)* # path
       (?:?[w+@%&=.;-]+)?     # query string
       (?:#[w-/]*)?           # trailing anchor

   )(([[:punct:]]|s|<|$))         # trailing text

  }x

  text.gsub(auto_link_re) do

      all, a, b, c, d = $&, $1, $2, $3, $5
      text = a + quot;<a href=quot;quot; + b + c + quot;quot;>quot; + truncate_in_middle(c, 40) + quot;</a>quot; + $5

  end

end
Truncate URLS in the
            middle...
def truncate_in_middle(text, length = 30, truncate_string = quot;...quot;)
  if text
      l = ((length - truncate_string.chars.length) / 2).to_int
      chars = text.chars
    return (chars.length > length ? chars[0...l] + truncate_string
+ chars[chars.length-l...chars.length] : text).to_s
  end
end
Detecting code snippets
 def mark_code(text)
   h(text).
   gsub(/(^&lt;[a-zA-Z]+.*$|&lt;[a-zA-Z]+.*&gt;)/) do
       text = quot;<code>quot; + ($1) + quot;</code>quot;
   end
 end


 <html>   => <code>&lt;html&gt;</code>
Detecting phone
            numbers
07736111111

=> <a tel=quot;07736111111quot;> 07736111111</a>
 def auto_link_phone_numbers(text)
   text.gsub(/(s|^)((0|+44)d{10,10})b/) do
     text = $1 + quot;<a href=quot;tel:quot; + $2 + quot;quot;>quot; + $2
 + quot;</a>quot;
   end
 end
Typography
quot; => “ / ”


' => ‘ / ’ (quote) / ’ (apos) / ' (prime)


... => …


etc...
Typography
gsub(/([^.])...([^.]|$)/, '1…2')


gsub(/([^s]+)quot;/, '1”')


gsub(/([^s]+)'(s)/, '1’2')


gsub(/([^s])'([^s])/, '1’2')


etc...
Tests!
Hosting




http://code.google.com/p/usertext/
Live demo!
http://www.usertext.org
What next?
What next?
•   Test on some real user input!
What next?
•   Test on some real user input!
•   Make it configurable
What next?
•   Test on some real user input!
•   Make it configurable
•   Port to PHP (for Wordpress)?
What next?
•   Test on some real user input!
•   Make it configurable
•   Port to PHP (for Wordpress)?
•   gem vs plugin?
What next?
•   Test on some real user input!
•   Make it configurable
•   Port to PHP (for Wordpress)?
•   gem vs plugin?
•   Get feedback from other developers.
Thanks...
Frankie Roberto
frankie@frankieroberto.com

More Related Content

What's hot

Perl.Hacks.On.Vim
Perl.Hacks.On.VimPerl.Hacks.On.Vim
Perl.Hacks.On.Vim
Lin Yo-An
 
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
Phil Calçado
 

What's hot (20)

Swift Programming Language
Swift Programming LanguageSwift Programming Language
Swift Programming Language
 
Let's build a parser!
Let's build a parser!Let's build a parser!
Let's build a parser!
 
Business Rules with Brick
Business Rules with BrickBusiness Rules with Brick
Business Rules with Brick
 
A Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming LanguageA Few Interesting Things in Apple's Swift Programming Language
A Few Interesting Things in Apple's Swift Programming Language
 
Zend Certification Preparation Tutorial
Zend Certification Preparation TutorialZend Certification Preparation Tutorial
Zend Certification Preparation Tutorial
 
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur..."How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
"How was it to switch from beautiful Perl to horrible JavaScript", Viktor Tur...
 
Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)Lisp Macros in 20 Minutes (Featuring Clojure)
Lisp Macros in 20 Minutes (Featuring Clojure)
 
Perl.Hacks.On.Vim
Perl.Hacks.On.VimPerl.Hacks.On.Vim
Perl.Hacks.On.Vim
 
Extreme Swift
Extreme SwiftExtreme Swift
Extreme Swift
 
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
(ThoughtWorks Away Day 2009) one or two things you may not know about typesys...
 
Taking Inspiration From The Functional World
Taking Inspiration From The Functional WorldTaking Inspiration From The Functional World
Taking Inspiration From The Functional World
 
RubyConf Portugal 2014 - Why ruby must go!
RubyConf Portugal 2014 - Why ruby must go!RubyConf Portugal 2014 - Why ruby must go!
RubyConf Portugal 2014 - Why ruby must go!
 
MISC TOPICS #2: I18n Data Programming Pearls Random Records Rpx Now Susher St...
MISC TOPICS #2: I18n Data Programming Pearls Random Records Rpx Now Susher St...MISC TOPICS #2: I18n Data Programming Pearls Random Records Rpx Now Susher St...
MISC TOPICS #2: I18n Data Programming Pearls Random Records Rpx Now Susher St...
 
[Erlang LT] Regexp Perl And Port
[Erlang LT] Regexp Perl And Port[Erlang LT] Regexp Perl And Port
[Erlang LT] Regexp Perl And Port
 
The Curious Clojurist - Neal Ford (Thoughtworks)
The Curious Clojurist - Neal Ford (Thoughtworks)The Curious Clojurist - Neal Ford (Thoughtworks)
The Curious Clojurist - Neal Ford (Thoughtworks)
 
Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2Lambdas and Streams Master Class Part 2
Lambdas and Streams Master Class Part 2
 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...
 
27. mathematical, date and time functions in VB Script
27. mathematical, date and time  functions in VB Script27. mathematical, date and time  functions in VB Script
27. mathematical, date and time functions in VB Script
 
Lenses
LensesLenses
Lenses
 
C++ L08-Classes Part1
C++ L08-Classes Part1C++ L08-Classes Part1
C++ L08-Classes Part1
 

Viewers also liked

Gå hjem møde oplæg den social organisation
Gå hjem møde oplæg den social organisationGå hjem møde oplæg den social organisation
Gå hjem møde oplæg den social organisation
Martin Christensen
 
Presentacion JAU CEDEMI
Presentacion JAU CEDEMIPresentacion JAU CEDEMI
Presentacion JAU CEDEMI
putikri
 
Lineamientos discapacidad cognitiva1
Lineamientos discapacidad cognitiva1Lineamientos discapacidad cognitiva1
Lineamientos discapacidad cognitiva1
magayagabe
 
Catálogo Corporativo Columbus IT
Catálogo Corporativo Columbus ITCatálogo Corporativo Columbus IT
Catálogo Corporativo Columbus IT
ColumbusSpain
 

Viewers also liked (8)

Netbiblioseminar2009
Netbiblioseminar2009Netbiblioseminar2009
Netbiblioseminar2009
 
Chapter 4 Summary
Chapter 4 SummaryChapter 4 Summary
Chapter 4 Summary
 
Gå hjem møde oplæg den social organisation
Gå hjem møde oplæg den social organisationGå hjem møde oplæg den social organisation
Gå hjem møde oplæg den social organisation
 
Presentacion JAU CEDEMI
Presentacion JAU CEDEMIPresentacion JAU CEDEMI
Presentacion JAU CEDEMI
 
Lineamientos discapacidad cognitiva1
Lineamientos discapacidad cognitiva1Lineamientos discapacidad cognitiva1
Lineamientos discapacidad cognitiva1
 
Escrito presentado ó Alcalde
Escrito presentado ó AlcaldeEscrito presentado ó Alcalde
Escrito presentado ó Alcalde
 
Taller
TallerTaller
Taller
 
Catálogo Corporativo Columbus IT
Catálogo Corporativo Columbus ITCatálogo Corporativo Columbus IT
Catálogo Corporativo Columbus IT
 

Similar to My First Rails Plugin - Usertext

Os Fetterupdated
Os FetterupdatedOs Fetterupdated
Os Fetterupdated
oscon2007
 
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
Carles Farré
 
Building Web Interface On Rails
Building Web Interface On RailsBuilding Web Interface On Rails
Building Web Interface On Rails
Wen-Tien Chang
 
Ruby 程式語言簡介
Ruby 程式語言簡介Ruby 程式語言簡介
Ruby 程式語言簡介
Wen-Tien Chang
 
JavaScript and jQuery Fundamentals
JavaScript and jQuery FundamentalsJavaScript and jQuery Fundamentals
JavaScript and jQuery Fundamentals
BG Java EE Course
 
Html and i_phone_mobile-2
Html and i_phone_mobile-2Html and i_phone_mobile-2
Html and i_phone_mobile-2
tonvanbart
 

Similar to My First Rails Plugin - Usertext (20)

Lettering js
Lettering jsLettering js
Lettering js
 
Os Fetterupdated
Os FetterupdatedOs Fetterupdated
Os Fetterupdated
 
Out with Regex, In with Tokens
Out with Regex, In with TokensOut with Regex, In with Tokens
Out with Regex, In with Tokens
 
Scala 3camp 2011
Scala   3camp 2011Scala   3camp 2011
Scala 3camp 2011
 
Writing DSLs with Parslet - Wicked Good Ruby Conf
Writing DSLs with Parslet - Wicked Good Ruby ConfWriting DSLs with Parslet - Wicked Good Ruby Conf
Writing DSLs with Parslet - Wicked Good Ruby Conf
 
Scala 2 + 2 > 4
Scala 2 + 2 > 4Scala 2 + 2 > 4
Scala 2 + 2 > 4
 
Django - Framework web para perfeccionistas com prazos
Django - Framework web para perfeccionistas com prazosDjango - Framework web para perfeccionistas com prazos
Django - Framework web para perfeccionistas com prazos
 
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
[DSBW Spring 2009] Unit 07: WebApp Design Patterns & Frameworks (3/3)
 
Php Sq Lite
Php Sq LitePhp Sq Lite
Php Sq Lite
 
Building Web Interface On Rails
Building Web Interface On RailsBuilding Web Interface On Rails
Building Web Interface On Rails
 
JavaScript
JavaScriptJavaScript
JavaScript
 
Introduction to JQuery
Introduction to JQueryIntroduction to JQuery
Introduction to JQuery
 
Adventurous Merb
Adventurous MerbAdventurous Merb
Adventurous Merb
 
Ruby 程式語言簡介
Ruby 程式語言簡介Ruby 程式語言簡介
Ruby 程式語言簡介
 
Rack Middleware
Rack MiddlewareRack Middleware
Rack Middleware
 
JavaScript and jQuery Fundamentals
JavaScript and jQuery FundamentalsJavaScript and jQuery Fundamentals
JavaScript and jQuery Fundamentals
 
More Secrets of JavaScript Libraries
More Secrets of JavaScript LibrariesMore Secrets of JavaScript Libraries
More Secrets of JavaScript Libraries
 
Html and i_phone_mobile-2
Html and i_phone_mobile-2Html and i_phone_mobile-2
Html and i_phone_mobile-2
 
What's new in Rails 2?
What's new in Rails 2?What's new in Rails 2?
What's new in Rails 2?
 
Dealing with Legacy Perl Code - Peter Scott
Dealing with Legacy Perl Code - Peter ScottDealing with Legacy Perl Code - Peter Scott
Dealing with Legacy Perl Code - Peter Scott
 

Recently uploaded

Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Victor Rentea
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 

Recently uploaded (20)

DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 AmsterdamDEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
DEV meet-up UiPath Document Understanding May 7 2024 Amsterdam
 
Vector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptxVector Search -An Introduction in Oracle Database 23ai.pptx
Vector Search -An Introduction in Oracle Database 23ai.pptx
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
Modular Monolith - a Practical Alternative to Microservices @ Devoxx UK 2024
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot ModelMcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
Mcleodganj Call Girls 🥰 8617370543 Service Offer VIP Hot Model
 
Artificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : UncertaintyArtificial Intelligence Chap.5 : Uncertainty
Artificial Intelligence Chap.5 : Uncertainty
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Exploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with MilvusExploring Multimodal Embeddings with Milvus
Exploring Multimodal Embeddings with Milvus
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
WSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering DevelopersWSO2's API Vision: Unifying Control, Empowering Developers
WSO2's API Vision: Unifying Control, Empowering Developers
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​Elevate Developer Efficiency & build GenAI Application with Amazon Q​
Elevate Developer Efficiency & build GenAI Application with Amazon Q​
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Six Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal OntologySix Myths about Ontologies: The Basics of Formal Ontology
Six Myths about Ontologies: The Basics of Formal Ontology
 
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 

My First Rails Plugin - Usertext