From 757fd49daff31911e3fa45fd41bd2d5960364de8 Mon Sep 17 00:00:00 2001 From: Anthony Gaudino Date: Sun, 30 Sep 2012 10:44:31 -0300 Subject: [PATCH 1/3] Allows to use markdown tables, automatic table of contents and HTML --- app/helpers/gitlab_markdown_helper.rb | 17 +++++++++++- app/views/help/markdown.html.haml | 38 +++++++++++++++++++++++++++ lib/gitlab/markdown.rb | 2 +- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index 111982e9147..e44852342d0 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -24,9 +24,20 @@ module GitlabMarkdownHelper def markdown(text) unless @markdown + + # If the user wants TOC we run a Render::HTML_TOC + # See http://dev.af83.com/2012/02/27/howto-extend-the-redcarpet2-markdown-lib.html + toc = nil + if text.match("~toc~") != nil + html_toc = Redcarpet::Markdown.new(Redcarpet::Render::HTML_TOC, space_after_headers: true) + toc = html_toc.render(text) + + text["~toc~"]= "" + end + gitlab_renderer = Redcarpet::Render::GitlabHTML.new(self, # see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch- - filter_html: true, + filter_html: false, with_toc_data: true, hard_wrap: true) @markdown = Redcarpet::Markdown.new(gitlab_renderer, @@ -41,6 +52,10 @@ module GitlabMarkdownHelper superscript: true) end + if toc == nil @markdown.render(text).html_safe + else + (toc + @markdown.render(text)).html_safe + end end end diff --git a/app/views/help/markdown.html.haml b/app/views/help/markdown.html.haml index aa608ed6d9a..ba5964d1a23 100644 --- a/app/views/help/markdown.html.haml +++ b/app/views/help/markdown.html.haml @@ -60,6 +60,25 @@ GFM will autolink standard URLs you copy and paste into your text. So if you want to link to a URL (instead of a textual link), you can simply put the URL in verbatim and it will be turned into a link to that URL. + %h4 Tables + +.row + .span8 + %p + GFM will generate tables if you use PHP-Markdown Extra like syntax: + %pre= %Q{First Header | Second Header\n---------------|---------------\nContent Cell 1 | Content Cell 2\nContent Cell 3 | Content Cell 4\nContent Cell 5 | Content Cell 6} + %p becomes + = markdown %Q{First Header | Second Header\n---------------|---------------\nContent Cell 1 | Content Cell 2\nContent Cell 3 | Content Cell 4\nContent Cell 5 | Content Cell 6} + + .span4 + .alert.alert-info + %p + Consult the + %strong= link_to "PHP-Markdown Extra Tables", "http://michelf.ca/projects/php-markdown/extra/#table" + for more details. + +.row + .span8 %h4 Fenced code blocks %p @@ -71,6 +90,16 @@ %p becomes = markdown %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```} + %h4 Automatic table of contents (TOC) + + %p + GFM can create a table of contents (TOC) from all headers. + To use this feature you must add ~toc~ anywhere. Note that the TOC will always appear in the top above enything else. + + %pre= %Q{~toc~\n# Header 1\n## Header 2\n# Header 1} + %p becomes + = markdown %Q{* [Header 1](#toc_0)\n * [Header 2](#toc_1)\n* [Header 1](#toc_2)\n\n# Header 1\n## Header 2\n# Header 1} + %h4 Emoji .row @@ -94,6 +123,15 @@ .row .span8 + %h4 Custom HTML + + %p + If you still want to, you can use custom HTML for specific tasks. + + %pre= %Q{\n

This line is in HTML

