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



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

def self.parse(content, context)
  Decidim.content_processors.each_with_object(Result.new(content, {})) do |type, result|
    parse_with_processor(type, result, context)
  end
end

.parse_with_processor(type, content, context) ⇒ Result

Public: Calls the specified processors to process the given content with it. For example, to convert hashtags to its Global ID representation.



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/decidim/content_processor.rb', line 67

def self.parse_with_processor(type, content, context)
  result = if content.is_a?(Result)
             content
           else
             Result.new(content, {})
           end

  if result.rewrite.is_a?(Hash)
    result.rewrite.each do |key, value|
      child_result = Result.new(value, {})
      child_result = parse_with_processor(type, child_result, context)

      result.rewrite.update(key => child_result.rewrite)
      result..update(child_result.)
    end
  else
    parser = parser_klass(type).constantize.new(result.rewrite, context)
    result.rewrite = parser.rewrite
    result..update(type => parser.)
  end

  result
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



141
142
143
# File 'lib/decidim/content_processor.rb', line 141

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

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

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



99
100
101
102
103
104
105
106
# File 'lib/decidim/content_processor.rb', line 99

def self.render(content, wrapper_tag = "p", options = {})
  simple_format(
    render_without_format(content, options),
    {},
    wrapper_tag: wrapper_tag,
    sanitize: false
  )
end

.render_without_format(content, options = {}) ⇒ String

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



116
117
118
119
120
121
122
# File 'lib/decidim/content_processor.rb', line 116

def self.render_without_format(content, options = {})
  return content if content.blank?

  Decidim.content_processors.reduce(content) do |result, type|
    renderer_klass(type).constantize.new(result).render(**options)
  end
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



150
151
152
# File 'lib/decidim/content_processor.rb', line 150

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.



129
130
131
132
133
134
# File 'lib/decidim/content_processor.rb', line 129

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