mirror of
https://we.phorge.it/source/phorge.git
synced 2025-02-23 12:09:12 +01:00
Make some incremental improvements in Diviner
Summary: Gets TOC populated for articles, at least, and fixes a few other things. Test Plan: {F45474} Reviewers: chad Reviewed By: chad CC: aran Differential Revision: https://secure.phabricator.com/D6144
This commit is contained in:
parent
76c8705a27
commit
1433a035c6
11 changed files with 170 additions and 45 deletions
|
@ -33,7 +33,7 @@ final class DivinerAtomController extends DivinerController {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
$atom = id(new DivinerAtomQuery())
|
$symbol = id(new DivinerAtomQuery())
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withBookPHIDs(array($book->getPHID()))
|
->withBookPHIDs(array($book->getPHID()))
|
||||||
->withTypes(array($this->atomType))
|
->withTypes(array($this->atomType))
|
||||||
|
@ -43,31 +43,91 @@ final class DivinerAtomController extends DivinerController {
|
||||||
->needAtoms(true)
|
->needAtoms(true)
|
||||||
->executeOne();
|
->executeOne();
|
||||||
|
|
||||||
if (!$atom) {
|
if (!$symbol) {
|
||||||
return new Aphront404Response();
|
return new Aphront404Response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$atom = $symbol->getAtom();
|
||||||
|
|
||||||
$crumbs = $this->buildApplicationCrumbs();
|
$crumbs = $this->buildApplicationCrumbs();
|
||||||
|
|
||||||
$crumbs->addCrumb(
|
$crumbs->addCrumb(
|
||||||
id(new PhabricatorCrumbView())
|
id(new PhabricatorCrumbView())
|
||||||
->setName($book->getName())
|
->setName($book->getShortTitle())
|
||||||
->setHref('/book/'.$book->getName().'/'));
|
->setHref('/book/'.$book->getName().'/'));
|
||||||
|
|
||||||
|
$atom_short_title = $atom->getDocblockMetaValue(
|
||||||
|
'short',
|
||||||
|
$symbol->getTitle());
|
||||||
|
|
||||||
$crumbs->addCrumb(
|
$crumbs->addCrumb(
|
||||||
id(new PhabricatorCrumbView())
|
id(new PhabricatorCrumbView())
|
||||||
->setName($atom->getName()));
|
->setName($atom_short_title));
|
||||||
|
|
||||||
$header = id(new PhabricatorHeaderView())->setHeader($atom->getName());
|
$header = id(new PhabricatorHeaderView())
|
||||||
|
->setHeader($symbol->getTitle())
|
||||||
|
->addTag(
|
||||||
|
id(new PhabricatorTagView())
|
||||||
|
->setType(PhabricatorTagView::TYPE_STATE)
|
||||||
|
->setBackgroundColor(PhabricatorTagView::COLOR_BLUE)
|
||||||
|
->setName($this->renderAtomTypeName($atom->getType())));
|
||||||
|
|
||||||
|
$properties = id(new PhabricatorPropertyListView());
|
||||||
|
|
||||||
|
$group = $atom->getDocblockMetaValue('group');
|
||||||
|
if ($group) {
|
||||||
|
$group_name = $book->getGroupName($group);
|
||||||
|
} else {
|
||||||
|
$group_name = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$properties->addProperty(
|
||||||
|
pht('Defined'),
|
||||||
|
$atom->getFile().':'.$atom->getLine());
|
||||||
|
|
||||||
|
$field = 'default';
|
||||||
|
$engine = id(new PhabricatorMarkupEngine())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->addObject($symbol, $field)
|
||||||
|
->process();
|
||||||
|
|
||||||
|
$content = $engine->getOutput($symbol, $field);
|
||||||
|
|
||||||
|
$toc = $engine->getEngineMetadata(
|
||||||
|
$symbol,
|
||||||
|
$field,
|
||||||
|
PhutilRemarkupEngineRemarkupHeaderBlockRule::KEY_HEADER_TOC,
|
||||||
|
array());
|
||||||
|
|
||||||
$document = id(new PHUIDocumentView())
|
$document = id(new PHUIDocumentView())
|
||||||
|
->setBook($book->getTitle(), $group_name)
|
||||||
|
->setHeader($header)
|
||||||
|
->appendChild($properties)
|
||||||
->appendChild(
|
->appendChild(
|
||||||
phutil_tag(
|
phutil_tag(
|
||||||
'div',
|
'div',
|
||||||
array(
|
array(
|
||||||
'class' => 'phabricator-remarkup',
|
'class' => 'phabricator-remarkup',
|
||||||
),
|
),
|
||||||
phutil_safe_html($atom->getContent())));
|
array(
|
||||||
|
$content,
|
||||||
|
)));
|
||||||
|
|
||||||
|
if ($toc) {
|
||||||
|
$side = new PHUIListView();
|
||||||
|
$side->addMenuItem(
|
||||||
|
id(new PHUIListItemView())
|
||||||
|
->setName(pht('Contents'))
|
||||||
|
->setType(PHUIListItemView::TYPE_LABEL));
|
||||||
|
foreach ($toc as $key => $entry) {
|
||||||
|
$side->addMenuItem(
|
||||||
|
id(new PHUIListItemView())
|
||||||
|
->setName($entry[1])
|
||||||
|
->setHref('#'.$key));
|
||||||
|
}
|
||||||
|
|
||||||
|
$document->setSideNav($side);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->buildApplicationPage(
|
return $this->buildApplicationPage(
|
||||||
array(
|
array(
|
||||||
|
@ -75,10 +135,14 @@ final class DivinerAtomController extends DivinerController {
|
||||||
$document,
|
$document,
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'title' => $atom->getName(),
|
'title' => $symbol->getTitle(),
|
||||||
'dust' => true,
|
'dust' => true,
|
||||||
'device' => true,
|
'device' => true,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function renderAtomTypeName($name) {
|
||||||
|
return phutil_utf8_ucwords($name);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ final class DivinerBookController extends DivinerController {
|
||||||
|
|
||||||
$crumbs->addCrumb(
|
$crumbs->addCrumb(
|
||||||
id(new PhabricatorCrumbView())
|
id(new PhabricatorCrumbView())
|
||||||
->setName($book->getTitle())
|
->setName($book->getShortTitle())
|
||||||
->setHref('/book/'.$book->getName().'/'));
|
->setHref('/book/'.$book->getName().'/'));
|
||||||
|
|
||||||
$header = id(new PhabricatorHeaderView())->setHeader($book->getTitle());
|
$header = id(new PhabricatorHeaderView())->setHeader($book->getTitle());
|
||||||
|
@ -56,19 +56,7 @@ final class DivinerBookController extends DivinerController {
|
||||||
|
|
||||||
$out = array();
|
$out = array();
|
||||||
foreach ($groups as $group => $atoms) {
|
foreach ($groups as $group => $atoms) {
|
||||||
$group_info = idx($group_spec, $group);
|
$group_name = $book->getGroupName($group);
|
||||||
if (!is_array($group_info)) {
|
|
||||||
$group_info = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
$group_name = idx($group_info, 'name');
|
|
||||||
if (!strlen($group_name)) {
|
|
||||||
if (strlen($group)) {
|
|
||||||
$group_name = $group;
|
|
||||||
} else {
|
|
||||||
$group_name = pht('Free Radicals');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$out[] = id(new PhabricatorHeaderView())
|
$out[] = id(new PhabricatorHeaderView())
|
||||||
->setHeader($group_name);
|
->setHeader($group_name);
|
||||||
|
|
|
@ -113,14 +113,12 @@ final class DivinerLivePublisher extends DivinerPublisher {
|
||||||
->setGroupName($ref->getGroup());
|
->setGroupName($ref->getGroup());
|
||||||
|
|
||||||
if ($is_documentable) {
|
if ($is_documentable) {
|
||||||
$renderer = $this->getRenderer();
|
|
||||||
$content = $renderer->renderAtom($atom);
|
|
||||||
|
|
||||||
$storage = $this->loadAtomStorageForSymbol($symbol)
|
$storage = $this->loadAtomStorageForSymbol($symbol)
|
||||||
->setAtomData($atom->toDictionary())
|
->setAtomData($atom->toDictionary())
|
||||||
->setContent((string)phutil_safe_html($content))
|
->setContent(null)
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
|
$renderer = $this->getRenderer();
|
||||||
$summary = $renderer->renderAtomSummary($atom);
|
$summary = $renderer->renderAtomSummary($atom);
|
||||||
$summary = (string)phutil_safe_html($summary);
|
$summary = (string)phutil_safe_html($summary);
|
||||||
$symbol->setSummary($summary);
|
$symbol->setSummary($summary);
|
||||||
|
|
|
@ -182,12 +182,13 @@ final class DivinerDefaultRenderer extends DivinerRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getBlockMarkupEngine() {
|
protected function getBlockMarkupEngine() {
|
||||||
$engine = PhabricatorMarkupEngine::newMarkupEngine(
|
$engine = PhabricatorMarkupEngine::newMarkupEngine(array());
|
||||||
array(
|
|
||||||
'preserve-linebreaks' => false,
|
$engine->setConfig('preserve-linebreaks', false);
|
||||||
));
|
|
||||||
$engine->setConfig('viewer', new PhabricatorUser());
|
$engine->setConfig('viewer', new PhabricatorUser());
|
||||||
$engine->setConfig('diviner.renderer', $this);
|
$engine->setConfig('diviner.renderer', $this);
|
||||||
|
$engine->setConfig('header.generate-toc', true);
|
||||||
|
|
||||||
return $engine;
|
return $engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ final class DivinerLiveAtom extends DivinerDAO {
|
||||||
return array(
|
return array(
|
||||||
self::CONFIG_TIMESTAMPS => false,
|
self::CONFIG_TIMESTAMPS => false,
|
||||||
self::CONFIG_SERIALIZATION => array(
|
self::CONFIG_SERIALIZATION => array(
|
||||||
|
'content' => self::SERIALIZATION_JSON,
|
||||||
'atomData' => self::SERIALIZATION_JSON,
|
'atomData' => self::SERIALIZATION_JSON,
|
||||||
),
|
),
|
||||||
) + parent::getConfiguration();
|
) + parent::getConfiguration();
|
||||||
|
|
|
@ -35,6 +35,16 @@ final class DivinerLiveBook extends DivinerDAO
|
||||||
return $this->getConfig('title', $this->getName());
|
return $this->getConfig('title', $this->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getShortTitle() {
|
||||||
|
return $this->getConfig('short', $this->getTitle());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGroupName($group) {
|
||||||
|
$groups = $this->getConfig('groups');
|
||||||
|
$spec = idx($groups, $group, array());
|
||||||
|
return idx($spec, 'name', pht('Free Radicals'));
|
||||||
|
}
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
public function getCapabilities() {
|
public function getCapabilities() {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
final class DivinerLiveSymbol extends DivinerDAO
|
final class DivinerLiveSymbol extends DivinerDAO
|
||||||
implements PhabricatorPolicyInterface {
|
implements PhabricatorPolicyInterface, PhabricatorMarkupInterface {
|
||||||
|
|
||||||
protected $phid;
|
protected $phid;
|
||||||
protected $bookPHID;
|
protected $bookPHID;
|
||||||
|
@ -18,7 +18,6 @@ final class DivinerLiveSymbol extends DivinerDAO
|
||||||
protected $isDocumentable = 0;
|
protected $isDocumentable = 0;
|
||||||
|
|
||||||
private $book;
|
private $book;
|
||||||
private $content;
|
|
||||||
private $atom;
|
private $atom;
|
||||||
|
|
||||||
public function getConfiguration() {
|
public function getConfiguration() {
|
||||||
|
@ -45,13 +44,6 @@ final class DivinerLiveSymbol extends DivinerDAO
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getContent() {
|
|
||||||
if ($this->content === null) {
|
|
||||||
throw new Exception("Call attachAtom() before getContent()!");
|
|
||||||
}
|
|
||||||
return $this->content;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAtom() {
|
public function getAtom() {
|
||||||
if ($this->atom === null) {
|
if ($this->atom === null) {
|
||||||
throw new Exception("Call attachAtom() before getAtom()!");
|
throw new Exception("Call attachAtom() before getAtom()!");
|
||||||
|
@ -60,7 +52,6 @@ final class DivinerLiveSymbol extends DivinerDAO
|
||||||
}
|
}
|
||||||
|
|
||||||
public function attachAtom(DivinerLiveAtom $atom) {
|
public function attachAtom(DivinerLiveAtom $atom) {
|
||||||
$this->content = $atom->getContent();
|
|
||||||
$this->atom = DivinerAtom::newFromDictionary($atom->getAtomData());
|
$this->atom = DivinerAtom::newFromDictionary($atom->getAtomData());
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
@ -135,4 +126,41 @@ final class DivinerLiveSymbol extends DivinerDAO
|
||||||
return $this->getBook()->hasAutomaticCapability($capability, $viewer);
|
return $this->getBook()->hasAutomaticCapability($capability, $viewer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -( Markup Interface )--------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
public function getMarkupFieldKey($field) {
|
||||||
|
return $this->getPHID().':'.$field.':'.$this->getGraphHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function newMarkupEngine($field) {
|
||||||
|
$engine = PhabricatorMarkupEngine::newMarkupEngine(array());
|
||||||
|
|
||||||
|
$engine->setConfig('preserve-linebreaks', false);
|
||||||
|
// $engine->setConfig('diviner.renderer', new DivinerDefaultRenderer());
|
||||||
|
$engine->setConfig('header.generate-toc', true);
|
||||||
|
|
||||||
|
return $engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getMarkupText($field) {
|
||||||
|
return $this->getAtom()->getDocblockText();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function didMarkupText(
|
||||||
|
$field,
|
||||||
|
$output,
|
||||||
|
PhutilMarkupEngine $engine) {
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function shouldUseMarkupCache($field) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"name" : "phabricator",
|
"name" : "phabricator",
|
||||||
"title" : "Phabricator User Documentation",
|
"title" : "Phabricator User Documentation",
|
||||||
|
"short" : "Phabricator User Docs",
|
||||||
"root" : "../../../",
|
"root" : "../../../",
|
||||||
"groups" : {
|
"groups" : {
|
||||||
"intro" : {
|
"intro" : {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
@title Give Feedback! Get Support!
|
@title Give Feedback! Get Support!
|
||||||
|
@short Feedback/Support
|
||||||
@group intro
|
@group intro
|
||||||
|
|
||||||
How to give us feedback, report bugs, and request features, and get support for
|
How to give us feedback, report bugs, and request features, and get support for
|
||||||
|
|
|
@ -120,15 +120,17 @@ final class PhabricatorMarkupEngine {
|
||||||
|
|
||||||
// Load or build the preprocessor caches.
|
// Load or build the preprocessor caches.
|
||||||
$blocks = $this->loadPreprocessorCaches($engines, $objects);
|
$blocks = $this->loadPreprocessorCaches($engines, $objects);
|
||||||
|
$blocks = mpull($blocks, 'getCacheData');
|
||||||
|
|
||||||
|
$this->engineCaches = $blocks;
|
||||||
|
|
||||||
// Finalize the output.
|
// Finalize the output.
|
||||||
foreach ($objects as $key => $info) {
|
foreach ($objects as $key => $info) {
|
||||||
$data = $blocks[$key]->getCacheData();
|
|
||||||
$engine = $engines[$key];
|
$engine = $engines[$key];
|
||||||
$field = $info['field'];
|
$field = $info['field'];
|
||||||
$object = $info['object'];
|
$object = $info['object'];
|
||||||
|
|
||||||
$output = $engine->postprocessText($data);
|
$output = $engine->postprocessText($blocks[$key]);
|
||||||
$output = $object->didMarkupText($field, $output, $engine);
|
$output = $object->didMarkupText($field, $output, $engine);
|
||||||
$this->objects[$key]['output'] = $output;
|
$this->objects[$key]['output'] = $output;
|
||||||
}
|
}
|
||||||
|
@ -149,18 +151,47 @@ final class PhabricatorMarkupEngine {
|
||||||
*/
|
*/
|
||||||
public function getOutput(PhabricatorMarkupInterface $object, $field) {
|
public function getOutput(PhabricatorMarkupInterface $object, $field) {
|
||||||
$key = $this->getMarkupFieldKey($object, $field);
|
$key = $this->getMarkupFieldKey($object, $field);
|
||||||
|
$this->requireKeyProcessed($key);
|
||||||
|
|
||||||
|
return $this->objects[$key]['output'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve engine metadata for a given field.
|
||||||
|
*
|
||||||
|
* @param PhabricatorMarkupInterface The object to retrieve.
|
||||||
|
* @param string The field to retrieve.
|
||||||
|
* @param string The engine metadata field to retrieve.
|
||||||
|
* @param wild Optional default value.
|
||||||
|
* @task markup
|
||||||
|
*/
|
||||||
|
public function getEngineMetadata(
|
||||||
|
PhabricatorMarkupInterface $object,
|
||||||
|
$field,
|
||||||
|
$metadata_key,
|
||||||
|
$default = null) {
|
||||||
|
|
||||||
|
$key = $this->getMarkupFieldKey($object, $field);
|
||||||
|
$this->requireKeyProcessed($key);
|
||||||
|
|
||||||
|
return idx($this->engineCaches[$key]['metadata'], $metadata_key, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task markup
|
||||||
|
*/
|
||||||
|
private function requireKeyProcessed($key) {
|
||||||
if (empty($this->objects[$key])) {
|
if (empty($this->objects[$key])) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
"Call addObject() before getOutput() (key = '{$key}').");
|
"Call addObject() before using results (key = '{$key}').");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($this->objects[$key]['output'])) {
|
if (!isset($this->objects[$key]['output'])) {
|
||||||
throw new Exception(
|
throw new Exception(
|
||||||
"Call process() before getOutput().");
|
"Call process() before using results.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->objects[$key]['output'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,11 +21,13 @@ final class PHUIDocumentView extends AphrontTagView {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setSideNav(PHUIListView $list) {
|
public function setSideNav(PHUIListView $list) {
|
||||||
|
$list->setType(PHUIListView::SIDENAV_LIST);
|
||||||
$this->sidenav = $list;
|
$this->sidenav = $list;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setTopNav(PHUIListView $list) {
|
public function setTopNav(PHUIListView $list) {
|
||||||
|
$list->setType(PHUIListView::NAVBAR_LIST);
|
||||||
$this->topnav = $list;
|
$this->topnav = $list;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue