Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F20064764
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
16 KB
Subscribers
None
View Options
diff --git a/src/markup/engine/remarkup/markuprule/PhutilRemarkupBoldRule.php b/src/markup/engine/remarkup/markuprule/PhutilRemarkupBoldRule.php
index 1940ee8..4640df2 100644
--- a/src/markup/engine/remarkup/markuprule/PhutilRemarkupBoldRule.php
+++ b/src/markup/engine/remarkup/markuprule/PhutilRemarkupBoldRule.php
@@ -1,24 +1,24 @@
<?php
final class PhutilRemarkupBoldRule extends PhutilRemarkupRule {
public function getPriority() {
return 1000.0;
}
public function apply($text) {
if ($this->getEngine()->isTextMode()) {
return $text;
}
return $this->replaceHTML(
'@\\*\\*(.+?)\\*\\*@s',
array($this, 'applyCallback'),
$text);
}
- protected function applyCallback($matches) {
+ protected function applyCallback(array $matches) {
return hsprintf('<strong>%s</strong>', $matches[1]);
}
}
diff --git a/src/markup/engine/remarkup/markuprule/PhutilRemarkupDelRule.php b/src/markup/engine/remarkup/markuprule/PhutilRemarkupDelRule.php
index 623441c..82f23d2 100644
--- a/src/markup/engine/remarkup/markuprule/PhutilRemarkupDelRule.php
+++ b/src/markup/engine/remarkup/markuprule/PhutilRemarkupDelRule.php
@@ -1,24 +1,24 @@
<?php
final class PhutilRemarkupDelRule extends PhutilRemarkupRule {
public function getPriority() {
return 1000.0;
}
public function apply($text) {
if ($this->getEngine()->isTextMode()) {
return $text;
}
return $this->replaceHTML(
'@(?<!~)~~([^\s~].*?~*)~~@s',
array($this, 'applyCallback'),
$text);
}
- protected function applyCallback($matches) {
+ protected function applyCallback(array $matches) {
return hsprintf('<del>%s</del>', $matches[1]);
}
}
diff --git a/src/markup/engine/remarkup/markuprule/PhutilRemarkupDocumentLinkRule.php b/src/markup/engine/remarkup/markuprule/PhutilRemarkupDocumentLinkRule.php
index 818ff9e..ed85d72 100644
--- a/src/markup/engine/remarkup/markuprule/PhutilRemarkupDocumentLinkRule.php
+++ b/src/markup/engine/remarkup/markuprule/PhutilRemarkupDocumentLinkRule.php
@@ -1,133 +1,132 @@
<?php
final class PhutilRemarkupDocumentLinkRule extends PhutilRemarkupRule {
public function getPriority() {
return 150.0;
}
public function apply($text) {
-
// Handle mediawiki-style links: [[ href | name ]]
$text = preg_replace_callback(
'@\B\\[\\[([^|\\]]+)(?:\\|([^\\]]+))?\\]\\]\B@U',
array($this, 'markupDocumentLink'),
$text);
// Handle markdown-style links: [name](href)
$text = preg_replace_callback(
'@\B\\[([^\\]]+)\\]\\(([^\\)]+)\\)\B@U',
array($this, 'markupAlternateLink'),
$text);
return $text;
}
protected function renderHyperlink($link, $name) {
if ($this->getEngine()->isTextMode()) {
$text = $link;
if (strncmp($link, '/', 1) == 0 || strncmp($link, '#', 1) == 0) {
$base = $this->getEngine()->getConfig('uri.prefix');
if (strncmp($link, '/', 1) == 0) {
$base = rtrim($base, '/');
}
$text = $base.$text;
}
// If present, strip off "mailto:" or "tel:".
$text = preg_replace('/^(?:mailto|tel):/', '', $text);
if ($link == $name) {
return $text;
}
return $name.' <'.$text.'>';
} else if ($this->getEngine()->isHTMLMailMode()) {
if (strncmp($link, '/', 1) == 0 || strncmp($link, '#', 1) == 0) {
$base = $this->getEngine()->getConfig('uri.base');
$text = $link;
if (strncmp($link, '/', 1) == 0) {
$base = rtrim($base, '/');
}
$link = $base.$text;
}
}
// By default, we open links in a new window or tab. For anchors on the same
// page, just jump normally.
$target = '_blank';
if (strncmp($link, '#', 1) == 0) {
$target = null;
}
$name = preg_replace('/^(?:mailto|tel):/', '', $name);
if ($this->getEngine()->getState('toc')) {
return $name;
} else {
return phutil_tag(
'a',
array(
'href' => $link,
'class' => 'remarkup-link',
'target' => $target,
),
$name);
}
}
- public function markupAlternateLink($matches) {
+ public function markupAlternateLink(array $matches) {
$uri = trim($matches[2]);
// NOTE: We apply some special rules to avoid false positives here. The
// major concern is that we do not want to convert `x[0][1](y)` in a
// discussion about C source code into a link. To this end, we:
//
// - Don't match at word boundaries;
// - require the URI to contain a "/" character or "@" character; and
// - reject URIs which being with a quote character.
if ($uri[0] == '"' || $uri[0] == "'" || $uri[0] == '`') {
return $matches[0];
}
if (strpos($uri, '/') === false &&
strpos($uri, '@') === false &&
strncmp($uri, 'tel:', 4)) {
return $matches[0];
}
return $this->markupDocumentLink(
array(
$matches[0],
$matches[2],
$matches[1],
));
}
- public function markupDocumentLink($matches) {
+ public function markupDocumentLink(array $matches) {
$uri = trim($matches[1]);
$name = trim(idx($matches, 2, $uri));
// If whatever is being linked to begins with "/" or "#", or has "://",
// or is "mailto:" or "tel:", treat it as a URI instead of a wiki page.
$is_uri = preg_match('@(^/)|(://)|(^#)|(^(?:mailto|tel):)@', $uri);
if ($is_uri && strncmp('/', $uri, 1) && strncmp('#', $uri, 1)) {
$protocols = $this->getEngine()->getConfig(
'uri.allowed-protocols',
array());
$protocol = id(new PhutilURI($uri))->getProtocol();
if (!idx($protocols, $protocol)) {
// Don't treat this as a URI if it's not an allowed protocol.
$is_uri = false;
}
}
if (!$is_uri) {
return $matches[0];
}
return $this->getEngine()->storeText($this->renderHyperlink($uri, $name));
}
}
diff --git a/src/markup/engine/remarkup/markuprule/PhutilRemarkupHyperlinkRule.php b/src/markup/engine/remarkup/markuprule/PhutilRemarkupHyperlinkRule.php
index 2e3d87b..b9c51e5 100644
--- a/src/markup/engine/remarkup/markuprule/PhutilRemarkupHyperlinkRule.php
+++ b/src/markup/engine/remarkup/markuprule/PhutilRemarkupHyperlinkRule.php
@@ -1,99 +1,99 @@
<?php
final class PhutilRemarkupHyperlinkRule extends PhutilRemarkupRule {
public function getPriority() {
return 400.0;
}
public function apply($text) {
// Hyperlinks with explicit "<>" around them get linked exactly, without
// the "<>". Angle brackets are basically special and mean "this is a URL
// with weird characters". This is assumed to be reasonable because they
// don't appear in normal text or normal URLs.
$text = preg_replace_callback(
'@<(\w{3,}://[^\s'.PhutilRemarkupBlockStorage::MAGIC_BYTE.']+?)>@',
array($this, 'markupHyperlink'),
$text);
// Anything else we match "ungreedily", which means we'll look for
// stuff that's probably puncutation or otherwise not part of the URL and
// not link it. This lets someone write "QuicK! Go to
// http://www.example.com/!". We also apply some paren balancing rules.
// NOTE: We're explicitly avoiding capturing stored blocks, so text like
// `http://www.example.com/[[x | y]]` doesn't get aggressively captured.
$text = preg_replace_callback(
'@(\w{3,}://[^\s'.PhutilRemarkupBlockStorage::MAGIC_BYTE.']+)@',
array($this, 'markupHyperlinkUngreedy'),
$text);
return $text;
}
- protected function markupHyperlink($matches) {
+ protected function markupHyperlink(array $matches) {
$protocols = $this->getEngine()->getConfig(
'uri.allowed-protocols',
array());
$protocol = id(new PhutilURI($matches[1]))->getProtocol();
if (!idx($protocols, $protocol)) {
// If this URI doesn't use a whitelisted protocol, don't link it. This
// is primarily intended to prevent javascript:// silliness.
return $this->getEngine()->storeText($matches[1]);
}
return $this->storeRenderedHyperlink($matches[1]);
}
protected function storeRenderedHyperlink($link) {
return $this->getEngine()->storeText($this->renderHyperlink($link));
}
protected function renderHyperlink($link) {
if ($this->getEngine()->isTextMode()) {
return $link;
}
if ($this->getEngine()->getState('toc')) {
return $link;
} else {
return phutil_tag(
'a',
array(
'href' => $link,
'class' => 'remarkup-link',
'target' => '_blank',
),
$link);
}
}
protected function markupHyperlinkUngreedy($matches) {
$match = $matches[1];
$tail = null;
$trailing = null;
if (preg_match('/[;,.:!?]+$/', $match, $trailing)) {
$tail = $trailing[0];
$match = substr($match, 0, -strlen($tail));
}
// If there's a closing paren at the end but no balancing open paren in
// the URL, don't link the close paren. This is an attempt to gracefully
// handle the two common paren cases, Wikipedia links and English language
// parentheticals, e.g.:
//
// http://en.wikipedia.org/wiki/Noun_(disambiguation)
// (see also http://www.example.com)
//
// We could apply a craftier heuristic here which tries to actually balance
// the parens, but this is probably sufficient.
if (preg_match('/\\)$/', $match) && !preg_match('/\\(/', $match)) {
$tail = ')'.$tail;
$match = substr($match, 0, -1);
}
return hsprintf('%s%s', $this->markupHyperlink(array(null, $match)), $tail);
}
}
diff --git a/src/markup/engine/remarkup/markuprule/PhutilRemarkupItalicRule.php b/src/markup/engine/remarkup/markuprule/PhutilRemarkupItalicRule.php
index f05410c..9eefe2a 100644
--- a/src/markup/engine/remarkup/markuprule/PhutilRemarkupItalicRule.php
+++ b/src/markup/engine/remarkup/markuprule/PhutilRemarkupItalicRule.php
@@ -1,24 +1,24 @@
<?php
final class PhutilRemarkupItalicRule extends PhutilRemarkupRule {
public function getPriority() {
return 1000.0;
}
public function apply($text) {
if ($this->getEngine()->isTextMode()) {
return $text;
}
return $this->replaceHTML(
'@(?<!:)//(.+?)//@s',
array($this, 'applyCallback'),
$text);
}
- protected function applyCallback($matches) {
+ protected function applyCallback(array $matches) {
return hsprintf('<em>%s</em>', $matches[1]);
}
}
diff --git a/src/markup/engine/remarkup/markuprule/PhutilRemarkupMonospaceRule.php b/src/markup/engine/remarkup/markuprule/PhutilRemarkupMonospaceRule.php
index e63415a..cd5ab8a 100644
--- a/src/markup/engine/remarkup/markuprule/PhutilRemarkupMonospaceRule.php
+++ b/src/markup/engine/remarkup/markuprule/PhutilRemarkupMonospaceRule.php
@@ -1,49 +1,49 @@
<?php
final class PhutilRemarkupMonospaceRule extends PhutilRemarkupRule {
public function getPriority() {
return 100.0;
}
public function apply($text) {
// NOTE: We don't require a trailing non-boundary on the backtick syntax,
// to permit the use case of naming and pluralizing a class, like
// "Load all the `PhutilArray`s and then iterate over them." In theory, the
// required \B on the leading backtick should protect us from most
// collateral damage.
return preg_replace_callback(
'@##([\s\S]+?)##|\B`(.+?)`@',
array($this, 'markupMonospacedText'),
$text);
}
- protected function markupMonospacedText($matches) {
+ protected function markupMonospacedText(array $matches) {
if ($this->getEngine()->isTextMode()) {
$result = $matches[0];
} else
if ($this->getEngine()->isHTMLMailMode()) {
$match = isset($matches[2]) ? $matches[2] : $matches[1];
$result = phutil_tag(
'tt',
array(
'style' => 'background: #ebebeb; font-size: 13px;',
),
$match);
} else {
$match = isset($matches[2]) ? $matches[2] : $matches[1];
$result = phutil_tag(
'tt',
array(
'class' => 'remarkup-monospaced',
),
$match);
}
return $this->getEngine()->storeText($result);
}
}
diff --git a/src/markup/engine/remarkup/markuprule/PhutilRemarkupRule.php b/src/markup/engine/remarkup/markuprule/PhutilRemarkupRule.php
index 3ef5c87..292bfe6 100644
--- a/src/markup/engine/remarkup/markuprule/PhutilRemarkupRule.php
+++ b/src/markup/engine/remarkup/markuprule/PhutilRemarkupRule.php
@@ -1,112 +1,112 @@
<?php
/**
* @stable
*/
abstract class PhutilRemarkupRule {
private $engine;
private $replaceCallback;
public function setEngine(PhutilRemarkupEngine $engine) {
$this->engine = $engine;
return $this;
}
public function getEngine() {
return $this->engine;
}
public function getPriority() {
return 500.0;
}
abstract public function apply($text);
public function getPostprocessKey() {
return spl_object_hash($this);
}
public function didMarkupText() {
return;
}
protected function replaceHTML($pattern, $callback, $text) {
$this->replaceCallback = $callback;
return phutil_safe_html(preg_replace_callback(
$pattern,
array($this, 'replaceHTMLCallback'),
phutil_escape_html($text)));
}
- private function replaceHTMLCallback($match) {
+ private function replaceHTMLCallback(array $match) {
return phutil_escape_html(call_user_func(
$this->replaceCallback,
array_map('phutil_safe_html', $match)));
}
/**
* Safely generate a tag.
*
* In Remarkup contexts, it's not safe to use arbitrary text in tag
* attributes: even though it will be escaped, it may contain replacement
* tokens which are then replaced with markup.
*
* This method acts as @{function:phutil_tag}, but checks attributes before
* using them.
*
* @param string Tag name.
* @param dict<string, wild> Tag attributes.
* @param wild Tag content.
* @return PhutilSafeHTML Tag object.
*/
protected function newTag($name, array $attrs, $content = null) {
foreach ($attrs as $key => $attr) {
if ($attr !== null) {
$attrs[$key] = $this->assertFlatText($attr);
}
}
return phutil_tag($name, $attrs, $content);
}
/**
* Assert that a text token is flat (it contains no replacement tokens).
*
* Because tokens can be replaced with markup, it is dangerous to use
* arbitrary input text in tag attributes. Normally, rule precedence should
* prevent this. Asserting that text is flat before using it as an attribute
* provides an extra layer of security.
*
* Normally, you can call @{method:newTag} rather than calling this method
* directly. @{method:newTag} will check attributes for you.
*
* @param wild Ostensibly flat text.
* @return string Flat text.
*/
protected function assertFlatText($text) {
$text = (string)hsprintf('%s', phutil_safe_html($text));
$rich = (strpos($text, PhutilRemarkupBlockStorage::MAGIC_BYTE) !== false);
if ($rich) {
throw new Exception(
pht(
'Remarkup rule precedence is dangerous: rendering text with tokens '.
'as flat text!'));
}
return $text;
}
/**
* Check whether text is flat (contains no replacement tokens) or not.
*
* @param wild Ostensibly flat text.
* @return bool True if the text is flat.
*/
protected function isFlatText($text) {
$text = (string)hsprintf('%s', phutil_safe_html($text));
return (strpos($text, PhutilRemarkupBlockStorage::MAGIC_BYTE) === false);
}
}
diff --git a/src/markup/engine/remarkup/markuprule/PhutilRemarkupUnderlineRule.php b/src/markup/engine/remarkup/markuprule/PhutilRemarkupUnderlineRule.php
index 0224fb7..1f15728 100644
--- a/src/markup/engine/remarkup/markuprule/PhutilRemarkupUnderlineRule.php
+++ b/src/markup/engine/remarkup/markuprule/PhutilRemarkupUnderlineRule.php
@@ -1,24 +1,24 @@
<?php
final class PhutilRemarkupUnderlineRule extends PhutilRemarkupRule {
public function getPriority() {
return 1000.0;
}
public function apply($text) {
if ($this->getEngine()->isTextMode()) {
return $text;
}
return $this->replaceHTML(
'@(?<!_|/)__([^\s_/].*?_*)__(?!/|\.\S)@s',
array($this, 'applyCallback'),
$text);
}
- protected function applyCallback($matches) {
+ protected function applyCallback(array $matches) {
return hsprintf('<u>%s</u>', $matches[1]);
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Feb 23, 7:32 PM (1 d, 45 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
8c/1a/5028f98aba23caa2c5fa4481f935
Attached To
rPHUTIL libphutil
Event Timeline
Log In to Comment