Page MenuHomePhabricator

D19274.id46135.diff
No OneTemporary

D19274.id46135.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -10,7 +10,7 @@
'conpherence.pkg.css' => 'e68cf1fa',
'conpherence.pkg.js' => '15191c65',
'core.pkg.css' => '1dd5fa4b',
- 'core.pkg.js' => 'b9b4a943',
+ 'core.pkg.js' => '1ea38af8',
'differential.pkg.css' => '113e692c',
'differential.pkg.js' => 'f6d809c0',
'diffusion.pkg.css' => 'a2d17c7d',
@@ -392,7 +392,7 @@
'rsrc/js/application/diffusion/behavior-pull-lastmodified.js' => 'f01586dc',
'rsrc/js/application/doorkeeper/behavior-doorkeeper-tag.js' => '1db13e70',
'rsrc/js/application/drydock/drydock-live-operation-status.js' => '901935ef',
- 'rsrc/js/application/files/behavior-document-engine.js' => '194cbe53',
+ 'rsrc/js/application/files/behavior-document-engine.js' => '9108ee1a',
'rsrc/js/application/files/behavior-icon-composer.js' => '8499b6ab',
'rsrc/js/application/files/behavior-launch-icon-composer.js' => '48086888',
'rsrc/js/application/harbormaster/behavior-harbormaster-log.js' => '191b4909',
@@ -508,7 +508,7 @@
'rsrc/js/phui/behavior-phui-submenu.js' => 'a6f7a73b',
'rsrc/js/phui/behavior-phui-tab-group.js' => '0a0b10e9',
'rsrc/js/phuix/PHUIXActionListView.js' => 'b5c256b8',
- 'rsrc/js/phuix/PHUIXActionView.js' => 'ed18356a',
+ 'rsrc/js/phuix/PHUIXActionView.js' => '8d4a8c72',
'rsrc/js/phuix/PHUIXAutocomplete.js' => 'df1bbd34',
'rsrc/js/phuix/PHUIXButtonView.js' => '8a91e1ac',
'rsrc/js/phuix/PHUIXDropdownMenu.js' => '04b2ae03',
@@ -607,7 +607,7 @@
'javelin-behavior-diffusion-jump-to' => '73d09eef',
'javelin-behavior-diffusion-locate-file' => '6d3e1947',
'javelin-behavior-diffusion-pull-lastmodified' => 'f01586dc',
- 'javelin-behavior-document-engine' => '194cbe53',
+ 'javelin-behavior-document-engine' => '9108ee1a',
'javelin-behavior-doorkeeper-tag' => '1db13e70',
'javelin-behavior-drydock-live-operation-status' => '901935ef',
'javelin-behavior-durable-column' => '2ae077e1',
@@ -864,7 +864,7 @@
'phui-workcard-view-css' => 'cca5fa92',
'phui-workpanel-view-css' => 'a3a63478',
'phuix-action-list-view' => 'b5c256b8',
- 'phuix-action-view' => 'ed18356a',
+ 'phuix-action-view' => '8d4a8c72',
'phuix-autocomplete' => 'df1bbd34',
'phuix-button-view' => '8a91e1ac',
'phuix-dropdown-menu' => '04b2ae03',
@@ -983,11 +983,6 @@
'191b4909' => array(
'javelin-behavior',
),
- '194cbe53' => array(
- 'javelin-behavior',
- 'javelin-dom',
- 'javelin-stratcom',
- ),
'1ad0a787' => array(
'javelin-install',
'javelin-reactor',
@@ -1619,6 +1614,11 @@
'javelin-stratcom',
'javelin-install',
),
+ '8d4a8c72' => array(
+ 'javelin-install',
+ 'javelin-dom',
+ 'javelin-util',
+ ),
'8e1baf68' => array(
'phui-button-css',
),
@@ -1644,6 +1644,11 @@
'javelin-stratcom',
'javelin-vector',
),
+ '9108ee1a' => array(
+ 'javelin-behavior',
+ 'javelin-dom',
+ 'javelin-stratcom',
+ ),
'92b9ec77' => array(
'javelin-behavior',
'javelin-stratcom',
@@ -2125,11 +2130,6 @@
'javelin-stratcom',
'javelin-vector',
),
- 'ed18356a' => array(
- 'javelin-install',
- 'javelin-dom',
- 'javelin-util',
- ),
'edf8a145' => array(
'javelin-behavior',
'javelin-uri',
diff --git a/src/applications/files/controller/PhabricatorFileDocumentController.php b/src/applications/files/controller/PhabricatorFileDocumentController.php
--- a/src/applications/files/controller/PhabricatorFileDocumentController.php
+++ b/src/applications/files/controller/PhabricatorFileDocumentController.php
@@ -43,6 +43,16 @@
$engine = $engines[$engine_key];
$this->engine = $engine;
+ $encode_setting = $request->getStr('encode');
+ if (strlen($encode_setting)) {
+ $engine->setEncodingConfiguration($encode_setting);
+ }
+
+ $highlight_setting = $request->getStr('highlight');
+ if (strlen($highlight_setting)) {
+ $engine->setHighlightingConfiguration($highlight_setting);
+ }
+
try {
$content = $engine->newDocument($ref);
} catch (Exception $ex) {
diff --git a/src/applications/files/controller/PhabricatorFileViewController.php b/src/applications/files/controller/PhabricatorFileViewController.php
--- a/src/applications/files/controller/PhabricatorFileViewController.php
+++ b/src/applications/files/controller/PhabricatorFileViewController.php
@@ -422,6 +422,16 @@
$engine->setHighlightedLines(range($lines[0], $lines[1]));
}
+ $encode_setting = $request->getStr('encode');
+ if (strlen($encode_setting)) {
+ $engine->setEncodingConfiguration($encode_setting);
+ }
+
+ $highlight_setting = $request->getStr('highlight');
+ if (strlen($highlight_setting)) {
+ $engine->setHighlightingConfiguration($highlight_setting);
+ }
+
$views = array();
foreach ($engines as $candidate_key => $candidate_engine) {
$label = $candidate_engine->getViewAsLabel($ref);
@@ -443,6 +453,8 @@
'engineURI' => $candidate_engine->getRenderURI($ref),
'viewURI' => $view_uri,
'loadingMarkup' => hsprintf('%s', $loading),
+ 'canEncode' => $candidate_engine->canConfigureEncoding($ref),
+ 'canHighlight' => $candidate_engine->CanConfigureHighlighting($ref),
);
}
@@ -474,6 +486,18 @@
'viewKey' => $engine->getDocumentEngineKey(),
'views' => $views,
'standaloneURI' => $engine->getRenderURI($ref),
+ 'encode' => array(
+ 'icon' => 'fa-font',
+ 'name' => pht('Change Text Encoding...'),
+ 'uri' => '/services/encoding/',
+ 'value' => $encode_setting,
+ ),
+ 'highlight' => array(
+ 'icon' => 'fa-lightbulb-o',
+ 'name' => pht('Highlight As...'),
+ 'uri' => '/services/highlight/',
+ 'value' => $highlight_setting,
+ ),
);
$view_button = id(new PHUIButtonView())
diff --git a/src/applications/files/document/PhabricatorDocumentEngine.php b/src/applications/files/document/PhabricatorDocumentEngine.php
--- a/src/applications/files/document/PhabricatorDocumentEngine.php
+++ b/src/applications/files/document/PhabricatorDocumentEngine.php
@@ -5,6 +5,8 @@
private $viewer;
private $highlightedLines = array();
+ private $encodingConfiguration;
+ private $highlightingConfiguration;
final public function setViewer(PhabricatorUser $viewer) {
$this->viewer = $viewer;
@@ -28,6 +30,32 @@
return $this->canRenderDocumentType($ref);
}
+ public function canConfigureEncoding(PhabricatorDocumentRef $ref) {
+ return false;
+ }
+
+ public function canConfigureHighlighting(PhabricatorDocumentRef $ref) {
+ return false;
+ }
+
+ final public function setEncodingConfiguration($config) {
+ $this->encodingConfiguration = $config;
+ return $this;
+ }
+
+ final public function getEncodingConfiguration() {
+ return $this->encodingConfiguration;
+ }
+
+ final public function setHighlightingConfiguration($config) {
+ $this->highlightingConfiguration = $config;
+ return $this;
+ }
+
+ final public function getHighlightingConfiguration() {
+ return $this->highlightingConfiguration;
+ }
+
public function shouldRenderAsync(PhabricatorDocumentRef $ref) {
return false;
}
diff --git a/src/applications/files/document/PhabricatorSourceDocumentEngine.php b/src/applications/files/document/PhabricatorSourceDocumentEngine.php
--- a/src/applications/files/document/PhabricatorSourceDocumentEngine.php
+++ b/src/applications/files/document/PhabricatorSourceDocumentEngine.php
@@ -9,6 +9,10 @@
return pht('View as Source');
}
+ public function canConfigureHighlighting(PhabricatorDocumentRef $ref) {
+ return true;
+ }
+
protected function getDocumentIconIcon(PhabricatorDocumentRef $ref) {
return 'fa-code';
}
@@ -20,9 +24,16 @@
protected function newDocumentContent(PhabricatorDocumentRef $ref) {
$content = $this->loadTextData($ref);
- $content = PhabricatorSyntaxHighlighter::highlightWithFilename(
- $ref->getName(),
- $content);
+ $highlighting = $this->getHighlightingConfiguration();
+ if ($highlighting !== null) {
+ $content = PhabricatorSyntaxHighlighter::highlightWithLanguage(
+ $highlighting,
+ $content);
+ } else {
+ $content = PhabricatorSyntaxHighlighter::highlightWithFilename(
+ $ref->getName(),
+ $content);
+ }
return $this->newTextDocumentContent($content);
}
diff --git a/src/applications/files/document/PhabricatorTextDocumentEngine.php b/src/applications/files/document/PhabricatorTextDocumentEngine.php
--- a/src/applications/files/document/PhabricatorTextDocumentEngine.php
+++ b/src/applications/files/document/PhabricatorTextDocumentEngine.php
@@ -3,10 +3,16 @@
abstract class PhabricatorTextDocumentEngine
extends PhabricatorDocumentEngine {
+ private $encodingMessage = null;
+
protected function canRenderDocumentType(PhabricatorDocumentRef $ref) {
return $ref->isProbablyText();
}
+ public function canConfigureEncoding(PhabricatorDocumentRef $ref) {
+ return true;
+ }
+
protected function newTextDocumentContent($content) {
$lines = phutil_split_lines($content);
@@ -14,19 +20,69 @@
->setHighlights($this->getHighlightedLines())
->setLines($lines);
+ $message = null;
+ if ($this->encodingMessage !== null) {
+ $message = $this->newMessage($this->encodingMessage);
+ }
+
$container = phutil_tag(
'div',
array(
'class' => 'document-engine-text',
),
- $view);
+ array(
+ $message,
+ $view,
+ ));
return $container;
}
protected function loadTextData(PhabricatorDocumentRef $ref) {
$content = $ref->loadData();
- $content = phutil_utf8ize($content);
+
+ $encoding = $this->getEncodingConfiguration();
+ if ($encoding !== null) {
+ if (function_exists('mb_convert_encoding')) {
+ $content = mb_convert_encoding($content, 'UTF-8', $encoding);
+ $this->encodingMessage = pht(
+ 'This document was converted from %s to UTF8 for display.',
+ $encoding);
+ } else {
+ $this->encodingMessage = pht(
+ 'Unable to perform text encoding conversion: mbstring extension '.
+ 'is not available.');
+ }
+ } else {
+ if (!phutil_is_utf8($content)) {
+ if (function_exists('mb_detect_encoding')) {
+ $try_encodings = array(
+ 'JIS' => pht('JIS'),
+ 'EUC-JP' => pht('EUC-JP'),
+ 'SJIS' => pht('Shift JIS'),
+ 'ISO-8859-1' => pht('ISO-8859-1 (Latin 1)'),
+ );
+
+ $guess = mb_detect_encoding($content, array_keys($try_encodings));
+ if ($guess) {
+ $content = mb_convert_encoding($content, 'UTF-8', $guess);
+ $this->encodingMessage = pht(
+ 'This document is not UTF8. It was detected as %s and '.
+ 'converted to UTF8 for display.',
+ idx($try_encodings, $guess, $guess));
+ }
+ }
+ }
+ }
+
+ if (!phutil_is_utf8($content)) {
+ $content = phutil_utf8ize($content);
+ $this->encodingMessage = pht(
+ 'This document is not UTF8 and its text encoding could not be '.
+ 'detected automatically. Use "Change Text Encoding..." to choose '.
+ 'an encoding.');
+ }
+
return $content;
}
diff --git a/webroot/rsrc/js/application/files/behavior-document-engine.js b/webroot/rsrc/js/application/files/behavior-document-engine.js
--- a/webroot/rsrc/js/application/files/behavior-document-engine.js
+++ b/webroot/rsrc/js/application/files/behavior-document-engine.js
@@ -52,6 +52,61 @@
});
}
+ list.addItem(
+ new JX.PHUIXActionView()
+ .setDivider(true));
+
+ var encode_item = new JX.PHUIXActionView()
+ .setName(data.encode.name)
+ .setIcon(data.encode.icon);
+
+ var onencode = JX.bind(null, function(data, e) {
+ e.prevent();
+
+ if (encode_item.getDisabled()) {
+ return;
+ }
+
+ new JX.Workflow(data.encode.uri, {encoding: data.encode.value})
+ .setHandler(function(r) {
+ data.encode.value = r.encoding;
+ onview(data);
+ })
+ .start();
+
+ menu.close();
+
+ }, data);
+
+ encode_item.setHandler(onencode);
+
+ list.addItem(encode_item);
+
+ var highlight_item = new JX.PHUIXActionView()
+ .setName(data.highlight.name)
+ .setIcon(data.highlight.icon);
+
+ var onhighlight = JX.bind(null, function(data, e) {
+ e.prevent();
+
+ if (highlight_item.getDisabled()) {
+ return;
+ }
+
+ new JX.Workflow(data.highlight.uri, {highlight: data.highlight.value})
+ .setHandler(function(r) {
+ data.highlight.value = r.highlight;
+ onview(data);
+ })
+ .start();
+
+ menu.close();
+ }, data);
+
+ highlight_item.setHandler(onhighlight);
+
+ list.addItem(highlight_item);
+
menu.setContent(list.getNode());
menu.listen('open', function() {
@@ -61,6 +116,11 @@
// Highlight the current rendering engine.
var is_selected = (engine.spec.viewKey == data.viewKey);
engine.view.setSelected(is_selected);
+
+ if (is_selected) {
+ encode_item.setDisabled(!engine.spec.canEncode);
+ highlight_item.setDisabled(!engine.spec.canHighlight);
+ }
}
});
@@ -68,13 +128,38 @@
menu.open();
}
+ function add_params(uri, data) {
+ uri = JX.$U(uri);
+
+ if (data.highlight.value) {
+ uri.setQueryParam('highlight', data.highlight.value);
+ }
+
+ if (data.encode.value) {
+ uri.setQueryParam('encode', data.encode.value);
+ }
+
+ return uri.toString();
+ }
+
function onview(data, spec, immediate) {
+ if (!spec) {
+ for (var ii = 0; ii < data.views.length; ii++) {
+ if (data.views[ii].viewKey == data.viewKey) {
+ spec = data.views[ii];
+ break;
+ }
+ }
+ }
+
data.sequence = (data.sequence || 0) + 1;
var handler = JX.bind(null, onrender, data, data.sequence);
data.viewKey = spec.viewKey;
- new JX.Request(spec.engineURI, handler)
+ var uri = add_params(spec.engineURI, data);
+
+ new JX.Request(uri, handler)
.send();
if (data.loadingView) {
@@ -93,7 +178,9 @@
// Replace the URI with the URI for the specific rendering the user
// has selected.
- JX.History.replace(spec.viewURI);
+
+ var view_uri = add_params(spec.viewURI, data);
+ JX.History.replace(view_uri);
}
}
@@ -134,13 +221,7 @@
if (config && config.renderControlID) {
var control = JX.$(config.renderControlID);
var data = JX.Stratcom.getData(control);
-
- for (var ii = 0; ii < data.views.length; ii++) {
- if (data.views[ii].viewKey == data.viewKey) {
- onview(data, data.views[ii], true);
- break;
- }
- }
+ onview(data, null, true);
}
});
diff --git a/webroot/rsrc/js/phuix/PHUIXActionView.js b/webroot/rsrc/js/phuix/PHUIXActionView.js
--- a/webroot/rsrc/js/phuix/PHUIXActionView.js
+++ b/webroot/rsrc/js/phuix/PHUIXActionView.js
@@ -34,6 +34,10 @@
return this;
},
+ getDisabled: function() {
+ return this._disabled;
+ },
+
setLabel: function(label) {
this._label = label;
JX.DOM.alterClass(

File Metadata

Mime Type
text/plain
Expires
Wed, Mar 5, 7:05 AM (2 w, 5 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7223862
Default Alt Text
D19274.id46135.diff (15 KB)

Event Timeline