我正在尝试实现一个简单的函数,给定文本输入,当检测到链接时返回xhp_a
修改的文本,在段落xhp_p
内。
考虑这个类
class Urlifier {
protected static $reg_exUrl = "/(http|https|ftp|ftps)://[a-zA-Z0-9-.]+.[a-zA-Z]{2,3}(/S*)?/";
public static function convertParagraphWithLink(?string $input):xhp_p{
if (!$input)
return <p></p>;
else
{
if (preg_match(self::$reg_exUrl,$input,$url_match)) //match found
{
return <p>{preg_replace($reg_exUrl, '<a href="'.$url_match[0].'>'.$url_match[0].'</a>', $input)}<p>;
}else{//no link inside
<p>{$input}</p>
}
}
}
这里的问题是xhp
转义html
,链接没有按照预期显示。我想这是因为a没有像预期的那样创建dom层次结构(例如appendChild
方法),因此regex
替换的所有内容都是字符串。
所以我对这个问题的另一种方法是使用preg_match_callback
和一个回调函数,它将创建xhp_a
并添加到xhp_p
下的层次结构,但这也不起作用。
我错了吗?如果没有,会有任何安全风险/更大的开销,只是寻找和替换加载html在客户端而不是服务器?
感谢您的宝贵时间!由于XHP维护映射到DOM的对象层次结构,因此简单地替换字符串的部分不会创建任何新对象。要操作XHP对象,应该使用相应的方法,例如appendChild
。
下面是一个示例,说明如何通过XHP操作实现所需的内容。
class Urlifier {
public static function convertParagraphWithLink(
?string $input,
): xhp_p {
$url_pattern = re"/(http|https|ftp|ftps)://[a-zA-Z0-9-.]+.[a-zA-Z]{2,3}(/S*)?/";
if (HHLibStris_empty($input)) {
return <p/>;
}
$input = $input as nonnull;
// Extract links
$link_matches = HHLibRegexevery_match($input, $url_pattern);
$links = HHLibVecmap($link_matches, $m ==> $m[0]);
$a_elements = HHLibVecmap($links, $link ==> <a href={$link}>{$link}</a>);
// Extract all pieces between matches
$texts = HHLibRegexsplit($input, $url_pattern);
$p_elements = HHLibVecmap($texts, $text ==> <p>{$text}</p>);
// Merge texts and links
$pairs = HHLibVeczip($p_elements, $a_elements);
$elements = HHLibVecflatten($pairs);
// Because there's one more p element than a element, append last p
$elements[] = HHLibClast($p_elements);
$result = <p/>;
$result->appendChild($elements);
return $result;
}