rich_text_renderer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +27 -0
  5. data/.rubocop_todo.yml +35 -0
  6. data/.travis.yml +13 -0
  7. data/.yardopts +4 -0
  8. data/CHANGELOG.md +19 -0
  9. data/Gemfile +3 -0
  10. data/Guardfile +24 -0
  11. data/LICENSE.txt +21 -0
  12. data/README.md +87 -0
  13. data/Rakefile +33 -0
  14. data/lib/rich_text_renderer.rb +2 -0
  15. data/lib/rich_text_renderer/base_node_renderer.rb +18 -0
  16. data/lib/rich_text_renderer/block_renderers.rb +18 -0
  17. data/lib/rich_text_renderer/block_renderers/base_block_renderer.rb +24 -0
  18. data/lib/rich_text_renderer/block_renderers/blockquote_renderer.rb +12 -0
  19. data/lib/rich_text_renderer/block_renderers/entry_block_renderer.rb +13 -0
  20. data/lib/rich_text_renderer/block_renderers/heading_five_renderer.rb +12 -0
  21. data/lib/rich_text_renderer/block_renderers/heading_four_renderer.rb +12 -0
  22. data/lib/rich_text_renderer/block_renderers/heading_one_renderer.rb +12 -0
  23. data/lib/rich_text_renderer/block_renderers/heading_six_renderer.rb +12 -0
  24. data/lib/rich_text_renderer/block_renderers/heading_three_renderer.rb +12 -0
  25. data/lib/rich_text_renderer/block_renderers/heading_two_renderer.rb +12 -0
  26. data/lib/rich_text_renderer/block_renderers/hr_renderer.rb +11 -0
  27. data/lib/rich_text_renderer/block_renderers/hyperlink_renderer.rb +11 -0
  28. data/lib/rich_text_renderer/block_renderers/list_item_renderer.rb +12 -0
  29. data/lib/rich_text_renderer/block_renderers/ordered_list_renderer.rb +12 -0
  30. data/lib/rich_text_renderer/block_renderers/paragraph_renderer.rb +12 -0
  31. data/lib/rich_text_renderer/block_renderers/unordered_list_renderer.rb +12 -0
  32. data/lib/rich_text_renderer/document_renderers.rb +1 -0
  33. data/lib/rich_text_renderer/document_renderers/document_renderer.rb +13 -0
  34. data/lib/rich_text_renderer/null_renderer.rb +19 -0
  35. data/lib/rich_text_renderer/renderer.rb +46 -0
  36. data/lib/rich_text_renderer/text_renderers.rb +5 -0
  37. data/lib/rich_text_renderer/text_renderers/base_inline_renderer.rb +17 -0
  38. data/lib/rich_text_renderer/text_renderers/bold_renderer.rb +12 -0
  39. data/lib/rich_text_renderer/text_renderers/code_renderer.rb +12 -0
  40. data/lib/rich_text_renderer/text_renderers/italic_renderer.rb +12 -0
  41. data/lib/rich_text_renderer/text_renderers/text_renderer.rb +19 -0
  42. data/lib/rich_text_renderer/text_renderers/underline_renderer.rb +12 -0
  43. data/lib/rich_text_renderer/version.rb +4 -0
  44. data/rich_text_renderer.gemspec +30 -0
  45. data/spec/lib/rich_text_renderer/block_renderers/base_block_renderer_spec.rb +26 -0
  46. data/spec/lib/rich_text_renderer/block_renderers/blockquote_renderer_spec.rb +25 -0
  47. data/spec/lib/rich_text_renderer/block_renderers/entry_block_renderer_spec.rb +15 -0
  48. data/spec/lib/rich_text_renderer/block_renderers/heading_five_renderer_spec.rb +24 -0
  49. data/spec/lib/rich_text_renderer/block_renderers/heading_four_renderer_spec.rb +24 -0
  50. data/spec/lib/rich_text_renderer/block_renderers/heading_one_renderer_spec.rb +24 -0
  51. data/spec/lib/rich_text_renderer/block_renderers/heading_six_renderer_spec.rb +24 -0
  52. data/spec/lib/rich_text_renderer/block_renderers/heading_three_renderer_spec.rb +24 -0
  53. data/spec/lib/rich_text_renderer/block_renderers/heading_two_renderer_spec.rb +24 -0
  54. data/spec/lib/rich_text_renderer/block_renderers/hr_renderer_spec.rb +13 -0
  55. data/spec/lib/rich_text_renderer/block_renderers/hyperlink_renderer_spec.rb +24 -0
  56. data/spec/lib/rich_text_renderer/block_renderers/list_item_renderer_spec.rb +24 -0
  57. data/spec/lib/rich_text_renderer/block_renderers/ordered_list_renderer_spec.rb +56 -0
  58. data/spec/lib/rich_text_renderer/block_renderers/paragraph_renderer_spec.rb +30 -0
  59. data/spec/lib/rich_text_renderer/block_renderers/unordered_list_renderer_spec.rb +56 -0
  60. data/spec/lib/rich_text_renderer/document_renderers/document_renderer_spec.rb +42 -0
  61. data/spec/lib/rich_text_renderer/null_renderer_spec.rb +19 -0
  62. data/spec/lib/rich_text_renderer/renderer_spec.rb +308 -0
  63. data/spec/lib/rich_text_renderer/text_renderers/base_inline_renderer_spec.rb +11 -0
  64. data/spec/lib/rich_text_renderer/text_renderers/bold_renderer_spec.rb +11 -0
  65. data/spec/lib/rich_text_renderer/text_renderers/code_renderer_spec.rb +11 -0
  66. data/spec/lib/rich_text_renderer/text_renderers/italic_renderer_spec.rb +11 -0
  67. data/spec/lib/rich_text_renderer/text_renderers/text_renderer_spec.rb +53 -0
  68. data/spec/lib/rich_text_renderer/text_renderers/underline_renderer_spec.rb +11 -0
  69. data/spec/spec_helper.rb +82 -0
  70. metadata +387 -0
