Textpattern CMS support forum
You are not logged in. Register | Login | Help
- Topics: Active | Unanswered
Code syntax highlighting of bc in txp:body with textile?
On the forum we have a little helper so that we can do:
bc..{space}{newline}
txp{newline}
txp:code here …
(or html, php, css, js in place of txp)
That works great for highlighting code, even though we have no actual txp-specific syntax highlighter at this time.
For that there’s a little helper file that converts the textile into the prism class for the pre tag (later the js turns that from language-txp -> language-html).
Can we do something similar for regular Textpattern sites? Prism and textile are both part of a standard Textpattern installation. Is there a way to add the same hook as used here in the forum to Textpattern’s textiling?
TXP Builders – finely-crafted code, design and txp
Offline
Re: Code syntax highlighting of bc in txp:body with textile?
jakob wrote #319900:
On the forum we have a little helper so that we can do:
bc..{space}{newline}...(or
html,php,css,jsin place oftxp)That works great for highlighting code, even though we have no actual txp-specific syntax highlighter at this time.
[…]
Can we do something similar for regular Textpattern sites?
+1 from me, great idea.
Offline
Offline
Re: Code syntax highlighting of bc in txp:body with textile?
Glad you both agree :-) What can we do about? :~))
Two Three options spring to mind:
- Incorporate that directly into textile (is the
language-…class general enough not to be tied to prism.js alone?) - Add that facility as a textile plugin (is that a thing? I vaguely remember Netcarver mentioning that possibility)
- Make a txp plugin / shortcode-form out of Jukka’s preg_replace helper file.
TXP Builders – finely-crafted code, design and txp
Offline
Re: Code syntax highlighting of bc in txp:body with textile?
Well, I’ve had a go at making a simple plugin that simply adds a syntaxhint attribute to txp:body but it’s not working as it should it is working thanks to etc’s input. Thank you!
// TXP 4.7 tag attribute registration
if (class_exists('\Textpattern\Tag\Registry')) {
// Attribute mode
if(method_exists('\Textpattern\Tag\Registry', 'registerAttr'))
Txp::get('\Textpattern\Tag\Registry')->registerAttr('jcr_syntaxhint', 'syntaxhint');
}
function jcr_syntaxhint($atts, $thing = null)
{
// borrowed wholesale from @gocom's code for the textpattern forum
static $extra_code_language_identifiers = array(
'apacheconf',
'clike',
'coffeescript',
'css',
'git',
'haml',
'html',
'javascript',
'js',
'json',
'less',
'markdown',
'markup',
'nginx',
'perl',
'php',
'ruby',
'sass',
'scss',
'sql',
'stylus',
'textile',
'txp',
'yaml',
);
extract(lAtts(array(
'syntaxhint' => ''
), $atts, false));
if ($syntaxhint) {
$code_language_identifiers = implode('|', $extra_code_language_identifiers);
return preg_replace(
'@<pre><code>(?:\/\/|#|;)?(?:\s+)?('.$code_language_identifiers.')[\n\r]+@',
'<pre class="prism language-$1" data-language="$1"><code>',
$thing
);
} else {
return $thing;
}
}
TXP Builders – finely-crafted code, design and txp
Offline
Re: Code syntax highlighting of bc in txp:body with textile?
I have edited the code, please try. But you will see the result only in page source, because .prism class does nothing on the public side.
Offline
Re: Code syntax highlighting of bc in txp:body with textile?
Got it working by taking out the code identifier variable and making it a global (probably not great but…):
... code removed. please see post above ...
But it works now as here on the forum. This just adds the class. It doesn’t bind in prism.js.
TXP Builders – finely-crafted code, design and txp
Offline
Re: Code syntax highlighting of bc in txp:body with textile?
Oh thank you, I’ll try your variant too! Hold on…
TXP Builders – finely-crafted code, design and txp
Offline
Offline
Re: Code syntax highlighting of bc in txp:body with textile?
etc wrote #319912:
It’s the same, less a global.
Yours is better not only in that respect. Also in outputting the body when syntaxhint is off. But I needed to remove $codeLanguageIdentifiers as a parameter from the function (txp seems to interpret that as $thing as I discovered which was throwing off the preg_replace code).
Thank you again for helping!
TXP Builders – finely-crafted code, design and txp
Offline
Re: Code syntax highlighting of bc in txp:body with textile?
jakob wrote #319913:
(txp seems to interpret that as $thing as I discovered which was throwing off the preg_replace code).
Every tag is passed attributes as its first argument and $thing (even if named differently) as the second one. But I think your plugin should act on article save rather than as global attribute.
Offline
Re: Code syntax highlighting of bc in txp:body with textile?
etc wrote #319914:
Every tag is passed attributes as its first argument and
$thing(even if named differently) as the second one.
As I gathered :-)
But I think your plugin should act on article save rather than as global attribute.
That’s a much better idea, I agree: process it only once instead of on every page render. I’ll have to investigate that but probably won’t get to that today.
TXP Builders – finely-crafted code, design and txp
Offline
Offline
Re: Code syntax highlighting of bc in txp:body with textile?
Thanks again for the pointers. After a little experimentation I think I have it working as a simple plugin that, as you suggested, simply works on installation and activation without any public-side tags. One only has to go over old articles, add the code identifier to the article body and resave.
It hooks into article_saved & article_posted as follows:
if (txpinterface === 'admin') {
register_callback('jcr_syntaxhint', 'article_posted');
register_callback('jcr_syntaxhint', 'article_saved');
}
function jcr_syntaxhint($event, $step, $rs)
{
// if there's a value for current article ID, extract it into a variable, otherwise do nothing
if (!($row = safe_row('Body_html', 'textpattern', 'ID='.$rs['ID']))) return;
extract($row);
// borrowed wholesale from @gocom's code for the textpattern forum
// list of permitted code language identifiers (for prism)
static $extra_code_language_identifiers = array(
'apacheconf',
'clike',
'coffeescript',
'css',
'git',
'haml',
'html',
'javascript',
'js',
'json',
'less',
'markdown',
'markup',
'nginx',
'perl',
'php',
'ruby',
'sass',
'scss',
'sql',
'stylus',
'textile',
'txp',
'yaml',
);
$code_language_identifiers = implode('|', $extra_code_language_identifiers);
// search and replace bc..{space}{newline}code identifier{newline} to prism classes
$body_html_codehint = preg_replace(
'@<pre><code>(?:\/\/|#|;)?(?:\s+)?('.$code_language_identifiers.')[\n\r]+@',
'<pre class="prism language-$1" data-language="$1"><code>',
$Body_html
);
$body_html_codehint = doSlash($body_html_codehint);
// write back to the database
safe_update('textpattern', "Body_html = '$body_html_codehint'", 'ID = '.$rs['ID']);
}
Is this the right way of going about things? i.e. retrieve the field, manipulate it and write it back to the database, or can you hook into the data before it gets written to the database? I had no luck with $rs['Body_html'].
Also, I presume $rs['ID'] comes straight from the page and can’t be tampered with so doesn’t need assert_int() for safety.
Another question: how does article_posted and article_saved handle several functions? i.e. if I had other functions that also manipulated the content. Do they chain, or does the last/first plugin to fire displace the others? If they chain, how do I control the order?
TXP Builders – finely-crafted code, design and txp
Offline
Re: Code syntax highlighting of bc in txp:body with textile?
jakob wrote #319924:
Is this the right way of going about things? i.e. retrieve the field, manipulate it and write it back to the database, or can you hook into the data before it gets written to the database? I had no luck with
$rs['Body_html'].
Not necessarily a right one, but the only way atm, since $rs[Body_html] is not set. We should set it and also add a pre-save callback, imo.
Also, I presume
$rs['ID']comes straight from the page and can’t be tampered with so doesn’t needassert_int()for safety.
It’s ok for $rs['ID'], but you must escape $body_html_codehint before inserting it into db:
$body_html_codehint = doSlash($body_html_codehint);
Another question: how does
article_postedandarticle_savedhandle several functions? i.e. if I had other functions that also manipulated the content. Do they chain, or does the last/first plugin to fire displace the others? If they chain, how do I control the order?
They chain and are ordered by plugins load order (which you don’t really control because it can be altered by users).
Offline