refactor: website (#740)
* refactor: website Signed-off-by: Yue Yang <g1enyy0ung@gmail.com> * fix: typo Signed-off-by: Yue Yang <g1enyy0ung@gmail.com> Co-authored-by: ti-srebot <66930949+ti-srebot@users.noreply.github.com>
|
|
@ -0,0 +1,9 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"semi": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"printWidth": 120
|
||||||
|
}
|
||||||
18
README.md
|
|
@ -1,33 +1,33 @@
|
||||||
# Website
|
# Chaos Mesh Website
|
||||||
|
|
||||||
This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator.
|
This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator.
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ yarn
|
yarn
|
||||||
```
|
```
|
||||||
|
|
||||||
### Local Development
|
### Local Development
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ yarn start
|
yarn start
|
||||||
```
|
```
|
||||||
|
|
||||||
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
||||||
|
|
||||||
### Build
|
### Build
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ yarn build
|
yarn build
|
||||||
```
|
```
|
||||||
|
|
||||||
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
||||||
|
|
||||||
### Deployment
|
### Deployment
|
||||||
|
|
||||||
```
|
```sh
|
||||||
$ GIT_USER=<Your GitHub username> USE_SSH=true yarn deploy
|
GIT_USER=<Your GitHub username> USE_SSH=true yarn deploy
|
||||||
```
|
```
|
||||||
|
|
||||||
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = {
|
||||||
|
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
|
||||||
|
};
|
||||||
|
|
@ -5,7 +5,7 @@ author: Cwen Yin
|
||||||
author_title: Maintainer of Chaos Mesh
|
author_title: Maintainer of Chaos Mesh
|
||||||
author_url: https://github.com/cwen0
|
author_url: https://github.com/cwen0
|
||||||
author_image_url: https://avatars1.githubusercontent.com/u/22956341?v=4
|
author_image_url: https://avatars1.githubusercontent.com/u/22956341?v=4
|
||||||
tags: [Chaos Mesh, Chaos Engineering, Kubernetes, Distributed system]
|
tags: [Chaos Mesh, Chaos Engineering, Kubernetes, Distributed System]
|
||||||
---
|
---
|
||||||
|
|
||||||

|

