summaryrefslogtreecommitdiffstats
path: root/Documentation/asciidoctor-extensions.rb.in
blob: 2494f17a514d9ddf48bfe4a15e00a09890f82df7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
require 'asciidoctor'
require 'asciidoctor/extensions'
require 'asciidoctor/converter/docbook5'
require 'asciidoctor/converter/html5'

module Git
  module Documentation
    class LinkGitProcessor < Asciidoctor::Extensions::InlineMacroProcessor
      use_dsl

      named :chrome

      def process(parent, target, attrs)
        prefix = parent.document.attr('git-relative-html-prefix')
        if parent.document.doctype == 'book'
          "<ulink url=\"#{prefix}#{target}.html\">" \
          "#{target}(#{attrs[1]})</ulink>"
        elsif parent.document.basebackend? 'html'
          %(<a href="#{prefix}#{target}.html">#{target}(#{attrs[1]})</a>)
        elsif parent.document.basebackend? 'docbook'
          "<citerefentry>\n" \
            "<refentrytitle>#{target}</refentrytitle>" \
            "<manvolnum>#{attrs[1]}</manvolnum>\n" \
          "</citerefentry>"
        end
      end
    end

    class DocumentPostProcessor < Asciidoctor::Extensions::Postprocessor
      def process document, output
        if document.basebackend? 'docbook'
          output = output.sub(/<refmiscinfo class="source">.*?<\/refmiscinfo>/, "")
          output = output.sub(/<refmiscinfo class="manual">.*?<\/refmiscinfo>/, "")
          output = output.sub(/<date>.*?<\/date>/, "<date>@GIT_DATE@</date>")
          new_tags = "" \
            "<refmiscinfo class=\"source\">Git @GIT_VERSION@</refmiscinfo>\n" \
            "<refmiscinfo class=\"manual\">Git Manual</refmiscinfo>\n"
          output = output.sub(/<\/refmeta>/, new_tags + "</refmeta>")
        end
        output
      end
    end

    class SynopsisBlock < Asciidoctor::Extensions::BlockProcessor

      use_dsl
      named :synopsis
      parse_content_as :simple

      def process parent, reader, attrs
        outlines = reader.lines.map do |l|
          l.gsub(/(\.\.\.?)([^\]$.])/, '`\1`\2')
           .gsub(%r{([\[\] |()>]|^)([-a-zA-Z0-9:+=~@,/_^\$]+)}, '\1{empty}`\2`{empty}')
           .gsub(/(<[-a-zA-Z0-9.]+>)/, '__\\1__')
           .gsub(']', ']{empty}')
        end
        create_block parent, :verse, outlines, attrs
      end
    end

    class GitDBConverter < Asciidoctor::Converter::DocBook5Converter

      extend Asciidoctor::Converter::Config
      register_for 'docbook5'

      def convert_inline_quoted node
        if (type = node.type) == :asciimath
          # NOTE fop requires jeuclid to process mathml markup
          asciimath_available? ? %(<inlineequation>#{(::AsciiMath.parse node.text).to_mathml 'mml:', 'xmlns:mml' => 'http://www.w3.org/1998/Math/MathML'}</inlineequation>) : %(<inlineequation><mathphrase><![CDATA[#{node.text}]]></mathphrase></inlineequation>)
        elsif type == :latexmath
          # unhandled math; pass source to alt and required mathphrase element; dblatex will process alt as LaTeX math
          %(<inlineequation><alt><![CDATA[#{equation = node.text}]]></alt><mathphrase><![CDATA[#{equation}]]></mathphrase></inlineequation>)
        elsif type == :monospaced
          node.text.gsub(/(\.\.\.?)([^\]$.])/, '<literal>\1</literal>\2')
              .gsub(%r{([\[\s|()>.]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1<literal>\2</literal>')
              .gsub(/(&lt;[-a-zA-Z0-9.]+&gt;)/, '<emphasis>\1</emphasis>')
        else
          open, close, supports_phrase = QUOTE_TAGS[type]
          text = node.text
          if node.role
            if supports_phrase
              quoted_text = %(#{open}<phrase role="#{node.role}">#{text}</phrase>#{close})
            else
              quoted_text = %(#{open.chop} role="#{node.role}">#{text}#{close})
            end
          else
            quoted_text = %(#{open}#{text}#{close})
          end
          node.id ? %(<anchor#{common_attributes node.id, nil, text}/>#{quoted_text}) : quoted_text
        end
      end
    end

    # register a html5 converter that takes in charge to convert monospaced text into Git style synopsis
    class GitHTMLConverter < Asciidoctor::Converter::Html5Converter

      extend Asciidoctor::Converter::Config
      register_for 'html5'

      def convert_inline_quoted node
        if node.type == :monospaced
          node.text.gsub(/(\.\.\.?)([^\]$.])/, '<code>\1</code>\2')
              .gsub(%r{([\[\s|()>.]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1<code>\2</code>')
              .gsub(/(&lt;[-a-zA-Z0-9.]+&gt;)/, '<em>\1</em>')

        else
          open, close, tag = QUOTE_TAGS[node.type]
          if node.id
            class_attr = node.role ? %( class="#{node.role}") : ''
            if tag
              %(#{open.chop} id="#{node.id}"#{class_attr}>#{node.text}#{close})
            else
              %(<span id="#{node.id}"#{class_attr}>#{open}#{node.text}#{close}</span>)
            end
          elsif node.role
            if tag
              %(#{open.chop} class="#{node.role}">#{node.text}#{close})
            else
              %(<span class="#{node.role}">#{open}#{node.text}#{close}</span>)
            end
          else
            %(#{open}#{node.text}#{close})
          end
        end
      end
    end
  end
end

Asciidoctor::Extensions.register do
  inline_macro Git::Documentation::LinkGitProcessor, :linkgit
  block Git::Documentation::SynopsisBlock
  postprocessor Git::Documentation::DocumentPostProcessor
end