Merge branch 'compact-ide' into 'dev'
Added compact IDE component See merge request ligolang/ligo!516
This commit is contained in:
commit
8e34c4a678
13534
gitlab-pages/website/package-lock.json
generated
13534
gitlab-pages/website/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -27,6 +27,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@docusaurus/plugin-sitemap": "^2.0.0-alpha.37",
|
||||
"@ligo/syntax": "file:src/@ligo/syntax"
|
||||
"@ligo/syntax": "file:src/@ligo/syntax",
|
||||
"@ligolang/compact-ligo-ide": "^3.0.3"
|
||||
}
|
||||
}
|
||||
}
|
@ -5,10 +5,13 @@
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import React, {useEffect, useState, useRef} from 'react';
|
||||
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 Highlight, { defaultProps } from 'prism-react-renderer';
|
||||
import { CompactLigoIde } from '@ligolang/compact-ligo-ide';
|
||||
|
||||
const { Prism } = require("prism-react-renderer");
|
||||
|
||||
Prism.languages = {
|
||||
...Prism.languages,
|
||||
pascaligo: {
|
||||
@ -58,21 +61,24 @@ Prism.languages = {
|
||||
],
|
||||
'punctuation': /\(\.|\.\)|[()\[\]:;,.]/
|
||||
},
|
||||
reasonligo:
|
||||
{...Prism.languages.reason,
|
||||
reasonligo:
|
||||
{
|
||||
...Prism.languages.reason,
|
||||
'comment': [
|
||||
/(^|[^\\])\/\*[\s\S]*?\*\//,
|
||||
/\(\*[\s\S]*?\*\)/,
|
||||
/\/\/.*/
|
||||
/\(\*[\s\S]*?\*\)/,
|
||||
/\/\/.*/
|
||||
]
|
||||
|
||||
|
||||
},
|
||||
cameligo: {...Prism.languages.ocaml,
|
||||
'comment': [
|
||||
cameligo: {
|
||||
...Prism.languages.ocaml,
|
||||
'comment': [
|
||||
/(^|[^\\])\/\*[\s\S]*?\*\//,
|
||||
/\(\*[\s\S]*?\*\)/,
|
||||
/\/\/.*/
|
||||
]}
|
||||
/\(\*[\s\S]*?\*\)/,
|
||||
/\/\/.*/
|
||||
]
|
||||
}
|
||||
};
|
||||
import defaultTheme from 'prism-react-renderer/themes/palenight';
|
||||
import Clipboard from 'clipboard';
|
||||
@ -84,10 +90,10 @@ import styles from './styles.module.css';
|
||||
|
||||
const highlightLinesRangeRegex = /{([\d,-]+)}/;
|
||||
|
||||
export default ({children, className: languageClassName, metastring}) => {
|
||||
export default ({ children, className: languageClassName, metastring }) => {
|
||||
const {
|
||||
siteConfig: {
|
||||
themeConfig: {prism = {}},
|
||||
themeConfig: { prism = {} },
|
||||
},
|
||||
} = useDocusaurusContext();
|
||||
|
||||
@ -108,7 +114,7 @@ export default ({children, className: languageClassName, metastring}) => {
|
||||
const button = useRef(null);
|
||||
let highlightLines = [];
|
||||
|
||||
const {isDarkTheme} = useThemeContext();
|
||||
const { isDarkTheme } = useThemeContext();
|
||||
const lightModeTheme = prism.theme || defaultTheme;
|
||||
const darkModeTheme = prism.darkTheme || lightModeTheme;
|
||||
const prismTheme = isDarkTheme ? darkModeTheme : lightModeTheme;
|
||||
@ -134,6 +140,21 @@ export default ({children, className: languageClassName, metastring}) => {
|
||||
};
|
||||
}, [button.current, target.current]);
|
||||
|
||||
// Compact Ligo IDE support - begin
|
||||
if (languageClassName === 'language-compactLigoIde') {
|
||||
const theme = isDarkTheme ? 'dark' : 'light';
|
||||
const webIdeUrlRegex = /webIdeUrl=(.*)/;
|
||||
|
||||
if (metastring && webIdeUrlRegex.test(metastring)) {
|
||||
const webIdeUrl = metastring.match(webIdeUrlRegex)[1];
|
||||
|
||||
return <CompactLigoIde webIdeUrl={webIdeUrl} theme={theme}>{children}</CompactLigoIde>
|
||||
}
|
||||
|
||||
return <CompactLigoIde theme={theme}>{children}</CompactLigoIde>
|
||||
}
|
||||
// Compact Ligo IDE support -- end
|
||||
|
||||
let language =
|
||||
languageClassName && languageClassName.replace(/language-/, '');
|
||||
|
||||
@ -155,7 +176,7 @@ export default ({children, className: languageClassName, metastring}) => {
|
||||
theme={prismTheme}
|
||||
code={children.trim()}
|
||||
language={language}>
|
||||
{({className, style, tokens, getLineProps, getTokenProps}) => (
|
||||
{({ className, style, tokens, getLineProps, getTokenProps }) => (
|
||||
<pre className={classnames(className, styles.codeBlock)}>
|
||||
<button
|
||||
ref={button}
|
||||
@ -172,7 +193,7 @@ export default ({children, className: languageClassName, metastring}) => {
|
||||
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`;
|
||||
@ -181,7 +202,7 @@ export default ({children, className: languageClassName, metastring}) => {
|
||||
return (
|
||||
<div key={i} {...lineProps}>
|
||||
{line.map((token, key) => (
|
||||
<span key={key} {...getTokenProps({token, key})} />
|
||||
<span key={key} {...getTokenProps({ token, key })} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
@ -1057,4 +1057,12 @@ a:hover {
|
||||
.boolean-example-table > .example pre,
|
||||
.boolean-example-table > .example .codeBlockLines_src-theme-CodeBlock- {
|
||||
background-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.compactLigoIde {
|
||||
height: 400px;
|
||||
}
|
||||
|
||||
.compactLigoIde pre {
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
8
tools/compact-ligo-ide/.babelrc
Normal file
8
tools/compact-ligo-ide/.babelrc
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"presets": [
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-env",
|
||||
"@babel/preset-typescript"
|
||||
],
|
||||
"plugins": ["@babel/plugin-transform-react-jsx"]
|
||||
}
|
6
tools/compact-ligo-ide/.gitignore
vendored
Normal file
6
tools/compact-ligo-ide/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*.log
|
||||
|
||||
node_modules/
|
||||
lib/
|
||||
.cache/
|
||||
dist/
|
9
tools/compact-ligo-ide/.npmignore
Normal file
9
tools/compact-ligo-ide/.npmignore
Normal file
@ -0,0 +1,9 @@
|
||||
src
|
||||
demo
|
||||
|
||||
*.lock
|
||||
.babelrc
|
||||
.gitignore
|
||||
webpack.config.js
|
||||
tsconfig.json
|
||||
webpack.config.js
|
194
tools/compact-ligo-ide/README.md
Normal file
194
tools/compact-ligo-ide/README.md
Normal file
@ -0,0 +1,194 @@
|
||||
A React component for embedding Ligo code snippets on a page.
|
||||
|
||||
# Quick start
|
||||
|
||||
1. Install package `yarn add @ligolang/compact-ligo-ide`
|
||||
2. Add `CompactLigoIde` component to a page
|
||||
|
||||
```jsx
|
||||
import { Code, Language } from "@ligolang/compact-ligo-ide";
|
||||
|
||||
const App = () => {
|
||||
const codeWithConfig = `(*_*
|
||||
name: CameLigo Contract
|
||||
dryRun:
|
||||
entrypoint: main
|
||||
parameters: Increment 2
|
||||
storage: 0
|
||||
*_*)
|
||||
// variant defining pseudo multi-entrypoint actions
|
||||
|
||||
type action is
|
||||
| Increment of int
|
||||
| Decrement of int
|
||||
|
||||
function add (const a : int ; const b : int) : int is
|
||||
block { skip } with a + b
|
||||
|
||||
function subtract (const a : int ; const b : int) : int is
|
||||
block { skip } with a - b
|
||||
|
||||
// real entrypoint that re-routes the flow based
|
||||
// on the action provided
|
||||
function main (const p : action ; const s : int) :
|
||||
(list(operation) * int) is
|
||||
block { skip } with ((nil : list(operation)),
|
||||
case p of
|
||||
| Increment(n) -> add(s, n)
|
||||
| Decrement(n) -> subtract(s, n)
|
||||
end)`;
|
||||
|
||||
const editor = {
|
||||
title: 'Smart Contract',
|
||||
language: Language.CameLigo
|
||||
};
|
||||
const compile = {
|
||||
entrypoint: 'main'
|
||||
};
|
||||
const dryRun = {
|
||||
entrypoint: 'main',
|
||||
parameters: 'Increment 1',
|
||||
storage: '0'
|
||||
};
|
||||
const deploy = {
|
||||
entrypoint: 'main',
|
||||
storage: '0'
|
||||
};
|
||||
const evaluateFunction = {
|
||||
entrypoint: 'add',
|
||||
parameters: '5, 3'
|
||||
};
|
||||
|
||||
return <CompactLigoIde
|
||||
theme="light"
|
||||
editor={editor}
|
||||
compile={compile}
|
||||
dryRun={dryRun}
|
||||
deploy={deploy}
|
||||
evaluateFunction={evaluateFunction}>
|
||||
{codeWithConfig}
|
||||
</CompactLigoIde>
|
||||
};
|
||||
```
|
||||
|
||||
3. Apply styling
|
||||
|
||||
```css
|
||||
<style type="text/css">
|
||||
.compactLigoIde {
|
||||
height: 600px;
|
||||
width: 600px;
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
# Configuration
|
||||
|
||||
Compact Ligo IDE can be configured via component parameters and/or by passing configuration as a child. The example above illustrastes how to do so.
|
||||
|
||||
## Available configuration
|
||||
|
||||
```js
|
||||
interface CompactLigoIdeProps {
|
||||
editor?: Partial<EditorConfig>;
|
||||
compile?: Partial<CompileConfig>;
|
||||
dryRun?: Partial<DryRunConfig>;
|
||||
deploy?: Partial<DeployConfig>;
|
||||
evaluateFunction?: Partial<EvaluateFunctionConfig>;
|
||||
evaluateValue?: Partial<EvaluateValueConfig>;
|
||||
result?: string;
|
||||
webIdeUrl?: string;
|
||||
theme?: "dark" | "light";
|
||||
children?: string;
|
||||
}
|
||||
|
||||
interface EditorConfig {
|
||||
language: Language;
|
||||
code: string;
|
||||
dirty: boolean;
|
||||
title: string;
|
||||
}
|
||||
|
||||
interface CompileConfig {
|
||||
entrypoint: string;
|
||||
}
|
||||
|
||||
interface DryRunConfig {
|
||||
entrypoint: string;
|
||||
parameters: string;
|
||||
storage: string;
|
||||
}
|
||||
|
||||
interface DeployConfig {
|
||||
entrypoint: string;
|
||||
storage: string;
|
||||
}
|
||||
|
||||
interface EvaluateFunctionConfig {
|
||||
entrypoint: string;
|
||||
parameters: string;
|
||||
}
|
||||
|
||||
interface EvaluateValueConfig {
|
||||
entrypoint: string;
|
||||
}
|
||||
```
|
||||
|
||||
Alternatively, the component can be configured by passing the configuration like so:
|
||||
|
||||
```
|
||||
(*_*
|
||||
name: PascaLIGO Contract
|
||||
language: pascaligo
|
||||
compile:
|
||||
entrypoint: main
|
||||
dryRun:
|
||||
entrypoint: main
|
||||
parameters: Increment (1)
|
||||
storage: 0
|
||||
deploy:
|
||||
entrypoint: main
|
||||
storage: 0
|
||||
evaluateValue:
|
||||
entrypoint: ""
|
||||
evaluateFunction:
|
||||
entrypoint: add
|
||||
parameters: (5, 6)
|
||||
*_*)
|
||||
// variant defining pseudo multi-entrypoint actions
|
||||
type action is
|
||||
| Increment of int
|
||||
| Decrement of int
|
||||
|
||||
function add (const a : int ; const b : int) : int is
|
||||
block { skip } with a + b
|
||||
|
||||
function subtract (const a : int ; const b : int) : int is
|
||||
block { skip } with a - b
|
||||
|
||||
// real entrypoint that re-routes the flow based
|
||||
// on the action provided
|
||||
function main (const p : action ; const s : int) :
|
||||
(list(operation) * int) is
|
||||
block { skip } with ((nil : list(operation)),
|
||||
case p of
|
||||
| Increment(n) -> add(s, n)
|
||||
| Decrement(n) -> subtract(s, n)
|
||||
end)
|
||||
```
|
||||
|
||||
# Contribute
|
||||
|
||||
## Starting dev server
|
||||
|
||||
1. Install dependencies with `yarn install`
|
||||
2. Run `yarn start`
|
||||
3. Open http://localhost:1234 in a browser
|
||||
|
||||
## Build package
|
||||
|
||||
Run `yarn build`.
|
||||
|
||||
## Publish package
|
||||
|
||||
Run `npm publish --access=public`.
|
22
tools/compact-ligo-ide/demo/index.html
Normal file
22
tools/compact-ligo-ide/demo/index.html
Normal file
@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<title>React TypeScript App</title>
|
||||
<style type="text/css">
|
||||
.compactLigoIde {
|
||||
height: 400px;
|
||||
width: 600px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="./index.tsx"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
73
tools/compact-ligo-ide/demo/index.tsx
Normal file
73
tools/compact-ligo-ide/demo/index.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
import React, { useState } from 'react';
|
||||
import { render } from 'react-dom';
|
||||
|
||||
import { CompactLigoIde, Language } from '../src';
|
||||
|
||||
const App = () => {
|
||||
const codeWithConfig = `(*_*
|
||||
name: CameLigo Contract
|
||||
dryRun:
|
||||
entrypoint: main
|
||||
parameters: Increment 2
|
||||
storage: 0
|
||||
*_*)
|
||||
// variant defining pseudo multi-entrypoint actions
|
||||
|
||||
type action is
|
||||
| Increment of int
|
||||
| Decrement of int
|
||||
|
||||
function add (const a : int ; const b : int) : int is
|
||||
block { skip } with a + b
|
||||
|
||||
function subtract (const a : int ; const b : int) : int is
|
||||
block { skip } with a - b
|
||||
|
||||
// real entrypoint that re-routes the flow based
|
||||
// on the action provided
|
||||
function main (const p : action ; const s : int) :
|
||||
(list(operation) * int) is
|
||||
block { skip } with ((nil : list(operation)),
|
||||
case p of
|
||||
| Increment(n) -> add(s, n)
|
||||
| Decrement(n) -> subtract(s, n)
|
||||
end)`;
|
||||
|
||||
const editor = {
|
||||
title: 'Smart Contract',
|
||||
language: Language.CameLigo
|
||||
};
|
||||
const compile = {
|
||||
entrypoint: 'main'
|
||||
};
|
||||
const dryRun = {
|
||||
entrypoint: 'main',
|
||||
parameters: 'Increment 1',
|
||||
storage: '0'
|
||||
};
|
||||
const deploy = {
|
||||
entrypoint: 'main',
|
||||
storage: '0'
|
||||
};
|
||||
const evaluateFunction = {
|
||||
entrypoint: 'add',
|
||||
parameters: '5, 3'
|
||||
};
|
||||
|
||||
const [theme, setTheme] = useState('light');
|
||||
|
||||
return <>
|
||||
<button onClick={() => theme === 'light' ? setTheme('dark') : setTheme('light')}>Toggle Theme</button>
|
||||
<CompactLigoIde
|
||||
theme={theme}
|
||||
editor={editor}
|
||||
compile={compile}
|
||||
dryRun={dryRun}
|
||||
deploy={deploy}
|
||||
evaluateFunction={evaluateFunction}>
|
||||
{codeWithConfig}
|
||||
</CompactLigoIde>
|
||||
</>;
|
||||
};
|
||||
|
||||
render(<App />, document.getElementById("root"));
|
55
tools/compact-ligo-ide/package.json
Normal file
55
tools/compact-ligo-ide/package.json
Normal file
@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "@ligolang/compact-ligo-ide",
|
||||
"version": "3.0.3",
|
||||
"main": "./lib/index.js",
|
||||
"scripts": {
|
||||
"start": "parcel ./demo/index.html",
|
||||
"build": "webpack"
|
||||
},
|
||||
"typings": "./typings/index.d.ts",
|
||||
"files": [
|
||||
"lib",
|
||||
"typings/index.d.ts"
|
||||
],
|
||||
"license": "ISC",
|
||||
"peerDependencies": {
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.8.4",
|
||||
"@babel/core": "^7.8.7",
|
||||
"@babel/plugin-transform-react-jsx": "^7.8.3",
|
||||
"@babel/preset-env": "^7.8.7",
|
||||
"@babel/preset-react": "^7.8.3",
|
||||
"@babel/preset-typescript": "^7.8.3",
|
||||
"@types/node": "^13.9.5",
|
||||
"@types/react": "^16.9.23",
|
||||
"@types/react-dom": "^16.9.5",
|
||||
"@types/styled-components": "^5.0.1",
|
||||
"babel-loader": "8.0.6",
|
||||
"css-loader": "^3.4.2",
|
||||
"parcel-bundler": "^1.12.4",
|
||||
"path": "^0.12.7",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"style-loader": "^1.1.3",
|
||||
"typescript": "^3.8.3",
|
||||
"webpack": "4.41.5",
|
||||
"webpack-cli": "^3.3.11",
|
||||
"webpack-node-externals": "^1.7.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-svg-core": "^1.2.28",
|
||||
"@fortawesome/free-solid-svg-icons": "^5.13.0",
|
||||
"@fortawesome/react-fontawesome": "^0.1.9",
|
||||
"@types/react-helmet": "^5.0.15",
|
||||
"@types/styled-theming": "^2.2.2",
|
||||
"axios": "^0.19.2",
|
||||
"monaco-editor": "npm:@ligolang/monaco-editor@0.18.1",
|
||||
"react-helmet": "^5.2.1",
|
||||
"styled-components": "^5.0.1",
|
||||
"styled-theming": "^2.2.0",
|
||||
"yaml": "^1.9.2"
|
||||
}
|
||||
}
|
145
tools/compact-ligo-ide/src/components/compact-ligo-ide.tsx
Normal file
145
tools/compact-ligo-ide/src/components/compact-ligo-ide.tsx
Normal file
@ -0,0 +1,145 @@
|
||||
import axios from 'axios';
|
||||
import React from 'react';
|
||||
import styled, { ThemeProvider } from 'styled-components';
|
||||
import { faExternalLinkAlt } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
|
||||
import { Editor } from './editor';
|
||||
import { CompactLigoIdeProps, DEFAULT_COMPACT_LIGO_IDE_PROPS, ShareParams } from '../types';
|
||||
import YAML from 'yaml';
|
||||
|
||||
const Container = styled.div`
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const Button = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
width: 60px;
|
||||
height: 30px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: 1;
|
||||
padding: 5px;
|
||||
color: white;
|
||||
|
||||
:hover {
|
||||
background: #fc683a;
|
||||
}
|
||||
`;
|
||||
|
||||
const Icon = styled(FontAwesomeIcon)`
|
||||
pointer-events: none;
|
||||
margin-left: 3px;
|
||||
`;
|
||||
|
||||
const OutputContainer = styled.div`
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const Output = styled.pre`
|
||||
background-color: rgba(14, 116, 255, 1);
|
||||
color: white;
|
||||
padding: 20px;
|
||||
margin: 0;
|
||||
overflow: auto;
|
||||
max-height: 200px;
|
||||
`;
|
||||
|
||||
function parseConfig(content: string): CompactLigoIdeProps {
|
||||
const METADATA_REGEX = /\(\*_\*([^]*?)\*_\*\)\s*/;
|
||||
const match = content.match(METADATA_REGEX);
|
||||
|
||||
if (!match || !match[1]) {
|
||||
return { editor: { code: content } };
|
||||
}
|
||||
|
||||
try {
|
||||
const config = YAML.parse(match[1]);
|
||||
|
||||
return {
|
||||
editor: {
|
||||
title: config.name,
|
||||
language: config.language,
|
||||
code: content.replace(METADATA_REGEX, '')
|
||||
},
|
||||
compile: { ...config.compile },
|
||||
dryRun: { ...config.dryRun },
|
||||
deploy: { ...config.deploy },
|
||||
evaluateFunction: { ...config.evaluateFunction },
|
||||
evaluateValue: { ...config.evaluateValue }
|
||||
};
|
||||
} catch (ex) {
|
||||
throw new Error(`Unable to parse configuration.`);
|
||||
}
|
||||
}
|
||||
|
||||
export function CompactLigoIde(props: CompactLigoIdeProps) {
|
||||
const yamlConfig = props.children ? parseConfig(props.children) : {};
|
||||
|
||||
const shareParams: ShareParams = {
|
||||
editor: {
|
||||
...DEFAULT_COMPACT_LIGO_IDE_PROPS.editor,
|
||||
...yamlConfig.editor,
|
||||
...props.editor
|
||||
},
|
||||
compile: {
|
||||
...DEFAULT_COMPACT_LIGO_IDE_PROPS.compile,
|
||||
...yamlConfig.compile,
|
||||
...props.compile
|
||||
},
|
||||
dryRun: {
|
||||
...DEFAULT_COMPACT_LIGO_IDE_PROPS.dryRun,
|
||||
...yamlConfig.dryRun,
|
||||
...props.dryRun
|
||||
},
|
||||
deploy: {
|
||||
...DEFAULT_COMPACT_LIGO_IDE_PROPS.deploy,
|
||||
...yamlConfig.deploy,
|
||||
...props.deploy
|
||||
},
|
||||
evaluateFunction: {
|
||||
...DEFAULT_COMPACT_LIGO_IDE_PROPS.evaluateFunction,
|
||||
...yamlConfig.evaluateFunction,
|
||||
...props.evaluateFunction
|
||||
},
|
||||
evaluateValue: {
|
||||
...DEFAULT_COMPACT_LIGO_IDE_PROPS.evaluateValue,
|
||||
...yamlConfig.evaluateValue,
|
||||
...props.evaluateValue
|
||||
}
|
||||
};
|
||||
const result = props.result || DEFAULT_COMPACT_LIGO_IDE_PROPS.result;
|
||||
const webIdeUrl = props.webIdeUrl || DEFAULT_COMPACT_LIGO_IDE_PROPS.webIdeUrl;
|
||||
const theme = props.theme || DEFAULT_COMPACT_LIGO_IDE_PROPS.theme;
|
||||
|
||||
async function openInIde() {
|
||||
const response = await axios.post(`${webIdeUrl}/api/share`, { ...shareParams });
|
||||
const { hash } = await response.data;
|
||||
|
||||
window.open(`${webIdeUrl}/p/${hash}`, "_blank");
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={{ mode: theme }}>
|
||||
<Container className="compactLigoIde">
|
||||
<Editor
|
||||
value={shareParams.editor.code}
|
||||
language={shareParams.editor.language}
|
||||
></Editor>
|
||||
<OutputContainer>
|
||||
<Output>{result}</Output>
|
||||
<Button onClick={openInIde} title="Open in Ligo Web IDE">
|
||||
<span>IDE<Icon icon={faExternalLinkAlt} /></span>
|
||||
</Button>
|
||||
</OutputContainer>
|
||||
</Container>
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
83
tools/compact-ligo-ide/src/components/editor.tsx
Normal file
83
tools/compact-ligo-ide/src/components/editor.tsx
Normal file
@ -0,0 +1,83 @@
|
||||
import * as monaco from 'monaco-editor';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import styled, { withTheme } from 'styled-components';
|
||||
|
||||
const Container = styled.div`
|
||||
flex: 2;
|
||||
`;
|
||||
|
||||
export const Editor = withTheme(
|
||||
(props: {
|
||||
value: string;
|
||||
language?: string;
|
||||
onChange?: (value: string) => void;
|
||||
theme: { mode: string };
|
||||
}) => {
|
||||
let containerRef = useRef(null);
|
||||
const isLightTheme = props.theme.mode === 'light';
|
||||
const background = isLightTheme ? "#eff7ff" : "#3b454e40";
|
||||
const lineHighlightBackground = isLightTheme ? "#cee3ff" : "#63768840";
|
||||
const lineNumberColor = "#888";
|
||||
|
||||
const model = monaco.editor.createModel(props.value, props.language);
|
||||
|
||||
monaco.editor.defineTheme("ligoTheme", {
|
||||
base: "vs",
|
||||
inherit: true,
|
||||
rules: [],
|
||||
colors: {
|
||||
"editor.background": background,
|
||||
"editor.lineHighlightBackground": lineHighlightBackground,
|
||||
"editorLineNumber.foreground": lineNumberColor
|
||||
}
|
||||
});
|
||||
|
||||
monaco.editor.setTheme("ligoTheme");
|
||||
|
||||
useEffect(() => {
|
||||
const cleanupFunc: Array<() => void> = [];
|
||||
const htmlElement = (containerRef.current as unknown) as HTMLElement;
|
||||
|
||||
const editor = monaco.editor.create(htmlElement, {
|
||||
readOnly: true,
|
||||
model: model,
|
||||
automaticLayout: true,
|
||||
minimap: {
|
||||
enabled: false
|
||||
}
|
||||
});
|
||||
|
||||
const { dispose } = editor.onDidChangeModelContent(() => {
|
||||
if (props.onChange) {
|
||||
props.onChange(editor.getValue());
|
||||
}
|
||||
});
|
||||
|
||||
cleanupFunc.push(dispose);
|
||||
|
||||
return function cleanUp() {
|
||||
cleanupFunc.forEach(f => f());
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Container ref={containerRef}>
|
||||
<Helmet>
|
||||
<style type="text/css">
|
||||
{`
|
||||
.monaco-editor .current-line ~ .line-numbers {
|
||||
color: ${lineNumberColor};
|
||||
}
|
||||
|
||||
.monaco-editor .margin-view-overlays .current-line,
|
||||
.monaco-editor .view-overlays .current-line {
|
||||
background-color: ${lineHighlightBackground};
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</Helmet>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
);
|
2
tools/compact-ligo-ide/src/index.tsx
Normal file
2
tools/compact-ligo-ide/src/index.tsx
Normal file
@ -0,0 +1,2 @@
|
||||
export { CompactLigoIde } from './components/compact-ligo-ide';
|
||||
export * from './types';
|
105
tools/compact-ligo-ide/src/types.ts
Normal file
105
tools/compact-ligo-ide/src/types.ts
Normal file
@ -0,0 +1,105 @@
|
||||
export enum Language {
|
||||
PascaLigo = 'pascaligo',
|
||||
CameLigo = 'cameligo',
|
||||
ReasonLigo = 'reasonligo'
|
||||
};
|
||||
|
||||
export interface ShareParams {
|
||||
editor: EditorConfig;
|
||||
compile: CompileConfig;
|
||||
dryRun: DryRunConfig;
|
||||
deploy: DeployConfig;
|
||||
evaluateFunction: EvaluateFunctionConfig;
|
||||
evaluateValue: EvaluateValueConfig;
|
||||
}
|
||||
|
||||
export interface EditorConfig {
|
||||
language: Language;
|
||||
code: string;
|
||||
dirty: boolean;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export interface CompileConfig {
|
||||
entrypoint: string;
|
||||
}
|
||||
|
||||
export interface DryRunConfig {
|
||||
entrypoint: string;
|
||||
parameters: string;
|
||||
storage: string;
|
||||
}
|
||||
|
||||
export interface DeployConfig {
|
||||
entrypoint: string;
|
||||
storage: string;
|
||||
}
|
||||
|
||||
export interface EvaluateFunctionConfig {
|
||||
entrypoint: string;
|
||||
parameters: string;
|
||||
}
|
||||
|
||||
export interface EvaluateValueConfig {
|
||||
entrypoint: string;
|
||||
}
|
||||
|
||||
export interface CompactLigoIdeProps {
|
||||
editor?: Partial<EditorConfig>;
|
||||
compile?: Partial<CompileConfig>;
|
||||
dryRun?: Partial<DryRunConfig>;
|
||||
deploy?: Partial<DeployConfig>;
|
||||
evaluateFunction?: Partial<EvaluateFunctionConfig>;
|
||||
evaluateValue?: Partial<EvaluateValueConfig>;
|
||||
result?: string;
|
||||
webIdeUrl?: string;
|
||||
theme?: "dark" | "light";
|
||||
children?: string;
|
||||
}
|
||||
|
||||
export const DEFAULT_EDITOR_CONFIG: EditorConfig = {
|
||||
code: "",
|
||||
language: Language.PascaLigo,
|
||||
dirty: true,
|
||||
title: ""
|
||||
};
|
||||
|
||||
export const DEFAULT_COMPILE_CONFIG: CompileConfig = {
|
||||
entrypoint: ""
|
||||
};
|
||||
|
||||
export const DEFAULT_DRY_RUN_CONFIG: DryRunConfig = {
|
||||
entrypoint: "",
|
||||
parameters: "",
|
||||
storage: ""
|
||||
};
|
||||
|
||||
export const DEFAULT_DEPLOY_CONFIG: DeployConfig = {
|
||||
entrypoint: "",
|
||||
storage: ""
|
||||
};
|
||||
|
||||
export const DEFAULT_EVALUATE_FUNCTION_CONFIG: EvaluateFunctionConfig = {
|
||||
entrypoint: "",
|
||||
parameters: ""
|
||||
};
|
||||
|
||||
export const DEFAULT_EVALUATE_VALUE_CONFIG: EvaluateValueConfig = {
|
||||
entrypoint: ""
|
||||
};
|
||||
|
||||
export const DEFAULT_SHARE_PARAMS: ShareParams = {
|
||||
editor: DEFAULT_EDITOR_CONFIG,
|
||||
compile: DEFAULT_COMPILE_CONFIG,
|
||||
dryRun: DEFAULT_DRY_RUN_CONFIG,
|
||||
deploy: DEFAULT_DEPLOY_CONFIG,
|
||||
evaluateFunction: DEFAULT_EVALUATE_FUNCTION_CONFIG,
|
||||
evaluateValue: DEFAULT_EVALUATE_VALUE_CONFIG
|
||||
};
|
||||
|
||||
export const DEFAULT_COMPACT_LIGO_IDE_PROPS: (ShareParams & CompactLigoIdeProps) = {
|
||||
...DEFAULT_SHARE_PARAMS,
|
||||
result: '',
|
||||
webIdeUrl: process.env.NODE_ENV === 'production' ? 'https://ide.ligolang.org' : 'http://localhost:8080',
|
||||
theme: 'light'
|
||||
};
|
19
tools/compact-ligo-ide/tsconfig.json
Normal file
19
tools/compact-ligo-ide/tsconfig.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"noEmit": true,
|
||||
"jsx": "react"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
5
tools/compact-ligo-ide/typings/index.d.ts
vendored
Normal file
5
tools/compact-ligo-ide/typings/index.d.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
import { StatelessComponent } from 'react';
|
||||
|
||||
declare const Boilerplate: StatelessComponent;
|
||||
|
||||
export { Boilerplate };
|
29
tools/compact-ligo-ide/webpack.config.js
Normal file
29
tools/compact-ligo-ide/webpack.config.js
Normal file
@ -0,0 +1,29 @@
|
||||
const path = require('path');
|
||||
const nodeExternals = require("webpack-node-externals");
|
||||
|
||||
module.exports = {
|
||||
mode: 'production',
|
||||
entry: './src/index.tsx',
|
||||
output: {
|
||||
path: path.resolve('lib'),
|
||||
filename: 'index.js',
|
||||
libraryTarget: 'commonjs2'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(t|j)sx?$/,
|
||||
exclude: /(node_modules)/,
|
||||
use: 'babel-loader'
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ["style-loader", "css-loader"],
|
||||
},
|
||||
]
|
||||
},
|
||||
externals: [nodeExternals()],
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.js', '.jsx']
|
||||
},
|
||||
}
|
6593
tools/compact-ligo-ide/yarn.lock
Normal file
6593
tools/compact-ligo-ide/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
35
tools/webide/packages/server/package-lock.json
generated
35
tools/webide/packages/server/package-lock.json
generated
@ -650,6 +650,15 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/cors": {
|
||||
"version": "2.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.6.tgz",
|
||||
"integrity": "sha512-invOmosX0DqbpA+cE2yoHGUlF/blyf7nB0OGYBBiH27crcVm5NmFaZkLP4Ta1hGaesckCi5lVLlydNJCxkTOSg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/express": "*"
|
||||
}
|
||||
},
|
||||
"@types/express": {
|
||||
"version": "4.17.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.3.tgz",
|
||||
@ -752,12 +761,14 @@
|
||||
"@types/node": {
|
||||
"version": "10.14.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.21.tgz",
|
||||
"integrity": "sha512-nuFlRdBiqbF+PJIEVxm2jLFcQWN7q7iWEJGsBV4n7v1dbI9qXB8im2pMMKMCUZe092sQb5SQft2DHfuQGK5hqQ=="
|
||||
"integrity": "sha512-nuFlRdBiqbF+PJIEVxm2jLFcQWN7q7iWEJGsBV4n7v1dbI9qXB8im2pMMKMCUZe092sQb5SQft2DHfuQGK5hqQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node-fetch": {
|
||||
"version": "2.5.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.5.tgz",
|
||||
"integrity": "sha512-IWwjsyYjGw+em3xTvWVQi5MgYKbRs0du57klfTaZkv/B24AEQ/p/IopNeqIYNy3EsfHOpg8ieQSDomPcsYMHpA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"form-data": "^3.0.0"
|
||||
@ -1056,7 +1067,8 @@
|
||||
"asynckit": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
|
||||
"dev": true
|
||||
},
|
||||
"atob": {
|
||||
"version": "2.1.2",
|
||||
@ -1677,6 +1689,7 @@
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"delayed-stream": "~1.0.0"
|
||||
}
|
||||
@ -1772,6 +1785,15 @@
|
||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||
},
|
||||
"cors": {
|
||||
"version": "2.8.5",
|
||||
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
|
||||
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
|
||||
"requires": {
|
||||
"object-assign": "^4",
|
||||
"vary": "^1"
|
||||
}
|
||||
},
|
||||
"create-error-class": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
|
||||
@ -1970,7 +1992,8 @@
|
||||
"delayed-stream": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
|
||||
"dev": true
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
@ -2662,6 +2685,7 @@
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.0.tgz",
|
||||
"integrity": "sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
@ -5181,6 +5205,11 @@
|
||||
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
|
||||
},
|
||||
"object-copy": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
|
||||
|
@ -19,6 +19,8 @@
|
||||
"@types/node": "10",
|
||||
"@types/tmp": "^0.1.0",
|
||||
"@types/winston": "^2.4.4",
|
||||
"@types/cors": "^2.8.6",
|
||||
"@types/node-fetch": "^2.5.4",
|
||||
"jest": "^24.9.0",
|
||||
"nodemon": "^1.19.3",
|
||||
"ts-jest": "^24.1.0",
|
||||
@ -32,8 +34,8 @@
|
||||
"@google-cloud/storage": "^4.0.0",
|
||||
"@hapi/joi": "^16.1.7",
|
||||
"@taquito/taquito": "^6.1.0-beta.0",
|
||||
"@types/node-fetch": "^2.5.4",
|
||||
"body-parser": "^1.19.0",
|
||||
"cors": "^2.8.5",
|
||||
"escape-html": "^1.0.3",
|
||||
"express": "^4.17.1",
|
||||
"express-prometheus-middleware": "^0.8.5",
|
||||
|
@ -1,3 +1,4 @@
|
||||
import cors from 'cors';
|
||||
import express from 'express';
|
||||
import fs from 'fs';
|
||||
import { dirname, join } from 'path';
|
||||
@ -25,6 +26,15 @@ const APP_PORT = 8080;
|
||||
const metrics = express();
|
||||
const METRICS_PORT = 8081;
|
||||
|
||||
const corsOptions = {
|
||||
origin: [
|
||||
'https://ligolang.org',
|
||||
'http://localhost:3000',
|
||||
'http://localhost:1234'
|
||||
],
|
||||
optionsSuccessStatus: 200
|
||||
};
|
||||
|
||||
const appRootDirectory =
|
||||
process.env['STATIC_ASSETS'] ||
|
||||
dirname(require.resolve('../../client/package.json'));
|
||||
@ -60,6 +70,9 @@ app.use('^/$', async (_, res) =>
|
||||
res.send(template(JSON.stringify(await loadDefaultState(appBundleDirectory))))
|
||||
);
|
||||
app.use(express.static(appBundleDirectory));
|
||||
|
||||
app.options('/api/share', cors(corsOptions));
|
||||
|
||||
app.get(
|
||||
`/p/:hash([0-9a-zA-Z\-\_]+)`,
|
||||
sharedLinkHandler(appBundleDirectory, template)
|
||||
@ -68,7 +81,7 @@ app.post('/api/compile-contract', compileContractHandler);
|
||||
app.post('/api/compile-expression', compileExpressionHandler);
|
||||
app.post('/api/compile-storage', compileStorageHandler);
|
||||
app.post('/api/dry-run', dryRunHandler);
|
||||
app.post('/api/share', shareHandler);
|
||||
app.post('/api/share', cors(corsOptions), shareHandler);
|
||||
app.post('/api/evaluate-value', evaluateValueHandler);
|
||||
app.post('/api/run-function', runFunctionHandler);
|
||||
app.post('/api/deploy', deployHandler);
|
||||
|
@ -1471,6 +1471,13 @@
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/cors@^2.8.6":
|
||||
version "2.8.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.6.tgz#cfaab33c49c15b1ded32f235111ce9123009bd02"
|
||||
integrity sha512-invOmosX0DqbpA+cE2yoHGUlF/blyf7nB0OGYBBiH27crcVm5NmFaZkLP4Ta1hGaesckCi5lVLlydNJCxkTOSg==
|
||||
dependencies:
|
||||
"@types/express" "*"
|
||||
|
||||
"@types/eslint-visitor-keys@^1.0.0":
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d"
|
||||
@ -3496,6 +3503,14 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||
|
||||
cors@^2.8.5:
|
||||
version "2.8.5"
|
||||
resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
|
||||
integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
|
||||
dependencies:
|
||||
object-assign "^4"
|
||||
vary "^1"
|
||||
|
||||
cosmiconfig@^5.0.0, cosmiconfig@^5.2.0, cosmiconfig@^5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
|
||||
@ -8225,7 +8240,7 @@ oauth-sign@~0.9.0:
|
||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||
|
||||
object-assign@4.1.1, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
object-assign@4.1.1, object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
@ -11935,7 +11950,7 @@ validate-npm-package-license@^3.0.1:
|
||||
spdx-correct "^3.0.0"
|
||||
spdx-expression-parse "^3.0.0"
|
||||
|
||||
vary@~1.1.2:
|
||||
vary@^1, vary@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
|
||||
|
Loading…
Reference in New Issue
Block a user