module Decidim::ContentProcessor
This module contains all logic related to decidim's ability for process a content. Their main job is to {ContentProcessor#parse parse} or {ContentProcessor#render 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).
@example How to parse a content
parsed = Decidim::ContentProcessor.parse(content, context) parsed.rewrite # contains rewritten content parsed.metadata # contains the merged metadata of all parsers
@example How to render a content (must have been parsed before)
rendered = Decidim::ContentProcessor.render(content) puts rendered
Constants
- Result
Class that represents the result of processing a text
@!attribute rewrite
@return [String] the rewritten content
@!attribute metadata
@return [Hash<Symbol, Metadata>] a hash where the keys are the parsers names, and the values are the Metadata object returned by the parser
Public Class Methods
This calls all registered processors one after the other and collects the metadata for each one and the resulting modified content
@param content [String] already rewritten content or regular content @param context [Hash] with information to inject to the parsers as context
@return [Result] a Result
object with the content rewritten and the metadata
# 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
Public: Calls the specified processors to process the given content with it. For example, to convert hashtags to its Global ID representation.
@param type [String] the name of the processor to use. @param content [String] already rewritten content or regular content @param context [Hash] with information to inject to the parsers as context
@return [Result] a Result
object with the content rewritten and the metadata
# 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.metadata.update(child_result.metadata) end else parser = parser_klass(type).constantize.new(result.rewrite, context) result.rewrite = parser.rewrite result.metadata.update(type => parser.metadata) end result end
Guess the class name of the parser for a processor represented by the given symbol
@api private @return [String] the content parser class name
# File lib/decidim/content_processor.rb, line 140 def self.parser_klass(type) "Decidim::ContentParsers::#{type.to_s.camelize}Parser" end
This calls all registered processors one after the other and returns the processed content ready to display.
@param content [String] with the content to be rendered. @param wrapper_tag [String] with the HTML tag to wrap the content. @param options [Hash] with options to pass to the renderer.
@return [String] the content processed and ready to display (it is expected to include HTML)
# 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 ) end
This calls all registered processors one after the other and returns the processed content ready to display without wrapping the content in HTML.
@param content [String] with the content to be rendered. @param options [Hash] with options to pass to the renderer.
@return [String] the content processed and ready to display.
# File lib/decidim/content_processor.rb, line 115 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
Guess the class name of the renderer for a processor represented by the given symbol
@api private @return [String] the content renderer class name
# File lib/decidim/content_processor.rb, line 149 def self.renderer_klass(type) "Decidim::ContentRenderers::#{type.to_s.camelize}Renderer" end
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.
@return [String] sanitized content.
# File lib/decidim/content_processor.rb, line 128 def self.sanitize(text, options = {}) Rails::Html::WhiteListSanitizer.new.sanitize( text, { scrubber: Decidim::UserInputScrubber.new }.merge(options) ).try(:html_safe) end