arbre-1.2.1/0000755000175000017500000000000013523740213012142 5ustar samyaksamyakarbre-1.2.1/LICENSE0000644000175000017500000000203513523740213013147 0ustar samyaksamyakCopyright (c) 2013 Greg Bell Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. arbre-1.2.1/.travis.yml0000644000175000017500000000034713523740213014257 0ustar samyaksamyaklanguage: ruby sudo: false before_install: - gem update --system 3.0.3 - gem install bundler:2.0.1 rvm: - 2.3.8 - 2.4.5 - 2.5.5 - 2.6.2 - jruby-9.1.17.0 - jruby-9.2.6.0 branches: only: - master cache: bundler arbre-1.2.1/.rubocop.yml0000644000175000017500000000026713523740213014421 0ustar samyaksamyak--- AllCops: DisabledByDefault: true DisplayCopNames: true DisplayStyleGuide: true TargetRubyVersion: 2.3 Metrics: Enabled: false Layout/IndentHeredoc: Enabled: true arbre-1.2.1/tasks/0000755000175000017500000000000013523740213013267 5ustar samyaksamyakarbre-1.2.1/tasks/release.rake0000644000175000017500000000020113523740213015544 0ustar samyaksamyakrequire "chandler/tasks" # # Add chandler as a prerequisite for `rake release` # task "release:rubygem_push" => "chandler:push" arbre-1.2.1/tasks/lint.rake0000644000175000017500000000234413523740213015104 0ustar samyaksamyakrequire "open3" # # Common stuff for a linter # module LinterMixin def run offenses = [] applicable_files.each do |file| if clean?(file) print "." else offenses << file print "F" end end print "\n" return if offenses.empty? raise failure_message_for(offenses) end private def applicable_files Open3.capture2("git grep -Il ''")[0].split end def failure_message_for(offenses) msg = "#{self.class.name} detected offenses. " msg += if respond_to?(:fixing_cmd) "Run `#{fixing_cmd(offenses)}` to fix them." else "Affected files: #{offenses.join(' ')}" end msg end end # # Checks trailing new lines in files # class MissingTrailingCarriageReturn include LinterMixin def clean?(file) File.read(file) =~ /\n\Z/m end end require 'rubocop/rake_task' RuboCop::RakeTask.new desc "Lints ActiveAdmin code base" task lint: ["rubocop", "lint:missing_trailing_carriage_return"] namespace :lint do desc "Check for missing trailing new lines" task :missing_trailing_carriage_return do puts "Checking for missing trailing carriage returns..." MissingTrailingCarriageReturn.new.run end end arbre-1.2.1/lib/0000755000175000017500000000000013523740213012710 5ustar samyaksamyakarbre-1.2.1/lib/arbre.rb0000644000175000017500000000072713523740213014336 0ustar samyaksamyakrequire 'active_support/core_ext/string/output_safety' require 'active_support/hash_with_indifferent_access' require 'active_support/inflector' module Arbre end require 'arbre/element' require 'arbre/context' require 'arbre/html/attributes' require 'arbre/html/class_list' require 'arbre/html/tag' require 'arbre/html/text_node' require 'arbre/html/document' require 'arbre/html/html5_elements' require 'arbre/component' if defined?(Rails) require 'arbre/rails' end arbre-1.2.1/lib/arbre/0000755000175000017500000000000013523740213014003 5ustar samyaksamyakarbre-1.2.1/lib/arbre/element/0000755000175000017500000000000013523740213015434 5ustar samyaksamyakarbre-1.2.1/lib/arbre/element/builder_methods.rb0000644000175000017500000000422513523740213021135 0ustar samyaksamyakmodule Arbre class Element module BuilderMethods def self.included(klass) klass.extend ClassMethods end module ClassMethods def builder_method(method_name) BuilderMethods.class_eval <<-EOF, __FILE__, __LINE__ def #{method_name}(*args, &block) insert_tag ::#{self.name}, *args, &block end EOF end end def build_tag(klass, *args, &block) tag = klass.new(arbre_context) tag.parent = current_arbre_element with_current_arbre_element tag do if block_given? && block.arity > 0 tag.build(*args, &block) else tag.build(*args) append_return_block(yield) if block_given? end end tag end def insert_tag(klass, *args, &block) tag = build_tag(klass, *args, &block) current_arbre_element.add_child(tag) tag end def current_arbre_element arbre_context.current_arbre_element end def with_current_arbre_element(tag, &block) arbre_context.with_current_arbre_element(tag, &block) end alias_method :within, :with_current_arbre_element private # Appends the value to the current DOM element if there are no # existing DOM Children and it responds to #to_s def append_return_block(tag) return nil if current_arbre_element.children? if appendable_tag?(tag) current_arbre_element << Arbre::HTML::TextNode.from_string(tag.to_s) end end # Returns true if the object should be converted into a text node # and appended into the DOM. def appendable_tag?(tag) # Array.new.to_s prints out an empty array ("[]"). In # Arbre, we append the return value of blocks to the output, which # can cause empty arrays to show up within the output. To get # around this, we check if the object responds to #empty? if tag.respond_to?(:empty?) && tag.empty? false else !tag.is_a?(Arbre::Element) && tag.respond_to?(:to_s) end end end end end arbre-1.2.1/lib/arbre/element/proxy.rb0000644000175000017500000000110313523740213017135 0ustar samyaksamyakmodule Arbre class Element class Proxy < BasicObject undef_method :== undef_method :equal? def initialize(element) @element = element end def respond_to?(method, include_all = false) if method.to_s == 'to_ary' false else super || @element.respond_to?(method, include_all) end end def method_missing(method, *args, &block) if method.to_s == 'to_ary' super else @element.__send__ method, *args, &block end end end end end arbre-1.2.1/lib/arbre/component.rb0000644000175000017500000000056613523740213016341 0ustar samyaksamyakmodule Arbre class Component < Arbre::HTML::Div # By default components render a div def tag_name 'div' end def initialize(*) super add_class default_class_name end protected # By default, add a css class named after the ruby class def default_class_name self.class.name.demodulize.underscore end end end arbre-1.2.1/lib/arbre/rails.rb0000644000175000017500000000023213523740213015437 0ustar samyaksamyakrequire 'arbre/rails/template_handler' require 'arbre/rails/forms' require 'arbre/rails/rendering' Arbre::Element.send :include, Arbre::Rails::Rendering arbre-1.2.1/lib/arbre/html/0000755000175000017500000000000013523740213014747 5ustar samyaksamyakarbre-1.2.1/lib/arbre/html/text_node.rb0000644000175000017500000000107413523740213017267 0ustar samyaksamyakrequire 'erb' module Arbre module HTML class TextNode < Element builder_method :text_node # Builds a text node from a string def self.from_string(string) node = new node.build(string) node end def add_child(*args) raise "TextNodes do not have children" end def build(string) @content = string end def class_list [] end def tag_name nil end def to_s ERB::Util.html_escape(@content.to_s) end end end end arbre-1.2.1/lib/arbre/html/class_list.rb0000644000175000017500000000064613523740213017442 0ustar samyaksamyakrequire 'set' module Arbre module HTML # Holds a set of classes class ClassList < Set def self.build_from_string(class_names) new.add(class_names) end def add(class_names) class_names.to_s.split(" ").each do |class_name| super(class_name) end self end alias :<< :add def to_s to_a.join(" ") end end end end arbre-1.2.1/lib/arbre/html/tag.rb0000644000175000017500000001036113523740213016050 0ustar samyaksamyakrequire 'erb' module Arbre module HTML class Tag < Element attr_reader :attributes # See: http://www.w3.org/html/wg/drafts/html/master/syntax.html#void-elements SELF_CLOSING_ELEMENTS = [ :area, :base, :br, :col, :embed, :hr, :img, :input, :keygen, :link, :menuitem, :meta, :param, :source, :track, :wbr ] def initialize(*) super @attributes = Attributes.new end def build(*args) super attributes = extract_arguments(args) self.content = args.first if args.first for_value = attributes[:for] unless for_value.is_a?(String) || for_value.is_a?(Symbol) set_for_attribute(attributes.delete(:for)) end attributes.each do |key, value| set_attribute(key, value) end end def extract_arguments(args) if args.last.is_a?(Hash) args.pop else {} end end def set_attribute(name, value) @attributes[name.to_sym] = value end def get_attribute(name) @attributes[name.to_sym] end alias :attr :get_attribute def has_attribute?(name) @attributes.has_key?(name.to_sym) end def remove_attribute(name) @attributes.delete(name.to_sym) end def id get_attribute(:id) end # Generates and id for the object if it doesn't exist already def id! return id if id self.id = object_id.to_s id end def id=(id) set_attribute(:id, id) end def add_class(class_names) class_list.add class_names end def remove_class(class_names) class_list.delete(class_names) end # Returns a string of classes def class_names class_list.to_s end def class_list list = get_attribute(:class) case list when ClassList list when String set_attribute(:class, ClassList.build_from_string(list)) else set_attribute(:class, ClassList.new) end end def to_s indent(opening_tag, content, closing_tag).html_safe end private def opening_tag "<#{tag_name}#{attributes_html}>" end def closing_tag "" end INDENT_SIZE = 2 def indent(open_tag, child_content, close_tag) spaces = ' ' * indent_level * INDENT_SIZE html = "" if no_child? || child_is_text? if self_closing_tag? html << spaces << open_tag.sub( />$/, '/>' ) else # one line html << spaces << open_tag << child_content << close_tag end else # multiple lines html << spaces << open_tag << "\n" html << child_content # the child takes care of its own spaces html << spaces << close_tag end html << "\n" html end def self_closing_tag? SELF_CLOSING_ELEMENTS.include?(tag_name.to_sym) end def no_child? children.empty? end def child_is_text? children.size == 1 && children.first.is_a?(TextNode) end def attributes_html " #{attributes}" if attributes.any? end def set_for_attribute(record) return unless record # set_attribute :id, ActionController::RecordIdentifier.dom_id(record, default_id_for_prefix) # add_class ActionController::RecordIdentifier.dom_class(record) set_attribute :id, dom_id_for(record) add_class dom_class_name_for(record) end def dom_class_name_for(record) if record.class.respond_to?(:model_name) record.class.model_name.singular else record.class.name.underscore.gsub("/", "_") end end def dom_id_for(record) id = if record.respond_to?(:to_key) record.to_key elsif record.respond_to?(:id) record.id else record.object_id end [default_id_for_prefix, dom_class_name_for(record), id].compact.join("_") end def default_id_for_prefix nil end end end end arbre-1.2.1/lib/arbre/html/document.rb0000644000175000017500000000110713523740213017111 0ustar samyaksamyakmodule Arbre module HTML class Document < Tag def build(*args) super build_head build_body end def document self end def tag_name 'html' end def doctype ''.html_safe end def to_s doctype + super end protected def build_head @head = head do meta :"http-equiv" => "Content-type", content: "text/html; charset=utf-8" end end def build_body @body = body end end end end arbre-1.2.1/lib/arbre/html/html5_elements.rb0000644000175000017500000000321713523740213020224 0ustar samyaksamyakmodule Arbre module HTML AUTO_BUILD_ELEMENTS = [ :a, :abbr, :address, :area, :article, :aside, :audio, :b, :base, :bdo, :blockquote, :body, :br, :button, :canvas, :caption, :cite, :code, :col, :colgroup, :command, :datalist, :dd, :del, :details, :dfn, :div, :dl, :dt, :em, :embed, :fieldset, :figcaption, :figure, :footer, :form, :h1, :h2, :h3, :h4, :h5, :h6, :head, :header, :hgroup, :hr, :html, :i, :iframe, :img, :input, :ins, :keygen, :kbd, :label, :legend, :li, :link, :map, :mark, :menu, :menuitem, :meta, :meter, :nav, :noscript, :object, :ol, :optgroup, :option, :output, :param, :pre, :progress, :q, :s, :samp, :script, :section, :select, :small, :source, :span, :strong, :style, :sub, :summary, :sup, :svg, :table, :tbody, :td, :textarea, :tfoot, :th, :thead, :time, :title, :tr, :track, :ul, :var, :video, :wbr ] HTML5_ELEMENTS = [ :p ] + AUTO_BUILD_ELEMENTS AUTO_BUILD_ELEMENTS.each do |name| class_eval <<-EOF class #{name.to_s.capitalize} < Tag builder_method :#{name} end EOF end class P < Tag builder_method :para end class Table < Tag def initialize(*) super set_table_tag_defaults end protected # Set some good defaults for tables def set_table_tag_defaults set_attribute :border, 0 set_attribute :cellspacing, 0 set_attribute :cellpadding, 0 end end end end arbre-1.2.1/lib/arbre/html/attributes.rb0000644000175000017500000000077413523740213017472 0ustar samyaksamyakmodule Arbre module HTML class Attributes < Hash def to_s map do |name, value| next if value_empty?(value) "#{html_escape(name)}=\"#{html_escape(value)}\"" end.compact.join ' ' end def any? super{ |k,v| !value_empty?(v) } end protected def value_empty?(value) value.respond_to?(:empty?) ? value.empty? : !value end def html_escape(s) ERB::Util.html_escape(s) end end end end arbre-1.2.1/lib/arbre/context.rb0000644000175000017500000000543613523740213016024 0ustar samyaksamyakrequire 'arbre/element' module Arbre # The Arbre::Context class is the frontend for using Arbre. # # The simplest example possible: # # html = Arbre::Context.new do # h1 "Hello World" # end # # html.to_s #=> "

