From dbe2fb466fedd15e0aadb5e35dcc2c78bf2c4af6 Mon Sep 17 00:00:00 2001 From: epriestley Date: Tue, 27 Jul 2021 14:02:48 -0700 Subject: [PATCH] Add an "eval" rule to Remarkup Summary: Ref T13658. This adds a simple expression evaluator to Remarkup and supports platform name expressions. The syntax is: ``` ${{{strings.platform.server.name}}} ``` Note that this won't work inside code blocks (or literal blocks, or other block-level literal elements) right now, although it could be made to selectively (the ".path" expressions might be useful in documentation codeblocks). Test Plan: {F9391006} Reviewers: cspeckmim Reviewed By: cspeckmim Maniphest Tasks: T13658 Differential Revision: https://secure.phabricator.com/D21713 --- src/__phutil_library_map__.php | 2 + .../markup/PhabricatorMarkupEngine.php | 3 +- .../markuprule/PhutilRemarkupEvalRule.php | 100 ++++++++++++++++++ 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/infrastructure/markup/markuprule/PhutilRemarkupEvalRule.php diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 5110b19f2e..421ee76400 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -5770,6 +5770,7 @@ phutil_register_library_map(array( 'PhutilRemarkupEngine' => 'infrastructure/markup/remarkup/PhutilRemarkupEngine.php', 'PhutilRemarkupEngineTestCase' => 'infrastructure/markup/remarkup/__tests__/PhutilRemarkupEngineTestCase.php', 'PhutilRemarkupEscapeRemarkupRule' => 'infrastructure/markup/markuprule/PhutilRemarkupEscapeRemarkupRule.php', + 'PhutilRemarkupEvalRule' => 'infrastructure/markup/markuprule/PhutilRemarkupEvalRule.php', 'PhutilRemarkupHeaderBlockRule' => 'infrastructure/markup/blockrule/PhutilRemarkupHeaderBlockRule.php', 'PhutilRemarkupHighlightRule' => 'infrastructure/markup/markuprule/PhutilRemarkupHighlightRule.php', 'PhutilRemarkupHorizontalRuleBlockRule' => 'infrastructure/markup/blockrule/PhutilRemarkupHorizontalRuleBlockRule.php', @@ -12770,6 +12771,7 @@ phutil_register_library_map(array( 'PhutilRemarkupEngine' => 'PhutilMarkupEngine', 'PhutilRemarkupEngineTestCase' => 'PhutilTestCase', 'PhutilRemarkupEscapeRemarkupRule' => 'PhutilRemarkupRule', + 'PhutilRemarkupEvalRule' => 'PhutilRemarkupRule', 'PhutilRemarkupHeaderBlockRule' => 'PhutilRemarkupBlockRule', 'PhutilRemarkupHighlightRule' => 'PhutilRemarkupRule', 'PhutilRemarkupHorizontalRuleBlockRule' => 'PhutilRemarkupBlockRule', diff --git a/src/infrastructure/markup/PhabricatorMarkupEngine.php b/src/infrastructure/markup/PhabricatorMarkupEngine.php index 5422870b68..3ad5304945 100644 --- a/src/infrastructure/markup/PhabricatorMarkupEngine.php +++ b/src/infrastructure/markup/PhabricatorMarkupEngine.php @@ -42,7 +42,7 @@ final class PhabricatorMarkupEngine extends Phobject { private $objects = array(); private $viewer; private $contextObject; - private $version = 20; + private $version = 21; private $engineCaches = array(); private $auxiliaryConfig = array(); @@ -504,6 +504,7 @@ final class PhabricatorMarkupEngine extends Phobject { $rules = array(); $rules[] = new PhutilRemarkupEscapeRemarkupRule(); + $rules[] = new PhutilRemarkupEvalRule(); $rules[] = new PhutilRemarkupMonospaceRule(); diff --git a/src/infrastructure/markup/markuprule/PhutilRemarkupEvalRule.php b/src/infrastructure/markup/markuprule/PhutilRemarkupEvalRule.php new file mode 100644 index 0000000000..ea20dfedef --- /dev/null +++ b/src/infrastructure/markup/markuprule/PhutilRemarkupEvalRule.php @@ -0,0 +1,100 @@ +isFlatText($expression)) { + return $matches[0]; + } + + $engine = $this->getEngine(); + $token = $engine->storeText($expression); + + $list_key = self::KEY_EVAL; + $expression_list = $engine->getTextMetadata($list_key, array()); + + $expression_list[] = array( + 'token' => $token, + 'expression' => $expression, + 'original' => $matches[0], + ); + + $engine->setTextMetadata($list_key, $expression_list); + + return $token; + } + + public function didMarkupText() { + $engine = $this->getEngine(); + + $list_key = self::KEY_EVAL; + $expression_list = $engine->getTextMetadata($list_key, array()); + + foreach ($expression_list as $expression_item) { + $token = $expression_item['token']; + $expression = $expression_item['expression']; + + $result = $this->evaluateExpression($expression); + + if ($result === null) { + $result = $expression_item['original']; + } + + $engine->overwriteStoredText($token, $result); + } + } + + private function evaluateExpression($expression) { + static $string_map; + + if ($string_map === null) { + $string_map = array( + 'strings' => array( + 'platform' => array( + 'server' => array( + 'name' => pht('Phabricator'), + 'path' => pht('phabricator/'), + ), + 'client' => array( + 'name' => pht('Arcanist'), + 'path' => pht('arcanist/'), + ), + ), + ), + ); + } + + $parts = explode('.', $expression); + + $cursor = $string_map; + foreach ($parts as $part) { + if (isset($cursor[$part])) { + $cursor = $cursor[$part]; + } else { + break; + } + } + + if (is_string($cursor)) { + return $cursor; + } + + return null; + } + +} -- 2.51.2