= Tree Processor Extension Example :navtitle: Tree Processor Purpose:: Detect literal blocks that contain shell commands, strip the prompt character and style the command using CSS in such a way that the prompt character cannot be selected (as seen on help.github.com). == sample-with-shell-session.adoc [source,asciidoc] ---- $ echo "Hello, World!" > Hello, World! $ gem install asciidoctor ---- == ShellSessionTreeProcessor [source,ruby] ---- class ShellSessionTreeProcessor < Asciidoctor::Extensions::TreeProcessor LF = ?\n def process document (document.find_by(context: :literal) {|candidate| candidate.lines[0].start_with? '$ ', '> ' }).each do |block| (children = block.parent.blocks)[children.index block] = convert_to_terminal_listing block end nil end def convert_to_terminal_listing block attrs = block.attributes attrs['role'] = 'terminal' prompt_attr = (attrs.key? 'prompt') ? %( data-prompt="#{block.sub_specialchars attrs['prompt']}") : nil lines = (block.content.split LF).map do |line| if line.start_with? '$ ' %(#{line[2..-1]}) elsif line.start_with? '> ' %(#{line[5..-1]}) #%(# #{line[5..-1]}) else line end end create_listing_block block.parent, lines * LF, attrs, subs: nil end end ---- == Usage [source,ruby] ---- Asciidoctor::Extensions.register do tree_processor ShellSessionTreeProcessor end Asciidoctor.convert_file 'sample-with-shell-session.adoc', safe: :safe ----