1
0
mirror of https://github.com/flarum/core.git synced 2025-08-11 19:04:29 +02:00

infrastructure: fix broken translation of strings with html tags (vnodes) passed into them

Under the old system, we would set the "childen" property of the vnode in the translation to an array containing the text between the tag as a raw string. Mithril 2 expects everything to be a vnode, and as such, errors when processing this raw string. This commit runs that "children" array of raw strings (and possibly other vnodes) through m.fragment to convert everything to vnodes.
This commit is contained in:
Alexander Skvortsov
2020-08-07 14:57:11 -04:00
committed by Franz Liedke
parent 5b3914535d
commit e28ba4acff

View File

@@ -1,4 +1,3 @@
import User from './models/User';
import username from './helpers/username'; import username from './helpers/username';
import extract from './utils/extract'; import extract from './utils/extract';
@@ -71,18 +70,34 @@ export default class Translator {
const match = part.match(new RegExp('{([a-z0-9_]+)}|<(/?)([a-z0-9_]+)>', 'i')); const match = part.match(new RegExp('{([a-z0-9_]+)}|<(/?)([a-z0-9_]+)>', 'i'));
if (match) { if (match) {
// Either an opening or closing tag.
if (match[1]) { if (match[1]) {
open[0].push(input[match[1]]); open[0].push(input[match[1]]);
} else if (match[3]) { } else if (match[3]) {
if (match[2]) { if (match[2]) {
// Closing tag. We start by removing all raw children (generally in the form of strings) from the temporary
// holding array, then run them through m.fragment to convert them to vnodes. Usually this will just give us a
// text vnode, but using m.fragment as opposed to an explicit conversion should be more flexible. This is necessary because
// otherwise, our generated vnode will have raw strings as its children, and mithril expects vnodes.
// Finally, we add the now-processed vnodes back onto the holding array (which is the same object in memory as the
// children array of the vnode we are currently processing), and remove the reference to the holding array so that
// further text will be added to the full set of returned elements.
const rawChildren = open[0].splice(0, open[0].length);
open[0].push(...m.fragment(rawChildren).children);
open.shift(); open.shift();
} else { } else {
// If a vnode with a matching tag was provided in the translator input, we use that. Otherwise, we create a new vnode
// with this tag, and an empty children array (since we're expecting to insert children, as that's the point of having this in translator)
let tag = input[match[3]] || { tag: match[3], children: [] }; let tag = input[match[3]] || { tag: match[3], children: [] };
open[0].push(tag); open[0].push(tag);
// Insert the tag's children array as the first element of open, so that text in between the opening
// and closing tags will be added to the tag's children, not to the full set of returned elements.
open.unshift(tag.children || tag); open.unshift(tag.children || tag);
} }
} }
} else { } else {
// Not an html tag, we add it to open[0], which is either the full set of returned elements (vnodes and text),
// or if an html tag is currently being processed, the children attribute of that html tag's vnode.
open[0].push(part); open[0].push(part);
} }
}); });