Split namespace for pretty mode

This commit is contained in:
Takashi Kokubun 2015-10-24 13:59:15 +09:00
parent 9753c2a0a5
commit 83b73aaa25
11 changed files with 230 additions and 142 deletions

View File

@ -4,7 +4,7 @@ require 'hamlit/compiler/script_compiler'
require 'hamlit/compiler/silent_script_compiler'
require 'hamlit/compiler/tag_compiler'
require 'hamlit/filters'
require 'hamlit/whitespace/compiler'
require 'hamlit/whitespace_compiler'
module Hamlit
class Compiler
@ -16,7 +16,7 @@ module Hamlit
@tag_compiler = TagCompiler.new(options)
@filter_compiler = Filters.new(options)
@whitespace_compiler = Whitespace::Compiler.new
@whitespace_compiler = WhitespaceCompiler.new
end
def call(ast)

View File

@ -1,7 +1,7 @@
require 'temple'
require 'hamlit/compiler'
require 'hamlit/pretty_compiler'
require 'hamlit/parser'
require 'hamlit/compiler'
require 'pretty_hamlit/engine'
module Hamlit
class Engine < Temple::Engine
@ -11,7 +11,6 @@ module Hamlit
html_type: nil,
attr_quote: "'",
escape_html: true,
pretty: false,
autoclose: %w(area base basefont br col command embed frame
hr img input isindex keygen link menuitem meta
param source track wbr),
@ -19,7 +18,7 @@ module Hamlit
)
use Parser
use :Compiler, -> { options[:pretty] ? PrettyCompiler : Compiler }
use Compiler
html :Fast
filter :Escapable
filter :ControlFlow
@ -35,7 +34,11 @@ module Hamlit
end
def precompiled
Engine.new(temple_options).call(@template)
if @options[:ugly]
Engine.new(temple_options).call(@template)
else
PrettyHamlit::Engine.new(temple_options).call(@template)
end
end
def render(scope = Object.new, locals = {}, &block)
@ -49,7 +52,7 @@ module Hamlit
def temple_options
@options.dup.tap do |options|
options[:pretty] = !options.delete(:ugly)
options.delete(:ugly)
case options[:format]
when :html5
options[:format] = :html

View File

@ -3,16 +3,11 @@ require 'haml/util'
module Hamlit
class Filters
class Plain < Base
def initialize(options = {})
super
@pretty = options[:pretty]
end
def compile(node)
text = node.value[:text].rstrip
if Haml::Util.contains_interpolation?(text)
# FIXME: Confirm whether this is correct or not
text << "\n".freeze unless @pretty
text << "\n".freeze
text = Haml::Util.unescape_interpolation(text)
[:escape, true, [:dynamic, text]]
else

View File

@ -1,66 +0,0 @@
module Hamlit
module Whitespace
class Compiler
def compile_children(node, &block)
temple = [:multi]
return temple if node.children.empty?
temple << :whitespace if prepend_whitespace?(node)
node.children.each do |n|
rstrip_whitespace!(temple) if nuke_outer_whitespace?(n)
temple << yield(n)
temple << :whitespace if insert_whitespace?(n)
end
rstrip_whitespace!(temple) if nuke_inner_whitespace?(node)
confirm_whitespace(temple)
end
private
def confirm_whitespace(temple)
temple.map do |exp|
case exp
when :whitespace
[:static, "\n"]
else
exp
end
end
end
def prepend_whitespace?(node)
return false unless %i[comment tag].include?(node.type)
!nuke_inner_whitespace?(node)
end
def nuke_inner_whitespace?(node)
return false if node.type != :tag
node.value[:nuke_inner_whitespace]
end
def nuke_outer_whitespace?(node)
return false if node.type != :tag
node.value[:nuke_outer_whitespace]
end
def rstrip_whitespace!(temple)
if temple[-1] == :whitespace
temple.delete_at(-1)
end
end
def insert_whitespace?(node)
return false if nuke_outer_whitespace?(node)
case node.type
when :doctype
node.value[:type] != 'xml'
when :comment, :filter, :plain, :script, :tag
true
else
false
end
end
end
end
end

View File

@ -1,57 +0,0 @@
require 'hamlit/whitespace/compiler'
module Hamlit
module Whitespace
class IndentedCompiler < Compiler
def compile_children(node, indent_level, &block)
temple = [:multi]
return temple if node.children.empty?
temple << :whitespace if prepend_whitespace?(node)
node.children.each do |n|
rstrip_whitespace!(temple) if nuke_outer_whitespace?(n)
temple << yield(n)
if insert_whitespace?(n)
if nuke_inner_whitespace?(node)
temple << :weak_whitespace
else
temple << :whitespace
end
end
end
rstrip_whitespace!(temple) if nuke_inner_whitespace?(node)
weaken_last_whitespace!(temple)
confirm_whitespace(temple, indent_level)
end
private
def rstrip_whitespace!(temple)
if %i[whitespace weak_whitespace].include?(temple[-1])
temple.delete_at(-1)
end
end
def weaken_last_whitespace!(temple)
if temple[-1] == :whitespace
temple.delete_at(-1)
temple << :weak_whitespace
end
end
def confirm_whitespace(temple, indent_level)
temple.map do |exp|
case exp
when :whitespace
[:static, "\n" + (' ' * indent_level)]
when :weak_whitespace
level = [0, indent_level - 1].max
[:static, "\n" + (' ' * level)]
else
exp
end
end
end
end
end
end

