Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15475106
D10753.id25809.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
D10753.id25809.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
@@ -2823,6 +2823,7 @@
'ProjectCreateProjectsCapability' => 'applications/project/capability/ProjectCreateProjectsCapability.php',
'ProjectQueryConduitAPIMethod' => 'applications/project/conduit/ProjectQueryConduitAPIMethod.php',
'ProjectRemarkupRule' => 'applications/project/remarkup/ProjectRemarkupRule.php',
+ 'ProjectRemarkupRuleTestCase' => 'applications/project/remarkup/__tests__/ProjectRemarkupRuleTestCase.php',
'QueryFormattingTestCase' => 'infrastructure/storage/__tests__/QueryFormattingTestCase.php',
'ReleephAuthorFieldSpecification' => 'applications/releeph/field/specification/ReleephAuthorFieldSpecification.php',
'ReleephBranch' => 'applications/releeph/storage/ReleephBranch.php',
@@ -6015,6 +6016,7 @@
'ProjectCreateProjectsCapability' => 'PhabricatorPolicyCapability',
'ProjectQueryConduitAPIMethod' => 'ProjectConduitAPIMethod',
'ProjectRemarkupRule' => 'PhabricatorObjectRemarkupRule',
+ 'ProjectRemarkupRuleTestCase' => 'PhabricatorTestCase',
'QueryFormattingTestCase' => 'PhabricatorTestCase',
'ReleephAuthorFieldSpecification' => 'ReleephFieldSpecification',
'ReleephBranch' => array(
diff --git a/src/applications/project/remarkup/ProjectRemarkupRule.php b/src/applications/project/remarkup/ProjectRemarkupRule.php
--- a/src/applications/project/remarkup/ProjectRemarkupRule.php
+++ b/src/applications/project/remarkup/ProjectRemarkupRule.php
@@ -30,7 +30,7 @@
// In other contexts, the PhabricatorProjectProjectPHIDType pattern is
// controlling and these names should parse correctly.
- return '[^\s.!,:;{}#]*[^\s\d!,:;{}#]+(?:[^\s.!,:;{}#][^\s!,:;{}#]*)*';
+ return '[^\s.\d!,:;{}#]+(?:[^\s!,:;{}#][^\s.!,:;{}#]+)*';
}
protected function loadObjects(array $ids) {
diff --git a/src/applications/project/remarkup/__tests__/ProjectRemarkupRuleTestCase.php b/src/applications/project/remarkup/__tests__/ProjectRemarkupRuleTestCase.php
new file mode 100644
--- /dev/null
+++ b/src/applications/project/remarkup/__tests__/ProjectRemarkupRuleTestCase.php
@@ -0,0 +1,57 @@
+<?php
+
+final class ProjectRemarkupRuleTestCase extends PhabricatorTestCase {
+
+ public function testProjectObjectRemarkup() {
+ $cases = array(
+ 'I like #ducks.' => array(
+ 'embed' => array(),
+ 'ref' => array(
+ array(
+ 'offset' => 8,
+ 'id' => 'ducks',
+ ),
+ ),
+ ),
+ 'We should make a post on #blog.example.com tomorrow.' => array(
+ 'embed' => array(),
+ 'ref' => array(
+ array(
+ 'offset' => 26,
+ 'id' => 'blog.example.com',
+ ),
+ ),
+ ),
+ 'We should make a post on #blog.example.com.' => array(
+ 'embed' => array(),
+ 'ref' => array(
+ array(
+ 'offset' => 26,
+ 'id' => 'blog.example.com',
+ ),
+ ),
+ ),
+ '#123' => array(
+ 'embed' => array(),
+ 'ref' => array(),
+ ),
+ '#security#123' => array(
+ 'embed' => array(),
+ 'ref' => array(
+ array(
+ 'offset' => 1,
+ 'id' => 'security',
+ 'tail' => '123',
+ ),
+ ),
+ ),
+ );
+
+ foreach ($cases as $input => $expect) {
+ $rule = new ProjectRemarkupRule();
+ $matches = $rule->extractReferences($input);
+ $this->assertEqual($expect, $matches, $input);
+ }
+ }
+
+}
diff --git a/src/infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php b/src/infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php
--- a/src/infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php
+++ b/src/infrastructure/markup/rule/PhabricatorObjectRemarkupRule.php
@@ -95,15 +95,33 @@
}
public function apply($text) {
- $prefix = $this->getObjectNamePrefix();
- $prefix = preg_quote($prefix, '@');
- $id = $this->getObjectIDPattern();
-
$text = preg_replace_callback(
- '@\B{'.$prefix.'('.$id.')((?:[^}\\\\]|\\\\.)*)}\B@u',
+ $this->getObjectEmbedPattern(),
array($this, 'markupObjectEmbed'),
$text);
+ $text = preg_replace_callback(
+ $this->getObjectReferencePattern(),
+ array($this, 'markupObjectReference'),
+ $text);
+
+ return $text;
+ }
+
+ private function getObjectEmbedPattern() {
+ $prefix = $this->getObjectNamePrefix();
+ $prefix = preg_quote($prefix);
+ $id = $this->getObjectIDPattern();
+
+ return '(\B{'.$prefix.'('.$id.')((?:[^}\\\\]|\\\\.)*)}\B)u';
+ }
+
+ private function getObjectReferencePattern() {
+ $prefix = $this->getObjectNamePrefix();
+ $prefix = preg_quote($prefix);
+
+ $id = $this->getObjectIDPattern();
+
// If the prefix starts with a word character (like "D"), we want to
// require a word boundary so that we don't match "XD1" as "D1". If the
// prefix does not start with a word character, we want to require no word
@@ -121,12 +139,55 @@
// The "\b" allows us to link "(abcdef)" or similar without linking things
// in the middle of words.
- $text = preg_replace_callback(
- '((?<![#-])'.$boundary.$prefix.'('.$id.')(?:#([-\w\d]+))?(?!\w))u',
- array($this, 'markupObjectReference'),
- $text);
+ return '((?<![#-])'.$boundary.$prefix.'('.$id.')(?:#([-\w\d]+))?(?!\w))u';
+ }
- return $text;
+
+ /**
+ * Extract matched object references from a block of text.
+ *
+ * This is intended to make it easy to write unit tests for object remarkup
+ * rules. Production code is not normally expected to call this method.
+ *
+ * @param string Text to match rules against.
+ * @return wild Matches, suitable for writing unit tests against.
+ */
+ public function extractReferences($text) {
+ $embed_matches = null;
+ preg_match_all(
+ $this->getObjectEmbedPattern(),
+ $text,
+ $embed_matches,
+ PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
+
+ $ref_matches = null;
+ preg_match_all(
+ $this->getObjectReferencePattern(),
+ $text,
+ $ref_matches,
+ PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
+
+ $results = array();
+ $sets = array(
+ 'embed' => $embed_matches,
+ 'ref' => $ref_matches,
+ );
+ foreach ($sets as $type => $matches) {
+ $formatted = array();
+ foreach ($matches as $match) {
+ $format = array(
+ 'offset' => $match[1][1],
+ 'id' => $match[1][0],
+ );
+ if (isset($match[2][0])) {
+ $format['tail'] = $match[2][0];
+ }
+ $formatted[] = $format;
+ }
+ $results[$type] = $formatted;
+ }
+
+ return $results;
}
public function markupObjectEmbed($matches) {
@@ -143,6 +204,9 @@
}
public function markupObjectReference($matches) {
+
+ phlog($matches);
+
if (!$this->isFlatText($matches[0])) {
return $matches[0];
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 7, 3:56 PM (2 w, 3 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7715328
Default Alt Text
D10753.id25809.diff (6 KB)
Attached To
Mode
D10753: Fix project hashtag regexp to stop matching terminal periods
Attached
Detach File
Event Timeline
Log In to Comment