Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14088492
D20825.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
5 KB
Referenced Files
None
Subscribers
None
D20825.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -5598,6 +5598,7 @@
'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 @@
'PhutilPhabricatorAuthAdapter' => 'PhutilOAuthAuthAdapter',
'PhutilQueryString' => 'Phobject',
'PhutilRealNameContextFreeGrammar' => 'PhutilContextFreeGrammar',
+ 'PhutilRemarkupAnchorRule' => 'PhutilRemarkupRule',
'PhutilRemarkupBlockInterpreter' => 'Phobject',
'PhutilRemarkupBlockRule' => 'Phobject',
'PhutilRemarkupBlockStorage' => 'Phobject',
diff --git a/src/docs/user/userguide/remarkup.diviner b/src/docs/user/userguide/remarkup.diviner
--- a/src/docs/user/userguide/remarkup.diviner
+++ b/src/docs/user/userguide/remarkup.diviner
@@ -715,6 +715,18 @@
> 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
diff --git a/src/infrastructure/markup/PhabricatorMarkupEngine.php b/src/infrastructure/markup/PhabricatorMarkupEngine.php
--- a/src/infrastructure/markup/PhabricatorMarkupEngine.php
+++ b/src/infrastructure/markup/PhabricatorMarkupEngine.php
@@ -539,6 +539,7 @@
$rules[] = new PhutilRemarkupDelRule();
$rules[] = new PhutilRemarkupUnderlineRule();
$rules[] = new PhutilRemarkupHighlightRule();
+ $rules[] = new PhutilRemarkupAnchorRule();
foreach (self::loadCustomInlineRules() as $rule) {
$rules[] = clone $rule;
diff --git a/src/infrastructure/markup/blockrule/PhutilRemarkupHeaderBlockRule.php b/src/infrastructure/markup/blockrule/PhutilRemarkupHeaderBlockRule.php
--- a/src/infrastructure/markup/blockrule/PhutilRemarkupHeaderBlockRule.php
+++ b/src/infrastructure/markup/blockrule/PhutilRemarkupHeaderBlockRule.php
@@ -162,12 +162,7 @@
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())
diff --git a/src/infrastructure/markup/markuprule/PhutilRemarkupAnchorRule.php b/src/infrastructure/markup/markuprule/PhutilRemarkupAnchorRule.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/markup/markuprule/PhutilRemarkupAnchorRule.php
@@ -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;
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Nov 25, 4:04 AM (13 h, 17 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6784881
Default Alt Text
D20825.diff (5 KB)
Attached To
Mode
D20825: Add an "{anchor #xyz}" rule to Remarkup
Attached
Detach File
Event Timeline
Log In to Comment