Page MenuHomePhorge

D25457.1726871433.diff
No OneTemporary

D25457.1726871433.diff

diff --git a/resources/celerity/map.php b/resources/celerity/map.php
--- a/resources/celerity/map.php
+++ b/resources/celerity/map.php
@@ -72,7 +72,7 @@
'rsrc/css/application/differential/table-of-contents.css' => 'bba788b9',
'rsrc/css/application/diffusion/diffusion-icons.css' => '23b31a1b',
'rsrc/css/application/diffusion/diffusion-readme.css' => 'b68a76e4',
- 'rsrc/css/application/diffusion/diffusion-repository.css' => 'b89e8c6c',
+ 'rsrc/css/application/diffusion/diffusion-repository.css' => '6c7a1d8c',
'rsrc/css/application/diffusion/diffusion.css' => 'e46232d6',
'rsrc/css/application/feed/feed.css' => 'd8b6e3f8',
'rsrc/css/application/files/global-drag-and-drop.css' => '1d2713a4',
@@ -471,6 +471,7 @@
'rsrc/js/core/behavior-badge-view.js' => '92cdd7b6',
'rsrc/js/core/behavior-bulk-editor.js' => 'aa6d2308',
'rsrc/js/core/behavior-choose-control.js' => '04f8a1e3',
+ 'rsrc/js/core/behavior-collapsiblejx.js' => '7072263b',
'rsrc/js/core/behavior-copy.js' => 'cf32921f',
'rsrc/js/core/behavior-detect-timezone.js' => '78bc5d94',
'rsrc/js/core/behavior-device.js' => 'ac2b1e01',
@@ -570,7 +571,7 @@
'diffusion-css' => 'e46232d6',
'diffusion-icons-css' => '23b31a1b',
'diffusion-readme-css' => 'b68a76e4',
- 'diffusion-repository-css' => 'b89e8c6c',
+ 'diffusion-repository-css' => '6c7a1d8c',
'diviner-shared-css' => '4bd263b0',
'font-fontawesome' => '3883938a',
'font-lato' => '23631304',
@@ -600,6 +601,7 @@
'javelin-behavior-bulk-job-reload' => '3829a3cf',
'javelin-behavior-calendar-month-view' => '158c64e0',
'javelin-behavior-choose-control' => '04f8a1e3',
+ 'javelin-behavior-collapsiblejx' => '7072263b',
'javelin-behavior-comment-actions' => '4dffaeb2',
'javelin-behavior-config-reorder-fields' => '2539f834',
'javelin-behavior-conpherence-menu' => '8c2ed2bf',
@@ -1587,6 +1589,10 @@
'javelin-workflow',
'javelin-dom',
),
+ '7072263b' => array(
+ 'javelin-behavior',
+ 'javelin-dom',
+ ),
'727a5a61' => array(
'phuix-icon-view',
),
diff --git a/src/applications/diffusion/controller/DiffusionBrowseController.php b/src/applications/diffusion/controller/DiffusionBrowseController.php
--- a/src/applications/diffusion/controller/DiffusionBrowseController.php
+++ b/src/applications/diffusion/controller/DiffusionBrowseController.php
@@ -190,6 +190,10 @@
->setRequest($request)
->setDiffusionRequest($drequest);
+ if ($engine instanceof PHUIRemarkupView) {
+ $engine->setGenerateTableOfContents(true);
+ }
+
$corpus = $engine->newDocumentView($ref);
$this->corpusButtons[] = $this->renderFileButton();
diff --git a/src/applications/files/document/PhabricatorRemarkupDocumentEngine.php b/src/applications/files/document/PhabricatorRemarkupDocumentEngine.php
--- a/src/applications/files/document/PhabricatorRemarkupDocumentEngine.php
+++ b/src/applications/files/document/PhabricatorRemarkupDocumentEngine.php
@@ -36,6 +36,7 @@
$content = phutil_utf8ize($content);
$remarkup = new PHUIRemarkupView($viewer, $content);
+ $remarkup->setGenerateTableOfContents(true);
$container = phutil_tag(
'div',
diff --git a/src/applications/files/document/render/PhabricatorDocumentRenderingEngine.php b/src/applications/files/document/render/PhabricatorDocumentRenderingEngine.php
--- a/src/applications/files/document/render/PhabricatorDocumentRenderingEngine.php
+++ b/src/applications/files/document/render/PhabricatorDocumentRenderingEngine.php
@@ -208,12 +208,12 @@
$this->activeEngine = $engine;
$encode_setting = $request->getStr('encode');
- if (strlen($encode_setting)) {
+ if (phutil_nonempty_string($encode_setting)) {
$engine->setEncodingConfiguration($encode_setting);
}
$highlight_setting = $request->getStr('highlight');
- if (strlen($highlight_setting)) {
+ if (phutil_nonempty_string($highlight_setting)) {
$engine->setHighlightingConfiguration($highlight_setting);
}
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
@@ -459,6 +459,10 @@
$engine = self::newMarkupEngine(array());
$engine->setConfig('pygments.enabled', false);
break;
+ case 'remarkupField':
+ $engine = self::newMarkupEngine(array());
+ $engine->setConfig('header.generate-toc', true);
+ break;
default:
throw new Exception(pht('Unknown engine ruleset: %s!', $ruleset));
}
diff --git a/src/infrastructure/markup/PhabricatorMarkupOneOff.php b/src/infrastructure/markup/PhabricatorMarkupOneOff.php
--- a/src/infrastructure/markup/PhabricatorMarkupOneOff.php
+++ b/src/infrastructure/markup/PhabricatorMarkupOneOff.php
@@ -97,7 +97,11 @@
if ($this->engineRuleset) {
return PhabricatorMarkupEngine::getEngine($this->engineRuleset);
} else if ($this->preserveLinebreaks) {
- return PhabricatorMarkupEngine::getEngine();
+ $engine = PhabricatorMarkupEngine::getEngine();
+ if ($this->generateTableOfContents) {
+ $engine->setConfig('header.generate-toc', true);
+ }
+ return $engine;
} else {
return PhabricatorMarkupEngine::getEngine('nolinebreaks');
}
@@ -115,10 +119,11 @@
if ($this->getGenerateTableOfContents()) {
$toc = PhutilRemarkupHeaderBlockRule::renderTableOfContents($engine);
$this->tableOfContents = $toc;
+ $collapsible_index = $this->buildCollapsibleIndex($toc);
+ $output = phutil_implode_html("\n", array($collapsible_index, $output));
}
require_celerity_resource('phabricator-remarkup-css');
-
return phutil_tag(
'div',
array(
@@ -127,6 +132,57 @@
$output);
}
+ /**
+ * Build a collapsible table of contents display consisting of a
+ * screen-wide button to toggle the display, and the table of
+ * contents itself.
+ * @param PhutilSafeHTML $tocThe table of contents HTML.
+ * @return PhutilSafeHTML Div containing a button and the toc.
+ */
+ private function buildCollapsibleIndex($toc) {
+ $config = array(
+ 'container_id' => celerity_generate_unique_node_id(),
+ 'toggle_button_id' => celerity_generate_unique_node_id(),
+ 'button_icon' => array(
+ 'id' => celerity_generate_unique_node_id(),
+ 'open_class' => 'fa-folder',
+ 'close_class' => 'fa-folder-open',
+ ),
+ 'button_i18n' => array(
+ 'id' => celerity_generate_unique_node_id(),
+ 'open_text' => pht('Open Index'),
+ 'close_text' => pht('Close Index'),
+ ),
+ );
+
+ $button_icon = id(new PHUIIconView())
+ ->setID($config['button_icon']['id'])
+ ->setIcon($config['button_icon']['open_class']);
+
+ $button_text_span = phutil_tag(
+ 'span',
+ array('class' => 'collapsible', 'id' => $config['button_i18n']['id']),
+ $config['button_i18n']['open_text']);
+
+ $button = phutil_tag(
+ 'button',
+ array(
+ 'type' => 'button',
+ 'class' => 'collapsible',
+ 'id' => $config['toggle_button_id'],
+ ),
+ phutil_implode_html("\n", array($button_icon, $button_text_span)));
+
+ $toc_div = phutil_tag(
+ 'div',
+ array('class' => 'collapsible-content', 'id' => $config['container_id']),
+ $toc);
+
+ require_celerity_resource('font-fontawesome');
+ Javelin::initBehavior('collapsiblejx', $config);
+ return phutil_implode_html("\n", array($button, $toc_div));
+ }
+
public function shouldUseMarkupCache($field) {
if ($this->getDisableCache()) {
return false;
diff --git a/src/infrastructure/markup/blockrule/PhutilRemarkupHeaderBlockRule.php b/src/infrastructure/markup/blockrule/PhutilRemarkupHeaderBlockRule.php
--- a/src/infrastructure/markup/blockrule/PhutilRemarkupHeaderBlockRule.php
+++ b/src/infrastructure/markup/blockrule/PhutilRemarkupHeaderBlockRule.php
@@ -134,7 +134,7 @@
list($level, $name) = $info;
while ($depth < $level) {
- $toc[] = hsprintf('<ul>');
+ $toc[] = hsprintf('<ul class="remarkup-list">');
$depth++;
}
while ($depth > $level) {
diff --git a/src/infrastructure/markup/remarkup/__tests__/remarkup/interpreter-test.txt b/src/infrastructure/markup/remarkup/__tests__/remarkup/interpreter-test.txt
--- a/src/infrastructure/markup/remarkup/__tests__/remarkup/interpreter-test.txt
+++ b/src/infrastructure/markup/remarkup/__tests__/remarkup/interpreter-test.txt
@@ -30,9 +30,7 @@
Content: (content)
Argv: (x=y)
-
-
-<div class="remarkup-interpreter-error">No interpreter found: phutil_fake_test_block_interpreter</div>
+<p>phutil_fake_test_block_interpreter {{{ content }}}</p>
~~~~~~~~~~
Content: (content)
Argv: (foo=bar)
@@ -53,6 +51,4 @@
Content: (content)
Argv: (x=y)
-
-
-(No interpreter found: phutil_fake_test_block_interpreter)
+phutil_fake_test_block_interpreter {{{ content }}}
diff --git a/src/infrastructure/markup/view/PHUIRemarkupView.php b/src/infrastructure/markup/view/PHUIRemarkupView.php
--- a/src/infrastructure/markup/view/PHUIRemarkupView.php
+++ b/src/infrastructure/markup/view/PHUIRemarkupView.php
@@ -85,7 +85,7 @@
$content = PhabricatorMarkupEngine::renderOneObject(
$oneoff,
- 'default',
+ 'remarkupField',
$viewer,
$context);
diff --git a/webroot/rsrc/css/application/diffusion/diffusion-repository.css b/webroot/rsrc/css/application/diffusion/diffusion-repository.css
--- a/webroot/rsrc/css/application/diffusion/diffusion-repository.css
+++ b/webroot/rsrc/css/application/diffusion/diffusion-repository.css
@@ -11,3 +11,40 @@
.diffusion-panel-header-view.phui-header-shell {
padding: 8px 4px 8px 16px;
}
+
+button.collapsible {
+ background-color: {$blue.button.color};
+ border: none;
+ color: #FFFFFF;
+ cursor: pointer;
+ font-size: {$biggerfontsize};
+ outline: none;
+ padding: 18px;
+ text-align: left;
+ width: 100%;
+}
+
+button.collapsible:hover {
+ background-color: {$blue.button.hover};
+}
+
+.collapsible-content {
+ background-color: {$lightgreybackground};
+ display: none;
+ overflow: hidden;
+ padding: 0 18px;
+}
+
+/* The "first element" in a Remarkup page receives a "margin-top: 0".
+ This is normally OK, but ugly for the TOC, so we want to replace it.
+ That "first element" selector is very specific - to override it
+ we have to set important.
+ The "margin-bottom" is copied since the inherited value may change. */
+.collapsible-content > ul.remarkup-list {
+ margin-top: 12px !important;
+ margin-bottom: 12px;
+}
+
+.collapsible-content.collapsible-content-open {
+ display: block;
+}
diff --git a/webroot/rsrc/externals/javelin/docs/concepts/behaviors.diviner b/webroot/rsrc/externals/javelin/docs/concepts/behaviors.diviner
--- a/webroot/rsrc/externals/javelin/docs/concepts/behaviors.diviner
+++ b/webroot/rsrc/externals/javelin/docs/concepts/behaviors.diviner
@@ -38,7 +38,7 @@
lang=php
$config = array('hogName' => 'Ethel');
- JavelinHelper::initBehaviors('win-a-hog', $config);
+ Javelin::initBehavior('win-a-hog', $config);
Regardless, this will alert the user that they've won a hog (named Ethel, which
is a good name for a hog) when they load the page.
diff --git a/webroot/rsrc/js/core/behavior-collapsiblejx.js b/webroot/rsrc/js/core/behavior-collapsiblejx.js
new file mode 100644
--- /dev/null
+++ b/webroot/rsrc/js/core/behavior-collapsiblejx.js
@@ -0,0 +1,54 @@
+/**
+ * @provides javelin-behavior-collapsiblejx
+ * @requires javelin-behavior
+ * javelin-dom
+ *
+ * Given a collapsible div and a button to open and close it, call with:
+ *
+ * Javelin::initBehavior(
+ * 'collapsiblejx',
+ * array(
+ * 'container_id' => $theCollapsibleDivId,
+ * 'toggle_button_id' => $theButtonId,
+ * 'button_icon' => array(
+ * 'id' => $theButtonIconId,
+ * 'open_class' => 'fa-folder',
+ * 'close_class' => 'fa-folder-open',
+ * ),
+ * 'button_i18n' => array(
+ * 'id' => $theButtonTextId,
+ * 'open_text' => pht('Open Whatever This Is'),
+ * 'close_text' => pht('Close Whatever This Is'),
+ * ),
+ * )
+ * );
+ *
+ * button_icon and button_i18n are both optional. If you want either or
+ * none, that's fine.
+ *
+ */
+
+JX.behavior('collapsiblejx', function(config, statics) {
+ var open = false;
+ JX.Stratcom.listen(
+ 'click',
+ 'id:' + config.toggle_button_id,
+ function(e) {
+ var containerNode = JX.$(config.container_id);
+ open = !open;
+ JX.DOM.alterClass(containerNode, 'collapsible-content-open', open);
+
+ // If element is open, we want a close button, and vice-versa.
+ if ('button_icon' in config) {
+ var button = JX.$(config.button_icon.id);
+ JX.DOM.alterClass(button, config.button_icon.open_class, !open);
+ JX.DOM.alterClass(button, config.button_icon.close_class, open);
+ }
+
+ if ('button_i18n' in config) {
+ var btn_text = config.button_i18n[open ? 'close_text' : 'open_text'];
+ JX.$(config.button_i18n.id).innerText = btn_text;
+ }
+ }
+ );
+});

File Metadata

Mime Type
text/plain
Expires
Fri, Sep 20, 22:30 (16 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
893443
Default Alt Text
D25457.1726871433.diff (13 KB)

Event Timeline