|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
id: get_started_on_kind
|
id: get_started_on_kind
|
||||||
title: Get started on kind
|
title: Get started on Kind
|
||||||
---
|
---
|
||||||
|
|
||||||
This document describes how to deploy Chaos Mesh in Kubernetes on your laptop (Linux or macOS) using kind.
|
This document describes how to deploy Chaos Mesh in Kubernetes on your laptop (Linux or macOS) using kind.
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
title: 'Chaos Mesh®',
|
title: 'Chaos Mesh®',
|
||||||
tagline: 'A Powerful Chaos Engineering Platform for Kubernetes',
|
tagline: 'A Powerful Chaos Engineering Platform for Kubernetes',
|
||||||
url: 'https://chaos-mesh.github.io',
|
url: 'https://chaos-mesh.org',
|
||||||
baseUrl: '/',
|
baseUrl: '/',
|
||||||
favicon: 'img/favicon.ico',
|
favicon: 'img/favicon.ico',
|
||||||
organizationName: 'chaos-mesh', // Usually your GitHub org/user name.
|
organizationName: 'chaos-mesh', // Usually your GitHub org/user name.
|
||||||
projectName: 'chaos-mesh.github.io', // Usually your repo name.
|
projectName: 'chaos-mesh.github.io', // Usually your repo name.
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
defaultDarkMode: false,
|
|
||||||
algolia: {
|
algolia: {
|
||||||
apiKey: '49739571d4f89670b12f39d5ad135f5a',
|
apiKey: '49739571d4f89670b12f39d5ad135f5a',
|
||||||
indexName: 'chaos-mesh',
|
indexName: 'chaos-mesh',
|
||||||
|
|
@ -16,19 +15,19 @@ module.exports = {
|
||||||
trackingID: 'UA-90760217-2',
|
trackingID: 'UA-90760217-2',
|
||||||
},
|
},
|
||||||
navbar: {
|
navbar: {
|
||||||
|
hideOnScroll: true,
|
||||||
|
title: 'Chaos Mesh®',
|
||||||
logo: {
|
logo: {
|
||||||
alt: 'Chaos Mesh Logo',
|
alt: 'Chaos Mesh Logo',
|
||||||
src: 'img/logo.svg',
|
src: 'img/logos/logo-mini.svg',
|
||||||
srcDark: 'img/logo_dark.svg'
|
|
||||||
},
|
},
|
||||||
links: [
|
items: [
|
||||||
{
|
{
|
||||||
to: 'docs/',
|
to: 'docs',
|
||||||
activeBasePath: 'docs',
|
activeBasePath: 'docs',
|
||||||
label: 'Docs',
|
label: 'Documentation',
|
||||||
position: 'left',
|
|
||||||
},
|
},
|
||||||
{to: 'blog', label: 'Blog', position: 'left'},
|
{ to: 'blog', activeBasePath: 'blog', label: 'Blog' },
|
||||||
{
|
{
|
||||||
href: 'https://github.com/chaos-mesh/chaos-mesh',
|
href: 'https://github.com/chaos-mesh/chaos-mesh',
|
||||||
label: 'GitHub',
|
label: 'GitHub',
|
||||||
|
|
@ -37,17 +36,16 @@ module.exports = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
style: 'dark',
|
|
||||||
links: [
|
links: [
|
||||||
{
|
{
|
||||||
title: 'Docs',
|
title: 'Documentation',
|
||||||
items: [
|
items: [
|
||||||
{
|
{
|
||||||
label: 'Getting started',
|
label: 'Getting Started',
|
||||||
to: 'docs/installation/installation',
|
to: 'docs/installation/installation',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'User Guide',
|
label: 'User Guides',
|
||||||
to: 'docs/user_guides/run_chaos_experiment',
|
to: 'docs/user_guides/run_chaos_experiment',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
@ -59,14 +57,6 @@ module.exports = {
|
||||||
label: 'Twitter',
|
label: 'Twitter',
|
||||||
href: 'https://twitter.com/chaos_mesh',
|
href: 'https://twitter.com/chaos_mesh',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: 'Slack',
|
|
||||||
href: 'https://chaos-mesh.org/tidbslack',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Stack Overflow',
|
|
||||||
href: 'https://stackoverflow.com/questions/tagged/chaos-mesh',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -83,9 +73,13 @@ module.exports = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
copyright: `<strong>© Chaos Mesh® Authors ${new Date().getFullYear()} | Documentation Distributed under CC-BY-4.0 </strong> <br> <br> © ${new Date().getFullYear()} The Linux Foundation. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Foundation, please see our <a href="https://www.linuxfoundation.org/trademark-usage/"> Trademark Usage page</a>.`,
|
copyright: `<br /><strong>© Chaos Mesh® Authors ${new Date().getFullYear()} | Documentation Distributed under CC-BY-4.0 </strong><br /><br />© ${new Date().getFullYear()} The Linux Foundation. All rights reserved. The Linux Foundation has registered trademarks and uses trademarks. For a list of trademarks of The Linux Foundation, please see our <a href="https://www.linuxfoundation.org/trademark-usage/"> Trademark Usage</a> page.`,
|
||||||
|
},
|
||||||
|
prism: {
|
||||||
|
theme: require('prism-react-renderer/themes/dracula'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
plugins: ['docusaurus-plugin-sass'],
|
||||||
presets: [
|
presets: [
|
||||||
[
|
[
|
||||||
'@docusaurus/preset-classic',
|
'@docusaurus/preset-classic',
|
||||||
|
|
@ -95,19 +89,17 @@ module.exports = {
|
||||||
homePageId: 'overview',
|
homePageId: 'overview',
|
||||||
sidebarPath: require.resolve('./sidebars.js'),
|
sidebarPath: require.resolve('./sidebars.js'),
|
||||||
// Please change this to your repo.
|
// Please change this to your repo.
|
||||||
editUrl:
|
editUrl: 'https://github.com/chaos-mesh/chaos-mesh/edit/master/website/',
|
||||||
'https://github.com/chaos-mesh/chaos-mesh/edit/master/website/',
|
|
||||||
},
|
},
|
||||||
blog: {
|
blog: {
|
||||||
showReadingTime: true,
|
showReadingTime: true,
|
||||||
// Please change this to your repo.
|
// Please change this to your repo.
|
||||||
editUrl:
|
editUrl: 'https://github.com/chaos-mesh/chaos-mesh/edit/master/website/',
|
||||||
'https://github.com/chaos-mesh/chaos-mesh/edit/master/website/blog/',
|
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
customCss: require.resolve('./src/css/custom.css'),
|
customCss: require.resolve('./src/styles/custom.scss'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
};
|
}
|
||||||
|
|
|
||||||
13
package.json
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "chaos-mesh",
|
"name": "chaos-mesh-website",
|
||||||
"version": "0.0.0",
|
"version": "0.8.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "docusaurus start",
|
"start": "docusaurus start",
|
||||||
|
|
@ -9,9 +9,10 @@
|
||||||
"deploy": "docusaurus deploy"
|
"deploy": "docusaurus deploy"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "^2.0.0-alpha.56",
|
"@docusaurus/core": "^2.0.0-alpha.58",
|
||||||
"@docusaurus/preset-classic": "^2.0.0-alpha.56",
|
"@docusaurus/preset-classic": "^2.0.0-alpha.58",
|
||||||
"classnames": "^2.2.6",
|
"clsx": "^1.1.1",
|
||||||
|
"docusaurus-plugin-sass": "^0.1.9",
|
||||||
"react": "^16.8.4",
|
"react": "^16.8.4",
|
||||||
"react-dom": "^16.8.4"
|
"react-dom": "^16.8.4"
|
||||||
},
|
},
|
||||||
|
|
@ -27,4 +28,4 @@
|
||||||
"last 1 safari version"
|
"last 1 safari version"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
sidebars.js
|
|
@ -7,11 +7,7 @@ module.exports = {
|
||||||
{
|
{
|
||||||
type: 'category',
|
type: 'category',
|
||||||
label: 'Getting Started',
|
label: 'Getting Started',
|
||||||
items: [
|
items: ['installation/installation', 'installation/get_started_on_kind', 'installation/get_started_on_minikube'],
|
||||||
'installation/installation',
|
|
||||||
'installation/get_started_on_kind',
|
|
||||||
'installation/get_started_on_minikube'
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'category',
|
type: 'category',
|
||||||
|
|
@ -37,11 +33,9 @@ module.exports = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "category",
|
type: 'category',
|
||||||
label: "Use Cases",
|
label: 'Use Cases',
|
||||||
items: [
|
items: ['use_cases/multi_data_centers'],
|
||||||
"use_cases/multi_data_centers",
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'category',
|
type: 'category',
|
||||||
|
|
@ -50,7 +44,7 @@ module.exports = {
|
||||||
'development_guides/development_overview',
|
'development_guides/development_overview',
|
||||||
'development_guides/set_up_the_development_environment',
|
'development_guides/set_up_the_development_environment',
|
||||||
'development_guides/develop_a_new_chaos',
|
'development_guides/develop_a_new_chaos',
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'doc',
|
type: 'doc',
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,121 @@
|
||||||
/*jshint esversion: 6 */
|
import CodeBlock from '../theme/CodeBlock'
|
||||||
import React from 'react';
|
import Layout from '@theme/Layout'
|
||||||
import classnames from 'classnames';
|
import React from 'react'
|
||||||
import Layout from '@theme/Layout';
|
import clsx from 'clsx'
|
||||||
import Link from '@docusaurus/Link';
|
import styles from './styles.module.css'
|
||||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
import useBaseUrl from '@docusaurus/useBaseUrl'
|
||||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext'
|
||||||
import styles from './styles.module.css';
|
|
||||||
import CodeSnippet from "@site/src/theme/CodeSnippet";
|
|
||||||
|
|
||||||
const install = `# Install on Kubernetes
|
const installChaosMesh = 'curl -sSL https://raw.githubusercontent.com/chaos-mesh/chaos-mesh/master/install.sh | bash'
|
||||||
curl -sSL https://raw.githubusercontent.com/chaos-mesh/chaos-mesh/master/install.sh | bash`
|
|
||||||
|
|
||||||
function Home() {
|
const features = [
|
||||||
const context = useDocusaurusContext();
|
{
|
||||||
const {siteConfig = {}} = context;
|
title: <>Easy to Use</>,
|
||||||
|
imageUrl: 'img/undraw_server_down_s4lk.svg',
|
||||||
|
description: (
|
||||||
|
<>
|
||||||
|
<p>
|
||||||
|
No special dependencies, Chaos Mesh can be easily deployed directly on Kubernetes clusters, including{' '}
|
||||||
|
<a href="https://github.com/kubernetes/minikube">Minikube</a> and{' '}
|
||||||
|
<a href="https://kind.sigs.k8s.io/docs/user/quick-start/">Kind</a>.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li>Require no modification to the deployment logic of the system under test (SUT)</li>
|
||||||
|
<li>Easily orchestrate fault injection behaviors in chaos experiments</li>
|
||||||
|
<li>Hide underlying implementation details so that users can focus on orchestrating the chaos experiments</li>
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: <>Design for Kubernetes</>,
|
||||||
|
imageUrl: 'img/logos/kubernetes.svg',
|
||||||
|
description: (
|
||||||
|
<>
|
||||||
|
<p>
|
||||||
|
Chaos Mesh uses{' '}
|
||||||
|
<a
|
||||||
|
href="https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
CustomResourceDefinitions
|
||||||
|
</a>{' '}
|
||||||
|
(CRD) to define chaos objects.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In the Kubernetes realm, CRD is a mature solution for implementing custom resources, with abundant
|
||||||
|
implementation cases and toolsets available. Using CRD makes Chaos Mesh naturally integrate with the
|
||||||
|
Kubernetes ecosystem.
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
reverse: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
function Feature({ imageUrl, title, description, reverse }) {
|
||||||
return (
|
return (
|
||||||
<Layout
|
<div className={clsx('row', styles.feature, reverse ? styles.featureReverse : '')}>
|
||||||
title={`Hello from ${siteConfig.title}`}
|
<div className="col col--6">
|
||||||
description="Description will go into a meta tag in <head />">
|
<div className="text--center">
|
||||||
<header className={classnames('hero hero--primary', styles.heroBanner)} style={{ background: 'linear-gradient(to right, #0b2050, #00b7ef, #0b2050)' }}>
|
{imageUrl && <img className={styles.featureImage} src={useBaseUrl(imageUrl)} alt={title} />}
|
||||||
<div className="container">
|
|
||||||
<h1 className="hero__title">{siteConfig.title}</h1>
|
|
||||||
<p className="hero__subtitle">{siteConfig.tagline}</p>
|
|
||||||
<div className={styles.buttons}>
|
|
||||||
<Link
|
|
||||||
className={classnames(
|
|
||||||
'button button--outline button--secondary button--lg',
|
|
||||||
styles.getStarted,
|
|
||||||
)}
|
|
||||||
to={useBaseUrl('docs/')}>
|
|
||||||
Get Started
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</div>
|
||||||
<main>
|
<div className={clsx('col col--6', styles.featureDesc)}>
|
||||||
<div className="container">
|
<div>
|
||||||
<div className="row">
|
<h3>{title}</h3>
|
||||||
<div className={classnames(`${styles.pitch} col col--6`)}>
|
<p>{description}</p>
|
||||||
<h2>Easy to Use</h2>
|
|
||||||
<div>
|
|
||||||
No special dependencies, Chaos Mesh can be easily deployed directly on Kubernetes
|
|
||||||
clusters, including <a href="https://github.com/kubernetes/minikube">Minikube</a> and <a href="https://kind.sigs.k8s.io/docs/user/quick-start/">Kind</a>.
|
|
||||||
<ul>
|
|
||||||
<li>Require no modification to the deployment logic of the system under test (SUT)</li>
|
|
||||||
<li>Easily orchestrate fault injection behaviors in chaos experiments</li>
|
|
||||||
<li>Hide underlying implementation details so that users can focus on orchestrating the chaos experiments</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<CodeSnippet snippet={install} lang="bash"></CodeSnippet>
|
|
||||||
</div>
|
|
||||||
<div className={classnames(`${styles.pitch} col col--6`)}>
|
|
||||||
<h2>Designed for Kubernetes</h2>
|
|
||||||
<p>
|
|
||||||
Chaos Mesh uses <a href="https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/">CustomResourceDefinitions</a> (CRD) to define chaos objects.
|
|
||||||
In the Kubernetes realm, CRD is a mature solution for implementing custom resources,
|
|
||||||
with abundant implementation cases and toolsets available.
|
|
||||||
Using CRD makes Chaos Mesh naturally integrate with the Kubernetes ecosystem.
|
|
||||||
</p>
|
|
||||||
<img src="img/chaos-mesh.svg" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="text--center">
|
</div>
|
||||||
<p className={styles.cncfTitle}>Chaos Mesh® is a <a href="https://cncf.io/">Cloud Native Computing Foundation</a> sandbox project</p>
|
</div>
|
||||||
<img className={styles.cncfLogo} src="img/cncf-color.svg" alt="cncf" />
|
)
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</Layout>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Home;
|
function Home() {
|
||||||
|
const context = useDocusaurusContext()
|
||||||
|
const { siteConfig } = context
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Layout title={siteConfig.tagline} description={siteConfig.tagline}>
|
||||||
|
<header className={clsx('hero', styles.hero)}>
|
||||||
|
<div className="container text--center">
|
||||||
|
<div className={styles.heroLogoWrapper}>
|
||||||
|
<img className={styles.heroLogo} src={useBaseUrl('img/logos/logo-mini.svg')} alt="Chaos Mesh Logo" />
|
||||||
|
</div>
|
||||||
|
<h1 className={clsx('hero__title', styles.heroTitle)}>{siteConfig.title}</h1>
|
||||||
|
<p className="hero__subtitle">{siteConfig.tagline}</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div className={clsx('text--center', styles.install)}>
|
||||||
|
<h2>Start By One Line</h2>
|
||||||
|
<div className={styles.installTextWrapper}>
|
||||||
|
<CodeBlock className="language-bash">{installChaosMesh}</CodeBlock>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<main className={styles.main}>
|
||||||
|
{features && features.length > 0 && (
|
||||||
|
<section className={styles.features}>
|
||||||
|
<div className="container">
|
||||||
|
{features.map((f, idx) => (
|
||||||
|
<Feature key={idx} {...f} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="hero">
|
||||||
|
<div className="container text--center">
|
||||||
|
<h2 className="hero__subtitle">
|
||||||
|
Chaos Mesh® is a <a href="https://cncf.io/">Cloud Native Computing Foundation</a> sandbox project
|
||||||
|
</h2>
|
||||||
|
<div className={clsx('cncf-logo', styles.cncfLogo)} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Home
|
||||||
|
|
|
||||||
|
|
@ -5,45 +5,90 @@
|
||||||
* and scoped locally.
|
* and scoped locally.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.heroBanner {
|
.hero {
|
||||||
padding: 4rem 0;
|
box-shadow: var(--ifm-navbar-shadow);
|
||||||
text-align: center;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 966px) {
|
.heroLogoWrapper {
|
||||||
.heroBanner {
|
position: relative;
|
||||||
padding: 2rem;
|
left: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 256px;
|
||||||
|
height: 256px;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 48px;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.heroLogo {
|
||||||
|
width: 80%;
|
||||||
|
height: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.heroTitle {
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.install {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 3rem 0;
|
||||||
|
box-shadow: var(--ifm-navbar-shadow);
|
||||||
|
}
|
||||||
|
|
||||||
|
.installTextWrapper {
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.installTextWrapper {
|
||||||
|
width: 90%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttons {
|
.main {
|
||||||
display: flex;
|
margin-top: 4.5rem;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.features {
|
.feature {
|
||||||
display: flex;
|
margin-bottom: 4.5rem;
|
||||||
align-items: center;
|
}
|
||||||
padding: 2rem 0;
|
|
||||||
width: 100%;
|
@media screen and (max-width: 768px) {
|
||||||
|
.feature {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.featureReverse {
|
||||||
|
flex-direction: row-reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
.featureImage {
|
.featureImage {
|
||||||
height: 200px;
|
height: 256px;
|
||||||
width: 200px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.pitch {
|
@media screen and (max-width: 768px) {
|
||||||
margin: 40px 0;
|
.featureImage {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cncfTitle {
|
.featureDesc {
|
||||||
font-size: 1.5rem;
|
display: flex !important;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cncfLogo {
|
.cncfLogo {
|
||||||
width: 30%;
|
height: 128px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.cncfLogo {
|
||||||
|
height: 64px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
// Converted automatically using ./tools/themeFromVsCode
|
|
||||||
var theme = {
|
|
||||||
"styles": [{
|
|
||||||
"types": ["comment"],
|
|
||||||
"style": {
|
|
||||||
"color": "rgb(136, 132, 111)"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"types": ["string", "changed"],
|
|
||||||
"style": {
|
|
||||||
"color": "rgb(230, 219, 116)"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"types": ["punctuation", "tag", "deleted"],
|
|
||||||
"style": {
|
|
||||||
"color": "rgb(249, 38, 114)"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"types": ["number", "builtin"],
|
|
||||||
"style": {
|
|
||||||
"color": "rgb(174, 129, 255)"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"types": ["variable"],
|
|
||||||
"style": {
|
|
||||||
"color": "rgb(248, 248, 242)"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"types": ["function", "attr-name", "inserted"],
|
|
||||||
"style": {
|
|
||||||
"color": "rgb(166, 226, 46)"
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
module.exports = theme;
|
|
||||||
|
|
@ -7,13 +7,13 @@
|
||||||
|
|
||||||
/* You can override the default Infima variables here. */
|
/* You can override the default Infima variables here. */
|
||||||
:root {
|
:root {
|
||||||
--ifm-color-primary: #25c2a0;
|
--ifm-color-primary: #10a6fa;
|
||||||
--ifm-color-primary-dark: rgb(33, 175, 144);
|
--ifm-color-primary-dark: #0598ea;
|
||||||
--ifm-color-primary-darker: rgb(31, 165, 136);
|
--ifm-color-primary-darker: #0590dd;
|
||||||
--ifm-color-primary-darkest: rgb(26, 136, 112);
|
--ifm-color-primary-darkest: #0476b6;
|
||||||
--ifm-color-primary-light: rgb(70, 203, 174);
|
--ifm-color-primary-light: #2ab0fb;
|
||||||
--ifm-color-primary-lighter: rgb(102, 212, 189);
|
--ifm-color-primary-lighter: #37b5fb;
|
||||||
--ifm-color-primary-lightest: rgb(146, 224, 208);
|
--ifm-color-primary-lightest: #5ec3fc;
|
||||||
--ifm-code-font-size: 95%;
|
--ifm-code-font-size: 95%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -23,3 +23,13 @@
|
||||||
margin: 0 calc(-1 * var(--ifm-pre-padding));
|
margin: 0 calc(-1 * var(--ifm-pre-padding));
|
||||||
padding: 0 var(--ifm-pre-padding);
|
padding: 0 var(--ifm-pre-padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cncf-logo {
|
||||||
|
background: center no-repeat url('/img/logos/cncf-color.svg');
|
||||||
|
}
|
||||||
|
|
||||||
|
html[data-theme='dark'] {
|
||||||
|
.cncf-logo {
|
||||||
|
background: center no-repeat url('/img/logos/cncf-white.svg');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,256 @@
|
||||||
|
/**
|
||||||
|
* 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 clsx from 'clsx';
|
||||||
|
import Highlight, {defaultProps} from 'prism-react-renderer';
|
||||||
|
import copy from 'copy-text-to-clipboard';
|
||||||
|
import rangeParser from 'parse-numeric-range';
|
||||||
|
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
||||||
|
import usePrismTheme from '@theme/hooks/usePrismTheme';
|
||||||
|
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']);
|
||||||
|
|
||||||
|
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 = {}},
|
||||||
|
},
|
||||||
|
} = useDocusaurusContext();
|
||||||
|
const [showCopied, setShowCopied] = useState(false);
|
||||||
|
const [mounted, setMounted] = useState(false); // The Prism theme on SSR is always the default theme but the site theme
|
||||||
|
// can be in a different mode. React hydration doesn't update DOM styles
|
||||||
|
// that come from SSR. Hence force a re-render after mounting to apply the
|
||||||
|
// current relevant styles. There will be a flash seen of the original
|
||||||
|
// styles seen using this current approach but that's probably ok. Fixing
|
||||||
|
// the flash will require changing the theming approach and is not worth it
|
||||||
|
// at this point.
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setMounted(true);
|
||||||
|
}, []);
|
||||||
|
const button = useRef(null);
|
||||||
|
let highlightLines = [];
|
||||||
|
let codeBlockTitle = '';
|
||||||
|
const prismTheme = usePrismTheme();
|
||||||
|
|
||||||
|
if (metastring && highlightLinesRangeRegex.test(metastring)) {
|
||||||
|
// Tested above
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
const highlightLinesRange = metastring.match(highlightLinesRangeRegex)[1];
|
||||||
|
highlightLines = rangeParser
|
||||||
|
.parse(highlightLinesRange)
|
||||||
|
.filter((n) => n > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (metastring && codeBlockTitleRegex.test(metastring)) {
|
||||||
|
// Tested above
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
|
codeBlockTitle = metastring
|
||||||
|
.match(codeBlockTitleRegex)[0]
|
||||||
|
.split('title=')[1]
|
||||||
|
.replace(/"+/g, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
let language =
|
||||||
|
languageClassName && languageClassName.replace(/language-/, '');
|
||||||
|
|
||||||
|
if (!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 = () => {
|
||||||
|
copy(code);
|
||||||
|
setShowCopied(true);
|
||||||
|
setTimeout(() => setShowCopied(false), 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Highlight
|
||||||
|
{...defaultProps}
|
||||||
|
key={String(mounted)}
|
||||||
|
theme={prismTheme}
|
||||||
|
code={code} // @ts-expect-error: prism-react-renderer doesn't export Language type
|
||||||
|
language={language}>
|
||||||
|
{({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={clsx(styles.copyButton, {
|
||||||
|
[styles.copyButtonWithTitle]: codeBlockTitle,
|
||||||
|
})}
|
||||||
|
onClick={handleCopyCode}>
|
||||||
|
{showCopied ? 'Copied' : 'Copy'}
|
||||||
|
</button>
|
||||||
|
<div
|
||||||
|
tabIndex={0}
|
||||||
|
className={clsx(className, styles.codeBlock, {
|
||||||
|
[styles.codeBlockWithTitle]: codeBlockTitle,
|
||||||
|
})}>
|
||||||
|
<div 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
|
||||||
|
}
|
||||||
|
|
||||||
|
const lineProps = getLineProps({
|
||||||
|
line,
|
||||||
|
key: i,
|
||||||
|
});
|
||||||
|
|
||||||
|
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>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Highlight>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
border-radius: var(--ifm-global-radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeBlockWithTitle {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyButton {
|
||||||
|
background: rgba(0, 0, 0, 0.3);
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--ifm-global-radius);
|
||||||
|
color: var(--ifm-color-white);
|
||||||
|
cursor: pointer;
|
||||||
|
opacity: 0;
|
||||||
|
outline: none;
|
||||||
|
padding: 0.4rem 0.5rem;
|
||||||
|
position: absolute;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeBlockTitle:hover + .codeBlockContent .copyButton,
|
||||||
|
.codeBlockContent:hover > .copyButton {
|
||||||
|
visibility: visible;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.codeBlockLines {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
/*jshint esversion: 6 */
|
|
||||||
import React, {useEffect, useState} from 'react';
|
|
||||||
import styles from './styles.module.css';
|
|
||||||
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
|
|
||||||
import useThemeContext from '@theme/hooks/useThemeContext';
|
|
||||||
import Highlight, { defaultProps } from "prism-react-renderer";
|
|
||||||
import monokai from "@site/src/plugins/prism_themes/monokai";
|
|
||||||
|
|
||||||
function CodeSnippet(props) {
|
|
||||||
const {
|
|
||||||
siteConfig: {
|
|
||||||
themeConfig: {prism = {}},
|
|
||||||
},
|
|
||||||
} = useDocusaurusContext();
|
|
||||||
|
|
||||||
const [mounted, setMounted] = useState(false);
|
|
||||||
// The Prism theme on SSR is always the default theme but the site theme
|
|
||||||
// can be in a different mode. React hydration doesn't update DOM styles
|
|
||||||
// that come from SSR. Hence force a re-render after mounting to apply the
|
|
||||||
// current relevant styles. There will be a flash seen of the original
|
|
||||||
// styles seen using this current approach but that's probably ok. Fixing
|
|
||||||
// the flash will require changing the theming approach and is not worth it
|
|
||||||
// at this point.
|
|
||||||
useEffect(() => {
|
|
||||||
setMounted(true);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const {isDarkTheme} = useThemeContext();
|
|
||||||
const lightModeTheme = prism.theme || monokai;
|
|
||||||
const darkModeTheme = prism.darkTheme || lightModeTheme;
|
|
||||||
const prismTheme = isDarkTheme ? darkModeTheme : lightModeTheme;
|
|
||||||
|
|
||||||
const {
|
|
||||||
lang = 'yaml',
|
|
||||||
snippet,
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Highlight {...defaultProps} key={mounted} theme={prismTheme} code={snippet} language={lang}>
|
|
||||||
{({ className, style, tokens, getLineProps, getTokenProps }) => (
|
|
||||||
<pre className={`${className} ${styles.codeSnippet}`} style={style}>
|
|
||||||
{tokens.map((line, i) => (
|
|
||||||
<div {...getLineProps({ line, key: i })}>
|
|
||||||
{line.map((token, key) => (
|
|
||||||
<span {...getTokenProps({ token, key })} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</pre>
|
|
||||||
)}
|
|
||||||
</Highlight>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CodeSnippet;
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
.codeSnippet {
|
|
||||||
font-size: 10pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 6.4 KiB |
|
|
@ -1,3 +0,0 @@
|
||||||
[
|
|
||||||
"v0.8.0"
|
|
||||||
]
|
|
||||||