diff options
| author | Sarah White <graphitefriction@gmail.com> | 2020-11-18 15:53:10 -0700 |
|---|---|---|
| committer | Sarah White <graphitefriction@gmail.com> | 2020-12-08 14:32:53 -0700 |
| commit | c3c7ddbda681cc8f44832b0549bb623d3eace748 (patch) | |
| tree | 06d5d290d15b2f71758c40efca08d587e9e691b8 /docs/modules/extensions | |
| parent | cd241bc19e5016468e24104f949f0d18f207c69b (diff) | |
rearchitect modules and filenames and drop asciidoctor folder under docs
Diffstat (limited to 'docs/modules/extensions')
| -rw-r--r-- | docs/modules/extensions/nav.adoc | 11 | ||||
| -rw-r--r-- | docs/modules/extensions/pages/block-macro-processor.adoc | 48 | ||||
| -rw-r--r-- | docs/modules/extensions/pages/block-processor.adoc | 45 | ||||
| -rw-r--r-- | docs/modules/extensions/pages/compound-block-processor.adoc | 56 | ||||
| -rw-r--r-- | docs/modules/extensions/pages/docinfo-processor.adoc | 36 | ||||
| -rw-r--r-- | docs/modules/extensions/pages/include-processor.adoc | 49 | ||||
| -rw-r--r-- | docs/modules/extensions/pages/index.adoc | 51 | ||||
| -rw-r--r-- | docs/modules/extensions/pages/inline-macro-processor.adoc | 48 | ||||
| -rw-r--r-- | docs/modules/extensions/pages/postprocessor.adoc | 33 | ||||
| -rw-r--r-- | docs/modules/extensions/pages/preprocessor.adoc | 66 | ||||
| -rw-r--r-- | docs/modules/extensions/pages/register.adoc | 25 | ||||
| -rw-r--r-- | docs/modules/extensions/pages/tree-processor.adoc | 83 |
12 files changed, 551 insertions, 0 deletions
diff --git a/docs/modules/extensions/nav.adoc b/docs/modules/extensions/nav.adoc new file mode 100644 index 00000000..e209f801 --- /dev/null +++ b/docs/modules/extensions/nav.adoc @@ -0,0 +1,11 @@ +* xref:index.adoc[] +** xref:register.adoc[] +** xref:preprocessor.adoc[] +** xref:tree-processor.adoc[] +** xref:postprocessor.adoc[] +** xref:docinfo-processor.adoc[] +** xref:block-processor.adoc[] +** xref:compound-block-processor.adoc[] +** xref:block-macro-processor.adoc[] +** xref:inline-macro-processor.adoc[] +** xref:include-processor.adoc[] diff --git a/docs/modules/extensions/pages/block-macro-processor.adoc b/docs/modules/extensions/pages/block-macro-processor.adoc new file mode 100644 index 00000000..df451c43 --- /dev/null +++ b/docs/modules/extensions/pages/block-macro-processor.adoc @@ -0,0 +1,48 @@ += Block Macro Processor Extension Example +:navtitle: Block Macro Processor + +Purpose:: +Create a block macro named `gist` for embedding a gist. + +== sample-with-gist-macro.adoc + +``` +.My Gist +gist::123456[] +``` + +== GistBlockMacro + +```ruby +require 'asciidoctor' +require 'asciidoctor/extensions' + +class GistBlockMacro < Asciidoctor::Extensions::BlockMacroProcessor + use_dsl + + named :gist + + def process parent, target, attrs + title_html = (attrs.has_key? 'title') ? + %(<div class="title">#{attrs['title']}</div>\n) : nil + + html = %(<div class="openblock gist"> +#{title_html}<div class="content"> +<script src="https://gist.github.com/#{target}.js"></script> +</div> +</div>) + + create_pass_block parent, html, attrs, subs: nil + end +end +``` + +== Usage + +```ruby +Asciidoctor::Extensions.register do + block_macro GistBlockMacro if document.basebackend? 'html' +end + +Asciidoctor.convert_file 'sample-with-gist.adoc', :safe => :safe +``` diff --git a/docs/modules/extensions/pages/block-processor.adoc b/docs/modules/extensions/pages/block-processor.adoc new file mode 100644 index 00000000..d228642e --- /dev/null +++ b/docs/modules/extensions/pages/block-processor.adoc @@ -0,0 +1,45 @@ += Block Processor Extension Example +:navtitle: Block Processor + +Purpose:: +Register a custom block style named `shout` that uppercases all the words and converts periods to exclamation points. + +== sample-with-shout-block.adoc + +``` +[shout] +The time is now. Get a move on. +``` + +== ShoutBlock + +```ruby +require 'asciidoctor' +require 'asciidoctor/extensions' + +class ShoutBlock < Asciidoctor::Extensions::BlockProcessor + PeriodRx = /\.(?= |$)/ + + use_dsl + + named :shout + on_context :paragraph + name_positional_attributes 'vol' + parse_content_as :simple + + def process parent, reader, attrs + volume = ((attrs.delete 'vol') || 1).to_i + create_paragraph parent, (reader.lines.map {|l| l.upcase.gsub PeriodRx, '!' * volume }), attrs + end +end +``` + +== Usage + +```ruby +Asciidoctor::Extensions.register do + block ShoutBlock +end + +Asciidoctor.convert_file 'sample-with-shout-block.adoc', :safe => :safe +``` diff --git a/docs/modules/extensions/pages/compound-block-processor.adoc b/docs/modules/extensions/pages/compound-block-processor.adoc new file mode 100644 index 00000000..32dea0e4 --- /dev/null +++ b/docs/modules/extensions/pages/compound-block-processor.adoc @@ -0,0 +1,56 @@ += Compound Block Processor Example +:navtitle: Compound Block Processor + +Purpose:: +Register a custom block named `collapsible` that transforms a listing block into a compound block composed of the following: + +* an example block with the collapsible option enabled +* the original listing block +* the listing block is promoted to a source block if a language is specified using the second positional attribute. + +.sample-with-collapsible-block.adoc +[source] +.... +.Show JSON +[collapsible,json] +---- +{ + "foo": "bar" +} +---- +.... + +.collapsible-block.rb +[source,ruby] +---- +class CollapsibleBlock < Asciidoctor::Extensions::BlockProcessor + enable_dsl + on_context :listing + positional_attributes 'language' + + def process parent, reader, attrs + lang = attrs.delete 'language' + attrs['title'] ||= 'Show Listing' + example = create_example_block parent, [], attrs, content_model: :compound + example.set_option 'collapsible' + listing = create_listing_block example, reader.readlines, nil + if lang + listing.style = 'source' + listing.set_attr 'language', lang + listing.commit_subs + end + example << listing + example + end +end + +Asciidoctor::Extensions.register do + block CollapsibleBlock, :collapsible +end +---- + +.Usage + $ asciidoctor -r ./collapsible-block.rb sample-with-collapsible-block.adoc + +NOTE: This extension mimics the builtin `collapsible` option on the example block, but consolidates it to a single block. +The purpose of this extension is to show how to assemble a compound block in an extension. diff --git a/docs/modules/extensions/pages/docinfo-processor.adoc b/docs/modules/extensions/pages/docinfo-processor.adoc new file mode 100644 index 00000000..d5510c1a --- /dev/null +++ b/docs/modules/extensions/pages/docinfo-processor.adoc @@ -0,0 +1,36 @@ += Docinfo Processor Extension Example +:navtitle: Docinfo Processor + +Purpose:: +Appends the Google Analytics tracking code to the bottom of an HTML document. + +== GoogleAnalyticsDocinfoProcessor + +```ruby +class GoogleAnalyticsDocinfoProcessor < Asciidoctor::Extensions::DocinfoProcessor + use_dsl + at_location :footer + def process document + return unless (ga_account_id = document.attr 'google-analytics-account') + %(<script> +(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ +(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), +m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) +})(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); +ga('create','#{ga_account_id}','auto'); +ga('send','pageview'); +</script>) + end +end +``` + +== Usage + +```ruby +Asciidoctor::Extensions.register do + docinfo_processor GoogleAnalyticsDocinfoProcessor +end + +Asciidoctor.convert_file 'sample.adoc', :safe => :safe, + :attributes => 'UA-ABCXYZ123' +``` diff --git a/docs/modules/extensions/pages/include-processor.adoc b/docs/modules/extensions/pages/include-processor.adoc new file mode 100644 index 00000000..8dbdd8e0 --- /dev/null +++ b/docs/modules/extensions/pages/include-processor.adoc @@ -0,0 +1,49 @@ += Include Processor Extension Example +:navtitle: Include Processor + +Purpose:: +Include a file from a URI. + +TIP: Asciidoctor supports including content from a URI out of the box if you set the `allow-uri-read` attribute (not available if the safe mode is `secure`). + +== sample-with-uri-include.adoc + +``` +:source-highlighter: coderay + +.Gemfile +[source,ruby] +---- +\include::https://raw.githubusercontent.com/asciidoctor/asciidoctor/master/Gemfile[] +---- +``` + +== UriIncludeProcessor + +```ruby +require 'asciidoctor' +require 'asciidoctor/extensions' +require 'open-uri' + +class UriIncludeProcessor < Asciidoctor::Extensions::IncludeProcessor + def handles? target + (target.start_with? 'http://') or (target.start_with? 'https://') + end + + def process doc, reader, target, attributes + content = (open target).readlines + reader.push_include content, target, target, 1, attributes + reader + end +end +``` + +== Usage + +```ruby +Asciidoctor::Extensions.register do + include_processor UriIncludeProcessor +end + +Asciidoctor.convert_file 'sample-with-uri-include.adoc', :safe => :safe +``` diff --git a/docs/modules/extensions/pages/index.adoc b/docs/modules/extensions/pages/index.adoc new file mode 100644 index 00000000..33b35755 --- /dev/null +++ b/docs/modules/extensions/pages/index.adoc @@ -0,0 +1,51 @@ += Extensions +:url-exten-lab: https://github.com/asciidoctor/asciidoctor-extensions-lab + +Extensions are central to the success of AsciiDoc because they open up the language to new use cases. +Asciidoctor provides an extension API that offers a superset of extension points. +As a result, extensions in Asciidoctor are easy to write, powerful, and simple to distribute. + +Asciidoctor also allows extensions to be written using the full power of a programming language (whether it be Ruby, Java, Groovy or JavaScript). +You don't have to shave yaks to get the functionality you want, and you can distribute the extension using defacto-standard packaging mechanisms like RubyGems or JARs. + +== Available extension points + +Asciidoctor provides the following extension points: + +Preprocessor:: +Processes the raw source lines before they are passed to the parser. +See xref:preprocessor.adoc[]. + +Tree processor:: +Processes the [.class]#Asciidoctor::Document# (AST) once parsing is complete. +See xref:tree-processor.adoc[]. + +Postprocessor:: +Processes the output after the document has been converted, but before it's written to disk. +See xref:postprocessor.adoc[]. + +Docinfo Processor:: +Adds additional content to the header or footer regions of the generated document. +See xref:docinfo-processor.adoc[]. + +Block processor:: +Processes a block of content marked with a custom block style (i.e., `[custom]`). (similar to an AsciiDoc filter) +See xref:block-processor.adoc[]. + +Compound block processor:: +Register a custom block named `collapsible` that transforms a listing block into a compound block. +See xref:compound-block-processor.adoc[]. + +Block macro processor:: +Registers a custom block macro and processes it (e.g., `gist::12345[]`). +See xref:block-macro-processor.adoc[]. + +Inline macro processor:: +Registers a custom inline macro and processes it (e.g., `btn:[Save]`). +See xref:inline-macro-processor.adoc[]. + +Include processor:: +Processes the `include::<filename>[]` directive. +See xref:include-processor.adoc[]. + +There are additional extension examples in the {url-exten-lab}[Asciidoctor extensions lab^]. diff --git a/docs/modules/extensions/pages/inline-macro-processor.adoc b/docs/modules/extensions/pages/inline-macro-processor.adoc new file mode 100644 index 00000000..b8d88b0e --- /dev/null +++ b/docs/modules/extensions/pages/inline-macro-processor.adoc @@ -0,0 +1,48 @@ += Inline Macro Processor Extension Example +:navtitle: Inline Macro Processor + +Purpose:: +Create an inline macro named `man` that links to a manpage. + +== sample-with-man-link.adoc + +``` +See man:gittutorial[7] to get started. +``` + +== ManpageInlineMacro + +```ruby +require 'asciidoctor' +require 'asciidoctor/extensions' + +class ManInlineMacro < Asciidoctor::Extensions::InlineMacroProcessor + use_dsl + + named :man + name_positional_attributes 'volnum' + + def process parent, target, attrs + text = manname = target + suffix = '' + target = %(#{manname}.html) + suffix = if (volnum = attrs['volnum']) + "(#{volnum})" + else + nil + end + parent.document.register :links, target + %(#{(create_anchor parent, text, type: :link, target: target).convert}#{suffix}) + end +end +``` + +== Usage + +```ruby +Asciidoctor::Extensions.register do + inline_macro ManInlineMacro +end + +Asciidoctor.convert_file 'sample-with-man-link.adoc', :safe => :safe +``` diff --git a/docs/modules/extensions/pages/postprocessor.adoc b/docs/modules/extensions/pages/postprocessor.adoc new file mode 100644 index 00000000..712706ea --- /dev/null +++ b/docs/modules/extensions/pages/postprocessor.adoc @@ -0,0 +1,33 @@ += Postprocessor Extension Example +:navtitle: Postprocessor + +Purpose:: +Insert copyright text in the footer. + +== CopyrightFooterPostprocessor + +```ruby +class CopyrightFooterPostprocessor < Asciidoctor::Extensions::Postprocessor + def process document, output + content = (document.attr 'copyright') || 'Copyright Acme, Inc.' + if document.basebackend? 'html' + replacement = %(<div id="footer-text">\\1<br>\n#{content}\n</div>) + output = output.sub(/<div id="footer-text">(.*?)<\/div>/m, replacement) + elsif document.basebackend? 'docbook' + replacement = %(<simpara>#{content}</simpara>\n\\1) + output = output.sub(/(<\/(?:article|book)>)/, replacement) + end + output + end +end +``` + +== Usage + +``` +Asciidoctor::Extensions.register do + postprocessor CopyrightFooterPostprocessor +end + +Asciidoctor.convert_file 'sample-with-copyright-footer.adoc', :safe => :safe +``` diff --git a/docs/modules/extensions/pages/preprocessor.adoc b/docs/modules/extensions/pages/preprocessor.adoc new file mode 100644 index 00000000..c1e5a406 --- /dev/null +++ b/docs/modules/extensions/pages/preprocessor.adoc @@ -0,0 +1,66 @@ += Preprocessor Extension Example +:navtitle: Preprocessor + +Purpose:: +Skim off front matter from the top of the document that gets used by site generators like Jekyll and Awestruct. + +== sample-with-front-matter.adoc + +``` +--- +tags: [announcement, website] +--- += Document Title + +content + +[subs="attributes,specialcharacters"] +.Captured front matter +.... +--- +{front-matter} +--- +.... +``` + +== FrontMatterPreprocessor + +```ruby +require 'asciidoctor' +require 'asciidoctor/extensions' + +class FrontMatterPreprocessor < Asciidoctor::Extensions::Preprocessor + def process document, reader + lines = reader.lines # get raw lines + return reader if lines.empty? + front_matter = [] + if lines.first.chomp == '---' + original_lines = lines.dup + lines.shift + while !lines.empty? && lines.first.chomp != '---' + front_matter << lines.shift + end + + if (first = lines.first).nil? || first.chomp != '---' + lines = original_lines + else + lines.shift + document.attributes['front-matter'] = front_matter.join.chomp + # advance the reader by the number of lines taken + (front_matter.length + 2).times { reader.advance } + end + end + reader + end +end +``` + +== Usage + +```ruby +Asciidoctor::Extensions.register do + preprocessor FrontMatterPreprocessor +end + +Asciidoctor.convert_file 'sample-with-front-matter.adoc', :safe => :safe +``` diff --git a/docs/modules/extensions/pages/register.adoc b/docs/modules/extensions/pages/register.adoc new file mode 100644 index 00000000..7e076ba1 --- /dev/null +++ b/docs/modules/extensions/pages/register.adoc @@ -0,0 +1,25 @@ += Register Extensions + +== Register one or more extensions + +These extensions are registered per document using a callback that feels like a DSL: + +```ruby +Asciidoctor::Extensions.register do |document| + preprocessor FrontMatterPreprocessor + tree_processor ShellSessionTreeProcessor + postprocessor CopyrightFooterPostprocessor + docinfo_processor TrackingCodeDocinfoProcessor if document.basebackend? 'html' + block ShoutBlock + block_macro GistBlockMacro if document.basebackend? 'html' + inline_macro ManInlineMacro + include_processor UriIncludeProcessor +end +``` + +CAUTION: Extension classes must be defined outside of the register block. +Once an extension class is registered, it is frozen, preventing further modification. +If you define an extension class inside the register block, it will result in an error on subsequent invocations. + +You can register more than one processor of each type, though you can only have one processor per custom block or macro. +Each registered class is instantiated when the [.class]#Asciidoctor::Document# is created. diff --git a/docs/modules/extensions/pages/tree-processor.adoc b/docs/modules/extensions/pages/tree-processor.adoc new file mode 100644 index 00000000..050737ed --- /dev/null +++ b/docs/modules/extensions/pages/tree-processor.adoc @@ -0,0 +1,83 @@ += 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 + +``` + $ echo "Hello, World!" + > Hello, World! + + $ gem install asciidoctor +``` + +== ShellSessionTreeProcessor + +```ruby +class ShellSessionTreeProcessor < Asciidoctor::Extensions::TreeProcessor + def process document + return unless document.blocks? + process_blocks document + nil + end + + def process_blocks node + node.blocks.each_with_index do |block, i| + if block.context == :literal && + (((first_line = block.lines.first).start_with? '$ ') || + (first_line.start_with? '> ')) + node.blocks[i] = convert_to_terminal_listing block + else + process_blocks block if block.blocks? + end + end + end + + def convert_to_terminal_listing block + attrs = block.attributes + attrs['role'] = 'terminal' + prompt_attr = (attrs.has_key? 'prompt') ? + %( data-prompt="#{block.sub_specialchars attrs['prompt']}") : nil + lines = block.lines.map do |line| + line = block.sub_specialchars line.chomp + if line.start_with? '$ ' + %(<span class="command"#{prompt_attr}>#{line[2..-1]}</span>) + elsif line.start_with? '> ' + %(<span class="output">#{line[5..-1]}</span>) + else + line + end + end + create_listing_block block.document, lines * EOL, attrs, subs: nil + end +end +``` + +== Usage + +```ruby +Asciidoctor::Extensions.register do + tree_processor ShellSessionTreeProcessor +end + +Asciidoctor.convert_file 'sample-with-shell-session.adoc', :safe => :safe +``` + +//// +In the example below the TreeProcessor examines the block contents looking for the `// (*)` suffix and rewrites the line so that Asciidoctor formats it appropriately. + +[source,java] +---- +protected void configure(HttpSecurity http) throws Exception { + http + .authorizeRequests() + .antMatchers("/resources/**").permitAll() // (*) + .anyRequest().authenticated() + .and() + .formLogin() + .loginPage("/login") + .permitAll(); +---- +//// |
