@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator

Make the Remarkup Help Page Extensible

Summary:
The Remarkup Help page is currently pointing to a HTML page on we.phorge.it.
Because of this it can not be customized/extended by custom extensions.
This diff allows you to implement a `RemarkupSyntaxDocumentationProvider` interface
to your custom class, which will implement a getDocumentation method.
This getDocumentation should return the custom help text in Remarkup format.
This diff also contains some extra help for the cowsay and figlet interpreters.
The local URLs for the local references are:
* /reference/remarkup/
* /reference/cowsay/
* /reference/figlet/

Closes T15401

Test Plan: Open the Phriction wiki editor and click on the Book (Remarkup Reference) icon in the toolbar and validate URL afterwards

Reviewers: O1 Blessed Committers, avivey

Reviewed By: O1 Blessed Committers, avivey

Subscribers: avivey, tobiaswiese, valerio.bozzolan, Matthew, Cigaryno

Maniphest Tasks: T15401

Differential Revision: https://we.phorge.it/D25698

+1256 -5
+19 -2
src/__phutil_library_map__.php
··· 436 436 'ConpherenceViewController' => 'applications/conpherence/controller/ConpherenceViewController.php', 437 437 'CountdownEditConduitAPIMethod' => 'applications/countdown/conduit/CountdownEditConduitAPIMethod.php', 438 438 'CountdownSearchConduitAPIMethod' => 'applications/countdown/conduit/CountdownSearchConduitAPIMethod.php', 439 + 'CowsayReferenceController' => 'applications/reference/src/controller/CowsayReferenceController.php', 439 440 'DarkConsoleController' => 'applications/console/controller/DarkConsoleController.php', 440 441 'DarkConsoleCore' => 'applications/console/core/DarkConsoleCore.php', 441 442 'DarkConsoleDataController' => 'applications/console/controller/DarkConsoleDataController.php', ··· 1304 1305 'FeedStoryNotificationGarbageCollector' => 'applications/notification/garbagecollector/FeedStoryNotificationGarbageCollector.php', 1305 1306 'FerretConfigurableSearchFunction' => 'applications/search/ferret/function/FerretConfigurableSearchFunction.php', 1306 1307 'FerretSearchFunction' => 'applications/search/ferret/function/FerretSearchFunction.php', 1308 + 'FigletReferenceController' => 'applications/reference/src/controller/FigletReferenceController.php', 1307 1309 'FileAllocateConduitAPIMethod' => 'applications/files/conduit/FileAllocateConduitAPIMethod.php', 1308 1310 'FileConduitAPIMethod' => 'applications/files/conduit/FileConduitAPIMethod.php', 1309 1311 'FileCreateMailReceiver' => 'applications/files/mail/FileCreateMailReceiver.php', ··· 5878 5880 'ProjectSearchConduitAPIMethod' => 'applications/project/conduit/ProjectSearchConduitAPIMethod.php', 5879 5881 'QueryFormattingTestCase' => 'infrastructure/storage/__tests__/QueryFormattingTestCase.php', 5880 5882 'QueryFuture' => 'infrastructure/storage/future/QueryFuture.php', 5883 + 'ReferenceApplication' => 'applications/reference/src/application/ReferenceApplication.php', 5884 + 'ReferenceController' => 'applications/reference/src/controller/ReferenceController.php', 5881 5885 'RemarkupProcessConduitAPIMethod' => 'applications/remarkup/conduit/RemarkupProcessConduitAPIMethod.php', 5886 + 'RemarkupReferenceController' => 'applications/reference/src/controller/RemarkupReferenceController.php', 5887 + 'RemarkupSyntaxDocumentationProvider' => 'infrastructure/markup/interface/RemarkupSyntaxDocumentationProvider.php', 5882 5888 'RemarkupValue' => 'applications/remarkup/RemarkupValue.php', 5883 5889 'RepositoryConduitAPIMethod' => 'applications/repository/conduit/RepositoryConduitAPIMethod.php', 5884 5890 'RepositoryQueryConduitAPIMethod' => 'applications/repository/conduit/RepositoryQueryConduitAPIMethod.php', ··· 6444 6450 'ConpherenceViewController' => 'ConpherenceController', 6445 6451 'CountdownEditConduitAPIMethod' => 'PhabricatorEditEngineAPIMethod', 6446 6452 'CountdownSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 6453 + 'CowsayReferenceController' => 'ReferenceController', 6447 6454 'DarkConsoleController' => 'PhabricatorController', 6448 6455 'DarkConsoleCore' => 'Phobject', 6449 6456 'DarkConsoleDataController' => 'PhabricatorController', ··· 7404 7411 'FeedStoryNotificationGarbageCollector' => 'PhabricatorGarbageCollector', 7405 7412 'FerretConfigurableSearchFunction' => 'FerretSearchFunction', 7406 7413 'FerretSearchFunction' => 'Phobject', 7414 + 'FigletReferenceController' => 'ReferenceController', 7407 7415 'FileAllocateConduitAPIMethod' => 'FileConduitAPIMethod', 7408 7416 'FileConduitAPIMethod' => 'ConduitAPIMethod', 7409 7417 'FileCreateMailReceiver' => 'PhabricatorApplicationMailReceiver', ··· 11211 11219 'PhabricatorRegistrationProfile' => 'Phobject', 11212 11220 'PhabricatorRemarkupCachePurger' => 'PhabricatorCachePurger', 11213 11221 'PhabricatorRemarkupControl' => 'AphrontFormTextAreaControl', 11214 - 'PhabricatorRemarkupCowsayBlockInterpreter' => 'PhutilRemarkupBlockInterpreter', 11222 + 'PhabricatorRemarkupCowsayBlockInterpreter' => array( 11223 + 'PhutilRemarkupBlockInterpreter', 11224 + 'RemarkupSyntaxDocumentationProvider', 11225 + ), 11215 11226 'PhabricatorRemarkupCustomBlockRule' => 'PhutilRemarkupBlockRule', 11216 11227 'PhabricatorRemarkupCustomInlineRule' => 'PhutilRemarkupRule', 11217 11228 'PhabricatorRemarkupDocumentEngine' => 'PhabricatorDocumentEngine', 11218 11229 'PhabricatorRemarkupEditField' => 'PhabricatorEditField', 11219 - 'PhabricatorRemarkupFigletBlockInterpreter' => 'PhutilRemarkupBlockInterpreter', 11230 + 'PhabricatorRemarkupFigletBlockInterpreter' => array( 11231 + 'PhutilRemarkupBlockInterpreter', 11232 + 'RemarkupSyntaxDocumentationProvider', 11233 + ), 11220 11234 'PhabricatorRemarkupHyperlinkEngineExtension' => 'PhutilRemarkupHyperlinkEngineExtension', 11221 11235 'PhabricatorRemarkupUIExample' => 'PhabricatorUIExample', 11222 11236 'PhabricatorRemoveEmailUserLogType' => 'PhabricatorUserLogType', ··· 12793 12807 'ProjectSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod', 12794 12808 'QueryFormattingTestCase' => 'PhabricatorTestCase', 12795 12809 'QueryFuture' => 'Future', 12810 + 'ReferenceApplication' => 'PhabricatorApplication', 12811 + 'ReferenceController' => 'PhabricatorController', 12796 12812 'RemarkupProcessConduitAPIMethod' => 'ConduitAPIMethod', 12813 + 'RemarkupReferenceController' => 'ReferenceController', 12797 12814 'RemarkupValue' => 'Phobject', 12798 12815 'RepositoryConduitAPIMethod' => 'ConduitAPIMethod', 12799 12816 'RepositoryQueryConduitAPIMethod' => 'RepositoryConduitAPIMethod',
+27
src/applications/reference/src/application/ReferenceApplication.php
··· 1 + <?php 2 + 3 + final class ReferenceApplication extends PhabricatorApplication { 4 + 5 + public function getName() { 6 + return pht('Reference'); 7 + } 8 + 9 + public function getIcon() { 10 + return 'fa-code'; 11 + } 12 + 13 + public function isUnlisted() { 14 + return true; 15 + } 16 + 17 + public function getRoutes() { 18 + return array( 19 + '/reference/' => array( 20 + 'remarkup/' => 'RemarkupReferenceController', 21 + 'cowsay/' => 'CowsayReferenceController', 22 + 'figlet/' => 'FigletReferenceController', 23 + ), 24 + ); 25 + } 26 + 27 + }
+291
src/applications/reference/src/controller/CowsayReferenceController.php
··· 1 + <?php 2 + 3 + final class CowsayReferenceController extends ReferenceController { 4 + private function getJokes() { 5 + $jokes = array(); 6 + $jokes[] = 7 + $jokes[] = 'Why did the team leader cross the road? To get to the'. 8 + ' other side and avoid responsibility.'; 9 + $jokes[] = "What do you call a mathematician who's afraid of". 10 + ' negative numbers? A coward.'; 11 + $jokes[] = 'Why did the sales person cross the road? To sell the'. 12 + ' chicken a new coop.'; 13 + $jokes[] = 'I told my doctor that I broke my arm in two places. He'. 14 + ' told me to stop going to those places.'; 15 + $jokes[] = 'Why do managers always carry a briefcase? So they have'. 16 + " something heavy to throw at their employees when they're not". 17 + ' meeting their targets.'; 18 + $jokes[] = 'What do you call a sales person with a conscience?'. 19 + ' Unemployed.'; 20 + $jokes[] = 'Why did the biologist bring a microscope to the party?'. 21 + ' Because she wanted to see things up close and personal.'; 22 + $jokes[] = "Why do IT guys like to work in the dark? Because it's". 23 + ' easier to hide their mistakes'; 24 + $jokes[] = 'How do you recognize a happy motorcyclist? By the bugs'. 25 + ' in his teeth.'; 26 + $jokes[] = 'Why did the tomato turn red? Because it saw the salad'. 27 + ' dressing.'; 28 + $jokes[] = 'Why did the engineer go to the beach? To build sand'. 29 + ' castles, of course.'; 30 + $jokes[] = "Why don't sales reps use trampolines? They never bounce". 31 + ' back from rejection.'; 32 + $jokes[] = "Why don't sales people play hide and seek? Because". 33 + ' nobody would look for them.'; 34 + $jokes[] = 'Why did the lumberjack break up with his girlfriend? She'. 35 + " couldn't handle his wood."; 36 + $jokes[] = 'I once went to a meeting that was so pointless, I'. 37 + ' started questioning the meaning of life...'; 38 + $jokes[] = 'How many sales people does it take to change a'. 39 + " lightbulb? None, they'll convince you the old one is still working". 40 + ' fine.'; 41 + $jokes[] = "What do you call an AI that can't learn from its". 42 + ' mistakes? A broken record.'; 43 + $jokes[] = 'Why did the engineer bring a ruler to bed? He wanted to'. 44 + ' see how long he could sleep.'; 45 + $jokes[] = "What did the sales rep say to the customer who couldn't". 46 + " afford the product? Don't worry, it's a steal!"; 47 + $jokes[] = "I just burned 2000 calories. That's the last time I". 48 + ' leave brownies in the oven while I nap.'; 49 + $jokes[] = 'Why was 6 afraid of 7? Because 7 8 9.'; 50 + $jokes[] = 'Why did the coffee file a police report? It got mugged.'; 51 + $jokes[] = 'Why did the plumber go to the opera? He wanted to see a'. 52 + ' show about pipe organs.'; 53 + $jokes[] = 'How many HR people does it take to change a light bulb?'. 54 + " None, they're too busy writing a policy on it."; 55 + $jokes[] = "What did the coffee say to the tea? You're too weak". 56 + ' for my taste.'; 57 + $jokes[] = 'Programmers are a unique breed of individuals who have'. 58 + ' the power to turn coffee into code.'; 59 + $jokes[] = 'What do you call an opera singer who can also fix a'. 60 + ' car? A mechanic.'; 61 + $jokes[] = "Dog owners are really the only people who think it's". 62 + " normal to pick up another species' poop."; 63 + $jokes[] = 'Why do some people bring a notebook to meetings? So'. 64 + " they can write down all the reasons they're never going to do any". 65 + ' of the things discussed in the meeting.'; 66 + $jokes[] = 'Why did the project manager go to the beach? To check'. 67 + ' if the tide was on schedule.'; 68 + $jokes[] = 'How many Nobel laureates does it take to change a'. 69 + ' lightbulb? Two. One to hold the lightbulb and the other to'. 70 + ' rotate the universe.'; 71 + $jokes[] = 'Why did the chemist bring a calculator to the party?'. 72 + ' Because she wanted to find the solution to every problem.'; 73 + $jokes[] = 'Why did the cyclist bring a ladder to the race? He'. 74 + ' wanted to get to the top of the podium.'; 75 + $jokes[] = "Why don't eggs tell jokes? They'd crack each other up."; 76 + $jokes[] = 'Why was the math book sad? It had too many problems.'; 77 + $jokes[] = "Trust me, this is a once-in-a-lifetime opportunity. 78 + It's like a unicorn, but with more broken promises."; 79 + $jokes[] = 'Why do programmers prefer dark mode? Because'. 80 + ' light attracts bugs.'; 81 + $jokes[] = "How many women does it take to change a lightbulb?'. 82 + ' None, they just sit in the dark and bitch about how they". 83 + " can't see anything!"; 84 + $jokes[] = "You won't find a better deal anywhere else, unless,". 85 + ' of course, you look on the internet.'; 86 + $jokes[] = 'How do you know if a programmer is extroverted?'. 87 + ' They stare at your shoes when they talk to you.'; 88 + $jokes[] = "\"I'm sorry\" and \"I apologize\" mean the same". 89 + " thing. Unless you're at a funeral."; 90 + $jokes[] = 'A man walks into a bar...ouch'; 91 + $jokes[] = 'Why do managers always have their hands in their'. 92 + " pockets? Because they're trying to find the key to their". 93 + " employees' motivation."; 94 + $jokes[] = "What do you call a brat who doesn't believe in". 95 + ' Santa? A rebel without a Claus.'; 96 + $jokes[] = 'How many programmers does it take to change a light'. 97 + " bulb? None, that's a hardware issue."; 98 + $jokes[] = 'How does NASA organize a party? They planet.'; 99 + $jokes[] = "I'm reading a book on anti-gravity. It's impossible". 100 + ' to put down.'; 101 + $jokes[] = "Why don't mathematicians get married? They'd always". 102 + ' be looking for a better half.'; 103 + $jokes[] = "What's an electrical engineer's favorite type of". 104 + ' exercise? Circuit training.'; 105 + $jokes[] = 'How does a CEO prepare for a presentation? By'. 106 + ' practicing his power-point-of-view.'; 107 + $jokes[] = 'Why did the salesman bring a ladder to the sales'. 108 + ' meeting? To reach his quota.'; 109 + $jokes[] = 'The special offer is like a regular offer, but'. 110 + ' with more glitter and less substance.'; 111 + $jokes[] = 'How does a project manager propose to his partner?'. 112 + ' \"Will you accept this project to marry me?\"'; 113 + $jokes[] = "Why did the programmer quit his job? He didn't". 114 + ' get arrays.'; 115 + $jokes[] = 'Why did the chemist take a piece of chalk to bed?'. 116 + ' To draw a conclusion.'; 117 + $jokes[] = "What's the difference between a sales person and a". 118 + ' mosquito? A mosquito stops sucking when you slap it.'; 119 + $jokes[] = "Why don't scientists trust atoms? Because they". 120 + ' make up everything.'; 121 + $jokes[] = 'Why do women have small feet? So they can stand'. 122 + ' closer to the kitchen sink.'; 123 + $jokes[] = 'I just ordered a chicken and an egg from Amazon.'. 124 + " I'll let you know."; 125 + $jokes[] = "Why don't help desk technicians go on vacation?". 126 + " Because they're afraid the users will break something while". 127 + " they're gone."; 128 + $jokes[] = "I'm on a seafood diet. I see food, I eat it."; 129 + $jokes[] = "What's the difference between a motorcycle and a". 130 + ' vacuum cleaner? The location of the dirtbag.'; 131 + $jokes[] = 'Why did the two 4s skip lunch? They already 8.'; 132 + $jokes[] = "What do you call a programmer who doesn't comment". 133 + ' their code? A future team leader.'; 134 + $jokes[] = 'Why did the cookie go to the doctor? Because he was'. 135 + ' feeling crumby.'; 136 + $jokes[] = "What's the difference between a poorly dressed man on". 137 + ' a unicycle and a well-dressed man on a bicycle? Attire.'; 138 + $jokes[] = 'Why did the statistician always carry a ruler to the'. 139 + ' party? He wanted to measure the standard deviation of the fun.'; 140 + $jokes[] = 'Why did the math teacher go to the beach? He wanted'. 141 + ' to work on his tan-gent.'; 142 + $jokes[] = 'What do you call a factory that makes okay products?'. 143 + ' A satisfactory.'; 144 + $jokes[] = 'Why did the philosopher refuse to buy a new calendar?'. 145 + ' He wanted to wait until the end of time.'; 146 + $jokes[] = 'Why do civil engineers refuse to play hide and seek?'. 147 + ' They always leave concrete evidence.'; 148 + $jokes[] = 'I told the help desk technician that my computer was'. 149 + " running slow, and he said, \"That's because it's trying to keep". 150 + ' up with your brain.\"'; 151 + $jokes[] = "What's the difference between a sales person and a". 152 + ' magician? A magician knows when to disappear.'; 153 + $jokes[] = 'Why did the sales rep sit on the photocopier? He wanted'. 154 + ' to make a good impression.'; 155 + $jokes[] = 'Why do scuba divers fall backwards off the boat?'. 156 + ' Because if they fell forward, they would still be in the boat.'; 157 + $jokes[] = "Why do some people love meetings? Because it's the". 158 + ' only time they can catch up on their sleep without getting fired.'; 159 + $jokes[] = 'What do you call fake spaghetti? An impasta.'; 160 + $jokes[] = 'Why did the electrical engineer become a comedian?'. 161 + ' They wanted to make light of the situation.'; 162 + $jokes[] = "Why do men like to play video games? Because it's the". 163 + ' only way they can win.'; 164 + $jokes[] = 'Why did the graduate cross the road? To prove to their'. 165 + " parents that they could make it on their own... even if it's just". 166 + ' to the other side of the street.'; 167 + $jokes[] = 'Why did the manufacturing operator get fired? He'. 168 + " couldn't even screw up the right way."; 169 + $jokes[] = "Why don't politicians campaign in cemeteries? Because". 170 + " they're afraid of waking the voters."; 171 + $jokes[] = 'What do you call a programmer who never makes'. 172 + ' mistakes? A liar.'; 173 + $jokes[] = 'Why did the manager go to the psychologist? Because'. 174 + ' he wanted to learn how to delegate his problems to someone else.'; 175 + $jokes[] = 'I sent my wife to the kitchen to make me a sandwich,'. 176 + " but she couldn't find it."; 177 + $jokes[] = "What rock group has four men who don't sing? Mount". 178 + ' Rushmore.'; 179 + $jokes[] = 'Why did the motorcycle go to the doctor? It was two'. 180 + ' tired.'; 181 + $jokes[] = "Why don't project managers make good cooks? They". 182 + ' always follow the recipe too closely and never improvise.'; 183 + $jokes[] = 'I told my wife she was drawing her eyebrows too high.'. 184 + ' She looked surprised.'; 185 + $jokes[] = 'If you think hunting is expensive, think of all the'. 186 + " money you'll save when your friends stop inviting you out to". 187 + ' dinner.'; 188 + $jokes[] = 'Why do meetings always start late? Because the boss'. 189 + " is too busy practicing his \"I'm important\" face in the mirror."; 190 + $jokes[] = "I've heard that smoking is a dying habit, but I". 191 + " didn't realize it was so literal."; 192 + $jokes[] = "I asked God for a bike, but I know God doesn't work". 193 + ' that way. So I stole a bike and asked for forgiveness.'; 194 + $jokes[] = "What do you call a project manager who doesn't believe". 195 + ' in deadlines? A myth.'; 196 + $jokes[] = 'Why do meetings feel like they last forever? Because'. 197 + " time flies when you're having fun."; 198 + $jokes[] = 'Why did the HR person become a detective? They'. 199 + ' wanted to solve the mystery of the missing stapler.'; 200 + $jokes[] = 'The IT guy at work seemingly vanished today.'. 201 + ' He ransomware.'; 202 + $jokes[] = 'My imaginary friend thinks I have problems.'; 203 + $jokes[] = "Why don't climate activists go on vacation? Because". 204 + " they're afraid the ice caps will melt while they're gone."; 205 + $jokes[] = 'Why do sales people wear slip-on shoes? You'. 206 + " don't need to tie something up if you're going to run away with it."; 207 + 208 + return $jokes; 209 + } 210 + 211 + public function getTitle() { 212 + return 'Cowsay reference'; 213 + } 214 + 215 + public function getContent() { 216 + $content = <<<EOTEXT 217 + = Cowsay reference 218 + == Templates 219 + EOTEXT; 220 + 221 + $root = dirname(phutil_get_library_root('phorge')); 222 + 223 + $directories = array( 224 + $root.'/externals/cowsay/cows/', 225 + $root.'/resources/cows/builtin/', 226 + $root.'/resources/cows/custom/', 227 + ); 228 + 229 + $jokes = $this->getJokes(); 230 + shuffle($jokes); 231 + 232 + $j = 0; 233 + 234 + foreach ($directories as $directory) { 235 + foreach (Filesystem::listDirectory($directory, false) as $cow_file) { 236 + $matches = null; 237 + if (!preg_match('/^(.*)\.cow$/', $cow_file, $matches)) { 238 + continue; 239 + } 240 + $cow_name = $matches[1]; 241 + $cow_name = phutil_utf8_strtolower($cow_name); 242 + 243 + $joke = $jokes[$j % count($jokes)]; 244 + 245 + $content .= "\n=== ".$cow_name; 246 + $content .= "\n```"; 247 + $content .= "\ncowsay(cow='".$cow_name."'){{{{$joke}}}}"; 248 + $content .= "\n```"; 249 + $content .= "\ncowsay(cow='".$cow_name."'){{{{$joke}}}}"; 250 + $content .= "\n"; 251 + 252 + $j++; 253 + } 254 + } 255 + 256 + $content .= "\n"; 257 + $content .= '== Parameters'; 258 + 259 + $joke = $jokes[$j % count($jokes)]; 260 + $j++; 261 + 262 + $content .= "\n=== eyes"; 263 + $content .= "\n```"; 264 + $content .= "\ncowsay(cow='cow', eyes='-x'){{{{$joke}}}}"; 265 + $content .= "\n```"; 266 + $content .= "\ncowsay(cow='cow', eyes='-x'){{{{$joke}}}}"; 267 + $content .= "\n"; 268 + 269 + $joke = $jokes[$j % count($jokes)]; 270 + $j++; 271 + 272 + $content .= "\n=== think"; 273 + $content .= "\n```"; 274 + $content .= "\ncowsay(cow='cow', think=1){{{{$joke}}}}"; 275 + $content .= "\n```"; 276 + $content .= "\ncowsay(cow='cow', think=1){{{{$joke}}}}"; 277 + $content .= "\n"; 278 + 279 + $joke = $jokes[$j % count($jokes)]; 280 + $j++; 281 + 282 + $content .= "\n=== tongue"; 283 + $content .= "\n```"; 284 + $content .= "\ncowsay(cow='cow', tongue=U){{{{$joke}}}}"; 285 + $content .= "\n```"; 286 + $content .= "\ncowsay(cow='cow', tongue=U){{{{$joke}}}}"; 287 + $content .= "\n"; 288 + 289 + return $content; 290 + } 291 + }
+39
src/applications/reference/src/controller/FigletReferenceController.php
··· 1 + <?php 2 + 3 + final class FigletReferenceController extends ReferenceController { 4 + public function getTitle() { 5 + return 'Figlet reference'; 6 + } 7 + 8 + public function getContent() { 9 + $content = <<<EOTEXT 10 + = Figlet reference 11 + == Fonts 12 + EOTEXT; 13 + 14 + $root = dirname(phutil_get_library_root('phorge')); 15 + 16 + $dirs = array( 17 + $root.'/externals/figlet/fonts/', 18 + $root.'/externals/pear-figlet/fonts/', 19 + $root.'/resources/figlet/custom/', 20 + ); 21 + 22 + foreach ($dirs as $dir) { 23 + foreach (Filesystem::listDirectory($dir, false) as $file) { 24 + if (preg_match('/\.flf$/', $file)) { 25 + $name = phutil_utf8_strtolower($file); 26 + $name = preg_replace('/\.flf$/', '', $name); 27 + $content .= "\n=== ".$name; 28 + $content .= "\n```"; 29 + $content .= "\nfiglet (font=".$name."){{{Great work!}}}"; 30 + $content .= "\n```"; 31 + $content .= "\nfiglet (font=".$name."){{{Great work!}}}"; 32 + $content .= "\n"; 33 + } 34 + } 35 + } 36 + 37 + return $content; 38 + } 39 + }
+75
src/applications/reference/src/controller/ReferenceController.php
··· 1 + <?php 2 + 3 + abstract class ReferenceController extends PhabricatorController { 4 + 5 + abstract public function getContent(); 6 + abstract public function getTitle(); 7 + 8 + public function handleRequest(AphrontRequest $request) { 9 + $request = $this->getRequest(); 10 + $viewer = $request->getViewer(); 11 + 12 + $content = $this->getContent(); 13 + 14 + $remarkup_view = id(new PHUIRemarkupView($viewer, $content)) 15 + ->setContextObject($this) 16 + ->setRemarkupOption('uri.same-window', true) 17 + ->setRemarkupOption(PHUIRemarkupView::OPTION_GENERATE_TOC, true) 18 + ->setRemarkupOption(PHUIRemarkupView::OPTION_PRESERVE_LINEBREAKS, false) 19 + ->setGenerateTableOfContents(true); 20 + 21 + $content = $remarkup_view->render(); 22 + 23 + $toc = $remarkup_view->getTableOfContents(); 24 + $toc = $this->formatToc($toc); 25 + 26 + $document = id(new PHUIDocumentView()) 27 + ->addClass('reference-documentation') 28 + ->setToc($toc) 29 + ->appendChild($remarkup_view); 30 + 31 + $crumbs = $this->buildApplicationCrumbs(); 32 + 33 + return $this->newPage() 34 + ->setTitle($this->getTitle()) 35 + ->setCrumbs($crumbs) 36 + ->appendChild($document); 37 + } 38 + 39 + protected function buildApplicationCrumbs() { 40 + $crumbs = array(); 41 + 42 + $application = $this->getCurrentApplication(); 43 + if ($application) { 44 + $icon = $application->getIcon(); 45 + if (!$icon) { 46 + $icon = 'fa-puzzle'; 47 + } 48 + 49 + $crumbs[] = id(new PHUICrumbView()) 50 + ->setName($this->getTitle()) 51 + ->setIcon($icon); 52 + } 53 + 54 + $view = new PHUICrumbsView(); 55 + foreach ($crumbs as $crumb) { 56 + $view->addCrumb($crumb); 57 + } 58 + 59 + return $view; 60 + } 61 + 62 + protected function formatToc($toc) { 63 + 64 + if ($toc) { 65 + $toc = phutil_tag_div('phui-document-toc-content', array( 66 + phutil_tag_div( 67 + 'phui-document-toc-header', 68 + pht('Contents')), 69 + $toc, 70 + )); 71 + } 72 + 73 + return $toc; 74 + } 75 + }
+762
src/applications/reference/src/controller/RemarkupReferenceController.php
··· 1 + <?php 2 + 3 + final class RemarkupReferenceController extends ReferenceController { 4 + public function getTitle() { 5 + return 'Remarkup reference'; 6 + } 7 + 8 + public function getContent() { 9 + $content = <<<EOTEXT 10 + = Remarkup Reference 11 + Explains how to make bold text; this makes your words louder so you can win 12 + arguments. 13 + 14 + = Overview = 15 + 16 + Phorge uses a lightweight markup language called "Remarkup", similar to 17 + other lightweight markup languages like Markdown and Wiki markup. 18 + 19 + This document describes how to format text using Remarkup. 20 + 21 + = Quick Reference = 22 + 23 + All the syntax is explained in more detail below, but this is a quick guide to 24 + formatting text in Remarkup. 25 + 26 + These are inline styles, and can be applied to most text: 27 + 28 + **bold** //italic// `monospaced` ##monospaced## ~~deleted~~ __underlined__ 29 + !!highlighted!! 30 + D123 T123 rX123 # Link to Objects 31 + {D123} {T123} # Link to Objects (Full Name) 32 + {F123} # Embed Images 33 + {M123} # Embed Pholio Mock 34 + @username # Mention a User 35 + #project # Mention a Project 36 + [[wiki page]] # Link to Phriction 37 + [[wiki page | name]] # Named link to Phriction 38 + http://xyz/ # Link to web 39 + [[http://xyz/ | name]] # Named link to web 40 + [name](http://xyz/) # Alternate Link 41 + 42 + These are block styles, and must be separated from surrounding text by 43 + empty lines: 44 + 45 + = Large Header = 46 + 47 + == Smaller Header == 48 + 49 + ## This is a Header As Well 50 + 51 + Also a Large Header 52 + =================== 53 + 54 + Also a Smaller Header 55 + --------------------- 56 + 57 + > Quoted Text 58 + 59 + Use `- ` or `* ` for bulleted lists, and `# ` for numbered lists. 60 + Use ``` or indent two spaces for code. 61 + Use %%% for a literal block. 62 + Use | ... | ... for tables. 63 + 64 + = Basic Styling = 65 + 66 + Format **basic text styles** like this: 67 + 68 + **bold text** 69 + //italic text// 70 + `monospaced text` 71 + ##monospaced text## 72 + ~~deleted text~~ 73 + __underlined text__ 74 + !!highlighted text!! 75 + 76 + Those produce **bold text**, //italic text//, `monospaced text`, ##monospaced 77 + text##, ~~deleted text~~, __underlined text__, and !!highlighted text!! 78 + respectively. 79 + 80 + = Layout = 81 + 82 + Make **headers** like this: 83 + 84 + = Large Header = 85 + 86 + == Smaller Header == 87 + 88 + ===== Very Small Header ===== 89 + 90 + Alternate Large Header 91 + ====================== 92 + 93 + Alternate Smaller Header 94 + ------------------------ 95 + 96 + You can optionally omit the trailing `=` signs -- that is, these are the same: 97 + 98 + == Smaller Header == 99 + 100 + == Smaller Header 101 + 102 + This produces headers like the ones in this document. Make sure you have an 103 + empty line before and after the header. 104 + 105 + Lists 106 + ===== 107 + 108 + Make **lists** by beginning each item with a `-` or a `*`: 109 + 110 + lang=text 111 + - milk 112 + - eggs 113 + - bread 114 + 115 + * duck 116 + * duck 117 + * goose 118 + 119 + This produces a list like this: 120 + 121 + - milk 122 + - eggs 123 + - bread 124 + 125 + (Note that you need to put a space after the `-` or `*`.) 126 + 127 + You can make numbered lists with a `#` instead of `-` or `*`: 128 + 129 + # Articuno 130 + # Zapdos 131 + # Moltres 132 + 133 + Numbered lists can also be started with `1.` or `1)`. If you use a number other 134 + than `1`, the list will start at that number instead. For example, this: 135 + 136 + ``` 137 + 200) OK 138 + 201) Created 139 + 202) Accepted 140 + ``` 141 + 142 + ...produces this: 143 + 144 + 200) OK 145 + 201) Created 146 + 202) Accepted 147 + 148 + You can also nest lists: 149 + 150 + ```- Body 151 + - Head 152 + - Arm 153 + - Elbow 154 + - Hand 155 + # Thumb 156 + # Index 157 + # Middle 158 + # Ring 159 + # Pinkie 160 + - Leg 161 + - Knee 162 + - Foot``` 163 + 164 + ...which produces: 165 + 166 + - Body 167 + - Head 168 + - Arm 169 + - Elbow 170 + - Hand 171 + # Thumb 172 + # Index 173 + # Middle 174 + # Ring 175 + # Pinkie 176 + - Leg 177 + - Knee 178 + - Foot 179 + 180 + If you prefer, you can indent lists using multiple characters to show indent 181 + depth, like this: 182 + 183 + ```- Tree 184 + -- Branch 185 + --- Twig``` 186 + 187 + As expected, this produces: 188 + 189 + - Tree 190 + -- Branch 191 + --- Twig 192 + 193 + You can add checkboxes to items by prefacing them with `[ ]` or `[X]`, like 194 + this: 195 + 196 + ``` 197 + - [X] Preheat oven to 450 degrees. 198 + - [ ] Zest 35 lemons. 199 + ``` 200 + 201 + When rendered, this produces: 202 + 203 + - [X] Preheat oven to 450 degrees. 204 + - [ ] Zest 35 lemons. 205 + 206 + Code Blocks 207 + =========== 208 + 209 + Make **code blocks** by indenting two spaces: 210 + 211 + f(x, y); 212 + 213 + You can also use three backticks to enclose the code block: 214 + 215 + ```f(x, y); 216 + g(f);``` 217 + 218 + You can specify a language for syntax highlighting with `lang=xxx`: 219 + 220 + lang=text 221 + lang=html 222 + <a href="#">...</a> 223 + 224 + When using fenced code blocks (triple backticks) you can simply append the 225 + language right after the backticks, like this: ##```html## 226 + 227 + This will highlight the block using a highlighter for that language, if one is 228 + available (in most cases, this means you need to configure Pygments): 229 + 230 + lang=html 231 + <a href="#">...</a> 232 + 233 + You can also use a `COUNTEREXAMPLE` header to show that a block of code is 234 + bad and shouldn't be copied: 235 + 236 + lang=text 237 + COUNTEREXAMPLE 238 + function f() { 239 + global \$\$variable_variable; 240 + } 241 + 242 + This produces a block like this: 243 + 244 + COUNTEREXAMPLE 245 + function f() { 246 + global \$\$variable_variable; 247 + } 248 + 249 + You can use `lines=N` to limit the vertical size of a chunk of code, and 250 + `name=some_name.ext` to give it a name. For example, this: 251 + 252 + lang=text 253 + lang=html, name=example.html, lines=12, counterexample 254 + ... 255 + 256 + ...produces this: 257 + 258 + lang=html, name=example.html, lines=12, counterexample 259 + <p>Apple</p> 260 + <p>Apricot</p> 261 + <p>Avocado</p> 262 + <p>Banana</p> 263 + <p>Bilberry</p> 264 + <p>Blackberry</p> 265 + <p>Blackcurrant</p> 266 + <p>Blueberry</p> 267 + <p>Currant</p> 268 + <p>Cherry</p> 269 + <p>Cherimoya</p> 270 + <p>Clementine</p> 271 + <p>Date</p> 272 + <p>Damson</p> 273 + <p>Durian</p> 274 + <p>Eggplant</p> 275 + <p>Elderberry</p> 276 + <p>Feijoa</p> 277 + <p>Gooseberry</p> 278 + <p>Grape</p> 279 + <p>Grapefruit</p> 280 + <p>Guava</p> 281 + <p>Huckleberry</p> 282 + <p>Jackfruit</p> 283 + <p>Jambul</p> 284 + <p>Kiwi fruit</p> 285 + <p>Kumquat</p> 286 + <p>Legume</p> 287 + <p>Lemon</p> 288 + <p>Lime</p> 289 + <p>Lychee</p> 290 + <p>Mandarine</p> 291 + <p>Mango</p> 292 + <p>Mangostine</p> 293 + <p>Melon</p> 294 + 295 + 296 + You can use the `NOTE:`, `WARNING:` or `IMPORTANT:` elements to call attention 297 + to an important idea. 298 + 299 + For example, write this: 300 + 301 + ``` 302 + NOTE: Best practices in proton pack operation include not crossing the streams. 303 + ``` 304 + 305 + ...to produce this: 306 + 307 + NOTE: Best practices in proton pack operation include not crossing the streams. 308 + 309 + Using `WARNING:` or `IMPORTANT:` at the beginning of the line changes the 310 + color of the callout: 311 + 312 + WARNING: Crossing the streams can result in total protonic reversal! 313 + 314 + IMPORTANT: Don't cross the streams! 315 + 316 + In addition, you can use `(NOTE)`, `(WARNING)`, or `(IMPORTANT)` to get the 317 + same effect but without `(NOTE)`, `(WARNING)`, or `(IMPORTANT)` appearing in 318 + the rendered result. For example, this callout uses `(NOTE)`: 319 + 320 + (NOTE) Dr. Egon Spengler is the best resource for additional proton pack 321 + questions. 322 + 323 + 324 + Dividers 325 + ======== 326 + 327 + You can divide sections by putting three or more dashes on a line by 328 + themselves. This creates a divider or horizontal rule similar to an `<hr />` 329 + tag, like this one: 330 + 331 + --- 332 + 333 + The dashes need to appear on their own line and be separated from other 334 + content. For example, like this: 335 + 336 + ``` 337 + This section will be visually separated. 338 + 339 + --- 340 + 341 + On an entirely different topic, ... 342 + ``` 343 + 344 + 345 + = Linking URIs = 346 + 347 + URIs are automatically linked: http://phorge.it/ 348 + 349 + If you have a URI with problematic characters in it, like 350 + "`http://comma.org/,`", you can surround it with angle brackets: 351 + 352 + <http://comma.org/,> 353 + 354 + This will force the parser to consume the whole URI: <http://comma.org/,> 355 + 356 + You can also use create named links, where you choose the displayed text. These 357 + work within Phorge or on the internet at large: 358 + 359 + [[/herald/transcript/ | Herald Transcripts]] 360 + [[http://www.boring-legal-documents.com/ | exciting legal documents]] 361 + 362 + Markdown-style links are also supported: 363 + 364 + [Toil](http://www.trouble.com) 365 + 366 + = Linking to Objects = 367 + 368 + You can link to Phorge objects, such as Differential revisions, Diffusion 369 + commits and Maniphest tasks, by mentioning the name of an object: 370 + 371 + D123 # Link to Differential revision D123 372 + rX123 # Link to SVN commit 123 from the "X" repository 373 + rXaf3192cd5 # Link to Git commit "af3192cd5..." from the "X" repository. 374 + # You must specify at least 7 characters of the hash. 375 + T123 # Link to Maniphest task T123 376 + 377 + You can also link directly to a comment in Maniphest and Differential (these 378 + can be found on the date stamp of any transaction/comment): 379 + 380 + T123#412 # Link to comment id #412 of task T123 381 + 382 + See the Phorge configuration setting `remarkup.ignored-object-names` to 383 + modify this behavior. 384 + 385 + = Embedding Objects 386 + 387 + You can also generate full-name references to some objects by using braces: 388 + 389 + {D123} # Link to Differential revision D123 with the full name 390 + {T123} # Link to Maniphest task T123 with the full name 391 + 392 + These references will also show when an object changes state (for instance, a 393 + task or revision is closed). Some types of objects support rich embedding. 394 + 395 + == Linking to Project Tags 396 + 397 + Projects can be linked to with the use of a hashtag `#`. This works by default 398 + using the name of the Project (lowercase, underscored). Additionally you 399 + can set multiple additional hashtags by editing the Project details. 400 + 401 + #qa, #quality_assurance 402 + 403 + == Embedding Mocks (Pholio) 404 + 405 + You can embed a Pholio mock by using braces to refer to it: 406 + 407 + {M123} 408 + 409 + By default the first four images from the mock set are displayed. This behavior 410 + can be overridden with the **image** option. With the **image** option you can 411 + provide one or more image IDs to display. 412 + 413 + You can set the image (or images) to display like this: 414 + 415 + {M123, image=12345} 416 + {M123, image=12345 & 6789} 417 + 418 + == Embedding Pastes 419 + 420 + You can embed a Paste using braces: 421 + 422 + {P123} 423 + 424 + You can adjust the embed height with the `lines` option: 425 + 426 + {P123, lines=15} 427 + 428 + You can highlight specific lines with the `highlight` option: 429 + 430 + {P123, highlight=15} 431 + {P123, highlight="23-25, 31"} 432 + 433 + == Embedding Images 434 + 435 + You can embed an image or other file by using braces to refer to it: 436 + 437 + {F123} 438 + 439 + In most interfaces, you can drag-and-drop an image from your computer into the 440 + text area to upload and reference it. 441 + 442 + Some browsers (e.g. Chrome) support uploading an image data just by pasting them 443 + from clipboard into the text area. 444 + 445 + You can set file display options like this: 446 + 447 + {F123, layout=left, float, size=full, alt="a duckling"} 448 + 449 + Valid options for all files are: 450 + 451 + - **layout** left (default), center, right, inline, link (render a link 452 + instead of a thumbnail for images) 453 + - **name** with `layout=link` or for non-images, use this name for the link 454 + text 455 + - **alt** Provide alternate text for assistive technologies. 456 + 457 + Image files support these options: 458 + 459 + - **float** If layout is set to left or right, the image will be floated so 460 + text wraps around it. 461 + - **size** thumb (default), full 462 + - **width** Scale image to a specific width. 463 + - **height** Scale image to a specific height. 464 + 465 + Audio and video files support these options: 466 + 467 + - **media**: Specify the media type as `audio` or `video`. This allows you 468 + to disambiguate how file format which may contain either audio or video 469 + should be rendered. 470 + - **loop**: Loop this media. 471 + - **autoplay**: Automatically begin playing this media. 472 + 473 + == Embedding Countdowns 474 + 475 + You can embed a countdown by using braces: 476 + 477 + {C123} 478 + 479 + = Quoting Text = 480 + 481 + To quote text, preface it with an `>`: 482 + 483 + > This is quoted text. 484 + 485 + This appears like this: 486 + 487 + > This is quoted text. 488 + 489 + = Embedding Media = 490 + 491 + If you set a configuration flag, you can embed media directly in text: 492 + 493 + - **remarkup.enable-embedded-youtube**: allows you to paste in YouTube videos 494 + and have them render inline. 495 + 496 + This option is disabled by default because it has security and/or 497 + silliness implications. Carefully read the description before enabling it. 498 + 499 + = Image Macros = 500 + 501 + You can upload image macros (More Stuff -> Macro) which will replace text 502 + strings with the image you specify. For instance, you could upload an image of a 503 + dancing banana to create a macro named "peanutbutterjellytime", and then any 504 + time you type that string on a separate line it will be replaced with the image 505 + of a dancing banana. 506 + 507 + = Memes = 508 + 509 + You can also use image macros in the context of memes. For example, if you 510 + have an image macro named `grumpy`, you can create a meme by doing the 511 + following: 512 + 513 + {meme, src = grumpy, above = toptextgoeshere, below = bottomtextgoeshere} 514 + 515 + By default, the font used to create the text for the meme is `tuffy.ttf`. For 516 + the more authentic feel of `impact.ttf`, you simply have to place the Impact 517 + TrueType font in the Phorge subfolder `/resources/font/`. If Remarkup 518 + detects the presence of `impact.ttf`, it will automatically use it. 519 + 520 + = Mentioning Users = 521 + 522 + In Differential and Maniphest, you can mention another user by writing: 523 + 524 + @username 525 + 526 + When you submit your comment, this will add them as a CC on the revision or task 527 + if they aren't already CC'd. 528 + 529 + Icons 530 + ===== 531 + 532 + You can add icons to comments using the `{icon ...}` syntax. For example: 533 + 534 + {icon camera} 535 + 536 + This renders: {icon camera} 537 + 538 + You can select a color for icons: 539 + 540 + {icon camera color=blue} 541 + 542 + This renders: {icon camera color=blue} 543 + 544 + For a list of available icons and colors, check the UIExamples application. 545 + (The icons are sourced from 546 + [[ https://fontawesome.com/v4.7.0/icons/ | FontAwesome ]], so you can also 547 + browse the collection there.) 548 + 549 + You can add `spin` to make the icon spin: 550 + 551 + {icon cog spin} 552 + 553 + This renders: {icon cog spin} 554 + 555 + 556 + = Phriction Documents = 557 + 558 + You can link to Phriction documents with a name or path: 559 + 560 + Make sure you sign and date your [[legal/Letter of Marque and Reprisal]]! 561 + 562 + By default, the link will render with the document title as the link name. 563 + With a pipe (`|`), you can retitle the link. Use this to mislead your 564 + opponents: 565 + 566 + Check out these [[legal/boring_documents/ | exciting legal documents]]! 567 + 568 + Links to pages which do not exist are shown in red. Links to pages which exist 569 + but which the viewer does not have permission to see are shown with a lock 570 + icon, and the link will not disclose the page title. 571 + 572 + If you begin a link path with `./` or `../`, the remainder of the path will be 573 + evaluated relative to the current wiki page. For example, if you are writing 574 + content for the document `fruit/` a link to `[[./guava]]` is the same as a link 575 + to `[[fruit/guava]]` from elsewhere. 576 + 577 + Relative links may use `../` to transverse up the document tree. From the 578 + `produce/vegetables/` page, you can use `[[../fruit/guava]]` to link to the 579 + `produce/fruit/guava` page. 580 + 581 + Relative links do not work when used outside of wiki pages. For example, 582 + you can't use a relative link in a comment on a task, because there is no 583 + reasonable place for the link to start resolving from. 584 + 585 + When documents are moved, relative links are not automatically updated: they 586 + are preserved as currently written. After moving a document, you may need to 587 + review and adjust any relative links it contains. 588 + 589 + 590 + = Literal Blocks = 591 + 592 + To place text in a literal block use `%%%`: 593 + 594 + %%%Text that won't be processed by remarkup 595 + [[http://www.example.com | example]] 596 + %%% 597 + 598 + Remarkup will not process the text inside of literal blocks (other than to 599 + escape HTML and preserve line breaks). 600 + 601 + = Tables = 602 + 603 + Remarkup supports simple table syntax. For example, this: 604 + 605 + ``` 606 + | Fruit | Color | Price | Peel? 607 + | ----- | ----- | ----- | ----- 608 + | Apple | red | `\$0.93` | no 609 + | Banana | yellow | `\$0.19` | **YES** 610 + ``` 611 + 612 + ...produces this: 613 + 614 + | Fruit | Color | Price | Peel? 615 + | ----- | ----- | ----- | ----- 616 + | Apple | red | `\$0.93` | no 617 + | Banana | yellow | `\$0.19` | **YES** 618 + 619 + Remarkup also supports a simplified HTML table syntax. For example, this: 620 + 621 + ``` 622 + <table> 623 + <tr> 624 + <th>Fruit</th> 625 + <th>Color</th> 626 + <th>Price</th> 627 + <th>Peel?</th> 628 + </tr> 629 + <tr> 630 + <td>Apple</td> 631 + <td>red</td> 632 + <td>`\$0.93`</td> 633 + <td>no</td> 634 + </tr> 635 + <tr> 636 + <td>Banana</td> 637 + <td>yellow</td> 638 + <td>`\$0.19`</td> 639 + <td>**YES**</td> 640 + </tr> 641 + </table> 642 + ``` 643 + 644 + ...produces this: 645 + 646 + <table> 647 + <tr> 648 + <th>Fruit</th> 649 + <th>Color</th> 650 + <th>Price</th> 651 + <th>Peel?</th> 652 + </tr> 653 + <tr> 654 + <td>Apple</td> 655 + <td>red</td> 656 + <td>`\$0.93`</td> 657 + <td>no</td> 658 + </tr> 659 + <tr> 660 + <td>Banana</td> 661 + <td>yellow</td> 662 + <td>`\$0.19`</td> 663 + <td>**YES**</td> 664 + </tr> 665 + </table> 666 + 667 + Some general notes about this syntax: 668 + 669 + - your tags must all be properly balanced; 670 + - your tags must NOT include attributes (`<td>` is OK, `<td style="...">` is 671 + not); 672 + - you can use other Remarkup rules (like **bold**, //italics//, etc.) inside 673 + table cells. 674 + 675 + Navigation Sequences 676 + ==================== 677 + 678 + You can use `{nav ...}` to render a stylized navigation sequence when helping 679 + someone to locate something. This can be useful when writing documentation. 680 + For example, you could give someone directions to purchase lemons: 681 + 682 + {nav icon=home, name=Home > 683 + Grocery Store > 684 + Produce Section > 685 + icon=lemon-o, name=Lemons} 686 + 687 + To render this example, use this markup: 688 + 689 + ``` 690 + {nav icon=home, name=Home > 691 + Grocery Store > 692 + Produce Section > 693 + icon=lemon-o, name=Lemons} 694 + ``` 695 + 696 + In general: 697 + 698 + - Separate sections with `>`. 699 + - Each section can just have a name to add an element to the navigation 700 + sequence, or a list of key-value pairs. 701 + - Supported keys are `icon`, `name`, `type` and `href`. 702 + - The `type` option can be set to `instructions` to indicate that an element 703 + is asking the user to make a choice or follow specific instructions. 704 + 705 + Keystrokes 706 + ========== 707 + 708 + You can use `{key ...}` to render a stylized keystroke. For example, this: 709 + 710 + ``` 711 + Press {key M} to view the starmap. 712 + ``` 713 + 714 + ...renders this: 715 + 716 + > Press {key M} to view the starmap. 717 + 718 + You can also render sequences with modifier keys. This: 719 + 720 + ``` 721 + Use {key command option shift 3} to take a screenshot. 722 + Press {key down down-right right LP} to activate the hadoken technique. 723 + ``` 724 + 725 + ...renders this: 726 + 727 + > Use {key command option shift 3} to take a screenshot. 728 + > Press {key down down-right right LP} to activate the hadoken technique. 729 + 730 + 731 + Anchors 732 + ======== 733 + 734 + You can use `{anchor #xyz}` to create a document anchor and later link to 735 + it directly with `#xyz` in the URI. 736 + 737 + Headers also automatically create named anchors. 738 + 739 + If you navigate to `#xyz` in your browser location bar, the page will scroll 740 + to the first anchor with "xyz" as a prefix of the anchor name. 741 + 742 + 743 + = Fullscreen Mode = 744 + 745 + Remarkup editors provide a fullscreen composition mode. This can make it easier 746 + to edit large blocks of text, or improve focus by removing distractions. You can 747 + exit **Fullscreen** mode by clicking the button again or by pressing escape. 748 + EOTEXT; 749 + 750 + $remarkup_syntax_documentation_providers = id(new PhutilClassMapQuery()) 751 + ->setAncestorClass('RemarkupSyntaxDocumentationProvider') 752 + ->execute(); 753 + 754 + // add custom Remarkup help 755 + $content .= "\r\n\r\n"; 756 + foreach ($remarkup_syntax_documentation_providers as $doc_provider) { 757 + $content .= $doc_provider->getDocumentation()."\r\n\r\n"; 758 + } 759 + 760 + return $content; 761 + } 762 + }
+5
src/infrastructure/markup/interface/RemarkupSyntaxDocumentationProvider.php
··· 1 + <?php 2 + 3 + interface RemarkupSyntaxDocumentationProvider { 4 + public function getDocumentation(); 5 + }
+20 -1
src/infrastructure/markup/interpreter/PhabricatorRemarkupCowsayBlockInterpreter.php
··· 1 1 <?php 2 2 3 3 final class PhabricatorRemarkupCowsayBlockInterpreter 4 - extends PhutilRemarkupBlockInterpreter { 4 + extends PhutilRemarkupBlockInterpreter 5 + implements RemarkupSyntaxDocumentationProvider { 5 6 6 7 public function getInterpreterName() { 7 8 return 'cowsay'; ··· 69 70 } 70 71 71 72 return $map; 73 + } 74 + 75 + public function getDocumentation() { 76 + return <<<EOT 77 + = Cowsay 78 + 79 + Cowsay is an application by Tony Monroe which has been ported over to 80 + Phabricator/Phorge to allow your comments to be voiced by 81 + a cow. 82 + 83 + A basic example of using cowsay would be to add a comment 84 + cowsay{{{Why don't they play poker in the jungle? Too many cheetahs}}} 85 + which generates: 86 + 87 + cowsay{{{Why don't they play poker in the jungle? Too many cheetahs}}} 88 + 89 + More information about Cowsay can be found [[/reference/cowsay/ | here]] 90 + EOT; 72 91 } 73 92 74 93 }
+17 -1
src/infrastructure/markup/interpreter/PhabricatorRemarkupFigletBlockInterpreter.php
··· 1 1 <?php 2 2 3 3 final class PhabricatorRemarkupFigletBlockInterpreter 4 - extends PhutilRemarkupBlockInterpreter { 4 + extends PhutilRemarkupBlockInterpreter 5 + implements RemarkupSyntaxDocumentationProvider { 5 6 6 7 public function getInterpreterName() { 7 8 return 'figlet'; ··· 68 69 return $map; 69 70 } 70 71 72 + public function getDocumentation() { 73 + return <<<EOT 74 + = Figlet 75 + The `figlet` interpreter allows you to write some large text. 76 + For example, this: 77 + 78 + ```figlet{{{Some big text!}}}``` 79 + 80 + ...produces this: 81 + 82 + figlet{{{Some big text!}}} 83 + 84 + More information about Figlet can be found [[/reference/figlet/ | here]] 85 + EOT; 86 + } 71 87 }
+1 -1
src/view/form/control/PhabricatorRemarkupControl.php
··· 255 255 $actions['fa-book'] = array( 256 256 'tip' => pht('Help'), 257 257 'align' => 'right', 258 - 'href' => PhabricatorEnv::getDoclink('Remarkup Reference'), 258 + 'href' => '/reference/remarkup/', 259 259 ); 260 260 261 261 $mode_actions = array();