From 7e3ff1852340c33f5b8853190d6a24813d5920a2 Mon Sep 17 00:00:00 2001 From: Ebrahim Byagowi Date: Sun, 11 Sep 2016 20:38:09 +0430 Subject: [PATCH] Add RTL support to markdown renderer --- CHANGELOG | 1 + app/assets/stylesheets/framework/typography.scss | 13 +++++++++++++ lib/banzai/filter/set_direction_filter.rb | 15 +++++++++++++++ lib/banzai/pipeline/gfm_pipeline.rb | 4 +++- spec/features/atom/users_spec.rb | 2 +- spec/lib/banzai/object_renderer_spec.rb | 6 +++--- .../banzai/pipeline/description_pipeline_spec.rb | 12 +++++++++--- spec/models/concerns/cache_markdown_field_spec.rb | 2 +- 8 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 lib/banzai/filter/set_direction_filter.rb diff --git a/CHANGELOG b/CHANGELOG index e3201cd2250..76b483d9019 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -55,6 +55,7 @@ v 8.13.0 (unreleased) - Added soft wrap button to repository file/blob editor - Update namespace validation to forbid reserved names (.git and .atom) (Will Starms) - Show the time ago a merge request was deployed to an environment + - Add RTL support to markdown renderer (Ebrahim Byagowi) - Add word-wrap to issue title on issue and milestone boards (ClemMakesApps) - Fix todos page mobile viewport layout (ClemMakesApps) - Fix inconsistent highlighting of already selected activity nav-links (ClemMakesApps) diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index 8df0067fac1..287653beac5 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -90,6 +90,11 @@ border-left: 3px solid #e7e9ed; } + blockquote:dir(rtl) { + border-left: 0; + border-right: 3px solid #e7e9ed; + } + blockquote p { color: #7f8fa4 !important; font-size: inherit; @@ -112,6 +117,10 @@ } } + table:dir(rtl) th { + text-align: right; + } + pre { margin: 12px 0; font-size: 13px; @@ -129,6 +138,10 @@ margin: 3px 0 3px 28px !important; } + ul:dir(rtl), ol:dir(rtl) { + margin: 3px 28px 3px 0 !important; + } + li { line-height: 1.6em; } diff --git a/lib/banzai/filter/set_direction_filter.rb b/lib/banzai/filter/set_direction_filter.rb new file mode 100644 index 00000000000..c2976aeb7c6 --- /dev/null +++ b/lib/banzai/filter/set_direction_filter.rb @@ -0,0 +1,15 @@ +module Banzai + module Filter + # HTML filter that sets dir="auto" for RTL languages support + class SetDirectionFilter < HTML::Pipeline::Filter + def call + # select these elements just on top level of the document + doc.xpath('p|h1|h2|h3|h4|h5|h6|ol|ul[not(@class="section-nav")]|blockquote|table').each do |el| + el['dir'] = 'auto' + end + + doc + end + end + end +end diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb index 8d94b199c66..5da2d0b008c 100644 --- a/lib/banzai/pipeline/gfm_pipeline.rb +++ b/lib/banzai/pipeline/gfm_pipeline.rb @@ -25,7 +25,9 @@ module Banzai Filter::MilestoneReferenceFilter, Filter::TaskListFilter, - Filter::InlineDiffFilter + Filter::InlineDiffFilter, + + Filter::SetDirectionFilter ] end diff --git a/spec/features/atom/users_spec.rb b/spec/features/atom/users_spec.rb index a8833194421..f8c3ccb416b 100644 --- a/spec/features/atom/users_spec.rb +++ b/spec/features/atom/users_spec.rb @@ -53,7 +53,7 @@ describe "User Feed", feature: true do end it 'has XHTML summaries in issue descriptions' do - expect(body).to match /we have a bug!<\/p>\n\n
\n\n

I guess/ + expect(body).to match /we have a bug!<\/p>\n\n


\n\n

I guess/ end it 'has XHTML summaries in notes' do diff --git a/spec/lib/banzai/object_renderer_spec.rb b/spec/lib/banzai/object_renderer_spec.rb index 90da78a67dd..6bcda87c999 100644 --- a/spec/lib/banzai/object_renderer_spec.rb +++ b/spec/lib/banzai/object_renderer_spec.rb @@ -24,7 +24,7 @@ describe Banzai::ObjectRenderer do with(an_instance_of(Array)). and_call_original - expect(object).to receive(:redacted_note_html=).with('

hello

') + expect(object).to receive(:redacted_note_html=).with('

hello

') expect(object).to receive(:user_visible_reference_count=).with(0) renderer.render([object], :note) @@ -92,10 +92,10 @@ describe Banzai::ObjectRenderer do docs = renderer.render_attributes(objects, :note) expect(docs[0]).to be_an_instance_of(Nokogiri::HTML::DocumentFragment) - expect(docs[0].to_html).to eq('

hello

') + expect(docs[0].to_html).to eq('

hello

') expect(docs[1]).to be_an_instance_of(Nokogiri::HTML::DocumentFragment) - expect(docs[1].to_html).to eq('

bye

') + expect(docs[1].to_html).to eq('

bye

') end it 'returns when no objects to render' do diff --git a/spec/lib/banzai/pipeline/description_pipeline_spec.rb b/spec/lib/banzai/pipeline/description_pipeline_spec.rb index 76f42071810..8cce1b96698 100644 --- a/spec/lib/banzai/pipeline/description_pipeline_spec.rb +++ b/spec/lib/banzai/pipeline/description_pipeline_spec.rb @@ -4,11 +4,11 @@ describe Banzai::Pipeline::DescriptionPipeline do def parse(html) # When we pass HTML to Redcarpet, it gets wrapped in `p` tags... # ...except when we pass it pre-wrapped text. Rabble rabble. - unwrap = !html.start_with?('

') + unwrap = !html.start_with?('

(.*)

(.*)\z}, '\1\2') if unwrap + output.gsub!(%r{\A

(.*)

(.*)\z}, '\1\2') if unwrap output end @@ -27,11 +27,17 @@ describe Banzai::Pipeline::DescriptionPipeline do end end - %w(b i strong em a ins del sup sub p).each do |elem| + %w(b i strong em a ins del sup sub).each do |elem| it "still allows '#{elem}' elements" do exp = act = "<#{elem}>Description" expect(parse(act).strip).to eq exp end end + + it "still allows 'p' elements" do + exp = act = "

Description

" + + expect(parse(act).strip).to eq exp + end end diff --git a/spec/models/concerns/cache_markdown_field_spec.rb b/spec/models/concerns/cache_markdown_field_spec.rb index 15cd3a7ed70..2e3702f7520 100644 --- a/spec/models/concerns/cache_markdown_field_spec.rb +++ b/spec/models/concerns/cache_markdown_field_spec.rb @@ -64,7 +64,7 @@ describe CacheMarkdownField do let(:html) { "

Foo

" } let(:updated_markdown) { "`Bar`" } - let(:updated_html) { "

Bar

" } + let(:updated_html) { "

Bar

" } subject { ThingWithMarkdownFields.new(foo: markdown, foo_html: html) }