我正在使用Parsedown将 HTML 从数据库解析到我的站点。使用 Parsedown,您无法真正添加target="_blank"
到链接中。
所以我想做的是添加target="_blank"
到外部链接。我在 Parsedown.php 中找到了这个函数:
protected function inlineLink($Excerpt)
{
$Element = array(
'name' => 'a',
'handler' => 'line',
'text' => null,
'attributes' => array(
'href' => null,
'title' => null,
),
);
$extent = 0;
$remainder = $Excerpt['text'];
if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches))
{
$Element['text'] = $matches[1];
$extent += strlen($matches[0]);
$remainder = substr($remainder, $extent);
}
else
{
return;
}
if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?\s*[)]/', $remainder, $matches))
{
$Element['attributes']['href'] = $matches[1];
if (isset($matches[2]))
{
$Element['attributes']['title'] = substr($matches[2], 1, - 1);
}
$extent += strlen($matches[0]);
}
else
{
if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches))
{
$definition = strlen($matches[1]) ? $matches[1] : $Element['text'];
$definition = strtolower($definition);
$extent += strlen($matches[0]);
}
else
{
$definition = strtolower($Element['text']);
}
if ( ! isset($this->DefinitionData['Reference'][$definition]))
{
return;
}
$Definition = $this->DefinitionData['Reference'][$definition];
$Element['attributes']['href'] = $Definition['url'];
$Element['attributes']['title'] = $Definition['title'];
}
$Element['attributes']['href'] = str_replace(array('&', '<'), array('&', '<'), $Element['attributes']['href']);
return array(
'extent' => $extent,
'element' => $Element,
);
}
Run Code Online (Sandbox Code Playgroud)
现在,我尝试过的是这个(添加了我更改的评论):
protected function inlineLink($Excerpt)
{
$Element = array(
'name' => 'a',
'handler' => 'line',
'text' => null,
'attributes' => array(
'href' => null,
'target' => null, // added this
'title' => null,
),
);
$extent = 0;
$remainder = $Excerpt['text'];
if (preg_match('/\[((?:[^][]++|(?R))*+)\]/', $remainder, $matches))
{
$Element['text'] = $matches[1];
$extent += strlen($matches[0]);
$remainder = substr($remainder, $extent);
}
else
{
return;
}
if (preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?\s*[)]/', $remainder, $matches))
{
$Element['attributes']['href'] = $matches[1];
if (isset($matches[2]))
{
$Element['attributes']['title'] = substr($matches[2], 1, - 1);
}
$extent += strlen($matches[0]);
}
else
{
if (preg_match('/^\s*\[(.*?)\]/', $remainder, $matches))
{
$definition = strlen($matches[1]) ? $matches[1] : $Element['text'];
$definition = strtolower($definition);
$extent += strlen($matches[0]);
}
else
{
$definition = strtolower($Element['text']);
}
if ( ! isset($this->DefinitionData['Reference'][$definition]))
{
return;
}
$Definition = $this->DefinitionData['Reference'][$definition];
$Element['attributes']['href'] = $Definition['url'];
if (strpos($Definition['url'], 'example.com') !== false) { // added this aswell, checking if its our own URL
$Element['attributes']['target'] = '_blank';
}
$Element['attributes']['title'] = $Definition['title'];
}
$Element['attributes']['href'] = str_replace(array('&', '<'), array('&', '<'), $Element['attributes']['href']);
return array(
'extent' => $extent,
'element' => $Element,
);
}
Run Code Online (Sandbox Code Playgroud)
有什么建议可以实现这一点吗?
今天遇到这个问题。我希望来自不同主机的所有链接自动在新目标中打开。不幸的是,接受的答案建议编辑 Parsedown 类文件,在我看来这是一个坏主意。
我创建了一个新的 PHP 类来扩展Parsedown
,并为该element
方法创建了一个重写。这是整个班级:
class ParsedownExtended extends Parsedown
{
protected function element(array $Element)
{
if ($this->safeMode) {
$Element = $this->sanitiseElement($Element);
}
$markup = '<' . $Element['name'];
if (isset($Element['name']) && $Element['name'] == 'a') {
$server_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : null;
$href_host = isset($Element['attributes']['href']) ? parse_url($Element['attributes']['href'], PHP_URL_HOST) : null;
if ($server_host != $href_host) {
$Element['attributes']['target'] = '_blank';
}
}
if (isset($Element['attributes'])) {
foreach ($Element['attributes'] as $name => $value) {
if ($value === null) {
continue;
}
$markup .= ' ' . $name . '="' . self::escape($value) . '"';
}
}
if (isset($Element['text'])) {
$markup .= '>';
if (!isset($Element['nonNestables'])) {
$Element['nonNestables'] = array();
}
if (isset($Element['handler'])) {
$markup .= $this->{$Element['handler']}($Element['text'], $Element['nonNestables']);
}
else {
$markup .= self::escape($Element['text'], true);
}
$markup .= '</' . $Element['name'] . '>';
}
else {
$markup .= ' />';
}
return $markup;
}
}
Run Code Online (Sandbox Code Playgroud)
这就是奇迹发生的地方:
if (isset($Element['name']) && $Element['name'] == 'a') {
$server_host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : null;
$href_host = isset($Element['attributes']['href']) ? parse_url($Element['attributes']['href'], PHP_URL_HOST) : null;
if ($server_host != $href_host) {
$Element['attributes']['target'] = '_blank';
}
}
Run Code Online (Sandbox Code Playgroud)
现在我只是在解析内容时使用ParsedownExtended
而不是,例如:Parsedown
$parsedown = new ParsedownExtended();
return $parsedown->text($this->body);
Run Code Online (Sandbox Code Playgroud)
希望这对某人有帮助。
GitHub 上已经存在此类问题。请看这个评论。
当检测到链接为外部链接时,我的扩展程序可以自动为链接设置 rel="nofollow" 和 target="_blank" 属性。您还可以通过属性块手动设置这些属性:
Run Code Online (Sandbox Code Playgroud)[text](http://example.com) {rel="nofollow" target="_blank"}
Run Code Online (Sandbox Code Playgroud)// custom external link attributes $parser->links_external_attr = array( 'rel' => 'nofollow', 'target' => '_blank' );
如果您想在不使用 parsedown-extra-plugin 扩展的情况下对 Parsedown 类进行更改,您可以执行以下操作:
1)在第一行\Parsedown::element
之后的方法中添加此行 $markup = '<'.$Element['name'];
$Element = $this->additionalProcessElement($Element);
2)向 Parsedown 类添加新方法:
protected function additionalProcessElement($Element) { }
Run Code Online (Sandbox Code Playgroud)
3)扩展Parsedown类并将其保存为MyParsedown.php文件:
<?php
namespace myapps;
require_once __DIR__.'/Parsedown.php';
/**
* Class MyParsedown
* @package app
*/
class MyParsedown extends \Parsedown
{
/**
* @param array $Element
* @return array
*/
protected function additionalProcessElement($Element)
{
if ($Element['name'] == 'a' && $this->isExternalUrl($Element['attributes']['href'])) {
$Element['attributes']['target'] = '_blank';
}
return $Element;
}
/**
* Modification of the funciton from answer to the question "How To Check Whether A URL Is External URL or Internal URL With PHP?"
* @param string $url
* @param null $internalHostName
* @see /sf/answers/1607545131/
* @return bool
*/
protected function isExternalUrl($url, $internalHostName = null) {
$components = parse_url($url);
$internalHostName = ($internalHostName == null) ? $_SERVER['HTTP_HOST'] : $internalHostName;
// we will treat url like '/relative.php' as relative
if (empty($components['host'])) {
return false;
}
// url host looks exactly like the local host
if (strcasecmp($components['host'], $internalHostName) === 0) {
return false;
}
$isNotSubdomain = strrpos(strtolower($components['host']), '.'.$internalHostName) !== strlen($components['host']) - strlen('.'.$internalHostName);
return $isNotSubdomain;
}
}
Run Code Online (Sandbox Code Playgroud)
4)创建test.php
文件并运行:
require_once __DIR__.'/MyParsedown.php';
$parsedown = new \myapps\MyParsedown();
$text = 'External link to [example.com](http://example.com/abc)';
echo $parsedown->text($text);
Run Code Online (Sandbox Code Playgroud)
此 HTML 代码将显示在浏览器页面上(当然,如果您的主机不是 example.com):
<p>External link to <a href="http://example.com/abc" target="_blank">example.com</a></p>
归档时间: |
|
查看次数: |
1569 次 |
最近记录: |