Class: Banzai::Filter::AsciiDocSanitizationFilter

Inherits:
BaseSanitizationFilter show all
Defined in:
lib/banzai/filter/ascii_doc_sanitization_filter.rb

Overview

Sanitize HTML produced by AsciiDoc/Asciidoctor.

Extends Banzai::Filter::BaseSanitizationFilter with specific rules.

Constant Summary collapse

/\A#{Gitlab::Asciidoc::DEFAULT_ADOC_ATTRS['idprefix']}(:?[[:alnum:]]|-|_)+\z/.freeze
SECTION_HEADINGS =
%w(h2 h3 h4 h5 h6).freeze
{
  a: /\A_footnoteref_\d+\z/,
  div: /\A_footnotedef_\d+\z/
}.freeze
ADMONITION_CLASSES =

Classes used by Asciidoctor to style components

%w(fa icon-note icon-tip icon-warning icon-caution icon-important).freeze
ALIGNMENT_BUILTINS_CLASSES =
%w(text-center text-left text-right text-justify).freeze
CALLOUT_CLASSES =
['conum'].freeze
CHECKLIST_CLASSES =
%w(fa fa-check-square-o fa-square-o).freeze
LIST_CLASSES =
%w(checklist none no-bullet unnumbered unstyled).freeze
TABLE_FRAME_CLASSES =
%w(frame-all frame-topbot frame-sides frame-ends frame-none).freeze
TABLE_GRID_CLASSES =
%w(grid-all grid-rows grid-cols grid-none).freeze
TABLE_STRIPES_CLASSES =
%w(stripes-all stripes-odd stripes-even stripes-hover stripes-none).freeze
ELEMENT_CLASSES_WHITELIST =
{
  span: %w(big small underline overline line-through).freeze,
  div: ALIGNMENT_BUILTINS_CLASSES + ['admonitionblock'].freeze,
  td: ['icon'].freeze,
  i: ADMONITION_CLASSES + CALLOUT_CLASSES + CHECKLIST_CLASSES,
  ul: LIST_CLASSES,
  ol: LIST_CLASSES,
  a: ['anchor'].freeze,
  table: TABLE_FRAME_CLASSES + TABLE_GRID_CLASSES + TABLE_STRIPES_CLASSES
}.freeze

Constants inherited from BaseSanitizationFilter

BaseSanitizationFilter::UNSAFE_PROTOCOLS

Constants included from Gitlab::Utils::SanitizeNodeLink

Gitlab::Utils::SanitizeNodeLink::ATTRS_TO_SANITIZE, Gitlab::Utils::SanitizeNodeLink::UNSAFE_PROTOCOLS

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BaseSanitizationFilter

remove_rel, #whitelist

Methods included from Gitlab::Utils::SanitizeNodeLink

#remove_unsafe_links, #safe_protocol?

Methods included from Gitlab::Utils::StrongMemoize

#clear_memoization, #strong_memoize, #strong_memoized?

Class Method Details

.remove_element_classesObject


99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/banzai/filter/ascii_doc_sanitization_filter.rb', line 99

def remove_element_classes
  lambda do |env|
    node = env[:node]

    return unless (classes_whitelist = ELEMENT_CLASSES_WHITELIST[node.name.to_sym])
    return unless node.has_attribute?('class')

    classes = node['class'].strip.split(' ')
    allowed_classes = (classes & classes_whitelist)
    if allowed_classes.empty?
      node.remove_attribute('class')
    else
      node['class'] = allowed_classes.join(' ')
    end
  end
end

.remove_non_footnote_idsObject


73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/banzai/filter/ascii_doc_sanitization_filter.rb', line 73

def remove_non_footnote_ids
  lambda do |env|
    node = env[:node]

    return unless (pattern = FOOTNOTE_LINK_ID_PATTERNS[node.name.to_sym])
    return unless node.has_attribute?('id')

    return if node['id'] =~ pattern

    node.remove_attribute('id')
  end
end

.remove_non_heading_idsObject


86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/banzai/filter/ascii_doc_sanitization_filter.rb', line 86

def remove_non_heading_ids
  lambda do |env|
    node = env[:node]

    return unless SECTION_HEADINGS.any?(node.name)
    return unless node.has_attribute?('id')

    return if node['id'] =~ SECTION_LINK_REF_PATTERN

    node.remove_attribute('id')
  end
end

Instance Method Details

#customize_whitelist(whitelist) ⇒ Object


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/banzai/filter/ascii_doc_sanitization_filter.rb', line 41

def customize_whitelist(whitelist)
  # Allow marks
  whitelist[:elements].push('mark')

  # Allow any classes in `span`, `i`, `div`, `td`, `ul`, `ol` and `a` elements
  # but then remove any unknown classes
  whitelist[:attributes]['span'] = %w(class)
  whitelist[:attributes]['div'].push('class')
  whitelist[:attributes]['td'] = %w(class)
  whitelist[:attributes]['i'] = %w(class)
  whitelist[:attributes]['ul'] = %w(class)
  whitelist[:attributes]['ol'] = %w(class)
  whitelist[:attributes]['a'].push('class')
  whitelist[:attributes]['table'] = %w(class)
  whitelist[:transformers].push(self.class.remove_element_classes)

  # Allow `id` in heading elements for section anchors
  SECTION_HEADINGS.each do |header|
    whitelist[:attributes][header] = %w(id)
  end
  whitelist[:transformers].push(self.class.remove_non_heading_ids)

  # Allow `id` in footnote elements
  FOOTNOTE_LINK_ID_PATTERNS.keys.each do |element|
    whitelist[:attributes][element.to_s].push('id')
  end
  whitelist[:transformers].push(self.class.remove_non_footnote_ids)

  whitelist
end