Extensions of useful macros for software documentation
Posted by mariocup on Feb 18, 2019; 10:10pm
URL: https://discuss.asciidoctor.org/Extensions-of-useful-macros-for-software-documentation-tp6753.html
Dear Asciidoctor community,
I am using Asciidoc to write documentation for software and I tried to write some macros to cover the following requirements.
opt::[] to format a string as option e.g. used to describe command line tools
var::[] format a variable as parameter by adding <parameter>
file::[] format a string in the text as file e.g. to mention a header file etc.
optentry: a list environment (role=optentry) which renders the list entry as option.
fcntenry: create a list environment (role=fcnentry) which renders the list entry with rouge syntax highlighting.
I consider this functionality also useful for other users and I would be more than happy if the functionality could be added to the extension lab after review and maintained by the community.
I collected my extensions in a file (can be passed by Asciidoctor option e.g. -r myextensions.rb).
```
RUBY_ENGINE == 'opal' ? (require 'variable-preprocessor/extension') : (require_relative 'variable-preprocessor/extension')
RUBY_ENGINE == 'opal' ? (require 'opt-preprocessor/extension') : (require_relative 'opt-preprocessor/extension')
RUBY_ENGINE == 'opal' ? (require 'file-preprocessor/extension') : (require_relative 'file-preprocessor/extension')
RUBY_ENGINE == 'opal' ? (require 'optentry-treeprocessor/extension') : (require_relative 'optentry-treeprocessor/extension')
RUBY_ENGINE == 'opal' ? (require 'fcnentry-treeprocessor/extension') : (require_relative 'fcnentry-treeprocessor/extension')
Extensions.register do
# preprocessor GitMetadataPreprocessor
preprocessor VariablePreprocessor
preprocessor FilePreprocessor
preprocessor OptPreprocessor
treeprocessor OptEntryTreeProcessor
treeprocessor FcnEntryTreeProcessor
end
```
The code looks like
# fcnentry
```
require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
require 'asciidoctor-pdf'
require 'asciidoctor-pdf/rouge_ext'
include Asciidoctor
module RawTerm
def text
@text
end
def text= text
@text = text
end
end
class FcnEntryTreeProcessor < Extensions::Treeprocessor
def process doc
(doc.find_by context: :dlist, role: 'fcnentry').each do |dlist|
dlist.items.each do |dlist_entry|
terms, description = dlist_entry
term_0 = terms[0]
term_0.extend RawTerm
lexer = Rouge::Lexer.find 'c'
formatter = if doc.backend == "html5"
Rouge::Formatters::HTML.new(Rouge::Theme.find(doc.attr('rouge-style', 'github')).new)
else
Rouge::Formatters::HTMLInline.new(Rouge::Theme.find(doc.attr('rouge-style', 'github')).new)
end
newText = formatter.format(lexer.lex(term_0.text))
term_0.text = newText
end
end
end
end
````
# opentry
```
require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
include Asciidoctor
def convert_to_opt block
newText = "`" << block.text << "`"
ListItem.new(block.parent, newText)
end
class OptEntryTreeProcessor < Extensions::Treeprocessor
def process doc
(doc.find_by context: :dlist, role: 'optentry').each do |dlist|
dlist.items.each.with_index do |dlist_entry, index|
#puts dlist_entry.inspect, index
terms, description = dlist_entry
terms[0] = convert_to_opt terms[0]
end
end
end
end
```
# variable
```
require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
include ::Asciidoctor
class VariablePreprocessor < Extensions::Preprocessor
def process document, reader
lines = []
while reader.has_more_lines?
lines << reader.read_line
end
lines.map do |line|
while ((startIndex = line.index("var::")))
if match = /(\w*-*(<\w*\s*\w*>)*)*/.match(line[(startIndex + 5)..-1])[0]
line.insert(startIndex + 5 + match.length, ">")
line[startIndex..startIndex+4] = "<"
end
end
end
Asciidoctor::Reader.new lines
end
end
```
# opt
```
require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
include ::Asciidoctor
class OptPreprocessor < Extensions::Preprocessor
def process document, reader
lines = []
while reader.has_more_lines?
lines << reader.read_line
end
lines.map do |line|
while ((startIndex = line.index("opt::")))
if match = /(\w*-*(<\w*\s*\w*>)*)*/.match(line[(startIndex + 5)..-1])[0]
line.insert(startIndex + 5 + match.length, "`")
line[startIndex..startIndex+4] = "`-"
end
end
end
Asciidoctor::Reader.new lines
end
end
```
# file
```
require 'asciidoctor/extensions' unless RUBY_ENGINE == 'opal'
include ::Asciidoctor
class FilePreprocessor < Extensions::Preprocessor
def process document, reader
lines = []
while reader.has_more_lines?
lines << reader.read_line
end
lines.map do |line|
while ((startIndex = line.index("file::")))
if match = /([[:punct:]]|\w)*\.\w+/.match(line[(startIndex + 6)..-1])[0]
line.insert(startIndex + 6 + match.length, "`")
line[startIndex..startIndex+5] = "`"
end
end
end
Asciidoctor::Reader.new lines
end
end
```
Any feedback is welcome.