\n
} + %p becomes + = markdown %Q{\n

This line is in HTML

\n
} + %h4 Special GitLab references %p diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 9eb35b84d42..436cf70635c 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -73,7 +73,7 @@ module Gitlab extractions[$1] end - sanitize text.html_safe, attributes: ActionView::Base.sanitized_allowed_attributes + %w(id class) + sanitize text.html_safe, attributes: ActionView::Base.sanitized_allowed_attributes + %w(id class), tags: ActionView::Base.sanitized_allowed_tags + %w(table tr td th) end private -- GitLab From 32657a5b7a4075a5a0505ebd36e41bb1459f47f5 Mon Sep 17 00:00:00 2001 From: Anthony Gaudino Date: Thu, 1 Nov 2012 13:27:05 -0300 Subject: [PATCH 2/3] ~toc~ must be placed on the first line of content --- app/helpers/gitlab_markdown_helper.rb | 4 ++-- app/views/help/markdown.html.haml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index e44852342d0..4600da20583 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -28,7 +28,7 @@ module GitlabMarkdownHelper # If the user wants TOC we run a Render::HTML_TOC # See http://dev.af83.com/2012/02/27/howto-extend-the-redcarpet2-markdown-lib.html toc = nil - if text.match("~toc~") != nil + if text.lines.first.match("~toc~") != nil html_toc = Redcarpet::Markdown.new(Redcarpet::Render::HTML_TOC, space_after_headers: true) toc = html_toc.render(text) @@ -53,7 +53,7 @@ module GitlabMarkdownHelper end if toc == nil - @markdown.render(text).html_safe + @markdown.render(text).html_safe else (toc + @markdown.render(text)).html_safe end diff --git a/app/views/help/markdown.html.haml b/app/views/help/markdown.html.haml index ba5964d1a23..b95ec2e7166 100644 --- a/app/views/help/markdown.html.haml +++ b/app/views/help/markdown.html.haml @@ -94,7 +94,7 @@ %p GFM can create a table of contents (TOC) from all headers. - To use this feature you must add ~toc~ anywhere. Note that the TOC will always appear in the top above enything else. + To use this feature you must add ~toc~ anywhere at the first line of your content. Note that the TOC will always appear in the top above enything else. %pre= %Q{~toc~\n# Header 1\n## Header 2\n# Header 1} %p becomes -- GitLab From fb813940df4a380fd2bb3ee494447465ce8d5429 Mon Sep 17 00:00:00 2001 From: Anthony Gaudino Date: Sun, 25 Nov 2012 20:14:31 -0300 Subject: [PATCH 3/3] Code refactoration as suggested by riyad --- app/helpers/gitlab_markdown_helper.rb | 18 ++-------------- app/views/help/markdown.html.haml | 6 +++--- lib/gitlab/markdown.rb | 30 +++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb index 4600da20583..e737f0a6b6b 100644 --- a/app/helpers/gitlab_markdown_helper.rb +++ b/app/helpers/gitlab_markdown_helper.rb @@ -24,17 +24,6 @@ module GitlabMarkdownHelper def markdown(text) unless @markdown - - # If the user wants TOC we run a Render::HTML_TOC - # See http://dev.af83.com/2012/02/27/howto-extend-the-redcarpet2-markdown-lib.html - toc = nil - if text.lines.first.match("~toc~") != nil - html_toc = Redcarpet::Markdown.new(Redcarpet::Render::HTML_TOC, space_after_headers: true) - toc = html_toc.render(text) - - text["~toc~"]= "" - end - gitlab_renderer = Redcarpet::Render::GitlabHTML.new(self, # see https://github.com/vmg/redcarpet#darling-i-packed-you-a-couple-renderers-for-lunch- filter_html: false, @@ -52,10 +41,7 @@ module GitlabMarkdownHelper superscript: true) end - if toc == nil - @markdown.render(text).html_safe - else - (toc + @markdown.render(text)).html_safe - end + @markdown.render(text).html_safe end end + diff --git a/app/views/help/markdown.html.haml b/app/views/help/markdown.html.haml index b95ec2e7166..97254d8f387 100644 --- a/app/views/help/markdown.html.haml +++ b/app/views/help/markdown.html.haml @@ -90,11 +90,11 @@ %p becomes = markdown %Q{```ruby\nrequire 'redcarpet'\nmarkdown = Redcarpet.new("Hello World!")\nputs markdown.to_html\n```} - %h4 Automatic table of contents (TOC) + %h4 Table of contents (TOC) generation %p - GFM can create a table of contents (TOC) from all headers. - To use this feature you must add ~toc~ anywhere at the first line of your content. Note that the TOC will always appear in the top above enything else. + GFM can automatically generate a TOC from the headers in the text. + To have the TOC generated just place ~toc~ on the first line. %pre= %Q{~toc~\n# Header 1\n## Header 2\n# Header 1} %p becomes diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb index 436cf70635c..e57812e6245 100644 --- a/lib/gitlab/markdown.rb +++ b/lib/gitlab/markdown.rb @@ -88,6 +88,7 @@ module Gitlab def parse(text) parse_references(text) if @project parse_emoji(text) + text = parse_toc(text) text end @@ -122,6 +123,35 @@ module Gitlab end end + # If the user wants TOC we run a Render::HTML_TOC + # See http://dev.af83.com/2012/02/27/howto-extend-the-redcarpet2-markdown-lib.html + # TODO: Allow TOC to be placed in the middle of the document, not only at top + def parse_toc(text) + if text.lines.first.match("~toc~") != nil + html_text = text.dup.to_str + + # First we must convert HTML headers back to Markdown headers + html_text.gsub!(/]*>/, "# ") + html_text.gsub!(/]*>/, "## ") + html_text.gsub!(/]*>/, "### ") + html_text.gsub!(/]*>/, "#### ") + html_text.gsub!(/]*>/, "##### ") + html_text.gsub!(/]*>/, "###### ") + + html_text.gsub!(/<\/?h\d[^>]*>/, "") + + + html_toc = Redcarpet::Markdown.new(Redcarpet::Render::HTML_TOC, space_after_headers: true) + toc = html_toc.render(html_text) + + text["~toc~"]= "" + + toc + text + else + text + end + end + # Private: Checks if an emoji icon exists in the image asset directory # # emoji - Identifier of the emoji as a string (e.g., "+1", "heart") -- GitLab