X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=editor.coffee;h=41d81c37192ed2aaab23cc543430a726d67e793a;hb=dde84cf239d827cb3a3b412d970e95bd5851216d;hp=6fa48cb25a760ee88d2ecaf3e0b021c36424a8dd;hpb=0bea1824fce33615c4ebc5f1a44b002bb76a8d1c;p=peach-html5-editor.git diff --git a/editor.coffee b/editor.coffee index 6fa48cb..41d81c3 100644 --- a/editor.coffee +++ b/editor.coffee @@ -58,19 +58,6 @@ is_display_block = (el) -> 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) -> @@ -161,65 +148,9 @@ no_text_elements = { # these elements never contain text 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 += "" - 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 += "" - when TYPE_DOCTYPE - ret += " 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 @@ -823,7 +754,7 @@ class PeachHTML5Editor @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" @@ -873,6 +804,117 @@ class PeachHTML5Editor @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 += "" + when TYPE_TEXT + ret += enc_text n.text + when TYPE_COMMENT + ret += "" # TODO encode? + when TYPE_DOCTYPE + ret += " 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...