Hello World

" # # The contents of the block are instance eval'd within the Context # object. This means that you lose context to the outside world from # within the block. To pass local variables into the Context, use the # assigns param. # # html = Arbre::Context.new({one: 1}) do # h1 "Your number #{one}" # end # # html.to_s #=> "Your number 1" # class Context < Element # Initialize a new Arbre::Context # # @param [Hash] assigns A hash of objecs that you would like to be # availble as local variables within the Context # # @param [Object] helpers An object that has methods on it which will become # instance methods within the context. # # @yield [] The block that will get instance eval'd in the context def initialize(assigns = {}, helpers = nil, &block) assigns = assigns || {} @_assigns = assigns.symbolize_keys @_helpers = helpers @_current_arbre_element_buffer = [self] super(self) instance_eval(&block) if block_given? end def arbre_context self end def assigns @_assigns end def helpers @_helpers end def indent_level # A context does not increment the indent_level super - 1 end def bytesize cached_html.bytesize end alias :length :bytesize def respond_to_missing?(method, include_all) super || cached_html.respond_to?(method, include_all) end # Webservers treat Arbre::Context as a string. We override # method_missing to delegate to the string representation # of the html. def method_missing(method, *args, &block) if cached_html.respond_to? method cached_html.send method, *args, &block else super end end def current_arbre_element @_current_arbre_element_buffer.last end def with_current_arbre_element(tag) raise ArgumentError, "Can't be in the context of nil. #{@_current_arbre_element_buffer.inspect}" unless tag @_current_arbre_element_buffer.push tag yield @_current_arbre_element_buffer.pop end alias_method :within, :with_current_arbre_element private # Caches the rendered HTML so that we don't re-render just to # get the content lenght or to delegate a method to the HTML def cached_html if defined?(@cached_html) @cached_html else html = to_s @cached_html = html if html.length > 0 html end end end end arbre-1.2.1/lib/arbre/version.rb0000644000175000017500000000004513523740213016014 0ustar samyaksamyakmodule Arbre VERSION = "1.2.1" end arbre-1.2.1/lib/arbre/rails/0000755000175000017500000000000013523740213015115 5ustar samyaksamyakarbre-1.2.1/lib/arbre/rails/rendering.rb0000644000175000017500000000045313523740213017421 0ustar samyaksamyakmodule Arbre module Rails module Rendering def render(*args) rendered = helpers.render(*args) case rendered when Arbre::Context current_arbre_element.add_child rendered else text_node rendered end end end end end arbre-1.2.1/lib/arbre/rails/forms.rb0000644000175000017500000000415513523740213016575 0ustar samyaksamyakmodule Arbre module Rails module Forms class FormBuilderProxy < Arbre::Component attr_reader :form_builder # Since label and select are Arbre Elements already, we must # override it here instead of letting method_missing # deal with it def label(*args) proxy_call_to_form :label, *args end def select(*args) proxy_call_to_form :select, *args end def respond_to_missing?(method, include_all) if form_builder && form_builder.respond_to?(method, include_all) true else super end end private def proxy_call_to_form(method, *args, &block) text_node form_builder.send(method, *args, &block) end def method_missing(method, *args, &block) if form_builder && form_builder.respond_to?(method) proxy_call_to_form(method, *args, &block) else super end end end class FormForProxy < FormBuilderProxy builder_method :form_for def build(resource, form_options = {}, &block) form_string = helpers.form_for(resource, form_options) do |f| @form_builder = f end @opening_tag, @closing_tag = split_string_on(form_string, "") super(&block) end def fields_for(*args, &block) insert_tag FieldsForProxy, form_builder, *args, &block end def split_string_on(string, match) return "" unless string && match part_1 = string.split(Regexp.new("#{match}\\z")).first [part_1, match] end def opening_tag @opening_tag || "" end def closing_tag @closing_tag || "" end end class FieldsForProxy < FormBuilderProxy def build(form_builder, *args, &block) form_builder.fields_for(*args) do |f| @form_builder = f end super(&block) end def to_s children.to_s end end end end end arbre-1.2.1/lib/arbre/rails/template_handler.rb0000644000175000017500000000055313523740213020755 0ustar samyaksamyakmodule Arbre module Rails class TemplateHandler def call(template, source = nil) source = template.source unless source <<-END Arbre::Context.new(assigns, self) { #{source} }.to_s END end end end end ActionView::Template.register_template_handler :arb, Arbre::Rails::TemplateHandler.new arbre-1.2.1/lib/arbre/element.rb0000644000175000017500000000756513523740213015776 0ustar samyaksamyakrequire 'arbre/element/builder_methods' require 'arbre/element/proxy' require 'arbre/element_collection' module Arbre class Element include BuilderMethods attr_reader :parent attr_reader :children, :arbre_context def initialize(arbre_context = Arbre::Context.new) @arbre_context = arbre_context @children = ElementCollection.new @parent = nil end def assigns arbre_context.assigns end def helpers arbre_context.helpers end def tag_name @tag_name ||= self.class.name.demodulize.downcase end def build(*args, &block) # Render the block passing ourselves in append_return_block(block.call(self)) if block end def add_child(child) return unless child if child.is_a?(Array) child.each{|item| add_child(item) } return @children end # If its not an element, wrap it in a TextNode unless child.is_a?(Element) child = Arbre::HTML::TextNode.from_string(child) end if child.respond_to?(:parent) # Remove the child child.parent.remove_child(child) if child.parent && child.parent != self # Set ourselves as the parent child.parent = self end @children << child end def remove_child(child) child.parent = nil if child.respond_to?(:parent=) @children.delete(child) end def <<(child) add_child(child) end def children? @children.any? end def parent=(parent) @parent = parent end def parent? !@parent.nil? end def ancestors if parent? [parent] + parent.ancestors else [] end end # TODO: Shouldn't grab whole tree def find_first_ancestor(type) ancestors.find{|a| a.is_a?(type) } end def content=(contents) clear_children! add_child(contents) end def get_elements_by_tag_name(tag_name) elements = ElementCollection.new children.each do |child| elements << child if child.tag_name == tag_name elements.concat(child.get_elements_by_tag_name(tag_name)) end elements end alias_method :find_by_tag, :get_elements_by_tag_name def get_elements_by_class_name(class_name) elements = ElementCollection.new children.each do |child| elements << child if child.class_list.include?(class_name) elements.concat(child.get_elements_by_class_name(class_name)) end elements end alias_method :find_by_class, :get_elements_by_class_name def content children.to_s end def html_safe to_s end def indent_level parent? ? parent.indent_level + 1 : 0 end def each(&block) [to_s].each(&block) end def inspect to_s end def to_str to_s end def to_s content end def +(element) case element when Element, ElementCollection else element = Arbre::HTML::TextNode.from_string(element) end to_ary + element end def to_ary ElementCollection.new [Proxy.new(self)] end alias_method :to_a, :to_ary private # Resets the Elements children def clear_children! @children.clear end # Implements the method lookup chain. When you call a method that # doesn't exist, we: # # 1. Try to call the method on the current DOM context # 2. Return an assigned variable of the same name # 3. Call the method on the helper object # 4. Call super # def method_missing(name, *args, &block) if current_arbre_element.respond_to?(name) current_arbre_element.send name, *args, &block elsif assigns && assigns.has_key?(name) assigns[name] elsif helpers.respond_to?(name) helpers.send(name, *args, &block) else super end end end end arbre-1.2.1/lib/arbre/element_collection.rb0000644000175000017500000000056013523740213020175 0ustar samyaksamyakmodule Arbre # Stores a collection of Element objects class ElementCollection < Array def +(other) self.class.new(super) end def -(other) self.class.new(super) end def &(other) self.class.new(super) end def to_s self.collect do |element| element.to_s end.join('').html_safe end end end arbre-1.2.1/Gemfile.lock0000644000175000017500000001244513523740213014372 0ustar samyaksamyakPATH remote: . specs: arbre (1.2.1) activesupport (>= 3.0.0) GEM remote: http://rubygems.org/ specs: actioncable (5.2.3) actionpack (= 5.2.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) actionmailer (5.2.3) actionpack (= 5.2.3) actionview (= 5.2.3) activejob (= 5.2.3) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) actionpack (5.2.3) actionview (= 5.2.3) activesupport (= 5.2.3) rack (~> 2.0) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) actionview (5.2.3) activesupport (= 5.2.3) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) activejob (5.2.3) activesupport (= 5.2.3) globalid (>= 0.3.6) activemodel (5.2.3) activesupport (= 5.2.3) activerecord (5.2.3) activemodel (= 5.2.3) activesupport (= 5.2.3) arel (>= 9.0) activestorage (5.2.3) actionpack (= 5.2.3) activerecord (= 5.2.3) marcel (~> 0.3.1) activesupport (5.2.3) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) addressable (2.5.2) public_suffix (>= 2.0.2, < 4.0) arel (9.0.0) ast (2.4.0) builder (3.2.3) capybara (3.15.0) addressable mini_mime (>= 0.1.3) nokogiri (~> 1.8) rack (>= 1.6.0) rack-test (>= 0.6.3) regexp_parser (~> 1.2) xpath (~> 3.2) chandler (0.9.0) netrc octokit (>= 2.2.0) coderay (1.1.2) combustion (1.1.0) activesupport (>= 3.0.0) railties (>= 3.0.0) thor (>= 0.14.6) concurrent-ruby (1.1.5) crass (1.0.4) diff-lcs (1.3) erubi (1.8.0) faraday (0.15.4) multipart-post (>= 1.2, < 3) ffi (1.9.25-java) globalid (0.4.2) activesupport (>= 4.2.0) i18n (1.6.0) concurrent-ruby (~> 1.0) jar-dependencies (0.4.0) jaro_winkler (1.5.2) jaro_winkler (1.5.2-java) loofah (2.2.3) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) marcel (0.3.3) mimemagic (~> 0.3.2) method_source (0.9.2) mimemagic (0.3.3) mini_mime (1.0.1) mini_portile2 (2.4.0) minitest (5.11.3) multipart-post (2.0.0) netrc (0.11.0) nio4r (2.3.1) nio4r (2.3.1-java) nokogiri (1.10.2) mini_portile2 (~> 2.4.0) nokogiri (1.10.2-java) octokit (4.13.0) sawyer (~> 0.8.0, >= 0.5.3) parallel (1.17.0) parser (2.6.2.1) ast (~> 2.4.0) pry (0.12.2) coderay (~> 1.1.0) method_source (~> 0.9.0) pry (0.12.2-java) coderay (~> 1.1.0) method_source (~> 0.9.0) spoon (~> 0.0) psych (3.1.0) psych (3.1.0-java) jar-dependencies (>= 0.1.7) public_suffix (3.0.3) rack (2.0.6) rack-test (1.1.0) rack (>= 1.0, < 3) rails (5.2.3) actioncable (= 5.2.3) actionmailer (= 5.2.3) actionpack (= 5.2.3) actionview (= 5.2.3) activejob (= 5.2.3) activemodel (= 5.2.3) activerecord (= 5.2.3) activestorage (= 5.2.3) activesupport (= 5.2.3) bundler (>= 1.3.0) railties (= 5.2.3) sprockets-rails (>= 2.0.0) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) rails-html-sanitizer (1.0.4) loofah (~> 2.2, >= 2.2.2) railties (5.2.3) actionpack (= 5.2.3) activesupport (= 5.2.3) method_source rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) rainbow (3.0.0) rake (12.3.2) regexp_parser (1.3.0) rspec (3.8.0) rspec-core (~> 3.8.0) rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-core (3.8.0) rspec-support (~> 3.8.0) rspec-expectations (3.8.2) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-mocks (3.8.0) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.8.0) rspec-rails (3.8.2) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) rspec-core (~> 3.8.0) rspec-expectations (~> 3.8.0) rspec-mocks (~> 3.8.0) rspec-support (~> 3.8.0) rspec-support (3.8.0) rubocop (0.67.2) jaro_winkler (~> 1.5.1) parallel (~> 1.10) parser (>= 2.5, != 2.5.1.1) psych (>= 3.1.0) rainbow (>= 2.2.2, < 4.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 1.6) ruby-progressbar (1.10.0) sawyer (0.8.1) addressable (>= 2.3.5, < 2.6) faraday (~> 0.8, < 1.0) spoon (0.0.6) ffi sprockets (3.7.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) sprockets-rails (3.2.1) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) thor (0.20.3) thread_safe (0.3.6) thread_safe (0.3.6-java) tzinfo (1.2.5) thread_safe (~> 0.1) unicode-display_width (1.5.0) websocket-driver (0.7.0) websocket-extensions (>= 0.1.0) websocket-driver (0.7.0-java) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) xpath (3.2.0) nokogiri (~> 1.8) PLATFORMS java ruby DEPENDENCIES arbre! capybara chandler combustion pry rails (>= 5.0.0.1) rake rspec rspec-rails rubocop BUNDLED WITH 2.0.1 arbre-1.2.1/Gemfile0000644000175000017500000000045413523740213013440 0ustar samyaksamyaksource 'http://rubygems.org' gemspec gem 'rake' group :test do gem 'rspec' gem 'pry' end group :tools do gem 'rubocop' end group :release do gem 'chandler' end group :rails do gem 'rails', '>= 5.0.0.1' # fixes CVE-2016-6316 gem 'rspec-rails' gem 'combustion' gem 'capybara' end arbre-1.2.1/.gitignore0000644000175000017500000000013313523740213014127 0ustar samyaksamyak*.gem .bundle pkg/* benchmarks .rvmrc .ruby-version .ruby-gemset tags .DS_Store docs/_site arbre-1.2.1/arbre.gemspec0000644000175000017500000000141613523740213014604 0ustar samyaksamyak# -*- encoding: utf-8 -*- $:.push File.expand_path("../lib", __FILE__) require "arbre/version" Gem::Specification.new do |s| s.name = "arbre" s.version = Arbre::VERSION s.platform = Gem::Platform::RUBY s.authors = ["Greg Bell"] s.email = ["gregdbell@gmail.com"] s.homepage = "" s.summary = %q{An Object Oriented DOM Tree in Ruby} s.description = %q{An Object Oriented DOM Tree in Ruby} s.license = "MIT" s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] s.required_ruby_version = '>= 2.3' s.add_dependency("activesupport", ">= 3.0.0") end arbre-1.2.1/docs/0000755000175000017500000000000013523740213013072 5ustar samyaksamyakarbre-1.2.1/docs/_includes/0000755000175000017500000000000013523740213015037 5ustar samyaksamyakarbre-1.2.1/docs/_includes/top-menu.html0000644000175000017500000000043413523740213017472 0ustar samyaksamyak arbre-1.2.1/docs/_includes/google-analytics.html0000644000175000017500000000101213523740213021160 0ustar samyaksamyak arbre-1.2.1/docs/_includes/head.html0000644000175000017500000000075013523740213016630 0ustar samyaksamyak Arbre | HTML Views in Ruby arbre-1.2.1/docs/_includes/toc.html0000644000175000017500000000117213523740213016513 0ustar samyaksamyak
  1. Contents
    1. Introduction
    2. Installation
    3. Tags
    4. Components
    5. Contexts
    6. Background
