mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-10 08:52:39 +01:00
Add an "{anchor #xyz}" rule to Remarkup
Summary: Ref T13410. Fixes T4280. Allows you to put a named anchor into a document explicitly. Test Plan: Used `{anchor ...}` in Remarkup, used location bar to jump to anchors. Maniphest Tasks: T13410, T4280 Differential Revision: https://secure.phabricator.com/D20825
This commit is contained in:
parent
bff72ce3b5
commit
b1d4d5c00c
5 changed files with 85 additions and 6 deletions
|
@ -5598,6 +5598,7 @@ phutil_register_library_map(array(
|
|||
'PhutilQsprintfInterface' => 'infrastructure/storage/xsprintf/PhutilQsprintfInterface.php',
|
||||
'PhutilQueryString' => 'infrastructure/storage/xsprintf/PhutilQueryString.php',
|
||||
'PhutilRealNameContextFreeGrammar' => 'infrastructure/lipsum/PhutilRealNameContextFreeGrammar.php',
|
||||
'PhutilRemarkupAnchorRule' => 'infrastructure/markup/markuprule/PhutilRemarkupAnchorRule.php',
|
||||
'PhutilRemarkupBlockInterpreter' => 'infrastructure/markup/blockrule/PhutilRemarkupBlockInterpreter.php',
|
||||
'PhutilRemarkupBlockRule' => 'infrastructure/markup/blockrule/PhutilRemarkupBlockRule.php',
|
||||
'PhutilRemarkupBlockStorage' => 'infrastructure/markup/PhutilRemarkupBlockStorage.php',
|
||||
|
@ -12391,6 +12392,7 @@ phutil_register_library_map(array(
|
|||
'PhutilPhabricatorAuthAdapter' => 'PhutilOAuthAuthAdapter',
|
||||
'PhutilQueryString' => 'Phobject',
|
||||
'PhutilRealNameContextFreeGrammar' => 'PhutilContextFreeGrammar',
|
||||
'PhutilRemarkupAnchorRule' => 'PhutilRemarkupRule',
|
||||
'PhutilRemarkupBlockInterpreter' => 'Phobject',
|
||||
'PhutilRemarkupBlockRule' => 'Phobject',
|
||||
'PhutilRemarkupBlockStorage' => 'Phobject',
|
||||
|
|
|
@ -715,6 +715,18 @@ Press {key down down-right right LP} to activate the hadoken technique.
|
|||
> Press {key down down-right right LP} to activate the hadoken technique.
|
||||
|
||||
|
||||
Anchors
|
||||
========
|
||||
|
||||
You can use `{anchor #xyz}` to create a document anchor and later link to
|
||||
it directly with `#xyz` in the URI.
|
||||
|
||||
Headers also automatically create named anchors.
|
||||
|
||||
If you navigate to `#xyz` in your browser location bar, the page will scroll
|
||||
to the first anchor with "xyz" as a prefix of the anchor name.
|
||||
|
||||
|
||||
= Fullscreen Mode =
|
||||
|
||||
Remarkup editors provide a fullscreen composition mode. This can make it easier
|
||||
|
|
|
@ -539,6 +539,7 @@ final class PhabricatorMarkupEngine extends Phobject {
|
|||
$rules[] = new PhutilRemarkupDelRule();
|
||||
$rules[] = new PhutilRemarkupUnderlineRule();
|
||||
$rules[] = new PhutilRemarkupHighlightRule();
|
||||
$rules[] = new PhutilRemarkupAnchorRule();
|
||||
|
||||
foreach (self::loadCustomInlineRules() as $rule) {
|
||||
$rules[] = clone $rule;
|
||||
|
|
|
@ -162,12 +162,7 @@ final class PhutilRemarkupHeaderBlockRule extends PhutilRemarkupBlockRule {
|
|||
|
||||
public static function getAnchorNameFromHeaderText($text) {
|
||||
$anchor = phutil_utf8_strtolower($text);
|
||||
|
||||
// Replace all latin characters which are not "a-z" or "0-9" with "-".
|
||||
// Preserve other characters, since non-latin letters and emoji work
|
||||
// fine in anchors.
|
||||
$anchor = preg_replace('/[\x00-\x2F\x3A-\x60\x7B-\x7F]+/', '-', $anchor);
|
||||
$anchor = trim($anchor, '-');
|
||||
$anchor = PhutilRemarkupAnchorRule::normalizeAnchor($anchor);
|
||||
|
||||
// Truncate the fragment to something reasonable.
|
||||
$anchor = id(new PhutilUTF8StringTruncator())
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
final class PhutilRemarkupAnchorRule extends PhutilRemarkupRule {
|
||||
|
||||
public function getPriority() {
|
||||
return 200.0;
|
||||
}
|
||||
|
||||
public function apply($text) {
|
||||
return preg_replace_callback(
|
||||
'/{anchor\s+#([^\s}]+)}/s',
|
||||
array($this, 'markupAnchor'),
|
||||
$text);
|
||||
}
|
||||
|
||||
protected function markupAnchor(array $matches) {
|
||||
$engine = $this->getEngine();
|
||||
|
||||
if ($engine->isTextMode()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($engine->isHTMLMailMode()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($engine->isAnchorMode()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!$this->isFlatText($matches[0])) {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
if (!self::isValidAnchorName($matches[1])) {
|
||||
return $matches[0];
|
||||
}
|
||||
|
||||
$tag_view = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'name' => $matches[1],
|
||||
),
|
||||
'');
|
||||
|
||||
return $this->getEngine()->storeText($tag_view);
|
||||
}
|
||||
|
||||
public static function isValidAnchorName($anchor_name) {
|
||||
$normal_anchor = self::normalizeAnchor($anchor_name);
|
||||
|
||||
if ($normal_anchor === $anchor_name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function normalizeAnchor($anchor) {
|
||||
// Replace all latin characters which are not "a-z" or "0-9" with "-".
|
||||
// Preserve other characters, since non-latin letters and emoji work
|
||||
// fine in anchors.
|
||||
$anchor = preg_replace('/[\x00-\x2F\x3A-\x60\x7B-\x7F]+/', '-', $anchor);
|
||||
$anchor = trim($anchor, '-');
|
||||
|
||||
return $anchor;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue