Module: Decidim::ContentProcessor

Extended by:
ActionView::Helpers::SanitizeHelper, ActionView::Helpers::TagHelper, ActionView::Helpers::TextHelper
Defined in:
lib/decidim/content_processor.rb

Overview

This module contains all logic related to decidim’s ability for process a content. Their main job is to parse or render a content calling all the registered processors in the Decidim.content_processors config.

Note that to render a content this must have been parsed before.

When creating a new processor, the both sides must be declared: parser and renderer e.g. If we are creating a processor to parse and render user mentions, we can call this the ‘user` processor, so we will declare the parser and renderer classes like that:

Decidim::ContentParsers::UserParser
Decidim::ContentRenderers::UserRenderer

and register it in an initializer, so it is executed:

Decidim.content_processors += [:user]

If for some reason you only want to do something in one of the both sides, please, also declare the other side making it “transparent” (declaring the class and leaving it empty).

Examples:

How to parse a content

parsed = Decidim::ContentProcessor.parse(content, context)
parsed.rewrite # contains rewritten content
parsed. # contains the merged metadata of all parsers

How to render a content (must have been parsed before)

rendered = Decidim::ContentProcessor.render(content)
puts rendered

Defined Under Namespace

Classes: Result

Class Method Summary collapse

Class Method Details

.parse(content, context) ⇒ Result

This calls all registered processors one after the other and collects the metadata for each one and the resulting modified content

Parameters:

  • content (String)

    already rewritten content or regular content

  • context (Hash)

    with information to inject to the parsers as context

Returns:

  • (Result)

    a Result object with the content rewritten and the metadata



53
54
55
56
57
58
59
60
61
# File 'lib/decidim/content_processor.rb', line 53

def self.parse(content, context)
  parsed = Decidim.content_processors.each_with_object(rewrite: content, metadata: {}) do |type, result|
    parser = parser_klass(type).constantize.new(result[:rewrite], context)
    result[:rewrite] = parser.rewrite
    result[:metadata][type] = parser.
  end

  Result.new(parsed[:rewrite], parsed[:metadata])
end

.parse_with_processor(_type, content, context) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/decidim/content_processor.rb', line 63

def self.parse_with_processor(_type, content, context)
  parsed = if content.is_a?(Hash)
             Decidim.content_processors.each_with_object(rewrite: content, metadata: {}) do |type, result|
               next unless type == :hashtag

               result[:rewrite].each do |key, value|
                 parser = parser_klass(type).constantize.new(value, context)
                 result[:rewrite][key] = parser.rewrite
                 result[:metadata][type] = parser.
               end
             end
           else
             Decidim.content_processors.each_with_object(rewrite: content, metadata: {}) do |type, result|
               next unless type == :hashtag

               parser = parser_klass(type).constantize.new(result[:rewrite], context)
               result[:rewrite] = parser.rewrite
               result[:metadata][type] = parser.
             end
           end
  Result.new(parsed[:rewrite], parsed[:metadata])
end

.parser_klass(type) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Guess the class name of the parser for a processor represented by the given symbol

Returns:

  • (String)

    the content parser class name



117
118
119
# File 'lib/decidim/content_processor.rb', line 117

def self.parser_klass(type)
  "Decidim::ContentParsers::#{type.to_s.camelize}Parser"
end

.render(content, wrapper_tag = "p") ⇒ String

This calls all registered processors one after the other and returns the processed content ready to display.

Returns:

  • (String)

    the content processed and ready to display (it is expected to include HTML)



90
91
92
93
94
95
96
97
98
# File 'lib/decidim/content_processor.rb', line 90

def self.render(content, wrapper_tag = "p")
  simple_format(
    Decidim.content_processors.reduce(content) do |result, type|
      renderer_klass(type).constantize.new(result).render
    end,
    {},
    wrapper_tag: wrapper_tag
  )
end

.renderer_klass(type) ⇒ String

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Guess the class name of the renderer for a processor represented by the given symbol

Returns:

  • (String)

    the content renderer class name



126
127
128
# File 'lib/decidim/content_processor.rb', line 126

def self.renderer_klass(type)
  "Decidim::ContentRenderers::#{type.to_s.camelize}Renderer"
end

.sanitize(text, options = {}) ⇒ String

This method overwrites the views ‘sanitize` method. This is required to ensure the content does not include any weird HTML that could harm the end user.

Returns:

  • (String)

    sanitized content.



105
106
107
108
109
110
# File 'lib/decidim/content_processor.rb', line 105

def self.sanitize(text, options = {})
  Rails::Html::WhiteListSanitizer.new.sanitize(
    text,
    { scrubber: Decidim::UserInputScrubber.new }.merge(options)
  ).try(:html_safe)
end