"Fossies" - the Fresh Open Source Software Archive

Member "asciidoctor-2.0.10/lib/asciidoctor/syntax_highlighter.rb" (1 Jun 2019, 10802 Bytes) of package /linux/www/asciidoctor-2.0.10.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Ruby source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "syntax_highlighter.rb": 2.0.9_vs_2.0.10.

    1 # frozen_string_literal: true
    2 module Asciidoctor
    3 # Public: A pluggable adapter for integrating a syntax (aka code) highlighter into AsciiDoc processing.
    4 #
    5 # There are two types of syntax highlighter adapters. The first performs syntax highlighting during the convert phase.
    6 # This adapter type must define a highlight? method that returns true. The companion highlight method will then be
    7 # called to handle the :specialcharacters substitution for source blocks. The second assumes syntax highlighting is
    8 # performed on the client (e.g., when the HTML document is loaded). This adapter type must define a docinfo? method
    9 # that returns true. The companion docinfo method will then be called to insert markup into the output document. The
   10 # docinfo functionality is available to both adapter types.
   11 #
   12 # Asciidoctor provides several built-in adapters, including coderay, pygments, rouge, highlight.js, html-pipeline, and
   13 # prettify. Additional adapters can be registered using SyntaxHighlighter.register or by supplying a custom factory.
   14 module SyntaxHighlighter
   15   # Public: Returns the String name of this syntax highlighter for referencing it in messages and option names.
   16   attr_reader :name
   17 
   18   def initialize name, backend = 'html5', opts = {}
   19     @name = @pre_class = name
   20   end
   21 
   22   # Public: Indicates whether this syntax highlighter has docinfo (i.e., markup) to insert into the output document at
   23   # the specified location.
   24   #
   25   # location - The Symbol representing the location slot (:head or :footer).
   26   #
   27   # Returns a [Boolean] indicating whether the docinfo method should be called for this location.
   28   def docinfo? location; end
   29 
   30   # Public: Generates docinfo markup for this syntax highlighter to insert at the specified location in the output document.
   31   #
   32   # location - The Symbol representing the location slot (:head or :footer).
   33   # doc      - The Document in which this syntax highlighter is being used.
   34   # opts     - A Hash of options that configure the syntax highlighting:
   35   #            :linkcss - A Boolean indicating whether the stylesheet should be linked instead of embedded (optional).
   36   #            :cdn_base_url - The String base URL for assets loaded from the CDN.
   37   #            :self_closing_tag_slash - The String '/' if the converter calling this method emits self-closing tags.
   38   #
   39   # Return the [String] markup to insert.
   40   def docinfo location, doc, opts
   41     raise ::NotImplementedError, %(#{SyntaxHighlighter} subclass #{self.class} must implement the ##{__method__} method since #docinfo? returns true)
   42   end
   43 
   44   # Public: Indicates whether highlighting is handled by this syntax highlighter or by the client.
   45   #
   46   # Returns a [Boolean] indicating whether the highlight method should be used to handle the :specialchars substitution.
   47   def highlight?; end
   48 
   49   # Public: Highlights the specified source when this source block is being converted.
   50   #
   51   # If the source contains callout marks, the caller assumes the source remains on the same lines and no closing tags
   52   # are added to the end of each line. If the source gets shifted by one or more lines, this method must return a
   53   # tuple containing the highlighted source and the number of lines by which the source was shifted.
   54   #
   55   # node   - The source Block to syntax highlight.
   56   # source - The raw source text String of this source block (after preprocessing).
   57   # lang   - The source language String specified on this block (e.g., ruby).
   58   # opts   - A Hash of options that configure the syntax highlighting:
   59   #          :callouts - A Hash of callouts extracted from the source, indexed by line number (1-based) (optional).
   60   #          :css_mode - The Symbol CSS mode (:class or :inline).
   61   #          :highlight_lines - A 1-based Array of Integer line numbers to highlight (aka emphasize) (optional).
   62   #          :number_lines - A Symbol indicating whether lines should be numbered (:table or :inline) (optional).
   63   #          :start_line_number - The starting Integer (1-based) line number (optional, default: 1).
   64   #          :style - The String style (aka theme) to use for colorizing the code (optional).
   65   #
   66   # Returns the highlighted source String or a tuple of the highlighted source String and an Integer line offset.
   67   def highlight node, source, lang, opts
   68     raise ::NotImplementedError, %(#{SyntaxHighlighter} subclass #{self.class} must implement the ##{__method__} method since #highlight? returns true)
   69   end
   70 
   71   # Public: Format the highlighted source for inclusion in an HTML document.
   72   #
   73   # node   - The source Block being processed.
   74   # lang   - The source language String for this Block (e.g., ruby).
   75   # opts   - A Hash of options that control syntax highlighting:
   76   #          :nowrap - A Boolean that indicates whether wrapping should be disabled (optional).
   77   #
   78   # Returns the highlighted source [String] wrapped in preformatted tags (e.g., pre and code)
   79   def format node, lang, opts
   80     raise ::NotImplementedError, %(#{SyntaxHighlighter} subclass #{self.class} must implement the ##{__method__} method)
   81   end
   82 
   83   # Public: Indicates whether this syntax highlighter wants to write a stylesheet to disk. Only called if both the
   84   # linkcss and copycss attributes are set on the document.
   85   #
   86   # doc - The Document in which this syntax highlighter is being used.
   87   #
   88   # Returns a [Boolean] indicating whether the write_stylesheet method should be called.
   89   def write_stylesheet? doc; end
   90 
   91   # Public: Writes the stylesheet to support the highlighted source(s) to disk.
   92   #
   93   # doc    - The Document in which this syntax highlighter is being used.
   94   # to_dir - The absolute String path of the stylesheet output directory.
   95   #
   96   # Returns nothing.
   97   def write_stylesheet doc, to_dir
   98     raise ::NotImplementedError, %(#{SyntaxHighlighter} subclass #{self.class} must implement the ##{__method__} method since #write_stylesheet? returns true)
   99   end
  100 
  101   private_class_method def self.included into
  102     into.extend Config
  103   end || :included
  104 
  105   module Config
  106     # Public: Statically register the current class in the registry for the specified names.
  107     #
  108     # names - one or more String or Symbol names with which to register the current class as a syntax highlighter
  109     #         implementation. Symbol arguments are coerced to Strings.
  110     #
  111     # Returns nothing.
  112     def register_for *names
  113       SyntaxHighlighter.register self, *(names.map {|name| name.to_s })
  114     end
  115   end
  116 
  117   module Factory
  118     # Public: Associates the syntax highlighter class or object with the specified names.
  119     #
  120     # syntax_highlighter - the syntax highlighter implementation to register
  121     # names              - one or more String names with which to register this syntax highlighter implementation.
  122     #
  123     # Returns nothing.
  124     def register syntax_highlighter, *names
  125       names.each {|name| registry[name] = syntax_highlighter }
  126     end
  127 
  128     # Public: Retrieves the syntax highlighter class or object registered for the specified name.
  129     #
  130     # name - The String name of the syntax highlighter to retrieve.
  131     #
  132     # Returns the SyntaxHighlighter Class or Object instance registered for this name.
  133     def for name
  134       registry[name]
  135     end
  136 
  137     # Public: Resolves the name to a syntax highlighter instance, if found in the registry.
  138     #
  139     # name    - The String name of the syntax highlighter to create.
  140     # backend - The String name of the backend for which this syntax highlighter is being used (default: 'html5').
  141     # opts    - A Hash of options providing information about the context in which this syntax highlighter is used:
  142     #           :doc - The Document for which this syntax highlighter was created.
  143     #
  144     # Returns a [SyntaxHighlighter] instance for the specified name.
  145     def create name, backend = 'html5', opts = {}
  146       if (syntax_hl = self.for name)
  147         syntax_hl = syntax_hl.new name, backend, opts if ::Class === syntax_hl
  148         raise ::NameError, %(#{syntax_hl.class} must specify a value for `name') unless syntax_hl.name
  149         syntax_hl
  150       end
  151     end
  152 
  153     private
  154     
  155     def registry
  156       raise ::NotImplementedError, %(#{Factory} subclass #{self.class} must implement the ##{__method__} method)
  157     end
  158   end
  159 
  160   class CustomFactory
  161     include Factory
  162 
  163     def initialize seed_registry = nil
  164       @registry = seed_registry || {}
  165     end
  166 
  167     private
  168     
  169     def registry
  170       @registry
  171     end
  172   end
  173 
  174   module DefaultFactory
  175     include Factory
  176 
  177     private
  178 
  179     @@registry = {}
  180 
  181     def registry
  182       @@registry
  183     end
  184 
  185     unless RUBY_ENGINE == 'opal'
  186       public
  187 
  188       def register syntax_highlighter, *names
  189         @@mutex.owned? ? names.each {|name| @@registry = @@registry.merge name => syntax_highlighter } :
  190             @@mutex.synchronize { register syntax_highlighter, *names }
  191       end
  192 
  193       # This method will lazy require and register additional built-in implementations, which include coderay,
  194       # pygments, rouge, and prettify. Refer to {Factory#for} for parameters and return value.
  195       def for name
  196         @@registry.fetch name do
  197           @@mutex.synchronize do
  198             @@registry.fetch name do
  199               if (require_path = PROVIDED[name])
  200                 require require_path
  201                 @@registry[name]
  202               else
  203                 @@registry = @@registry.merge name => nil
  204                 nil
  205               end
  206             end
  207           end
  208         end
  209       end
  210 
  211       PROVIDED = {
  212         'coderay' => %(#{__dir__}/syntax_highlighter/coderay),
  213         'prettify' => %(#{__dir__}/syntax_highlighter/prettify),
  214         'pygments' => %(#{__dir__}/syntax_highlighter/pygments),
  215         'rouge' => %(#{__dir__}/syntax_highlighter/rouge),
  216       }
  217 
  218       private
  219 
  220       @@mutex = ::Mutex.new
  221     end
  222   end
  223 
  224   class DefaultFactoryProxy < CustomFactory
  225     include DefaultFactory # inserts module into ancestors immediately after superclass
  226 
  227     def for name
  228       @registry.fetch(name) { super }
  229     end unless RUBY_ENGINE == 'opal'
  230   end
  231 
  232   class Base
  233     include SyntaxHighlighter
  234 
  235     def format node, lang, opts
  236       class_attr_val = opts[:nowrap] ? %(#{@pre_class} highlight nowrap) : %(#{@pre_class} highlight)
  237       if (transform = opts[:transform])
  238         pre = { 'class' => class_attr_val }
  239         code = lang ? { 'data-lang' => lang } : {}
  240         transform[pre, code]
  241         %(<pre#{pre.map {|k, v| %[ #{k}="#{v}"] }.join}><code#{code.map {|k, v| %[ #{k}="#{v}"] }.join}>#{node.content}</code></pre>)
  242       else
  243         %(<pre class="#{class_attr_val}"><code#{lang ? %[ data-lang="#{lang}"] : ''}>#{node.content}</code></pre>)
  244       end
  245     end
  246   end
  247 
  248   extend DefaultFactory # exports static methods
  249 end
  250 end
  251 
  252 require_relative 'syntax_highlighter/highlightjs'
  253 require_relative 'syntax_highlighter/html_pipeline' unless RUBY_ENGINE == 'opal'