else
return window.getComputedStyle(el, null).getPropertyValue('display') is 'block'
-# pass a node (not an element) for a tag
-# returns if this is the sort of tag that cares about leading/trailing whitespace
-# FIXME this probably doesn't work all the time
-is_whitespace_significant = (n) ->
- if n.name is 'textarea'
- return true
- if n.name is 'pre'
- return true
- if n.el.currentStyle?
- return n.el.currentStyle['white-space'].substr(0, 3) is 'pre'
- else
- return window.getComputedStyle(n.el, null).getPropertyValue('white-space').substr(0, 3) is 'pre'
-
# Pass return value from dom event handlers to this.
# If they return false, this will addinionally stop propagation and default.
event_return = (e, bool) ->
tr: true
thead: true
tbody: true
+ ul: true
+ ol: true
}
-# FIXME terminology: s/dom/tree/; s/el/n/
-tree_to_html = (tree, indent = '', parent_is_block = false) ->
- ret = ''
- for n, i in tree
- switch n.type
- when TYPE_TAG
- is_block = is_display_block n.el
- if is_block
- is_tiny_block = false
- if is_whitespace_significant n
- is_tiny_block = true
- else
- if n.children.length is 1
- if n.children[0].type is TYPE_TEXT
- if n.children[0].text.length < 35
- is_tiny_block = true
- if is_block or (parent_is_block and i is 0)
- ret += indent
- ret += '<' + n.name
- attr_keys = []
- for k of n.attrs
- attr_keys.unshift k
- #attr_keys.sort()
- for k in attr_keys
- ret += " #{k}"
- if n.attrs[k].length > 0
- ret += "=\"#{enc_attr n.attrs[k]}\""
- ret += '>'
- unless void_elements[n.name]?
- if is_block
- next_indent = indent + ' '
- else
- next_indent = indent
- if n.children.length
- if is_block and not is_tiny_block
- ret += "\n"
- ret += tree_to_html n.children, next_indent, is_block and not is_tiny_block
- if is_block and not is_tiny_block
- ret += indent
- ret += "</#{n.name}>"
- if is_block or (parent_is_block and i is tree.length - 1)
- ret += "\n"
- when TYPE_TEXT
- if parent_is_block and i is 0
- ret += indent
- ret += enc_text n.text
- if parent_is_block and i is tree.length - 1
- ret += "\n"
- when TYPE_COMMENT
- ret += "<!--#{n.text}-->"
- when TYPE_DOCTYPE
- ret += "<!DOCTYPE #{n.name}"
- if n.public_identifier? and n.public_identifier.length > 0
- ret += " \"#{n.public_identifier}\""
- if n.system_identifier? and n.system_identifier.length > 0
- ret += " \"#{n.system_identifier}\""
- ret += ">\n"
- return ret
domify = (doc, hash) ->
for tag, attrs of hash
@changed()
changed: ->
@in_el.onchange = null
- @in_el.value = tree_to_html @tree
+ @in_el.value = @pretty_html @tree
@in_el.onchange = =>
@load_html @in_el.value
@iframe.style.height = "0"
@matting.push ann
n = n.parent
alpha *= 1.5
+ pretty_html: (tree, indent = '', parent_flags = pre_ish: false, block: true, want_nl: false) ->
+ ret = ''
+ want_nl = parent_flags.want_nl
+ prev_in_flow_is_text = false
+ prev_in_flow_is_block = false
+ for n, i in tree
+ # figure out flags
+ inner_flags = want_nl: true
+ is_br = false
+ switch n.type
+ when TYPE_TAG
+ if n.name is 'br'
+ is_br = true
+ is_text = false
+ if n.el.currentStyle?
+ cs = n.el.currentStyle
+ whitespace = cs['white-space']
+ display = cs['display']
+ position = cs['position']
+ float = cs['float']
+ else
+ cs = @iframe.contentWindow.getComputedStyle(n.el, null)
+ whitespace = cs.getPropertyValue 'white-space'
+ display = cs.getPropertyValue 'display'
+ position = cs.getPropertyValue 'position'
+ float = cs.getPropertyValue 'float'
+ if n.name is 'textarea'
+ inner_flags.pre_ish = true
+ else
+ inner_flags.pre_ish = whitespace.substr(0, 3) is 'pre'
+ switch float
+ when 'left', 'right'
+ in_flow = false
+ else
+ switch position
+ when 'absolute', 'fixed'
+ in_flow = false
+ else
+ if 'display' is 'none'
+ in_flow = false
+ else
+ in_flow = true
+ switch display
+ when 'inline', 'none'
+ inner_flags.block = false
+ is_block = in_flow_block = false
+ when 'inline-black'
+ inner_flags.block = true
+ is_block = in_flow_block = false
+ else # block, table, etc
+ inner_flags.block = true
+ is_block = true
+ in_flow_block = in_flow
+ when TYPE_TEXT
+ is_text = true
+ is_block = false
+ in_flow = true
+ in_flow_block = false
+ else # TYPE_COMMENT, TYPE_DOCTYPE
+ is_text = false
+ is_block = false
+ in_flow = false
+ in_flow_block = false
+ # print whitespace if we can
+ unless parent_flags.pre_ish
+ unless prev_in_flow_is_text and is_br
+ if (i is 0 and parent_flags.block) or in_flow_block or prev_in_flow_is_block
+ if want_nl
+ ret += "\n"
+ ret += indent
+ switch n.type
+ when TYPE_TAG
+ ret += '<' + n.name
+ attr_keys = []
+ for k of n.attrs
+ attr_keys.unshift k
+ #attr_keys.sort()
+ for k in attr_keys
+ ret += " #{k}"
+ if n.attrs[k].length > 0
+ ret += "=\"#{enc_attr n.attrs[k]}\""
+ ret += '>'
+ unless void_elements[n.name]?
+ if inner_flags.block
+ next_indent = indent + ' '
+ else
+ next_indent = indent
+ if n.children.length
+ ret += @pretty_html n.children, next_indent, inner_flags
+ ret += "</#{n.name}>"
+ when TYPE_TEXT
+ ret += enc_text n.text
+ when TYPE_COMMENT
+ ret += "<!--#{n.text}-->" # TODO encode?
+ when TYPE_DOCTYPE
+ ret += "<!DOCTYPE #{n.name}"
+ if n.public_identifier? and n.public_identifier.length > 0
+ ret += " \"#{n.public_identifier}\""
+ if n.system_identifier? and n.system_identifier.length > 0
+ ret += " \"#{n.system_identifier}\""
+ ret += ">"
+ want_nl = true
+ if in_flow
+ prev_in_flow_is_text = is_text
+ prev_in_flow_is_block = is_block or (in_flow and is_br)
+ if tree.length
+ # output final newline if allowed
+ unless parent_flags.pre_ish
+ if prev_in_flow_is_block or parent_flags.block
+ ret += "\n#{indent.substr 4}"
+ return ret
window.peach_html5_editor = (args...) ->
return new PeachHTML5Editor args...