hyper/website/index.html

1688 lines
92 KiB
HTML
Raw Normal View History

2017-01-27 17:45:42 -09:00
<!doctype html>
<html>
<head>
<title>Hyper™</title>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1.0" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:site" content="@zeithq" />
<meta name="og:title" content="Hyper™" />
<meta name="og:url" content="https://hyper.now.sh" />
<meta name="description" content="Hyper™: HTML/JS/CSS terminal" />
<meta name="og:description" content="Hyper™: HTML/JS/CSS terminal" />
<meta name="og:image" content="https://hyper.now.sh/static/hyper.png" />
<meta name="theme-color" content="#000000">
<link rel="dns-prefetch" href="https://cdn.zeit.co" />
<link rel="shortcut icon" href="favicon.png" />
<style>
* {
margin: 0;
padding: 0;
text-rendering: geometricPrecision;
box-sizing: border-box;
}
body, html {
background: #000;
color: #ccc;
font: 12px Menlo, "DejaVu Sans Mono", "Lucida Console", monospace;
}
#header {
position: fixed;
top: 15px;
right: 20px;
z-index: 10000;
display: flex;
transition: all 0.3s ease;
transition-property: transform, opacity;
}
#header span {
color: #999;
font-family: -apple-system, BlinkMacSystemFont,
"Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans",
"Droid Sans", "Helvetica Neue", sans-serif;
display: flex;
align-items: center;
margin-right: 10px;
}
#header a {
color: #999;
text-decoration: none;
}
#header a img {
height: 16px;
margin-left: 6px;
margin-right: 4px;
}
#header a:hover {
color: #FF2E88;
}
#header a.download-link {
color: #FF2E88;
}
#header.hidden {
transform: translateY(-35px);
opacity: 0;
}
#logo {
position: absolute;
left: 0;
right: 0;
top: 0;
padding: 50px 0 40px;
font-family: -apple-system, BlinkMacSystemFont,
"Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans",
"Droid Sans", "Helvetica Neue", sans-serif;
text-align: center;
z-index: 1000;
}
#logo img {
display: block;
margin: 0 auto 10px;
}
#logo .title, #logo .subtitle {
padding: 3px 0;
}
#logo .title {
font-size: 16px;
}
#logo .title b {
font-weight: 500;
}
#logo .subtitle {
color: #9B9B9B;
}
#top {
height: 100vh;
width: 100vw;
position: relative;
text-align: center;
max-width: 100%;
}
#top .top-content {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
opacity: 0;
animation-name: arrow-appear;
animation-delay: 2s;
animation-duration: 500ms;
animation-timing-function: ease;
animation-fill-mode: forwards;
}
.top-download {
position: relative;
bottom: 75px;
font-family: -apple-system, BlinkMacSystemFont,
"Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans",
"Droid Sans", "Helvetica Neue", sans-serif;
}
.download-button {
background: #50E3C2;
color: #494949;
height: 42px;
display: flex;
align-items: center;
padding: 0 20px;
margin-bottom: 10px;
text-decoration: none;
transition: background .12s ease-in-out;
}
.download-button:hover {
background: #72EBD0;
}
.download-button svg {
color: #2EAA8F;
}
.download-button svg#fallback-icon {
margin-left: 10px;
}
.download-button svg:not(#fallback-icon) {
margin-right: 10px;
}
.download-button strong {
color: #000000;
}
#arrow {
position: absolute;
left: 50%;
margin-left: -9px;
bottom: 20px;
}
@keyframes arrow-appear {
from {
opacity: 0;
}
to {
bottom: 0;
opacity: 1;
}
}
@keyframes arrow-video-finish {
from {
opacity: 0;
}
to {
bottom: 0;
opacity: 1;
}
}
#video {
height: 100vh;
bottom: 0;
width: 100%;
position: absolute;
}
#video video {
height: 100%;
width: 100%;
}
#loading:before {
content: 'Loading...';
position: absolute;
display: block;
left: 0;
top: 50%;
right: 0;
color: #666;
opacity: 0;
animation-name: appear;
animation-delay: 2s;
animation-duration: 500ms;
animation-timing-function: ease;
animation-fill-mode: forwards;
}
@keyframes appear {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#poster {
position: absolute;
left: 0;
right: 0;
bottom: 0;
}
#poster img {
margin: auto;
}
#content {
max-width: 800px;
margin: auto;
}
#content a, .other-downloads a {
color: #FF2E88;
text-decoration: none;
border-bottom: 1px solid #FF2E88;
}
#content a:hover, .other-downloads a:hover {
background: #FF2E88;
color: #fff;
}
#content h2, #content h3 {
font-size: 12px;
font-weight: bold;
color: #ccc;
margin: 0 0 30px 0;
padding-top: 30px;
}
#content h2 a, #content h3 a {
color: #ccc;
border-bottom-width: 0;
}
#content p {
margin: 0 0 20px;
line-height: 18px;
}
#content h2:before {
content: '## ';
}
#content h3:before {
content: '### ';
}
#content h4:before {
content: '#### ';
}
2017-01-27 17:45:42 -09:00
#content code {
font: 12px Menlo, "DejaVu Sans Mono", "Lucida Console", monospace;
}
#content p code, #content li code, #content td code {
color: #fff;
}
#content p code:before, #content p code:after,
#content td code:before, #content td code:after,
#content li code:before, #content li code:after {
content: '`';
}
#content pre {
margin: 30px;
color: #50E3C2;
line-height: 18px;
}
#content table thead td {
color: #999;
font-size: 10px;
}
#content table {
width: 100%;
border-collapse: collapse;
margin-bottom: 20px;
2017-01-27 17:45:42 -09:00
}
#content td > table {
margin: 0;
}
#content table td {
vertical-align: top;
border: 1px solid #444;
line-height: 15px;
position: relative;
}
#content table td.highlighted:after {
position: absolute;
content: "";
border: 1px solid #50E3C2;
width: 100%;
height: 100%;
top: -1px;
left: -1px;
pointer-events: none;
}
#content table td.invisible-top-left {
border-top: 0;
border-left: 0;
}
#content #installation-table a {
border-bottom: none;
display: block;
padding: 10px;
2017-01-27 17:45:42 -09:00
transition: color 0.3s ease;
}
#content #installation-table a:hover {
background: none;
color: #50E3C2;
}
#content #installation-table td:not(:first-child) {
text-align: center;
}
#content #installation-table td:not(.highlighted) img {
opacity: 0;
transition: opacity 0.3s ease;
}
#content #installation-table td a:hover img {
opacity: 1;
}
#content #installation-table td.highlighted a {
color: #50E3C2;
}
#content #installation-table {
color: #FFF;
}
#content #installation-table td[id^="td"] {
padding: 0;
}
#content #installation-table img {
width: 17px;
height: 13px;
2017-01-27 17:45:42 -09:00
}
#content td.soon {
color: #555;
}
#content td {
padding: 10px;
}
#content table.config td:nth-child(2) {
width: 30%;
color: #999;
}
#content table.config tbody td:first-child {
color: #fff;
}
#content table.api tbody td:first-child {
color: #fff;
}
#content table.api > tbody > tr > td:nth-child(2) {
width: 13%;
}
#content table.api tbody tbody td:first-child {
width: 20%;
}
#content td > p:first-child {
margin-top: 0;
}
#content ul {
margin: 20px 10px;
}
#content ul li {
list-style-type: none;
line-height: 18px;
margin: 5px 0;
padding-left: 20px;
}
#content ul li:before {
content: '-';
color: #999;
position: absolute;
margin-left: -20px;
}
#content p b {
color: #fff;
}
@media screen and (max-height: 500px) {
.title {
display: none;
}
}
@media screen and (max-height: 550px) {
.title span {
display: none !important;
}
}
@media screen and (max-height: 650px) {
#logo img {
height: 50px;
width: auto;
padding: 0;
margin-top: 0;
}
}
@media screen and (max-height: 700px) {
#logo {
padding: 30px 0 0;
}
}
@media screen and (max-width: 800px) {
#content table {
margin-left: 0;
margin-right: 0;
}
#download-for {
display: none !important;
}
#header {
width:300px;
margin: 0 auto;
}
}
@media screen and (max-width: 700px) {
#header {
text-align: center;
padding: 20px 0;
position: static;
}
#video video {
display: none;
}
#video {
background: no-repeat center url('https://cdn.zeit.co/hyper/hyperapp.gif');
background-size: 100%;
height: 100vh;
}
#content {
padding: 20px;
}
pre {
white-space:pre-wrap; word-wrap:break-word; overflow:auto;
}
#content table {
margin-left: 0;
margin-right: 0;
margin-bottom: 20px;
2017-01-27 17:45:42 -09:00
}
#content table td {
width: 50% !important;
}
#content table td:nth-child(3) {
display: none;
}
#content .table-note:after {
margin: 15px 0;
content: "Please note: the complete table information is available in bigger resolutions!";
display: block;
color: #999;
}
#content img {
max-width: 100%;
height: auto;
}
#arrow {
display: none;
}
}
.is-hidden {
display: none;
}
</style>
</head>
<body>
<div id="main">
<div id="header">
<span><a target="_blank" href="https://zeit.co">&#9650;</a></span>
<span><a target="_blank" href="https://github.com/zeit/hyper/releases">Changelog</a></span>
<span><a target="_blank" href="https://github.com/zeit/hyper">GitHub</a></span>
<span>License:&nbsp;<b>MIT</b></span>
<span><span id="download-for">Download for:</span>
<a href="#installation" class="download-link"><img src="static/apple-logo.svg"/></a>
<a href="#installation" class="download-link"><img src="static/windows-logo.svg"/></a>
<a href="#installation" class="download-link"><img src="static/linux-logo.svg"/></a>
</span>
</div>
<div id="top">
<div id="loading"></div>
<div id="logo">
<img width='60' height='53' title='' alt='' src='data:image/gif;base64,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
<div class="title"><b>Hyper</b><span style="font-size: 12px; display: block; margin-top: 6px; color: #999">JS/HTML/CSS Terminal</span></div>
</div>
<div id="video">
<video id="vid" src="https://cdn.zeit.co/hyper/hyperapp.mp4" height="100%" autoplay muted></video>
</div>
<div class="top-content">
<div class="top-download">
<a href="#installation" class="download-button">
<svg id="mac-os-icon" class="is-hidden" xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16" fill="currentColor" fill-rule="evenodd">
<path d="M13.11 12.415c-.24.552-.523 1.06-.85 1.527-.447.638-.813 1.078-1.095 1.323-.437.402-.905.608-1.407.62-.36 0-.794-.103-1.3-.31-.506-.207-.972-.31-1.398-.31-.447 0-.927.103-1.44.31-.512.207-.926.316-1.242.326-.48.022-.96-.19-1.44-.635-.304-.266-.686-.723-1.144-1.37-.49-.69-.894-1.49-1.21-2.404-.34-.986-.51-1.94-.51-2.865 0-1.06.23-1.973.688-2.74.36-.614.84-1.1 1.44-1.455.6-.356 1.248-.537 1.946-.55.382 0 .883.12 1.505.35.62.234 1.02.352 1.194.352.13 0 .574-.138 1.324-.413.71-.257 1.31-.362 1.8-.32 1.33.107 2.33.63 2.994 1.575-1.19.72-1.778 1.73-1.766 3.025.01 1.008.377 1.848 1.096 2.514.326.31.69.548 1.094.718-.088.255-.18.498-.28.733zm-3.05-12c0 .79-.29 1.527-.865 2.21C8.5 3.437 7.66 3.907 6.75 3.833c-.012-.095-.02-.195-.02-.3 0-.76.33-1.57.918-2.235.293-.336.665-.616 1.117-.84.45-.218.877-.34 1.278-.36.012.105.017.21.017.316z"/>
2017-01-27 17:45:42 -09:00
</svg>
<svg id="linux-icon" class="is-hidden" xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16" fill="currentColor" fill-rule="evenodd">
<path d="M13.47 13.393c-.065-.075-.158-.147-.276-.22-.018-.01-.067-.04-.147-.084-.08-.045-.143-.084-.192-.117-.048-.032-.11-.09-.188-.17-.077-.08-.14-.164-.183-.254-.044-.09-.088-.21-.13-.362-.04-.152-.064-.32-.07-.504-.084.072-.13.212-.14.424-.01.21.037.426.135.647.096.22.243.362.44.43.192.064.344.135.46.208.117.075.192.158.225.255.033.094-.023.197-.165.308-.144.11-.372.22-.687.327-.434.148-.743.276-.924.38-.183.103-.45.3-.8.593-.238.196-.49.302-.76.317-.267.014-.484-.084-.65-.294-.167-.212-.22-.512-.16-.9.112-.744.11-1.323-.008-1.74-.095-.326-.116-.615-.062-.865.053-.25.137-.395.25-.437.112-.043.234.047.365.267.01.03.04.088.08.175.042.087.075.147.103.183.026.036.067.08.12.14.055.056.122.095.202.12.08.024.174.04.28.044.203.006.384-.036.546-.126.16-.09.28-.19.36-.298.08-.11.16-.215.242-.317.08-.1.15-.158.21-.17.066-.01.126-.076.18-.195.053-.12.088-.284.106-.495.018-.21.004-.464-.044-.754-.09-.517-.266-1.085-.53-1.706-.265-.618-.562-1.103-.888-1.454-.59-.626-.985-1.274-1.187-1.946-.208-.71-.298-1.346-.268-1.91.03-.405-.06-.845-.263-1.318-.204-.474-.478-.834-.816-1.084-.214-.16-.48-.284-.795-.37-.316-.087-.63-.126-.947-.122-.387 0-.697.062-.93.188-.476.256-.79.567-.946.932-.155.366-.227.817-.214 1.352.024 1.18.072 2.1.144 2.768-.084.31-.453.89-1.107 1.74-.12.12-.236.28-.348.482-.113.202-.203.383-.268.545-.065.16-.153.393-.263.695-.11.304-.19.518-.237.644-.042.107-.107.232-.195.375-.09.143-.162.284-.214.42-.054.138-.084.293-.09.464-.007.13 0 .244.018.34.024.144.068.188.134.134.267-.202.604-.083 1.01.358.284.31.787 1.03 1.507 2.16.06.1.12.208.178.326.06.116.116.27.17.464.054.194.077.367.067.522-.01.155-.077.297-.206.428-.127.13-.32.214-.576.25-.137.018-.302.006-.496-.036-.193-.043-.44-.11-.737-.206-.297-.095-.517-.16-.66-.196-.21-.047-.505-.108-.89-.183-.383-.075-.634-.13-.753-.165-.203-.053-.312-.13-.33-.23-.018-.085.024-.228.126-.43.1-.202.15-.347.15-.437.008-.065.005-.13-.007-.196-.01-.065-.024-.116-.04-.15-.015-.037-.04-.09-.077-.16-.036-.073-.06-.127-.072-.16-.108-.25-.123-.42-.044-.51.054-.078.18-.11.383-.09.304.03.55-.015.742-.135.315-.195.41-.512.285-.946 0 .202-.036.354-.107.455-.072.102-.196.207-.376.313-.1.06-.28.095-.535.108-.257.012-.427.054-.51.126-.06.054-.09.134-.093.242-.004.108.01.215.04.326.03.11.06.237.09.38.03.143.042.262.036.357-.007.066-.06.228-.16.487-.102.26-.123.457-.062.595.03.065.08.124.15.174.073.05.173.093.3.13.128.035.245.063.353.084.108.02.256.048.446.08.19.033.342.06.455.085.38.077.815.206 1.303.384.49.177.82.27.992.275.167.006.327-.028.478-.103.152-.075.28-.16.39-.255.107-.095.265-.184.477-.268.21-.084.448-.128.71-.134.12-.007.293-.014.518-.023.227-.01.395-.013.51-.013.512 0 .897.003 1.16.008.178.006.32.034.42.085.1.05.166.11.196.174.03.066.08.142.148.227.068.087.156.157.263.21.226.107.492.15.796.128.303-.02.506-.078.607-.174.167-.16.392-.35.674-.572.283-.22.537-.387.764-.5l.243-.115c.113-.053.21-.1.286-.138.075-.04.17-.088.28-.147.11-.06.2-.114.267-.165.07-.05.14-.108.21-.175.07-.065.117-.13.138-.196.02-.066.028-.133.023-.2-.016-.072-.052-.143-.118-.217zm-4.785-8.63c.018-.012.03-.016.036-.013.007.003.02.014.037.036l.05.058.06.072c.027.03.056.054.086.072.036.025.078.04.13.05.05.007.09.024.115.043.026.022.045.057.058.104.012.065.002.126-.03.178-.033.054-.077.077-.13.072-.107-.025-.223-.118-.347-.28-.127-.166-.148-.295-.065-.39zM7.578 1.295c.03-.04.047-.07.054-.093.01-.036.013-.073.005-.11-.01-.04-.007-.078.008-.117.015-.04.05-.06.103-.067.054 0 .126.044.214.134.018.01.045.03.085.054.04.024.065.044.08.062.014.018.023.033.023.044-.012.03-.04.05-.08.062-.04.012-.087.018-.134.018-.048 0-.075.003-.08.008-.048.018-.093.044-.134.08-.04.036-.075.062-.098.08-.025.018-.048.018-.072 0-.025-.036-.033-.06-.026-.075.005-.015.023-.04.052-.08zM3.256 7.978c.04-.048.072-.087.09-.116.018-.03.035-.07.05-.12.014-.052.027-.09.04-.112.01-.025.03-.033.054-.026.01-.004.02.003.026.018.007.014.008.022.008.022v.027c0 .01 0 .022-.005.037l-.014.04c-.006.012-.01.03-.018.054-.006.026-.01.045-.018.063-.024.06-.06.113-.11.16-.05.048-.09.07-.112.062-.036-.013-.032-.05.008-.107zm5.84 5.508c-.01.19-.052.46-.12.8
2017-01-27 17:45:42 -09:00
</svg>
<svg id="windows-icon" class="is-hidden" xmlns="http://www.w3.org/2000/svg" width="14" height="16" viewBox="0 0 14 16" fill="currentColor" fill-rule="evenodd">
<path d="M0 2.265l6.54-.887.002 6.287-6.536.037L0 2.265zM6.536 8.39l.005 6.293-6.535-.896v-5.44l6.53.043zm.792-7.13L15.998 0v7.585l-8.67.07V1.26zM16 8.45L15.998 16l-8.67-1.22-.012-6.345L16 8.45z"/>
2017-01-27 17:45:42 -09:00
</svg>
<span id="download-button-text">
<strong>Download Hyper</strong>
</span>
<svg id="fallback-icon" class="is-hidden" width="17px" height="13px" viewBox="0 0 17 13" version="1.1" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd" stroke="currentColor" stroke-linecap="square"><path d="M.5 5.5v6M16.5 5.5v6M8.5.5v7.07M5.5 5l2.828 2.828M11.328 5L8.5 7.828M.5 12h16"/></g>
2017-01-27 17:45:42 -09:00
</svg>
</a>
<span class="other-downloads"><a href="#installation">Other platforms</a></span>
</div>
<div id="arrow"><a href="#installation"><img src="static/arrow.svg" width="18" /></a></div>
</div>
</div>
<div id="content">
<h2 id="installation"><a href="#installation">Installation</a></h2>
<table id="installation-table" class="offset-header">
<tr>
<td style="width: 33.333%" class="invisible-top-left"></td>
<td style="width: 33.333%">32-bit</td>
<td style="width: 33.333%">64-bit</td>
</tr>
<tr>
<td><b>macOS</b> (.app)</td>
2017-01-27 17:45:42 -09:00
<td id="td-mac-os" colspan="2">
<a href="https://releases.hyper.is/download/mac">DOWNLOAD <img src="static/download-icon.svg"/></a>
2017-01-27 17:45:42 -09:00
</td>
</tr>
<tr>
<td><b>Windows</b> (.exe)</td>
<td class="soon">COMING SOON</td>
<td id="td-win">
<a href="https://releases.hyper.is/download/win">DOWNLOAD <img src="static/download-icon.svg"/></a>
2017-01-27 17:45:42 -09:00
</td>
</tr>
<tr>
<td><b>Debian</b> (.deb)</td>
<td class="soon">COMING SOON</td>
<td id="td-debian">
<a href="https://releases.hyper.is/download/deb">DOWNLOAD <img src="static/download-icon.svg"/></a>
2017-01-27 17:45:42 -09:00
</td>
</tr>
<tr>
<td><b>Fedora</b> (.rpm)</td>
<td class="soon">COMING SOON</td>
<td id="td-fedora">
<a href="https://releases.hyper.is/download/rpm">DOWNLOAD <img src="static/download-icon.svg"/></a>
2017-01-27 17:45:42 -09:00
</td>
</tr>
<tr>
<td><b>Other Linux distros</b> (.AppImage)</td>
<td class="soon">COMING SOON</td>
<td id="td-appimage" colspan="2">
<a href="https://releases.hyper.is/download/AppImage">DOWNLOAD <img src="static/download-icon.svg"/></a>
2017-01-27 17:45:42 -09:00
</td>
</tr>
</table>
<h2 id="hashtag-goals"><a href="#hashtag-goals">Project goals</a></h2>
<p> The goal of the project is to create a beautiful and extensible experience
for command-line interface users, built on open web standards.</p>
<p>In the beginning, our focus will be primarily around speed, stability and
the development of the correct API for extension authors.</p>
<p>In the future, we anticipate the community will come up with
innovative additions to enhance what could be the simplest,
most powerful and well-tested interface for productivity.</p>
<h2 id="extensions"><a href="#extensions">Extensions</a></h2>
<p>Extensions are available on npm. We encourage everyone to
include <code>hyper</code> in the <code>keywords</code>
field in <code>package.json</code>.</p>
<pre><code>$ npm search hyper</code></pre>
<p>Then edit <code>~/.hyper.js</code> and add it to <code>plugins</code></p>
<pre><code>module.exports = {
config: { /*... */ },
plugins: [
<b>"hyperpower"</b>
]
};</code></pre>
<p><code>Hyper</code> will show a notification when your modules are
installed to <code>~/.hyper_plugins</code>.</p>
<p>You can also take a look at
2017-01-27 17:45:42 -09:00
<a href="https://github.com/bnb/awesome-hyper">Awesome Hyper</a>
for a curated list of plugins and resources.</p>
<h2 id="keymaps"><a href="#keymaps">Keymaps</a></h2>
2017-08-04 14:05:10 -08:00
<P> All command keys can be changed. In order to change them, edit
<code>~/.hyper.js</code> and add your desired change to <code>keymaps</code>.
</p>
<p> Then Hyper will change the default with your custom change.</p>
<p> Example: <code>'window:devtools': 'Cmd+Alt+O'</code> <p>
<pre><code>module.exports = {
config: { /*... */ },
keymaps: {
'window:devtools': 'cmd+alt+o'
}
};</code></pre>
2017-08-04 14:05:10 -08:00
<p>Default keymaps: </p>
<table>
<tbody>
<tr>
<td><a href="https://github.com/zeit/hyper/blob/master/app/keymaps/win32.json">Windows</a></td>
<td><a href="https://github.com/zeit/hyper/blob/master/app/keymaps/linux.json">Linux</a></td>
<td><a href="https://github.com/zeit/hyper/blob/master/app/keymaps/darwin.json">macOS</a></td>
</tr>
</tbody>
</table>
2017-01-27 17:45:42 -09:00
<h2 id="cfg"><a href="#cfg">Configuration</a></h2>
<p>The <code>config</code> object seen above in <code>~/.hyper.js</code>
admits the following</p>
<table class="config">
<thead>
<tr>
<td>Property</td>
<td>Default</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td>"updateChannel"</td>
<td>"stable"</td>
<td>The update channel to receive updates from</td>
</tr>
2017-01-27 17:45:42 -09:00
<tr>
<td>"fontSize"</td>
<td>12</td>
<td>The default size in pixels for the terminal</td>
</tr>
<tr>
<td>"fontFamily"</td>
<td>"Menlo, DejaVu Sans Mono, Lucida Console, monospace"</td>
<td>The font family to use with optional fallbacks</td>
</tr>
<tr>
<td>"uiFontFamily"</td>
<td>"-apple-system, BlinkMacSystemFont, Segoe UI, Roboto, ..."</td>
<td>The font family to use for the UI with optional fallbacks</td>
</tr>
<tr>
2017-01-27 17:45:42 -09:00
<tr>
<td>"cursorColor"</td>
<td>"#F81CE5"</td>
<td>The color of the caret in the terminal</td>
</tr>
<tr>
<td>"cursorShape"</td>
<td>"BLOCK"</td>
<td>The shape of the caret in the terminal. Available options are: 'BEAM', 'UNDERLINE', 'BLOCK'</td>
</tr>
<tr>
<td>"cursorBlink"</td>
<td>"false"</td>
<td>If true, cursor will blink</td>
</tr>
2017-01-27 17:45:42 -09:00
<tr>
<td>"foregroundColor"</td>
<td>"#fff"</td>
<td>The color of the main text of the terminal</td>
</tr>
<tr>
<td>"backgroundColor"</td>
<td>"#000"</td>
<td>The color and opacity of the window and main terminal background</td>
</tr>
<tr>
<td>"borderColor"</td>
<td>"#333"</td>
<td>The color of the main window border and tab bar</td>
</tr>
<tr>
<td>"css"</td>
<td>""</td>
<td>Custom CSS to include in the main window</td>
</tr>
<tr>
<td>"termCSS"</td>
<td>""</td>
<td>Custom CSS to include in the terminal window</td>
</tr>
<tr>
<td>"padding"</td>
<td>"12px 14px"</td>
<td>CSS padding values for the space around each term</td>
</tr>
<tr>
<td>"colors"</td>
<td>{ black: "#000000", red: "#ff0000", ... }</td>
<td>A list of overrides for the color palette. The names of the keys represent the "ANSI 16", which can all be seen <a href="https://github.com/zeit/hyper/blob/aaed99abac97a3d6b1766f194522a69e8a994bcb/lib/utils/colors.js">in the default config</a>.</td>
</tr>
<tr>
<td>"shell"</td>
<td>""</td>
<td>A path to a custom shell to run when Hyper starts a new session</td>
</tr>
<tr>
<td>"npmRegistry"</td>
<td>npm get registry</td>
<td>Override the npm registry URL to use when installing plugins</td>
</tr>
<tr>
<td>"windowSize"</td>
<td>null</td>
<td>The default width/height in pixels of a new window e.g. [540, 380]</td>
</tr>
<tr>
<td>"copyOnSelect"</td>
<td>false</td>
<td>If true, selected text will automatically be copied to the clipboard</td>
</tr>
<tr>
<td>"quickEdit"</td>
<td>false</td>
<td>If true, on right click selected text will be copied or pasted if no selection is present (true by default on Windows)</td>
</tr>
2017-01-27 17:45:42 -09:00
<tr>
<td>"bell"</td>
<td>"SOUND"</td>
<td>System bell configuration. Available options are: "SOUND", false</td>
</tr>
<tr>
<td>"bellSoundURL"</td>
<td>"lib-resource:hterm/audio/bell"</td>
<td>The URL of the bell sound to use, used only if "bell" is set to "SOUND"</td>
</tr>
<tr>
<td>"modifierKeys"</td>
<td>
{
cmdIsMeta: false,
altIsMeta: false
}
</td>
<td>Change the behaviour of modifier keys to act as meta key</td>
</tr>
<tr>
<td>"showHamburgerMenu"</td>
<td>""</td>
<td>
Change the visibility of the hamburger menu. Available options
are: true, false
</td>
</tr>
<tr>
<td>"showWindowControls"</td>
<td>""</td>
<td>
Change the position/visibility of the window controls.
Available options are: true, false, "left"
</td>
</tr>
2017-01-27 17:45:42 -09:00
</tbody>
</table>
<span class="table-note"></span>
<h2 id="extensions-api"><a href="#extensions-api">Extensions API</a></h2>
<p>Extensions are universal Node.js modules loaded by both
Electron and the renderer process.</p>
<p>The extension system is designed around <b>composition</b>
of the APIs we use to build the terminal: <code>React</code>
components and <code>Redux</code> actions.</p>
<p>Instead of exposing a custom API method or parameter for
every possible customization point, we allow you to intercept
and compose every bit of functionality!</p>
<p>The only knowledge that is therefore required to successfully
extend <code>Hyper</code> is that of its underlying open
source libraries.</p>
<p>Your module has to expose at least one of these methods:</p>
2017-01-27 17:45:42 -09:00
<table class="api">
<thead>
<tr>
<td>Method</td>
<td>Invoked from</td>
<td>Description</td>
</tr>
</thead>
<tbody>
<tr>
<td><code>onApp</code></td>
<td>Electron</td>
<td>
<p>Invoked when the app first loads. If a plugin reloads,
it's invoked again with the existing app.</p>
<p>Parameters:</p>
<table>
<tbody>
<tr>
<td><code>app</code></td>
<td>The electron app.</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td><code>onWindow</code></td>
<td>Electron</td>
<td>
<p>Invoked when each window is created. If a plugin reloads,
it's invoked again with the existing windows.</p>
<p>Parameters:</p>
<table>
<tbody>
<tr>
<td><code>window</code></td>
<td>An electron <code>BrowserWindow</code>.</td>
</tr>
</table>
</td>
</tr>
<tr>
<td><code>onUnload</code></td>
<td>Electron</td>
<td>
<p>Invoked when a plugin is removed by the user.</p>
<p>Parameters:</p>
<table>
<tbody>
<tr>
<td><code>app</code></td>
<td>The electron app.</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td><code>decorateConfig</code></td>
<td>Electron / Renderer</td>
<td>
<p><b>v0.5.0+</b>. Allows you to decorate the user's configuration.<br>
Useful for themeing or custom parameters for your
plugin.</p>
<p>Parameters:</p>
<table>
<tbody>
<tr>
<td><code>config</code></td>
<td>The <code>config</code> object</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td><code>decorateEnv</code></td>
<td>Electron</td>
<td>
<p><b>v0.7.0+</b>. Allows you to decorate the user's environment
by returning a modified environment object.
<p>Parameters:</p>
<table>
<tbody>
<tr>
<td><code>environment</code></td>
<td>The <code>environment</code> object</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td><code>decorateMenu</code></td>
<td>Electron</td>
<td>
<p>Invoked with the Electron's <code>Menu</code> template.
If a plugin reloads, it's called again and the menu
is refreshed.</p>
<p>Parameters:</p>
<table>
<tbody>
<tr>
<td><code>menu</code></td>
<td>The menu template object</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td><code>onRendererWindow</code></td>
2017-01-27 17:45:42 -09:00
<td>Renderer</td>
<td>
<p>Invoked when a plugin is first loaded or subsequently
reloaded in each window.</p>
<p>Parameters:</p>
<table>
<tr>
<tbody>
<td><code>window</code></td>
<td>The window object</td>
</tbody>
</tr>
</table>
</td>
</tr>
<tr>
<td><code>middleware</code></td>
<td>Renderer</td>
<td>
<p>A custom Redux middleware that can intercept any
action. Subsequently we invoke the <code>thunk</code>
middleware, which means your middleware can
<code>next</code> thunks.</p>
</td>
</tr>
<tr>
<td><code>reduceUI</code><br><code>reduceSessions</code><br><code>reduceTermGroups</code></td>
2017-01-27 17:45:42 -09:00
<td>Renderer</td>
<td>
<p>A custom reducer for the <code>ui</code>, <code>sessions</code> or <code>termgroups</code> state shape.</p>
2017-01-27 17:45:42 -09:00
<table>
<tbody>
<tr>
<td><code>state</code></td>
<td>The Redux state object</td>
</tr>
<tr>
<td><code>action</code></td>
<td>The action object</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
<code>getTermGroupProps</code>
2017-01-27 17:45:42 -09:00
</td>
<td>Renderer</td>
<td>
<p>Passes down props from <code>&lt;Terms&gt;</code>
to the <code>&lt;TermGroup&gt;</code> component. Must return
the composed props object.</p>
<table>
<tbody>
<tr>
<td><code>uid</code></td>
<td>TermGroup uid</td>
</tr>
<tr>
<td><code>parentProps</code></td>
<td>Props form the parent component.</td>
</tr>
<tr>
<td><code>props</code></td>
<td>The existing properties that will be
passed to the component.</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
<code>getTermProps</code>
</td>
<td>Renderer</td>
<td>
<p>Passes down props from <code>&lt;TermGroup&gt;</code>
2017-01-27 17:45:42 -09:00
to the <code>&lt;Term&gt;</code> component. Must return
the composed props object.</p>
<table>
<tbody>
<tr>
<td><code>uid</code></td>
<td>Term uid</td>
</tr>
<tr>
<td><code>parentProps</code></td>
<td>Props form the parent component.</td>
</tr>
<tr>
<td><code>props</code></td>
<td>The existing properties that will be
passed to the component.</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
<code>getTabsProps</code>
</td>
<td>Renderer</td>
<td>
2017-02-18 08:04:19 -09:00
<p>Passes down props from <code>&lt;Tabs&gt;</code>
2017-01-27 17:45:42 -09:00
to the <code>&lt;Header&gt;</code> component. Must return
the composed props object.</p>
<table>
<tbody>
<tr>
<td><code>parentProps</code></td>
<td>Props form the parent component.</td>
</tr>
<tr>
<td><code>props</code></td>
<td>The existing properties that will be
passed to the component.</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
<code>getTabProps</code>
</td>
<td>Renderer</td>
<td>
2017-02-18 08:04:19 -09:00
<p>Passes down props from <code>&lt;Tab&gt;</code>
2017-01-27 17:45:42 -09:00
to the <code>&lt;Tabs&gt;</code> component. Must return
the composed props object.</p>
<table>
<tbody>
<tr>
<td><code>uid</code></td>
<td>Tab / Term uid</td>
</tr>
<tr>
<td><code>parentProps</code></td>
<td>Props form the parent component.</td>
</tr>
<tr>
<td><code>props</code></td>
<td>The existing properties that will be
passed to the component.</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
<code>mapHyperState</code><br>
<code>mapTermsState</code><br>
<code>mapHeaderState</code><br>
<code>mapNotificationsState</code>
</td>
<td>Renderer</td>
<td>
<p>A custom mapper for the state properties that
<a href="https://github.com/zeit/hyper/tree/master/lib/containers" target="_blank">container components</a> receive. Note that for children components to
get these properties, you have to pass them down using the corresponding
methods (like <code>getTermProps</code>).</p><p> Must
return an extended object of the map passed.</p>
<table>
<tbody>
<tr>
<td><code>state</code></td>
<td>The <code>Redux</code> global state</td>
</tr>
<tr>
<td><code>map</code></td>
<td>The existing map of properties that will be
passed to the component.</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
<code>mapHyperDispatch</code><br>
<code>mapTermsDispatch</code><br>
<code>mapHeaderDispatch</code><br>
<code>mapNotificationsDispatch</code>
</td>
<td>Renderer</td>
<td>
<p>A custom mapper for the dispatch properties. Must
return an extended object of the map passed.</p>
<table>
<tbody>
<tr>
<td><code>dispatch</code></td>
<td>The Redux dispatch function</td>
</tr>
<tr>
<td><code>map</code></td>
<td>The existing map of properties that will be
passed to the component.</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
<code>decorateHyper</code><br>
<code>decorateNotifications</code><br>
<code>decorateNotification</code>
2017-01-27 17:45:42 -09:00
<code>decorateHeader</code><br>
<code>decorateTabs</code><br>
<code>decorateTab</code>
<code>decorateTerms</code><br>
<code>decorateTermGroup</code><br>
<code>decorateSplitPane</code><br>
<code>decorateTerm</code><br>
2017-01-27 17:45:42 -09:00
</td>
<td>Renderer</td>
<td>
<p>Invoked with the <code>React</code> <code>Component</code>
to decorate. Must return a Higher Order Component.</p>
<p>Parameters:</p>
<table>
<tbody>
<tr>
<td><code>Hyper</code></td>
<td>The <code>React</code> <code>Component</code>
constructor.</td>
</tr>
<tr>
<td><code>env</code></td>
<td>A collection of useful module references for
building components. <a href="#decorating-components">See below</a></td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<span class="table-note"></span>
<h3 id="extensions-module-loading"><a href="#extensions-module-loading">Module loading</a></h3>
<p>The user can hot-load and hot-reload plugins by pressing
Command + R (refresh). Please strive to make plugins that don't
require a complete restart of the application to work.</p>
<h4>Notice</h4>
<p>Plugins affecting the `BrowserWindow` will the effect on new windows after hot-reload.</p>
2017-01-27 17:45:42 -09:00
<p>In the future we might do this automatically.</p>
<p>When developing, you can add your plugin to
<code>~/.hyper_plugins/local</code> and then specify it
under the <code>localPlugins</code> array in <code>~/.hyper.js</code>.
We load new plugins:
<ul>
<li>Periodically (every few hours)</li>
<li>When changes are made to the configuration file
(<code>plugins</code> or <code>localPlugins</code>)</li>
<li>When the user clicks Plugins &gt; Update all now</li>
</ul>
<p>The process of reloading involves</p>
<ul>
<li>Running <code>npm prune</code> and <code>npm install</code>
in <code>~/.hyper_plugins</code>.</li>
<li>Pruning the <code>require.cache</code> in both electron
and the renderer process</li>
<li>Invoking <code>on*<code> methods on the existing instances
and re-rendering components with the fresh decorations in place.</li>
</ul>
<p>Note: on the main process, plugins are registered as
soon as possible (we fire <code>onLoad</code>).
On the browser, it's up to the user to trigger their load by
pressing command+R. We put the user in control of the loading
in this way to prevent them from losing critical work by
extensions that reset state or don't preserve it correctly.</p>
<h3 id="decorating-components"><a href="#decorating-components">Decorating components</a></h3>
<p>We give you the ability to provide a higher order component
for every piece of the <code>Hyper</code> UI.<br> Its structure
is as follows:</p>
<pre><code>&lt;Hyper&gt;
&lt;Header&gt;
&lt;Tabs&gt;
&lt;Tab /&gt; ...
&lt;/Tabs&gt;
&lt;/Header&gt;
&lt;Terms&gt;
&lt;TermGroup&gt;
&lt;SplitPane&gt;
&lt;TermGroup&gt;
&lt;Term /&gt; ...
&lt;/TermGroup&gt;
&lt;TermGroup&gt;
&lt;Term /&gt; ...
&lt;/TermGroup&gt;
&lt;/SplitPane&gt;
&lt;/TermGroup&gt;
2017-01-27 17:45:42 -09:00
&lt;/Terms&gt;
&lt;Notifications&gt;
&lt;Notification /&gt; ...
&lt;/Notifications&gt;
&lt;/Hyper&gt;</code></pre>
<p>All the <code>decorate*</code> methods receive the following
references in an object passed as the second parameter:</p>
<table>
<tbody>
<tr>
<td><code>React</code></td>
<td>The entire React namespace.</td>
</tr>
<tr>
<td><code>notify</code></td>
<td>A helper function that shows a desktop notification.
The first parameter is the title and the second is the optional
body of the notification.</td>
</tr>
<tr>
<td><code>Notification</code></td>
<td>The <code>Notification</code> component in case you
want to re-use it.</td>
</tr>
</tbody>
</table>
<p>All the components accept the following two properties
to extend their markup:</p>
<table>
<tbody>
<tr>
<td><code>customChildren</code></td>
<td>An array of <code>Element</code> or a single
<code>Element</code> to insert at the bottom
of the component.</td>
</tr>
<tr>
<td><code>customChildrenBefore</code></td>
<td>The same as the above property, but inserted
as the first child element(s) of the component.</td>
</tr>
</tbody>
</table>
<p>Your higher order component can supply a <code>onDecorated</code>
property to the decorated component to get a reference to its instance.</p>
2017-01-27 17:45:42 -09:00
<p>We encourage you to maintain compatibility with other decorators.
Since many can be set, don't assume that yours is the only one.<p>
<p>For example, if you're passing children, compose potential existing
2017-01-27 17:45:42 -09:00
values:</p>
<pre><code>render () {
const customChildren = Array.from(this.props.customChildren)
.concat(&lt;p&gt;My new child&lt;/p&gt;);
return &lt;Tab {...this.props} customChildren={customChildren} /&gt;
}</code></pre>
<p>Or if you use <code>onDecorated</code> property</p>
<pre><code>onDecorated (term) {
this.term = term;
if (this.props.onDecorated) {
this.props.onDecorated(term);
}
}</code></pre>
2017-01-27 17:45:42 -09:00
<h3 id="actions-and-effects"><a href="#actions-and-effects">Actions and Effects</a></h3>
<p>All the <a href="https://github.com/zeit/hyper/tree/master/lib/actions"
target="_blank">Redux actions</a> are available for you to
handle through your middleware and reducers. For an example, refer to the <a href="#hyperpower">Hyperpower</a> reference plugin.</p>
<p>Side effects occur in two fundamental forms:</p>
<ul>
<li>Some actions dispatch other actions based on state.</li>
<li>Some actions do async work by communicating over the RPC
channel to the main process</li>
</ul>
<p>In all cases, the side effect is passed as
the <code>effect</code> key in the action and later handled
by our middleware.</p>
<p>This means that you can override, compose or completely
eliminate effects! In other words, this is how you can
change the default functionality or behavior of the app.</p>
<p>As an example, consider the action we use to increase
the font size when you press <code>Command+=</code>:</p>
<pre><code>export function increaseFontSize () {
return (dispatch, getState) => {
dispatch({
type: UI_FONT_SIZE_INCR,
effect () {
const state = getState();
const old = state.ui.fontSizeOverride || state.ui.fontSize;
const value = old + 1;
dispatch({
type: UI_FONT_SIZE_SET,
value
});
}
});
};
}</code></pre>
<h3 id="hterm"><a href="#hterm">The underlying terminal</a></h3>
<p><code>Hyper</code> achieves a lot of its speed and functionality
thanks to the power of <a target="_blank" href="https://chromium.googlesource.com/apps/libapps/+/master/hterm">hterm</a> underneath,
the terminal emulator of the Chromium project.</p>
<p>To access the terminal object, you can supply
a <code>onTerminal</code> property to the <code>&lt;Term&gt;</code>
component.</p>
<h3 id="additional-apis"><a href="#additional-apis">Additional APIs</a></h3>
<p>The Electron <code>app</code> objects are extended with the following properties:</p>
<table>
<tbody>
<tr>
<td><code>config</code></td>
<td>An <code>Object</code> with the <code>config</code> block
from <code>~/.hyper.js</code>.</td>
</tr>
<tr>
<td><code>plugins</code></td>
<td>An <code>Object</code> with helpers for plugins.</td>
</tr>
<tr>
<td><code>getWindows</code></td>
<td>A <code>Function</code> that returns an <code>Set</code>
of all the open windows.</td>
</tr>
<tr>
<td><code>createWindow</code></td>
<td>A <code>Function</code> that will create a new window. Accepts an
optional <code>callback</code> that will be passed as the new window's
<code>init</code> callback.</td>
</tr>
</tbody>
</table>
<p>Electron <code>BrowserWindow</code> objects are extended
with the following parameters:</p>
<table>
<tbody>
<tr>
<td><code>rpc</code></td>
<td>An <code>EventEmitter</code> that allows for communication
with the window process.</td>
</tr>
<tr>
<td><code>sessions</code></td>
<td>A <code>Map</code> of <code>Session</code>
objects which hold the communication with each
term's pty..</td>
</tr>
</tbody>
</table>
<p>Renderer windows are similarly extended with:</p>
<table>
<tbody>
<tr>
<td><code>rpc</code></td>
<td>An <code>EventEmitter</code> that allows for communication
with the window process.</td>
</tr>
<tr>
<td><code>store</code></td>
<td>The Redux <code>Store</code> object. This allows
access to <code>dispatch</code> actions or read the global
state with <code>getState</code>.</td>
</tr>
</tbody>
</table>
<p>The <code>rpc</code> object is symmetrical between browser
and renderer process. The API is the same as Node.js,
with the exception that it only admits a single object
as its parameters only:</p>
<pre><code>window.rpc.emit('hi there', {
some: 'payload',
any: [
'object',
'here'
]
});</code></pre>
<h3 id="hyperyellow"><a href="#hyperyellow">Example theme: Hyperyellow</a></h3>
<p>The following extension simply alters the config to add CSS
and yellow colors! Here's the <a target="_blank" href="https://github.com/zeit/hyperyellow/blob/29c4ac9748be74d7ad587b7077758ef26f6ce5c2/index.js#L1">code</a>.</p>
<p style="text-align: center"><img src="static/hyperyellow.gif" width="446" height="333" /></p>
<p>Themes are simply plugins! Only one hook, <code>decorateConfig</code>
is needed:</p>
<pre><code>exports.decorateConfig = (config) => {
return Object.assign({}, config, {
borderColor: 'yellow',
cursorColor: 'yellow',
css: `
${config.css || ''}
.tabs_nav .tabs_list .tab_text {
color: yellow;
}
.tabs_nav .tabs_title {
color: yellow;
}
`
});
}</code></pre>
<p>I grabbed the class names by inspecting the term with
Devtools, which you can trigger from <code>View -&gt; Toggle Developer Tools</code>.
When you do so, notice that some classes are automatically generated and
followed by a random nonce (e.g.: <code>term_13hv8io</code>). Ignore those: they change with every new window!</p>
<p>Notice the emphasis on playing nice with other extensions.
Specifically, we create a new object, extend only the keys we
are interested in, and we <b>compose</b> the CSS to preserve
the user's setting and that of other authors':</p>
<pre><code>return Object.assign({}, config, {
css: `
${config.css || ''}
/* your css here */
`
});</code></pre>
<h3 id="hyperpower"><a href="#hyperpower">Example extension: Hyperpower</a></h3>
<p>The following extension renders particles as the
caret moves:</p>
<p style="text-align: center"><img src="https://cloud.githubusercontent.com/assets/13041/16820268/13c9bfe6-4905-11e6-8fe4-baf8fc8d9293.gif" width="457" height="340" /></p>
<p>Let's walk through <a target="_blank"
href="https://github.com/zeit/hyperpower/blob/master/index.js">its code</a>.
<br>First, we intercept the Redux action <code>SESSION_ADD_DATA</code>. See the whole list of them <a target="_blank" href="https://github.com/zeit/hyper/tree/master/lib/actions">here</a>.</p>
<pre><code>exports.middleware = (store) => (next) => (action) => {
if ('SESSION_ADD_DATA' === action.type) {
const { data } = action;
if (/bash: wow: command not found/.test(data)) {
store.dispatch({
type: 'WOW_MODE_TOGGLE'
});
} else {
next(action);
}
} else {
next(action);
}
};</code></pre>
<p>Notice that we don't re-dispatch the action, which means
we never render the output of the command to the terminal. Instead, we dispatch an action of our own, which we grab
in the <code>uiReducer</code>and later map:</p>
<pre><code>exports.reduceUI = (state, action) => {
switch (action.type) {
case 'WOW_MODE_TOGGLE':
return state.set('wowMode', !state.wowMode);
}
return state;
};
exports.mapTermsState = (state, map) => {
return Object.assign(map, {
wowMode: state.ui.wowMode
});
};</code></pre>
<p>We then want to decorate the <code>&lt;Term&gt;</code> component
so that we can access the underlying caret.</p>
<p>However, <code>&lt;Term&gt;</code> is not a container that
we can map props to. So we use <code>getTermProps</code> to
pass the property further down:</p>
<pre><code>exports.getTermProps = (uid, parentProps, props) => {
return Object.assign(props, {
wowMode: parentProps.wowMode
});
}</code></pre>
<p>The extension then <a href="https://github.com/zeit/hyperpower/blob/82a09148e176584458829fdd8877fbc003fbb5b4/index.js#L51" target="_blank">returns</a> a higher order component to
wrap <code>&lt;Term&gt;</code>. Notice we pass the <code>onTerminal</code>
property to access the underlying hterm object:</p>
<pre><code>render () {
return React.createElement(Term, Object.assign({}, this.props, {
onTerminal: this._onTerminal
}));
}</code></pre>
<h2 id="credits"><a href="#credits">Credits</a></h2>
<p>Authored by <b>Guillermo Rauch</b> - <a href="https://twitter.com/rauchg" target="_blank">@rauchg</a>.<br />
Brought to you by <a href="https://zeit.co"><span style="font-size: 16px">&#9650;</span>ZEIT</a>. Hosted on <a target="_blank" href="https://zeit.co/now">now</a>.</p>
<p>Special thanks to the following people:</p>
<ul>
<li>Jeff Haynies for his work on polish for general terminal behavior.</li>
<li>Nuno Campos for his work on zooming and configuration.</li>
<li>Leo Lamprecht and Johan Brook for their excellent UI improvements.</li>
<li>Harrison Harnisch for our nice default color palette.</li>
<li>Fernando Montoya for his feedback and patches.</li>
<li>Matias Tucci for his work on the auto updater.</li>
<li>Sebastian Markbage for his insight on the higher-order component extensibility API.</li>
<li>Joel Besada for his editor particles <a target="_blank" href="https://github.com/codeinthedark/editor/pull/1">idea</a> and Zero Cho for his reference implementation.</li>
</ul>
</div>
<script>
document.getElementById('vid').playbackRate = 1.7;
document.getElementById('vid').onended = function () {
document.getElementsByClassName('top-content')[0].style.animationDelay = '100ms';
document.getElementsByClassName('top-content')[0].style.animationName = 'arrow-video-finish';
2017-01-27 17:45:42 -09:00
}
document.addEventListener('DOMContentLoaded', () => {
var userAgent = navigator.userAgent;
var downloadButton = document.getElementsByClassName('download-button')[0];
var downloadButtonText = document.getElementById('download-button-text');
if (/Mac/.test(userAgent) && !/iPhone/.test(userAgent) && !/iPad/.test(userAgent)) {
downloadButton.setAttribute('href', 'https://releases.hyper.is/download/mac');
2017-01-27 17:45:42 -09:00
downloadButtonText.innerHTML += ' for <strong>macOS</strong>';
document.getElementById('td-mac-os').classList.add('highlighted');
document.getElementById('mac-os-icon').classList.remove('is-hidden');
} else if (/Windows/.test(userAgent)) {
downloadButton.setAttribute('href', 'https://releases.hyper.is/download/win');
2017-01-27 17:45:42 -09:00
downloadButtonText.innerHTML += ' for <strong>Windows</strong>';
document.getElementById('td-win').classList.add('highlighted');
document.getElementById('windows-icon').classList.remove('is-hidden');
} else if (/Linux/.test(userAgent) && !/Android/.test(userAgent)) {
document.getElementById('linux-icon').classList.remove('is-hidden');
if (/Ubuntu/.test(userAgent)) { // needs to be improved with other debian distros
downloadButton.setAttribute('href', 'https://releases.hyper.is/download/deb');
2017-01-27 17:45:42 -09:00
downloadButtonText.innerHTML += ' for <strong>Debian</strong>';
document.getElementById('td-debian').classList.add('highlighted');
} else if (/Fedora/.test(userAgent)) {
downloadButton.setAttribute('href', 'https://releases.hyper.is/download/rpm');
2017-01-27 17:45:42 -09:00
downloadButtonText.innerHTML += ' for <strong>Fedora</strong>';
document.getElementById('td-fedora').classList.add('highlighted');
} else {
downloadButton.setAttribute('href', 'https://releases.hyper.is/download/AppImage');
2017-01-27 17:45:42 -09:00
downloadButtonText.innerHTML += ' for <strong>Linux</strong>';
document.getElementById('td-appimage').classList.add('highlighted');
}
} else {
document.getElementById('fallback-icon').classList.remove('is-hidden');
document.getElementsByClassName('other-downloads')[0].classList.add('is-hidden');
}
});
var header = document.getElementById('header');
window.addEventListener('scroll', function () {
if (window.scrollY > 200) {
header.classList.add('hidden');
} else {
header.classList.remove('hidden');
}
});
</script>
</body>
2017-08-04 14:05:10 -08:00
</html>