Loading lib/jsduck/assets.rb +1 −2 Original line number Diff line number Diff line Loading @@ -27,8 +27,7 @@ module JsDuck @relations = relations @opts = opts doc_formatter = DocFormatter.new(@opts) doc_formatter.relations = @relations doc_formatter = DocFormatter.new(@relations, @opts) @images = Img::DirSet.new(@opts.images, "images") @welcome = Welcome.create(@opts.welcome, doc_formatter) Loading lib/jsduck/batch_formatter.rb +1 −2 Original line number Diff line number Diff line Loading @@ -45,8 +45,7 @@ module JsDuck # Factory method to create new ClassFormatter instances. def self.create_class_formatter(relations, opts) doc_formatter = DocFormatter.new(opts) doc_formatter.relations = relations doc_formatter = DocFormatter.new(relations, opts) doc_formatter.images = Img::DirSet.new(opts.images, "images") class_formatter = ClassFormatter.new(relations, doc_formatter) Loading lib/jsduck/doc_formatter.rb +10 −13 Original line number Diff line number Diff line Loading @@ -3,6 +3,8 @@ require 'strscan' require 'rdiscount' require 'jsduck/html_stack' require 'jsduck/inline/link' require 'jsduck/inline/auto_link' require 'jsduck/inline/link_renderer' require 'jsduck/inline/img' require 'jsduck/inline/video' require 'jsduck/inline/example' Loading @@ -15,9 +17,11 @@ module JsDuck # Creates a formatter configured with options originating from # command line. For the actual effect of the options see # Inline::* classes. def initialize(opts={}) def initialize(relations={}, opts={}) @opts = opts @inline_link = Inline::Link.new(opts) @link_renderer = Inline::LinkRenderer.new(relations, opts) @inline_link = Inline::Link.new(@link_renderer) @auto_link = Inline::AutoLink.new(@link_renderer) @inline_img = Inline::Img.new(opts) @inline_video = Inline::Video.new(opts) @inline_example = Inline::Example.new(opts) Loading @@ -37,6 +41,7 @@ module JsDuck # Context#blah is meant. def class_context=(cls) @inline_link.class_context = cls @auto_link.class_context = cls end # Sets up instance to work in context of particular doc object. Loading @@ -45,6 +50,7 @@ module JsDuck @doc_context = doc @inline_video.doc_context = doc @inline_link.doc_context = doc @auto_link.doc_context = doc @inline_img.doc_context = doc end Loading @@ -53,15 +59,6 @@ module JsDuck @doc_context end # JsDuck::Relations for looking up class names. # # When auto-creating class links from CamelCased names found from # text, we check the relations object to see if a class with that # name actually exists. def relations=(relations) @inline_link.relations = relations end # Formats doc-comment for placement into HTML. # Renders it with Markdown-formatter and replaces @link-s. def format(input) Loading Loading @@ -127,7 +124,7 @@ module JsDuck # Replace class names in the following text up to next "<" or "{" # but only when we're not inside <a>...</a> text = s.scan(/[^{<]+/) out += tags.open?("a") ? text : @inline_link.create_magic_links(text) out += tags.open?("a") ? text : @auto_link.replace(text) end end Loading @@ -136,7 +133,7 @@ module JsDuck # Creates a link based on the link template. def link(cls, member, anchor_text, type=nil, static=nil) @inline_link.link(cls, member, anchor_text, type, static) @link_renderer.link(cls, member, anchor_text, type, static) end end Loading lib/jsduck/inline/auto_link.rb 0 → 100644 +106 −0 Original line number Diff line number Diff line require 'jsduck/logger' module JsDuck module Inline # Takes care of the auto-detection of links in text. class AutoLink # Sets up instance to work in context of particular class, so it # knows that #blah is in context of SomeClass. attr_accessor :class_context # Sets up instance to work in context of particular doc object. # Used for error reporting. attr_accessor :doc_context def initialize(link_renderer) @class_context = "" @doc_context = {} @relations = link_renderer.relations @renderer = link_renderer @magic_link_re = magic_link_re end # Looks input text for patterns like: # # My.ClassName # MyClass#method # #someProperty # # and converts them to links, as if they were surrounded with # {@link} tag. One notable exception is that Foo is not created to # link, even when Foo class exists, but Foo.Bar is. This is to # avoid turning normal words into links. For example: # # Math involves a lot of numbers. Ext JS is a JavaScript framework. # # In these sentences we don't want to link "Math" and "Ext" to the # corresponding JS classes. And that's why we auto-link only # class names containing a dot "." # def replace(input) input.gsub(@magic_link_re) do cls = $1 || $3 member = $2 || $4 replace_magic_link(cls, member) end end private # Generates regex for auto-linking class and member names in text. def magic_link_re ident_re = "(?:[A-Za-z_$][A-Za-z0-9_$]*)" cls_re = "(#{ident_re}(?:\\.#{ident_re})*)" ns_cls_re = "(#{ident_re}(?:\\.#{ident_re})+)" member_re = "(?:#(#{ident_re}))" /#{cls_re}#{member_re}|#{ns_cls_re}|#{member_re}/m end def replace_magic_link(cls, member) if cls && member if @relations[cls] && @renderer.get_matching_member(cls, {:name => member}) return @renderer.link(cls, member, cls+"."+member) else warn_magic_link("#{cls}##{member} links to non-existing " + (@relations[cls] ? "member" : "class")) end elsif cls if @relations[cls] return @renderer.link(cls, nil, cls) else cls2, member2 = split_to_cls_and_member(cls) if @relations[cls2] && @renderer.get_matching_member(cls2, {:name => member2}) return @renderer.link(cls2, member2, cls2+"."+member2) elsif cls =~ /\.(js|css|html|php)\Z/ # Ignore common filenames else warn_magic_link("#{cls} links to non-existing class") end end else if @renderer.get_matching_member(@class_context, {:name => member}) return @renderer.link(@class_context, member, member) elsif member =~ /\A([A-F0-9]{3}|[A-F0-9]{6})\Z/i || member =~ /\A[0-9]/ # Ignore HEX color codes and # member names beginning with number else warn_magic_link("##{member} links to non-existing member") end end return "#{cls}#{member ? '#' : ''}#{member}" end def split_to_cls_and_member(str) parts = str.split(/\./) return [parts.slice(0, parts.length-1).join("."), parts.last] end def warn_magic_link(msg) Logger.warn(:link_auto, msg, @doc_context[:filename], @doc_context[:linenr]) end end end end lib/jsduck/inline/link.rb +6 −132 Original line number Diff line number Diff line require 'jsduck/util/html' require 'jsduck/logger' require 'jsduck/tag_registry' Loading @@ -19,28 +18,11 @@ module JsDuck # Used for error reporting. attr_accessor :doc_context # JsDuck::Relations for looking up class names. # # When auto-creating class links from CamelCased names found from # text, we check the relations object to see if a class with that # name actually exists. attr_accessor :relations def initialize(opts={}) def initialize(link_renderer) @class_context = "" @doc_context = {} @relations = {} # Template HTML that replaces {@link Class#member anchor text}. # Can contain placeholders: # # %c - full class name (e.g. "Ext.Panel") # %m - class member name prefixed with member type (e.g. "method-urlEncode") # %# - inserts "#" if member name present # %- - inserts "-" if member name present # %a - anchor text for link @tpl = opts[:link_tpl] || '<a href="%c%#%m">%a</a>' @relations = link_renderer.relations @renderer = link_renderer @re = /\{@link\s+(\S*?)(?:\s+(.+?))?\}/m end Loading Loading @@ -86,7 +68,7 @@ module JsDuck Logger.warn(:link, "#{full_link} links to non-existing class", file, line) return text elsif member ms = find_members(cls, {:name => member, :tagname => type, :static => static}) ms = @renderer.find_members(cls, {:name => member, :tagname => type, :static => static}) if ms.length == 0 Logger.warn(:link, "#{full_link} links to non-existing member", file, line) return text Loading @@ -108,118 +90,10 @@ module JsDuck end end return link(cls, member, text, type, static) return @renderer.link(cls, member, text, type, static) else return link(cls, false, text) end return @renderer.link(cls, false, text) end # Looks input text for patterns like: # # My.ClassName # MyClass#method # #someProperty # # and converts them to links, as if they were surrounded with # {@link} tag. One notable exception is that Foo is not created to # link, even when Foo class exists, but Foo.Bar is. This is to # avoid turning normal words into links. For example: # # Math involves a lot of numbers. Ext JS is a JavaScript framework. # # In these sentences we don't want to link "Math" and "Ext" to the # corresponding JS classes. And that's why we auto-link only # class names containing a dot "." # def create_magic_links(input) cls_re = "([A-Z][A-Za-z0-9.]*[A-Za-z0-9])" member_re = "(?:#([A-Za-z0-9]+))" input.gsub(/\b#{cls_re}#{member_re}?\b|#{member_re}\b/m) do replace_magic_link($1, $2 || $3) end end def replace_magic_link(cls, member) if cls && member if @relations[cls] && get_matching_member(cls, {:name => member}) return link(cls, member, cls+"."+member) else warn_magic_link("#{cls}##{member} links to non-existing " + (@relations[cls] ? "member" : "class")) end elsif cls && cls =~ /\./ if @relations[cls] return link(cls, nil, cls) else cls2, member2 = split_to_cls_and_member(cls) if @relations[cls2] && get_matching_member(cls2, {:name => member2}) return link(cls2, member2, cls2+"."+member2) elsif cls =~ /\.(js|css|html|php)\Z/ # Ignore common filenames else warn_magic_link("#{cls} links to non-existing class") end end elsif !cls && member if get_matching_member(@class_context, {:name => member}) return link(@class_context, member, member) elsif member =~ /\A([A-F0-9]{3}|[A-F0-9]{6})\Z/i || member =~ /\A[0-9]/ # Ignore HEX color codes and # member names beginning with number else warn_magic_link("##{member} links to non-existing member") end end return "#{cls}#{member ? '#' : ''}#{member}" end def split_to_cls_and_member(str) parts = str.split(/\./) return [parts.slice(0, parts.length-1).join("."), parts.last] end def warn_magic_link(msg) Logger.warn(:link_auto, msg, @doc_context[:filename], @doc_context[:linenr]) end # applies the link template def link(cls, member, anchor_text, type=nil, static=nil) # Use the canonical class name for link (not some alternateClassName) cls = @relations[cls][:name] # prepend type name to member name member = member && get_matching_member(cls, {:name => member, :tagname => type, :static => static}) @tpl.gsub(/(%[\w#-])/) do case $1 when '%c' cls when '%m' member ? member[:id] : "" when '%#' member ? "#" : "" when '%-' member ? "-" : "" when '%a' Util::HTML.escape(anchor_text||"") else $1 end end end def get_matching_member(cls, query) ms = find_members(cls, query) if ms.length > 1 instance_ms = ms.find_all {|m| !m[:static] } instance_ms.length > 0 ? instance_ms[0] : ms.find_all {|m| m[:static] }[0] else ms[0] end end def find_members(cls, query) @relations[cls] ? @relations[cls].find_members(query) : [] end end Loading Loading
lib/jsduck/assets.rb +1 −2 Original line number Diff line number Diff line Loading @@ -27,8 +27,7 @@ module JsDuck @relations = relations @opts = opts doc_formatter = DocFormatter.new(@opts) doc_formatter.relations = @relations doc_formatter = DocFormatter.new(@relations, @opts) @images = Img::DirSet.new(@opts.images, "images") @welcome = Welcome.create(@opts.welcome, doc_formatter) Loading
lib/jsduck/batch_formatter.rb +1 −2 Original line number Diff line number Diff line Loading @@ -45,8 +45,7 @@ module JsDuck # Factory method to create new ClassFormatter instances. def self.create_class_formatter(relations, opts) doc_formatter = DocFormatter.new(opts) doc_formatter.relations = relations doc_formatter = DocFormatter.new(relations, opts) doc_formatter.images = Img::DirSet.new(opts.images, "images") class_formatter = ClassFormatter.new(relations, doc_formatter) Loading
lib/jsduck/doc_formatter.rb +10 −13 Original line number Diff line number Diff line Loading @@ -3,6 +3,8 @@ require 'strscan' require 'rdiscount' require 'jsduck/html_stack' require 'jsduck/inline/link' require 'jsduck/inline/auto_link' require 'jsduck/inline/link_renderer' require 'jsduck/inline/img' require 'jsduck/inline/video' require 'jsduck/inline/example' Loading @@ -15,9 +17,11 @@ module JsDuck # Creates a formatter configured with options originating from # command line. For the actual effect of the options see # Inline::* classes. def initialize(opts={}) def initialize(relations={}, opts={}) @opts = opts @inline_link = Inline::Link.new(opts) @link_renderer = Inline::LinkRenderer.new(relations, opts) @inline_link = Inline::Link.new(@link_renderer) @auto_link = Inline::AutoLink.new(@link_renderer) @inline_img = Inline::Img.new(opts) @inline_video = Inline::Video.new(opts) @inline_example = Inline::Example.new(opts) Loading @@ -37,6 +41,7 @@ module JsDuck # Context#blah is meant. def class_context=(cls) @inline_link.class_context = cls @auto_link.class_context = cls end # Sets up instance to work in context of particular doc object. Loading @@ -45,6 +50,7 @@ module JsDuck @doc_context = doc @inline_video.doc_context = doc @inline_link.doc_context = doc @auto_link.doc_context = doc @inline_img.doc_context = doc end Loading @@ -53,15 +59,6 @@ module JsDuck @doc_context end # JsDuck::Relations for looking up class names. # # When auto-creating class links from CamelCased names found from # text, we check the relations object to see if a class with that # name actually exists. def relations=(relations) @inline_link.relations = relations end # Formats doc-comment for placement into HTML. # Renders it with Markdown-formatter and replaces @link-s. def format(input) Loading Loading @@ -127,7 +124,7 @@ module JsDuck # Replace class names in the following text up to next "<" or "{" # but only when we're not inside <a>...</a> text = s.scan(/[^{<]+/) out += tags.open?("a") ? text : @inline_link.create_magic_links(text) out += tags.open?("a") ? text : @auto_link.replace(text) end end Loading @@ -136,7 +133,7 @@ module JsDuck # Creates a link based on the link template. def link(cls, member, anchor_text, type=nil, static=nil) @inline_link.link(cls, member, anchor_text, type, static) @link_renderer.link(cls, member, anchor_text, type, static) end end Loading
lib/jsduck/inline/auto_link.rb 0 → 100644 +106 −0 Original line number Diff line number Diff line require 'jsduck/logger' module JsDuck module Inline # Takes care of the auto-detection of links in text. class AutoLink # Sets up instance to work in context of particular class, so it # knows that #blah is in context of SomeClass. attr_accessor :class_context # Sets up instance to work in context of particular doc object. # Used for error reporting. attr_accessor :doc_context def initialize(link_renderer) @class_context = "" @doc_context = {} @relations = link_renderer.relations @renderer = link_renderer @magic_link_re = magic_link_re end # Looks input text for patterns like: # # My.ClassName # MyClass#method # #someProperty # # and converts them to links, as if they were surrounded with # {@link} tag. One notable exception is that Foo is not created to # link, even when Foo class exists, but Foo.Bar is. This is to # avoid turning normal words into links. For example: # # Math involves a lot of numbers. Ext JS is a JavaScript framework. # # In these sentences we don't want to link "Math" and "Ext" to the # corresponding JS classes. And that's why we auto-link only # class names containing a dot "." # def replace(input) input.gsub(@magic_link_re) do cls = $1 || $3 member = $2 || $4 replace_magic_link(cls, member) end end private # Generates regex for auto-linking class and member names in text. def magic_link_re ident_re = "(?:[A-Za-z_$][A-Za-z0-9_$]*)" cls_re = "(#{ident_re}(?:\\.#{ident_re})*)" ns_cls_re = "(#{ident_re}(?:\\.#{ident_re})+)" member_re = "(?:#(#{ident_re}))" /#{cls_re}#{member_re}|#{ns_cls_re}|#{member_re}/m end def replace_magic_link(cls, member) if cls && member if @relations[cls] && @renderer.get_matching_member(cls, {:name => member}) return @renderer.link(cls, member, cls+"."+member) else warn_magic_link("#{cls}##{member} links to non-existing " + (@relations[cls] ? "member" : "class")) end elsif cls if @relations[cls] return @renderer.link(cls, nil, cls) else cls2, member2 = split_to_cls_and_member(cls) if @relations[cls2] && @renderer.get_matching_member(cls2, {:name => member2}) return @renderer.link(cls2, member2, cls2+"."+member2) elsif cls =~ /\.(js|css|html|php)\Z/ # Ignore common filenames else warn_magic_link("#{cls} links to non-existing class") end end else if @renderer.get_matching_member(@class_context, {:name => member}) return @renderer.link(@class_context, member, member) elsif member =~ /\A([A-F0-9]{3}|[A-F0-9]{6})\Z/i || member =~ /\A[0-9]/ # Ignore HEX color codes and # member names beginning with number else warn_magic_link("##{member} links to non-existing member") end end return "#{cls}#{member ? '#' : ''}#{member}" end def split_to_cls_and_member(str) parts = str.split(/\./) return [parts.slice(0, parts.length-1).join("."), parts.last] end def warn_magic_link(msg) Logger.warn(:link_auto, msg, @doc_context[:filename], @doc_context[:linenr]) end end end end
lib/jsduck/inline/link.rb +6 −132 Original line number Diff line number Diff line require 'jsduck/util/html' require 'jsduck/logger' require 'jsduck/tag_registry' Loading @@ -19,28 +18,11 @@ module JsDuck # Used for error reporting. attr_accessor :doc_context # JsDuck::Relations for looking up class names. # # When auto-creating class links from CamelCased names found from # text, we check the relations object to see if a class with that # name actually exists. attr_accessor :relations def initialize(opts={}) def initialize(link_renderer) @class_context = "" @doc_context = {} @relations = {} # Template HTML that replaces {@link Class#member anchor text}. # Can contain placeholders: # # %c - full class name (e.g. "Ext.Panel") # %m - class member name prefixed with member type (e.g. "method-urlEncode") # %# - inserts "#" if member name present # %- - inserts "-" if member name present # %a - anchor text for link @tpl = opts[:link_tpl] || '<a href="%c%#%m">%a</a>' @relations = link_renderer.relations @renderer = link_renderer @re = /\{@link\s+(\S*?)(?:\s+(.+?))?\}/m end Loading Loading @@ -86,7 +68,7 @@ module JsDuck Logger.warn(:link, "#{full_link} links to non-existing class", file, line) return text elsif member ms = find_members(cls, {:name => member, :tagname => type, :static => static}) ms = @renderer.find_members(cls, {:name => member, :tagname => type, :static => static}) if ms.length == 0 Logger.warn(:link, "#{full_link} links to non-existing member", file, line) return text Loading @@ -108,118 +90,10 @@ module JsDuck end end return link(cls, member, text, type, static) return @renderer.link(cls, member, text, type, static) else return link(cls, false, text) end return @renderer.link(cls, false, text) end # Looks input text for patterns like: # # My.ClassName # MyClass#method # #someProperty # # and converts them to links, as if they were surrounded with # {@link} tag. One notable exception is that Foo is not created to # link, even when Foo class exists, but Foo.Bar is. This is to # avoid turning normal words into links. For example: # # Math involves a lot of numbers. Ext JS is a JavaScript framework. # # In these sentences we don't want to link "Math" and "Ext" to the # corresponding JS classes. And that's why we auto-link only # class names containing a dot "." # def create_magic_links(input) cls_re = "([A-Z][A-Za-z0-9.]*[A-Za-z0-9])" member_re = "(?:#([A-Za-z0-9]+))" input.gsub(/\b#{cls_re}#{member_re}?\b|#{member_re}\b/m) do replace_magic_link($1, $2 || $3) end end def replace_magic_link(cls, member) if cls && member if @relations[cls] && get_matching_member(cls, {:name => member}) return link(cls, member, cls+"."+member) else warn_magic_link("#{cls}##{member} links to non-existing " + (@relations[cls] ? "member" : "class")) end elsif cls && cls =~ /\./ if @relations[cls] return link(cls, nil, cls) else cls2, member2 = split_to_cls_and_member(cls) if @relations[cls2] && get_matching_member(cls2, {:name => member2}) return link(cls2, member2, cls2+"."+member2) elsif cls =~ /\.(js|css|html|php)\Z/ # Ignore common filenames else warn_magic_link("#{cls} links to non-existing class") end end elsif !cls && member if get_matching_member(@class_context, {:name => member}) return link(@class_context, member, member) elsif member =~ /\A([A-F0-9]{3}|[A-F0-9]{6})\Z/i || member =~ /\A[0-9]/ # Ignore HEX color codes and # member names beginning with number else warn_magic_link("##{member} links to non-existing member") end end return "#{cls}#{member ? '#' : ''}#{member}" end def split_to_cls_and_member(str) parts = str.split(/\./) return [parts.slice(0, parts.length-1).join("."), parts.last] end def warn_magic_link(msg) Logger.warn(:link_auto, msg, @doc_context[:filename], @doc_context[:linenr]) end # applies the link template def link(cls, member, anchor_text, type=nil, static=nil) # Use the canonical class name for link (not some alternateClassName) cls = @relations[cls][:name] # prepend type name to member name member = member && get_matching_member(cls, {:name => member, :tagname => type, :static => static}) @tpl.gsub(/(%[\w#-])/) do case $1 when '%c' cls when '%m' member ? member[:id] : "" when '%#' member ? "#" : "" when '%-' member ? "-" : "" when '%a' Util::HTML.escape(anchor_text||"") else $1 end end end def get_matching_member(cls, query) ms = find_members(cls, query) if ms.length > 1 instance_ms = ms.find_all {|m| !m[:static] } instance_ms.length > 0 ? instance_ms[0] : ms.find_all {|m| m[:static] }[0] else ms[0] end end def find_members(cls, query) @relations[cls] ? @relations[cls].find_members(query) : [] end end Loading