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 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 ## Compiling a contract

View File

@ -3,26 +3,28 @@ id: installation
title: 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) ## Dockerized installation (recommended)
> 🐳 You can find instructions on how to install Docker [here](https://docs.docker.com/install/). > 🐳 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: 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. 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). * 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). 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 ### 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 ```zsh
# next (pre-release) # 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 ```zsh
ligo --help ligo --help
``` ```
@ -44,7 +46,7 @@ ligo --help
The `ligo` executable is statically linked. It should run on most modern Linux distributions. 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 ```zsh
wget https://ligolang.org/bin/linux/ligo wget https://ligolang.org/bin/linux/ligo
@ -60,7 +62,7 @@ sudo cp ./ligo /usr/local/bin
## Debian Linux package installation ## Debian Linux package installation
A `.deb` package containing the static `ligo` executable is also available. 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 ```zsh
sudo apt install ./ligo.deb sudo apt install ./ligo.deb

View File

@ -1,6 +1,6 @@
--- ---
id: introduction id: introduction
title: Introduction To LIGO title: Introduction to LIGO
--- ---
import Tabs from '@theme/Tabs'; 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. 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 Smart contracts are a unique domain with extreme resource constraints and even
more extreme security risks. Unlike desktop, mobile, or web 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 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 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 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 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 amended. Naturally, under these conditions, it's not possible to develop smart contracts
the way we're used to developing user facing applications. the way we're used to developing user-facing applications.
LIGO is designed with these problems in mind. The design philosophy can be LIGO is designed with these problems in mind. The design philosophy can be
described in a few bullet points: 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/). 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 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 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 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 - **PascaLIGO**, a syntax inspired by Pascal which provides an
imperative developer experience. 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. syntax that allows you to write in a functional style.
- **ReasonLIGO**, an [ReasonML]((https://reasonml.github.io/)) inspired syntax - **ReasonLIGO**, a [ReasonML](https://reasonml.github.io/) inspired syntax
that builds on the strong points of OCaml. It aims to be familiar for those that builds on the strong points of OCaml. It aims to be familiar to those
coming from JavaScript. coming from JavaScript.
Let's define some LIGO contract in the three flavours above. Do 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). the [LIGO Gitlab repository](https://gitlab.com/ligolang/ligo).
### Snippets ### Snippets
For example **code snippets** for the *Types* subsection of this doc, can be found here: For example **code snippets** for the *Types* subsection of this doc, can be found here:
`gitlab-pages/docs/language-basics/src/types/**` `gitlab-pages/docs/language-basics/src/types/**`
### Exercises ### Running snippets
Solutions to exercises can be found e.g. here: `gitlab-pages/docs/language-basics/exercises/types/**/solutions/**`
### Running snippets / exercise solutions 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:
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:
```shell ```shell
ligo evaluate-value -s pascaligo gitlab-pages/docs/language-basics/src/variables-and-constants/const.ligo age 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) limited to tail recursion (i.e the recursive call should be the last expression of the function)
<Syntax syntax="pascaligo"> <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 ```pascaligo group=d
recursive function sum (const n : int; const acc: int) : int is 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 syntax="cameligo"> <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 ```cameligo group=d
let rec sum ((n,acc):int * int) : int = 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 syntax="reasonligo"> <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 ```reasonligo group=d
let rec sum = ((n, acc) : (int,int)): int => 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 value bound to a field can be accessed by giving its field name to a
special operator (`.`). 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"> <Syntax syntax="pascaligo">

View File

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

View File

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

View File

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

View File

@ -6,10 +6,24 @@ const TEAM = [
{ {
firstName: 'Christian', firstName: 'Christian',
lastName: 'Rinderknecht', lastName: 'Rinderknecht',
image: 'img/christian.jpeg', image: 'img/christian.jpg',
link: 'https://github.com/rinderknecht', link: 'https://github.com/rinderknecht',
pinned: true 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', firstName: 'Gabriel',
lastName: 'Alfour', lastName: 'Alfour',
@ -17,6 +31,13 @@ const TEAM = [
link: 'https://gitlab.com/gabriel.alfour', link: 'https://gitlab.com/gabriel.alfour',
pinned: true pinned: true
}, },
{
firstName: 'Pierre-Emmanuel',
lastName: 'Wolfman',
image: 'img/pierre-emmanuel.jpg',
link: 'https://gitlab.com/Popu-sama',
pinned: true
},
{ {
firstName: 'Sander', firstName: 'Sander',
lastName: 'Spies', lastName: 'Spies',
@ -27,27 +48,32 @@ const TEAM = [
{ {
firstName: 'Suzanne', firstName: 'Suzanne',
lastName: 'Dupéron', lastName: 'Dupéron',
image: 'img/suzanne.jpeg', image: 'img/suzanne.jpg',
link: 'https://gitlab.com/suzanne.duperon', link: 'https://gitlab.com/suzanne.duperon',
pinned: true pinned: true
} }
]; ];
const COMMUNICATION_CHANNELS = [ 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', link: 'https://t.me/LigoLang',
icon: 'img/telegram.svg', 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', link: 'https://gitlab.com/ligolang/ligo/issues',
icon: 'img/gitlab.svg', 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', link: 'https://twitter.com/ligolang',
icon: 'img/twitter.svg', 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', image: 'img/easy-integration.svg',
title: 'Easy Integration', 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 pinned: true
}, },
{ {
name: 'Tocqueville Group', name: 'TQ Tezos',
image: 'img/tq-logo.svg', image: 'img/tq-logo.svg',
link: 'https://tqgroup.io/', link: 'https://tqtezos.com/',
pinned: true 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 * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * 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 React, { useEffect, useState, useRef } from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import Highlight, { defaultProps } from 'prism-react-renderer'; import Highlight, { defaultProps } from 'prism-react-renderer';
const { Prism } = require("prism-react-renderer"); import Prism from 'prism-react-renderer/prism';
Prism.languages = { Prism.languages = {
...Prism.languages, ...Prism.languages,
@ -88,11 +90,79 @@ import useThemeContext from '@theme/hooks/useThemeContext';
import styles from './styles.module.css'; import styles from './styles.module.css';
const highlightLinesRangeRegex = /{([\d,-]+)}/; 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 { const {
siteConfig: { siteConfig: {
themeConfig: { prism = {} }, themeConfig: {prism = {}},
}, },
} = useDocusaurusContext(); } = useDocusaurusContext();
@ -112,15 +182,25 @@ export default ({ children, className: languageClassName, metastring }) => {
const target = useRef(null); const target = useRef(null);
const button = useRef(null); const button = useRef(null);
let highlightLines = []; let highlightLines = [];
let codeBlockTitle = '';
const { isDarkTheme } = useThemeContext(); const {isDarkTheme} = useThemeContext();
const lightModeTheme = prism.theme || defaultTheme; const lightModeTheme = prism.theme || defaultTheme;
const darkModeTheme = prism.darkTheme || lightModeTheme; const darkModeTheme = prism.darkTheme || lightModeTheme;
const prismTheme = isDarkTheme ? darkModeTheme : lightModeTheme; const prismTheme = isDarkTheme ? darkModeTheme : lightModeTheme;
if (metastring && highlightLinesRangeRegex.test(metastring)) { if (metastring && highlightLinesRangeRegex.test(metastring)) {
const highlightLinesRange = metastring.match(highlightLinesRangeRegex)[1]; 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(() => { useEffect(() => {
@ -146,6 +226,50 @@ export default ({ children, className: languageClassName, metastring }) => {
language = prism.defaultLanguage; 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 = () => { const handleCopyCode = () => {
window.getSelection().empty(); window.getSelection().empty();
setShowCopied(true); setShowCopied(true);
@ -158,26 +282,38 @@ export default ({ children, className: languageClassName, metastring }) => {
{...defaultProps} {...defaultProps}
key={mounted} key={mounted}
theme={prismTheme} theme={prismTheme}
code={children.trim()} code={code}
language={language}> language={language}>
{({ className, style, tokens, getLineProps, getTokenProps }) => ( {({className, style, tokens, getLineProps, getTokenProps}) => (
<pre className={classnames(className, styles.codeBlock)}> <>
{codeBlockTitle && (
<div style={style} className={styles.codeBlockTitle}>
{codeBlockTitle}
</div>
)}
<div className={styles.codeBlockContent}>
<button <button
ref={button} ref={button}
type="button" type="button"
aria-label="Copy code to clipboard" aria-label="Copy code to clipboard"
className={styles.copyButton} className={classnames(styles.copyButton, {
[styles.copyButtonWithTitle]: codeBlockTitle,
})}
onClick={handleCopyCode}> onClick={handleCopyCode}>
{showCopied ? 'Copied' : 'Copy'} {showCopied ? 'Copied' : 'Copy'}
</button> </button>
<div
<code ref={target} className={styles.codeBlockLines}> tabIndex="0"
className={classnames(className, styles.codeBlock, {
[styles.codeBlockWithTitle]: codeBlockTitle,
})}>
<div ref={target} className={styles.codeBlockLines} style={style}>
{tokens.map((line, i) => { {tokens.map((line, i) => {
if (line.length === 1 && line[0].content === '') { if (line.length === 1 && line[0].content === '') {
line[0].content = '\n'; // eslint-disable-line no-param-reassign 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)) { if (highlightLines.includes(i + 1)) {
lineProps.className = `${lineProps.className} docusaurus-highlight-code-line`; lineProps.className = `${lineProps.className} docusaurus-highlight-code-line`;
@ -186,13 +322,15 @@ export default ({ children, className: languageClassName, metastring }) => {
return ( return (
<div key={i} {...lineProps}> <div key={i} {...lineProps}>
{line.map((token, key) => ( {line.map((token, key) => (
<span key={key} {...getTokenProps({ token, key })} /> <span key={key} {...getTokenProps({token, key})} />
))} ))}
</div> </div>
); );
})} })}
</code> </div>
</pre> </div>
</div>
</>
)} )}
</Highlight> </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 * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * 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 { .codeBlock {
overflow: auto; overflow: auto;
display: block; border-radius: var(--ifm-global-radius);
padding: 0; }
margin: 0;
.codeBlockWithTitle {
border-top-left-radius: 0;
border-top-right-radius: 0;
} }
.copyButton { .copyButton {
background: rgb(1, 22, 39); background: rgba(0, 0, 0, 0.3);
border: 1px solid rgb(214, 222, 235); border: none;
border-radius: var(--ifm-global-radius); border-radius: var(--ifm-global-radius);
color: rgb(214, 222, 235); color: var(--ifm-color-white);
cursor: pointer; cursor: pointer;
line-height: 12px;
opacity: 0; opacity: 0;
outline: none; outline: none;
padding: 4px 8px; padding: 0.4rem 0.5rem;
position: absolute; position: absolute;
right: var(--ifm-pre-padding); right: calc(var(--ifm-pre-padding) / 2);
top: var(--ifm-pre-padding); top: calc(var(--ifm-pre-padding) / 2);
visibility: hidden; visibility: hidden;
transition: opacity 200ms ease-in-out, visibility 200ms ease-in-out, transition: opacity 200ms ease-in-out, visibility 200ms ease-in-out,
bottom 200ms ease-in-out; bottom 200ms ease-in-out;
} }
.codeBlock:hover > .copyButton { .codeBlockTitle:hover + .codeBlockContent .copyButton,
.codeBlockContent:hover > .copyButton {
visibility: visible; visibility: visible;
opacity: 1; opacity: 1;
} }
.codeBlockLines { .codeBlockLines {
background-color: transparent; font-family: var(--ifm-font-family-monospace);
border-radius: 0; font-size: inherit;
margin-bottom: 0; line-height: var(--ifm-pre-line-height);
white-space: pre;
float: left; float: left;
min-width: 100%; min-width: 100%;
padding: var(--ifm-pre-padding); 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 * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * 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 useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import renderRoutes from '@docusaurus/renderRoutes'; import renderRoutes from '@docusaurus/renderRoutes';
import Layout from '@theme/Layout'; import Layout from '@theme/Layout';
import DocItem from '@theme/DocItem';
import DocSidebar from '@theme/DocSidebar'; import DocSidebar from '@theme/DocSidebar';
import MDXComponents from '@theme/MDXComponents'; import MDXComponents from '@theme/MDXComponents';
import NotFound from '@theme/NotFound'; import NotFound from '@theme/NotFound';
@ -21,20 +22,29 @@ import styles from './styles.module.css';
import SyntaxContext from '@theme/Syntax/SyntaxContext'; import SyntaxContext from '@theme/Syntax/SyntaxContext';
function DocPage(props) { function DocPage(props) {
const {route: baseRoute, docsMetadata, location} = props; const {route: baseRoute, docsMetadata, location, content} = 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 { 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, isClient,
} = useDocusaurusContext(); } = useDocusaurusContext();
const {sidebarCollapsible = true} = themeConfig;
let defaultSyntax = 'pascaligo'; let defaultSyntax = 'pascaligo';
if (isClient) { if (isClient) {
@ -43,7 +53,7 @@ function DocPage(props) {
const [syntax, setSyntax] = useState(defaultSyntax); const [syntax, setSyntax] = useState(defaultSyntax);
if (Object.keys(currentRoute).length === 0) { if (!isHomePage && Object.keys(currentRoute).length === 0) {
return <NotFound {...props} />; return <NotFound {...props} />;
} }
@ -55,7 +65,7 @@ function DocPage(props) {
<div className={styles.docSidebarContainer}> <div className={styles.docSidebarContainer}>
<DocSidebar <DocSidebar
docsSidebars={docsSidebars} docsSidebars={docsSidebars}
path={currentRoute.path} path={isHomePage ? homePagePath : currentRoute.path}
sidebar={sidebar} sidebar={sidebar}
sidebarCollapsible={sidebarCollapsible} sidebarCollapsible={sidebarCollapsible}
syntax={syntax} syntax={syntax}
@ -68,7 +78,11 @@ function DocPage(props) {
)} )}
<main className={styles.docMainContainer}> <main className={styles.docMainContainer}>
<MDXProvider components={MDXComponents}> <MDXProvider components={MDXComponents}>
{renderRoutes(baseRoute.routes)} {isHomePage ? (
<DocItem content={content} />
) : (
renderRoutes(baseRoute.routes)
)}
</MDXProvider> </MDXProvider>
</main> </main>
</div> </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 * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
@ -10,11 +10,11 @@
} }
.docSidebarContainer { .docSidebarContainer {
border-right: 1px solid var(--ifm-contents-border-color); border-right: 1px solid var(--ifm-toc-border-color);
box-sizing: border-box; box-sizing: border-box;
width: 300px; width: 300px;
position: relative; position: relative;
top: calc(-1 * var(--ifm-navbar-height)); margin-top: calc(-1 * var(--ifm-navbar-height));
} }
.docMainContainer { .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 * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
@ -8,19 +8,24 @@
import React, {useState, useCallback} from 'react'; import React, {useState, useCallback} from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import useBaseUrl from '@docusaurus/useBaseUrl';
import useLockBodyScroll from '@theme/hooks/useLockBodyScroll'; import useLockBodyScroll from '@theme/hooks/useLockBodyScroll';
import useLogo from '@theme/hooks/useLogo';
import Link from '@docusaurus/Link'; 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 styles from './styles.module.css';
import SyntaxSwitch from '@theme/Syntax/SyntaxSwitch'; import SyntaxSwitch from '@theme/Syntax/SyntaxSwitch';
const MOBILE_TOGGLE_SIZE = 24; const MOBILE_TOGGLE_SIZE = 24;
function DocSidebarItem({item, onItemClick, collapsible}) { function DocSidebarItem({
item,
onItemClick,
collapsible,
activePath,
...props
}) {
const {items, href, label, type} = item; const {items, href, label, type} = item;
const [collapsed, setCollapsed] = useState(item.collapsed); const [collapsed, setCollapsed] = useState(item.collapsed);
const [prevCollapsedProp, setPreviousCollapsedProp] = useState(null); const [prevCollapsedProp, setPreviousCollapsedProp] = useState(null);
@ -33,9 +38,10 @@ function DocSidebarItem({item, onItemClick, collapsible}) {
setCollapsed(item.collapsed); setCollapsed(item.collapsed);
} }
const handleItemClick = useCallback(e => { const handleItemClick = useCallback((e) => {
e.preventDefault(); e.preventDefault();
setCollapsed(state => !state); e.target.blur();
setCollapsed((state) => !state);
}); });
switch (type) { switch (type) {
@ -53,16 +59,19 @@ function DocSidebarItem({item, onItemClick, collapsible}) {
'menu__link--active': collapsible && !item.collapsed, 'menu__link--active': collapsible && !item.collapsed,
})} })}
href="#!" href="#!"
onClick={collapsible ? handleItemClick : undefined}> onClick={collapsible ? handleItemClick : undefined}
{...props}>
{label} {label}
</a> </a>
<ul className="menu__list"> <ul className="menu__list">
{items.map(childItem => ( {items.map((childItem) => (
<DocSidebarItem <DocSidebarItem
tabIndex={collapsed ? '-1' : '0'}
key={childItem.label} key={childItem.label}
item={childItem} item={childItem}
onItemClick={onItemClick} onItemClick={onItemClick}
collapsible={collapsible} collapsible={collapsible}
activePath={activePath}
/> />
))} ))}
</ul> </ul>
@ -75,18 +84,21 @@ function DocSidebarItem({item, onItemClick, collapsible}) {
return ( return (
<li className="menu__list-item" key={label}> <li className="menu__list-item" key={label}>
<Link <Link
className="menu__link" className={classnames('menu__link', {
'menu__link--active': href === activePath,
})}
to={href} to={href}
{...(isInternalUrl(href) {...(isInternalUrl(href)
? { ? {
activeClassName: 'menu__link--active', isNavLink: true,
exact: true, exact: true,
onClick: onItemClick, onClick: onItemClick,
} }
: { : {
target: '_blank', target: '_blank',
rel: 'noreferrer noopener', rel: 'noreferrer noopener',
})}> })}
{...props}>
{label} {label}
</Link> </Link>
</li> </li>
@ -102,8 +114,8 @@ function mutateSidebarCollapsingState(item, path) {
case 'category': { case 'category': {
const anyChildItemsActive = const anyChildItemsActive =
items items
.map(childItem => mutateSidebarCollapsingState(childItem, path)) .map((childItem) => mutateSidebarCollapsingState(childItem, path))
.filter(val => val).length > 0; .filter((val) => val).length > 0;
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
item.collapsed = !anyChildItemsActive; item.collapsed = !anyChildItemsActive;
return anyChildItemsActive; return anyChildItemsActive;
@ -118,9 +130,12 @@ function mutateSidebarCollapsingState(item, path) {
function DocSidebar(props) { function DocSidebar(props) {
const [showResponsiveSidebar, setShowResponsiveSidebar] = useState(false); const [showResponsiveSidebar, setShowResponsiveSidebar] = useState(false);
const { const {
siteConfig: {themeConfig: {navbar: {title, logo = {}} = {}}} = {}, isClient siteConfig: {
themeConfig: {navbar: {title, hideOnScroll = false} = {}},
} = {},
isClient,
} = useDocusaurusContext(); } = useDocusaurusContext();
const logoUrl = useBaseUrl(logo.src); const {logoLink, logoLinkProps, logoImageUrl, logoAlt} = useLogo();
const { const {
docsSidebars, docsSidebars,
@ -144,17 +159,25 @@ function DocSidebar(props) {
} }
if (sidebarCollapsible) { if (sidebarCollapsible) {
sidebarData.forEach(sidebarItem => sidebarData.forEach((sidebarItem) =>
mutateSidebarCollapsingState(sidebarItem, path), mutateSidebarCollapsingState(sidebarItem, path),
); );
} }
return ( return (
<div className={styles.sidebar}> <div className={styles.sidebar}>
<div className={styles.sidebarLogo}> {hideOnScroll && (
{logo != null && <img src={logoUrl} alt={logo.alt} />} <Link
tabIndex="-1"
className={styles.sidebarLogo}
to={logoLink}
{...logoLinkProps}>
{logoImageUrl != null && (
<img key={isClient} src={logoImageUrl} alt={logoAlt} />
)}
{title != null && <strong>{title}</strong>} {title != null && <strong>{title}</strong>}
</div> </Link>
)}
{isClient && document.location.pathname.startsWith('/docs') && !showResponsiveSidebar ? {isClient && document.location.pathname.startsWith('/docs') && !showResponsiveSidebar ?
<div className={styles.switchContainer}> <div className={styles.switchContainer}>
Display syntax: <SyntaxSwitch syntax={props.syntax} onSyntaxChange={s => props.onSyntaxChange(s)} /> Display syntax: <SyntaxSwitch syntax={props.syntax} onSyntaxChange={s => props.onSyntaxChange(s)} />
@ -168,14 +191,14 @@ function DocSidebar(props) {
})}> })}>
{isClient && document.location.pathname.startsWith('/docs') && showResponsiveSidebar ? {isClient && document.location.pathname.startsWith('/docs') && showResponsiveSidebar ?
<div className={styles.switchContainerResponsive}> <div className={styles.switchContainerResponsive}>
Display syntax: Display syntax: <SyntaxSwitch syntax={props.syntax} onSyntaxChange={s => props.onSyntaxChange(s)} />
<SyntaxSwitch syntax={props.syntax} onSyntaxChange={s => props.onSyntaxChange(s)} />
</div> </div>
: :
null null
} }
<button <button
aria-label={showResponsiveSidebar ? 'Close Menu' : 'Open Menu'} aria-label={showResponsiveSidebar ? 'Close Menu' : 'Open Menu'}
aria-haspopup="true"
className="button button--secondary button--sm menu__button" className="button button--secondary button--sm menu__button"
type="button" type="button"
onClick={() => { onClick={() => {
@ -191,6 +214,7 @@ function DocSidebar(props) {
</span> </span>
) : ( ) : (
<svg <svg
aria-label="Menu"
className={styles.sidebarMenuIcon} className={styles.sidebarMenuIcon}
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
height={MOBILE_TOGGLE_SIZE} height={MOBILE_TOGGLE_SIZE}
@ -210,14 +234,16 @@ function DocSidebar(props) {
)} )}
</button> </button>
<ul className="menu__list"> <ul className="menu__list">
{sidebarData.map(item => ( {sidebarData.map((item) => (
<DocSidebarItem <DocSidebarItem
key={item.label} key={item.label}
item={item} item={item}
onItemClick={() => { onItemClick={(e) => {
e.target.blur();
setShowResponsiveSidebar(false); setShowResponsiveSidebar(false);
}} }}
collapsible={sidebarCollapsible} collapsible={sidebarCollapsible}
activePath={path}
/> />
))} ))}
</ul> </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 * This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
@ -39,6 +39,8 @@
top: 0; top: 0;
margin: 0 var(--ifm-navbar-padding-horizontal); margin: 0 var(--ifm-navbar-padding-horizontal);
height: var(--ifm-navbar-height); height: var(--ifm-navbar-height);
color: inherit !important;
text-decoration: none !important;
} }
.sidebarLogo img { .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, #contactPage,
#pageNotFoundPage { #pageNotFoundPage {
font-weight: lighter;
margin-top: 80px; margin-top: 80px;
margin-bottom: 80px; margin-bottom: 80px;
} }
@ -692,7 +691,7 @@ a:hover {
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
font-size: 1.25em; font-size: 0.85em;
font-weight: normal; font-weight: normal;
color: white; color: white;
} }
@ -735,6 +734,8 @@ a:hover {
cursor: pointer; cursor: pointer;
background-color: var(--lighter-blue); background-color: var(--lighter-blue);
border-left: 6px solid var(--blue); border-left: 6px solid var(--blue);
color: black;
text-decoration: none;
} }
#contactPage #message .communicationOptions .option .icon { #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 <FloatButtonComponent
tooltip="Report an issue" tooltip="Report an issue"
text="!" text="!"
href="https://gitlab.com/ligolang/ligo-web-ide/issues" href="https://gitlab.com/ligolang/ligo/issues"
></FloatButtonComponent> ></FloatButtonComponent>
<FloatButtonComponent <FloatButtonComponent
tooltip="Ask a question" tooltip="Ask a question"

View File

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