arbre-1.2.1/docs/_includes/footer.html0000644000175000017500000000041713523740213017225 0ustar samyaksamyak
Copyright 2011 Greg Bell and VersaPay
Tweet

arbre-1.2.1/docs/index.md0000644000175000017500000000706613523740213014534 0ustar samyaksamyak--- redirect_from: /docs/documentation.html --- # Arbre HTML Views in Ruby ### Introduction Arbre is a alternate template system for [Ruby on Rails Action View](http://guides.rubyonrails.org/action_view_overview.html). Arbre expresses HTML using a Ruby DSL, which makes it similar to the [Builder](https://github.com/tenderlove/builder) gem for XML. Arbre was extracted from [Active Admin](https://activeadmin.info/). An example `index.html.arb`: ```ruby html { head { title "Welcome page" } body { para "Hello, world" } } ``` The purpose of Arbre is to leave the view as Ruby objects as long as possible, which allows an object-oriented approach including inheritance, composition, and encapsulation. ### Installation Add gem `arbre` to your `Gemfile` and `bundle install`. Arbre registers itself as a Rails template handler for files with an extension `.arb`. ### Tags Arbre DSL is composed of HTML tags. Tag attributes including `id` and HTML classes are passed as a hash parameter and the tag body is passed as a block. Most HTML5 tags are implemented, including `script`, `embed` and `video`. A special case is the paragraph tag,

, which is mapped to `para`. JavaScript can be included by using `script { raw ... }` To include text that is not immediately part of a tag use `text_node`. ### Components Arbre DSL can be extended by defining new tags composed of other, simpler tags. This provides a simpler alternative to nesting partials. The recommended approach is to subclass Arbre::Component and implement a new builder method. The builder_method defines the method that will be called to build this component when using the DSL. The arguments passed into the builder_method will be passed into the #build method for you. For example: ```ruby class Panel < Arbre::Component builder_method :panel def build(title, attributes = {}) super(attributes) h3(title, class: "panel-title") end end ``` By default components are `div` tags with an HTML class corresponding to the component class name. This can be overridden by redefining the `tag_name` method. Several examples of Arbre components are [included in Active Admin](https://activeadmin.info/12-arbre-components.html) ### Contexts An [Arbre::Context](http://www.rubydoc.info/gems/arbre/Arbre/Context) is an object in which Arbre DSL is interpreted, providing a root for the Ruby DOM that can be [searched and manipulated](http://www.rubydoc.info/gems/arbre/Arbre/Element). A context is automatically provided when a `.arb` template or partial is loaded. Contexts can be used when developing or testing a component. Contexts are rendered by calling to_s. ```ruby html = Arbre::Context.new do panel "Hello World", id: "my-panel" do span "Inside the panel" text_node "Plain text" end end puts html.to_s # => ``` ```html

Hello World

