Module: MarkupAttributes

Defined in:
lib/markup_attributes.rb,
lib/markup_attributes/engine.rb,
lib/markup_attributes/version.rb

Overview

The main behaviour for defining markup attributes

To enable this for your models, either extend it directly into one or more models, or extend it into ‘ApplicationRecord` to include it everywhere

Markup constraints

Markup content typically comes from users of the app, and as with any user-generated content, we probably can’t allow them to insert any old HTML into our rendered pages.

The main benefit of this approach is that it allows us to declare constraints on the types of markup we want to deal with in a single place, but without coupling rendering logic into the model itself.

Those constraints are grouped into certain types of elements:

Emphasis (:emphasis)

allow ‘i` and `em` tags.

Links (:links)

allow ‘a` tags, but mark them as `nofollow` so that they are not useful for spammers.

Images (:images)

allow ‘img` tags.

Automatic sanitisation

All the HTML generated is automatically run through Rails’ own sanitisation mechanism, which means that things like ‘<script>alert();</script>` will automatically either be sanitised into a non-running piece of content, or entirely removed, depending on the options given.

Examples:

a simple model declaring textile attributes

class Post < ApplicationRecord
  extend MarkupAttributes

  textile_attribute :title, :description, allow: [:emphasis, :images]

  # ...
end

Defined Under Namespace

Classes: Engine, MarkupString, MarkupType

Constant Summary collapse

VERSION =
'0.1.2'

Instance Method Summary collapse

Instance Method Details

#markdown_attribute(*attribute_names, **options) ⇒ Object

Declare one or more attributes as containing Markdown markup.

Parameters:

  • attribute_names (Symbol, Array<Symbol>)

    One or more attribute names to mark as containing markup

  • options (Hash<Symbol=>Symbol>, Hash<Symbol=>Array<Symbol>>)

    Options to be used when rendering this/these attributes



77
78
79
# File 'lib/markup_attributes.rb', line 77

def markdown_attribute(*attribute_names, **options)
  markup_attribute(*attribute_names, **options.merge(markup: :markdown))
end

#markup_attribute(*attribute_names, **options) ⇒ Object

Declare one or more attributes as containing markup content

Markup types

The following types can be provided in either the :allow or :deny options:

:emphasis

i and em tags

:links

a tags (will all have rel=nofollow automatically set)

:images

img tags

Parameters:

  • attribute_names (Symbol, Array<Symbol>)

    One or more attribute names to mark as containing markup

  • options (Hash<Symbol=>Symbol>, Hash<Symbol=>Array<Symbol>>)

    Options to be used when rendering this/these attributes

Options Hash (**options):

  • :markup (Symbol)

    The markup engine to use, either :textile or :markdown. If you use either of textile_attribute or markdown_attribute, wrapper methods, this will be set automatically.

  • :allow (Symbol, Array<Symbol>)

    Which types of markup to allow (any not included are implicity denied)

  • :deny (Symbol, Array<symbol>)

    Which types of markup to deny (any not included are implicity allowed)



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/markup_attributes.rb', line 95

def markup_attribute(*attribute_names, **options)
  raise "must define :markup option" unless options[:markup]
  options.deep_symbolize_keys!
  options[:allow] = Array.wrap(options[:allow] || :all).map(&:to_sym)
  options[:deny] = Array.wrap(options[:deny]).map(&:to_sym)
  options.freeze

  attribute_registry_type = get_type_for(options)

  attribute_names.each do |attribute_name|
    if respond_to?(:translates?) && translates? && translated_attribute_names.include?(attribute_name)
      translation_class.attribute attribute_name, attribute_registry_type
    else
      attribute attribute_name, attribute_registry_type
    end
  end
end

#textile_attribute(*attribute_names, **options) ⇒ Object

Declare one or more attributes as containing Textile markup.

Examples:

An attribute which only supports Textile emphasis and links

textile_attribute :title, allow: [:emphasis, :links]

An attribute which supports everything except images

textile_attribute :title, deny: [:images]

Parameters:

  • attribute_names (Symbol, Array<Symbol>)

    One or more attribute names to mark as containing markup

  • options (Hash<Symbol=>Symbol>, Hash<Symbol=>Array<Symbol>>)

    Options to be used when rendering this/these attributes



71
72
73
# File 'lib/markup_attributes.rb', line 71

def textile_attribute(*attribute_names, **options)
  markup_attribute(*attribute_names, **options.merge(markup: :textile))
end