1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 00:42:41 +01:00

Implement Graphviz, Figlet and Cowsay as Remarkup interpreter blocks

Summary: Fixes T3274. Fixes T3964. Ref T3591.

Test Plan: {F70928}

Reviewers: btrahan

Reviewed By: btrahan

CC: chad, aran

Maniphest Tasks: T3274, T3964, T3591

Differential Revision: https://secure.phabricator.com/D7332
This commit is contained in:
epriestley 2013-10-16 19:12:14 -07:00
parent 07b8c2cfd0
commit b55cf56d2e
7 changed files with 206 additions and 46 deletions

View file

@ -3433,7 +3433,7 @@ celerity_register_resource_map(array(
),
'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 @@ celerity_register_resource_map(array(
), array(
'packages' =>
array(
'a4e76ef8' =>
'30de5267' =>
array(
'name' => 'core.pkg.css',
'symbols' =>
@ -4322,7 +4322,7 @@ celerity_register_resource_map(array(
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 @@ celerity_register_resource_map(array(
),
'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 @@ celerity_register_resource_map(array(
'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 @@ celerity_register_resource_map(array(
'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',
),
));

View file

@ -1536,6 +1536,9 @@ phutil_register_library_map(array(
'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 @@ phutil_register_library_map(array(
'PhabricatorRedirectController' => 'PhabricatorController',
'PhabricatorRefreshCSRFController' => 'PhabricatorAuthController',
'PhabricatorRegistrationProfile' => 'Phobject',
'PhabricatorRemarkupBlockInterpreterCowsay' => 'PhutilRemarkupBlockInterpreter',
'PhabricatorRemarkupBlockInterpreterFiglet' => 'PhutilRemarkupBlockInterpreter',
'PhabricatorRemarkupBlockInterpreterGraphviz' => 'PhutilRemarkupBlockInterpreter',
'PhabricatorRemarkupControl' => 'AphrontFormTextAreaControl',
'PhabricatorRemarkupRuleEmbedFile' => 'PhabricatorRemarkupRuleObject',
'PhabricatorRemarkupRuleImageMacro' => 'PhutilRemarkupRule',

View file

@ -460,6 +460,7 @@ final class PhabricatorMarkupEngine {
$blocks[] = new PhutilRemarkupEngineRemarkupNoteBlockRule();
$blocks[] = new PhutilRemarkupEngineRemarkupTableBlockRule();
$blocks[] = new PhutilRemarkupEngineRemarkupSimpleTableBlockRule();
$blocks[] = new PhutilRemarkupEngineRemarkupInterpreterRule();
$custom_block_rule_classes = $options['custom-block'];
if ($custom_block_rule_classes) {

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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(),
));
}
}

View file

@ -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;