Inside the panel Plain text
``` A context allows you to specify Rails template assigns, aka. 'locals' and helper methods. Templates loaded by Action View have access to all [Action View helper methods](http://guides.rubyonrails.org/action_view_overview.html#overview-of-helpers-provided-by-action-view) ### Background Similar projects include: - [Markaby](http://markaby.github.io/), written by \_why the luck stiff. - [Erector](http://erector.github.io/), developed at PivotalLabs. - [Fortitude](https://github.com/ageweke/fortitude), developed at Scribd. - [Inesita](https://inesita.fazibear.me/) (Opal) - [html_builder](https://github.com/crystal-lang/html_builder) (Crystal) arbre-1.2.1/docs/Gemfile0000644000175000017500000000005613523740213014366 0ustar samyaksamyakgem 'github-pages' gem 'jekyll-redirect-from' arbre-1.2.1/docs/stylesheets/0000755000175000017500000000000013523740213015446 5ustar samyaksamyakarbre-1.2.1/docs/stylesheets/main.css0000644000175000017500000004106213523740213017107 0ustar samyaksamyakhtml, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } body { line-height: 1; } ol, ul { list-style: none; } table { border-collapse: collapse; border-spacing: 0; } caption, th, td { text-align: left; font-weight: normal; vertical-align: middle; } q, blockquote { quotes: none; } q:before, q:after, blockquote:before, blockquote:after { content: ""; content: none; } a img { border: none; } article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } #dsl { /* Comment */ /* Error */ /* Keyword */ /* Literal */ /* Name */ /* Operator */ /* Punctuation */ /* Comment.Multiline */ /* Comment.Preproc */ /* Comment.Single */ /* Comment.Special */ /* Generic.Emph */ /* Generic.Strong */ /* Keyword.Constant */ /* Keyword.Declaration */ /* Keyword.Namespace */ /* Keyword.Pseudo */ /* Keyword.Reserved */ /* Keyword.Type */ /* Literal.Date */ /* Literal.Number */ /* Literal.String */ /* Name.Attribute */ /* Name.Builtin */ /* Name.Class */ /* Name.Constant */ /* Name.Decorator */ /* Name.Entity */ /* Name.Exception */ /* Name.Function */ /* Name.Label */ /* Name.Namespace */ /* Name.Other */ /* Name.Property */ /* Name.Tag */ /* Name.Variable */ /* Operator.Word */ /* Text.Whitespace */ /* Literal.Number.Float */ /* Literal.Number.Hex */ /* Literal.Number.Integer */ /* Literal.Number.Oct */ /* Literal.String.Backtick */ /* Literal.String.Char */ /* Literal.String.Doc */ /* Literal.String.Double */ /* Literal.String.Escape */ /* Literal.String.Heredoc */ /* Literal.String.Interpol */ /* Literal.String.Other */ /* Literal.String.Regex */ /* Literal.String.Single */ /* Literal.String.Symbol */ /* Name.Builtin.Pseudo */ /* Name.Variable.Class */ /* Name.Variable.Global */ /* Name.Variable.Instance */ /* Literal.Number.Integer.Long */ } #dsl .highlight .hll { background-color: #49483e; } #dsl .highlight { background: #272822; color: #f8f8f2; } #dsl .highlight .c { color: #75715e; } #dsl .highlight .err { color: #960050; background-color: #1e0010; } #dsl .highlight .k { color: #66d9ef; } #dsl .highlight .l { color: #ae81ff; } #dsl .highlight .n { color: #f8f8f2; } #dsl .highlight .o { color: #f92672; } #dsl .highlight .p { color: #f8f8f2; } #dsl .highlight .cm { color: #75715e; } #dsl .highlight .cp { color: #75715e; } #dsl .highlight .c1 { color: #75715e; } #dsl .highlight .cs { color: #75715e; } #dsl .highlight .ge { font-style: italic; } #dsl .highlight .gs { font-weight: bold; } #dsl .highlight .kc { color: #66d9ef; } #dsl .highlight .kd { color: #66d9ef; } #dsl .highlight .kn { color: #f92672; } #dsl .highlight .kp { color: #66d9ef; } #dsl .highlight .kr { color: #66d9ef; } #dsl .highlight .kt { color: #66d9ef; } #dsl .highlight .ld { color: #e6db74; } #dsl .highlight .m { color: #ae81ff; } #dsl .highlight .s { color: #e6db74; } #dsl .highlight .na { color: #a6e22e; } #dsl .highlight .nb { color: #f8f8f2; } #dsl .highlight .nc { color: #a6e22e; } #dsl .highlight .no { color: #66d9ef; } #dsl .highlight .nd { color: #a6e22e; } #dsl .highlight .ni { color: #f8f8f2; } #dsl .highlight .ne { color: #a6e22e; } #dsl .highlight .nf { color: #a6e22e; } #dsl .highlight .nl { color: #f8f8f2; } #dsl .highlight .nn { color: #f8f8f2; } #dsl .highlight .nx { color: #a6e22e; } #dsl .highlight .py { color: #f8f8f2; } #dsl .highlight .nt { color: #f92672; } #dsl .highlight .nv { color: #f8f8f2; } #dsl .highlight .ow { color: #f92672; } #dsl .highlight .w { color: #f8f8f2; } #dsl .highlight .mf { color: #ae81ff; } #dsl .highlight .mh { color: #ae81ff; } #dsl .highlight .mi { color: #ae81ff; } #dsl .highlight .mo { color: #ae81ff; } #dsl .highlight .sb { color: #e6db74; } #dsl .highlight .sc { color: #e6db74; } #dsl .highlight .sd { color: #e6db74; } #dsl .highlight .s2 { color: #e6db74; } #dsl .highlight .se { color: #ae81ff; } #dsl .highlight .sh { color: #e6db74; } #dsl .highlight .si { color: #e6db74; } #dsl .highlight .sx { color: #e6db74; } #dsl .highlight .sr { color: #e6db74; } #dsl .highlight .s1 { color: #e6db74; } #dsl .highlight .ss { color: #AE81FF; } #dsl .highlight .bp { color: #f8f8f2; } #dsl .highlight .vc { color: #f8f8f2; } #dsl .highlight .vg { color: #f8f8f2; } #dsl .highlight .vi { color: #f8f8f2; } #dsl .highlight .il { color: #ae81ff; } body { line-height: 1.5; font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; color: #333333; font-size: 75%; } h1, h2, h3, h4, h5, h6 { font-weight: normal; color: #222222; } h1 img, h2 img, h3 img, h4 img, h5 img, h6 img { margin: 0; } h1 { font-size: 3em; line-height: 1; margin-bottom: 0.50em; } h2 { font-size: 2em; margin-bottom: 0.75em; } h3 { font-size: 1.5em; line-height: 1; margin-bottom: 1.00em; } h4 { font-size: 1.2em; line-height: 1.25; margin-bottom: 1.25em; } h5 { font-size: 1em; font-weight: bold; margin-bottom: 1.50em; } h6 { font-size: 1em; font-weight: bold; } p { margin: 0 0 1.5em; } p .left { display: inline; float: left; margin: 1.5em 1.5em 1.5em 0; padding: 0; } p .right { display: inline; float: right; margin: 1.5em 0 1.5em 1.5em; padding: 0; } a { text-decoration: underline; color: #0066cc; } a:visited { color: #004c99; } a:focus { color: #0099ff; } a:hover { color: #0099ff; } a:active { color: #bf00ff; } blockquote { margin: 1.5em; color: #666666; font-style: italic; } strong, dfn { font-weight: bold; } em, dfn { font-style: italic; } sup, sub { line-height: 0; } abbr, acronym { border-bottom: 1px dotted #666666; } address { margin: 0 0 1.5em; font-style: italic; } del { color: #666666; } pre { margin: 1.5em 0; white-space: pre; } pre, code, tt { font: 1em "andale mono", "lucida console", monospace; line-height: 1.5; } li ul, li ol { margin: 0; } ul, ol { margin: 0 1.5em 1.5em 0; padding-left: 1.5em; } ul { list-style-type: disc; } ol { list-style-type: decimal; } dl { margin: 0 0 1.5em 0; } dl dt { font-weight: bold; } dd { margin-left: 1.5em; } table { margin-bottom: 1.4em; width: 100%; } th { font-weight: bold; } thead th { background: #c3d9ff; } th, td, caption { padding: 4px 10px 4px 5px; } table.striped tr:nth-child(even) td, table tr.even td { background: #e5ecf9; } tfoot { font-style: italic; } caption { background: #eeeeee; } .quiet { color: #666666; } .loud { color: #111111; } body { background: #f6f4f1; color: #676767; width: 676px; padding: 0 20px; font-size: 95%; margin: 25px auto; font-family: 'Georgia'; } body #wrapper { position: relative; } body a, body a:hover, body a:link, body a:visited { color: #407985; } body h1, body h2, body h3, body h4, body h5, body h6 { color: #595959; font-family: 'Yanone Kaffeesatz', 'Helvetica Neue', Arial, Helvetica, sans-serif; } body h1 a { background: url("../images/activeadmin.png") 0 0 no-repeat; display: block; width: 257px; height: 55px; } body h1 a span { display: none; } body #header { margin: 40px 0; } body .clear { clear: both; } body .intro { color: #595959; font-family: 'Yanone Kaffeesatz', 'Helvetica Neue', Arial, Helvetica, sans-serif; font-size: 3.2em; font-weight: 300; line-height: 1em; margin-bottom: 0.3em; padding-top: 35px; background: url("../images/divider.png") 0 0 repeat-x; } body .intro strong { font-weight: 400; } body h2 { margin: 50px 0 10px 0; padding-top: 35px; background: url("../images/divider.png") 0 0 repeat-x; font-size: 2.5em; font-weight: 200; line-height: 105%; } body h3 { margin-top: 30px; margin-bottom: 10px; font-size: 1.7em; font-weight: 300; } body #nav { font-family: 'Yanone Kaffeesatz', 'Helvetica Neue', Arial, Helvetica, sans-serif; font-weight: 400; font-size: 1.2em; text-transform: uppercase; position: absolute; right: 0; top: 20px; text-align: right; } body #nav a { text-decoration: none; color: #8b9091; margin-left: 20px; } body #features { padding-top: 0; clear: both; background: url("../images/features.png") 0 0 no-repeat; margin: 0 -35px; overflow: visible; min-height: 569px; font-size: 1.0em; line-height: 1.2em; font-weight: 300; font-family: 'Yanone Kaffeesatz', 'Helvetica Neue', Arial, Helvetica, sans-serif; } body #features #features-left { float: left; width: 150px; margin-left: -150px; } body #features #features-right { float: right; width: 150px; margin-right: -150px; } body #features h3 { font-size: 1.2em; padding-bottom: 0; margin-bottom: 5px; } body #features h3.first { margin-top: 10px; } body.with-sidebar { width: 976px; } body .toc { font-family: Helvetica, Arial, sans-serif; padding-top: 35px; width: 270px; float: right; font-size: 0.9em; background: url("../images/divider.png") top left repeat-x; } body .toc ol li { list-style: none; } body .toc a, body .toc a:link, body .toc a:hover, body .toc a:visited { text-decoration: none; color: #595959; } body .toc ol.level-1 > li { font-size: 1.0em; font-weight: bold; margin-top: 20px; } body .toc ol.level-1 > ol { padding-left: 0; font-size: 0.95em; margin: 0; } body .toc ol.level-2 > ol { display: none; } body .toc-content { width: 676px; } body #dsl { margin-top: 20px; } body #dsl .highlight { font-size: 0.82em; background: #292929 url("../images/code-header.png") 0 0 no-repeat; padding: 40px 15px 20px 15px !important; -moz-box-shadow: 0 8px 20px #444444; -webkit-box-shadow: 0 8px 20px #444444; -o-box-shadow: 0 8px 20px #444444; box-shadow: 0 8px 20px #444444; } body .getting-started { font-size: 2em; text-align: center; } body .getting-started a { margin-right: 15px; display: block; } body .getting-started-heading { text-align: center; } body .left { float: left; } body .right { float: right; } body .highlight { background-color: #333; font-family: "Droid Sans Mono", Monaco, monospace; padding: 10px 5px; font-size: 0.9em; -moz-border-radius: 2px; -webkit-border-radius: 2px; -o-border-radius: 2px; -ms-border-radius: 2px; -khtml-border-radius: 2px; border-radius: 2px; margin-bottom: 1.5em; } body .highlight > pre, body .highlight code, body .highlight span { line-height: 1.3em; margin: 0; padding: 0; } body #footer { margin-top: 50px; margin-bottom: 20px; background: url("../images/divider.png") 0 0 repeat-x; clear: both; padding-top: 20px; font-size: 0.9em; } body .post .post-date, body .post .post-meta { font-size: 0.7em; } body .post .post-date { display: inline-block; width: 100px; } body .post .post-meta { font-size: 0.6em; padding-left: 40px; } span.breadcrumb { display: block; font-size: 45%; font-weight: 200; margin: 0; padding: 0; } h2.in-docs { font-weight: 400; } .docs-content { /* Comment */ /* Error */ /* Keyword */ /* Comment.Multiline */ /* Comment.Preproc */ /* Comment.Single */ /* Comment.Special */ /* Generic.Deleted */ /* Generic.Emph */ /* Generic.Error */ /* Generic.Heading */ /* Generic.Inserted */ /* Generic.Output */ /* Generic.Prompt */ /* Generic.Strong */ /* Generic.Subheading */ /* Generic.Traceback */ /* Keyword.Constant */ /* Keyword.Declaration */ /* Keyword.Namespace */ /* Keyword.Pseudo */ /* Keyword.Reserved */ /* Keyword.Type */ /* Literal.Number */ /* Name */ /* Name */ /* Literal.String */ /* Name.Attribute */ /* Name.Builtin */ /* Name.Class */ /* Name.Constant */ /* Name.Decorator */ /* Name.Entity */ /* Name.Function */ /* Name.Namespace */ /* Name.Tag */ /* Name.Variable */ /* Operator.Word */ /* Text.Whitespace */ /* Literal.Number.Float */ /* Literal.Number.Hex */ /* Literal.Number.Integer */ /* Literal.Number.Oct */ /* Literal.String.Backtick */ /* Literal.String.Char */ /* Literal.String.Doc */ /* Literal.String.Double */ /* Literal.String.Escape */ /* Literal.String.Heredoc */ /* Literal.String.Interpol */ /* Literal.String.Other */ /* Literal.String.Regex */ /* Literal.String.Single */ /* Literal.String.Symbol */ /* Name.Builtin.Pseudo */ /* Name.Variable.Class */ /* Name.Variable.Global */ /* Name.Variable.Instance */ /* Literal.Number.Integer.Long */ } .docs-content h3 { margin-top: 50px; margin-bottom: 10px; font-size: 2em; font-weight: 400; } .docs-content h4 { font-size: 1.5em; font-weight: 400; margin-bottom: 0; } .docs-content p, .docs-content li { font-family: Helvetica, Arial, sans-serif; font-size: 0.9em; } .docs-content .highlight { font-size: 0.85em; background-color: #ece8e1; color: #000000; } .docs-content .highlight .hll { background-color: #ffffcc; } .docs-content .highlight .c { color: #aaaaaa; font-style: italic; } .docs-content .highlight .err { color: #F00000; background-color: #F0A0A0; } .docs-content .highlight .k { color: #0000aa; } .docs-content .highlight .cm { color: #aaaaaa; font-style: italic; } .docs-content .highlight .cp { color: #4c8317; } .docs-content .highlight .c1 { color: #aaaaaa; font-style: italic; } .docs-content .highlight .cs { color: #0000aa; font-style: italic; } .docs-content .highlight .gd { color: #aa0000; } .docs-content .highlight .ge { font-style: italic; } .docs-content .highlight .gr { color: #aa0000; } .docs-content .highlight .gh { color: #000080; font-weight: bold; } .docs-content .highlight .gi { color: #00aa00; } .docs-content .highlight .go { color: #888888; } .docs-content .highlight .gp { color: #555555; } .docs-content .highlight .gs { font-weight: bold; } .docs-content .highlight .gu { color: #800080; font-weight: bold; } .docs-content .highlight .gt { color: #aa0000; } .docs-content .highlight .kc { color: #0000aa; } .docs-content .highlight .kd { color: #0000aa; } .docs-content .highlight .kn { color: #0000aa; } .docs-content .highlight .kp { color: #0000aa; } .docs-content .highlight .kr { color: #0000aa; } .docs-content .highlight .kt { color: #00aaaa; } .docs-content .highlight .m { color: #009999; } .docs-content .highlight .n { color: #000000; } .docs-content .highlight .p { color: #000000; } .docs-content .highlight .s { color: #aa5500; } .docs-content .highlight .na { color: #1e90ff; } .docs-content .highlight .nb { color: #00aaaa; } .docs-content .highlight .nc { color: #00aa00; text-decoration: underline; } .docs-content .highlight .no { color: #aa0000; } .docs-content .highlight .nd { color: #888888; } .docs-content .highlight .ni { color: #800000; font-weight: bold; } .docs-content .highlight .nf { color: #00aa00; } .docs-content .highlight .nn { color: #00aaaa; text-decoration: underline; } .docs-content .highlight .nt { color: #1e90ff; font-weight: bold; } .docs-content .highlight .nv { color: #aa0000; } .docs-content .highlight .ow { color: #0000aa; } .docs-content .highlight .w { color: #bbbbbb; } .docs-content .highlight .mf { color: #009999; } .docs-content .highlight .mh { color: #009999; } .docs-content .highlight .mi { color: #009999; } .docs-content .highlight .mo { color: #009999; } .docs-content .highlight .sb { color: #aa5500; } .docs-content .highlight .sc { color: #aa5500; } .docs-content .highlight .sd { color: #aa5500; } .docs-content .highlight .s2 { color: #aa5500; } .docs-content .highlight .se { color: #aa5500; } .docs-content .highlight .sh { color: #aa5500; } .docs-content .highlight .si { color: #aa5500; } .docs-content .highlight .sx { color: #aa5500; } .docs-content .highlight .sr { color: #009999; } .docs-content .highlight .s1 { color: #aa5500; } .docs-content .highlight .ss { color: #0000aa; } .docs-content .highlight .bp { color: #00aaaa; } .docs-content .highlight .vc { color: #aa0000; } .docs-content .highlight .vg { color: #aa0000; } .docs-content .highlight .vi { color: #aa0000; } .docs-content .highlight .il { color: #009999; } arbre-1.2.1/docs/_layouts/0000755000175000017500000000000013523740213014731 5ustar samyaksamyakarbre-1.2.1/docs/_layouts/default.html0000644000175000017500000000075513523740213017252 0ustar samyaksamyak {% include head.html %}
{% include top-menu.html %}
{% include toc.html %}
{{ content }}
{% include footer.html %}
{% include google-analytics.html %} arbre-1.2.1/docs/_config.yml0000644000175000017500000000012513523740213015217 0ustar samyaksamyakplugins: - jekyll-redirect-from defaults: - values: layout: "default" arbre-1.2.1/spec/0000755000175000017500000000000013523740213013074 5ustar samyaksamyakarbre-1.2.1/spec/support/0000755000175000017500000000000013523740213014610 5ustar samyaksamyakarbre-1.2.1/spec/support/bundle.rb0000644000175000017500000000013213523740213016402 0ustar samyaksamyak$LOAD_PATH.unshift(File.expand_path("../../", __FILE__)) require "bundler" Bundler.setup arbre-1.2.1/spec/changelog_spec.rb0000644000175000017500000000120313523740213016356 0ustar samyaksamyakrequire 'spec_helper' describe "Changelog" do subject(:changelog) do path = File.join(File.dirname(__dir__), "CHANGELOG.md") File.read(path) end it 'has definitions for all implicit links' do implicit_link_names = changelog.scan(/\[([^\]]+)\]\[\]/).flatten.uniq implicit_link_names.each do |name| expect(changelog).to include("[#{name}]: https") end end describe 'entry' do let(:lines) { changelog.each_line } subject(:entries) { lines.grep(/^\*/) } it 'does not end with a punctuation' do entries.each do |entry| expect(entry).not_to match(/\.$/) end end end end arbre-1.2.1/spec/rails/0000755000175000017500000000000013523740213014206 5ustar samyaksamyakarbre-1.2.1/spec/rails/support/0000755000175000017500000000000013523740213015722 5ustar samyaksamyakarbre-1.2.1/spec/rails/support/mock_person.rb0000644000175000017500000000023613523740213020567 0ustar samyaksamyakrequire 'active_model' class MockPerson extend ActiveModel::Naming attr_accessor :name def persisted? false end def to_key [] end end arbre-1.2.1/spec/rails/templates/0000755000175000017500000000000013523740213016204 5ustar samyaksamyakarbre-1.2.1/spec/rails/templates/arbre/0000755000175000017500000000000013523740213017277 5ustar samyaksamyakarbre-1.2.1/spec/rails/templates/arbre/_partial_with_assignment.arb0000644000175000017500000000004313523740213025040 0ustar samyaksamyakpara "Partial: #{my_instance_var}" arbre-1.2.1/spec/rails/templates/arbre/page_with_arb_partial_and_assignment.arb0000644000175000017500000000011613523740213027344 0ustar samyaksamyakh1 "Before Partial" render "arbre/partial_with_assignment" h2 "After Partial" arbre-1.2.1/spec/rails/templates/arbre/page_with_assignment.arb0000644000175000017500000000002313523740213024157 0ustar samyaksamyakh1 my_instance_var arbre-1.2.1/spec/rails/templates/arbre/empty.arb0000644000175000017500000000000013523740213021111 0ustar samyaksamyakarbre-1.2.1/spec/rails/templates/arbre/page_with_erb_partial.arb0000644000175000017500000000007413523740213024301 0ustar samyaksamyakh1 "Before Partial" render "erb/partial" h2 "After Partial" arbre-1.2.1/spec/rails/templates/arbre/_partial.arb0000644000175000017500000000003413523740213021555 0ustar samyaksamyakpara "Hello from a partial" arbre-1.2.1/spec/rails/templates/arbre/page_with_partial.arb0000644000175000017500000000007613523740213023453 0ustar samyaksamyakh1 "Before Partial" render "arbre/partial" h2 "After Partial" arbre-1.2.1/spec/rails/templates/arbre/simple_page.arb0000644000175000017500000000013113523740213022245 0ustar samyaksamyakhtml do head do end body do h1 "Hello World" para "Hello again!" end end arbre-1.2.1/spec/rails/templates/erb/0000755000175000017500000000000013523740213016754 5ustar samyaksamyakarbre-1.2.1/spec/rails/templates/erb/_partial.erb0000644000175000017500000000004113523740213021234 0ustar samyaksamyak

Hello from an erb partial

arbre-1.2.1/spec/rails/stub_app/0000755000175000017500000000000013523740213016023 5ustar samyaksamyakarbre-1.2.1/spec/rails/stub_app/config/0000755000175000017500000000000013523740213017270 5ustar samyaksamyakarbre-1.2.1/spec/rails/stub_app/config/database.yml0000644000175000017500000000010013523740213021546 0ustar samyaksamyaktest: adapter: sqlite3 database: db/combustion_test.sqlite arbre-1.2.1/spec/rails/stub_app/config/routes.rb0000644000175000017500000000005113523740213021132 0ustar samyaksamyakRails.application.routes.draw do # end arbre-1.2.1/spec/rails/stub_app/log/0000755000175000017500000000000013523740213016604 5ustar samyaksamyakarbre-1.2.1/spec/rails/stub_app/log/.gitignore0000644000175000017500000000000613523740213020570 0ustar samyaksamyak*.log arbre-1.2.1/spec/rails/stub_app/public/0000755000175000017500000000000013523740213017301 5ustar samyaksamyakarbre-1.2.1/spec/rails/stub_app/public/favicon.ico0000644000175000017500000000000013523740213021410 0ustar samyaksamyakarbre-1.2.1/spec/rails/stub_app/db/0000755000175000017500000000000013523740213016410 5ustar samyaksamyakarbre-1.2.1/spec/rails/stub_app/db/schema.rb0000644000175000017500000000005513523740213020175 0ustar samyaksamyak# ActiveRecord::Schema.define do # # # end arbre-1.2.1/spec/rails/integration/0000755000175000017500000000000013523740213016531 5ustar samyaksamyakarbre-1.2.1/spec/rails/integration/forms_spec.rb0000644000175000017500000000465113523740213021224 0ustar samyaksamyakrequire 'rails/rails_spec_helper' describe "Building forms" do let(:assigns){ {} } let(:helpers){ mock_action_view } let(:html) { form.to_s } describe "building a simple form for" do let(:form) do arbre do form_for MockPerson.new, url: "/" do |f| f.label :name f.text_field :name end end end it "should build a form" do expect(html).to have_selector("form") end it "should include the hidden authenticity token" do expect(html).to include '' end it "should create a label" do expect(html).to have_selector("form label[for=mock_person_name]") end it "should create a text field" do expect(html).to have_selector("form input[type=text]") end end describe "building a form with fields for" do let(:form) do arbre do form_for MockPerson.new, url: "/" do |f| f.label :name f.text_field :name f.fields_for :permission do |pf| pf.label :admin pf.check_box :admin end end end end it "should render nested label" do expect(html).to have_selector("form label[for=mock_person_permission_admin]", text: "Admin") end it "should render nested label" do expect(html).to have_selector("form input[type=checkbox][name='mock_person[permission][admin]']") end it "should not render a div for the proxy" do expect(html).not_to have_selector("form div.fields_for_proxy") end end describe "forms with other elements" do let(:form) do arbre do form_for MockPerson.new, url: "/" do |f| div do f.label :name f.text_field :name end para do f.label :name f.text_field :name end div class: "permissions" do f.fields_for :permission do |pf| div class: "permissions_label" do pf.label :admin end pf.check_box :admin end end end end end it "should correctly nest elements" do expect(html).to have_selector("form > p > label") end it "should correnctly nest elements within fields for" do expect(html).to have_selector("form > div.permissions > div.permissions_label label") end end end arbre-1.2.1/spec/rails/integration/rendering_spec.rb0000644000175000017500000000515313523740213022051 0ustar samyaksamyakrequire 'rails/rails_spec_helper' ARBRE_VIEWS_PATH = File.expand_path("../../templates", __FILE__) class TestController < ActionController::Base append_view_path ARBRE_VIEWS_PATH def render_empty render "arbre/empty" end def render_simple_page render "arbre/simple_page" end def render_partial render "arbre/page_with_partial" end def render_erb_partial render "arbre/page_with_erb_partial" end def render_with_instance_variable @my_instance_var = "From Instance Var" render "arbre/page_with_assignment" end def render_partial_with_instance_variable @my_instance_var = "From Instance Var" render "arbre/page_with_arb_partial_and_assignment" end end describe TestController, "Rendering with Arbre", type: :request do let(:body){ response.body } before do Rails.application.routes.draw do get 'test/render_empty', controller: "test" get 'test/render_simple_page', controller: "test" get 'test/render_partial', controller: "test" get 'test/render_erb_partial', controller: "test" get 'test/render_with_instance_variable', controller: "test" get 'test/render_partial_with_instance_variable', controller: "test" get 'test/render_page_with_helpers', controller: "test" end end after do Rails.application.reload_routes! end it "should render the empty template" do get "/test/render_empty" expect(response).to be_successful end it "should render a simple page" do get "/test/render_simple_page" expect(response).to be_successful expect(body).to have_selector("h1", text: "Hello World") expect(body).to have_selector("p", text: "Hello again!") end it "should render an arb partial" do get "/test/render_partial" expect(response).to be_successful expect(body).to eq <<~HTML

Before Partial

Hello from a partial

After Partial

HTML end it "should render an erb (or other) partial" do get "/test/render_erb_partial" expect(response).to be_successful expect(body).to eq <<~HTML

Before Partial

Hello from an erb partial

After Partial

HTML end it "should render with instance variables" do get "/test/render_with_instance_variable" expect(response).to be_successful expect(body).to have_selector("h1", text: "From Instance Var") end it "should render an arbre partial with assignments" do get "/test/render_partial_with_instance_variable" expect(response).to be_successful expect(body).to have_selector("p", text: "Partial: From Instance Var") end end arbre-1.2.1/spec/rails/rails_spec_helper.rb0000644000175000017500000000157213523740213020223 0ustar samyaksamyakrequire 'rubygems' require 'bundler/setup' require 'combustion' Combustion.path = 'spec/rails/stub_app' Combustion.initialize! :action_controller, :action_view require 'rspec/rails' require 'capybara/rspec' require 'capybara/rails' require 'spec_helper' require 'rails/support/mock_person' # Ensure that the rails plugin is installed require 'arbre/rails' module AdditionalHelpers def protect_against_forgery? true end def form_authenticity_token(form_options: {}) "AUTH_TOKEN" end end def mock_action_view(assigns = {}) controller = ActionView::TestCase::TestController.new ActionView::Base.send :include, ActionView::Helpers ActionView::Base.send :include, AdditionalHelpers ActionView::Base.new(ActionController::Base.view_paths, assigns, controller) end RSpec.configure do |config| config.include Capybara::RSpecMatchers end arbre-1.2.1/spec/arbre/0000755000175000017500000000000013523740213014167 5ustar samyaksamyakarbre-1.2.1/spec/arbre/integration/0000755000175000017500000000000013523740213016512 5ustar samyaksamyakarbre-1.2.1/spec/arbre/integration/html_spec.rb0000644000175000017500000001111113523740213021010 0ustar samyaksamyakrequire 'spec_helper' describe Arbre do let(:helpers){ nil } let(:assigns){ {} } it "should render a single element" do expect(arbre { span "Hello World" }.to_s).to eq("Hello World\n") end it "should render a child element" do expect(arbre { span do span "Hello World" end }.to_s).to eq <<~HTML Hello World HTML end it "should render an unordered list" do expect(arbre { ul do li "First" li "Second" li "Third" end }.to_s).to eq <<~HTML HTML end it "should allow local variables inside the tags" do expect(arbre { first = "First" second = "Second" ul do li first li second end }.to_s).to eq <<~HTML HTML end it "should add children and nested" do expect(arbre { div do ul li do li end end }.to_s).to eq <<~HTML
  • HTML end it "should pass the element in to the block if asked for" do expect(arbre { div do |d| d.ul do li end end }.to_s).to eq <<~HTML
    HTML end it "should move content tags between parents" do expect(arbre { div do span(ul(li)) end }.to_s).to eq <<~HTML
    HTML end it "should add content to the parent if the element is passed into block" do expect(arbre { div do |d| d.id = "my-tag" ul do li end end }.to_s).to eq <<~HTML
    HTML end it "should have the parent set on it" do list, item = nil arbre { list = ul do li "Hello" item = li "World" end } expect(item.parent).to eq list end it "should set a string content return value with no children" do expect(arbre { li do "Hello World" end }.to_s).to eq <<~HTML
  • Hello World
  • HTML end it "should turn string return values into text nodes" do node = nil arbre { list = li do "Hello World" end node = list.children.first } expect(node).to be_a Arbre::HTML::TextNode end it "should not render blank arrays" do expect(arbre { tbody do [] end }.to_s).to eq <<~HTML HTML end describe "self-closing nodes" do it "should not self-close script tags" do expect(arbre { script type: 'text/javascript' }.to_s).to eq("\n") end it "should self-close meta tags" do expect(arbre { meta content: "text/html; charset=utf-8" }.to_s).to eq("\n") end it "should self-close link tags" do expect(arbre { link rel: "stylesheet" }.to_s).to eq("\n") end Arbre::HTML::Tag::SELF_CLOSING_ELEMENTS.each do |tag| it "should self-close #{tag} tags" do expect(arbre { send(tag) }.to_s).to eq("<#{tag}/>\n") end end end describe "html safe" do it "should escape the contents" do expect(arbre { span("
    ") }.to_s).to eq <<~HTML <br /> HTML end it "should return html safe strings" do expect(arbre { span("
    ") }.to_s).to be_html_safe end it "should not escape html passed in" do expect(arbre { span(span("
    ")) }.to_s).to eq <<~HTML <br /> HTML end it "should escape string contents when passed in block" do expect(arbre { span { span { "
    " } } }.to_s).to eq <<~HTML <br /> HTML end it "should escape the contents of attributes" do expect(arbre { span(class: "
    ") }.to_s).to eq <<~HTML HTML end end end arbre-1.2.1/spec/arbre/unit/0000755000175000017500000000000013523740213015146 5ustar samyaksamyakarbre-1.2.1/spec/arbre/unit/component_spec.rb0000644000175000017500000000161113523740213020506 0ustar samyaksamyakrequire 'spec_helper' # A mock subclass to play with class MockComponent < Arbre::Component builder_method :mock_component def build h2 "Hello World" end end describe Arbre::Component do let(:assigns) { {} } let(:helpers) { nil } let(:component_class){ MockComponent } let(:component){ component_class.new } it "should be a subclass of an html div" do expect(Arbre::Component.ancestors).to include(Arbre::HTML::Div) end it "should render to a div, even as a subclass" do expect(component.tag_name).to eq('div') end it "should add a class by default" do expect(component.class_list).to include("mock_component") end it "should render the object using the builder method name" do comp = expect(arbre { mock_component }.to_s).to eq <<~HTML

    Hello World

    HTML end end arbre-1.2.1/spec/arbre/unit/html/0000755000175000017500000000000013523740213016112 5ustar samyaksamyakarbre-1.2.1/spec/arbre/unit/html/tag_attributes_spec.rb0000644000175000017500000000323313523740213022473 0ustar samyaksamyakrequire 'spec_helper' describe Arbre::HTML::Tag, "Attributes" do let(:tag){ Arbre::HTML::Tag.new } describe "attributes" do before { tag.build id: "my_id" } it "should have an attributes hash" do expect(tag.attributes).to eq({id: "my_id"}) end it "should render the attributes to html" do expect(tag.to_s).to eq "\n" end it "shouldn't render attributes that are empty" do tag.class_list # initializes an empty ClassList tag.set_attribute :foo, '' tag.set_attribute :bar, nil expect(tag.to_s).to eq "\n" end it "should get an attribute value" do expect(tag.attr(:id)).to eq("my_id") end describe "#has_attribute?" do context "when the attribute exists" do it "should return true" do expect(tag.has_attribute?(:id)).to eq(true) end end context "when the attribute does not exist" do it "should return false" do expect(tag.has_attribute?(:class)).to eq(false) end end end it "should remove an attribute" do expect(tag.attributes).to eq({id: "my_id"}) expect(tag.remove_attribute(:id)).to eq("my_id") expect(tag.attributes).to eq({}) end end describe "rendering attributes" do it "should html safe the attribute values" do tag.set_attribute(:class, '">bad things!') expect(tag.to_s).to eq "\n" end it "should should escape the attribute names" do tag.set_attribute(">bad", "things") expect(tag.to_s).to eq "\n" end end end arbre-1.2.1/spec/arbre/unit/html/class_list_spec.rb0000644000175000017500000000051413523740213021611 0ustar samyaksamyakrequire 'spec_helper' describe Arbre::HTML::ClassList do describe ".build_from_string" do it "should build a new list from a string of classes" do list = Arbre::HTML::ClassList.build_from_string("first second") expect(list.size).to eq(2) expect(list).to match_array(%w{first second}) end end end arbre-1.2.1/spec/arbre/unit/html/tag_spec.rb0000644000175000017500000000553013523740213020227 0ustar samyaksamyakrequire 'spec_helper' describe Arbre::HTML::Tag do let(:tag){ Arbre::HTML::Tag.new } describe "building a new tag" do before { tag.build "Hello World", id: "my_id" } it "should set the contents to a string" do expect(tag.content).to eq("Hello World") end it "should set the hash of options to the attributes" do expect(tag.attributes).to eq({ id: "my_id" }) end end describe "creating a tag 'for' an object" do let(:model_name){ double(singular: "resource_class")} let(:resource_class){ double(model_name: model_name) } let(:resource){ double(class: resource_class, to_key: ['5'])} before do tag.build for: resource end it "should set the id to the type and id" do expect(tag.id).to eq("resource_class_5") end it "should add a class name" do expect(tag.class_list).to include("resource_class") end describe "for an object that doesn't have a model_name" do let(:resource_class){ double(name: 'ResourceClass') } before do tag.build for: resource end it "should set the id to the type and id" do expect(tag.id).to eq("resource_class_5") end it "should add a class name" do expect(tag.class_list).to include("resource_class") end end describe "with a default_id_for_prefix" do let(:tag) do Class.new(Arbre::HTML::Tag) do def default_id_for_prefix "a_prefix" end end.new end it "should set the id to the type and id" do expect(tag.id).to eq("a_prefix_resource_class_5") end end end describe "creating a tag with a for attribute" do it "sets the `for` attribute when a string is given" do tag.build for: "email" expect(tag.attributes[:for]).to eq "email" end it "sets the `for` attribute when a symbol is given" do tag.build for: :email expect(tag.attributes[:for]).to eq :email end end describe "css class names" do it "should add a class" do tag.add_class "hello_world" expect(tag.class_names).to eq("hello_world") end it "should remove_class" do tag.add_class "hello_world" expect(tag.class_names).to eq("hello_world") tag.remove_class "hello_world" expect(tag.class_names).to eq("") end it "should not add a class if it already exists" do tag.add_class "hello_world" tag.add_class "hello_world" expect(tag.class_names).to eq("hello_world") end it "should seperate classes with space" do tag.add_class "hello world" expect(tag.class_list.size).to eq(2) end it "should create a class list from a string" do tag = Arbre::HTML::Tag.new tag.build(class: "first-class") tag.add_class "second-class" expect(tag.class_list.size).to eq(2) end end end arbre-1.2.1/spec/arbre/unit/html/text_node_spec.rb0000644000175000017500000000007613523740213021445 0ustar samyaksamyakrequire 'spec_helper' describe Arbre::HTML::TextNode do end arbre-1.2.1/spec/arbre/unit/context_spec.rb0000644000175000017500000000150413523740213020171 0ustar samyaksamyak# coding: utf-8 require 'spec_helper' describe Arbre::Context do let(:context) do Arbre::Context.new do h1 "札幌市北区" # Add some HTML to the context end end it "should not increment the indent_level" do expect(context.indent_level).to eq(-1) end it "should return a bytesize" do expect(context.bytesize).to eq(25) end it "should return a length" do expect(context.length).to eq(25) end it "should delegate missing methods to the html string" do expect(context).to respond_to(:index) expect(context.index('<')).to eq(0) end it "should use a cached version of the HTML for method delegation" do expect(context).to receive(:to_s).once.and_return("

    札幌市北区

    ") expect(context.index('<')).to eq(0) expect(context.index('<')).to eq(0) end end arbre-1.2.1/spec/arbre/unit/element_spec.rb0000644000175000017500000001575113523740213020147 0ustar samyaksamyakrequire 'spec_helper' describe Arbre::Element do let(:element){ Arbre::Element.new } context "when initialized" do it "should have no children" do expect(element.children).to be_empty end it "should have no parent" do expect(element.parent).to be_nil end it "should respond to the HTML builder methods" do expect(element).to respond_to(:span) end it "should have a set of local assigns" do context = Arbre::Context.new hello: "World" element = Arbre::Element.new(context) expect(element.assigns[:hello]).to eq("World") end it "should have an empty hash with no local assigns" do expect(element.assigns).to eq({}) end end describe "passing in a helper object" do let(:helper) do Class.new do def helper_method "helper method" end end end let(:element){ Arbre::Element.new(Arbre::Context.new(nil, helper.new)) } it "should call methods on the helper object and return TextNode objects" do expect(element.helper_method).to eq("helper method") end it "should raise a NoMethodError if not found" do expect { element.a_method_that_doesnt_exist }.to raise_error(NoMethodError) end end describe "passing in assigns" do let(:post){ double } let(:assigns){ {post: post} } it "should be accessible via a method call" do element = Arbre::Element.new(Arbre::Context.new(assigns)) expect(element.post).to eq(post) end end it "to_a.flatten should not infinitely recurse" do Timeout.timeout(1) do element.to_a.flatten end end describe "adding a child" do let(:child){ Arbre::Element.new } before do element.add_child child end it "should add the child to the parent" do expect(element.children.first).to eq(child) end it "should set the parent of the child" do expect(child.parent).to eq(element) end context "when the child is nil" do let(:child){ nil } it "should not add the child" do expect(element.children).to be_empty end end context "when the child is a string" do let(:child){ "Hello World" } it "should add as a TextNode" do expect(element.children.first).to be_instance_of(Arbre::HTML::TextNode) expect(element.children.first.to_s).to eq("Hello World") end end end describe "setting the content" do context "when a string" do before do element.add_child "Hello World" element.content = "Goodbye" end it "should clear the existing children" do expect(element.children.size).to eq(1) end it "should add the string as a child" do expect(element.children.first.to_s).to eq("Goodbye") end it "should html escape the string" do string = "Goodbye
    " element.content = string expect(element.content.to_s).to eq("Goodbye <br />") end end context "when an element" do let(:content_element){ Arbre::Element.new } before do element.content = content_element end it "should set the content tag" do expect(element.children.first).to eq(content_element) end it "should set the tags parent" do expect(content_element.parent).to eq(element) end end context "when an array of tags" do let(:first){ Arbre::Element.new } let(:second){ Arbre::Element.new } before do element.content = [first, second] end it "should set the content tag" do expect(element.children.first).to eq(first) end it "should set the tags parent" do expect(element.children.first.parent).to eq(element) end end end describe "rendering to html" do before { @separator = $, } after { $, = @separator } let(:collection){ element + "hello world" } it "should render the children collection" do expect(element.children).to receive(:to_s).and_return("content") expect(element.to_s).to eq("content") end it "should render collection when is set the default separator" do $, = "_" expect(collection.to_s).to eq("hello world") end it "should render collection when is not set the default separator" do expect(collection.to_s).to eq("hello world") end end describe "adding elements together" do context "when both elements are tags" do let(:first){ Arbre::Element.new } let(:second){ Arbre::Element.new } let(:collection){ first + second } it "should return an instance of Collection" do expect(collection).to be_an_instance_of(Arbre::ElementCollection) end it "should return the elements in the collection" do expect(collection.size).to eq(2) expect(collection.first).to eq(first) expect(collection[1]).to eq(second) end end context "when the left is a collection and the right is a tag" do let(:first){ Arbre::Element.new } let(:second){ Arbre::Element.new } let(:third){ Arbre::Element.new } let(:collection){ Arbre::ElementCollection.new([first, second]) + third} it "should return an instance of Collection" do expect(collection).to be_an_instance_of(Arbre::ElementCollection) end it "should return the elements in the collection flattened" do expect(collection.size).to eq(3) expect(collection[0]).to eq(first) expect(collection[1]).to eq(second) expect(collection[2]).to eq(third) end end context "when the right is a collection and the left is a tag" do let(:first){ Arbre::Element.new } let(:second){ Arbre::Element.new } let(:third){ Arbre::Element.new } let(:collection){ first + Arbre::ElementCollection.new([second,third]) } it "should return an instance of Collection" do expect(collection).to be_an_instance_of(Arbre::ElementCollection) end it "should return the elements in the collection flattened" do expect(collection.size).to eq(3) expect(collection[0]).to eq(first) expect(collection[1]).to eq(second) expect(collection[2]).to eq(third) end end context "when the left is a tag and the right is a string" do let(:element){ Arbre::Element.new } let(:collection){ element + "Hello World"} it "should return an instance of Collection" do expect(collection).to be_an_instance_of(Arbre::ElementCollection) end it "should return the elements in the collection" do expect(collection.size).to eq(2) expect(collection[0]).to eq(element) expect(collection[1]).to be_an_instance_of(Arbre::HTML::TextNode) end end context "when the left is a string and the right is a tag" do let(:collection){ "hello World" + Arbre::Element.new} it "should return a string" do expect(collection.strip.chomp).to eq("hello World") end end end end arbre-1.2.1/spec/arbre/unit/element_finder_methods_spec.rb0000644000175000017500000000614513523740213023216 0ustar samyaksamyakrequire 'spec_helper' describe Arbre::Element, "Finder Methods" do let(:assigns){ {} } let(:helpers){ {} } describe "finding elements by tag name" do it "should return 0 when no elements exist" do expect(arbre { div }.get_elements_by_tag_name("li").size).to eq(0) end it "should return a child element" do html = arbre do ul li ul end elements = html.get_elements_by_tag_name("li") expect(elements.size).to eq(1) expect(elements[0]).to be_instance_of(Arbre::HTML::Li) end it "should return multple child elements" do html = arbre do ul li ul li end elements = html.get_elements_by_tag_name("li") expect(elements.size).to eq(2) expect(elements[0]).to be_instance_of(Arbre::HTML::Li) expect(elements[1]).to be_instance_of(Arbre::HTML::Li) end it "should return children's child elements" do html = arbre do ul li do li end end elements = html.get_elements_by_tag_name("li") expect(elements.size).to eq(2) expect(elements[0]).to be_instance_of(Arbre::HTML::Li) expect(elements[1]).to be_instance_of(Arbre::HTML::Li) expect(elements[1].parent).to eq(elements[0]) end end #TODO: describe "finding an element by id" describe "finding an element by a class name" do it "should return 0 when no elements exist" do expect(arbre { div }.get_elements_by_class_name("my_class").size).to eq(0) end it "should allow text nodes on tree" do expect(arbre { text_node "text" }.get_elements_by_class_name("my_class").size).to eq(0) end it "should return a child element" do html = arbre do div class: "some_class" div class: "my_class" end elements = html.get_elements_by_class_name("my_class") expect(elements.size).to eq(1) expect(elements[0]).to be_instance_of(Arbre::HTML::Div) end it "should return multple child elements" do html = arbre do div class: "some_class" div class: "my_class" div class: "my_class" end elements = html.get_elements_by_class_name("my_class") expect(elements.size).to eq(2) expect(elements[0]).to be_instance_of(Arbre::HTML::Div) expect(elements[1]).to be_instance_of(Arbre::HTML::Div) end it "should return elements that match one of several classes" do html = arbre do div class: "some_class this_class" div class: "some_class" div class: "other_class" end elements = html.get_elements_by_class_name("this_class") expect(elements.size).to eq(1) expect(elements[0]).to be_instance_of(Arbre::HTML::Div) end it "should return a grandchild element" do html = arbre do div class: "some_class" do div class: "my_class" end end elements = html.get_elements_by_class_name("my_class") expect(elements.size).to eq(1) expect(elements[0]).to be_instance_of(Arbre::HTML::Div) end end end arbre-1.2.1/spec/spec_helper.rb0000644000175000017500000000015713523740213015715 0ustar samyaksamyakrequire 'support/bundle' require 'arbre' def arbre(&block) Arbre::Context.new assigns, helpers, &block end arbre-1.2.1/Rakefile0000644000175000017500000000050613523740213013610 0ustar samyaksamyakrequire 'bundler' Bundler::GemHelper.install_tasks require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) import 'tasks/lint.rake' import 'tasks/release.rake' task default: [:spec, :lint] task :console do require 'irb' require 'irb/completion' require 'pry' require 'arbre' ARGV.clear IRB.start end arbre-1.2.1/README.md0000644000175000017500000000325013523740213013421 0ustar samyaksamyak# Arbre - HTML Views in Ruby [Arbre][docs] makes it easy to generate HTML directly in Ruby. This gem was extracted from [Active Admin](https://github.com/activeadmin/active_admin). [![Version ][rubygems_badge]][rubygems] [![Travis CI ][travis_badge]][travis] [![Tidelift ][tidelift_badge]][tidelift] ## Goals The purpose of Arbre is to leave the view as ruby objects as long as possible. This allows OO Design to be used to implement the view layer. ## Getting started * Check out [the docs][docs]. ## Need help? Please use [StackOverflow][stackoverflow] for help requests and how-to questions. Please open GitHub issues for bugs and enhancements only, not general help requests. Please search previous issues (and Google and StackOverflow) before creating a new issue. ## Want to support us? Subscribe to [Tidelift][tidelift] to support Arbre and get licensing assurances and timely security notifications. ## Security contact information Please use the Tidelift security contact to [report a security vulnerability][Tidelift security contact]. Tidelift will coordinate the fix and disclosure. [rubygems_badge]: http://img.shields.io/gem/v/arbre.svg [rubygems]: https://rubygems.org/gems/arbre [travis_badge]: http://img.shields.io/travis/activeadmin/arbre/master.svg [travis]: https://travis-ci.org/activeadmin/arbre [tidelift_badge]: https://tidelift.com/badges/github/activeadmin/arbre [tidelift]: https://tidelift.com/subscription/pkg/rubygems-arbre?utm_source=rubygems-arbre&utm_medium=readme [docs]: https://activeadmin.github.io/arbre/ [stackoverflow]: http://stackoverflow.com/questions/tagged/arbre [Tidelift security contact]: https://tidelift.com/security arbre-1.2.1/CHANGELOG.md0000644000175000017500000001027413523740213013757 0ustar samyaksamyak# Changelog ## Master (unreleased) ## 1.2.1 [☰](https://github.com/activeadmin/arbre/compare/v1.2.0...v1.2.1) * Revert [#64][] to fix several regressions, at the cost of reintroducing [#46][]. [#121][] by [@deivid-rodriguez][] ## 1.2.0 [☰](https://github.com/activeadmin/arbre/compare/v1.2.0.rc1...v1.2.0) _No changes_. ## 1.2.0.rc1 [☰](https://github.com/activeadmin/arbre/compare/v1.1.1...v1.2.0.rc1) * Fix deprecation warning about single arity template handlers on Rails 6. [#110][] by [@aramvisser][] * Fix rendering `link_to` with a block in a arbre template. [#64][] by [@varyonic][] * Drop support for EOL'd rubies (under 2.3). [#78][] by [@deivid-rodriguez][] ## 1.1.1 [☰](https://github.com/activeadmin/arbre/compare/v1.1.0...v1.1.1) * Use mime-types 2.x for Ruby 1.9 by [@timoschilling][] * Verify Ruby 2.3 support. [#59][] by [@dlackty][] ## 1.1.0 [☰](https://github.com/activeadmin/arbre/compare/v1.0.3...v1.1.0) * Tag option `for` sets the attribute when value is a string or symbol [#49][] by [@ramontayag][] ## 1.0.3 [☰](https://github.com/activeadmin/arbre/compare/v1.0.2...v1.0.3) * Performance improvements [#40][] by [@alexesDev][] * Added all void elements as self-closing tags [#39][] by [@OscarBarrett][] * Missing tags added [#36][] / [#39][] by [@dtaniwaki][] and [@OscarBarrett][] ## 1.0.2 [☰](https://github.com/activeadmin/arbre/compare/v1.0.1...v1.0.2) * make `Element#inspect` behave correctly in Ruby 2.0 [#16][] by [@seanlinsley][] * prevent `Arbre::Element#flatten` infinite recursion [#32][] by [@seanlinsley][] * make `find_by_class` correctly find children by class [#33][] by [@kaapa][] ## 1.0.1 [☰](https://github.com/activeadmin/arbre/compare/v1.0.0...v1.0.1) * Template handler converts to string to satisfy Rack::Lint [#6][] by [@jpmckinney][] * Fix to `Tag#add_class` when passing a string of classes to Tag build method [#4][] by [@gregbell][] * Not longer uses the default separator [#7][] by [@LTe][] ## 1.0.0 [☰](https://github.com/activeadmin/arbre/compare/v1.0.0.rc4...v1.0.0) * Added support for the use of `:for` with non Active Model objects ## 1.0.0.rc4 [☰](https://github.com/activeadmin/arbre/compare/v1.0.0.rc3...v1.0.0.rc4) * Fix issue where user could call `symbolize_keys!` on a HashWithIndifferentAccess which doesn't implement the method ## 1.0.0.rc3 [☰](https://github.com/activeadmin/arbre/compare/v1.0.0.rc2...v1.0.0.rc3) * Implemented `Arbre::HTML::Tag#default_id_for_prefix` ## 1.0.0.rc2 [☰](https://github.com/activeadmin/arbre/compare/v1.0.0.rc1...v1.0.0.rc2) * Fixed bug where Component's build methods were being rendered within the parent context. ## 1.0.0.rc1 Initial release and extraction from Active Admin [#4]: https://github.com/activeadmin/arbre/issues/4 [#6]: https://github.com/activeadmin/arbre/issues/6 [#7]: https://github.com/activeadmin/arbre/issues/7 [#16]: https://github.com/activeadmin/arbre/issues/16 [#32]: https://github.com/activeadmin/arbre/issues/32 [#33]: https://github.com/activeadmin/arbre/issues/33 [#36]: https://github.com/activeadmin/arbre/issues/36 [#39]: https://github.com/activeadmin/arbre/issues/39 [#40]: https://github.com/activeadmin/arbre/issues/40 [#46]: https://github.com/activeadmin/arbre/issues/46 [#49]: https://github.com/activeadmin/arbre/issues/49 [#59]: https://github.com/activeadmin/arbre/issues/59 [#64]: https://github.com/activeadmin/arbre/pull/64 [#78]: https://github.com/activeadmin/arbre/pull/78 [#110]: https://github.com/activeadmin/arbre/pull/110 [#121]: https://github.com/activeadmin/arbre/pull/121 [@aramvisser]: https://github.com/aramvisser [@LTe]: https://github.com/LTe [@OscarBarrett]: https://github.com/OscarBarrett [@alexesDev]: https://github.com/alexesDev [@deivid-rodriguez]: https://github.com/deivid-rodriguez [@dlackty]: https://github.com/dlackty [@dtaniwaki]: https://github.com/dtaniwaki [@gregbell]: https://github.com/gregbell [@jpmckinney]: https://github.com/jpmckinney [@kaapa]: https://github.com/kaapa [@ramontayag]: https://github.com/ramontayag [@seanlinsley]: https://github.com/seanlinsley [@timoschilling]: https://github.com/timoschilling [@varyonic]: https://github.com/varyonic