Commit a978069d authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Define member subsections in Tag#member_type config.

No more special casing for config options subsections - the Tag::Cfg
just defines different rules for splitting members into subsections.

Instance/Static subsections are now only defined for properties and
methods.  Events and CSS members will be listed without subsectioning.
parent 08e380b2
Loading
Loading
Loading
Loading
+31 −26
Original line number Diff line number Diff line
@@ -45,43 +45,48 @@ module JsDuck
      end

      def render_section(sec)
        # We have special logic for configs.
        return render_configs_section if sec[:name] == :cfg

        members = @cls[:members][sec[:name]]
        statics = @cls[:statics][sec[:name]]
        members = @cls[:members][sec[:name]] + @cls[:statics][sec[:name]]

        # Skip rendering empty sections
        if members.length > 0 || statics.length > 0
        return [] if members.length == 0

        # Split members array into subsections
        subsections = Array(sec[:subsections]).map do |subsec|
          ms = members.find_all {|m| test_filter(m, subsec[:filter]) }
          if ms.length > 0
            {:title => subsec[:title], :members => ms, :default => subsec[:default]}
          else
            nil
          end
        end.compact

        # Print no subsections when no subsections defined or there's
        # just single subsection which is the default one.
        if subsections.length == 0 || subsections.length == 1 && subsections[0][:default]
          return [
            "<div class='members-section'>",
              statics.length == 0 ? "<div class='definedBy'>Defined By</div>" : "",
              "<div class='definedBy'>Defined By</div>",
              "<h3 class='members-title icon-#{sec[:name]}'>#{sec[:title]}</h3>",
              render_subsection(members, statics.length > 0 ? "Instance #{sec[:title]}" : nil),
              render_subsection(statics, "Static #{sec[:title]}"),
              render_subsection(members, nil),
            "</div>",
          ]
        else
          return []
        end
      end

      def render_configs_section
        configs = @cls[:members][:cfg] + @cls[:statics][:cfg]

        if configs.length > 0
          required, optional = configs.partition {|c| c[:required] }
        return [
          "<div class='members-section'>",
              required.length == 0 ? "<div class='definedBy'>Defined By</div>" : "",
              "<h3 class='members-title icon-cfg'>Config options</h3>",
              render_subsection(required, "Required Config options"),
              render_subsection(optional, required.length > 0 ? "Optional Config options" : nil),
          "<h3 class='members-title icon-#{sec[:name]}'>#{sec[:title]}</h3>",
          subsections.map {|ss| render_subsection(ss[:members], ss[:title]) },
          "</div>",
        ]
        else
          return []
      end

      # Returns true if member matches the conditions described by a
      # subsection filter.
      def test_filter(member, filter)
        filter.each_pair do |field, truthy|
          return false unless truthy ? member[field] : !member[field]
        end
        return true
      end

      def render_subsection(members, title)
+4 −0
Original line number Diff line number Diff line
@@ -12,6 +12,10 @@ module JsDuck::Tag
        :title => "Config options",
        :toolbar_title => "Configs",
        :position => MEMBER_POS_CFG,
        :subsections => [
          {:title => "Required config options", :filter => {:required => true}},
          {:title => "Optional config options", :filter => {:required => false}, :default => true},
        ]
      }
    end

+4 −0
Original line number Diff line number Diff line
@@ -11,6 +11,10 @@ module JsDuck::Tag
        :category => :method_like,
        :title => "Methods",
        :position => MEMBER_POS_METHOD,
        :subsections => [
          {:title => "Instance methods", :filter => {:static => false}, :default => true},
          {:title => "Static methods", :filter => {:static => true}},
        ]
      }
    end

+4 −0
Original line number Diff line number Diff line
@@ -11,6 +11,10 @@ module JsDuck::Tag
        :category => :property_like,
        :title => "Properties",
        :position => MEMBER_POS_PROPERTY,
        :subsections => [
          {:title => "Instance properties", :filter => {:static => false}, :default => true},
          {:title => "Static properties", :filter => {:static => true}},
        ]
      }
    end

+36 −9
Original line number Diff line number Diff line
@@ -39,23 +39,50 @@ module JsDuck::Tag
    def process_doc(hash, docs, position)
    end

    # Defines that the tag defines a class member and specifies a name
    # and category for the member type.  For example:
    # Defines a class member type and specifies a name and several
    # other settings.  For example:
    #
    #     {
    #       :name => :event,
    #       :category => :method_like,
    #       :title => "Events",
    #         :toolbar_title => "Events", // optional
    #       :position => MEMBER_POS_EVENT,
    #       # The following are optional
    #       :toolbar_title => "Events",
    #       :subsections => [
    #         {:title => "Static events",
    #          :filter => {:static => false},
    #          :default => true},
    #         {:title => "Instance events",
    #          :filter => {:static => true}},
    #       ]
    #     }
    #
    # The category must be either :property_like or :method_like.
    #
    # Position defines the ordering of member section in final HTML
    # output.  Title is shown at the top of each such section and also
    # as a label on Docs app toolbar button unless :toolbar_title is
    # output.
    #
    # Title is shown at the top of each such section and also as a
    # label on Docs app toolbar button unless :toolbar_title is
    # specified.
    #
    # Subsections allows splitting the list of members to several
    # subgroups.  For example methods get split into static and
    # instance methods.
    #
    # - The :filter field defines how to filter out the members for
    #   this subcategory.  :static=>true filters out all members that
    #   have a :static field with a truthy value.  Conversely,
    #   :static=>false filters out members not having a :static field
    #   or having it with a falsy value.
    #
    # - Setting :default=>true will hide the subsection title when all
    #   the members end up in that subsection.  For example when there
    #   are only instance methods, the docs will only contain the
    #   section title "Methods", as by default one should assume all
    #   methods are instance methods if not stated otherwise.
    #
    attr_reader :member_type

    MEMBER_POS_CFG = 1