Update the Contact page and other minor improvements to the website
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 =>
|
||||
|
@ -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">
|
||||
|
||||
|
@ -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
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
id: toplevel
|
||||
title: Toplevel
|
||||
title: Top-Level
|
||||
description: Available functions at the top level
|
||||
hide_table_of_contents: true
|
||||
---
|
||||
|
@ -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'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
2157
gitlab-pages/website/package-lock.json
generated
@ -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"
|
||||
}
|
||||
}
|
||||
|
@ -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!'
|
||||
}
|
||||
];
|
||||
|
||||
|
@ -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
|
||||
},
|
||||
{
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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);
|
||||
|
217
gitlab-pages/website/src/theme/DocItem/index.js
Normal 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;
|
70
gitlab-pages/website/src/theme/DocItem/styles.module.css
Normal 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;
|
||||
}
|
@ -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) {
|
||||
@ -42,8 +52,8 @@ 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>
|
||||
|
@ -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 {
|
||||
|
@ -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>
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
@ -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;
|
||||
}
|
@ -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 {
|
||||
|
Before Width: | Height: | Size: 54 KiB |
Before Width: | Height: | Size: 32 KiB |
BIN
gitlab-pages/website/static/img/christian.jpg
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
gitlab-pages/website/static/img/eowyn.jpg
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
gitlab-pages/website/static/img/francis.jpg
Normal file
After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 33 KiB |
BIN
gitlab-pages/website/static/img/pierre-emmanuel.jpg
Normal file
After Width: | Height: | Size: 39 KiB |
Before Width: | Height: | Size: 24 KiB |
BIN
gitlab-pages/website/static/img/suzanne.jpg
Normal file
After Width: | Height: | Size: 29 KiB |
@ -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"
|
||||
|
@ -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>
|
||||
|