class Trenni::Builder

Build markup quickly and efficiently.

def self.fragment(output = nil, &block)

A helper to generate fragments of markup.
def self.fragment(output = nil, &block)
	if output.is_a?(Binding)
		output = Template.buffer(output)
	end
	
	if output.nil?
		return Fragment.new(block)
	end
	
	if output.is_a?(Builder)
		block.call(output)
	else
		block.call(Builder.new(output))
	end
	
	return nil
end

def self.tag(name, content, **attributes)

def self.tag(name, content, **attributes)
	self.fragment do |builder|
		builder.inline(name, attributes) do
			builder.text(content)
		end
	end
end

def <<(content)

def <<(content)
	return unless content
	
	if content.is_a?(Fragment)
		inline! do
			content.call(self)
		end
	else
		Markup.append(@output, content)
	end
end

def == other

def == other
	@output == String(other)
end

def append(value)

Append pre-existing markup:
def append(value)
	return unless value
	
	# The parent has one more child:
	@level[-1] += 1
	
	if @indent
		value.each_line.with_index do |line, i|
			@output << indentation << line
		end
	else
		@output << value
	end
end

def capture(*arguments, &block)

def capture(*arguments, &block)
	Template.capture(*arguments, output: self, &block)
end

def doctype(attributes = 'html')

def doctype(attributes = 'html')
	@output << "<!DOCTYPE #{attributes}>\n"
end

def encoding

def encoding
	@output.encoding
end

def full_tag(name, attributes, indent_outer, indent_inner, &block)

A normal block level/container tag.
def full_tag(name, attributes, indent_outer, indent_inner, &block)
	if block_given?
		if indent_outer
			@output << "\n" if @level.last > 0
			@output << indentation
		end
		
		tag = Trenni::Tag.opened(name.to_s, attributes)
		tag.write_opening_tag(@output)
		@output << "\n" if indent_inner
		
		# The parent has one more child:
		@level[-1] += 1
		
		@level << 0
		
		yield
		
		children = @level.pop
		
		if indent_inner
			@output << "\n" if children > 0
			@output << indentation
		end
		
		tag.write_closing_tag(@output)
	else
		# The parent has one more child:
		@level[-1] += 1
		
		@output << indentation
		Trenni::Tag.append_tag(@output, name.to_s, attributes, nil)
	end
end

def indentation

def indentation
	if @indent
		INDENT * (@level.size - 1)
	else
		''
	end
end

def initialize(output = nil, indent: true, encoding: Encoding::UTF_8)

def initialize(output = nil, indent: true, encoding: Encoding::UTF_8)
	# This field gets togged in #inline so we keep track of it separately from @indentation.
	@indent = indent
	
	# We don't need to use MarkupString here as Builder itself is considered markup and should be inserted directly into the output stream.
	@output = output || MarkupString.new.force_encoding(encoding)
	
	@level = [0]
	@children = [0]
end

def inline!

def inline!
	original_indent = @indent
	@indent = false
	
	yield
ensure
	@indent = original_indent
end

def inline_tag(name, attributes = {}, &block)

Begin an inline tag.
def inline_tag(name, attributes = {}, &block)
	original_indent = @indent
	
	full_tag(name, attributes, @indent, false) do
		@indent = false
		yield if block_given?
	end
ensure
	@indent = original_indent
end

def raw(content)

def raw(content)
	@output << content
end

def tag(name, attributes = {}, &block)

Begin a block tag.
def tag(name, attributes = {}, &block)
	full_tag(name, attributes, @indent, @indent, &block)
end

def text(content)

def text(content)
	return unless content
	
	if @indent
		@output << "\n" if @level.last > 0
		@output << indentation
	end
	
	Markup.append(@output, content)
	
	if @indent
		@output << "\n"
	end
end

def to_str

Required for output to buffer.
def to_str
	@output
end