13 ms·
Creating an Editable Textarea That Supports Syntax-Highlighted Code (2021)
- deleted 4y ago[deleted]
- deleted 4y ago[deleted]
- deleted 4y ago[deleted]
- deleted 4y ago[deleted]
- deleted 4y ago[deleted]
- _boffin_ 4y agoBrilliant and excellent write up.
- retrofx 4y agoBut 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).