Raw
1 require 'asciidoctor'
2 require 'asciidoctor/extensions'
3 require 'asciidoctor/converter/docbook5'
4 require 'asciidoctor/converter/html5'
5
6 module Git
7 module Documentation
8 class LinkGitProcessor < Asciidoctor::Extensions::InlineMacroProcessor
9 use_dsl
10
11 named :chrome
12
13 def process(parent, target, attrs)
14 prefix = parent.document.attr('git-relative-html-prefix')
15 if parent.document.doctype == 'book'
16 "<ulink url=\"#{prefix}#{target}.html\">" \
17 "#{target}(#{attrs[1]})</ulink>"
18 elsif parent.document.basebackend? 'html'
19 %(<a href="#{prefix}#{target}.html">#{target}(#{attrs[1]})</a>)
20 elsif parent.document.basebackend? 'docbook'
21 "<citerefentry>\n" \
22 "<refentrytitle>#{target}</refentrytitle>" \
23 "<manvolnum>#{attrs[1]}</manvolnum>\n" \
24 "</citerefentry>"
25 end
26 end
27 end
28
29 class DocumentPostProcessor < Asciidoctor::Extensions::Postprocessor
30 def process document, output
31 if document.basebackend? 'docbook'
32 output = output.sub(/<refmiscinfo class="source">.*?<\/refmiscinfo>/, "")
33 output = output.sub(/<refmiscinfo class="manual">.*?<\/refmiscinfo>/, "")
34 output = output.sub(/<date>.*?<\/date>/, "<date>@GIT_DATE@</date>")
35 new_tags = "" \
36 "<refmiscinfo class=\"source\">Git @GIT_VERSION@</refmiscinfo>\n" \
37 "<refmiscinfo class=\"manual\">Git Manual</refmiscinfo>\n"
38 output = output.sub(/<\/refmeta>/, new_tags + "</refmeta>")
39 end
40 output
41 end
42 end
43
44 class SynopsisBlock < Asciidoctor::Extensions::BlockProcessor
45
46 use_dsl
47 named :synopsis
48 parse_content_as :simple
49
50 def process parent, reader, attrs
51 outlines = reader.lines.map do |l|
52 l.gsub(/(\.\.\.?)([^\]$\. ])/, '{empty}`\1`{empty}\2')
53 .gsub(%r{([\[\] |()>]|^)([-a-zA-Z0-9:+=~@,/_^\$\\\*]+)}, '\1{empty}`\2`{empty}')
54 .gsub(/(<[-a-zA-Z0-9.]+>)/, '__\\1__')
55 .gsub(']', ']{empty}')
56 end
57 create_block parent, :verse, outlines, attrs
58 end
59 end
60
61 class GitDBConverter < Asciidoctor::Converter::DocBook5Converter
62
63 extend Asciidoctor::Converter::Config
64 register_for 'docbook5'
65
66 def convert_inline_quoted node
67 if (type = node.type) == :asciimath
68 # NOTE fop requires jeuclid to process mathml markup
69 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>)
70 elsif type == :latexmath
71 # unhandled math; pass source to alt and required mathphrase element; dblatex will process alt as LaTeX math
72 %(<inlineequation><alt><![CDATA[#{equation = node.text}]]></alt><mathphrase><![CDATA[#{equation}]]></mathphrase></inlineequation>)
73 elsif type == :monospaced
74 node.text.gsub(/(\.\.\.?)([^\]$\.])/, '<literal>\1</literal>\2')
75 .gsub(/^\.\.\.?$/, '<literal>\0</literal>')
76 .gsub(%r{([\[\s|()>.]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@/_^\$\\\*%]+\.{0,2})+|,)}, '\1<literal>\2</literal>')
77 .gsub(/(&lt;[-a-zA-Z0-9.]+&gt;)/, '<emphasis>\1</emphasis>')
78 else
79 open, close, supports_phrase = QUOTE_TAGS[type]
80 text = node.text
81 if node.role
82 if supports_phrase
83 quoted_text = %(#{open}<phrase role="#{node.role}">#{text}</phrase>#{close})
84 else
85 quoted_text = %(#{open.chop} role="#{node.role}">#{text}#{close})
86 end
87 else
88 quoted_text = %(#{open}#{text}#{close})
89 end
90 node.id ? %(<anchor#{common_attributes node.id, nil, text}/>#{quoted_text}) : quoted_text
91 end
92 end
93 end
94
95 # register a html5 converter that takes in charge to convert monospaced text into Git style synopsis
96 class GitHTMLConverter < Asciidoctor::Converter::Html5Converter
97
98 extend Asciidoctor::Converter::Config
99 register_for 'html5'
100
101 def convert_inline_quoted node
102 if node.type == :monospaced
103 node.text.gsub(/(\.\.\.?)([^\]$.])/, '<code>\1</code>\2')
104 .gsub(/^\.\.\.?$/, '<code>\0</code>')
105 .gsub(%r{([\[\s|()>.]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@,/_^\$\\\*%]+\.{0,2})+)}, '\1<code>\2</code>')
106 .gsub(/(&lt;[-a-zA-Z0-9.]+&gt;)/, '<em>\1</em>')
107
108 else
109 open, close, tag = QUOTE_TAGS[node.type]
110 if node.id
111 class_attr = node.role ? %( class="#{node.role}") : ''
112 if tag
113 %(#{open.chop} id="#{node.id}"#{class_attr}>#{node.text}#{close})
114 else
115 %(<span id="#{node.id}"#{class_attr}>#{open}#{node.text}#{close}</span>)
116 end
117 elsif node.role
118 if tag
119 %(#{open.chop} class="#{node.role}">#{node.text}#{close})
120 else
121 %(<span class="#{node.role}">#{open}#{node.text}#{close}</span>)
122 end
123 else
124 %(#{open}#{node.text}#{close})
125 end
126 end
127 end
128 end
129 end
130 end
131
132 Asciidoctor::Extensions.register do
133 inline_macro Git::Documentation::LinkGitProcessor, :linkgit
134 block Git::Documentation::SynopsisBlock
135 postprocessor Git::Documentation::DocumentPostProcessor
136 end