diff options
author | Robert Speicher <rspeicher@gmail.com> | 2015-04-14 18:07:21 -0400 |
---|---|---|
committer | Robert Speicher <rspeicher@gmail.com> | 2015-04-20 13:01:45 -0400 |
commit | 6189b24fddae66e1c2bb71c496301ff85701cb90 (patch) | |
tree | 2b4929c5c4bdc1e2e48e39bf8014a3c3dce66091 | |
parent | c4eb6a55f14bfbe457be459092dff83207a27ac0 (diff) | |
download | gitlab-ce-6189b24fddae66e1c2bb71c496301ff85701cb90.tar.gz |
Add a ReferenceFilter base class
This will allow for the removal of a lot of duplication from the
reference filters.
-rw-r--r-- | lib/gitlab/markdown/reference_filter.rb | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/lib/gitlab/markdown/reference_filter.rb b/lib/gitlab/markdown/reference_filter.rb new file mode 100644 index 00000000000..55cb6a4e6bc --- /dev/null +++ b/lib/gitlab/markdown/reference_filter.rb @@ -0,0 +1,68 @@ +require 'html/pipeline' + +module Gitlab + module Markdown + # Base class for GitLab Flavored Markdown reference filters. + # + # References within <pre>, <code>, <a>, and <style> elements are ignored. + # + # Context options: + # :project (required) - Current project, ignored when reference is + # cross-project. + # :reference_class - Custom CSS class added to reference links. + # :only_path - Generate path-only links. + # + class ReferenceFilter < HTML::Pipeline::Filter + # Don't look for references in text nodes that are children of these + # elements. + IGNORE_PARENTS = %w(pre code a style).to_set + + def ignored_ancestry?(node) + has_ancestor?(node, IGNORE_PARENTS) + end + + def project + context[:project] + end + + def reference_class(type) + "gfm gfm-#{type} #{context[:reference_class]}".strip + end + + # Iterate through the document's text nodes, yielding the current node's + # content if: + # + # * The `project` context value is present AND + # * The node's content matches `pattern` AND + # * The node is not an ancestor of an ignored node type + # + # pattern - Regex pattern against which to match the node's content + # + # Yields the current node's String contents. The result of the block will + # replace the node's existing content and update the current document. + # + # Returns the updated Nokogiri::Document object. + def replace_text_nodes_matching(pattern) + doc.search('text()').each do |node| + content = node.to_html + + next if project.nil? + next unless content.match(pattern) + next if ignored_ancestry?(node) + + html = yield content + + next if html == content + + node.replace(html) + end + + doc + end + + def validate + needs :project + end + end + end +end |