Git 2.48
[git/gitster.git] / Documentation / asciidoctor-extensions.rb.in
blob2494f17a514d9ddf48bfe4a15e00a09890f82df7
1 require 'asciidoctor'
2 require 'asciidoctor/extensions'
3 require 'asciidoctor/converter/docbook5'
4 require 'asciidoctor/converter/html5'
6 module Git
7 module Documentation
8 class LinkGitProcessor < Asciidoctor::Extensions::InlineMacroProcessor
9 use_dsl
11 named :chrome
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
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
44 class SynopsisBlock < Asciidoctor::Extensions::BlockProcessor
46 use_dsl
47 named :synopsis
48 parse_content_as :simple
50 def process parent, reader, attrs
51 outlines = reader.lines.map do |l|
52 l.gsub(/(\.\.\.?)([^\]$.])/, '`\1`\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
61 class GitDBConverter < Asciidoctor::Converter::DocBook5Converter
63 extend Asciidoctor::Converter::Config
64 register_for 'docbook5'
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(%r{([\[\s|()>.]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1<literal>\2</literal>')
76 .gsub(/(&lt;[-a-zA-Z0-9.]+&gt;)/, '<emphasis>\1</emphasis>')
77 else
78 open, close, supports_phrase = QUOTE_TAGS[type]
79 text = node.text
80 if node.role
81 if supports_phrase
82 quoted_text = %(#{open}<phrase role="#{node.role}">#{text}</phrase>#{close})
83 else
84 quoted_text = %(#{open.chop} role="#{node.role}">#{text}#{close})
85 end
86 else
87 quoted_text = %(#{open}#{text}#{close})
88 end
89 node.id ? %(<anchor#{common_attributes node.id, nil, text}/>#{quoted_text}) : quoted_text
90 end
91 end
92 end
94 # register a html5 converter that takes in charge to convert monospaced text into Git style synopsis
95 class GitHTMLConverter < Asciidoctor::Converter::Html5Converter
97 extend Asciidoctor::Converter::Config
98 register_for 'html5'
100 def convert_inline_quoted node
101 if node.type == :monospaced
102 node.text.gsub(/(\.\.\.?)([^\]$.])/, '<code>\1</code>\2')
103 .gsub(%r{([\[\s|()>.]|^|\]|&gt;)(\.?([-a-zA-Z0-9:+=~@,/_^\$]+\.{0,2})+)}, '\1<code>\2</code>')
104 .gsub(/(&lt;[-a-zA-Z0-9.]+&gt;)/, '<em>\1</em>')
106 else
107 open, close, tag = QUOTE_TAGS[node.type]
108 if node.id
109 class_attr = node.role ? %( class="#{node.role}") : ''
110 if tag
111 %(#{open.chop} id="#{node.id}"#{class_attr}>#{node.text}#{close})
112 else
113 %(<span id="#{node.id}"#{class_attr}>#{open}#{node.text}#{close}</span>)
115 elsif node.role
116 if tag
117 %(#{open.chop} class="#{node.role}">#{node.text}#{close})
118 else
119 %(<span class="#{node.role}">#{open}#{node.text}#{close}</span>)
121 else
122 %(#{open}#{node.text}#{close})
130 Asciidoctor::Extensions.register do
131 inline_macro Git::Documentation::LinkGitProcessor, :linkgit
132 block Git::Documentation::SynopsisBlock
133 postprocessor Git::Documentation::DocumentPostProcessor