@@ -0,0 +1,12 @@
1
+ require_relative './base_block_renderer'
2
+
3
+ module RichTextRenderer
4
+ # H3 node renderer.
5
+ class HeadingThreeRenderer < BaseBlockRenderer
6
+ protected
7
+
8
+ def render_tag
9
+ 'h3'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require_relative './base_block_renderer'
2
+
3
+ module RichTextRenderer
4
+ # H2 node renderer.
5
+ class HeadingTwoRenderer < BaseBlockRenderer
6
+ protected
7
+
8
+ def render_tag
9
+ 'h2'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ require_relative '../base_node_renderer'
2
+
3
+ module RichTextRenderer
4
+ # hr node renderer
5
+ class HrRenderer < BaseNodeRenderer
6
+ # Renders an hr node
7
+ def render(_node)
8
+ '<hr />'
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require_relative './base_block_renderer'
2
+
3
+ module RichTextRenderer
4
+ # a node renderer.
5
+ class HyperlinkRenderer < BaseBlockRenderer
6
+ # Renders hyperlink
7
+ def render(node)
8
+ "<a href=\"#{node['data']['uri']}\">#{render_content(node)}</a>"
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ require_relative './base_block_renderer'
2
+
3
+ module RichTextRenderer
4
+ # li node renderer.
5
+ class ListItemRenderer < BaseBlockRenderer
6
+ protected
7
+
8
+ def render_tag
9
+ 'li'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require_relative './base_block_renderer'
2
+
3
+ module RichTextRenderer
4
+ # ol node renderer.
5
+ class OrderedListRenderer < BaseBlockRenderer
6
+ protected
7
+
8
+ def render_tag
9
+ 'ol'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require_relative './base_block_renderer'
2
+
3
+ module RichTextRenderer
4
+ # P node renderer.
5
+ class ParagraphRenderer < BaseBlockRenderer
6
+ protected
7
+
8
+ def render_tag
9
+ 'p'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require_relative './base_block_renderer'
2
+
3
+ module RichTextRenderer
4
+ # ul node renderer.
5
+ class UnorderedListRenderer < BaseBlockRenderer
6
+ protected
7
+
8
+ def render_tag
9
+ 'ul'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1 @@
1
+ require_relative './document_renderers/document_renderer'
@@ -0,0 +1,13 @@
1
+ require_relative '../base_node_renderer'
2
+
3
+ module RichTextRenderer
4
+ # Document renderer.
5
+ class DocumentRenderer < BaseNodeRenderer
6
+ # Renders all nodes in the document.
7
+ def render(document)
8
+ document['content'].each_with_object([]) do |node, result|
9
+ result << find_renderer(node).render(node)
10
+ end.join("\n")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ require_relative './base_node_renderer'
2
+
3
+ module RichTextRenderer
4
+ # Catch-all renderer for missing node types
5
+ class NullRenderer < BaseNodeRenderer
6
+ # Will raise an exception indicating the missing node type.
7
+ def render(node)
8
+ fail "No renderer defined for '#{node_type(node)}' nodes"
9
+ end
10
+
11
+ private
12
+
13
+ def node_type(node)
14
+ return node['nodeType'] if node.key?('nodeType')
15
+ return node['type'] if node.key?('type')
16
+ node
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,46 @@
1
+ require_relative './text_renderers'
2
+ require_relative './block_renderers'
3
+ require_relative './document_renderers'
4
+ require_relative './base_node_renderer'
5
+ require_relative './null_renderer'
6
+
7
+ # RichTextRenderer Namespace
8
+ module RichTextRenderer
9
+ # Renderer for RichText field from Contentful
10
+ class Renderer < BaseNodeRenderer
11
+ # Default Renderers
12
+ DEFAULT_MAPPINGS = {
13
+ nil => NullRenderer,
14
+ 'document' => DocumentRenderer,
15
+ 'heading-1' => HeadingOneRenderer,
16
+ 'heading-2' => HeadingTwoRenderer,
17
+ 'heading-3' => HeadingThreeRenderer,
18
+ 'heading-4' => HeadingFourRenderer,
19
+ 'heading-5' => HeadingFiveRenderer,
20
+ 'heading-6' => HeadingSixRenderer,
21
+ 'blockquote' => BlockQuoteRenderer,
22
+ 'hyperlink' => HyperlinkRenderer,
23
+ 'paragraph' => ParagraphRenderer,
24
+ 'list-item' => ListItemRenderer,
25
+ 'ordered-list' => OrderedListRenderer,
26
+ 'unordered-list' => UnorderedListRenderer,
27
+ 'embedded-entry-block' => EntryBlockRenderer,
28
+ 'hr' => HrRenderer,
29
+ 'text' => TextRenderer,
30
+ 'bold' => BoldRenderer,
31
+ 'code' => CodeRenderer,
32
+ 'italic' => ItalicRenderer,
33
+ 'underline' => UnderlineRenderer
34
+ }
35
+
36
+ def initialize(mappings = {})
37
+ @mappings = DEFAULT_MAPPINGS.merge(mappings)
38
+ end
39
+
40
+ # Returns a rendered RichText document
41
+ def render(document)
42
+ renderer = find_renderer(document)
43
+ renderer.render(document) unless renderer.nil?
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,5 @@
1
+ require_relative './text_renderers/text_renderer'
2
+ require_relative './text_renderers/bold_renderer'
3
+ require_relative './text_renderers/code_renderer'
4
+ require_relative './text_renderers/italic_renderer'
5
+ require_relative './text_renderers/underline_renderer'
@@ -0,0 +1,17 @@
1
+ require_relative '../base_node_renderer'
2
+
3
+ module RichTextRenderer
4
+ # Base renderer for inline nodes.
5
+ class BaseInlineRenderer < BaseNodeRenderer
6
+ # Renders inline nodes.
7
+ def render(node)
8
+ "<#{render_tag}>#{node['value']}</#{render_tag}>"
9
+ end
10
+
11
+ protected
12
+
13
+ def render_tag
14
+ 'span'
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,12 @@
1
+ require_relative './base_inline_renderer'
2
+
3
+ module RichTextRenderer
4
+ # B node renderer.
5
+ class BoldRenderer < BaseInlineRenderer
6
+ protected
7
+
8
+ def render_tag
9
+ 'b'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require_relative './base_inline_renderer'
2
+
3
+ module RichTextRenderer
4
+ # code node renderer.
5
+ class CodeRenderer < BaseInlineRenderer
6
+ protected
7
+
8
+ def render_tag
9
+ 'code'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ require_relative './base_inline_renderer'
2
+
3
+ module RichTextRenderer
4
+ # I node renderer.
5
+ class ItalicRenderer < BaseInlineRenderer
6
+ protected
7
+
8
+ def render_tag
9
+ 'i'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,19 @@
1
+ require_relative '../base_node_renderer'
2
+
3
+ module RichTextRenderer
4
+ # Renderer for Text nodes.
5
+ class TextRenderer < BaseNodeRenderer
6
+ # Renders text nodes with all markings.
7
+ def render(node)
8
+ node = Marshal.load(Marshal.dump(node)) # Clone the node
9
+
10
+ node.fetch('marks', []).each do |mark|
11
+ renderer = mappings[mark['type']]
12
+ return mappings[nil].new(mappings).render(mark) if renderer.nil? && mappings.key?(nil)
13
+ node['value'] = renderer.new(mappings).render(node) unless renderer.nil?
14
+ end
15
+
16
+ node['value']
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ require_relative './base_inline_renderer'
2
+
3
+ module RichTextRenderer
4
+ # U node renderer.
5
+ class UnderlineRenderer < BaseInlineRenderer
6
+ protected
7
+
8
+ def render_tag
9
+ 'u'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,4 @@
1
+ module RichTextRenderer
2
+ # Gem Version
3
+ VERSION = '0.1.0'.freeze
4
+ end
@@ -0,0 +1,30 @@
1
+ require File.expand_path('../lib/rich_text_renderer/version', __FILE__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'rich_text_renderer'
5
+ gem.version = RichTextRenderer::VERSION
6
+ gem.summary = 'Rich Text Renderer for the Contentful RichText field type'
7
+ gem.description = 'Rich Text Renderer for the Contentful RichText field type'
8
+ gem.license = 'MIT'
9
+ gem.authors = ['Contentful GmbH (David Litvak Bruno)']
10
+ gem.email = 'rubygems@contentful.com'
11
+ gem.homepage = 'https://github.com/contentful/rich-text-renderer.rb'
12
+
13
+ gem.files = Dir['{**/}{.*,*}'].select { |path| File.file?(path) && !path.start_with?('pkg') }
14
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^spec/})
16
+ gem.require_paths = ['lib']
17
+
18
+ gem.add_development_dependency 'bundler', '~> 1.5'
19
+ gem.add_development_dependency 'rake', '< 11.0'
20
+ gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
21
+
22
+ gem.add_development_dependency 'guard'
23
+ gem.add_development_dependency 'guard-rspec'
24
+ gem.add_development_dependency 'guard-rubocop'
25
+ gem.add_development_dependency 'guard-yard'
26
+ gem.add_development_dependency 'yard'
27
+ gem.add_development_dependency 'rubocop', '~> 0.49.1'
28
+ gem.add_development_dependency 'rspec', '~> 3'
29
+ gem.add_development_dependency 'simplecov'
30
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ mock_node = {"content" => [{"value" => "foo", "nodeType" => "text"}]}
4
+
5
+ mock_node_with_marks = {"content" => [{"value" => "foo", "nodeType" => "text", "marks" => [{"type" => "bold"}]}]}
6
+
7
+ describe RichTextRenderer::BaseBlockRenderer do
8
+ subject do
9
+ described_class.new(
10
+ 'text' => RichTextRenderer::TextRenderer,
11
+ 'bold' => RichTextRenderer::BoldRenderer,
12
+ 'italic' => RichTextRenderer::ItalicRenderer,
13
+ 'underline' => RichTextRenderer::UnderlineRenderer
14
+ )
15
+ end
16
+
17
+ describe '#render' do
18
+ it 'by defaults renders a div' do
19
+ expect(subject.render(mock_node)).to eq "<div>foo</div>"
20
+ end
21
+
22
+ it 'will propagate marks to text renderers' do
23
+ expect(subject.render(mock_node_with_marks)).to eq "<div><b>foo</b></div>"
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ mock_node = {"content" => [{"nodeType" => "paragraph", "content" => [{"value" => "foo", "nodeType" => "text"}]}]}
4
+
5
+ mock_node_with_marks = {"content" => [{"nodeType" => "paragraph", "content" => [{"value" => "foo", "nodeType" => "text", "marks" => [{"type" => "bold"}]}]}]}
6
+
7
+ describe RichTextRenderer::BlockQuoteRenderer do
8
+ subject do
9
+ described_class.new(
10
+ 'paragraph' => RichTextRenderer::ParagraphRenderer,
11
+ 'text' => RichTextRenderer::TextRenderer,
12
+ 'bold' => RichTextRenderer::BoldRenderer
13
+ )
14
+ end
15
+
16
+ describe '#render' do
17
+ it 'renders a blockqoute' do
18
+ expect(subject.render(mock_node)).to eq "<blockqoute><p>foo</p></blockqoute>"
19
+ end
20
+
21
+ it 'will propagate marks to text renderers' do
22
+ expect(subject.render(mock_node_with_marks)).to eq "<blockqoute><p><b>foo</b></p></blockqoute>"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ mock_data_node = {
4
+ "data" => {"target" => {"sys" => {"id" => "foo", "type" => "Link", "linkType" => "Entry"}}}
5
+ }
6
+
7
+ describe RichTextRenderer::EntryBlockRenderer do
8
+ subject { described_class.new }
9
+
10
+ describe '#render' do
11
+ it 'will stringify node data' do
12
+ expect(subject.render(mock_data_node)).to eq '<div>{"target"=>{"sys"=>{"id"=>"foo", "type"=>"Link", "linkType"=>"Entry"}}}</div>'
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ mock_node = {"content" => [{"value" => "foo", "nodeType" => "text"}]}
4
+
5
+ mock_node_with_marks = {"content" => [{"value" => "foo", "nodeType" => "text", "marks" => [{"type" => "bold"}]}]}
6
+
7
+ describe RichTextRenderer::HeadingFiveRenderer do
8
+ subject do
9
+ described_class.new(
10
+ 'text' => RichTextRenderer::TextRenderer,
11
+ 'bold' => RichTextRenderer::BoldRenderer
12
+ )
13
+ end
14
+
15
+ describe '#render' do
16
+ it 'renders a h5' do
17
+ expect(subject.render(mock_node)).to eq "<h5>foo</h5>"
18
+ end
19
+
20
+ it 'will propagate marks to text renderers' do
21
+ expect(subject.render(mock_node_with_marks)).to eq "<h5><b>foo</b></h5>"
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ mock_node = {"content" => [{"value" => "foo", "nodeType" => "text"}]}
4
+
5
+ mock_node_with_marks = {"content" => [{"value" => "foo", "nodeType" => "text", "marks" => [{"type" => "bold"}]}]}
6
+
7
+ describe RichTextRenderer::HeadingFourRenderer do
8
+ subject do
9
+ described_class.new(
10
+ 'text' => RichTextRenderer::TextRenderer,
11
+ 'bold' => RichTextRenderer::BoldRenderer
12
+ )
13
+ end
14
+
15
+ describe '#render' do
16
+ it 'renders a h4' do
17
+ expect(subject.render(mock_node)).to eq "<h4>foo</h4>"
18
+ end
19
+
20
+ it 'will propagate marks to text renderers' do
21
+ expect(subject.render(mock_node_with_marks)).to eq "<h4><b>foo</b></h4>"
22
+ end
23
+ end
24
+ end