Fred

MODX Tags in Code Snippets with Fred

 fare

MODX Tags in Code Snippets

Posting code snippets with MODX tags was not possible with Fred using the FixedPre plugin. MODX tags were being parsed by MODX as usual, causing unexpected output.

From multiple conversations in Slack and the Forums

sottwell asked...

Is there a way to post MODX tags in code snippets in Fred?

The Solution:

In a Slack conversation,

bruno17 says...

Maybe this could be a solution...it works together with prism.js highlighter. Begin code blocks with ### and end them with ####. Here is the modified plugin code.

    <?php
/**
 * FixedPre plugin
 *
 * *
 * @author Bob Ray <http://bobsguides.com>
 * Copyright 2011-2014 Bob Ray
 * 3/23/11
 *
 * FixedPre is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option) any
 * later version.
 *
 * FixedPre is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * FixedPre; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * @package fixedpre
 */
/**
 * MODx FixedPre plugin
 *
 * Description: MODx tags inside <fixedpre> blocks will be displayed
 * rather than executed.
 *
 * Events: OnParseDocument
 *
 * @package fixedpre
 *
 * @property
 */
/** plugin fixedpre  -- implements <fixedpre> tag
 * MODx code inside <fixedpre> tags will be displayed
 * rather than executed.
 * @author Rahul Dhesi
 * @author Bob Ray
 * @package fixedpre
 * 
 */
 
$opentag = $modx->getOption('fred-fixedpre-opentag',null,'###');
$closetag = $modx->getOption('fred-fixedpre-close',null,'####');

if (! function_exists('quote_meta') ) {
    function quote_meta($a) {
        $lhs = array("<", ">", "[", "]", "!", "{", "}", "`", "*", "~");
        $rhs = array("<", ">", "[", "]", "!", "{", "}", "`", "*", "~");
        $b = str_replace("&", "\255", $a[2]);  //save "&"
        $lhs_preg = array('||',  '||');
        $rhs_preg = array('<$1fixedpre>',  '<$1/fixedpre>');
        $b = preg_replace($lhs_preg, $rhs_preg, $b);
        $b = str_replace($lhs, $rhs, $b);
        /* restore '&' as '&' and wrap in span tag */
        //return '' . str_replace("\255", "&", $b) . '';
        return str_replace("\255", "&", $b);
    }
}
/** @var $modx modX */
$output =& $modx->documentOutput;
$output = str_replace($closetag,'</fixedpre></code></pre>',$output);
$output = str_replace($opentag,'<pre><code class="language-markup"><fixedpre>',$output);
$output = preg_replace_callback("#()(.*?)()#s",
    "quote_meta", $output);
return '';
  

And I created this javascript code to get html entities back and convert br to newlines.

  (function () {
if (typeof self === 'undefined' || !self.Prism || !self.document || !document.createRange) {
	return;
}
Prism.hooks.add('before-highlight', function (env) {
	env.code = env.element.innerText;        
	var str = env.code;
	str = decodeHTMLEntities(str);
	str = str.replace(/<br>/g, '\n');
	console.log(str);
	env.code = str;
});
function decodeHTMLEntities(text) {
  textArea = document.createElement('textarea');
  textArea.innerHTML = text;
  return textArea.value;
}
}());

What's the Story?

Because of the way Fred intercepts and then saves its content the FixedPre plugin couldn't work with Fred. Bruno's solution involves a modified FixedPre plugin and some prism.js javascript to reslove the problem.

Just start with three ###, then enter or paste your code, then end with four ####.

You'll need to download the prism files, upload them to your site, and add prism.js and prism.css to your template, as well as the javascript code either in script tags in the template or in a file included in a template.

You'll also need to create a new plugin, I called it fredFixedPre, with Bruno's PHP code. Like the original, it uses the OnParseDocument event. You should disable the original FixedPre plugin if you have it installed.

.

Like the original FixedPre, this modification will clean up the content to remove the special tags, replacing them with the pre fixedpre and code tags, and encoding MODX tags so that MODX won't process them. The javascript decodes the tag entities and enables the Prism syntax highlighing.

There are two ways you can use this system.

With TinyMCE

If you are editing content with (or without) TinyMCE, you can simply enter the first three ###, enter or paste your code, then finish with the four ####. You can also add a "code" button to the TinyMCE insert toolbar and use that on an empty new line, again enter the three ### before and the four #### after your code. You'll need to include the "code" plugin in the list of plugins for your custom TinyMCE configuration.

As a Fred Element

The second way is to use it in a Fred Element with an Option Set to provide a textarea to use for entering your code in an element's options panel.

<div class="card my-5 py-4 ">
  <div class="card-body">
    ###{{ code }}####
  </div>
</div>

The option set would look like this...

{
  "remote": true,
  "settings": [
    {
      "name": "code",
      "label": "Code",
      "type": "textarea",
      "value": "Enter your Code here"
    }
  ]
}

In this case, you don't even need to enter the delimiters with your code.

And to put the frosting on the cake, Bruno has even added System Settings to his mix, so you can specify what characters you want to delimit your code. The System Settings are "fred-fixedpre-opentag", and "fred-fixedpre-close". If you don't create the System Settings, they'll be ### and #### by default.

So now, once you set up the Prism files and the new plugin, you can use MODX tags in code snippets in your tutorials and articles using Fred.

Many, many thanks to Bruno!