Plugin interferes with inline parsing of mathematical formulae
-
Thank you for the plugin! Have been using it for years on several websites. But those did not use mathematics whereas a new site that I’m working on does (in the form of MathJax), so I discovered the following issue: If I use inline LaTeX code with MathJax, something like
“…where $\gamma$ is a parameter …”
then $\gamma$ turns into $\gam­ma$. Since \gamma has no wrapper apart from $ … $, I cannot use the class ignore feature unless I wrap it into a separate <span class=”something”></span> which is a pain most of the time. As the author of the plugin, perhaps, you would have other suggestions?
-
This topic was modified 7 years, 5 months ago by
Aleksei Tepljakov.
-
This topic was modified 7 years, 5 months ago by
Aleksei Tepljakov.
-
This topic was modified 7 years, 5 months ago by
-
Hi @pputzer, can we return to this discussion? Regrettably I didn’t have time to do anything with my website, and it’s not yet public, but that again there’s a chance the problem described above could be fixed before the official release.
Above you mentioned some new filter hooks. Is that a thing already or…?
@firelord Thanks for reminding me. Unfortunately, I’ve put this issue on the back burner a bit as well. (I’d need to replicate things in a test environment to be able to provide a solution. I’ll check out your plugin tonight.)
Hi @firelord, implementing this properly is harder than I thought, because the underlying PHP-Typography library would have to be changed. However, I’ve a “probably good enough” proof-of-concept here that works with the current version of the plugin.
Warning: This is not production-quality code. At the very least, the functions and the global will need to be prefixed (better yet, they should be refactored as a class).
add_filter( 'typo_custom_characters_node_fix', 'mask_latex_equations', 10, 4 ); add_filter( 'typo_custom_html_insertion_node_fix', 'reveal_latex_equations', 10, 4 ); $latex_equations = []; function mask_latex_equations( $nodedata, $textnode, $settings, $is_title ) { global $latex_equations; if ( preg_match_all( '/(?:\A|\s)(\$[^\$]+\$)(?:\s|\Z)/', $nodedata, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE ) ) { $mask = '__MASKED_LATEX__'; $mask_length = strlen( $mask ); $offset = 0; foreach( $matches as $match ) { $equation = $match[1][0]; $length = strlen( $equation ); $applied_offset = $offset + $match[1][1]; // Store equation. $latex_equations[ spl_object_id( $textnode ) ][] = $equation; // Replace equation with mask. $nodedata = substr_replace( $nodedata, $mask, $applied_offset, $length ); // Fix matched offset. $offset += $mask_legth - $length; } } return $nodedata; } function reveal_latex_equations( $nodedata, $textnode, $settings, $is_title ) { global $latex_equations; $key = spl_object_id( $textnode ); if ( ! empty( $latex_equations[ $key ] ) ) { $mask = '__MASKED_LATEX__'; $mask_length = strlen( $mask ); foreach ( $latex_equations[ $key ] as $equation ) { $pos = strpos( $nodedata, $mask ); if ( $pos !== false ) { $nodedata = substr_replace( $nodedata, $equation, $pos, $mask_length ); } } } return $nodedata; }Cool, thanks. I’ll give it a go as soon as I can.
@firelord Have you been able to check out the proof-of-concept?
Tried using the filter hooks, no go. Let me know how you applied this in your setup.
What’s more important, I realied just now that I apparently only targeted inline math $like=this$, but displayed equations also suffer from automatic insertion of like $$myequation=1$$ or \[this=0\].
This thing becomes more complicated by the minute.I put the code into into a MU plugin, but should work in functions.php as well. You can add error_log() calls to check if the filters are actually called.
Ok, here’s a solution. It only works for math enclosed in
\( math \)(inline) and\[ math \](displayed). Dollar signs are too much of a hassle to implement properly.function fixWpTypoMathCompat($content) { preg_match_all('/\\\\\[(?!\\\\\]).*?\\\\\]/s', $content, $result, PREG_PATTERN_ORDER); for ($i = 0; $i < count($result[0]); $i++) { for ($i = 0; $i < count($result[0]); $i++) { $now_eq = $result[0][$i]; $content = str_replace($now_eq, "<div class=\"lire-equation\">" . $result[0][$i] . "</div>", $content); } } preg_match_all('/\\\\\((?!\\\\\)).*?\\\\\)/s', $content, $result, PREG_PATTERN_ORDER); for ($i = 0; $i < count($result[0]); $i++) { $now_eq = $result[0][$i]; $content = str_replace($now_eq, "<span class=\"lire-equation\">" . $result[0][$i] . "</span>", $content); } return $content; }Added this as action with default priority to my plugin and then set up an option in wp-typography to ignore
lire-equationclass. Seems to be working. Will test further.Added support for “dollarsigned” inline math as well.
But now there’s also the issue with\begin{env} ... \end{env}. Will have to figure out a regex for handling that as well, hopefully for a generalenvand not forequation,align, etc. separately.I’m glad to hear you have been able to make this work, though I have doubts that generalizing this will really be feasible. It would amount to LaTeX parsing with regular expressions, and I’m not sure that’s technically possible.
I’m assuming you use
the_contenthook for your filter? My approach might have been overkill, but I used wp-Typography’s processing hooks to get access to the parsed HTML DOM, skipping all HTML elements and dealing only with plain text nodes. While my PoC was limited to the$something$notation, it should be adaptable to other markers.That’s right. I do it like this:
if (defined("LIRE_USE_WITH_WP_TYPOGRAPHY") && LIRE_USE_WITH_WP_TYPOGRAPHY === true) { add_action('the_content', array(&$wpLire, 'fixWpTypoMathCompat'), 1); }And I’ve also come up with updated code that also takes into account
\begin{env}...\end{env}. I guess for completeness I should also do$$...$$, but that can probably wait. For reference, this is what I have now:define("LIRE_USE_WITH_WP_TYPOGRAPHY", true); define("LIRE_FIX_DOLLAR_INLINE_MATH_WP_TYPOGRAPHY", true); define("LIRE_FIX_ENVS_WP_TYPOGRAPHY", true); function fixWpTypoMathCompat($content) { // Display equations \[ ... \] preg_match_all('/\\\\\[(?!\\\\\]).*?\\\\\]/s', $content, $result, PREG_PATTERN_ORDER); for ($i = 0; $i < count($result[0]); $i++) { for ($i = 0; $i < count($result[0]); $i++) { $now_eq = $result[0][$i]; $content = str_replace($now_eq, "<div class=\"lire-equation\">" . $result[0][$i] . "</div>", $content); } } // Environments such as \begin{equation} ... \end{equation} if (defined("LIRE_FIX_ENVS_WP_TYPOGRAPHY") && LIRE_FIX_ENVS_WP_TYPOGRAPHY === true) { preg_match_all('/\\\\begin{([A-Za-z]+\*?)}.+?\\\\end{\g{1}}/s', $content, $result, PREG_PATTERN_ORDER); for ($i = 0; $i < count($result[0]); $i++) { $now_eq = $result[0][$i]; $content = str_replace($now_eq, "<div class=\"lire-equation\">" . $result[0][$i] . "</div>", $content); } } // Inline equations \( ... \) preg_match_all('/\\\\\((?!\\\\\)).*?\\\\\)/s', $content, $result, PREG_PATTERN_ORDER); for ($i = 0; $i < count($result[0]); $i++) { $now_eq = $result[0][$i]; $content = str_replace($now_eq, "<span class=\"lire-equation\">" . $result[0][$i] . "</span>", $content); } // Inline equations $ ... $ if (defined("LIRE_FIX_DOLLAR_INLINE_MATH_WP_TYPOGRAPHY") && LIRE_FIX_DOLLAR_INLINE_MATH_WP_TYPOGRAPHY === true) { preg_match_all('/(?<!\\\\)\$((?:\\\\[^\n\r\x{2028}\x{2029}]|[^$])*)(?<!\\\\)\$/u', $content, $result, PREG_PATTERN_ORDER); for ($i = 0; $i < count($result[0]); $i++) { $now_eq = $result[0][$i]; $content = str_replace($now_eq, "<span class=\"lire-equation\">" . $result[0][$i] . "</span>", $content); } } return $content; }What would be really cool is if you could add
lire-equationas a default ignored class when you update the plugin. Or, maybe suggest some other class name that would be more generic, I’m open to suggestions as I can easily change the class name in my plugin.The
noTypoclass is ignored by default. If you want to have specialized class for styling the equations, just add both (class="lire-equation noTypo"). Or you can add custom ignored classes via the settings.Good point. Basically, I think we can finally consider this issue resolved 🙂
The topic ‘Plugin interferes with inline parsing of mathematical formulae’ is closed to new replies.