<commit_before># -*- encoding : utf-8 -*-

# Utilities for html text generation.
module Forma::Html

  # Attribute creation.
  def attr(*params)
    if params.length == 2
      SimpleAttr.new(params[0].to_s, params[1].to_s)
    elsif params.length == 1 and params[0].is_a?(Hash)
      StyleAttr.new(params[0])
    elsif params.length == 1
      ClassAttr.new(params[0])
    else
      raise "illegal attr specification: #{params}"
    end
  end

  # You can easily create elements using this method.
  #
  # ```
  # include Forma::Html
  # element = el("div", attrs = {id: 'main', class: 'header', style: {'font-size' => '20px'}})
  # html = element.to_s
  # ```
  def el(tag, opts = {})
    opts = opts.symbolize_keys
    h = { text: opts[:text] }
    if opts[:attrs]
      attributes = []
      opts[:attrs].each do |k, v|
        if k == :class || k == :style
          attributes << attr(v)
        else
          attributes << attr(k, v)
        end
      end
      h[:attrs] = attributes
    end
    h[:children] = opts[:children]
    Element.new(tag, h)
  end

  module_function :attr
  module_function :el

  private

  class Attr; end

  # Simple attribute.
  class SimpleAttr < Attr
    def initialize(name, value)
      @name = name
      @value = value
    end

    def name
      @name
    end

    def value
      @value
    end

    def to_s
      if @name.present? and @value.present?
        %Q{#{@name}="#{@value}"}
      end
    end
  end

  # Class attribute.
  class ClassAttr < Attr
    def initialize(values)
      @values = values
    end

    def values
      @values
    end

    def to_s
      if @values.present?
        if @values.is_a?(Array)
          %Q{class="#{@values.join(" ")}"}
        else
          %Q{class="#{@values}"}
        end
      end
    end
  end

  # Style attribute.
  class StyleAttr < Attr
    def initialize(styles)
      @styles = styles
    end

    def styles
      @styles
    end

    def to_s
      if @styles.present?
        %Q{style="#{@styles.map{ |k,v| "#{k}:#{v}" }.join(";")}"}
      end
    end
  end

  # Element class.
  class Element

    def initialize(tag, h)
      @tag = tag.to_s
      @text = h[:text]
      @attrs = h[:attrs] || []
      @children = []
      h[:children].each { |c| @children << c } if h[:children]
      ids = @attrs.select { |x| x.is_a?(SimpleAttr) and x.name == "id" }.map { |x| x.value }
      @id = ids[0] if ids.length > 0
      @classes = @attrs.select { |x| x.is_a?(ClassAttr) }.map{ |x| x.values }.flatten
    end

    def tag
      @tag
    end

    def text
      @text
    end

    def id
      @id
    end

    def klass
      @classes
    end

    def to_s
      generate_html.html_safe
    end

    private<commit_msg>you can change text of html element<commit_after># -*- encoding : utf-8 -*-

# Utilities for html text generation.
module Forma::Html

  # Attribute creation.
  def attr(*params)
    if params.length == 2
      SimpleAttr.new(params[0].to_s, params[1].to_s)
    elsif params.length == 1 and params[0].is_a?(Hash)
      StyleAttr.new(params[0])
    elsif params.length == 1
      ClassAttr.new(params[0])
    else
      raise "illegal attr specification: #{params}"
    end
  end

  # You can easily create elements using this method.
  #
  # ```
  # include Forma::Html
  # element = el("div", attrs = {id: 'main', class: 'header', style: {'font-size' => '20px'}})
  # html = element.to_s
  # ```
  def el(tag, opts = {})
    opts = opts.symbolize_keys
    h = { text: opts[:text] }
    if opts[:attrs]
      attributes = []
      opts[:attrs].each do |k, v|
        if k == :class || k == :style
          attributes << attr(v)
        else
          attributes << attr(k, v)
        end
      end
      h[:attrs] = attributes
    end
    h[:children] = opts[:children]
    Element.new(tag, h)
  end

  module_function :attr
  module_function :el

  private

  class Attr; end

  # Simple attribute.
  class SimpleAttr < Attr
    def initialize(name, value)
      @name = name
      @value = value
    end

    def name
      @name
    end

    def value
      @value
    end

    def to_s
      if @name.present? and @value.present?
        %Q{#{@name}="#{@value}"}
      end
    end
  end

  # Class attribute.
  class ClassAttr < Attr
    def initialize(values)
      @values = values
    end

    def values
      @values
    end

    def to_s
      if @values.present?
        if @values.is_a?(Array)
          %Q{class="#{@values.join(" ")}"}
        else
          %Q{class="#{@values}"}
        end
      end
    end
  end

  # Style attribute.
  class StyleAttr < Attr
    def initialize(styles)
      @styles = styles
    end

    def styles
      @styles
    end

    def to_s
      if @styles.present?
        %Q{style="#{@styles.map{ |k,v| "#{k}:#{v}" }.join(";")}"}
      end
    end
  end

  # Element class.
  class Element
    attr_reader :tag, :id, :attrs
    attr_accessor :text

    def initialize(tag, h)
      @tag = tag.to_s
      @text = h[:text]
      @attrs = h[:attrs] || []
      @children = []
      h[:children].each { |c| @children << c } if h[:children]
      ids = @attrs.select { |x| x.is_a?(SimpleAttr) and x.name == "id" }.map { |x| x.value }
      @id = ids[0] if ids.length > 0
      @classes = @attrs.select { |x| x.is_a?(ClassAttr) }.map{ |x| x.values }.flatten
    end

    def klass
      @classes
    end

    def to_s
      generate_html.html_safe
    end

    private
{'fraction_non_alphanumeric': 0.13910327085630284, 'fraction_numerical': 0.004777655273796398, 'mean_word_length': 1.9743169398907103, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4964801', 'n_tokens_mistral': 1900, 'n_tokens_neox': 1866, 'n_words': 501}