From 0f0011fe19f527abc6d67c7245720d5d451085f5 Mon Sep 17 00:00:00 2001 From: Jason Woofenden Date: Mon, 1 Feb 2016 14:36:01 -0500 Subject: [PATCH] rename to Peach HTML5 Editor --- README.md | 27 ++++++++++------ editor.coffee | 78 +++++++++++++++++++++++++++++++++++++--------- editor_tests.coffee | 2 +- editor_tests.html | 26 ++++++++++++++++ editor_tests_coffee.html | 2 +- parser.coffee | 8 ++--- parser_tests.coffee | 24 +++++++------- parser_tests.html | 2 +- parser_tests_coffee.html | 2 +- 9 files changed, 127 insertions(+), 44 deletions(-) create mode 100644 editor_tests.html diff --git a/README.md b/README.md index af50f19..272da2e 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,26 @@ -wheic -===== +Peach HTML5 Editor +================== -This project is to build a HTML5 parser, then use that to build a WYSIWYG html -editor for the browser. - -The code is written in CoffeeScript for modern browsers. The HTML5 parser can -also run under node.js. +This is a WYSIWYG HTML5 editor for the browser. Status ------ -HTML5 parser: all (1581) tests pass. Works in the browser and node.js +Early development stages. + +The HTML5 parser component passes the full test suite (1581 tests). + +The interface is starting to exist. + + +Technologies +------------ + +Programming language: CoffeeScript (compiles to javascript) + +Interface: Implemented using the DOM api. No ``contenteditable`` or jquery. -WYSIWYG editor: planning stages Quick Start Guide @@ -28,7 +35,7 @@ Quick Start Guide 4. Try running the parser in the console, example: - window.wheic_parser.parse("

foo

", {fragment: "body"}) + window.peach_parser.parse("

foo

", {fragment: "body"}) For further reading, see "Running Under node.js" below. diff --git a/editor.coffee b/editor.coffee index 0f68f40..faa2e3f 100644 --- a/editor.coffee +++ b/editor.coffee @@ -43,7 +43,7 @@ dom_to_html = (dom) -> ret = '' for el in dom switch el.type - when wheic_parser.TYPE_TAG + when peach_parser.TYPE_TAG ret += '<' + el.name attr_keys = [] for k of el.attrs @@ -58,11 +58,11 @@ dom_to_html = (dom) -> if el.children.length ret += dom_to_html el.children ret += "" - when wheic_parser.TYPE_TEXT + when peach_parser.TYPE_TEXT ret += el.text - when wheic_parser.TYPE_COMMENT + when peach_parser.TYPE_COMMENT ret += "" - when wheic_parser.TYPE_DOCTYPE + when peach_parser.TYPE_DOCTYPE ret += " 0 ret += " \"#{el.public_identifier}\"" @@ -85,7 +85,7 @@ domify = (h) -> return el css = '' -css += 'span.peach_editor_cursor {' +css += 'div#peach_editor_cursor {' css += 'display: inline-block;' css += 'height: 1em;' css += 'width: 2px;' @@ -96,14 +96,30 @@ css += '-webkit-animation: 1s blink step-end infinite;' css += 'animation: 1s blink step-end infinite;' css += '}' css += '@-webkit-keyframes "blink" {' -css += 'from, to { background: transparent; }' -css += '50% { background: #000; }' +css += 'from, to { background: #000; }' +css += '50% { background: transparent; }' css += '}' css += '@keyframes "blink" {' -css += 'from, to { background: transparent; }' -css += '50% { background: #000; }' +css += 'from, to { background: #000; }' +css += '50% { background: transparent; }' css += '}' +# key codes: +KEY_LEFT = 37 +KEY_UP = 38 +KEY_RIGHT = 39 +KEY_DOWN = 40 +KEY_BACKSPACE = 8 # <-- +KEY_DELETE = 46 # --> +KEY_END = 35 +KEY_ENTER = 13 +KEY_ESCAPE = 27 +KEY_HOME = 36 +KEY_INSERT = 45 +KEY_PAGE_UP = 33 +KEY_PAGE_DOWN = 34 +KEY_TAB = 9 + wysiwyg = (el, options = {}) -> opt_fragment = options.fragment ? true parser_opts = {} @@ -113,15 +129,49 @@ wysiwyg = (el, options = {}) -> dom: [] iframe: document.createElement('iframe') load_html: (html) -> - @dom = wheic_parser.parse html, parser_opts - as_html = wheic.dom_to_html @dom + @dom = peach_parser.parse html, parser_opts + as_html = peach.dom_to_html @dom as_html = as_html.substr(0, 5) + '' + as_html.substr(5) @iframe.contentDocument.body.innerHTML = as_html } el.parentNode.appendChild editor_instance.iframe idoc = editor_instance.iframe.contentDocument + ignore_key_codes = + '18': true # alt + '20': true # capslock + '17': true # ctrl + '144': true # numlock + '16': true # shift + '91': true # windows "start" key + control_key_codes = # we react to these, but they aren't typing + '37': KEY_LEFT + '38': KEY_UP + '39': KEY_RIGHT + '40': KEY_DOWN + '35': KEY_END + '8': KEY_BACKSPACE + '46': KEY_DELETE + '13': KEY_ENTER + '27': KEY_ESCAPE + '36': KEY_HOME + '45': KEY_INSERT + '33': KEY_PAGE_UP + '34': KEY_PAGE_DOWN + '9': KEY_TAB + + idoc.body.onkeyup = (e) -> + return false if ignore_key_codes[e.keyCode]? + return false if control_key_codes[e.keyCode]? + idoc.body.onkeydown = (e) -> + return false if ignore_key_codes[e.keyCode]? + return false if control_key_codes[e.keyCode]? idoc.body.onkeypress = (e) -> - char = e.charCode ? e.keyCode ? e.which + return if e.ctrlKey + return false if ignore_key_codes[e.keyCode]? + # in firefox, keyCode is only set for non-typing keys + if e.keyCode isnt KEY_BACKSPACE # so this is fine + return false if control_key_codes[e.keyCode]? + char = e.charCode ? e.keyCode el.value += String.fromCharCode char editor_instance.load_html el.value return false @@ -135,9 +185,9 @@ wysiwyg = (el, options = {}) -> editor_instance.load_html el.value return editor_instance -window.wheic = { +window.peach = { wysiwyg: wysiwyg dom_to_html: dom_to_html } -# test in browser: wheic(document.getElementsByTagName('textarea')[0]) +# test in browser: peach.wysiwyg(document.getElementsByTagName('textarea')[0]) diff --git a/editor_tests.coffee b/editor_tests.coffee index 06dfd40..27a891d 100644 --- a/editor_tests.coffee +++ b/editor_tests.coffee @@ -8,7 +8,7 @@ button.onclick = in_el.onchange = in_el.onkeyup = -> else # first run button.parentNode.removeChild button - editor = wheic.wysiwyg in_el + editor = peach.wysiwyg in_el return false button.value="Load" button.removeAttribute 'disabled' diff --git a/editor_tests.html b/editor_tests.html new file mode 100644 index 0000000..1a04544 --- /dev/null +++ b/editor_tests.html @@ -0,0 +1,26 @@ + + + + + + html editor tester + + + +

Peach HTML5 Editor test page (partially compiled version)

+

This version of the editor test page requires that you've compiled parser.js (to speed up page load) but it does compile editor.coffee and editor_tests.coffee in the browser so you don't have to rebuild them every time you make a change.

+
+

In:

+

+
+ + + + + + diff --git a/editor_tests_coffee.html b/editor_tests_coffee.html index a16c0c4..8eb3932 100644 --- a/editor_tests_coffee.html +++ b/editor_tests_coffee.html @@ -12,7 +12,7 @@ -

WHEIC editor test page (CoffeeScript version)

+

Peach HTML5 Editor test page (CoffeeScript version)

This version of the test page compiles the CoffeeScript files in the browser. This is slower to load, but saves you having to rebuild as you work (or even install CoffeeScript).

In:

diff --git a/parser.coffee b/parser.coffee index 509e492..aa7233e 100644 --- a/parser.coffee +++ b/parser.coffee @@ -43,11 +43,11 @@ # # Call it like this: # -# wheic_parser.parse("

hi

") +# peach_parser.parse("

hi

") # # Or, if you don't want /etc, do this: # -# wheic_parser.parse("

hi

", {fragment: "body"}) +# peach_parser.parse("

hi

", {fragment: "body"}) # # return value is an array of Nodes, see "class Node" below. @@ -80,8 +80,8 @@ if (typeof module) isnt 'undefined' and module.exports? exports = module.exports else context = 'browser' - window.wheic_parser = {} - exports = window.wheic_parser + window.peach_parser = {} + exports = window.peach_parser from_code_point = (x) -> if String.fromCodePoint? diff --git a/parser_tests.coffee b/parser_tests.coffee index 5cc99bf..cc65725 100644 --- a/parser_tests.coffee +++ b/parser_tests.coffee @@ -7932,19 +7932,19 @@ tests = [ ] if typeof module isnt 'undefined' and module.exports? - wheic_parser = require './parser.coffee' + peach_parser = require './parser.coffee' else - wheic_parser = window.wheic_parser + peach_parser = window.peach_parser serialize_els = (els, prefix = '| ') -> ret = '' for el in els switch el.type - when wheic_parser.TYPE_TAG + when peach_parser.TYPE_TAG ret += "#{prefix}<" - if el.namespace is wheic_parser.NS_MATHML + if el.namespace is peach_parser.NS_MATHML ret += "math " - if el.namespace is wheic_parser.NS_SVG + if el.namespace is peach_parser.NS_SVG ret += "svg " ret += "#{el.name}>\n" attr_keys = [] @@ -7953,16 +7953,16 @@ serialize_els = (els, prefix = '| ') -> attr_keys.sort() # TODO this should be "lexicographically by UTF-16 code unit" for k in attr_keys ret += "#{prefix} #{k}=\"#{el.attrs[k]}\"\n" - if el.name is 'template' and el.namespace is wheic_parser.NS_HTML + if el.name is 'template' and el.namespace is peach_parser.NS_HTML ret += "#{prefix} content\n" ret += serialize_els el.children, "#{prefix} " else ret += serialize_els el.children, "#{prefix} " - when wheic_parser.TYPE_TEXT + when peach_parser.TYPE_TEXT ret += "#{prefix}\"#{el.text}\"\n" - when wheic_parser.TYPE_COMMENT + when peach_parser.TYPE_COMMENT ret += "#{prefix}\n" - when wheic_parser.TYPE_DOCTYPE + when peach_parser.TYPE_DOCTYPE ret += "#{prefix} 0) or (el.system_identifier? and el.system_identifier.length > 0) ret += " \"#{el.public_identifier ? ''}\"" @@ -7974,17 +7974,17 @@ serialize_els = (els, prefix = '| ') -> test_results = passed: 0, failed: 0 test_parser = (args) -> - wheic_parser.debug_log_reset() + peach_parser.debug_log_reset() parse_errors = [] args.error_cb = (i) -> parse_errors.push i prev_node_id = 0 # reset counter - parsed = wheic_parser.parse args.html, args + parsed = peach_parser.parse args.html, args serialized = serialize_els parsed if serialized isnt args.expected test_results.failed += 1 if test_results.failed is 1 - wheic_parser.debug_log_each (str) -> + peach_parser.debug_log_each (str) -> console.log str console.log "FAILED: \"#{args.name}\"" console.log " Input: #{args.html}" diff --git a/parser_tests.html b/parser_tests.html index 5288014..1e59713 100644 --- a/parser_tests.html +++ b/parser_tests.html @@ -6,7 +6,7 @@ html parser tester -

WHEIC html parser test page (javascript version)

+

Peach HTML5 Parser test page (javascript version)

You'll need to run make to build the javascript files used on this page.

If you don't have node.js and CoffeeScript installed, you can use the other test page which compiles the CoffeeScript files on the fly in the browser.

Check the inspector/console for test results.

diff --git a/parser_tests_coffee.html b/parser_tests_coffee.html index 7d2fc4d..78920ab 100644 --- a/parser_tests_coffee.html +++ b/parser_tests_coffee.html @@ -6,7 +6,7 @@ html parser tester -

WHEIC html parser test page (CoffeeScript version)

+

Peach HTML5 Parser test page (CoffeeScript version)

This version of the test page compiles the CoffeeScript files in the browser, so you don't have to install CoffeeScript (or node.js).

It can take a few seconds for the tests to compile.

Check the inspector/console for test results.

-- 1.7.10.4