View File

@ -0,0 +1,64 @@
module Hamlit
class WhitespaceCompiler
def compile_children(node, &block)
temple = [:multi]
return temple if node.children.empty?
temple << :whitespace if prepend_whitespace?(node)
node.children.each do |n|
rstrip_whitespace!(temple) if nuke_outer_whitespace?(n)
temple << yield(n)
temple << :whitespace if insert_whitespace?(n)
end
rstrip_whitespace!(temple) if nuke_inner_whitespace?(node)
confirm_whitespace(temple)
end
private
def confirm_whitespace(temple)
temple.map do |exp|
case exp
when :whitespace
[:static, "\n"]
else
exp
end
end
end
def prepend_whitespace?(node)
return false unless %i[comment tag].include?(node.type)
!nuke_inner_whitespace?(node)
end
def nuke_inner_whitespace?(node)
return false if node.type != :tag
node.value[:nuke_inner_whitespace]
end
def nuke_outer_whitespace?(node)
return false if node.type != :tag
node.value[:nuke_outer_whitespace]
end
def rstrip_whitespace!(temple)
if temple[-1] == :whitespace
temple.delete_at(-1)
end
end
def insert_whitespace?(node)
return false if nuke_outer_whitespace?(node)
case node.type
when :doctype
node.value[:type] != 'xml'
when :comment, :filter, :plain, :script, :tag
true
else
false
end
end
end
end

View File

@ -1,12 +1,15 @@
require 'hamlit/compiler'
require 'hamlit/whitespace/indented_compiler'
require 'pretty_hamlit/filters'
require 'pretty_hamlit/whitespace_compiler'
module Hamlit
class PrettyCompiler < Compiler
def initialize(*)
module PrettyHamlit
class Compiler < Hamlit::Compiler
def initialize(options = {})
super
@indent_level = 0
@whitespace_compiler = Whitespace::IndentedCompiler.new
@filter_compiler = Filters.new(options)
@whitespace_compiler = WhitespaceCompiler.new
end
private

View File

@ -0,0 +1,29 @@
require 'temple'
require 'hamlit/parser'
require 'pretty_hamlit/compiler'
module PrettyHamlit
class Engine < Temple::Engine
define_options(
generator: Temple::Generators::ArrayBuffer,
format: :html,
html_type: nil,
attr_quote: "'",
escape_html: true,
pretty: true,
autoclose: %w(area base basefont br col command embed frame
hr img input isindex keygen link menuitem meta
param source track wbr),
filename: "",
)
use Hamlit::Parser
use Compiler
html :Fast
filter :Escapable
filter :ControlFlow
filter :MultiFlattener
filter :StaticMerger
use :Generator, -> { options[:generator] }
end
end

View File

@ -0,0 +1,45 @@
require 'hamlit/filters'
require 'pretty_hamlit/filters/plain'
module PrettyHamlit
class Filters
@registered = Hamlit::Filters.registered.dup
class << self
attr_reader :registered
private
def register(name, compiler)
registered[name] = compiler
end
end
register :plain, Plain
def initialize(options = {})
@options = options
end
def compile(node)
find_compiler(node.value[:name]).compile(node)
end
private
def find_compiler(name)
name = name.to_sym
compiler = Filters.registered[name]
raise NotFound.new("FilterCompiler for '#{name}' was not found") unless compiler
compilers[name] ||= compiler.new(@options)
end
def compilers
@compilers ||= {}
end
class NotFound < RuntimeError
end
end
end

View File

@ -0,0 +1,17 @@
require 'hamlit/filters/plain'
module PrettyHamlit
class Filters
class Plain < Hamlit::Filters::Plain
def compile(node)
text = node.value[:text].rstrip
if Haml::Util.contains_interpolation?(text)
text = Haml::Util.unescape_interpolation(text)
[:escape, true, [:dynamic, text]]
else
[:static, text]
end
end
end
end
end

View File

@ -0,0 +1,55 @@
require 'hamlit/whitespace_compiler'
module PrettyHamlit
class WhitespaceCompiler < Hamlit::WhitespaceCompiler
def compile_children(node, indent_level, &block)
temple = [:multi]
return temple if node.children.empty?
temple << :whitespace if prepend_whitespace?(node)
node.children.each do |n|
rstrip_whitespace!(temple) if nuke_outer_whitespace?(n)
temple << yield(n)
if insert_whitespace?(n)
if nuke_inner_whitespace?(node)
temple << :weak_whitespace
else
temple << :whitespace
end
end
end
rstrip_whitespace!(temple) if nuke_inner_whitespace?(node)
weaken_last_whitespace!(temple)
confirm_whitespace(temple, indent_level)
end
private
def rstrip_whitespace!(temple)
if %i[whitespace weak_whitespace].include?(temple[-1])
temple.delete_at(-1)
end
end
def weaken_last_whitespace!(temple)
if temple[-1] == :whitespace
temple.delete_at(-1)
temple << :weak_whitespace
end
end
def confirm_whitespace(temple, indent_level)
temple.map do |exp|
case exp
when :whitespace
[:static, "\n" + (' ' * indent_level)]
when :weak_whitespace
level = [0, indent_level - 1].max
[:static, "\n" + (' ' * level)]
else
exp
end
end
end
end
end