But what is the real problem ? (getting editing and feedback in a simple way)
Textarea or contenteditable provide support for editing, but not for syntax highliting or fancy functions - or to have them, the usual is to write all needed for editing from the ground - because it's not possible to control content of editable in other way than by operating ranges of selection (like startOfsset and endOffset, regarding to startContainer and endContainer - and if they are equal, that's the cursor).
But it's very convinient to get both: contenteditable and syntax just by aligning precisely one over another, then get rid of few corner cases - as you can see below.
I made it once in Firefox 23+- in very minimal way. I applied it by userContent.css with @-moz-document regexp("^.*#?\\.(css|js|jsm)$") { .. }, it was working with view-source: as well, without making any changes to the original document (half transparent anonymous content over it), very little was needed to keep it in sync (or to have a handy feature to highligt same words as under cursor when Ctrl key is pressed) and.. you could just save the document after editing.
@-moz-document regexp("^.\*#?\\.(css|js|jsm)$") {
html>body>pre { -moz-binding: url(hilite.xml#hilite) !important; }
div { position:absolute; pointer-events:none; }
div, pre, span{ white-space:pre !important; background:transparent; .. }
::-moz-selection { background: #d0e0d0 !important;}
}
- - - <binding id="hilite" bindToUntrustedContent="true">
<content
><xht:div> </xht:div
><children /></content>
<implementation><constructor><![CDATA[
.. // "http://softwaremaniacs.org/soft/highlight/en/", version: 7.3.0 ..
this.sync =function(){
var t=this.replace(/<br>/g,'\n').replace(/ /g,' ').replace(/</g,'<<>')
.replace(/>/g,'<>>').replace(/&/g,'<&>');
t=hilite(t, this.word).replace(/<<>/g,'<span><</span>')
.replace(/<>>/g,'<span>></span>').replace(/<&>/g,'<span>&</span>')
this.e0.innerHTML= t;
};
this.keydownt = function(e){ // filtering keycodes
if ((e.keyCode == 9)&&(!e.ctrlKey)){
document.execCommand('insertHTML',false,'\t'); e.preventDefault(); } .. } //tab
this.keydownf = function(e){
if(e.ctrlKey) getWord(); setTimeout(function() {sync();}, 0); .. }
setTimeout(function(){
document.body.setAttribute('spellcheck',"false"); this.contentEditable = true;
this.e0=document.getAnonymousNodes(this)[0];
this.textContent=this.innerHTML.replace(/ /g,' ').replace(/&/g,'&')
.replace(/</g,'<').replace(/>/g,'>');
sync(); this.focus(); }, 0, false);
]]></constructor></implementation></binding></bindings>
Orthogonally to that, I had userContent/Chrome.css opened in the sidebar and on every key up I unregister and loadAndRegisterSheet with it :) (the styles were applied live to documents or browser when the sidebar was open and saved on unload).
Brilliant and excellent write up.