Search code examples
javascripteditorace-editor

Ace Editor and entity encoding/decoding


I have searched across entire SO. for similar or exact topic and I couldn't find *(or didn't saw) topic on issue that's bothering me. If this is duplicate, and solution already exists, accept my apologies.

Currently I am working on cms application that uses both codemirror and ace editor, either this one or that one, and that depends on user/operator preference which one is going to be fired up once when particular document is loaded.

With codemirror, I have no issues at all. Everything works as expected. Codemirror is loading files via php's file_get_contents() directly into textarea, while ace is loading contents via ajax (current application nature demands so) and the issue that bothers me is actually one single operator/character which is : &

I have checked all the methods I wrote in the backend and there is no a single sanitize method or function or preg or whatever.. which I implemented.

The only thing being sanitized by me personally, on backend side is textarea tag, which is being wrapped within comment, and unwrapped again upon saving to file as php/html.

Ace is -aggressively- converting & character to & entity all the time, no matter what I try, no matter which selected "mode" is chosen (HTML,CSS,PHP, JS... you name it) and I don't want such behavior, I want loaded code to remain intact, on doc/file load/open and doc/file save/write, unless, normally, user doesn't edit or convert those characters manually by hand while editing.

In fact, < and > are "doing fine" .. ace is not "afraid of 'em", there is no automatic conversion to &lt; and to &gt; - just &.

I spent a lot of time on ace api pages, and found nothing (or didn't looked very good), no particular "setThisThat.option: boolean", etc.. that could solve this little issue.

If that matters, I am using ace min-noconflict (modes and themes as well, minified) version 5 days old since this very day.

I know that automatic conversion of "problematic characters" is there for a reason, but I actually do know how to handle those by my self with php, and all I need is to totally disable that feature.

I hope that I was clear regarding my issue, here is an issue example with JavaScript mode:

Expected result

if (typeof(pureTextReal) === "object" && aceSetMode === 'php' ) { /* Code */ }

Ace result

if (typeof(pureTextReal) === "object" &amp;&amp; aceSetMode === 'php' ) { /* Code */ }

Solution

  • This question should remain open no longer as I accomplished what I wanted.

    When the content is loaded with all applicable characters substituted with their html entites and placed inside hidden textarea first, than, textarea.value passed to ace element, upon ace loading, all characters are displayed correctly. Both ace and codemirror are now working exactly the same.

    Here is an example of working ace scenario.

    HTML generated via PHP

    Somewhere in the middle of the page, within form ..

    Ace pre tag here, (either pre or div tag, both are working well) Note that there is no & present, but nonetheless, it is converted now for good as all other specialcharacters once when it is present

        <!-- class cloak hides the element from being displayed -->
        <div id="code-wrapper" style="display: block;">
        <pre id="editor"></pre>
        <textarea id="code-content" name="code-content" class="cloak">
        &lt;h1&gt; Heading for &quot;Page&quot; &lt;/h1&gt;
            &lt;dl class=&quot;currentProject&quot;&gt;
                &lt;dt&gt;Current page ..&lt;/dt&gt;
                &lt;dd&gt;.. is under construction.&lt;/dd&gt;
            &lt;/dl&gt;
        </textarea>
        </div>
    

    .. than, right before closing </body> tag

    Ace requests, entire JAVASCRIPT in fact is created here, at the bottom of the documents

        <div class="cloak">
        <!-- Dynamic PHP generated paths -->
        <script type="text/javascript">var ui={u:'/path/to/library/', i:'/path/to/style/'};</script>
    
        <!-- Little framework --> 
        <script type="text/javascript" src="/path/to/dBmb.js" charset="utf-8"></script> 
        <script type="text/javascript"> // Dynamic values/elements
            var aceCode = 'editor', aceTHEME = 'dawn', aceSetMode = "php", hidden = 'code-content';
    
            // Append ace call to head
            dBmb.headScript(ui.u + 'ace/ace.js', true);
    
            // Append ace-config call to head
            dBmb.headScript(ui.u + 'dbmb.ace.config.js', true);
        </script>
        </div>
    

    CSS

    portion of linked css stylesheet

        div#code-wrapper {
            height: 100% !important;
            padding-top: 5px;
            border-top: 3px solid LightGrey;
        }
    
        div#code-wrapper * {
            transition: none !important;
        }
    
        pre#editor {
            display: block;
            width: auto;
            height: auto;
            text-align: initial;
            line-height: 1.5;
        }
    
        .ace_editor {
            font-size: 100% !important;
        }
    
        .cloak {
            display: none !important;
            max-width: 0 !important;
            max-height: 0 !important;
            position: absolute;
            z-index: -10;
            overflow: hidden;
            visibility: hidden;
        }
    

    Ace custom config

    This file is previously pulled (created) by custom dBmb.headScript function *(appends script tag to the head), at the end of the loaded html document, and it is dynamic. What PHP serves, this script accepts.

        // dbmb.ace.config.js
        var wh, textarea, elementAce, safetext, editor;
    
        document.onreadystatechange = function () {
            if (document.readyState === "complete") {
    
                elementAce = document.getElementById(aceCode);
                textarea = document.getElementById(hidden);
    
                editor = ace.edit(elementAce);
                safetext = textarea.value;
    
                editor.setOptions({
                    useWorker: false,
                    showPrintMargin: false,
                    behavioursEnabled: true,
                    theme: "ace/theme/" + aceTHEME,
                    mode: "ace/mode/" + aceSetMode
                });
    
                editor.$blockScrolling = Infinity;
                editor.session.setUseWrapMode(true);
                editor.session.setValue(safetext);
    
                var autoHeight = function() {
                    wh = (window.innerHeight - 100);
                    elementAce.style.height = wh + 'px';
                    editor.resize();
                };
    
                window.onresize = autoHeight;
    
                editor.getSession().on('change', function(e) {
                    textarea.value = editor.session.getValue();
                }); autoHeight();
    
        }};
    

    After everything is loaded, this is what I get on screen.

    Ace Result

    No console notices and errors on anything undefined.

    And when POST request is altered - $_POST['code-content'] is what I save to new/edited file.