rich_text_renderer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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