Merge branch 'website-changes' into 'dev'

Update the Contact page and other minor improvements to the website

See merge request ligolang/ligo!607
This commit is contained in:
Francis Brunelle 2020-06-03 22:30:39 +00:00
commit 5cfe6e893c
34 changed files with 2034 additions and 1230 deletions

View File

@ -3,7 +3,7 @@ id: cli-commands
title: CLI Commands
---
Contracts written in Ligo can be compiled using the `ligo` executable.
Contracts written in LIGO can be compiled using the `ligo` executable.
## Compiling a contract

View File

@ -3,26 +3,28 @@ id: installation
title: Installation
---
There are currently two ways to get started with Ligo. You can choose to use a Docker image, or to install packages for your Debian Linux distribution.
There are currently three ways to get started with LIGO. You can choose to use a Docker image, a static Linux binary or to install packages for your Debian Linux distribution.
## Dockerized installation (recommended)
> 🐳 You can find instructions on how to install Docker [here](https://docs.docker.com/install/).
It's easiest to use LIGO through one of its Docker images. You have two options:
* Use our installation script to set up a globally available LIGO
* Use our installation script to set up a globally available `ligo`
executable (see below). This manages the Docker bits for you.
* Use the Docker image available at [Docker Hub](https://hub.docker.com/r/ligolang/ligo).
This lets you run multiple versions and keep your installation(s) self contained, but requires more familiarity with Docker.
This lets you run multiple versions and keep your installation(s) self-contained but requires more familiarity with Docker.
Sources for the image can be found on [GitLab](https://gitlab.com/ligolang/ligo/blob/master/docker/Dockerfile).
If this is your first time using Docker, you probably want to set up a global LIGO executable as shown below.
If this is your first time using Docker, you probably want to set up a global `ligo` executable as shown below.
### Setting up a globally available `ligo` executable
> You can install additional ligo versions by replacing `next` with the desired version number
<!--
> You can install additional LIGO versions by replacing `next` with the desired version number
-->
Download the latest binaries here: https://gitlab.com/ligolang/ligo/pipelines/85536879/builds or get the latest pre-release:
Get the latest pre-release:
```zsh
# next (pre-release)
@ -35,7 +37,7 @@ curl https://gitlab.com/ligolang/ligo/raw/master/scripts/installer.sh | bash -s
```
-->
**Verify your ligo installation by running:**
**Verify your LIGO installation by running:**
```zsh
ligo --help
```
@ -44,7 +46,7 @@ ligo --help
The `ligo` executable is statically linked. It should run on most modern Linux distributions.
To use it, get it [here](/bin/linux/ligo), make it executable, you're done!
To use it, get it [here](https://ligolang.org/bin/linux/ligo), make it executable, you're done!
```zsh
wget https://ligolang.org/bin/linux/ligo
@ -60,7 +62,7 @@ sudo cp ./ligo /usr/local/bin
## Debian Linux package installation
A `.deb` package containing the static `ligo` executable is also available.
First download [the package](/deb/ligo.deb), and then install using:
First, download [the package](https://ligolang.org/deb/ligo.deb), and then install using:
```zsh
sudo apt install ./ligo.deb

View File

@ -1,6 +1,6 @@
---
id: introduction
title: Introduction To LIGO
title: Introduction to LIGO
---
import Tabs from '@theme/Tabs';
@ -9,13 +9,13 @@ import TabItem from '@theme/TabItem';
LIGO is a programming language for writing [Tezos](https://tezos.com/) smart contracts.
Smart contracts are a unique domain with extreme resource constraints and even
more extreme security risks. Unlike desktop, mobile, or web
application development smart contracts cannot rely on cheap CPU time and memory.
application development, smart contracts cannot rely on cheap CPU time and memory.
All resources used by contracts are expensive, and tracked as 'gas costs'. Smart
contracts often directly control money or assets, which if stolen could rack up to
a large financial loss to the contracts controllers and users. Tezos smart contracts
live on the blockchain forever, if there's a bug in them they can't be patched or
amended. Naturally under these conditions it's not possible to develop smart contracts
the way we're used to developing user facing applications.
amended. Naturally, under these conditions, it's not possible to develop smart contracts
the way we're used to developing user-facing applications.
LIGO is designed with these problems in mind. The design philosophy can be
described in a few bullet points:
@ -29,7 +29,7 @@ compiled output using a project like [Mi-Cho-Coq](https://gitlab.com/nomadic-lab
4. Significantly reduce the risk that your smart contract will lose its balance to an [avoidable exploit](https://www.wired.com/2016/06/50-million-hack-just-showed-dao-human/).
LIGO is a functional language designed to include the features you need, while
LIGO is a functional language designed to include the features you need while
avoiding patterns that make formal verification hard. Most useful smart contracts
can express their core functionality in under a thousand lines of code. This makes
them a good target for formal methods, and what can't be easily proven can at least
@ -41,11 +41,11 @@ LIGO currently offers three syntaxes:
- **PascaLIGO**, a syntax inspired by Pascal which provides an
imperative developer experience.
- **CameLIGO**, an [OCaml]((https://ocaml.org/)) inspired
- **CameLIGO**, an [OCaml](https://ocaml.org/) inspired
syntax that allows you to write in a functional style.
- **ReasonLIGO**, an [ReasonML]((https://reasonml.github.io/)) inspired syntax
that builds on the strong points of OCaml. It aims to be familiar for those
- **ReasonLIGO**, a [ReasonML](https://reasonml.github.io/) inspired syntax
that builds on the strong points of OCaml. It aims to be familiar to those
coming from JavaScript.
Let's define some LIGO contract in the three flavours above. Do
@ -134,20 +134,19 @@ This LIGO contract accepts the following LIGO expressions:
---
## Runnable code snippets & exercises
## Runnable code snippets
Some of the sections in this documentation will include runnable code snippets and exercises. Sources for those are available at
Some of the sections in this documentation will include runnable code snippets. Sources for those are available at
the [LIGO Gitlab repository](https://gitlab.com/ligolang/ligo).
### Snippets
For example **code snippets** for the *Types* subsection of this doc, can be found here:
`gitlab-pages/docs/language-basics/src/types/**`
### Exercises
Solutions to exercises can be found e.g. here: `gitlab-pages/docs/language-basics/exercises/types/**/solutions/**`
### Running snippets
### Running snippets / exercise solutions
In certain cases it makes sense to be able to run/evaluate the given snippet or a solution, usually there'll be an example command which you can use, such as:
In certain cases it makes sense to be able to run/evaluate the given snippet. Usually there'll be an example command which you can use, such as:
```shell
ligo evaluate-value -s pascaligo gitlab-pages/docs/language-basics/src/variables-and-constants/const.ligo age

View File

@ -342,7 +342,7 @@ At the moment, recursive function are limited to one (possibly tupled) parameter
limited to tail recursion (i.e the recursive call should be the last expression of the function)
<Syntax syntax="pascaligo">
In PascaLigo recursive functions are defined using the `recursive` keyword
In PascaLIGO recursive functions are defined using the `recursive` keyword
```pascaligo group=d
recursive function sum (const n : int; const acc: int) : int is
@ -353,7 +353,7 @@ recursive function fibo (const n: int; const n_1: int; const n_0 :int) : int is
```
</Syntax>
<Syntax syntax="cameligo">
In CameLigo recursive functions are defined using the `rec` keyword
In CameLIGO recursive functions are defined using the `rec` keyword
```cameligo group=d
let rec sum ((n,acc):int * int) : int =
@ -364,7 +364,7 @@ let rec fibo ((n,n_1,n_0):int*int*int) : int =
```
</Syntax>
<Syntax syntax="reasonligo">
In ReasonLigo recursive functions are defined using the `rec` keyword
In ReasonLIGO recursive functions are defined using the `rec` keyword
```reasonligo group=d
let rec sum = ((n, acc) : (int,int)): int =>

View File

@ -16,7 +16,7 @@ a *field name* and a *field type*. Given a value of a record type, the
value bound to a field can be accessed by giving its field name to a
special operator (`.`).
Let us first consider and example of record type declaration.
Let us first consider an example of record type declaration.
<Syntax syntax="pascaligo">

View File

@ -742,9 +742,7 @@ val set_delegate : key_hash option -> operation
let set_delegate: option(key_hash) => operation
</SyntaxTitle>
Modify the
(delegate)[http://tezos.gitlab.io/user/glossary.html?highlight=delegate#delegate]
of the current contract.
Modify the [delegate](http://tezos.gitlab.io/user/glossary.html?highlight=delegate#delegate) of the current contract.
The operation fails when:
- the delegate is the same as current delegate

View File

@ -1,6 +1,6 @@
---
id: toplevel
title: Toplevel
title: Top-Level
description: Available functions at the top level
hide_table_of_contents: true
---

View File

@ -113,14 +113,14 @@ const siteConfig = {
// template. For example, if you need your repo's URL...
// repoUrl: repoUrl,
plugins: [
'@ligo/syntax', {
require.resolve('@ligo/syntax', {
},
'@docusaurus/plugin-sitemap', {
cacheTime: 600 * 1000, // 600 sec - cache purge period
changefreq: 'weekly',
priority: 0.5,
}
})
],
presets: [
@ -156,17 +156,18 @@ const siteConfig = {
srcDark: 'img/logo-night.svg'
},
links: [
{ href: 'https://ide.ligolang.org/', label: 'Try Online' },
{ to: 'docs/intro/installation', label: 'Install' },
{ to: 'docs/intro/introduction', label: 'Docs' },
{ href: 'https://ide.ligolang.org/', label: 'Try Online', position: 'left', target: '_self' },
{ to: 'docs/intro/installation', label: 'Install', position: 'left' },
{ to: 'docs/intro/introduction', label: 'Docs', position: 'left' },
{
to: 'docs/tutorials/get-started/tezos-taco-shop-smart-contract',
label: 'Tutorials'
label: 'Tutorials',
position: 'left'
},
{ href: 'https://forum.tezosagora.org/tag/ligo', label: 'Blog' },
{ href: 'https://forum.tezosagora.org/tag/ligo', label: 'Blog', position: 'left' },
// TODO: { href: "/odoc", label: "API" },
// { doc: 'contributors/origin', label: 'Contribute' },
{ to: '/contact', label: 'Ask Questions' }
{ to: '/contact', label: 'Ask Questions', position: 'left' }
],
},
footer: {
@ -176,28 +177,28 @@ const siteConfig = {
items: [
{ to: 'docs/intro/installation', label: 'Install' },
{ to: 'docs/api/cli-commands', label: 'CLI Commands' },
{ to: 'docs/contributors/origin', label: 'Contribute' },
{ to: '/odoc', label: 'API Documentation' }
{ to: 'docs/api/cheat-sheet', label: 'Cheat Sheet' },
{ href: 'https://ligolang.org/odoc/', label: 'API Documentation' }
]
},
{
title: 'Community',
items: [
{
href: 'https://forum.tezosagora.org/tag/ligo',
label: 'Tezos Agora Forum'
},
{
href: 'https://tezos.stackexchange.com/questions/tagged/ligo',
label: 'Tezos Stack Exchange'
},
{
href: 'https://discord.gg/9rhYaEt',
label: 'Discord'
},
{
href: 'https://t.me/LigoLang',
label: 'Telegram'
},
{
href: 'https://discord.gg/9rhYaEt',
label: 'Discord'
href: 'https://riot.im/app/#/room/#ligo-public:matrix.org',
label: 'Riot'
}
]
},
@ -208,9 +209,17 @@ const siteConfig = {
label: 'Tutorials',
to: 'docs/tutorials/get-started/tezos-taco-shop-smart-contract'
},
{
href: 'https://forum.tezosagora.org/tag/ligo',
label: 'Blog'
},
{
label: 'GitLab',
href: repoUrl
},
{
label: 'Contribute',
to: 'docs/contributors/origin'
}
]
}

File diff suppressed because it is too large Load Diff

View File

@ -8,8 +8,8 @@
"deploy": "docusaurus deploy"
},
"devDependencies": {
"@docusaurus/core": "^2.0.0-alpha.43",
"@docusaurus/preset-classic": "^2.0.0-alpha.43",
"@docusaurus/core": "^2.0.0-alpha.56",
"@docusaurus/preset-classic": "^2.0.0-alpha.56",
"classnames": "^2.2.6",
"react": "^16.13.0",
"react-dom": "^16.13.0",
@ -28,7 +28,7 @@
]
},
"dependencies": {
"@docusaurus/plugin-sitemap": "^2.0.0-alpha.37",
"@docusaurus/plugin-sitemap": "^2.0.0-alpha.56",
"@ligo/syntax": "file:src/@ligo/syntax"
}
}

View File

@ -6,10 +6,24 @@ const TEAM = [
{
firstName: 'Christian',
lastName: 'Rinderknecht',
image: 'img/christian.jpeg',
image: 'img/christian.jpg',
link: 'https://github.com/rinderknecht',
pinned: true
},
{
firstName: 'Eowyn',
lastName: 'Dean',
image: 'img/eowyn.jpg',
link: 'https://gitlab.com/dernhelm7',
pinned: true
},
{
firstName: 'Francis',
lastName: 'Brunelle',
image: 'img/francis.jpg',
link: 'https://github.com/frabrunelle',
pinned: true
},
{
firstName: 'Gabriel',
lastName: 'Alfour',
@ -17,6 +31,13 @@ const TEAM = [
link: 'https://gitlab.com/gabriel.alfour',
pinned: true
},
{
firstName: 'Pierre-Emmanuel',
lastName: 'Wolfman',
image: 'img/pierre-emmanuel.jpg',
link: 'https://gitlab.com/Popu-sama',
pinned: true
},
{
firstName: 'Sander',
lastName: 'Spies',
@ -27,27 +48,32 @@ const TEAM = [
{
firstName: 'Suzanne',
lastName: 'Dupéron',
image: 'img/suzanne.jpeg',
image: 'img/suzanne.jpg',
link: 'https://gitlab.com/suzanne.duperon',
pinned: true
}
];
const COMMUNICATION_CHANNELS = [
{
link: 'https://discord.gg/9rhYaEt',
icon: 'img/discord.svg',
description: "Join our Discord server. We're here to help."
},
{
link: 'https://t.me/LigoLang',
icon: 'img/telegram.svg',
description: "We're here to help. Ask us anything"
description: "We're also on Telegram. Ask us anything!"
},
{
link: 'https://gitlab.com/ligolang/ligo/issues',
icon: 'img/gitlab.svg',
description: 'Need a fix? Create an issue on GitLab'
description: 'Need a fix? Create an issue on GitLab.'
},
{
link: 'https://twitter.com/ligolang',
icon: 'img/twitter.svg',
description: 'Join the latest chit-chat'
description: 'Join the latest chit-chat and follow us on Twitter!'
}
];

View File

@ -88,7 +88,7 @@ const FEATURES = [
{
image: 'img/easy-integration.svg',
title: 'Easy Integration',
content: 'You can use LIGO as a NodeJS library with Granary'
content: 'You can use LIGO as a Node.js library with Truffle.'
}
];
@ -100,9 +100,9 @@ const PARTNERS = [
pinned: true
},
{
name: 'Tocqueville Group',
name: 'TQ Tezos',
image: 'img/tq-logo.svg',
link: 'https://tqgroup.io/',
link: 'https://tqtezos.com/',
pinned: true
},
{

View File

@ -1,15 +1,17 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable jsx-a11y/no-noninteractive-tabindex */
import React, { useEffect, useState, useRef } from 'react';
import classnames from 'classnames';
import Highlight, { defaultProps } from 'prism-react-renderer';
const { Prism } = require("prism-react-renderer");
import Prism from 'prism-react-renderer/prism';
Prism.languages = {
...Prism.languages,
@ -88,11 +90,79 @@ import useThemeContext from '@theme/hooks/useThemeContext';
import styles from './styles.module.css';
const highlightLinesRangeRegex = /{([\d,-]+)}/;
const getHighlightDirectiveRegex = (
languages = ['js', 'jsBlock', 'jsx', 'python', 'html'],
) => {
// supported types of comments
const comments = {
js: {
start: '\\/\\/',
end: '',
},
jsBlock: {
start: '\\/\\*',
end: '\\*\\/',
},
jsx: {
start: '\\{\\s*\\/\\*',
end: '\\*\\/\\s*\\}',
},
python: {
start: '#',
end: '',
},
html: {
start: '<!--',
end: '-->',
},
};
// supported directives
const directives = [
'highlight-next-line',
'highlight-start',
'highlight-end',
].join('|');
// to be more reliable, the opening and closing comment must match
const commentPattern = languages
.map(
(lang) =>
`(?:${comments[lang].start}\\s*(${directives})\\s*${comments[lang].end})`,
)
.join('|');
// white space is allowed, but otherwise it should be on it's own line
return new RegExp(`^\\s*(?:${commentPattern})\\s*$`);
};
// select comment styles based on language
const highlightDirectiveRegex = (lang) => {
switch (lang) {
case 'js':
case 'javascript':
case 'ts':
case 'typescript':
return getHighlightDirectiveRegex(['js', 'jsBlock']);
export default ({ children, className: languageClassName, metastring }) => {
case 'jsx':
case 'tsx':
return getHighlightDirectiveRegex(['js', 'jsBlock', 'jsx']);
case 'html':
return getHighlightDirectiveRegex(['js', 'jsBlock', 'html']);
case 'python':
case 'py':
return getHighlightDirectiveRegex(['python']);
default:
// all comment types
return getHighlightDirectiveRegex();
}
};
const codeBlockTitleRegex = /title=".*"/;
export default ({children, className: languageClassName, metastring}) => {
const {
siteConfig: {
themeConfig: { prism = {} },
themeConfig: {prism = {}},
},
} = useDocusaurusContext();
@ -112,15 +182,25 @@ export default ({ children, className: languageClassName, metastring }) => {
const target = useRef(null);
const button = useRef(null);
let highlightLines = [];
let codeBlockTitle = '';
const { isDarkTheme } = useThemeContext();
const {isDarkTheme} = useThemeContext();
const lightModeTheme = prism.theme || defaultTheme;
const darkModeTheme = prism.darkTheme || lightModeTheme;
const prismTheme = isDarkTheme ? darkModeTheme : lightModeTheme;
if (metastring && highlightLinesRangeRegex.test(metastring)) {
const highlightLinesRange = metastring.match(highlightLinesRangeRegex)[1];
highlightLines = rangeParser.parse(highlightLinesRange).filter(n => n > 0);
highlightLines = rangeParser
.parse(highlightLinesRange)
.filter((n) => n > 0);
}
if (metastring && codeBlockTitleRegex.test(metastring)) {
codeBlockTitle = metastring
.match(codeBlockTitleRegex)[0]
.split('title=')[1]
.replace(/"+/g, '');
}
useEffect(() => {
@ -146,6 +226,50 @@ export default ({ children, className: languageClassName, metastring }) => {
language = prism.defaultLanguage;
}
// only declaration OR directive highlight can be used for a block
let code = children.replace(/\n$/, '');
if (highlightLines.length === 0 && language !== undefined) {
let range = '';
const directiveRegex = highlightDirectiveRegex(language);
// go through line by line
const lines = children.replace(/\n$/, '').split('\n');
let blockStart;
// loop through lines
for (let index = 0; index < lines.length; ) {
const line = lines[index];
// adjust for 0-index
const lineNumber = index + 1;
const match = line.match(directiveRegex);
if (match !== null) {
const directive = match
.slice(1)
.reduce((final, item) => final || item, undefined);
switch (directive) {
case 'highlight-next-line':
range += `${lineNumber},`;
break;
case 'highlight-start':
blockStart = lineNumber;
break;
case 'highlight-end':
range += `${blockStart}-${lineNumber - 1},`;
break;
default:
break;
}
lines.splice(index, 1);
} else {
// lines without directives are unchanged
index += 1;
}
}
highlightLines = rangeParser.parse(range);
code = lines.join('\n');
}
const handleCopyCode = () => {
window.getSelection().empty();
setShowCopied(true);
@ -158,41 +282,55 @@ export default ({ children, className: languageClassName, metastring }) => {
{...defaultProps}
key={mounted}
theme={prismTheme}
code={children.trim()}
code={code}
language={language}>
{({ className, style, tokens, getLineProps, getTokenProps }) => (
<pre className={classnames(className, styles.codeBlock)}>
<button
ref={button}
type="button"
aria-label="Copy code to clipboard"
className={styles.copyButton}
onClick={handleCopyCode}>
{showCopied ? 'Copied' : 'Copy'}
</button>
{({className, style, tokens, getLineProps, getTokenProps}) => (
<>
{codeBlockTitle && (
<div style={style} className={styles.codeBlockTitle}>
{codeBlockTitle}
</div>
)}
<div className={styles.codeBlockContent}>
<button
ref={button}
type="button"
aria-label="Copy code to clipboard"
className={classnames(styles.copyButton, {
[styles.copyButtonWithTitle]: codeBlockTitle,
})}
onClick={handleCopyCode}>
{showCopied ? 'Copied' : 'Copy'}
</button>
<div
tabIndex="0"
className={classnames(className, styles.codeBlock, {
[styles.codeBlockWithTitle]: codeBlockTitle,
})}>
<div ref={target} className={styles.codeBlockLines} style={style}>
{tokens.map((line, i) => {
if (line.length === 1 && line[0].content === '') {
line[0].content = '\n'; // eslint-disable-line no-param-reassign
}
<code ref={target} className={styles.codeBlockLines}>
{tokens.map((line, i) => {
if (line.length === 1 && line[0].content === '') {
line[0].content = '\n'; // eslint-disable-line no-param-reassign
}
const lineProps = getLineProps({line, key: i});
const lineProps = getLineProps({ line, key: i });
if (highlightLines.includes(i + 1)) {
lineProps.className = `${lineProps.className} docusaurus-highlight-code-line`;
}
if (highlightLines.includes(i + 1)) {
lineProps.className = `${lineProps.className} docusaurus-highlight-code-line`;
}
return (
<div key={i} {...lineProps}>
{line.map((token, key) => (
<span key={key} {...getTokenProps({ token, key })} />
))}
</div>
);
})}
</code>
</pre>
return (
<div key={i} {...lineProps}>
{line.map((token, key) => (
<span key={key} {...getTokenProps({token, key})} />
))}
</div>
);
})}
</div>
</div>
</div>
</>
)}
</Highlight>
);

View File

@ -1,44 +1,62 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
.codeBlockContent {
position: relative;
}
.codeBlockTitle {
border-top-left-radius: var(--ifm-global-radius);
border-top-right-radius: var(--ifm-global-radius);
border-bottom: 1px solid var(--ifm-color-emphasis-200);
font-family: var(--ifm-font-family-monospace);
font-weight: bold;
padding: 0.75rem var(--ifm-pre-padding);
width: 100%;
}
.codeBlock {
overflow: auto;
display: block;
padding: 0;
margin: 0;
border-radius: var(--ifm-global-radius);
}
.codeBlockWithTitle {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
.copyButton {
background: rgb(1, 22, 39);
border: 1px solid rgb(214, 222, 235);
background: rgba(0, 0, 0, 0.3);
border: none;
border-radius: var(--ifm-global-radius);
color: rgb(214, 222, 235);
color: var(--ifm-color-white);
cursor: pointer;
line-height: 12px;
opacity: 0;
outline: none;
padding: 4px 8px;
padding: 0.4rem 0.5rem;
position: absolute;
right: var(--ifm-pre-padding);
top: var(--ifm-pre-padding);
right: calc(var(--ifm-pre-padding) / 2);
top: calc(var(--ifm-pre-padding) / 2);
visibility: hidden;
transition: opacity 200ms ease-in-out, visibility 200ms ease-in-out,
bottom 200ms ease-in-out;
}
.codeBlock:hover > .copyButton {
.codeBlockTitle:hover + .codeBlockContent .copyButton,
.codeBlockContent:hover > .copyButton {
visibility: visible;
opacity: 1;
}
.codeBlockLines {
background-color: transparent;
border-radius: 0;
margin-bottom: 0;
font-family: var(--ifm-font-family-monospace);
font-size: inherit;
line-height: var(--ifm-pre-line-height);
white-space: pre;
float: left;
min-width: 100%;
padding: var(--ifm-pre-padding);

View File

@ -0,0 +1,217 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React from 'react';
import Head from '@docusaurus/Head';
import isInternalUrl from '@docusaurus/isInternalUrl';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useBaseUrl from '@docusaurus/useBaseUrl';
import DocPaginator from '@theme/DocPaginator';
import useTOCHighlight from '@theme/hooks/useTOCHighlight';
import classnames from 'classnames';
import styles from './styles.module.css';
const LINK_CLASS_NAME = 'table-of-contents__link';
const ACTIVE_LINK_CLASS_NAME = 'table-of-contents__link--active';
const TOP_OFFSET = 100;
function DocTOC({headings}) {
useTOCHighlight(LINK_CLASS_NAME, ACTIVE_LINK_CLASS_NAME, TOP_OFFSET);
return (
<div className="col col--3">
<div className={styles.tableOfContents}>
<Headings headings={headings} />
</div>
</div>
);
}
/* eslint-disable jsx-a11y/control-has-associated-label */
function Headings({headings, isChild}) {
if (!headings.length) {
return null;
}
return (
<ul
className={
isChild ? '' : 'table-of-contents table-of-contents__left-border'
}>
{headings.map((heading) => (
<li key={heading.id}>
<a
href={`#${heading.id}`}
className={LINK_CLASS_NAME}
dangerouslySetInnerHTML={{__html: heading.value}}
/>
<Headings isChild headings={heading.children} />
</li>
))}
</ul>
);
}
function DocItem(props) {
const {siteConfig = {}} = useDocusaurusContext();
const {url: siteUrl, title: siteTitle} = siteConfig;
const {content: DocContent} = props;
const {metadata} = DocContent;
const {
description,
title,
permalink,
editUrl,
lastUpdatedAt,
lastUpdatedBy,
version,
} = metadata;
const {
frontMatter: {
image: metaImage,
keywords,
hide_title: hideTitle,
hide_table_of_contents: hideTableOfContents,
},
} = DocContent;
const metaTitle = title ? `${title} | ${siteTitle}` : siteTitle;
let metaImageUrl = siteUrl + useBaseUrl(metaImage);
if (!isInternalUrl(metaImage)) {
metaImageUrl = metaImage;
}
return (
<>
<Head>
<title>{metaTitle}</title>
<meta property="og:title" content={metaTitle} />
{description && <meta name="description" content={description} />}
{description && (
<meta property="og:description" content={description} />
)}
{keywords && keywords.length && (
<meta name="keywords" content={keywords.join(',')} />
)}
{metaImage && <meta property="og:image" content={metaImageUrl} />}
{metaImage && <meta property="twitter:image" content={metaImageUrl} />}
{metaImage && (
<meta name="twitter:image:alt" content={`Image for ${title}`} />
)}
{permalink && <meta property="og:url" content={siteUrl + permalink} />}
{permalink && <link rel="canonical" href={siteUrl + permalink} />}
</Head>
<div
className={classnames(
'container padding-vert--lg',
styles.docItemWrapper,
)}>
<div className="row">
<div
className={classnames('col', {
[styles.docItemCol]: !hideTableOfContents,
})}>
<div className={styles.docItemContainer}>
<article>
{version && (
<div>
<span className="badge badge--secondary">
Version: {version}
</span>
</div>
)}
{!hideTitle && (
<header>
<h1 className={styles.docTitle}>{title}</h1>
</header>
)}
<div className="markdown">
<DocContent />
</div>
</article>
{(editUrl || lastUpdatedAt || lastUpdatedBy) && (
<div className="margin-vert--xl">
<div className="row">
<div className="col">
{editUrl && (
<a
href={editUrl}
target="_blank"
rel="noreferrer noopener">
<svg
fill="currentColor"
height="1.2em"
width="1.2em"
preserveAspectRatio="xMidYMid meet"
viewBox="0 0 40 40"
style={{
marginRight: '0.3em',
verticalAlign: 'sub',
}}>
<g>
<path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z" />
</g>
</svg>
Edit this page
</a>
)}
</div>
{(lastUpdatedAt || lastUpdatedBy) && (
<div className="col text--right">
<em>
<small>
Last updated{' '}
{lastUpdatedAt && (
<>
on{' '}
<time
dateTime={new Date(
lastUpdatedAt * 1000,
).toISOString()}
className={styles.docLastUpdatedAt}>
{new Date(
lastUpdatedAt * 1000,
).toLocaleDateString()}
</time>
{lastUpdatedBy && ' '}
</>
)}
{lastUpdatedBy && (
<>
by <strong>{lastUpdatedBy}</strong>
</>
)}
{process.env.NODE_ENV === 'development' && (
<div>
<small>
{' '}
(Simulated during dev for better perf)
</small>
</div>
)}
</small>
</em>
</div>
)}
</div>
</div>
)}
<div className="margin-vert--lg">
<DocPaginator metadata={metadata} />
</div>
</div>
</div>
{!hideTableOfContents && DocContent.rightToc && (
<DocTOC headings={DocContent.rightToc} />
)}
</div>
</div>
</>
);
}
export default DocItem;

View File

@ -0,0 +1,70 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
.docTitle {
font-size: 3rem;
margin-bottom: calc(var(--ifm-leading-desktop) * var(--ifm-leading));
}
.docItemContainer {
margin: 0 auto;
padding: 0 0.5rem;
}
@media only screen and (min-width: 997px) {
.docItemCol {
max-width: 75% !important;
}
}
@media (min-width: 997px) and (max-width: 1320px) {
.docItemWrapper {
max-width: calc(
var(--ifm-container-width) - 300px - var(--ifm-spacing-horizontal) * 2
);
}
}
.tableOfContents {
display: inherit;
max-height: calc(100vh - (var(--ifm-navbar-height) + 2rem));
overflow-y: auto;
position: sticky;
top: calc(var(--ifm-navbar-height) + 2rem);
}
.tableOfContents::-webkit-scrollbar {
width: 7px;
}
.tableOfContents::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 10px;
}
.tableOfContents::-webkit-scrollbar-thumb {
background: #888;
border-radius: 10px;
}
.tableOfContents::-webkit-scrollbar-thumb:hover {
background: #555;
}
@media only screen and (max-width: 996px) {
.tableOfContents {
display: none;
}
.docItemContainer {
padding: 0 0.3rem;
}
}
.docLastUpdatedAt {
font-weight: bold;
}

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
@ -11,6 +11,7 @@ import {MDXProvider} from '@mdx-js/react';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import renderRoutes from '@docusaurus/renderRoutes';
import Layout from '@theme/Layout';
import DocItem from '@theme/DocItem';
import DocSidebar from '@theme/DocSidebar';
import MDXComponents from '@theme/MDXComponents';
import NotFound from '@theme/NotFound';
@ -21,20 +22,29 @@ import styles from './styles.module.css';
import SyntaxContext from '@theme/Syntax/SyntaxContext';
function DocPage(props) {
const {route: baseRoute, docsMetadata, location} = props;
// case-sensitive route such as it is defined in the sidebar
const currentRoute =
baseRoute.routes.find(route => {
return matchPath(location.pathname, route);
}) || {};
const {permalinkToSidebar, docsSidebars, version} = docsMetadata;
const sidebar = permalinkToSidebar[currentRoute.path];
const {route: baseRoute, docsMetadata, location, content} = props;
const {
siteConfig: {themeConfig = {}} = {},
permalinkToSidebar,
docsSidebars,
version,
isHomePage,
homePagePath,
} = docsMetadata;
// Get case-sensitive route such as it is defined in the sidebar.
const currentRoute = !isHomePage
? baseRoute.routes.find((route) => {
return matchPath(location.pathname, route);
}) || {}
: {};
const sidebar = isHomePage
? content.metadata.sidebar
: permalinkToSidebar[currentRoute.path];
const {
siteConfig: {themeConfig: {sidebarCollapsible = true} = {}} = {},
isClient,
} = useDocusaurusContext();
const {sidebarCollapsible = true} = themeConfig;
let defaultSyntax = 'pascaligo';
if (isClient) {
@ -43,7 +53,7 @@ function DocPage(props) {
const [syntax, setSyntax] = useState(defaultSyntax);
if (Object.keys(currentRoute).length === 0) {
if (!isHomePage && Object.keys(currentRoute).length === 0) {
return <NotFound {...props} />;
}
@ -55,7 +65,7 @@ function DocPage(props) {
<div className={styles.docSidebarContainer}>
<DocSidebar
docsSidebars={docsSidebars}
path={currentRoute.path}
path={isHomePage ? homePagePath : currentRoute.path}
sidebar={sidebar}
sidebarCollapsible={sidebarCollapsible}
syntax={syntax}
@ -68,7 +78,11 @@ function DocPage(props) {
)}
<main className={styles.docMainContainer}>
<MDXProvider components={MDXComponents}>
{renderRoutes(baseRoute.routes)}
{isHomePage ? (
<DocItem content={content} />
) : (
renderRoutes(baseRoute.routes)
)}
</MDXProvider>
</main>
</div>

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
@ -10,11 +10,11 @@
}
.docSidebarContainer {
border-right: 1px solid var(--ifm-contents-border-color);
border-right: 1px solid var(--ifm-toc-border-color);
box-sizing: border-box;
width: 300px;
position: relative;
top: calc(-1 * var(--ifm-navbar-height));
margin-top: calc(-1 * var(--ifm-navbar-height));
}
.docMainContainer {

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
@ -8,19 +8,24 @@
import React, {useState, useCallback} from 'react';
import classnames from 'classnames';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useBaseUrl from '@docusaurus/useBaseUrl';
import useLockBodyScroll from '@theme/hooks/useLockBodyScroll';
import useLogo from '@theme/hooks/useLogo';
import Link from '@docusaurus/Link';
import isInternalUrl from '@docusaurus/utils'; // eslint-disable-line import/no-extraneous-dependencies
import isInternalUrl from '@docusaurus/isInternalUrl';
import styles from './styles.module.css';
import SyntaxSwitch from '@theme/Syntax/SyntaxSwitch';
const MOBILE_TOGGLE_SIZE = 24;
function DocSidebarItem({item, onItemClick, collapsible}) {
function DocSidebarItem({
item,
onItemClick,
collapsible,
activePath,
...props
}) {
const {items, href, label, type} = item;
const [collapsed, setCollapsed] = useState(item.collapsed);
const [prevCollapsedProp, setPreviousCollapsedProp] = useState(null);
@ -33,9 +38,10 @@ function DocSidebarItem({item, onItemClick, collapsible}) {
setCollapsed(item.collapsed);
}
const handleItemClick = useCallback(e => {
const handleItemClick = useCallback((e) => {
e.preventDefault();
setCollapsed(state => !state);
e.target.blur();
setCollapsed((state) => !state);
});
switch (type) {
@ -53,16 +59,19 @@ function DocSidebarItem({item, onItemClick, collapsible}) {
'menu__link--active': collapsible && !item.collapsed,
})}
href="#!"
onClick={collapsible ? handleItemClick : undefined}>
onClick={collapsible ? handleItemClick : undefined}
{...props}>
{label}
</a>
<ul className="menu__list">
{items.map(childItem => (
{items.map((childItem) => (
<DocSidebarItem
tabIndex={collapsed ? '-1' : '0'}
key={childItem.label}
item={childItem}
onItemClick={onItemClick}
collapsible={collapsible}
activePath={activePath}
/>
))}
</ul>
@ -75,18 +84,21 @@ function DocSidebarItem({item, onItemClick, collapsible}) {
return (
<li className="menu__list-item" key={label}>
<Link
className="menu__link"
className={classnames('menu__link', {
'menu__link--active': href === activePath,
})}
to={href}
{...(isInternalUrl(href)
? {
activeClassName: 'menu__link--active',
isNavLink: true,
exact: true,
onClick: onItemClick,
}
: {
target: '_blank',
rel: 'noreferrer noopener',
})}>
})}
{...props}>
{label}
</Link>
</li>
@ -102,8 +114,8 @@ function mutateSidebarCollapsingState(item, path) {
case 'category': {
const anyChildItemsActive =
items
.map(childItem => mutateSidebarCollapsingState(childItem, path))
.filter(val => val).length > 0;
.map((childItem) => mutateSidebarCollapsingState(childItem, path))
.filter((val) => val).length > 0;
// eslint-disable-next-line no-param-reassign
item.collapsed = !anyChildItemsActive;
return anyChildItemsActive;
@ -118,9 +130,12 @@ function mutateSidebarCollapsingState(item, path) {
function DocSidebar(props) {
const [showResponsiveSidebar, setShowResponsiveSidebar] = useState(false);
const {
siteConfig: {themeConfig: {navbar: {title, logo = {}} = {}}} = {}, isClient
siteConfig: {
themeConfig: {navbar: {title, hideOnScroll = false} = {}},
} = {},
isClient,
} = useDocusaurusContext();
const logoUrl = useBaseUrl(logo.src);
const {logoLink, logoLinkProps, logoImageUrl, logoAlt} = useLogo();
const {
docsSidebars,
@ -144,21 +159,29 @@ function DocSidebar(props) {
}
if (sidebarCollapsible) {
sidebarData.forEach(sidebarItem =>
sidebarData.forEach((sidebarItem) =>
mutateSidebarCollapsingState(sidebarItem, path),
);
}
return (
<div className={styles.sidebar}>
<div className={styles.sidebarLogo}>
{logo != null && <img src={logoUrl} alt={logo.alt} />}
{title != null && <strong>{title}</strong>}
</div>
{hideOnScroll && (
<Link
tabIndex="-1"
className={styles.sidebarLogo}
to={logoLink}
{...logoLinkProps}>
{logoImageUrl != null && (
<img key={isClient} src={logoImageUrl} alt={logoAlt} />
)}
{title != null && <strong>{title}</strong>}
</Link>
)}
{isClient && document.location.pathname.startsWith('/docs') && !showResponsiveSidebar ?
<div className={styles.switchContainer}>
Display syntax: <SyntaxSwitch syntax={props.syntax} onSyntaxChange={s => props.onSyntaxChange(s)} />
</div>
<div className={styles.switchContainer}>
Display syntax: <SyntaxSwitch syntax={props.syntax} onSyntaxChange={s => props.onSyntaxChange(s)} />
</div>
:
null
}
@ -168,14 +191,14 @@ function DocSidebar(props) {
})}>
{isClient && document.location.pathname.startsWith('/docs') && showResponsiveSidebar ?
<div className={styles.switchContainerResponsive}>
Display syntax:
<SyntaxSwitch syntax={props.syntax} onSyntaxChange={s => props.onSyntaxChange(s)} />
Display syntax: <SyntaxSwitch syntax={props.syntax} onSyntaxChange={s => props.onSyntaxChange(s)} />
</div>
:
null
}
:
null
}
<button
aria-label={showResponsiveSidebar ? 'Close Menu' : 'Open Menu'}
aria-haspopup="true"
className="button button--secondary button--sm menu__button"
type="button"
onClick={() => {
@ -191,6 +214,7 @@ function DocSidebar(props) {
</span>
) : (
<svg
aria-label="Menu"
className={styles.sidebarMenuIcon}
xmlns="http://www.w3.org/2000/svg"
height={MOBILE_TOGGLE_SIZE}
@ -210,14 +234,16 @@ function DocSidebar(props) {
)}
</button>
<ul className="menu__list">
{sidebarData.map(item => (
{sidebarData.map((item) => (
<DocSidebarItem
key={item.label}
item={item}
onItemClick={() => {
onItemClick={(e) => {
e.target.blur();
setShowResponsiveSidebar(false);
}}
collapsible={sidebarCollapsible}
activePath={path}
/>
))}
</ul>

View File

@ -1,5 +1,5 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
@ -39,6 +39,8 @@
top: 0;
margin: 0 var(--ifm-navbar-padding-horizontal);
height: var(--ifm-navbar-height);
color: inherit !important;
text-decoration: none !important;
}
.sidebarLogo img {

View File

@ -1,201 +0,0 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React, {useCallback, useState} from 'react';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useBaseUrl from '@docusaurus/useBaseUrl';
import SearchBar from '@theme/SearchBar';
import Toggle from '@theme/Toggle';
import classnames from 'classnames';
import useThemeContext from '@theme/hooks/useThemeContext';
import useHideableNavbar from '@theme/hooks/useHideableNavbar';
import useLockBodyScroll from '@theme/hooks/useLockBodyScroll';
import styles from './styles.module.css';
function NavLink({to, href, label, position, ...props}) {
const toUrl = useBaseUrl(to);
return (
<Link
className="navbar__item navbar__link"
{...(href
? {
target: '_blank',
rel: 'noopener noreferrer',
href,
}
: {
activeClassName: 'navbar__link--active',
to: toUrl,
})}
{...props}>
{label}
</Link>
);
}
function Navbar(props) {
const context = useDocusaurusContext();
const {siteConfig = {}} = context;
const {baseUrl, themeConfig = {}} = siteConfig;
const {navbar = {}, disableDarkMode = false} = themeConfig;
const {title, logo = {}, links = [], hideOnScroll = false} = navbar;
const [sidebarShown, setSidebarShown] = useState(false);
const [isSearchBarExpanded, setIsSearchBarExpanded] = useState(false);
const {isDarkTheme, setLightTheme, setDarkTheme} = useThemeContext();
const {navbarRef, isNavbarVisible} = useHideableNavbar(hideOnScroll);
useLockBodyScroll(sidebarShown);
const showSidebar = useCallback(() => {
setSidebarShown(true);
}, [setSidebarShown]);
const hideSidebar = useCallback(() => {
setSidebarShown(false);
}, [setSidebarShown]);
const onToggleChange = useCallback(
e => (e.target.checked ? setDarkTheme() : setLightTheme()),
[setLightTheme, setDarkTheme],
);
const logoLink = logo.href || baseUrl;
const isExternalLogoLink = /http/.test(logoLink);
const logoLinkProps = isExternalLogoLink
? {
rel: 'noopener noreferrer',
target: '_blank',
}
: null;
const logoSrc = logo.srcDark && isDarkTheme ? logo.srcDark : logo.src;
const logoImageUrl = useBaseUrl(logoSrc);
return (
<nav
ref={navbarRef}
className={classnames('navbar', 'navbar--light', 'navbar--fixed-top', {
'navbar-sidebar--show': sidebarShown,
[styles.navbarHideable]: hideOnScroll,
[styles.navbarHidden]: !isNavbarVisible,
})}>
<div className="navbar__inner">
<div className="navbar__items">
<div
aria-label="Navigation bar toggle"
className="navbar__toggle"
role="button"
tabIndex={0}
onClick={showSidebar}
onKeyDown={showSidebar}>
<svg
xmlns="http://www.w3.org/2000/svg"
width="30"
height="30"
viewBox="0 0 30 30"
role="img"
focusable="false">
<title>Menu</title>
<path
stroke="currentColor"
strokeLinecap="round"
strokeMiterlimit="10"
strokeWidth="2"
d="M4 7h22M4 15h22M4 23h22"
/>
</svg>
</div>
<Link className="navbar__brand" to={logoLink} {...logoLinkProps}>
{logo != null && (
<img className="navbar__logo" src={logoImageUrl} alt={logo.alt} />
)}
{title != null && (
<strong
className={isSearchBarExpanded ? styles.hideLogoText : ''}>
{title}
</strong>
)}
</Link>
{links
.filter(linkItem => linkItem.position !== 'right')
.map((linkItem, i) => (
<NavLink {...linkItem} key={i} />
))}
</div>
<div className="navbar__items navbar__items--right">
{links
.filter(linkItem => linkItem.position === 'right')
.map((linkItem, i) => (
<NavLink {...linkItem} key={i} />
))}
{!disableDarkMode && (
<Toggle
className={styles.displayOnlyInLargeViewport}
aria-label="Dark mode toggle"
checked={isDarkTheme}
onChange={onToggleChange}
/>
)}
<SearchBar
handleSearchBarToggle={setIsSearchBarExpanded}
isSearchBarExpanded={isSearchBarExpanded}
/>
</div>
</div>
<div
role="presentation"
className="navbar-sidebar__backdrop"
onClick={hideSidebar}
/>
<div className="navbar-sidebar">
<div className="navbar-sidebar__brand">
<Link
className="navbar__brand"
onClick={hideSidebar}
to={logoLink}
{...logoLinkProps}>
{logo != null && (
<img className="navbar__logo" src={logoImageUrl} alt={logo.alt} />
)}
{title != null && <strong>{title}</strong>}
</Link>
{!disableDarkMode && sidebarShown && (
<Toggle
aria-label="Dark mode toggle in sidebar"
checked={isDarkTheme}
onChange={onToggleChange}
/>
)}
</div>
<div className="navbar-sidebar__items">
<div className="menu">
<ul className="menu__list">
{links.map((linkItem, i) => (
<li className="menu__list-item" key={i}>
<NavLink
className="menu__link"
{...linkItem}
onClick={hideSidebar}
/>
</li>
))}
</ul>
</div>
</div>
</div>
</nav>
);
}
export default Navbar;

View File

@ -1,26 +0,0 @@
/**
* Copyright (c) 2017-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
@media screen and (max-width: 997px) {
.displayOnlyInLargeViewport {
display: none !important;
}
}
@media (max-width: 360px) {
.hideLogoText {
display: none;
}
}
.navbarHideable {
transition: top 0.2s ease-in-out;
}
.navbarHidden {
top: calc(var(--ifm-navbar-height) * -1) !important;
}

View File

@ -507,7 +507,6 @@ a:hover {
#contactPage,
#pageNotFoundPage {
font-weight: lighter;
margin-top: 80px;
margin-bottom: 80px;
}
@ -692,7 +691,7 @@ a:hover {
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 1.25em;
font-size: 0.85em;
font-weight: normal;
color: white;
}
@ -735,6 +734,8 @@ a:hover {
cursor: pointer;
background-color: var(--lighter-blue);
border-left: 6px solid var(--blue);
color: black;
text-decoration: none;
}
#contactPage #message .communicationOptions .option .icon {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

View File

@ -41,7 +41,7 @@ const App: React.FC = () => {
<FloatButtonComponent
tooltip="Report an issue"
text="!"
href="https://gitlab.com/ligolang/ligo-web-ide/issues"
href="https://gitlab.com/ligolang/ligo/issues"
></FloatButtonComponent>
<FloatButtonComponent
tooltip="Ask a question"

View File

@ -1,12 +1,12 @@
import React from 'react';
import styled from 'styled-components';
import styled, { css } from 'styled-components';
const Container = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5em 1em;
padding: 0.3em 1em;
font-family: 'DM Sans', 'Open Sans', sans-serif;
box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.3);
@ -24,11 +24,23 @@ const Logo = styled.img`
const Link = styled.a`
text-decoration: none;
color: black;
padding: 0em 1em;
padding: 0.5em 1em;
&:hover {
color: #0e74ff;
}
${(props: { cheatSheetStyle?: boolean }) =>
props.cheatSheetStyle &&
css`
background-color: #efefef;
font-weight: 600;
margin-left: 3em;
&:hover {
color: black;
}
`}
`;
export const HeaderComponent = () => {
@ -38,15 +50,19 @@ export const HeaderComponent = () => {
<a href="https://ligolang.org">
<Logo src="/logo.svg" />
</a>
<Link cheatSheetStyle href="https://ligolang.org/docs/api/cheat-sheet" target="_blank">
Cheat Sheet
</Link>
</Group>
<Group>
<Link href="https://ligolang.org/docs/intro/installation">Docs</Link>
<Link href="https://ligolang.org/docs/intro/installation">Install</Link>
<Link href="https://ligolang.org/docs/intro/introduction">Docs</Link>
<Link href="https://ligolang.org/docs/tutorials/get-started/tezos-taco-shop-smart-contract">
Tutorials
</Link>
<Link href="https://ligolang.org/blog">Blog</Link>
<Link href="https://ligolang.org/docs/contributors/origin">
Contribute
<Link href="https://forum.tezosagora.org/tag/ligo" target="_blank">Blog</Link>
<Link href="https://ligolang.org/contact">
Ask Questions
</Link>
</Group>
</Container>