Add a {key ..} Remarkup rule for discussing keystrokes
Summary: Ruleset for styles in D16506.
Test Plan: {F1803883}
Reviewers: chad
Reviewed By: chad
Differential Revision: https://secure.phabricator.com/D16510
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
return array(
|
return array(
|
||||||
'names' => array(
|
'names' => array(
|
||||||
'core.pkg.css' => '6791587e',
|
'core.pkg.css' => 'd28c0515',
|
||||||
'core.pkg.js' => '1d376fa9',
|
'core.pkg.js' => '1d376fa9',
|
||||||
'darkconsole.pkg.js' => 'e7393ebb',
|
'darkconsole.pkg.js' => 'e7393ebb',
|
||||||
'differential.pkg.css' => '3fb7f532',
|
'differential.pkg.css' => '3fb7f532',
|
||||||
@@ -105,7 +105,7 @@ return array(
|
|||||||
'rsrc/css/application/tokens/tokens.css' => '3d0f239e',
|
'rsrc/css/application/tokens/tokens.css' => '3d0f239e',
|
||||||
'rsrc/css/application/uiexample/example.css' => '528b19de',
|
'rsrc/css/application/uiexample/example.css' => '528b19de',
|
||||||
'rsrc/css/core/core.css' => 'd0801452',
|
'rsrc/css/core/core.css' => 'd0801452',
|
||||||
'rsrc/css/core/remarkup.css' => '9905d6c4',
|
'rsrc/css/core/remarkup.css' => 'cd912f2c',
|
||||||
'rsrc/css/core/syntax.css' => '769d3498',
|
'rsrc/css/core/syntax.css' => '769d3498',
|
||||||
'rsrc/css/core/z-index.css' => '2b01a823',
|
'rsrc/css/core/z-index.css' => '2b01a823',
|
||||||
'rsrc/css/diviner/diviner-shared.css' => 'aa3656aa',
|
'rsrc/css/diviner/diviner-shared.css' => 'aa3656aa',
|
||||||
@@ -792,7 +792,7 @@ return array(
|
|||||||
'phabricator-object-selector-css' => '85ee8ce6',
|
'phabricator-object-selector-css' => '85ee8ce6',
|
||||||
'phabricator-phtize' => 'd254d646',
|
'phabricator-phtize' => 'd254d646',
|
||||||
'phabricator-prefab' => 'cfd23f37',
|
'phabricator-prefab' => 'cfd23f37',
|
||||||
'phabricator-remarkup-css' => '9905d6c4',
|
'phabricator-remarkup-css' => 'cd912f2c',
|
||||||
'phabricator-search-results-css' => '7dea472c',
|
'phabricator-search-results-css' => '7dea472c',
|
||||||
'phabricator-shaped-request' => '7cbe244b',
|
'phabricator-shaped-request' => '7cbe244b',
|
||||||
'phabricator-slowvote-css' => 'a94b7230',
|
'phabricator-slowvote-css' => 'a94b7230',
|
||||||
|
|||||||
@@ -2707,6 +2707,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorJiraIssueHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorJiraIssueHasObjectEdgeType.php',
|
'PhabricatorJiraIssueHasObjectEdgeType' => 'applications/doorkeeper/edge/PhabricatorJiraIssueHasObjectEdgeType.php',
|
||||||
'PhabricatorJumpNavHandler' => 'applications/search/engine/PhabricatorJumpNavHandler.php',
|
'PhabricatorJumpNavHandler' => 'applications/search/engine/PhabricatorJumpNavHandler.php',
|
||||||
'PhabricatorKeyValueDatabaseCache' => 'applications/cache/PhabricatorKeyValueDatabaseCache.php',
|
'PhabricatorKeyValueDatabaseCache' => 'applications/cache/PhabricatorKeyValueDatabaseCache.php',
|
||||||
|
'PhabricatorKeyboardRemarkupRule' => 'infrastructure/markup/rule/PhabricatorKeyboardRemarkupRule.php',
|
||||||
'PhabricatorKeyring' => 'applications/files/keyring/PhabricatorKeyring.php',
|
'PhabricatorKeyring' => 'applications/files/keyring/PhabricatorKeyring.php',
|
||||||
'PhabricatorKeyringConfigOptionType' => 'applications/files/keyring/PhabricatorKeyringConfigOptionType.php',
|
'PhabricatorKeyringConfigOptionType' => 'applications/files/keyring/PhabricatorKeyringConfigOptionType.php',
|
||||||
'PhabricatorLDAPAuthProvider' => 'applications/auth/provider/PhabricatorLDAPAuthProvider.php',
|
'PhabricatorLDAPAuthProvider' => 'applications/auth/provider/PhabricatorLDAPAuthProvider.php',
|
||||||
@@ -7532,6 +7533,7 @@ phutil_register_library_map(array(
|
|||||||
'PhabricatorJiraIssueHasObjectEdgeType' => 'PhabricatorEdgeType',
|
'PhabricatorJiraIssueHasObjectEdgeType' => 'PhabricatorEdgeType',
|
||||||
'PhabricatorJumpNavHandler' => 'Phobject',
|
'PhabricatorJumpNavHandler' => 'Phobject',
|
||||||
'PhabricatorKeyValueDatabaseCache' => 'PhutilKeyValueCache',
|
'PhabricatorKeyValueDatabaseCache' => 'PhutilKeyValueCache',
|
||||||
|
'PhabricatorKeyboardRemarkupRule' => 'PhutilRemarkupRule',
|
||||||
'PhabricatorKeyring' => 'Phobject',
|
'PhabricatorKeyring' => 'Phobject',
|
||||||
'PhabricatorKeyringConfigOptionType' => 'PhabricatorConfigJSONOptionType',
|
'PhabricatorKeyringConfigOptionType' => 'PhabricatorConfigJSONOptionType',
|
||||||
'PhabricatorLDAPAuthProvider' => 'PhabricatorAuthProvider',
|
'PhabricatorLDAPAuthProvider' => 'PhabricatorAuthProvider',
|
||||||
|
|||||||
@@ -688,6 +688,32 @@ In general:
|
|||||||
- The `type` option can be set to `instructions` to indicate that an element
|
- The `type` option can be set to `instructions` to indicate that an element
|
||||||
is asking the user to make a choice or follow specific instructions.
|
is asking the user to make a choice or follow specific instructions.
|
||||||
|
|
||||||
|
Keystrokes
|
||||||
|
==========
|
||||||
|
|
||||||
|
You can use `{key ...}` to render a stylized keystroke. For example, this:
|
||||||
|
|
||||||
|
```
|
||||||
|
Press {key M} to view the starmap.
|
||||||
|
```
|
||||||
|
|
||||||
|
...renders this:
|
||||||
|
|
||||||
|
> Press {key M} to view the starmap.
|
||||||
|
|
||||||
|
You can also render sequences with modifier keys. This:
|
||||||
|
|
||||||
|
```
|
||||||
|
Use {key command option shift 3} to take a screenshot.
|
||||||
|
Press {key down down-right right LP} to activate the hadoken technique.
|
||||||
|
```
|
||||||
|
|
||||||
|
...renders this:
|
||||||
|
|
||||||
|
> Use {key command option shift 3} to take a screenshot.
|
||||||
|
> Press {key down down-right right LP} to activate the hadoken technique.
|
||||||
|
|
||||||
|
|
||||||
= Fullscreen Mode =
|
= Fullscreen Mode =
|
||||||
|
|
||||||
Remarkup editors provide a fullscreen composition mode. This can make it easier
|
Remarkup editors provide a fullscreen composition mode. This can make it easier
|
||||||
|
|||||||
@@ -505,6 +505,7 @@ final class PhabricatorMarkupEngine extends Phobject {
|
|||||||
|
|
||||||
$rules[] = new PhutilRemarkupDocumentLinkRule();
|
$rules[] = new PhutilRemarkupDocumentLinkRule();
|
||||||
$rules[] = new PhabricatorNavigationRemarkupRule();
|
$rules[] = new PhabricatorNavigationRemarkupRule();
|
||||||
|
$rules[] = new PhabricatorKeyboardRemarkupRule();
|
||||||
|
|
||||||
if ($options['youtube']) {
|
if ($options['youtube']) {
|
||||||
$rules[] = new PhabricatorYoutubeRemarkupRule();
|
$rules[] = new PhabricatorYoutubeRemarkupRule();
|
||||||
|
|||||||
@@ -0,0 +1,225 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorKeyboardRemarkupRule extends PhutilRemarkupRule {
|
||||||
|
|
||||||
|
public function getPriority() {
|
||||||
|
return 200.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function apply($text) {
|
||||||
|
return preg_replace_callback(
|
||||||
|
'@{key\b((?:[^}\\\\]+|\\\\.)*)}@m',
|
||||||
|
array($this, 'markupKeystrokes'),
|
||||||
|
$text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function markupKeystrokes(array $matches) {
|
||||||
|
if (!$this->isFlatText($matches[0])) {
|
||||||
|
return $matches[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
$keys = explode(' ', $matches[1]);
|
||||||
|
foreach ($keys as $k => $v) {
|
||||||
|
$v = trim($v, " \n");
|
||||||
|
$v = preg_replace('/\\\\(.)/', '\\1', $v);
|
||||||
|
if (!strlen($v)) {
|
||||||
|
unset($keys[$k]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$keys[$k] = $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
$special = array(
|
||||||
|
array(
|
||||||
|
'name' => pht('Command'),
|
||||||
|
'symbol' => "\xE2\x8C\x98",
|
||||||
|
'aliases' => array(
|
||||||
|
'cmd',
|
||||||
|
'command',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Option'),
|
||||||
|
'symbol' => "\xE2\x8C\xA5",
|
||||||
|
'aliases' => array(
|
||||||
|
'opt',
|
||||||
|
'option',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Shift'),
|
||||||
|
'symbol' => "\xE2\x87\xA7",
|
||||||
|
'aliases' => array(
|
||||||
|
'shift',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Escape'),
|
||||||
|
'symbol' => "\xE2\x8E\x8B",
|
||||||
|
'aliases' => array(
|
||||||
|
'esc',
|
||||||
|
'escape',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Up'),
|
||||||
|
'symbol' => "\xE2\x86\x91",
|
||||||
|
'heavy' => "\xE2\xAC\x86",
|
||||||
|
'aliases' => array(
|
||||||
|
'up',
|
||||||
|
'arrow-up',
|
||||||
|
'up-arrow',
|
||||||
|
'north',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Tab'),
|
||||||
|
'symbol' => "\xE2\x87\xA5",
|
||||||
|
'aliases' => array(
|
||||||
|
'tab',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Right'),
|
||||||
|
'symbol' => "\xE2\x86\x92",
|
||||||
|
'heavy' => "\xE2\x9E\xA1",
|
||||||
|
'aliases' => array(
|
||||||
|
'right',
|
||||||
|
'right-arrow',
|
||||||
|
'arrow-right',
|
||||||
|
'east',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Left'),
|
||||||
|
'symbol' => "\xE2\x86\x90",
|
||||||
|
'heavy' => "\xE2\xAC\x85",
|
||||||
|
'aliases' => array(
|
||||||
|
'left',
|
||||||
|
'left-arrow',
|
||||||
|
'arrow-left',
|
||||||
|
'west',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Down'),
|
||||||
|
'symbol' => "\xE2\x86\x93",
|
||||||
|
'heavy' => "\xE2\xAC\x87",
|
||||||
|
'aliases' => array(
|
||||||
|
'down',
|
||||||
|
'down-arrow',
|
||||||
|
'arrow-down',
|
||||||
|
'south',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Up Right'),
|
||||||
|
'symbol' => "\xE2\x86\x97",
|
||||||
|
'heavy' => "\xE2\xAC\x88",
|
||||||
|
'aliases' => array(
|
||||||
|
'up-right',
|
||||||
|
'upright',
|
||||||
|
'up-right-arrow',
|
||||||
|
'upright-arrow',
|
||||||
|
'arrow-up-right',
|
||||||
|
'arrow-upright',
|
||||||
|
'northeast',
|
||||||
|
'north-east',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Down Right'),
|
||||||
|
'symbol' => "\xE2\x86\x98",
|
||||||
|
'heavy' => "\xE2\xAC\x8A",
|
||||||
|
'aliases' => array(
|
||||||
|
'down-right',
|
||||||
|
'downright',
|
||||||
|
'down-right-arrow',
|
||||||
|
'downright-arrow',
|
||||||
|
'arrow-down-right',
|
||||||
|
'arrow-downright',
|
||||||
|
'southeast',
|
||||||
|
'south-east',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Down Left'),
|
||||||
|
'symbol' => "\xE2\x86\x99",
|
||||||
|
'heavy' => "\xE2\xAC\x8B",
|
||||||
|
'aliases' => array(
|
||||||
|
'down-left',
|
||||||
|
'downleft',
|
||||||
|
'down-left-arrow',
|
||||||
|
'downleft-arrow',
|
||||||
|
'arrow-down-left',
|
||||||
|
'arrow-downleft',
|
||||||
|
'southwest',
|
||||||
|
'south-west',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => pht('Up Left'),
|
||||||
|
'symbol' => "\xE2\x86\x96",
|
||||||
|
'heavy' => "\xE2\xAC\x89",
|
||||||
|
'aliases' => array(
|
||||||
|
'up-left',
|
||||||
|
'upleft',
|
||||||
|
'up-left-arrow',
|
||||||
|
'upleft-arrow',
|
||||||
|
'arrow-up-left',
|
||||||
|
'arrow-upleft',
|
||||||
|
'northwest',
|
||||||
|
'north-west',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
$map = array();
|
||||||
|
foreach ($special as $spec) {
|
||||||
|
foreach ($spec['aliases'] as $alias) {
|
||||||
|
$map[$alias] = $spec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$is_text = $this->getEngine()->isTextMode();
|
||||||
|
|
||||||
|
$parts = array();
|
||||||
|
foreach ($keys as $k => $v) {
|
||||||
|
$normal = phutil_utf8_strtolower($v);
|
||||||
|
if (isset($map[$normal])) {
|
||||||
|
$spec = $map[$normal];
|
||||||
|
} else {
|
||||||
|
$spec = array(
|
||||||
|
'name' => null,
|
||||||
|
'symbol' => $v,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($is_text) {
|
||||||
|
$parts[] = '['.$spec['symbol'].']';
|
||||||
|
} else {
|
||||||
|
$parts[] = phutil_tag(
|
||||||
|
'kbd',
|
||||||
|
array(
|
||||||
|
'title' => $spec['name'],
|
||||||
|
),
|
||||||
|
$spec['symbol']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($is_text) {
|
||||||
|
$parts = implode(' + ', $parts);
|
||||||
|
} else {
|
||||||
|
$glue = phutil_tag(
|
||||||
|
'span',
|
||||||
|
array(
|
||||||
|
'class' => 'kbd-join',
|
||||||
|
),
|
||||||
|
'+');
|
||||||
|
$parts = phutil_implode_html($glue, $parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getEngine()->storeText($parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -70,6 +70,11 @@
|
|||||||
border: 1px solid {$lightgreyborder};
|
border: 1px solid {$lightgreyborder};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.phabricator-remarkup .kbd-join {
|
||||||
|
padding: 0 4px;
|
||||||
|
color: {$lightgreytext};
|
||||||
|
}
|
||||||
|
|
||||||
.phabricator-remarkup pre.remarkup-counterexample {
|
.phabricator-remarkup pre.remarkup-counterexample {
|
||||||
background-color: {$sh-redbackground};
|
background-color: {$sh-redbackground};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user