Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F72674
D7332.diff
All Users
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
13 KB
Referenced Files
None
Subscribers
None
D7332.diff
View Options
diff --git a/src/__celerity_resource_map__.php b/src/__celerity_resource_map__.php
--- a/src/__celerity_resource_map__.php
+++ b/src/__celerity_resource_map__.php
@@ -3433,7 +3433,7 @@
),
'phabricator-remarkup-css' =>
array(
- 'uri' => '/res/7e8988dd/rsrc/css/core/remarkup.css',
+ 'uri' => '/res/4c313572/rsrc/css/core/remarkup.css',
'type' => 'css',
'requires' =>
array(
@@ -4273,7 +4273,7 @@
), array(
'packages' =>
array(
- 'a4e76ef8' =>
+ '30de5267' =>
array(
'name' => 'core.pkg.css',
'symbols' =>
@@ -4322,7 +4322,7 @@
41 => 'phabricator-tag-view-css',
42 => 'phui-list-view-css',
),
- 'uri' => '/res/pkg/a4e76ef8/core.pkg.css',
+ 'uri' => '/res/pkg/30de5267/core.pkg.css',
'type' => 'css',
),
'6041c6c8' =>
@@ -4514,15 +4514,15 @@
),
'reverse' =>
array(
- 'aphront-dialog-view-css' => 'a4e76ef8',
- 'aphront-error-view-css' => 'a4e76ef8',
- 'aphront-list-filter-view-css' => 'a4e76ef8',
- 'aphront-pager-view-css' => 'a4e76ef8',
- 'aphront-panel-view-css' => 'a4e76ef8',
- 'aphront-table-view-css' => 'a4e76ef8',
- 'aphront-tokenizer-control-css' => 'a4e76ef8',
- 'aphront-tooltip-css' => 'a4e76ef8',
- 'aphront-typeahead-control-css' => 'a4e76ef8',
+ 'aphront-dialog-view-css' => '30de5267',
+ 'aphront-error-view-css' => '30de5267',
+ 'aphront-list-filter-view-css' => '30de5267',
+ 'aphront-pager-view-css' => '30de5267',
+ 'aphront-panel-view-css' => '30de5267',
+ 'aphront-table-view-css' => '30de5267',
+ 'aphront-tokenizer-control-css' => '30de5267',
+ 'aphront-tooltip-css' => '30de5267',
+ 'aphront-typeahead-control-css' => '30de5267',
'differential-changeset-view-css' => '7cd7e387',
'differential-core-view-css' => '7cd7e387',
'differential-inline-comment-editor' => '5e9e5c4e',
@@ -4536,7 +4536,7 @@
'differential-table-of-contents-css' => '7cd7e387',
'diffusion-commit-view-css' => '270f4eb4',
'diffusion-icons-css' => '270f4eb4',
- 'global-drag-and-drop-css' => 'a4e76ef8',
+ 'global-drag-and-drop-css' => '30de5267',
'inline-comment-summary-css' => '7cd7e387',
'javelin-aphlict' => '6041c6c8',
'javelin-behavior' => '3e3be199',
@@ -4611,56 +4611,56 @@
'javelin-util' => '3e3be199',
'javelin-vector' => '3e3be199',
'javelin-workflow' => '3e3be199',
- 'lightbox-attachment-css' => 'a4e76ef8',
+ 'lightbox-attachment-css' => '30de5267',
'maniphest-task-summary-css' => '49898640',
- 'phabricator-action-list-view-css' => 'a4e76ef8',
- 'phabricator-application-launch-view-css' => 'a4e76ef8',
+ 'phabricator-action-list-view-css' => '30de5267',
+ 'phabricator-application-launch-view-css' => '30de5267',
'phabricator-busy' => '6041c6c8',
'phabricator-content-source-view-css' => '7cd7e387',
- 'phabricator-core-css' => 'a4e76ef8',
- 'phabricator-crumbs-view-css' => 'a4e76ef8',
+ 'phabricator-core-css' => '30de5267',
+ 'phabricator-crumbs-view-css' => '30de5267',
'phabricator-drag-and-drop-file-upload' => '5e9e5c4e',
'phabricator-dropdown-menu' => '6041c6c8',
'phabricator-file-upload' => '6041c6c8',
- 'phabricator-filetree-view-css' => 'a4e76ef8',
- 'phabricator-flag-css' => 'a4e76ef8',
+ 'phabricator-filetree-view-css' => '30de5267',
+ 'phabricator-flag-css' => '30de5267',
'phabricator-hovercard' => '6041c6c8',
- 'phabricator-jump-nav' => 'a4e76ef8',
+ 'phabricator-jump-nav' => '30de5267',
'phabricator-keyboard-shortcut' => '6041c6c8',
'phabricator-keyboard-shortcut-manager' => '6041c6c8',
- 'phabricator-main-menu-view' => 'a4e76ef8',
+ 'phabricator-main-menu-view' => '30de5267',
'phabricator-menu-item' => '6041c6c8',
- 'phabricator-nav-view-css' => 'a4e76ef8',
+ 'phabricator-nav-view-css' => '30de5267',
'phabricator-notification' => '6041c6c8',
- 'phabricator-notification-css' => 'a4e76ef8',
- 'phabricator-notification-menu-css' => 'a4e76ef8',
+ 'phabricator-notification-css' => '30de5267',
+ 'phabricator-notification-menu-css' => '30de5267',
'phabricator-object-selector-css' => '7cd7e387',
'phabricator-phtize' => '6041c6c8',
'phabricator-prefab' => '6041c6c8',
'phabricator-project-tag-css' => '49898640',
- 'phabricator-remarkup-css' => 'a4e76ef8',
+ 'phabricator-remarkup-css' => '30de5267',
'phabricator-shaped-request' => '5e9e5c4e',
- 'phabricator-side-menu-view-css' => 'a4e76ef8',
- 'phabricator-standard-page-view' => 'a4e76ef8',
- 'phabricator-tag-view-css' => 'a4e76ef8',
+ 'phabricator-side-menu-view-css' => '30de5267',
+ 'phabricator-standard-page-view' => '30de5267',
+ 'phabricator-tag-view-css' => '30de5267',
'phabricator-textareautils' => '6041c6c8',
'phabricator-tooltip' => '6041c6c8',
- 'phabricator-transaction-view-css' => 'a4e76ef8',
- 'phabricator-zindex-css' => 'a4e76ef8',
- 'phui-button-css' => 'a4e76ef8',
- 'phui-form-css' => 'a4e76ef8',
- 'phui-form-view-css' => 'a4e76ef8',
- 'phui-header-view-css' => 'a4e76ef8',
- 'phui-icon-view-css' => 'a4e76ef8',
- 'phui-list-view-css' => 'a4e76ef8',
- 'phui-object-item-list-view-css' => 'a4e76ef8',
- 'phui-property-list-view-css' => 'a4e76ef8',
- 'phui-spacing-css' => 'a4e76ef8',
- 'sprite-apps-large-css' => 'a4e76ef8',
- 'sprite-gradient-css' => 'a4e76ef8',
- 'sprite-icons-css' => 'a4e76ef8',
- 'sprite-menu-css' => 'a4e76ef8',
- 'sprite-status-css' => 'a4e76ef8',
- 'syntax-highlighting-css' => 'a4e76ef8',
+ 'phabricator-transaction-view-css' => '30de5267',
+ 'phabricator-zindex-css' => '30de5267',
+ 'phui-button-css' => '30de5267',
+ 'phui-form-css' => '30de5267',
+ 'phui-form-view-css' => '30de5267',
+ 'phui-header-view-css' => '30de5267',
+ 'phui-icon-view-css' => '30de5267',
+ 'phui-list-view-css' => '30de5267',
+ 'phui-object-item-list-view-css' => '30de5267',
+ 'phui-property-list-view-css' => '30de5267',
+ 'phui-spacing-css' => '30de5267',
+ 'sprite-apps-large-css' => '30de5267',
+ 'sprite-gradient-css' => '30de5267',
+ 'sprite-icons-css' => '30de5267',
+ 'sprite-menu-css' => '30de5267',
+ 'sprite-status-css' => '30de5267',
+ 'syntax-highlighting-css' => '30de5267',
),
));
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
@@ -1536,6 +1536,9 @@
'PhabricatorRedirectController' => 'applications/base/controller/PhabricatorRedirectController.php',
'PhabricatorRefreshCSRFController' => 'applications/auth/controller/PhabricatorRefreshCSRFController.php',
'PhabricatorRegistrationProfile' => 'applications/people/storage/PhabricatorRegistrationProfile.php',
+ 'PhabricatorRemarkupBlockInterpreterCowsay' => 'infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterCowsay.php',
+ 'PhabricatorRemarkupBlockInterpreterFiglet' => 'infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterFiglet.php',
+ 'PhabricatorRemarkupBlockInterpreterGraphviz' => 'infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterGraphviz.php',
'PhabricatorRemarkupControl' => 'view/form/control/PhabricatorRemarkupControl.php',
'PhabricatorRemarkupRuleEmbedFile' => 'applications/files/remarkup/PhabricatorRemarkupRuleEmbedFile.php',
'PhabricatorRemarkupRuleImageMacro' => 'applications/macro/remarkup/PhabricatorRemarkupRuleImageMacro.php',
@@ -3747,6 +3750,9 @@
'PhabricatorRedirectController' => 'PhabricatorController',
'PhabricatorRefreshCSRFController' => 'PhabricatorAuthController',
'PhabricatorRegistrationProfile' => 'Phobject',
+ 'PhabricatorRemarkupBlockInterpreterCowsay' => 'PhutilRemarkupBlockInterpreter',
+ 'PhabricatorRemarkupBlockInterpreterFiglet' => 'PhutilRemarkupBlockInterpreter',
+ 'PhabricatorRemarkupBlockInterpreterGraphviz' => 'PhutilRemarkupBlockInterpreter',
'PhabricatorRemarkupControl' => 'AphrontFormTextAreaControl',
'PhabricatorRemarkupRuleEmbedFile' => 'PhabricatorRemarkupRuleObject',
'PhabricatorRemarkupRuleImageMacro' => 'PhutilRemarkupRule',
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
@@ -460,6 +460,7 @@
$blocks[] = new PhutilRemarkupEngineRemarkupNoteBlockRule();
$blocks[] = new PhutilRemarkupEngineRemarkupTableBlockRule();
$blocks[] = new PhutilRemarkupEngineRemarkupSimpleTableBlockRule();
+ $blocks[] = new PhutilRemarkupEngineRemarkupInterpreterRule();
$custom_block_rule_classes = $options['custom-block'];
if ($custom_block_rule_classes) {
diff --git a/src/infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterCowsay.php b/src/infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterCowsay.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterCowsay.php
@@ -0,0 +1,55 @@
+<?php
+
+final class PhabricatorRemarkupBlockInterpreterCowsay
+ extends PhutilRemarkupBlockInterpreter {
+
+ public function getInterpreterName() {
+ return 'cowsay';
+ }
+
+ public function markupContent($content, array $argv) {
+ if (!Filesystem::binaryExists('cowsay')) {
+ return $this->markupError(
+ pht('Unable to locate the `cowsay` binary. Install cowsay.'));
+ }
+
+ $bin = idx($argv, 'think') ? 'cowthink' : 'cowsay';
+ $eyes = idx($argv, 'eyes', 'oo');
+ $tongue = idx($argv, 'tongue', ' ');
+ $cow = idx($argv, 'cow', 'default');
+
+ // NOTE: Strip this aggressively to prevent nonsense like
+ // `cow=/etc/passwd`. We could build a whiltelist with `cowsay -l`.
+ $cow = preg_replace('/[^a-z.-]+/', '', $cow);
+
+ $future = new ExecFuture(
+ '%s -e %s -T %s -f %s ',
+ $bin,
+ $eyes,
+ $tongue,
+ $cow);
+
+ $future->write($content);
+
+ list($err, $stdout, $stderr) = $future->resolve();
+
+ if ($err) {
+ return $this->markupError(
+ pht(
+ 'Execution of `cowsay` failed:', $stderr));
+ }
+
+
+ if ($this->getEngine()->isTextMode()) {
+ return $stdout;
+ }
+
+ return phutil_tag(
+ 'div',
+ array(
+ 'class' => 'PhabricatorMonospaced remarkup-cowsay',
+ ),
+ $stdout);
+ }
+
+}
diff --git a/src/infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterFiglet.php b/src/infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterFiglet.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterFiglet.php
@@ -0,0 +1,40 @@
+<?php
+
+final class PhabricatorRemarkupBlockInterpreterFiglet
+ extends PhutilRemarkupBlockInterpreter {
+
+ public function getInterpreterName() {
+ return 'figlet';
+ }
+
+ public function markupContent($content, array $argv) {
+ if (!Filesystem::binaryExists('figlet')) {
+ return $this->markupError(
+ pht('Unable to locate the `figlet` binary. Install figlet.'));
+ }
+
+ $future = id(new ExecFuture('figlet'))
+ ->write(trim($content, "\n"));
+
+ list($err, $stdout, $stderr) = $future->resolve();
+
+ if ($err) {
+ return $this->markupError(
+ pht(
+ 'Execution of `figlet` failed:', $stderr));
+ }
+
+
+ if ($this->getEngine()->isTextMode()) {
+ return $stdout;
+ }
+
+ return phutil_tag(
+ 'div',
+ array(
+ 'class' => 'PhabricatorMonospaced remarkup-figlet',
+ ),
+ $stdout);
+ }
+
+}
diff --git a/src/infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterGraphviz.php b/src/infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterGraphviz.php
new file mode 100644
--- /dev/null
+++ b/src/infrastructure/markup/interpreter/PhabricatorRemarkupBlockInterpreterGraphviz.php
@@ -0,0 +1,44 @@
+<?php
+
+final class PhabricatorRemarkupBlockInterpreterGraphviz
+ extends PhutilRemarkupBlockInterpreter {
+
+ public function getInterpreterName() {
+ return 'dot';
+ }
+
+ public function markupContent($content, array $argv) {
+ if (!Filesystem::binaryExists('dot')) {
+ return $this->markupError(
+ pht('Unable to locate the `dot` binary. Install Graphviz.'));
+ }
+
+ $future = id(new ExecFuture('dot -T%s', 'png'))
+ ->write(trim($content));
+
+ list($err, $stdout, $stderr) = $future->resolve();
+
+ if ($err) {
+ return $this->markupError(
+ pht(
+ 'Execution of `dot` failed, check your syntax: %s', $stderr));
+ }
+
+ $file = PhabricatorFile::buildFromFileDataOrHash(
+ $stdout,
+ array(
+ 'name' => 'graphviz.png',
+ ));
+
+ if ($this->getEngine()->isTextMode()) {
+ return '<'.$file->getBestURI().'>';
+ }
+
+ return phutil_tag(
+ 'img',
+ array(
+ 'src' => $file->getBestURI(),
+ ));
+ }
+
+}
diff --git a/webroot/rsrc/css/core/remarkup.css b/webroot/rsrc/css/core/remarkup.css
--- a/webroot/rsrc/css/core/remarkup.css
+++ b/webroot/rsrc/css/core/remarkup.css
@@ -329,6 +329,20 @@
border-right: 1px solid #cccccc;
}
+.remarkup-interpreter-error {
+ padding: 8px;
+ border: 1px solid {$red};
+ background-color: {$lightred};
+}
+
+.remarkup-cowsay {
+ white-space: pre-wrap;
+}
+
+.remarkup-figlet {
+ white-space: pre-wrap;
+}
+
.remarkup-assist {
display: block;
width: 14px;
File Metadata
Details
Attached
Mime Type
text/x-diff
Storage Engine
amazon-s3
Storage Format
Raw Data
Storage Handle
phabricator/aq/3e/mke66sxxe37gsecb
Default Alt Text
D7332.diff (13 KB)
Attached To
Mode
D7332: Implement Graphviz, Figlet and Cowsay as Remarkup interpreter blocks
Attached
Detach File
Event Timeline
Log In to Comment