diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..2a8ed509 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +**/src/api/apollo/generated \ No newline at end of file diff --git a/Makefile b/Makefile index 6f0ed7be..e8252b7e 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,11 @@ install: $(info Task: install) $(EXEC) sh -c 'npm install || exit 255' +.PHONY: format +format: + $(info Task: format:check) + $(EXEC) sh -c 'npm run format:check:app || exit 255' + .PHONY: build build: $(info Task: build production) @@ -36,4 +41,4 @@ test: $(EXEC) sh -c 'npm run test || exit 255' .PHONY: ci -ci: clean install build test +ci: clean install format build test diff --git a/src/api/apollo/generated/graphql.tsx b/src/api/apollo/generated/graphql.tsx index 3bef27a0..a59739ae 100644 --- a/src/api/apollo/generated/graphql.tsx +++ b/src/api/apollo/generated/graphql.tsx @@ -1636,4 +1636,3 @@ export type GetResultsQueryResult = ApolloReactCommon.QueryResult void; @@ -13,14 +13,14 @@ export const AccountAvatar: React.FC<{ {children} @@ -33,8 +33,8 @@ export const AvatarList: React.FC = ({ children }) => { return ( {children} @@ -52,9 +52,16 @@ const AccountAvatars: React.FC<{ accounts: Account[]; maxSelection?: number; }> = (props) => { - const { multi, selectedAccounts, accounts, project, onChange, maxSelection = 4 } = props; + const { + multi, + selectedAccounts, + accounts, + project, + onChange, + maxSelection = 4, + } = props; if (!multi) { - throw new Error("Must include multi prop."); + throw new Error('Must include multi prop.'); } const { theme } = useThemeUI(); @@ -64,24 +71,25 @@ const AccountAvatars: React.FC<{ {accounts.map((account: Account, i: number) => { const isSelected = - selectedAccounts.includes(i) || selectionLimitReached + selectedAccounts.includes(i) || selectionLimitReached; return ( { onChange(i); } + onClick={ + isSelected + ? noop + : () => { + onChange(i); + } } active={isSelected} > @@ -89,22 +97,23 @@ const AccountAvatars: React.FC<{ seed={project.seed} index={i} style={{ - width: "35px", - height: "35px", - display: "block", - borderRadius: "0 0 20px 20px", - filter: isSelected - ? "grayscale(1)" - : "none" - }} /> + width: '35px', + height: '35px', + display: 'block', + borderRadius: '0 0 20px 20px', + filter: isSelected ? 'grayscale(1)' : 'none', + }} + /> 0x{account.address.slice(-2)} diff --git a/src/components/AccountList.tsx b/src/components/AccountList.tsx index 31c79e7b..31542a0c 100644 --- a/src/components/AccountList.tsx +++ b/src/components/AccountList.tsx @@ -1,24 +1,24 @@ -import React from "react"; -import {navigate, useLocation} from "@reach/router" -import {Account} from "api/apollo/generated/graphql"; -import {EntityType} from "providers/Project"; -import {SidebarSection as Root} from "layout/SidebarSection"; -import {SidebarHeader as Header} from "layout/SidebarHeader"; -import {SidebarItems as Items} from "layout/SidebarItems"; -import {SidebarItem as Item} from "layout/SidebarItem"; -import {Stack} from "layout/Stack"; -import {useProject} from "providers/Project/projectHooks"; -import Avatar from "components/Avatar"; -import styled from "@emotion/styled"; -import {ExportButton} from "components/ExportButton"; -import {getParams, isUUUID, LOCAL_PROJECT_ID} from "../util/url"; -import {ResourcesExplorerButton} from "components/ResourcesExplorerButton"; +import React from 'react'; +import { navigate, useLocation } from '@reach/router'; +import { Account } from 'api/apollo/generated/graphql'; +import { EntityType } from 'providers/Project'; +import { SidebarSection as Root } from 'layout/SidebarSection'; +import { SidebarHeader as Header } from 'layout/SidebarHeader'; +import { SidebarItems as Items } from 'layout/SidebarItems'; +import { SidebarItem as Item } from 'layout/SidebarItem'; +import { Stack } from 'layout/Stack'; +import { useProject } from 'providers/Project/projectHooks'; +import Avatar from 'components/Avatar'; +import styled from '@emotion/styled'; +import { ExportButton } from 'components/ExportButton'; +import { getParams, isUUUID, LOCAL_PROJECT_ID } from '../util/url'; +import { ResourcesExplorerButton } from 'components/ResourcesExplorerButton'; function getDeployedContracts(account: Account): string { const contracts = account.deployedContracts.map( - contract => contract.split(".").slice(-1)[0] + (contract) => contract.split('.').slice(-1)[0], ); - return contracts.join(", "); + return contracts.join(', '); } export const AccountCard = styled.div` @@ -30,45 +30,45 @@ export const AccountCard = styled.div` `; const AccountList: React.FC = () => { - const { - project, - active, - selectedResourceAccount - } = useProject(); - const accountSelected = active.type === EntityType.Account + const { project, active, selectedResourceAccount } = useProject(); + const accountSelected = active.type === EntityType.Account; const location = useLocation(); - const params = getParams(location.search) - const projectPath = isUUUID(project.id) ? project.id : LOCAL_PROJECT_ID + const params = getParams(location.search); + const projectPath = isUUUID(project.id) ? project.id : LOCAL_PROJECT_ID; return (
Accounts
{project.accounts.map((account: Account, i: number) => { - const { id } = account - const isActive = accountSelected && params.id === id - const accountAddress = `0x${account.address.slice(-2)}` - const contractName = getDeployedContracts(account) + const { id } = account; + const isActive = accountSelected && params.id === id; + const accountAddress = `0x${account.address.slice(-2)}`; + const contractName = getDeployedContracts(account); const title = contractName ? `${contractName} is deployed to this account` - : `This account don't have any contracts` - const typeName = account.__typename + : `This account don't have any contracts`; + const typeName = account.__typename; return ( - + navigate(`/${projectPath}?type=account&id=${id}&storage=${selectedResourceAccount || 'none'}`)} + onClick={() => + navigate( + `/${projectPath}?type=account&id=${id}&storage=${ + selectedResourceAccount || 'none' + }`, + ) + } > {accountAddress} {contractName || '--'} - {isActive && } + {isActive && ( + + )} diff --git a/src/components/AccountPicker.tsx b/src/components/AccountPicker.tsx index 7952760e..4c5357ef 100644 --- a/src/components/AccountPicker.tsx +++ b/src/components/AccountPicker.tsx @@ -1,8 +1,8 @@ -import React, { useEffect } from "react"; -import { Flex, useThemeUI } from "theme-ui"; -import { Account, Project } from "api/apollo/generated/graphql"; -import AccountAvatars from "components/AccountAvatars"; -import AccountSigners from "components/AccountSigners"; +import React, { useEffect } from 'react'; +import { Flex, useThemeUI } from 'theme-ui'; +import { Account, Project } from 'api/apollo/generated/graphql'; +import AccountAvatars from 'components/AccountAvatars'; +import AccountSigners from 'components/AccountSigners'; type AccountPickerProps = { project: Project; @@ -18,7 +18,7 @@ const AccountPicker: React.FC = ({ selected, onChange, maxSelection = 4, - children + children, }) => { const { theme } = useThemeUI(); const handleOnChange = (i: number) => { @@ -33,25 +33,25 @@ const AccountPicker: React.FC = ({ if (!selected.length) { onChange([0]); } - if (selected.length > maxSelection){ - onChange(selected.slice(0,maxSelection)) + if (selected.length > maxSelection) { + onChange(selected.slice(0, maxSelection)); } }, [maxSelection]); return ( = ({ - = ({ maxSelection={maxSelection} /> {children} diff --git a/src/components/AccountSigners.tsx b/src/components/AccountSigners.tsx index ab53a557..1ae5897a 100644 --- a/src/components/AccountSigners.tsx +++ b/src/components/AccountSigners.tsx @@ -1,9 +1,9 @@ -import React from "react"; -import { useThemeUI, Flex, Badge, Text } from "theme-ui"; -import { motion } from "framer-motion"; -import { Account, Project } from "src/api/apollo/generated/graphql"; -import Avatar from "components/Avatar"; -import { AccountAvatar, AvatarList } from "components/AccountAvatars"; +import React from 'react'; +import { useThemeUI, Flex, Badge, Text } from 'theme-ui'; +import { motion } from 'framer-motion'; +import { Account, Project } from 'src/api/apollo/generated/graphql'; +import Avatar from 'components/Avatar'; +import { AccountAvatar, AvatarList } from 'components/AccountAvatars'; export const Outline: React.FC = ({ children }) => { const { theme } = useThemeUI(); @@ -11,14 +11,14 @@ export const Outline: React.FC = ({ children }) => { return ( {children} @@ -33,15 +33,22 @@ const AccountSigners: React.FC<{ onChange: (selected: number) => void; project: Project; accounts: Account[]; - maxSelection?: number + maxSelection?: number; }> = (props) => { - const { multi, selectedAccounts, accounts, project, onChange, maxSelection} = props; + const { + multi, + selectedAccounts, + accounts, + project, + onChange, + maxSelection, + } = props; if (!multi) { - throw new Error("Must include multi prop."); + throw new Error('Must include multi prop.'); } const { theme } = useThemeUI(); - const amount = maxSelection || project.accounts.length + const amount = maxSelection || project.accounts.length; const renderOutlines = () => { const outlines = []; for (let i = selectedAccounts.length; i < amount; i++) { @@ -50,12 +57,12 @@ const AccountSigners: React.FC<{ {i + 1} - + , ); } return outlines; @@ -76,29 +83,30 @@ const AccountSigners: React.FC<{ > - + width: '35px', + height: '35px', + display: 'block', + borderRadius: '0 0 20px 20px', + }} + /> 0x{account.address.slice(-2)} diff --git a/src/components/ActionButton.tsx b/src/components/ActionButton.tsx index c9af6c46..1b511beb 100644 --- a/src/components/ActionButton.tsx +++ b/src/components/ActionButton.tsx @@ -1,21 +1,24 @@ -import React from "react"; -import { motion } from "framer-motion"; +import React from 'react'; +import { motion } from 'framer-motion'; import { CSSProperties } from 'styled-components'; import Button from './Button'; interface ActionButtonProps { - children?: any, - onClick?: any, - className?: string, - style?: CSSProperties, - Icon?: any, - isLoading?: boolean, - isActive?: boolean, -}; + children?: any; + onClick?: any; + className?: string; + style?: CSSProperties; + Icon?: any; + isLoading?: boolean; + isActive?: boolean; +} -const ActionButton: React.FC = props => { +const ActionButton: React.FC = (props) => { return ( - + ); diff --git a/src/components/Arguments/SingleArgument/index.tsx b/src/components/Arguments/SingleArgument/index.tsx index 8281da68..7b50b493 100644 --- a/src/components/Arguments/SingleArgument/index.tsx +++ b/src/components/Arguments/SingleArgument/index.tsx @@ -1,30 +1,35 @@ -import React from "react"; -import { Argument } from "components/Arguments/types"; -import { InputBlock, Input, Label, Type, Error } from "./styles"; - -type SingleArgumentProps = { - argument: Argument, - error: String, - onChange: (name: String, value:any) => void -} - -const SingleArgument: React.FC = ({ argument, error, onChange }) => { - const {name, type} = argument - return ( - - - { - const {value} = event.target - onChange(name,value) - }}/> - {error && {error}} - - ) -} - -export default SingleArgument +import React from 'react'; +import { Argument } from 'components/Arguments/types'; +import { InputBlock, Input, Label, Type, Error } from './styles'; + +type SingleArgumentProps = { + argument: Argument; + error: String; + onChange: (name: String, value: any) => void; +}; + +const SingleArgument: React.FC = ({ + argument, + error, + onChange, +}) => { + const { name, type } = argument; + return ( + + + { + const { value } = event.target; + onChange(name, value); + }} + /> + {error && {error}} + + ); +}; + +export default SingleArgument; diff --git a/src/components/Arguments/SingleArgument/styles.tsx b/src/components/Arguments/SingleArgument/styles.tsx index 3316f620..a4e2c92e 100644 --- a/src/components/Arguments/SingleArgument/styles.tsx +++ b/src/components/Arguments/SingleArgument/styles.tsx @@ -1,43 +1,42 @@ -import React from 'react' -import styled from "styled-components" +import React from 'react'; +import styled from 'styled-components'; interface InpubBlockProps { - mb?: string + mb?: string; } export const InputBlock = styled.div` display: flex; flex-direction: column; - margin-bottom: ${({mb = "0"}) => mb}; + margin-bottom: ${({ mb = '0' }) => mb}; position: relative; -` - +`; interface LabelProps { - error?: boolean + error?: boolean; } export const Label = styled.p` margin: 0; font-size: 14px; margin-bottom: 5px; - color: ${({error})=> error ? "#EE431E" : "#000"}; + color: ${({ error }) => (error ? '#EE431E' : '#000')}; `; export const Type = styled.span` font-weight: normal; - color: #3E98EB; + color: #3e98eb; margin-left: 4px; - &:before{ - content: "("; + &:before { + content: '('; } - &:after{ - content: ")"; + &:after { + content: ')'; } -` +`; export const Input = styled.input` - border: 1px solid #C4C4C4; + border: 1px solid #c4c4c4; border-radius: 5px; font-size: 14px; color: #000; @@ -45,7 +44,7 @@ export const Input = styled.input` width: 100%; font-weight: bold; margin-bottom: 5px; - &:last-child{ + &:last-child { margin-bottom: 0; } box-sizing: border-box; @@ -71,23 +70,18 @@ export const InputIconContainer = styled.div` cursor: pointer; color: #888; user-select: none; - - &:hover{ + + &:hover { color: #333; } `; - type InputIconProps = { - onClick?: any, - icon: JSX.Element -} + onClick?: any; + icon: JSX.Element; +}; export const InputIcon = (props: InputIconProps) => { - const { onClick, icon } = props - return ( - - {icon} - - ) -} \ No newline at end of file + const { onClick, icon } = props; + return {icon}; +}; diff --git a/src/components/Arguments/index.tsx b/src/components/Arguments/index.tsx index 4f2d3442..1e23c40c 100644 --- a/src/components/Arguments/index.tsx +++ b/src/components/Arguments/index.tsx @@ -1,7 +1,7 @@ import React, { useEffect, useRef, useState } from 'react'; import { FaRegCheckCircle, FaRegTimesCircle, FaSpinner } from 'react-icons/fa'; import { AiFillCloseCircle } from 'react-icons/ai'; -import { motion, AnimatePresence } from "framer-motion"; +import { motion, AnimatePresence } from 'framer-motion'; import { EntityType } from 'providers/Project'; import { useProject } from 'providers/Project/projectHooks'; import { RemoveToastButton } from 'layout/RemoveToastButton'; @@ -15,7 +15,12 @@ import { import { ArgumentsProps } from 'components/Arguments/types'; import { ExecuteCommandRequest } from 'monaco-languageclient'; -import { ControlContainer, ToastContainer, HoverPanel, StatusMessage } from './styles'; +import { + ControlContainer, + ToastContainer, + HoverPanel, + StatusMessage, +} from './styles'; import { ActionButton, @@ -26,30 +31,26 @@ import { Signers, } from './components'; -const isDictionaary = (type:string) => type.includes("{") -const isArray = (type:string) => type.includes("[") -const isImportedType = (type:string) => type.includes(".") -const isComplexType = (type:string)=> isDictionaary(type) - || isArray(type) - || isImportedType(type) +const isDictionaary = (type: string) => type.includes('{'); +const isArray = (type: string) => type.includes('['); +const isImportedType = (type: string) => type.includes('.'); +const isComplexType = (type: string) => + isDictionaary(type) || isArray(type) || isImportedType(type); -const startsWith = (value : string, prefix: string) => { - return value.startsWith(prefix) || value.startsWith("U"+prefix) -} +const startsWith = (value: string, prefix: string) => { + return value.startsWith(prefix) || value.startsWith('U' + prefix); +}; const checkJSON = (value: any, type: string) => { - try{ - JSON.parse(value) - return null - } catch (e){ - return `Not a valid argument of type ${type}` + try { + JSON.parse(value); + return null; + } catch (e) { + return `Not a valid argument of type ${type}`; } -} +}; -const validateByType = ( - value: any, - type: string, -) => { +const validateByType = (value: any, type: string) => { if (value.length === 0) { return "Value can't be empty"; } @@ -61,7 +62,7 @@ const validateByType = ( } // Integers - case startsWith(type,'Int'): { + case startsWith(type, 'Int'): { if (isNaN(value) || value === '') { return 'Should be a valid Integer number'; } @@ -69,7 +70,7 @@ const validateByType = ( } // Words - case startsWith(type,'Word'): { + case startsWith(type, 'Word'): { if (isNaN(value) || value === '') { return 'Should be a valid Word number'; } @@ -111,7 +112,6 @@ const validateByType = ( } }; - const getLabel = ( resultType: ResultType, project: any, @@ -167,7 +167,7 @@ const Arguments: React.FC = (props) => { const needSigners = type == EntityType.TransactionTemplate && signers > 0; const [selected, updateSelectedAccounts] = useState([]); - const [errors, setErrors] = useState({}) + const [errors, setErrors] = useState({}); const [expanded, setExpanded] = useState(true); const [values, setValue] = useState({}); const constraintsRef = useRef(); @@ -176,7 +176,7 @@ const Arguments: React.FC = (props) => { set((prev: any[]) => { delete prev[id]; return { - ...prev + ...prev, }; }); }; @@ -202,12 +202,12 @@ const Arguments: React.FC = (props) => { return acc; }, {}); - console.log({errors}); + console.log({ errors }); setErrors(errors); }; - useEffect(()=>{ - validate(list, values) + useEffect(() => { + validate(list, values); }, [list, values]); const [processingStatus, setProcessingStatus] = useState(false); @@ -218,15 +218,17 @@ const Arguments: React.FC = (props) => { transactionFactory, contractDeployment, } = useTemplateType(); - const { - project, - active, - isSavingCode, + const { + project, + active, + isSavingCode, lastSigners, // updateAccountDeployedCode } = useProject(); - const [notifications, setNotifications] = useState< { [identifier: string]: string[] } >({}); + const [notifications, setNotifications] = useState<{ + [identifier: string]: string[]; + }>({}); // compare 'state' field for each account, set 'notifications' state for new data // @ts-ignore: <- this state is only used to compare and render notifications @@ -235,21 +237,24 @@ const Arguments: React.FC = (props) => { useEffect(() => { setProjectAccts((prevAccounts) => { const latestAccounts = project.accounts; - const updatedAccounts = latestAccounts.filter((latestAccount, index)=> latestAccount.state !== prevAccounts[index].state); + const updatedAccounts = latestAccounts.filter( + (latestAccount, index) => + latestAccount.state !== prevAccounts[index].state, + ); if (updatedAccounts.length > 0) { setNotifications((prev) => { return { ...prev, - [counter]: updatedAccounts + [counter]: updatedAccounts, }; }); setTimeout(() => removeNotification(setNotifications, counter), 5000); setCounter((prev) => prev + 1); - }; + } return project.accounts; }); - },[project]); + }, [project]); const { accounts } = project; @@ -299,7 +304,7 @@ const Arguments: React.FC = (props) => { } // Map values to strings that will be passed to backend - const args: any = list.map((_, index) => JSON.stringify(formatted[index])) + const args: any = list.map((_, index) => JSON.stringify(formatted[index])); let rawResult, resultType; try { @@ -426,58 +431,68 @@ const Arguments: React.FC = (props) => { let updatedStorageAccts: string[] = []; updatedAccounts.map((acct: any) => { const addr = acct.address; - const acctNum = addr.charAt(addr.length-1); + const acctNum = addr.charAt(addr.length - 1); const acctHex = `0x0${acctNum}`; updatedStorageAccts.push(acctHex); }); // render a new list item for each new id in 'notifications' state return ( - (lastSigners && updatedStorageAccts) && - - removeNotification(setNotifications, parseInt(id))} + - - - - - + removeNotification(setNotifications, parseInt(id)) + } + > + + + + - {`Account${lastSigners?.length > 1 ? "s" : ""} - ${lastSigners.join(", ")} + + {`Account${lastSigners?.length > 1 ? 's' : ''} + ${lastSigners.join(', ')} updated the storage in - account${updatedStorageAccts?.length > 1 ? "s" : ""} - ${updatedStorageAccts.join(", ")}.`} - - - - ) + account${updatedStorageAccts?.length > 1 ? 's' : ''} + ${updatedStorageAccts.join(', ')}.`} + +
+ + ) + ); })} diff --git a/src/components/Arguments/styles.tsx b/src/components/Arguments/styles.tsx index 99be388b..d7928b0b 100644 --- a/src/components/Arguments/styles.tsx +++ b/src/components/Arguments/styles.tsx @@ -6,7 +6,7 @@ interface HoverPanelProps { } export const HoverPanel = styled.div` - min-width: ${({minWidth}) => minWidth}; + min-width: ${({ minWidth }) => minWidth}; max-width: 500px; padding: 20px; border-radius: 4px; @@ -15,11 +15,11 @@ export const HoverPanel = styled.div` `; interface HidableProps { - hidden: Boolean + hidden: Boolean; } export const Hidable = styled.div` - display: ${({hidden = false}) => hidden ? "none" : "block"}; -` + display: ${({ hidden = false }) => (hidden ? 'none' : 'block')}; +`; export const Heading = styled.div` display: flex; @@ -29,7 +29,7 @@ export const Heading = styled.div` `; interface TitleProps { - lineColor?: string + lineColor?: string; } export const Title = styled.div` @@ -87,7 +87,7 @@ export const Badge = styled.div` `; interface ListProps { - hidden?: boolean + hidden?: boolean; } export const List = styled.div` display: ${({ hidden }) => (hidden ? 'none' : 'grid')}; @@ -108,8 +108,8 @@ interface ControlContainerProps { showPrompt?: boolean; } export const ControlContainer = styled.div` - display: ${({ showPrompt }) => showPrompt ? 'block' : 'flex'}; - max-width: ${({ showPrompt }) => showPrompt ? 'min-content' : 'none'}; + display: ${({ showPrompt }) => (showPrompt ? 'block' : 'flex')}; + max-width: ${({ showPrompt }) => (showPrompt ? 'min-content' : 'none')}; align-items: center; justify-content: space-between; color: ${({ isOk, progress, showPrompt }) => { @@ -174,23 +174,23 @@ export const SingleError = styled.div` padding: 10px; border-radius: 4px; font-size: 14px; - &:hover{ + &:hover { background-color: rgba(244, 57, 64, 0.15); - - &.hint-warning{ + + &.hint-warning { background-color: rgb(238, 169, 30, 0.15); } - &.hint-info{ + &.hint-info { background-color: rgb(85, 238, 30, 0.15); } } -` +`; export const ErrorIndex = styled.div` width: 20px; height: 20px; - background-color: rgba(0,0,0,0.15); + background-color: rgba(0, 0, 0, 0.15); display: flex; align-items: center; justify-content: center; @@ -203,13 +203,13 @@ export const ErrorMessage = styled.p` line-height: 1.2; word-break: break-word; span { - background-color: rgba(0,0, 0, 0.05); + background-color: rgba(0, 0, 0, 0.05); padding: 2px 6px; border-radius: 3px; margin: 3px 3px 3px 5px; line-height: 20px; - .suggestion{ - background-color: ${theme.colors.primary} + .suggestion { + background-color: ${theme.colors.primary}; } } `; @@ -221,7 +221,7 @@ export const SignersError = styled.p` box-sizing: border-box; margin: 10px 0; color: ${theme.colors.error}; - svg{ + svg { margin-right: 0.5em; } `; diff --git a/src/components/Arguments/types.tsx b/src/components/Arguments/types.tsx index 6dcce08e..ea60ef4d 100644 --- a/src/components/Arguments/types.tsx +++ b/src/components/Arguments/types.tsx @@ -48,16 +48,16 @@ export type Actions = { goTo: (position: monaco.IPosition) => void; hover: (highlight: Highlight) => void; hideDecorations: () => void; -} +}; export type ErrorListProps = { list: CadenceProblem[]; - actions: Actions + actions: Actions; }; export type HintsProps = { problems: ProblemsList; - actions: Actions + actions: Actions; }; export type HintsState = { diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx index 55160ba1..91ca2262 100644 --- a/src/components/Avatar.tsx +++ b/src/components/Avatar.tsx @@ -1,11 +1,11 @@ -import React from "react"; -import { avataaar } from "util/avataaar"; -import { mb32 } from "util/rng"; +import React from 'react'; +import { avataaar } from 'util/avataaar'; +import { mb32 } from 'util/rng'; interface AvatarProps { - seed: number - index: number - style?: any + seed: number; + index: number; + style?: any; } const Avatar: React.FC = ({ seed, index, style }) => { @@ -17,7 +17,7 @@ const Avatar: React.FC = ({ seed, index, style }) => { return ( - ) + ); }; export default Avatar; diff --git a/src/components/Button.tsx b/src/components/Button.tsx index 57b0f213..5cbaecba 100644 --- a/src/components/Button.tsx +++ b/src/components/Button.tsx @@ -1,9 +1,9 @@ -import React from "react"; -import { Button as ThemedButton } from "theme-ui"; -import styled from "@emotion/styled"; -import { motion } from "framer-motion"; -import { FaSpinner } from "react-icons/fa"; -import { CSSProperties } from "styled-components"; +import React from 'react'; +import { Button as ThemedButton } from 'theme-ui'; +import styled from '@emotion/styled'; +import { motion } from 'framer-motion'; +import { FaSpinner } from 'react-icons/fa'; +import { CSSProperties } from 'styled-components'; interface StyledButtonProps { style?: CSSProperties; @@ -13,11 +13,10 @@ interface StyledButtonProps { } const StyledButton: React.FC = styled(ThemedButton)` - display: flex; align-items: center; justify-content: center; - + @keyframes rotating { from { transform: rotate(0deg); @@ -34,27 +33,28 @@ const StyledButton: React.FC = styled(ThemedButton)` .loading { animation: rotating 0.5s linear infinite; } - - &.violet{ - background-color: #BDC4F4; - color: #575E89; + + &.violet { + background-color: #bdc4f4; + color: #575e89; } - &.grey{ - background-color: #EDEDED; + &.grey { + background-color: #ededed; color: #696969; } - &.modal{ + &.modal { width: 100px; font-size: 16px; font-weight: bold; } - + display: flex; align-items: center; - - cursor: ${({variant}) => variant === "buttons.disabled" ? "not-allowed !important" : "pointer"}; + + cursor: ${({ variant }) => + variant === 'buttons.disabled' ? 'not-allowed !important' : 'pointer'}; `; interface ButtonProps { @@ -78,17 +78,15 @@ const Button: React.FC = ({ Icon, isLoading, isActive, - disabled + disabled, }) => { return ( - + {children} {isLoading ? ( @@ -104,10 +102,10 @@ const Button: React.FC = ({ Button.defaultProps = { onClick: () => {}, style: {}, - className: "", + className: '', Icon: null, isLoading: false, - isActive: true + isActive: true, }; export default Button; diff --git a/src/components/CadenceEditor/ControlPanel/components.tsx b/src/components/CadenceEditor/ControlPanel/components.tsx index d9c14b12..0e16e8ed 100644 --- a/src/components/CadenceEditor/ControlPanel/components.tsx +++ b/src/components/CadenceEditor/ControlPanel/components.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React from 'react'; import { motion } from 'framer-motion'; import styled from 'styled-components'; import theme from '../../../theme'; @@ -240,7 +240,7 @@ export const Confirm = styled(Button)` &:active { background-color: #cf3529; } -` +`; export const Cancel = styled(Button)` background-color: ${theme.colors.background}; @@ -250,7 +250,7 @@ export const Cancel = styled(Button)` &:active { background-color: #dedede; } -` +`; export const PromptActionsContainer = styled.div` padding-top: 1rem; diff --git a/src/components/CadenceEditor/ControlPanel/index.tsx b/src/components/CadenceEditor/ControlPanel/index.tsx index eb740506..88604112 100644 --- a/src/components/CadenceEditor/ControlPanel/index.tsx +++ b/src/components/CadenceEditor/ControlPanel/index.tsx @@ -37,7 +37,13 @@ import { // Component Scoped Files import { getLabel, validateByType, useTemplateType } from './utils'; import { ControlPanelProps, IValue } from './types'; -import { MotionBox, Confirm, Cancel, PromptActionsContainer, StatusIcon } from './components'; +import { + MotionBox, + Confirm, + Cancel, + PromptActionsContainer, + StatusIcon, +} from './components'; // Other import { @@ -354,9 +360,7 @@ const ControlPanel: React.FC = (props) => { let statusMessage; switch (true) { case isOk && showPrompt: - statusIcon = ( - - ); + statusIcon = ; statusMessage = 'Redeploying will clear the state of all accounts. Proceed?'; break; @@ -432,9 +436,17 @@ const ControlPanel: React.FC = (props) => { - + - + {statusIcon}

{statusMessage}

diff --git a/src/components/CadenceEditor/index.tsx b/src/components/CadenceEditor/index.tsx index 65895537..5c0d77ed 100644 --- a/src/components/CadenceEditor/index.tsx +++ b/src/components/CadenceEditor/index.tsx @@ -144,7 +144,12 @@ const CadenceEditor = (props: any) => { if (editor) { setupEditor(); } - }, [editor, project.active.index, project.active.type, project.project.accounts]); + }, [ + editor, + project.active.index, + project.active.type, + project.project.accounts, + ]); // "initEditor" will create new instance of Monaco Editor and set it up const initEditor = async () => { diff --git a/src/components/CadenceEditor/types.tsx b/src/components/CadenceEditor/types.tsx index 74105854..da851210 100644 --- a/src/components/CadenceEditor/types.tsx +++ b/src/components/CadenceEditor/types.tsx @@ -1 +1 @@ -export type EditorState = { model: any; viewState: any }; \ No newline at end of file +export type EditorState = { model: any; viewState: any }; diff --git a/src/components/CadenceVersion.tsx b/src/components/CadenceVersion.tsx index dfdcdc3a..9bd04c70 100644 --- a/src/components/CadenceVersion.tsx +++ b/src/components/CadenceVersion.tsx @@ -108,7 +108,7 @@ export const Version = () => { const lsStatus = languageServer ? 'ON' : 'OFF'; const lcStatus = languageClient ? 'ON' : 'OFF'; - const cadenceIsOutdated = false + const cadenceIsOutdated = false; return ( @@ -121,13 +121,12 @@ export const Version = () => { Cadence: {version} {cadenceIsOutdated ? : undefined} - {cadenceIsOutdated - ? - The playground is currently running an older version of Cadence and will - be updated shortly - - : undefined - } - + {cadenceIsOutdated ? ( + + The playground is currently running an older version of Cadence and + will be updated shortly + + ) : undefined} + ); }; diff --git a/src/components/Common.tsx b/src/components/Common.tsx index 92d91543..d8f64310 100644 --- a/src/components/Common.tsx +++ b/src/components/Common.tsx @@ -1,5 +1,5 @@ import styled from '@emotion/styled'; -import { motion } from "framer-motion"; +import { motion } from 'framer-motion'; interface FullScreenContainerProps { elevation?: number; @@ -43,7 +43,7 @@ export const PopupContainer = styled(motion.div)` padding: 20px; border-radius: 6px; background-color: white; - box-shadow: 0 3px 5px rgba(0, 0, 0, 0.1), 0 0 3px 1px rgba(0,0,0,0.05); + box-shadow: 0 3px 5px rgba(0, 0, 0, 0.1), 0 0 3px 1px rgba(0, 0, 0, 0.05); z-index: 2; box-sizing: border-box; `; @@ -60,12 +60,12 @@ export const PopupHeader = styled.h3` text-transform: uppercase; color: ${({ color = 'inherit' }) => color}; margin-bottom: ${({ mb = '0' }) => mb}; - :after{ - content: ""; + :after { + content: ''; display: block; height: 3px; width: 16px; - background-color: ${({lineColor = "currentColor"}) => lineColor}; + background-color: ${({ lineColor = 'currentColor' }) => lineColor}; margin-top: 4px; } `; diff --git a/src/components/DeploymentBottomBar.tsx b/src/components/DeploymentBottomBar.tsx index f41b1707..d4ad8baa 100644 --- a/src/components/DeploymentBottomBar.tsx +++ b/src/components/DeploymentBottomBar.tsx @@ -29,7 +29,9 @@ interface DeploymentBottomBarProps { setBottomBarHeight: (height: number) => void; } -const DeploymentBottomBar: React.FC = ({ setBottomBarHeight }) => { +const DeploymentBottomBar: React.FC = ({ + setBottomBarHeight, +}) => { const { x, y } = useMousePosition(); const [resultHeight, setResultHeight] = useState(140); diff --git a/src/components/EditorPanel/animation.tsx b/src/components/EditorPanel/animation.tsx index 813302c2..0f648f6d 100644 --- a/src/components/EditorPanel/animation.tsx +++ b/src/components/EditorPanel/animation.tsx @@ -1,43 +1,43 @@ export const animations = { editor: { default: { - height: "100%", + height: '100%', opacity: 1, transition: { delay: 0.3, - when: "afterChildren" - } + when: 'afterChildren', + }, }, saveTemplate: { opacity: 0, transition: { - when: "beforeChildren" - } - } + when: 'beforeChildren', + }, + }, }, contracts: { default: { opacity: 0, zIndex: -1, - paddingTop: "1rem", - marginTop: "-1rem", - paddingLeft: "1rem", - paddingRight: "1rem", + paddingTop: '1rem', + marginTop: '-1rem', + paddingLeft: '1rem', + paddingRight: '1rem', transition: { - when: "afterChildren", + when: 'afterChildren', staggerChildren: 0.03, - staggerDirection: -1 - } + staggerDirection: -1, + }, }, saveTemplate: { - height: "100%", + height: '100%', opacity: 1, zIndex: 2, transition: { - when: "beforeChildren", - staggerChildren: 0.1 - } - } + when: 'beforeChildren', + staggerChildren: 0.1, + }, + }, }, templateItem: { default: { @@ -45,15 +45,15 @@ export const animations = { y: 200, transition: { duration: 0.1, - ease: [1, 0.8, 0, 0] - } + ease: [1, 0.8, 0, 0], + }, }, saveTemplate: { opacity: 1, y: 0, transition: { - ease: [1, 0.5, 0, 0] - } - } - } + ease: [1, 0.5, 0, 0], + }, + }, + }, }; diff --git a/src/components/EditorPanel/components.tsx b/src/components/EditorPanel/components.tsx index dba7f32e..a93a4e39 100644 --- a/src/components/EditorPanel/components.tsx +++ b/src/components/EditorPanel/components.tsx @@ -1,8 +1,8 @@ -import React, { useState } from "react"; -import { Flex, Box, Text } from "theme-ui"; -import { motion, AnimatePresence } from "framer-motion"; -import styled from "@emotion/styled"; -import { IoIosArrowUp } from "react-icons/io"; +import React, { useState } from 'react'; +import { Flex, Box, Text } from 'theme-ui'; +import { motion, AnimatePresence } from 'framer-motion'; +import styled from '@emotion/styled'; +import { IoIosArrowUp } from 'react-icons/io'; export const SavedTemplateContainer = styled(motion.div)` position: absolute; @@ -38,8 +38,8 @@ export const Template = styled(motion.div)` props.isSelected ? props.theme.colors.primary : props.theme.colors.border}; - background: ${props => - props.isSelected ? "white" : props.theme.colors.border}; + background: ${(props) => + props.isSelected ? 'white' : props.theme.colors.border}; border-right: none; border-top-left-radius: 0.5rem; border-bottom-left-radius: 0.5rem; @@ -59,70 +59,70 @@ export const PanelContainer = styled(motion.div)` width: 100%; display: grid; grid-template-columns: 1fr 20fr; - grid-template-areas: "templates editor"; + grid-template-areas: 'templates editor'; `; export const PanelFooter: React.FC<{ dismiss: () => void }> = ({ children, - dismiss + dismiss, }) => { const [open, setOpen] = useState(false); return children ? ( setOpen(!open)} > {children && } {children} { + onClick={(e) => { e.preventDefault(); e.stopPropagation(); setOpen(false); @@ -133,10 +133,10 @@ export const PanelFooter: React.FC<{ dismiss: () => void }> = ({ Dismiss @@ -154,9 +154,9 @@ export const EditorHeader: React.FC = ({ children }) => { pr={2} pt={0} sx={{ - alignItems: "center", - justifyContent: "flex-end", - width: "100%" + alignItems: 'center', + justifyContent: 'flex-end', + width: '100%', }} > {children} @@ -169,7 +169,7 @@ export const EditorPanelMenu: React.FC = ({ children }) => { {children} diff --git a/src/components/EditorPanel/index.tsx b/src/components/EditorPanel/index.tsx index de09d107..229faf91 100644 --- a/src/components/EditorPanel/index.tsx +++ b/src/components/EditorPanel/index.tsx @@ -1,5 +1,5 @@ -import React from "react"; -import { Flex } from "theme-ui"; +import React from 'react'; +import { Flex } from 'theme-ui'; import { TemplatesContainer, @@ -7,13 +7,13 @@ import { PanelContainer, PanelFooter, EditorHeader, - EditorPanelMenu -} from "./components"; + EditorPanelMenu, +} from './components'; const EditorPanel: React.FC = ({ children }) => { return ( {children} @@ -28,5 +28,5 @@ export { PanelContainer, PanelFooter, EditorHeader, - EditorPanelMenu + EditorPanelMenu, }; diff --git a/src/components/Examples.tsx b/src/components/Examples.tsx index 797b7083..43061a25 100644 --- a/src/components/Examples.tsx +++ b/src/components/Examples.tsx @@ -1,11 +1,11 @@ -import React from "react"; -import { Text } from "theme-ui"; -import styled from "@emotion/styled"; -import { motion } from "framer-motion"; -import { IoMdClose } from "react-icons/io"; -import { WhiteOverlay } from "components/Common"; +import React from 'react'; +import { Text } from 'theme-ui'; +import styled from '@emotion/styled'; +import { motion } from 'framer-motion'; +import { IoMdClose } from 'react-icons/io'; +import { WhiteOverlay } from 'components/Common'; -import Mixpanel from "util/mixpanel"; +import Mixpanel from 'util/mixpanel'; import ActionButton from 'components/ActionButton'; const examples = [ @@ -99,7 +99,7 @@ const Header = styled.div` align-items: center; justify-content: space-between; margin-bottom: 1rem; - + & h3 { font-size: 1.5rem; } @@ -113,10 +113,10 @@ const ExampleContainer = styled.div` display: grid; grid-template-columns: repeat(4, minmax(100px, 320px)); grid-gap: 1rem; - a, .full-height{ + a, + .full-height { height: 100%; } - `; const Buttons = styled.div` @@ -124,14 +124,13 @@ const Buttons = styled.div` grid-template-columns: repeat(2, 1fr); grid-gap: 10px; width: 100%; - + align-items: flex-start; - - button{ + + button { width: 100%; } -` - +`; const Example = styled.div` display: grid; @@ -186,22 +185,22 @@ const Examples: React.FC<{ }> = ({ visible, triggerClose }) => { const ExampleContainers = { visible: { - display: "flex", + display: 'flex', opacity: 1, transition: { - staggerChildren: 0.1 + staggerChildren: 0.1, }, - zIndex: 99 + zIndex: 99, }, hidden: { opacity: 0, transition: { - when: "afterChildren", + when: 'afterChildren', staggerChildren: 0.1, - staggerDirection: -1 + staggerDirection: -1, }, - zIndex: -1 - } + zIndex: -1, + }, }; const exampleItem = { @@ -209,22 +208,22 @@ const Examples: React.FC<{ opacity: 1, x: 0, transition: { - ease: [1, 0.5, 0, 0] - } + ease: [1, 0.5, 0, 0], + }, }, hidden: { opacity: 0, x: 200, transition: { - ease: [1, 0.5, 0, 0] - } - } + ease: [1, 0.5, 0, 0], + }, + }, }; return ( @@ -236,45 +235,49 @@ const Examples: React.FC<{ {examples.map((_example: any, index: number) => { return ( - - - {_example.emoji} - {_example.title} - {_example.subtitle} - - { - Mixpanel.track("Redirect to project documentation", { - link: _example.docsLink, - title: _example.title - }); - }} - > - Read More - - {_example.projectLink && + + + {_example.emoji} + {_example.title} + {_example.subtitle} + + { + Mixpanel.track('Redirect to project documentation', { + link: _example.docsLink, + title: _example.title, + }); + }} + > + Read More + + {_example.projectLink && ( { - Mixpanel.track("Open example project", { + Mixpanel.track('Open example project', { link: _example.projectLink, - title: _example.title + title: _example.title, }); }} > Open Project - } - - - + )} + + + ); })} diff --git a/src/components/ExportButton.tsx b/src/components/ExportButton.tsx index f88b5fa8..d27fe6b9 100644 --- a/src/components/ExportButton.tsx +++ b/src/components/ExportButton.tsx @@ -4,7 +4,7 @@ import { FaClipboard, FaClipboardCheck } from 'react-icons/fa'; import { SidebarItemExport } from 'layout/SidebarItemExport'; import { useProject } from 'providers/Project/projectHooks'; import { generateCode } from '../util/generate-code'; -import { LOCAL_PROJECT_ID } from '../util/url' +import { LOCAL_PROJECT_ID } from '../util/url'; type ExportButtonProps = { id: string; diff --git a/src/components/ExportPopup.tsx b/src/components/ExportPopup.tsx index 94e38ce4..8be9c2db 100644 --- a/src/components/ExportPopup.tsx +++ b/src/components/ExportPopup.tsx @@ -69,7 +69,7 @@ const ExportPopup: React.FC<{ opacity: 0, y: -200, transition: { - ease: [1, 0.5, 0, 0] + ease: [1, 0.5, 0, 0], }, }, }; @@ -90,7 +90,7 @@ const ExportPopup: React.FC<{ setFolderName(event.target.value)} + onChange={(event) => setFolderName(event.target.value)} /> {processing ? ( diff --git a/src/components/Icons.tsx b/src/components/Icons.tsx index e783551d..1c211b2e 100644 --- a/src/components/Icons.tsx +++ b/src/components/Icons.tsx @@ -1,50 +1,88 @@ -import React from 'react' -import styled from 'styled-components' +import React from 'react'; +import styled from 'styled-components'; interface IconSVGProps { - size?: string, - title?: string + size?: string; + title?: string; } const IconSVG = styled.svg` width: ${(props) => props.size || '1em'}; height: auto; -` +`; const Cadence = styled(IconSVG)` .withGradient { fill: currentColor; } - &:hover{ - .withGradient{ + &:hover { + .withGradient { fill: url(#cadence-gradient); } } `; export const IconCadence = (props: IconSVGProps) => { - const { title, size } = props - return( - + const { title, size } = props; + return ( + {title && {title}} - - - - + + + + - + - - - - - - + + + + + + - ) -} + ); +}; diff --git a/src/components/Markdown.tsx b/src/components/Markdown.tsx index cf25c807..976f68ac 100644 --- a/src/components/Markdown.tsx +++ b/src/components/Markdown.tsx @@ -1,16 +1,9 @@ import React from 'react'; -import MarkdownPreview from "markdown-to-jsx"; -import "unreset-css/dist/unreset.min.css"; // restore browser default element styles +import MarkdownPreview from 'markdown-to-jsx'; +import 'unreset-css/dist/unreset.min.css'; // restore browser default element styles export const Markdown: React.FC<{ content: string; }> = ({ content }) => { - - return ( - - {content} - - ) -} + return {content}; +}; diff --git a/src/components/MdeEditor.tsx b/src/components/MdeEditor.tsx index 546045c2..1788aa48 100644 --- a/src/components/MdeEditor.tsx +++ b/src/components/MdeEditor.tsx @@ -1,22 +1,21 @@ import React from 'react'; -import SimpleMDE from "react-simplemde-editor"; -import "easymde/dist/easymde.min.css"; -import "unreset-css/dist/unreset.min.css"; // restore browser default element styles -import "../styles/markdown.css" +import SimpleMDE from 'react-simplemde-editor'; +import 'easymde/dist/easymde.min.css'; +import 'unreset-css/dist/unreset.min.css'; // restore browser default element styles +import '../styles/markdown.css'; export const MdeEditor: React.FC<{ value: string; onChange: (v: string) => void; - overflow: boolean + overflow: boolean; }> = ({ value, onChange, overflow }) => { - - const className = overflow ? "unreset ease-md-red-border" : "unreset" + const className = overflow ? 'unreset ease-md-red-border' : 'unreset'; return ( onChange(v)} + onChange={(v) => onChange(v)} /> - ) -} + ); +}; diff --git a/src/components/MenuList.tsx b/src/components/MenuList.tsx index 2c4f7889..d8f20384 100644 --- a/src/components/MenuList.tsx +++ b/src/components/MenuList.tsx @@ -1,20 +1,20 @@ -import React, {SyntheticEvent, useEffect, useRef, useState} from "react"; -import {IoMdAddCircleOutline} from "react-icons/io"; -import {FaPen, FaTimes} from "react-icons/fa"; -import {SidebarSection} from "layout/SidebarSection"; -import {SidebarHeader} from "layout/SidebarHeader"; -import {SidebarItems} from "layout/SidebarItems"; -import {SidebarItem} from "layout/SidebarItem"; -import {SidebarItemInsert} from "layout/SidebarItemInsert"; -import {SidebarItemInput} from "layout/SidebarItemInput"; -import {SidebarItemEdit} from "layout/SidebarItemEdit"; -import {SidebarItemDelete} from "layout/SidebarItemDelete"; -import useKeyPress from "../hooks/useKeyPress"; -import { ExportButton } from "components/ExportButton"; -import { getParams } from "util/url"; -import { useProject } from "providers/Project/projectHooks"; -import { EntityType } from "providers/Project"; -import { useLocation } from "@reach/router"; +import React, { SyntheticEvent, useEffect, useRef, useState } from 'react'; +import { IoMdAddCircleOutline } from 'react-icons/io'; +import { FaPen, FaTimes } from 'react-icons/fa'; +import { SidebarSection } from 'layout/SidebarSection'; +import { SidebarHeader } from 'layout/SidebarHeader'; +import { SidebarItems } from 'layout/SidebarItems'; +import { SidebarItem } from 'layout/SidebarItem'; +import { SidebarItemInsert } from 'layout/SidebarItemInsert'; +import { SidebarItemInput } from 'layout/SidebarItemInput'; +import { SidebarItemEdit } from 'layout/SidebarItemEdit'; +import { SidebarItemDelete } from 'layout/SidebarItemDelete'; +import useKeyPress from '../hooks/useKeyPress'; +import { ExportButton } from 'components/ExportButton'; +import { getParams } from 'util/url'; +import { useProject } from 'providers/Project/projectHooks'; +import { EntityType } from 'providers/Project'; +import { useLocation } from '@reach/router'; type MenuListProps = { active: number | null; @@ -34,13 +34,13 @@ const MenuList: React.FC = ({ onSelect, onUpdate, onInsert, - onDelete + onDelete, }) => { - const { active } = useProject() + const { active } = useProject(); const isEditing = useRef(); const [editing, setEditing] = useState([]); - const enterPressed = useKeyPress("Enter"); - const escapePressed = useKeyPress("Escape"); + const enterPressed = useKeyPress('Enter'); + const escapePressed = useKeyPress('Escape'); const toggleEditing = (i: number, newTitle: string) => { if (editing.includes(i)) { @@ -53,7 +53,6 @@ const MenuList: React.FC = ({ return setEditing([...editing, i]); }; - useEffect(() => { setEditing([]); }, [items, active]); @@ -68,14 +67,16 @@ const MenuList: React.FC = ({ const setEditingRef = (element: HTMLInputElement | undefined) => { isEditing.current = element; element?.focus(); - element?.select() + element?.select(); }; - const isScript = title.toLowerCase().includes("script"); - const itemType = isScript ? EntityType.ScriptTemplate : EntityType.TransactionTemplate + const isScript = title.toLowerCase().includes('script'); + const itemType = isScript + ? EntityType.ScriptTemplate + : EntityType.TransactionTemplate; const location = useLocation(); - const params = getParams(location.search) + const params = getParams(location.search); return ( @@ -89,7 +90,7 @@ const MenuList: React.FC = ({ {items.map((item, i) => { - const isActive = active.type === itemType && item.id === params.id + const isActive = active.type === itemType && item.id === params.id; return ( = ({ }} defaultValue={item.title} readonly={!editing.includes(i)} - onChange={e => { + onChange={(e) => { if (e.target.value.length > NAME_MAX_CHARS) { isEditing.current.value = e.target.value.substr( 0, - NAME_MAX_CHARS - 1 + NAME_MAX_CHARS - 1, ); } }} @@ -127,7 +128,7 @@ const MenuList: React.FC = ({ - + )} @@ -136,7 +137,8 @@ const MenuList: React.FC = ({ onClick={(e: any) => { e.stopPropagation(); onDelete(item.id); - }}> + }} + > )} diff --git a/src/components/ProjectInfo.tsx b/src/components/ProjectInfo.tsx index 332ae572..90c2c1e8 100644 --- a/src/components/ProjectInfo.tsx +++ b/src/components/ProjectInfo.tsx @@ -1,35 +1,32 @@ -import React from "react"; -import {navigate} from "@reach/router" -import {SidebarSection as Root} from "layout/SidebarSection"; -import {SidebarItems as Items} from "layout/SidebarItems"; -import {ProjectItem as Item} from "layout/ProjectItem"; -import {useProject} from "providers/Project/projectHooks"; -import {isUUUID, LOCAL_PROJECT_ID} from "util/url"; -import { EntityType } from "providers/Project"; -import { HiOutlineDocumentReport } from "react-icons/hi"; -import { Text, Box } from "@theme-ui/components"; +import React from 'react'; +import { navigate } from '@reach/router'; +import { SidebarSection as Root } from 'layout/SidebarSection'; +import { SidebarItems as Items } from 'layout/SidebarItems'; +import { ProjectItem as Item } from 'layout/ProjectItem'; +import { useProject } from 'providers/Project/projectHooks'; +import { isUUUID, LOCAL_PROJECT_ID } from 'util/url'; +import { EntityType } from 'providers/Project'; +import { HiOutlineDocumentReport } from 'react-icons/hi'; +import { Text, Box } from '@theme-ui/components'; const ProjectInfo: React.FC = () => { - const { - project, - active - } = useProject(); + const { project, active } = useProject(); - const projectPath = isUUUID(project.id) ? project.id : LOCAL_PROJECT_ID + const projectPath = isUUUID(project.id) ? project.id : LOCAL_PROJECT_ID; return ( { - navigate(`/${projectPath}`) + navigate(`/${projectPath}`); }} > - - + + - Project + Project diff --git a/src/components/RenderResponse/Line/index.tsx b/src/components/RenderResponse/Line/index.tsx index 364aab32..904ef092 100644 --- a/src/components/RenderResponse/Line/index.tsx +++ b/src/components/RenderResponse/Line/index.tsx @@ -1,25 +1,22 @@ -import React from "react"; -import { IoIosArrowForward } from "react-icons/io"; -import { - Line as LineType, - Tag -} from "util/normalize-interaction-response"; -import styled from "@emotion/styled"; -import { css } from "@emotion/core"; -import theme from "../../../theme"; +import React from 'react'; +import { IoIosArrowForward } from 'react-icons/io'; +import { Line as LineType, Tag } from 'util/normalize-interaction-response'; +import styled from '@emotion/styled'; +import { css } from '@emotion/core'; +import theme from '../../../theme'; const PS1 = (tag: Tag) => { switch (tag) { case Tag.ERROR: - return "Error"; + return 'Error'; case Tag.VALUE: - return "Result"; + return 'Result'; case Tag.UNKNOWN: - return "Unknown"; + return 'Unknown'; case Tag.LOG: - return ""; + return ''; default: - return ""; + return ''; } }; @@ -39,35 +36,35 @@ const Root = styled.div` const Label = styled.strong<{ tag: Tag }>` margin-right: var(--gap); - font-weight:bold; + font-weight: bold; &:before { counter-increment: lines; - content: "[" counter(lines) "]"; + content: '[' counter(lines) ']'; margin-right: var(--gap); color: ${theme.colors.text}; } &:empty { - margin-right:0; + margin-right: 0; } & + svg { margin-right: var(--gap); - margin-left:-3px; + margin-left: -3px; } - ${p => + ${(p) => p.tag === Tag.ERROR && css` color: ${theme.colors.error}; `} - ${p => + ${(p) => p.tag === Tag.VALUE && css` color: ${theme.colors.purple}; `} - ${p => + ${(p) => p.tag === Tag.UNKNOWN && css` color: ${theme.colors.error}; @@ -75,7 +72,7 @@ const Label = styled.strong<{ tag: Tag }>` `; const StringValue = styled.pre<{ tag: Tag }>` - ${p => + ${(p) => p.tag === Tag.ERROR && css` color: ${theme.colors.error}; @@ -95,15 +92,15 @@ export const Line: React.FC = ({ timestamp, tag, value, label }) => { return ( {timestamp}  - {label && {label} } + {label && {label} } - { - typeof value === "string" - ? {value} - : {JSON.stringify(value, null, 2)} - } + {typeof value === 'string' ? ( + {value} + ) : ( + {JSON.stringify(value, null, 2)} + )} ); }; diff --git a/src/components/RenderResponse/index.tsx b/src/components/RenderResponse/index.tsx index 14697c1d..7c083074 100644 --- a/src/components/RenderResponse/index.tsx +++ b/src/components/RenderResponse/index.tsx @@ -1,11 +1,11 @@ -import React from "react"; -import { useQuery } from "@apollo/react-hooks"; -import { GET_CACHED_EXECUTION_RESULTS } from "api/apollo/queries"; -import { ResultType } from "api/apollo/generated/graphql"; -import { Line as LineType } from "util/normalize-interaction-response"; +import React from 'react'; +import { useQuery } from '@apollo/react-hooks'; +import { GET_CACHED_EXECUTION_RESULTS } from 'api/apollo/queries'; +import { ResultType } from 'api/apollo/generated/graphql'; +import { Line as LineType } from 'util/normalize-interaction-response'; -import { Line } from "components/RenderResponse/Line"; -import styled from "@emotion/styled"; +import { Line } from 'components/RenderResponse/Line'; +import styled from '@emotion/styled'; const Root = styled.div<{ resultType: ResultType }>` counter-reset: lines; @@ -17,16 +17,14 @@ const Root = styled.div<{ resultType: ResultType }>` export const RenderResponse: React.FC<{ resultType: ResultType.Transaction | ResultType.Script | ResultType.Contract; }> = ({ resultType }) => { - const { data, error, loading } = useQuery( - GET_CACHED_EXECUTION_RESULTS - ); + const { data, error, loading } = useQuery(GET_CACHED_EXECUTION_RESULTS); return ( {!loading && !error && - data.cachedExecutionResults[resultType].map((line: LineType, n: number) => ( - - ))} + data.cachedExecutionResults[ + resultType + ].map((line: LineType, n: number) => )} ); }; diff --git a/src/components/ResourcesBar.tsx b/src/components/ResourcesBar.tsx index 495616ce..65d24a03 100644 --- a/src/components/ResourcesBar.tsx +++ b/src/components/ResourcesBar.tsx @@ -1,10 +1,10 @@ import React, { useState, useEffect } from 'react'; import { Badge, Flex, Box, Divider } from 'theme-ui'; import { GoChevronDown, GoChevronUp } from 'react-icons/go'; -import { IoMdAddCircleOutline } from "react-icons/io"; +import { IoMdAddCircleOutline } from 'react-icons/io'; import { useProject } from 'providers/Project/projectHooks'; import useMousePosition from '../hooks/useMousePosition'; -import TemplatePopup from "components/TemplatePopup"; +import TemplatePopup from 'components/TemplatePopup'; import { Feedback as FeedbackRoot } from 'layout/Feedback'; import { FeedbackActions } from 'layout/FeedbackActions'; import { SidebarItemInsert } from 'layout/SidebarItemInsert'; @@ -58,27 +58,24 @@ interface StorageBadgeProps { type: string; } -const StorageBadge: React.FC = ({ - type -}) => { - +const StorageBadge: React.FC = ({ type }) => { return ( { switch (type) { - case "Struct": + case 'Struct': return theme.colors.badgeStruct; - case "Resource": + case 'Resource': return theme.colors.badgeResource; - case "Link": + case 'Link': return theme.colors.badgeCapability; case null: return theme.colors.badgeNull; @@ -86,8 +83,8 @@ const StorageBadge: React.FC = ({ }, }} > - {type === "Link" ? "Capability" : type} - {type === null && "null"} + {type === 'Link' ? 'Capability' : type} + {type === null && 'null'} ); }; @@ -107,18 +104,14 @@ const IdentifierTypeList: React.FC = ({ controls, resize, }) => { - const [showTemplatePopup, toggleShowTemplatePopup] = useState(false); const { selectedResourceAccount } = useProject(); - + return ( <> - + ACCOUNT {selectedResourceAccount} STORAGE {controls()}
= ({
    {Object.keys(types).map((key) => { const identifierType = types[key]; - return( + return ( = ({ > {key} - + - {identifierType == "Link" && - { - toggleShowTemplatePopup(true) - }}> + {identifierType == 'Link' && ( + { + toggleShowTemplatePopup(true); + }} + > - } + )} - ) + ); })}
- { - toggleShowTemplatePopup(false) + toggleShowTemplatePopup(false); }} /> ); }; -const StateContainer: React.FC<{ - value?: any - path?: any +const StateContainer: React.FC<{ + value?: any; + path?: any; }> = ({ value, path }) => (
- {value ? + {value ? ( <> - + Path: {path} - - + Object:
{JSON.stringify(value, null, 2)}
- : + ) : ( '(account storage is empty)' - } + )}
); @@ -256,11 +243,10 @@ const AccountState: React.FC<{ renderDeployButton: () => JSX.Element; resultHeight: number; }> = ({ state, selectedResourcesAccount, resultHeight }) => { - const { storage, paths, types } = getStorageData(state); const identifiers = Object.keys(storage); - + // @ts-ignore const [selected, setSelected] = useState( identifiers.length > 0 ? identifiers[0] : null, @@ -298,37 +284,37 @@ const AccountState: React.FC<{ return ( <> {selectedResourcesAccount !== 'none' && ( - - toggleResizingStorage(true)} - controls={() => { - return ( - - {storageHeight > 40 ? ( - setStorageHeight(40)} - /> - ) : ( - - setStorageHeight(STORAGE_PANEL_MIN_HEIGHT * 2) - } - /> - )} - - ); - }} - /> - - + + toggleResizingStorage(true)} + controls={() => { + return ( + + {storageHeight > 40 ? ( + setStorageHeight(40)} + /> + ) : ( + + setStorageHeight(STORAGE_PANEL_MIN_HEIGHT * 2) + } + /> + )} + + ); + }} + /> + + )} ); @@ -346,14 +332,18 @@ const ResourcesBar: React.FC = ({ resultHeight }) => { {isLoading ? (

Loading...

) : ( - selectedResourceAccount && { - return ; - }} - resultHeight={resultHeight} - /> + selectedResourceAccount && ( + { + return ; + }} + resultHeight={resultHeight} + /> + ) )} ); diff --git a/src/components/ResourcesExplorerButton.tsx b/src/components/ResourcesExplorerButton.tsx index 6435ffba..b8cecb97 100644 --- a/src/components/ResourcesExplorerButton.tsx +++ b/src/components/ResourcesExplorerButton.tsx @@ -1,15 +1,17 @@ import React from 'react'; -import {navigate, useLocation} from "@reach/router"; +import { navigate, useLocation } from '@reach/router'; import { FaDatabase } from 'react-icons/fa'; import { SidebarItemToggleResources } from 'layout/SidebarItemToggleResources'; import { useProject } from 'providers/Project/projectHooks'; -import { isUUUID, getParams, LOCAL_PROJECT_ID } from "util/url"; +import { isUUUID, getParams, LOCAL_PROJECT_ID } from 'util/url'; type ResourcesExplorerButtonProps = { address: string; }; -export const ResourcesExplorerButton = (props: ResourcesExplorerButtonProps) => { +export const ResourcesExplorerButton = ( + props: ResourcesExplorerButtonProps, +) => { const { project, setSelectedResourceAccount } = useProject(); const { address } = props; @@ -17,15 +19,16 @@ export const ResourcesExplorerButton = (props: ResourcesExplorerButtonProps) => const location = useLocation(); const params = getParams(location.search); - const { type, id, storage } = params; + const { type, id, storage } = params; - let queryParams = type ? `&type=${type}`: ""; - queryParams += id ? `&id=${id}`: ""; - if (storage){ - queryParams += storage === address ? "&storage=none" : `&storage=${address}`; - } + let queryParams = type ? `&type=${type}` : ''; + queryParams += id ? `&id=${id}` : ''; + if (storage) { + queryParams += + storage === address ? '&storage=none' : `&storage=${address}`; + } - queryParams = queryParams.replace("&","?") + queryParams = queryParams.replace('&', '?'); return ( void; } -const ScriptBottomBar: React.FC = ({ setBottomBarHeight }) => { +const ScriptBottomBar: React.FC = ({ + setBottomBarHeight, +}) => { const { x, y } = useMousePosition(); const [resultHeight, setResultHeight] = useState(140); diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index b287525f..485e1ff3 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -1,13 +1,13 @@ -import React from "react"; -import { EntityType } from "providers/Project"; -import AccountList from "components/AccountList"; -import ProjectInfo from "components/ProjectInfo"; -import MenuList from "components/MenuList"; -import { Sidebar as SidebarRoot } from "layout/Sidebar"; +import React from 'react'; +import { EntityType } from 'providers/Project'; +import AccountList from 'components/AccountList'; +import ProjectInfo from 'components/ProjectInfo'; +import MenuList from 'components/MenuList'; +import { Sidebar as SidebarRoot } from 'layout/Sidebar'; -import { useProject } from "providers/Project/projectHooks"; -import { navigate } from "@reach/router"; -import { isUUUID, LOCAL_PROJECT_ID } from "../util/url"; +import { useProject } from 'providers/Project/projectHooks'; +import { navigate } from '@reach/router'; +import { isUUUID, LOCAL_PROJECT_ID } from '../util/url'; const Sidebar: React.FC = () => { const { @@ -19,14 +19,14 @@ const Sidebar: React.FC = () => { deleteScriptTemplate, updateTransactionTemplate, updateScriptTemplate, - selectedResourceAccount + selectedResourceAccount, } = useProject(); if (isLoading) return

Loading...

; - const projectPath = isUUUID(project.id) ? project.id : LOCAL_PROJECT_ID + const projectPath = isUUUID(project.id) ? project.id : LOCAL_PROJECT_ID; - const storageAcct = selectedResourceAccount || 'none' + const storageAcct = selectedResourceAccount || 'none'; return ( @@ -39,7 +39,7 @@ const Sidebar: React.FC = () => { active.type == EntityType.TransactionTemplate ? active.index : null } onSelect={(_, id) => { - navigate(`/${projectPath}?type=tx&id=${id}&storage=${storageAcct}`) + navigate(`/${projectPath}?type=tx&id=${id}&storage=${storageAcct}`); }} onUpdate={(templateId: string, script: string, title: string) => { updateTransactionTemplate(templateId, script, title); @@ -47,11 +47,16 @@ const Sidebar: React.FC = () => { onDelete={async (templateId: string) => { await deleteTransactionTemplate(templateId); const id = project.transactionTemplates[0].id; - navigate(`/${projectPath}?type=tx&id=${id}&storage=${storageAcct}`) + navigate(`/${projectPath}?type=tx&id=${id}&storage=${storageAcct}`); }} onInsert={async () => { - const res = await mutator.createTransactionTemplate("", `New Transaction`) - navigate(`/${projectPath}?type=tx&id=${res.data?.createTransactionTemplate?.id}&storage=${storageAcct}`) + const res = await mutator.createTransactionTemplate( + '', + `New Transaction`, + ); + navigate( + `/${projectPath}?type=tx&id=${res.data?.createTransactionTemplate?.id}&storage=${storageAcct}`, + ); }} /> { items={project.scriptTemplates} active={active.type == EntityType.ScriptTemplate ? active.index : null} onSelect={(_, id) => { - navigate(`/${projectPath}?type=script&id=${id}&storage=${storageAcct}`) + navigate( + `/${projectPath}?type=script&id=${id}&storage=${storageAcct}`, + ); }} onUpdate={(templateId: string, script: string, title: string) => { updateScriptTemplate(templateId, script, title); @@ -67,11 +74,15 @@ const Sidebar: React.FC = () => { onDelete={async (templateId: string) => { await deleteScriptTemplate(templateId); const id = project.scriptTemplates[0].id; - navigate(`/${projectPath}?type=script&id=${id}&storage=${storageAcct}`) + navigate( + `/${projectPath}?type=script&id=${id}&storage=${storageAcct}`, + ); }} onInsert={async () => { - const res = await mutator.createScriptTemplate("", `New Script`); - navigate(`/${projectPath}?type=script&id=${res.data?.createScriptTemplate?.id}&storage=${storageAcct}`) + const res = await mutator.createScriptTemplate('', `New Script`); + navigate( + `/${projectPath}?type=script&id=${res.data?.createScriptTemplate?.id}&storage=${storageAcct}`, + ); }} /> diff --git a/src/components/Spinner.tsx b/src/components/Spinner.tsx index 6abe966e..676c5c1e 100644 --- a/src/components/Spinner.tsx +++ b/src/components/Spinner.tsx @@ -1,21 +1,21 @@ -import React from "react"; -import { FaCircleNotch } from "react-icons/fa"; -import { motion } from "framer-motion"; +import React from 'react'; +import { FaCircleNotch } from 'react-icons/fa'; +import { motion } from 'framer-motion'; const Spinner: React.FC = () => { return ( - - + ); }; diff --git a/src/components/TemplatePopup.tsx b/src/components/TemplatePopup.tsx index a78b4b48..640ec1be 100644 --- a/src/components/TemplatePopup.tsx +++ b/src/components/TemplatePopup.tsx @@ -1,12 +1,12 @@ import React, { useState, useRef, useEffect } from 'react'; -import { navigate } from "@reach/router"; +import { navigate } from '@reach/router'; import { default as FlowButton } from 'components/Button'; import theme from '../theme'; import { Select, Spinner } from '@theme-ui/components'; import { useProject } from 'providers/Project/projectHooks'; -import { isUUUID } from "util/url"; +import { isUUUID } from 'util/url'; import { getInterpolatedTemplate } from 'util/templates'; -import { getStorageData } from "util/storage"; +import { getStorageData } from 'util/storage'; import { storageMap } from 'util/accounts'; import { @@ -27,26 +27,30 @@ const TemplatePopup: React.FC<{ visible: boolean; triggerClose?: (e: React.SyntheticEvent) => any; }> = ({ visible, triggerClose }) => { - const { project, mutator, selectedResourceAccount } = useProject(); - const selectedAcctState = project.accounts[storageMap[selectedResourceAccount] || 0].state; + const selectedAcctState = + project.accounts[storageMap[selectedResourceAccount] || 0].state; const { types, capabilities } = getStorageData(selectedAcctState); - + const capabilitiesKeys = Object.keys(capabilities || []); const [processing, setProcessing] = useState(false); - const [templateName, setTemplateName] = useState("My amazing script or transaction"); - const [templateType, setTemplateType] = useState("Script"); + const [templateName, setTemplateName] = useState( + 'My amazing script or transaction', + ); + const [templateType, setTemplateType] = useState('Script'); - const [selectedCapability, setSelectedCapability] = useState< string | null >(capabilitiesKeys[0] || null); + const [selectedCapability, setSelectedCapability] = useState( + capabilitiesKeys[0] || null, + ); - const projectPath = isUUUID(project.id) ? project.id : "local"; + const projectPath = isUUUID(project.id) ? project.id : 'local'; const firstInput = useRef(null!); - const storageAcct = selectedResourceAccount || 'none' + const storageAcct = selectedResourceAccount || 'none'; useEffect(() => { firstInput.current.focus(); @@ -88,7 +92,7 @@ const TemplatePopup: React.FC<{ opacity: 0, y: 200, transition: { - ease: [1, 0.5, 0, 0] + ease: [1, 0.5, 0, 0], }, }, }; @@ -99,31 +103,34 @@ const TemplatePopup: React.FC<{ initial="hidden" animate={visible ? 'visible' : 'hidden'} variants={containerFrames} - onAnimationComplete={() => {setProcessing(false)}} + onAnimationComplete={() => { + setProcessing(false); + }} > - - + + {`Create a ${templateType} from a template`} { - setSelectedCapability(event.target.value) + setSelectedCapability(event.target.value); }} defaultValue={capabilitiesKeys[0]} sx={{ - border: "1px solid #C4C4C4", - fontSize: "14px", - color: "#000", - padding: "8px", - width: "100%", - fontWeight: "bold", - marginBottom: "5px", - borderRadius: "2px" + border: '1px solid #C4C4C4', + fontSize: '14px', + color: '#000', + padding: '8px', + width: '100%', + fontWeight: 'bold', + marginBottom: '5px', + borderRadius: '2px', }} > - {capabilitiesKeys.map((capabilityKey) => - types[capabilityKey] === "Link" && - + {capabilitiesKeys.map( + (capabilityKey) => + types[capabilityKey] === 'Link' && ( + + ), )} @@ -164,54 +170,54 @@ const TemplatePopup: React.FC<{ setTemplateName(event.target.value)} + onChange={(event) => setTemplateName(event.target.value)} /> Close - { - setProcessing(true); - const capData = capabilities[selectedCapability]; - - if (templateType=== "Transaction") { - const res = await mutator.createTransactionTemplate( - getInterpolatedTemplate( - "tx", - capData.contractAddr, - capData.path, - `${capData.resourceContract}.${capData.resource}`, - capData.contractImplementedInterfaces.join(",") - ), - templateName - ) - navigate(`/${projectPath}?type=tx&id=${res.data?.createTransactionTemplate?.id}&storage=${storageAcct}`) - } else if (templateType === "Script") { - const res = await mutator.createScriptTemplate( - getInterpolatedTemplate( - "script", - capData.contractAddr, - capData.path, - `${capData.resourceContract}.${capData.resource}`, - capData.contractImplementedInterfaces.join(",") - ), - templateName - ) - navigate(`/${projectPath}?type=script&id=${res.data?.createScriptTemplate?.id}&storage=${storageAcct}`) - } - - triggerClose(null); - }} - > - {processing ? - - : - "Create" + { + setProcessing(true); + const capData = capabilities[selectedCapability]; + + if (templateType === 'Transaction') { + const res = await mutator.createTransactionTemplate( + getInterpolatedTemplate( + 'tx', + capData.contractAddr, + capData.path, + `${capData.resourceContract}.${capData.resource}`, + capData.contractImplementedInterfaces.join(','), + ), + templateName, + ); + navigate( + `/${projectPath}?type=tx&id=${res.data?.createTransactionTemplate?.id}&storage=${storageAcct}`, + ); + } else if (templateType === 'Script') { + const res = await mutator.createScriptTemplate( + getInterpolatedTemplate( + 'script', + capData.contractAddr, + capData.path, + `${capData.resourceContract}.${capData.resource}`, + capData.contractImplementedInterfaces.join(','), + ), + templateName, + ); + navigate( + `/${projectPath}?type=script&id=${res.data?.createScriptTemplate?.id}&storage=${storageAcct}`, + ); } - + + triggerClose(null); + }} + > + {processing ? : 'Create'} + diff --git a/src/components/TransactionBottomBar.tsx b/src/components/TransactionBottomBar.tsx index 6ea49f1b..e21865d1 100644 --- a/src/components/TransactionBottomBar.tsx +++ b/src/components/TransactionBottomBar.tsx @@ -66,7 +66,9 @@ interface TransactionBottomBarProps { setBottomBarHeight: (height: number) => void; } -const TransactionBottomBar: React.FC = ({ setBottomBarHeight }) => { +const TransactionBottomBar: React.FC = ({ + setBottomBarHeight, +}) => { const { x, y } = useMousePosition(); const [resultHeight, setResultHeight] = useState(140); diff --git a/src/containers/AppMobileWrapper.tsx b/src/containers/AppMobileWrapper.tsx index 63834039..16a6ac58 100644 --- a/src/containers/AppMobileWrapper.tsx +++ b/src/containers/AppMobileWrapper.tsx @@ -1,65 +1,67 @@ -import React from "react"; -import styled from "@emotion/styled"; -import { Text, Box, Button } from "theme-ui"; +import React from 'react'; +import styled from '@emotion/styled'; +import { Text, Box, Button } from 'theme-ui'; const AppMobileWrapperDiv = styled.div` - display: block; - position: relative; - @media only screen and (max-width: 1080px) { - display: none; - } + display: block; + position: relative; + @media only screen and (max-width: 1080px) { + display: none; + } `; const AppMobileWrapperMessageDiv = styled.div` - display: flex; - padding: 2rem; - height: 100vh; - width: 100%; - flex-direction: column; - justify-content: center; - align-items: center; - text-align: center; + display: flex; + padding: 2rem; + height: 100vh; + width: 100%; + flex-direction: column; + justify-content: center; + align-items: center; + text-align: center; - @media only screen and (min-width: 1080px) { - display: none; - } + @media only screen and (min-width: 1080px) { + display: none; + } `; interface AppMobileWrapperProps { - children: any; + children: any; } -const AppMobileWrapper: React.FC = ({children}) => { - return ( - <> - - {children} - - - - Flow Logo - - - The Flow Playground is best used on larger screens. - - - - - - - ) -} +const AppMobileWrapper: React.FC = ({ children }) => { + return ( + <> + {children} + + + Flow Logo + + + The Flow Playground is best used on larger screens. + + + + + + + ); +}; export default AppMobileWrapper; diff --git a/src/containers/Editor/components.tsx b/src/containers/Editor/components.tsx index 78ca398d..a3eee93f 100644 --- a/src/containers/Editor/components.tsx +++ b/src/containers/Editor/components.tsx @@ -256,7 +256,7 @@ const EditorContainer: React.FC = ({ project.title = title; project.description = description; project.readme = readme; - active.onChange(title, description, readme) + active.onChange(title, description, readme); }; const isReadmeEditor = active.type === 4; diff --git a/src/containers/Editor/layout-components.tsx b/src/containers/Editor/layout-components.tsx index 7eda35a9..7e0ccf2c 100644 --- a/src/containers/Editor/layout-components.tsx +++ b/src/containers/Editor/layout-components.tsx @@ -1,5 +1,5 @@ -import styled from "@emotion/styled"; -import {WithShowProps} from "containers/Editor/components"; +import styled from '@emotion/styled'; +import { WithShowProps } from 'containers/Editor/components'; export const ProjectInfoContainer = styled.div` display: ${({ show }) => (show ? 'block' : 'none')}; @@ -27,4 +27,4 @@ export const ProjectDescription = styled.div` export const ReadmeHtmlContainer = styled.div` margin: 1rem; margin-top: 0rem; -`; \ No newline at end of file +`; diff --git a/src/containers/Editor/layout.tsx b/src/containers/Editor/layout.tsx index 7ebc6bb8..d28f7f45 100644 --- a/src/containers/Editor/layout.tsx +++ b/src/containers/Editor/layout.tsx @@ -32,7 +32,7 @@ import { } from './components'; import { useProject } from 'providers/Project/projectHooks'; -import { decodeText } from "util/readme"; +import { decodeText } from 'util/readme'; const FDP = [ 'f1383d67-6f0a-4be7-8e61-f6141ebdd92c', @@ -74,7 +74,9 @@ const EditorLayout: React.FC = () => { } const [helmetTitle, setHelmetTitle] = useState(decodeText(project.title)); - const [helmetDescription, setHelmetDescription] = useState(decodeText(project.title)); + const [helmetDescription, setHelmetDescription] = useState( + decodeText(project.title), + ); useEffect(() => { if (project.title) { diff --git a/src/globalStyles.ts b/src/globalStyles.ts index bb3d9a6b..c0753e16 100644 --- a/src/globalStyles.ts +++ b/src/globalStyles.ts @@ -1,462 +1,462 @@ -import { css } from "@emotion/core"; +import { css } from '@emotion/core'; export default css` /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 100; - src: local("Overpass Thin Italic"), local("Overpass-ThinItalic"), + src: local('Overpass Thin Italic'), local('Overpass-ThinItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdD35WCmI96Ajtm81Gga7rayz8NoVgyNIjK.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 100; - src: local("Overpass Thin Italic"), local("Overpass-ThinItalic"), + src: local('Overpass Thin Italic'), local('Overpass-ThinItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdD35WCmI96Ajtm81Gga7raxT8NoVgyNA.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 200; - src: local("Overpass ExtraLight Italic"), local("Overpass-ExtraLightItalic"), + src: local('Overpass ExtraLight Italic'), local('Overpass-ExtraLightItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdC35WCmI96Ajtm81GgaxbL0hYojnA4PLDzOA.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 200; - src: local("Overpass ExtraLight Italic"), local("Overpass-ExtraLightItalic"), + src: local('Overpass ExtraLight Italic'), local('Overpass-ExtraLightItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdC35WCmI96Ajtm81GgaxbL0hgojnA4PLA.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 300; - src: local("Overpass Light Italic"), local("Overpass-LightItalic"), + src: local('Overpass Light Italic'), local('Overpass-LightItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdC35WCmI96Ajtm81Gga3LI0hYojnA4PLDzOA.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 300; - src: local("Overpass Light Italic"), local("Overpass-LightItalic"), + src: local('Overpass Light Italic'), local('Overpass-LightItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdC35WCmI96Ajtm81Gga3LI0hgojnA4PLA.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 400; - src: local("Overpass Italic"), local("Overpass-Italic"), + src: local('Overpass Italic'), local('Overpass-Italic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdB35WCmI96Ajtm81GgY9fqxzUKg1oCNQ.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 400; - src: local("Overpass Italic"), local("Overpass-Italic"), + src: local('Overpass Italic'), local('Overpass-Italic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdB35WCmI96Ajtm81GgY9nqxzUKg1o.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 600; - src: local("Overpass SemiBold Italic"), local("Overpass-SemiBoldItalic"), + src: local('Overpass SemiBold Italic'), local('Overpass-SemiBoldItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdC35WCmI96Ajtm81GgawbO0hYojnA4PLDzOA.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 600; - src: local("Overpass SemiBold Italic"), local("Overpass-SemiBoldItalic"), + src: local('Overpass SemiBold Italic'), local('Overpass-SemiBoldItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdC35WCmI96Ajtm81GgawbO0hgojnA4PLA.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 700; - src: local("Overpass Bold Italic"), local("Overpass-BoldItalic"), + src: local('Overpass Bold Italic'), local('Overpass-BoldItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdC35WCmI96Ajtm81Gga2LP0hYojnA4PLDzOA.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 700; - src: local("Overpass Bold Italic"), local("Overpass-BoldItalic"), + src: local('Overpass Bold Italic'), local('Overpass-BoldItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdC35WCmI96Ajtm81Gga2LP0hgojnA4PLA.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 800; - src: local("Overpass ExtraBold Italic"), local("Overpass-ExtraBoldItalic"), + src: local('Overpass ExtraBold Italic'), local('Overpass-ExtraBoldItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdC35WCmI96Ajtm81Gga37M0hYojnA4PLDzOA.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 800; - src: local("Overpass ExtraBold Italic"), local("Overpass-ExtraBoldItalic"), + src: local('Overpass ExtraBold Italic'), local('Overpass-ExtraBoldItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdC35WCmI96Ajtm81Gga37M0hgojnA4PLA.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 900; - src: local("Overpass Black Italic"), local("Overpass-BlackItalic"), + src: local('Overpass Black Italic'), local('Overpass-BlackItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdC35WCmI96Ajtm81Gga1rN0hYojnA4PLDzOA.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: italic; font-weight: 900; - src: local("Overpass Black Italic"), local("Overpass-BlackItalic"), + src: local('Overpass Black Italic'), local('Overpass-BlackItalic'), url(https://fonts.gstatic.com/s/overpass/v4/qFdC35WCmI96Ajtm81Gga1rN0hgojnA4PLA.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 100; - src: local("Overpass Thin"), local("Overpass-Thin"), + src: local('Overpass Thin'), local('Overpass-Thin'), url(https://fonts.gstatic.com/s/overpass/v4/qFdB35WCmI96Ajtm81nGY9fqxzUKg1oCNQ.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 100; - src: local("Overpass Thin"), local("Overpass-Thin"), + src: local('Overpass Thin'), local('Overpass-Thin'), url(https://fonts.gstatic.com/s/overpass/v4/qFdB35WCmI96Ajtm81nGY9nqxzUKg1o.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 200; - src: local("Overpass ExtraLight"), local("Overpass-ExtraLight"), + src: local('Overpass ExtraLight'), local('Overpass-ExtraLight'), url(https://fonts.gstatic.com/s/overpass/v4/qFdA35WCmI96Ajtm81lqcs7D4hoiiVI6DLE.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 200; - src: local("Overpass ExtraLight"), local("Overpass-ExtraLight"), + src: local('Overpass ExtraLight'), local('Overpass-ExtraLight'), url(https://fonts.gstatic.com/s/overpass/v4/qFdA35WCmI96Ajtm81lqcs7N4hoiiVI6.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 300; - src: local("Overpass Light"), local("Overpass-Light"), + src: local('Overpass Light'), local('Overpass-Light'), url(https://fonts.gstatic.com/s/overpass/v4/qFdA35WCmI96Ajtm81kOcc7D4hoiiVI6DLE.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 300; - src: local("Overpass Light"), local("Overpass-Light"), + src: local('Overpass Light'), local('Overpass-Light'), url(https://fonts.gstatic.com/s/overpass/v4/qFdA35WCmI96Ajtm81kOcc7N4hoiiVI6.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 400; - src: local("Overpass Regular"), local("Overpass-Regular"), + src: local('Overpass Regular'), local('Overpass-Regular'), url(https://fonts.gstatic.com/s/overpass/v4/qFdH35WCmI96Ajtm81GrU9vgwBcIs1s.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 400; - src: local("Overpass Regular"), local("Overpass-Regular"), + src: local('Overpass Regular'), local('Overpass-Regular'), url(https://fonts.gstatic.com/s/overpass/v4/qFdH35WCmI96Ajtm81GlU9vgwBcI.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 600; - src: local("Overpass SemiBold"), local("Overpass-SemiBold"), + src: local('Overpass SemiBold'), local('Overpass-SemiBold'), url(https://fonts.gstatic.com/s/overpass/v4/qFdA35WCmI96Ajtm81l6d87D4hoiiVI6DLE.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 600; - src: local("Overpass SemiBold"), local("Overpass-SemiBold"), + src: local('Overpass SemiBold'), local('Overpass-SemiBold'), url(https://fonts.gstatic.com/s/overpass/v4/qFdA35WCmI96Ajtm81l6d87N4hoiiVI6.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 700; - src: local("Overpass Bold"), local("Overpass-Bold"), + src: local('Overpass Bold'), local('Overpass-Bold'), url(https://fonts.gstatic.com/s/overpass/v4/qFdA35WCmI96Ajtm81keds7D4hoiiVI6DLE.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 700; - src: local("Overpass Bold"), local("Overpass-Bold"), + src: local('Overpass Bold'), local('Overpass-Bold'), url(https://fonts.gstatic.com/s/overpass/v4/qFdA35WCmI96Ajtm81keds7N4hoiiVI6.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 800; - src: local("Overpass ExtraBold"), local("Overpass-ExtraBold"), + src: local('Overpass ExtraBold'), local('Overpass-ExtraBold'), url(https://fonts.gstatic.com/s/overpass/v4/qFdA35WCmI96Ajtm81kCdc7D4hoiiVI6DLE.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 800; - src: local("Overpass ExtraBold"), local("Overpass-ExtraBold"), + src: local('Overpass ExtraBold'), local('Overpass-ExtraBold'), url(https://fonts.gstatic.com/s/overpass/v4/qFdA35WCmI96Ajtm81kCdc7N4hoiiVI6.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 900; - src: local("Overpass Black"), local("Overpass-Black"), + src: local('Overpass Black'), local('Overpass-Black'), url(https://fonts.gstatic.com/s/overpass/v4/qFdA35WCmI96Ajtm81kmdM7D4hoiiVI6DLE.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass"; + font-family: 'Overpass'; font-style: normal; font-weight: 900; - src: local("Overpass Black"), local("Overpass-Black"), + src: local('Overpass Black'), local('Overpass-Black'), url(https://fonts.gstatic.com/s/overpass/v4/qFdA35WCmI96Ajtm81kmdM7N4hoiiVI6.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass Mono"; + font-family: 'Overpass Mono'; font-style: normal; font-weight: 300; - src: local("Overpass Mono Light"), local("OverpassMono-Light"), + src: local('Overpass Mono Light'), local('OverpassMono-Light'), url(https://fonts.gstatic.com/s/overpassmono/v5/_Xm3-H86tzKDdAPa-KPQZ-AC3oSWo_6XBlRc4EUk4A.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass Mono"; + font-family: 'Overpass Mono'; font-style: normal; font-weight: 300; - src: local("Overpass Mono Light"), local("OverpassMono-Light"), + src: local('Overpass Mono Light'), local('OverpassMono-Light'), url(https://fonts.gstatic.com/s/overpassmono/v5/_Xm3-H86tzKDdAPa-KPQZ-AC3oSWo_CXBlRc4EU.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass Mono"; + font-family: 'Overpass Mono'; font-style: normal; font-weight: 400; - src: local("Overpass Mono Regular"), local("OverpassMono-Regular"), + src: local('Overpass Mono Regular'), local('OverpassMono-Regular'), url(https://fonts.gstatic.com/s/overpassmono/v5/_Xmq-H86tzKDdAPa-KPQZ-AC1iG0tt21C35m6Q.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass Mono"; + font-family: 'Overpass Mono'; font-style: normal; font-weight: 400; - src: local("Overpass Mono Regular"), local("OverpassMono-Regular"), + src: local('Overpass Mono Regular'), local('OverpassMono-Regular'), url(https://fonts.gstatic.com/s/overpassmono/v5/_Xmq-H86tzKDdAPa-KPQZ-AC1i-0tt21C34.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass Mono"; + font-family: 'Overpass Mono'; font-style: normal; font-weight: 600; - src: local("Overpass Mono SemiBold"), local("OverpassMono-SemiBold"), + src: local('Overpass Mono SemiBold'), local('OverpassMono-SemiBold'), url(https://fonts.gstatic.com/s/overpassmono/v5/_Xm3-H86tzKDdAPa-KPQZ-AC3vCQo_6XBlRc4EUk4A.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass Mono"; + font-family: 'Overpass Mono'; font-style: normal; font-weight: 600; - src: local("Overpass Mono SemiBold"), local("OverpassMono-SemiBold"), + src: local('Overpass Mono SemiBold'), local('OverpassMono-SemiBold'), url(https://fonts.gstatic.com/s/overpassmono/v5/_Xm3-H86tzKDdAPa-KPQZ-AC3vCQo_CXBlRc4EU.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* latin-ext */ @font-face { - font-family: "Overpass Mono"; + font-family: 'Overpass Mono'; font-style: normal; font-weight: 700; - src: local("Overpass Mono Bold"), local("OverpassMono-Bold"), + src: local('Overpass Mono Bold'), local('OverpassMono-Bold'), url(https://fonts.gstatic.com/s/overpassmono/v5/_Xm3-H86tzKDdAPa-KPQZ-AC3pSRo_6XBlRc4EUk4A.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { - font-family: "Overpass Mono"; + font-family: 'Overpass Mono'; font-style: normal; font-weight: 700; - src: local("Overpass Mono Bold"), local("OverpassMono-Bold"), + src: local('Overpass Mono Bold'), local('OverpassMono-Bold'), url(https://fonts.gstatic.com/s/overpassmono/v5/_Xm3-H86tzKDdAPa-KPQZ-AC3pSRo_CXBlRc4EU.woff2) - format("woff2"); + format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; @@ -470,7 +470,7 @@ export default css` #root { height: 100vh; width: 100vw; - font-family: "Overpass", sans-serif; + font-family: 'Overpass', sans-serif; } /* applies to the markdown editor button text */ diff --git a/src/hooks/useKeyPress.ts b/src/hooks/useKeyPress.ts index 4a91f540..052efa3c 100644 --- a/src/hooks/useKeyPress.ts +++ b/src/hooks/useKeyPress.ts @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useState, useEffect } from 'react'; export default function useKeyPress(targetKey: string) { // State for keeping track of whether key is pressed @@ -22,12 +22,12 @@ export default function useKeyPress(targetKey: string) { // Add event listeners useEffect(() => { - window.addEventListener("keydown", downHandler); - window.addEventListener("keyup", upHandler); + window.addEventListener('keydown', downHandler); + window.addEventListener('keyup', upHandler); // Remove event listeners on cleanup return () => { - window.removeEventListener("keydown", downHandler); - window.removeEventListener("keyup", upHandler); + window.removeEventListener('keydown', downHandler); + window.removeEventListener('keyup', upHandler); }; }, []); // Empty array ensures that effect is only run on mount and unmount diff --git a/src/hooks/useLanguageServer.ts b/src/hooks/useLanguageServer.ts index 957b6e2c..09dcadc3 100644 --- a/src/hooks/useLanguageServer.ts +++ b/src/hooks/useLanguageServer.ts @@ -25,7 +25,11 @@ async function startLanguageServer(callbacks: any, getCode: any, ops) { }); } -const launchLanguageClient = async (callbacks, languageServer, setLanguageClient) => { +const launchLanguageClient = async ( + callbacks, + languageServer, + setLanguageClient, +) => { if (languageServer) { const newClient = createCadenceLanguageClient(callbacks); newClient.start(); @@ -118,4 +122,4 @@ export default function useLanguageServer() { languageServer, restartServer, }; -} \ No newline at end of file +} diff --git a/src/hooks/useMousePosition.ts b/src/hooks/useMousePosition.ts index c4c6789a..dacf722b 100644 --- a/src/hooks/useMousePosition.ts +++ b/src/hooks/useMousePosition.ts @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useState, useEffect } from 'react'; const useMousePosition = () => { const [mousePosition, setMousePosition] = useState({ x: null, y: null }); @@ -6,14 +6,14 @@ const useMousePosition = () => { const updateMousePosition = (ev: MouseEvent) => { setMousePosition({ x: ev.clientX, - y: window.innerHeight - ev.clientY + y: window.innerHeight - ev.clientY, }); }; useEffect(() => { - window.addEventListener("mousemove", updateMousePosition); + window.addEventListener('mousemove', updateMousePosition); - return () => window.removeEventListener("mousemove", updateMousePosition); + return () => window.removeEventListener('mousemove', updateMousePosition); }, []); return mousePosition; diff --git a/src/index.html b/src/index.html index 920ae61f..e7c9d06b 100644 --- a/src/index.html +++ b/src/index.html @@ -1,8 +1,8 @@ - - + + Flow Playground diff --git a/src/index.tsx b/src/index.tsx index 6b576baa..d171681e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,20 +1,20 @@ -import * as React from 'react'; -import * as ReactDOM from 'react-dom'; - -import * as Sentry from '@sentry/react'; -import { BrowserTracing } from '@sentry/tracing'; -import { CaptureConsole as CaptureConsoleIntegration } from '@sentry/integrations'; - -import App from './App'; - -Sentry.init({ - dsn: process.env.SENTRY_DSN, - integrations: [ - new BrowserTracing(), - new CaptureConsoleIntegration({ levels: ['error'] }), - ], - tracesSampleRate: 1.0, -}); - -const root = document.getElementById('root'); -ReactDOM.render(, root); +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; + +import * as Sentry from '@sentry/react'; +import { BrowserTracing } from '@sentry/tracing'; +import { CaptureConsole as CaptureConsoleIntegration } from '@sentry/integrations'; + +import App from './App'; + +Sentry.init({ + dsn: process.env.SENTRY_DSN, + integrations: [ + new BrowserTracing(), + new CaptureConsoleIntegration({ levels: ['error'] }), + ], + tracesSampleRate: 1.0, +}); + +const root = document.getElementById('root'); +ReactDOM.render(, root); diff --git a/src/layout/Base.tsx b/src/layout/Base.tsx index 969a573b..a086bf24 100644 --- a/src/layout/Base.tsx +++ b/src/layout/Base.tsx @@ -1,5 +1,5 @@ -import styled from "@emotion/styled"; -import theme from "../theme"; +import styled from '@emotion/styled'; +import theme from '../theme'; export const Base = styled.div` --gap: 1px; @@ -15,8 +15,8 @@ export const Base = styled.div` display: grid; grid-gap: var(--gap) var(--gap); grid-template-areas: - "header header" - "sidebar main"; + 'header header' + 'sidebar main'; grid-template-columns: 244px auto; grid-template-rows: 72px auto; background: var(--key); diff --git a/src/layout/BottomBarItemInsert.tsx b/src/layout/BottomBarItemInsert.tsx index 71bec7cb..a5be2608 100644 --- a/src/layout/BottomBarItemInsert.tsx +++ b/src/layout/BottomBarItemInsert.tsx @@ -1,6 +1,6 @@ -import React from "react"; -import styled from "@emotion/styled"; -import theme from "../theme"; +import React from 'react'; +import styled from '@emotion/styled'; +import theme from '../theme'; type BottomBarItemInsertProps = { onClick?: (e: React.SyntheticEvent) => any | void; @@ -15,9 +15,9 @@ export const BottomBarItemInsert = styled.button` color: ${theme.colors.darkGrey}; &:hover { color: ${theme.colors.heading}; - cursor: ${p => (p.grab ? "grab" : "pointer")}; + cursor: ${(p) => (p.grab ? 'grab' : 'pointer')}; } &:active { - cursor: ${p => (p.grab ? "grabbing" : "pointer")}; + cursor: ${(p) => (p.grab ? 'grabbing' : 'pointer')}; } `; diff --git a/src/layout/Editor.tsx b/src/layout/Editor.tsx index 666c631c..0238f9e8 100644 --- a/src/layout/Editor.tsx +++ b/src/layout/Editor.tsx @@ -1,4 +1,4 @@ -import styled from "@emotion/styled"; +import styled from '@emotion/styled'; export const Editor = styled.div` grid-area: editor; diff --git a/src/layout/FeedbackActions.tsx b/src/layout/FeedbackActions.tsx index 6a810d30..1dcdead3 100644 --- a/src/layout/FeedbackActions.tsx +++ b/src/layout/FeedbackActions.tsx @@ -1,4 +1,4 @@ -import styled from "@emotion/styled"; +import styled from '@emotion/styled'; export const FeedbackActions = styled.div` position: absolute; diff --git a/src/layout/Header.tsx b/src/layout/Header.tsx index 6697794b..55a03765 100644 --- a/src/layout/Header.tsx +++ b/src/layout/Header.tsx @@ -1,4 +1,4 @@ -import styled from "@emotion/styled"; +import styled from '@emotion/styled'; export const Header = styled.div` grid-area: header; diff --git a/src/layout/Heading.tsx b/src/layout/Heading.tsx index a292787c..f9f7ec40 100644 --- a/src/layout/Heading.tsx +++ b/src/layout/Heading.tsx @@ -1,15 +1,15 @@ -import styled from "@emotion/styled"; -import theme from "../theme"; +import styled from '@emotion/styled'; +import theme from '../theme'; type HeadingProps = { textTransform?: string; -} +}; export const Heading = styled.div` padding: 1rem; font-size: 10px; font-weight: bold; - text-transform: ${({ textTransform = "uppercase" }) => (textTransform)}; + text-transform: ${({ textTransform = 'uppercase' }) => textTransform}; letter-spacing: 0.1em; color: ${theme.colors.heading}; padding-bottom: calc(1rem - 3px); @@ -22,7 +22,7 @@ export const Heading = styled.div` &:after { opacity: 0.5; - content: ""; + content: ''; display: block; position: absolute; left: 1rem; @@ -34,9 +34,8 @@ export const Heading = styled.div` } `; - export const ResizeHeading = styled(Heading)` - &:hover { - cursor: ns-resize; - } -` + &:hover { + cursor: ns-resize; + } +`; diff --git a/src/layout/Main.tsx b/src/layout/Main.tsx index c3983a43..e009209b 100644 --- a/src/layout/Main.tsx +++ b/src/layout/Main.tsx @@ -1,4 +1,4 @@ -import styled from "@emotion/styled"; +import styled from '@emotion/styled'; export const Main = styled.div` grid-area: main; diff --git a/src/layout/ProjectItem.tsx b/src/layout/ProjectItem.tsx index 8bb55c91..03624db1 100644 --- a/src/layout/ProjectItem.tsx +++ b/src/layout/ProjectItem.tsx @@ -1,7 +1,7 @@ -import React from "react"; -import styled from "@emotion/styled"; -import { css } from "@emotion/core"; -import theme from "../theme"; +import React from 'react'; +import styled from '@emotion/styled'; +import { css } from '@emotion/core'; +import theme from '../theme'; type ItemProps = { active?: boolean; @@ -12,7 +12,7 @@ export const ProjectItem = styled.div` --active-width: 6px; padding: 1rem; - font-size: 1.0rem; + font-size: 1rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.05em; @@ -23,13 +23,13 @@ export const ProjectItem = styled.div` background: var(--bg); position: relative; - ${p => + ${(p) => p.active && css` background: rgba(255, 255, 255, 0.75); &:after { - content: ""; + content: ''; display: block; position: absolute; left: 0; @@ -47,7 +47,7 @@ export const ProjectItem = styled.div` background: rgba(255, 255, 255, 0.75); } text-decoration: none; - display:flex; + display: flex; align-items: center; color: ${theme.colors.muted}; `; diff --git a/src/layout/RemoveToastButton.tsx b/src/layout/RemoveToastButton.tsx index ccd2f15e..edc87c59 100644 --- a/src/layout/RemoveToastButton.tsx +++ b/src/layout/RemoveToastButton.tsx @@ -1,5 +1,5 @@ -import styled from "@emotion/styled"; -import theme from "../theme"; +import styled from '@emotion/styled'; +import theme from '../theme'; export const RemoveToastButton = styled.button` border: none; diff --git a/src/layout/Sidebar.tsx b/src/layout/Sidebar.tsx index 49b4a0bd..11abf43b 100644 --- a/src/layout/Sidebar.tsx +++ b/src/layout/Sidebar.tsx @@ -1,9 +1,9 @@ -import styled from "@emotion/styled"; +import styled from '@emotion/styled'; export const Sidebar = styled.div` grid-area: sidebar; display: flex; flex-direction: column; background: var(--bg); - overflow-y:auto; + overflow-y: auto; `; diff --git a/src/layout/SidebarHeader.tsx b/src/layout/SidebarHeader.tsx index 4b815c56..fee2f903 100644 --- a/src/layout/SidebarHeader.tsx +++ b/src/layout/SidebarHeader.tsx @@ -1,3 +1,3 @@ -import { Heading } from "./Heading" +import { Heading } from './Heading'; export const SidebarHeader = Heading; diff --git a/src/layout/SidebarItem.tsx b/src/layout/SidebarItem.tsx index cf050a41..a812fd29 100644 --- a/src/layout/SidebarItem.tsx +++ b/src/layout/SidebarItem.tsx @@ -1,7 +1,7 @@ -import React from "react"; -import styled from "@emotion/styled"; -import { css } from "@emotion/core"; -import theme from "../theme"; +import React from 'react'; +import styled from '@emotion/styled'; +import { css } from '@emotion/core'; +import theme from '../theme'; type ItemProps = { active?: boolean; @@ -19,13 +19,13 @@ export const SidebarItem = styled.div` background: var(--bg); position: relative; - ${p => + ${(p) => p.active && css` background: rgba(255, 255, 255, 0.75); &:after { - content: ""; + content: ''; display: block; position: absolute; left: 0; @@ -43,7 +43,7 @@ export const SidebarItem = styled.div` background: rgba(255, 255, 255, 0.75); } text-decoration: none; - display:flex; + display: flex; align-items: center; font-weight: bold; color: ${theme.colors.muted}; diff --git a/src/layout/SidebarItemEdit.tsx b/src/layout/SidebarItemEdit.tsx index 36eb2cd1..4c94d6c6 100644 --- a/src/layout/SidebarItemEdit.tsx +++ b/src/layout/SidebarItemEdit.tsx @@ -1,11 +1,11 @@ -import React from "react" -import styled from "@emotion/styled" +import React from 'react'; +import styled from '@emotion/styled'; type SidebarItemEditProps = { - active?: boolean, - onClick?: (e: React.SyntheticEvent) => any | void, - children?: React.ReactNode, -} + active?: boolean; + onClick?: (e: React.SyntheticEvent) => any | void; + children?: React.ReactNode; +}; export const SidebarItemEdit = styled.div` -moz-appearance: none; diff --git a/src/layout/SidebarItemInput.tsx b/src/layout/SidebarItemInput.tsx index 52570374..078405da 100644 --- a/src/layout/SidebarItemInput.tsx +++ b/src/layout/SidebarItemInput.tsx @@ -1,7 +1,7 @@ -import React from "react"; -import styled from "@emotion/styled"; -import { css } from "@emotion/core"; -import theme from "../theme"; +import React from 'react'; +import styled from '@emotion/styled'; +import { css } from '@emotion/core'; +import theme from '../theme'; type SidebarItemInputProps = { type: string; @@ -25,9 +25,10 @@ export const SidebarItemInput = styled.input` font-weight: 600; background: var(--bg); text-overflow: ellipsis; - border: ${p => (p.readonly ? "1px solid transparent" : `1px solid #dedede`)}; - pointer-events: ${p => (p.readonly ? "none" : "initial")}; - background: ${p => (p.readonly ? "none" : "#ffffff")}; + border: ${(p) => + p.readonly ? '1px solid transparent' : `1px solid #dedede`}; + pointer-events: ${(p) => (p.readonly ? 'none' : 'initial')}; + background: ${(p) => (p.readonly ? 'none' : '#ffffff')}; padding: 4px; border-radius: 4px; margin-left: -5px; @@ -40,7 +41,7 @@ export const SidebarItemInput = styled.input` &:hover + .editIcon { opacity: 1; } - ${p => + ${(p) => p.onClick && css` cursor: pointer; diff --git a/src/layout/SidebarItemInsert.tsx b/src/layout/SidebarItemInsert.tsx index aa520427..b1cf76f1 100644 --- a/src/layout/SidebarItemInsert.tsx +++ b/src/layout/SidebarItemInsert.tsx @@ -1,6 +1,6 @@ -import React from "react"; -import styled from "@emotion/styled"; -import theme from "../theme"; +import React from 'react'; +import styled from '@emotion/styled'; +import theme from '../theme'; type SidebarItemInsertProps = { onClick?: (e: React.SyntheticEvent) => any | void; @@ -19,9 +19,9 @@ export const SidebarItemInsert = styled.button` color: ${theme.colors.grey}; &:hover { color: ${theme.colors.heading}; - cursor: ${p => (p.grab ? "grab" : "pointer")}; + cursor: ${(p) => (p.grab ? 'grab' : 'pointer')}; } &:active { - cursor: ${p => (p.grab ? "grabbing" : "pointer")}; + cursor: ${(p) => (p.grab ? 'grabbing' : 'pointer')}; } `; diff --git a/src/layout/SidebarItems.tsx b/src/layout/SidebarItems.tsx index 795aa081..0d3cfc01 100644 --- a/src/layout/SidebarItems.tsx +++ b/src/layout/SidebarItems.tsx @@ -1,5 +1,5 @@ -import styled from "@emotion/styled" +import styled from '@emotion/styled'; export const SidebarItems = styled.div` - background:var(--key); -` + background: var(--key); +`; diff --git a/src/layout/SidebarSection.tsx b/src/layout/SidebarSection.tsx index d6b062ee..cc907aa9 100644 --- a/src/layout/SidebarSection.tsx +++ b/src/layout/SidebarSection.tsx @@ -1,20 +1,20 @@ -import styled from "@emotion/styled"; +import styled from '@emotion/styled'; export const SidebarSection = styled.div` - position:relative; + position: relative; & + & { margin-top: calc(2rem + 1px); } & + &:before { - display:block; - content: ""; - position:absolute; + display: block; + content: ''; + position: absolute; bottom: 100%; margin-bottom: 1rem; border-top: 1px solid var(--key); - right:4rem; - left:4rem; + right: 4rem; + left: 4rem; } `; diff --git a/src/layout/Stack.tsx b/src/layout/Stack.tsx index 4f3ca15e..353bc32d 100644 --- a/src/layout/Stack.tsx +++ b/src/layout/Stack.tsx @@ -1,18 +1,19 @@ -import styled from "@emotion/styled" +import styled from '@emotion/styled'; export const Stack = styled.div` - display:flex; - flex-direction:column; + display: flex; + flex-direction: column; flex: 1; & > * + * { - margin-top:3px; + margin-top: 3px; } - - strong, small { + + strong, + small { max-width: 9em; text-overflow: ellipsis; overflow: hidden; } -` +`; diff --git a/src/pages/404.tsx b/src/pages/404.tsx index 6b5d4495..b1a10817 100644 --- a/src/pages/404.tsx +++ b/src/pages/404.tsx @@ -1,54 +1,54 @@ -import React from 'react'; -import { Box, Text, Button } from 'theme-ui'; -import { RouteComponentProps, navigate } from '@reach/router'; - -interface ProjectProps extends RouteComponentProps { - '*'?: string; -} - -const FourOhFour: React.FC = () => { - return ( - - - Floh No! We couldn't find that project. - - - (If you were expecting a project here, you may be experiencing a 🐛. - Please clear your browser's cookies and browser cache. This is a known - issue. Thanks for your patience! 🙏) - - - - ); -}; - -export default FourOhFour; +import React from 'react'; +import { Box, Text, Button } from 'theme-ui'; +import { RouteComponentProps, navigate } from '@reach/router'; + +interface ProjectProps extends RouteComponentProps { + '*'?: string; +} + +const FourOhFour: React.FC = () => { + return ( + + + Floh No! We couldn't find that project. + + + (If you were expecting a project here, you may be experiencing a 🐛. + Please clear your browser's cookies and browser cache. This is a known + issue. Thanks for your patience! 🙏) + + + + ); +}; + +export default FourOhFour; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 45197767..75aa07c0 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,7 +1,7 @@ -import React from "react"; - -export default () => ( -
-

Flow Playground

-
-); +import React from 'react'; + +export default () => ( +
+

Flow Playground

+
+); diff --git a/src/providers/Project/index.tsx b/src/providers/Project/index.tsx index 8503736c..4bfdffaa 100644 --- a/src/providers/Project/index.tsx +++ b/src/providers/Project/index.tsx @@ -1,4 +1,4 @@ -import React, {createContext, useState} from 'react'; +import React, { createContext, useState } from 'react'; import { useApolloClient, useQuery } from '@apollo/react-hooks'; import { navigate, useLocation, Redirect } from '@reach/router'; import ProjectMutator from './projectMutator'; @@ -324,15 +324,13 @@ export const ProjectProvider: React.FC = ({ return { type: active.type, index: active.index, - onChange: (code: any) => - updateActiveTransactionTemplate(code), + onChange: (code: any) => updateActiveTransactionTemplate(code), }; case EntityType.ScriptTemplate: return { type: active.type, index: active.index, - onChange: (code: any) => - updateActiveScriptTemplate(code), + onChange: (code: any) => updateActiveScriptTemplate(code), }; case EntityType.Readme: return { @@ -345,7 +343,7 @@ export const ProjectProvider: React.FC = ({ } }; - const activeEditor = getActiveEditor() + const activeEditor = getActiveEditor(); const location = useLocation(); if (isLoading) return null; diff --git a/src/providers/Project/projectDefault.ts b/src/providers/Project/projectDefault.ts index dc33b602..66b0fd1e 100644 --- a/src/providers/Project/projectDefault.ts +++ b/src/providers/Project/projectDefault.ts @@ -2,10 +2,10 @@ import { Project, Account, TransactionTemplate, - ScriptTemplate -} from "api/apollo/generated/graphql"; -import { strToSeed, uuid } from "util/rng"; -import { LOCAL_PROJECT_ID } from "util/url"; + ScriptTemplate, +} from 'api/apollo/generated/graphql'; +import { strToSeed, uuid } from 'util/rng'; +import { LOCAL_PROJECT_ID } from 'util/url'; const DEFAULT_ACCOUNT_1 = `// HelloWorld.cdc // @@ -115,7 +115,7 @@ const DEFAULT_ACCOUNTS = [ DEFAULT_ACCOUNT_2, DEFAULT_ACCOUNT_3, DEFAULT_ACCOUNT_4, - DEFAULT_ACCOUNT_5 + DEFAULT_ACCOUNT_5, ]; const DEFAULT_TRANSACTION = `import HelloWorld from 0x01 @@ -135,14 +135,15 @@ const DEFAULT_SCRIPT = `pub fun main(): Int { } `; -export const SEED_TITLE = "Cadence Playground" -export const SEED_DESCRIPTION = "Showcase Cadence interactions" -export const SEED_README = "" +export const SEED_TITLE = 'Cadence Playground'; +export const SEED_DESCRIPTION = 'Showcase Cadence interactions'; +export const SEED_README = ''; -export const PLACEHOLDER_TITLE = "Name of your project" -export const PLACEHOLDER_DESCRIPTION = "Single sentence describing this project" +export const PLACEHOLDER_TITLE = 'Name of your project'; +export const PLACEHOLDER_DESCRIPTION = + 'Single sentence describing this project'; export const PLACEHOLDER_README = `Here you can provide a detailed explanation to help others understand how to use your Playground project. -Editor supports Markdown. Please, consult https://www.markdownguide.org/cheat-sheet/ for examples and tips.` +Editor supports Markdown. Please, consult https://www.markdownguide.org/cheat-sheet/ for examples and tips.`; export function createDefaultProject(): Project { return createLocalProject( @@ -152,15 +153,15 @@ export function createDefaultProject(): Project { SEED_DESCRIPTION, SEED_README, DEFAULT_ACCOUNTS, - [{ title: "Transaction", code: DEFAULT_TRANSACTION }], - [{ title: "Script" , code :DEFAULT_SCRIPT }] + [{ title: 'Transaction', code: DEFAULT_TRANSACTION }], + [{ title: 'Script', code: DEFAULT_SCRIPT }], ); } type ScriptDetails = { - code: string, - title: string -} + code: string; + title: string; +}; export function createLocalProject( parentId: string | null, @@ -170,56 +171,56 @@ export function createLocalProject( readme: string, accounts: Array, transactionTemplates: Array, - scriptTemplates: Array + scriptTemplates: Array, ): Project { const accountEntities: Account[] = accounts.map((script, i) => { return { - __typename: "Account", + __typename: 'Account', id: `local-account-${i}`, address: `000000000000000000000000000000000000000${i + 1}`, title: title, description: description, readme: readme, draftCode: script, - deployedCode: "", + deployedCode: '', deployedContracts: [], - state: "{}" + state: '{}', }; }); const transactionTemplatesEntities: TransactionTemplate[] = transactionTemplates.map( (script, i) => { - const { title, code } = script + const { title, code } = script; return { - __typename: "TransactionTemplate", + __typename: 'TransactionTemplate', id: `local-tx-temp-${i}`, title: title || `Transaction ${i + 1}`, script: code, index: i, }; - } + }, ); const scriptsTemplatesEntities: ScriptTemplate[] = scriptTemplates.map( (script, i) => { - const { title, code } = script + const { title, code } = script; return { - __typename: "ScriptTemplate", + __typename: 'ScriptTemplate', id: `local-script-temp-${i}`, title: title || `Script ${i + 1}`, script: code, index: i, }; - } + }, ); return { - __typename: "Project", + __typename: 'Project', id: LOCAL_PROJECT_ID, - publicId: "", + publicId: '', persist: false, mutable: false, - title: title, + title: title, description: description, readme: readme, seed: seed, @@ -227,6 +228,6 @@ export function createLocalProject( accounts: accountEntities, transactionTemplates: transactionTemplatesEntities, scriptTemplates: scriptsTemplatesEntities, - version: "" + version: '', }; } diff --git a/src/providers/Project/projectHooks.ts b/src/providers/Project/projectHooks.ts index 5527918d..3a98b15c 100644 --- a/src/providers/Project/projectHooks.ts +++ b/src/providers/Project/projectHooks.ts @@ -1,11 +1,11 @@ -import { useContext } from "react"; -import { useQuery } from "@apollo/react-hooks"; +import { useContext } from 'react'; +import { useQuery } from '@apollo/react-hooks'; -import { GET_PROJECT, GET_LOCAL_PROJECT } from "api/apollo/queries"; +import { GET_PROJECT, GET_LOCAL_PROJECT } from 'api/apollo/queries'; -import { Project } from "api/apollo/generated/graphql"; -import { ProjectContext, ProjectContextValue } from "./index"; -import { createDefaultProject, createLocalProject } from "./projectDefault"; +import { Project } from 'api/apollo/generated/graphql'; +import { ProjectContext, ProjectContextValue } from './index'; +import { createDefaultProject, createLocalProject } from './projectDefault'; function writeDefaultProject(client: any) { const defaultProject = createDefaultProject(); @@ -13,8 +13,8 @@ function writeDefaultProject(client: any) { client.writeData({ data: { activeProject: true, - localProject: defaultProject - } + localProject: defaultProject, + }, }); } @@ -25,31 +25,31 @@ function cloneProject(client: any, project: Project) { project.title, project.description, project.readme, - project.accounts.map(acc => acc.draftCode), + project.accounts.map((acc) => acc.draftCode), - project.transactionTemplates.map(tpl => ({ - code: tpl.script, - title: tpl.title - })), + project.transactionTemplates.map((tpl) => ({ + code: tpl.script, + title: tpl.title, + })), - project.scriptTemplates.map(tpl => ({ + project.scriptTemplates.map((tpl) => ({ code: tpl.script, - title: tpl.title - })) + title: tpl.title, + })), ); client.writeData({ data: { activeProject: true, - localProject: localProject - } + localProject: localProject, + }, }); } export default function useGetProject( client: any, projectId: string | null, - isActiveProject: boolean + isActiveProject: boolean, ): { project: any | null; isLocal: boolean; @@ -61,7 +61,7 @@ export default function useGetProject( const { loading, data: remoteData } = useQuery(GET_PROJECT, { variables: { projectId: projectId }, // skip remote query if this is a new project - skip: isNewProject + skip: isNewProject, }); if (isNewProject) { @@ -73,7 +73,7 @@ export default function useGetProject( project: readLocalProject(client), isLocal: true, isClone: false, - isLoading: false + isLoading: false, }; } @@ -83,7 +83,7 @@ export default function useGetProject( project: readLocalProject(client), isLocal: false, isClone: false, - isLoading: false + isLoading: false, }; } @@ -102,7 +102,7 @@ export default function useGetProject( project: readLocalProject(client), isLocal: true, isClone: true, - isLoading: false + isLoading: false, }; } @@ -110,7 +110,7 @@ export default function useGetProject( project: remoteData.project, isLocal: false, isClone: false, - isLoading: false + isLoading: false, }; } diff --git a/src/styles/markdown.css b/src/styles/markdown.css index e14d5f09..d61c11b6 100644 --- a/src/styles/markdown.css +++ b/src/styles/markdown.css @@ -1,5 +1,5 @@ .ease-md-red-border .editor-toolbar, -.ease-md-red-border .CodeMirror-wrap{ - border-color: #EE431E; - transition: border 0.5s ease-in-out; -} \ No newline at end of file +.ease-md-red-border .CodeMirror-wrap { + border-color: #ee431e; + transition: border 0.5s ease-in-out; +} diff --git a/src/templates.d.ts b/src/templates.d.ts index 1d6668fc..007feb74 100644 --- a/src/templates.d.ts +++ b/src/templates.d.ts @@ -1 +1 @@ -declare module "*.hbs"; +declare module '*.hbs'; diff --git a/src/templates/js/helpers/getNameByAddress.js b/src/templates/js/helpers/getNameByAddress.js index 99c8240f..65f1a4b0 100644 --- a/src/templates/js/helpers/getNameByAddress.js +++ b/src/templates/js/helpers/getNameByAddress.js @@ -1,10 +1,10 @@ -module.exports = (address) => { - const addressBook = { - '0x01': 'Alice', - '0x02': 'Bob', - '0x03': 'Charlie', - '0x04': 'Dave', - }; - - return addressBook[address]; -} \ No newline at end of file +module.exports = (address) => { + const addressBook = { + '0x01': 'Alice', + '0x02': 'Bob', + '0x03': 'Charlie', + '0x04': 'Dave', + }; + + return addressBook[address]; +}; diff --git a/src/templates/js/helpers/isString.js b/src/templates/js/helpers/isString.js index b25fbd7d..b4dcc100 100644 --- a/src/templates/js/helpers/isString.js +++ b/src/templates/js/helpers/isString.js @@ -1,3 +1,3 @@ -module.exports = function (item) { - return (typeof item === 'string' || item instanceof String) -}; +module.exports = function (item) { + return typeof item === 'string' || item instanceof String; +}; diff --git a/src/theme.ts b/src/theme.ts index 3648dff3..7b18f9da 100644 --- a/src/theme.ts +++ b/src/theme.ts @@ -1,133 +1,133 @@ export default { colors: { - primary: "#00ff76", - darkPrimary: "#2bb169", - background: "#fff", - text: "#222", - muted: "#6a6a6a", - grey: "#DDDDDD", - darkGrey: "#909090", - greyBorder: "#D8D8D8", - purple: "#f694ff", - border: "rgb(240, 240, 240)", - borderDark: "rgb(222, 222, 222)", - shadowColor: "rgb(222, 222, 222)", - warning: "#ffcc00", - error: "#f44336", - blue: "#0000ff", - heading: "#919191", - badgeResource: "#0093AF", - badgeCapability: "#3DDC84", - badgeStruct: "#FA8C28", - badgeNull: "#8C92AC", + primary: '#00ff76', + darkPrimary: '#2bb169', + background: '#fff', + text: '#222', + muted: '#6a6a6a', + grey: '#DDDDDD', + darkGrey: '#909090', + greyBorder: '#D8D8D8', + purple: '#f694ff', + border: 'rgb(240, 240, 240)', + borderDark: 'rgb(222, 222, 222)', + shadowColor: 'rgb(222, 222, 222)', + warning: '#ffcc00', + error: '#f44336', + blue: '#0000ff', + heading: '#919191', + badgeResource: '#0093AF', + badgeCapability: '#3DDC84', + badgeStruct: '#FA8C28', + badgeNull: '#8C92AC', }, fonts: { - body: "Interstate, system-ui, sans-serif", - heading: "Interstate, system-ui, sans-serif", - monospace: "Menlo, Monaco, 'Courier New', monospace" + body: 'Interstate, system-ui, sans-serif', + heading: 'Interstate, system-ui, sans-serif', + monospace: "Menlo, Monaco, 'Courier New', monospace", }, forms: { subtle: { padding: 0, - border: "none", - color: "purple", - marginRight: "0.5rem", - textOverflow: "ellipsis" - } + border: 'none', + color: 'purple', + marginRight: '0.5rem', + textOverflow: 'ellipsis', + }, }, buttons: { primary: { - border: "none", - borderRadius: "8px", - backgroundColor: "primary", - fontFamily: "body", + border: 'none', + borderRadius: '8px', + backgroundColor: 'primary', + fontFamily: 'body', fontWeight: 500, - color: "text", + color: 'text', margin: 0, - paddingX: "1rem", - paddingY: "0.75rem", + paddingX: '1rem', + paddingY: '0.75rem', fontSize: 4, - "&:active": { - backgroundColor: "#10EF77", + '&:active': { + backgroundColor: '#10EF77', }, }, disabled: { - border: "none", - backgroundColor: "grey", - borderRadius: "8px", + border: 'none', + backgroundColor: 'grey', + borderRadius: '8px', borderWidth: 3, - fontFamily: "body", + fontFamily: 'body', fontWeight: 500, - color: "text", + color: 'text', margin: 0, - paddingX: "1rem", - paddingY: "0.75rem", - fontSize: 4 + paddingX: '1rem', + paddingY: '0.75rem', + fontSize: 4, }, secondary: { - border: "none", - background: "none", - fontFamily: "body", - color: "text", - textDecoration: "none", - display: "flex", - alignItems: "center", + border: 'none', + background: 'none', + fontFamily: 'body', + color: 'text', + textDecoration: 'none', + display: 'flex', + alignItems: 'center', margin: 0, fontWeight: 500, - paddingX: "0.65rem", - paddingY: "0.5rem", - borderRadius: "5px", - "&:hover": { - background: "rgb(245, 245, 245)", - } - } + paddingX: '0.65rem', + paddingY: '0.5rem', + borderRadius: '5px', + '&:hover': { + background: 'rgb(245, 245, 245)', + }, + }, }, fontWeights: { thin: 200, body: 400, medium: 500, heading: 700, - bold: 800 + bold: 800, }, lineHeights: { body: 1.5, - heading: 1.125 + heading: 1.125, }, - fontSizes: ["1rem", "2rem", "4rem", 12, 14, 16, 20, 24, 32, 48, 64, 72], - space: [0, "1rem", "2rem", "4rem"], - radii: [4, 8, "1rem", "2rem", "4rem"], + fontSizes: ['1rem', '2rem', '4rem', 12, 14, 16, 20, 24, 32, 48, 64, 72], + space: [0, '1rem', '2rem', '4rem'], + radii: [4, 8, '1rem', '2rem', '4rem'], borderWidths: [1, 4], shadows: [ - "9px 9px 10px #d9c5d6, -9px -9px 10px whitesmoke", - "5px 5px 10px #d6e3e6, -5px -5px 10px #ffffff", - "2px 2px 5px #d6e3e6, -2px -2px 5px #ffffff" + '9px 9px 10px #d9c5d6, -9px -9px 10px whitesmoke', + '5px 5px 10px #d6e3e6, -5px -5px 10px #ffffff', + '2px 2px 5px #d6e3e6, -2px -2px 5px #ffffff', ], - borders: ["2px solid rgb(240, 240, 240)"], + borders: ['2px solid rgb(240, 240, 240)'], boxes: { borderBox: { - position: "relative", - background: "white", - overflow: "hidden", + position: 'relative', + background: 'white', + overflow: 'hidden', borderRadius: 2, boxShadow: 2, border: 0, - transition: "box-shadow 0.2s", - "&:hover": { - boxShadow: 1 - } - } + transition: 'box-shadow 0.2s', + '&:hover': { + boxShadow: 1, + }, + }, }, text: { icon: { - display: "flex", - alignItems: "center", + display: 'flex', + alignItems: 'center', fontSize: 3, - ":hover": { - cursor: "pointer" + ':hover': { + cursor: 'pointer', }, svg: { - marginRight: "0.2rem" - } - } - } + marginRight: '0.2rem', + }, + }, + }, }; diff --git a/src/util/accounts.ts b/src/util/accounts.ts index e92cfebb..cb0c4c01 100644 --- a/src/util/accounts.ts +++ b/src/util/accounts.ts @@ -1,8 +1,8 @@ export const storageMap: { [account: string]: number } = { - "none": 0, - "0x01": 0, - "0x02": 1, - "0x03": 2, - "0x04": 3, - "0x05": 4 -} + none: 0, + '0x01': 0, + '0x02': 1, + '0x03': 2, + '0x04': 3, + '0x05': 4, +}; diff --git a/src/util/avataaar.ts b/src/util/avataaar.ts index a66999c9..a02fbb9b 100644 --- a/src/util/avataaar.ts +++ b/src/util/avataaar.ts @@ -1,2 +1,2 @@ export const avataaar = (hash: string): string => - `${process.env.AVATAAR_URL}avatar/${hash}.svg` + `${process.env.AVATAAR_URL}avatar/${hash}.svg`; diff --git a/src/util/cadence.ts b/src/util/cadence.ts index 121b05ee..9e510ae3 100644 --- a/src/util/cadence.ts +++ b/src/util/cadence.ts @@ -1,115 +1,114 @@ import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'; -import {languages} from "monaco-editor/esm/vs/editor/editor.api" -import IMonarchLanguage = languages.IMonarchLanguage +import { languages } from 'monaco-editor/esm/vs/editor/editor.api'; +import IMonarchLanguage = languages.IMonarchLanguage; -export const CADENCE_LANGUAGE_ID = "cadence" +export const CADENCE_LANGUAGE_ID = 'cadence'; export default function configureCadence() { - monaco.languages.register({ id: CADENCE_LANGUAGE_ID, - extensions: [".cdc"], - aliases: ["CDC", "cdc"] + extensions: ['.cdc'], + aliases: ['CDC', 'cdc'], }); const languageDef: IMonarchLanguage & { - keywords: string[], - typeKeywords: string[], - operators: string[], - symbols: RegExp, - escapes: RegExp, - digits: RegExp, - octaldigits: RegExp, - binarydigits: RegExp, - hexdigits: RegExp, + keywords: string[]; + typeKeywords: string[]; + operators: string[]; + symbols: RegExp; + escapes: RegExp; + digits: RegExp; + octaldigits: RegExp; + binarydigits: RegExp; + hexdigits: RegExp; } = { keywords: [ - "if", - "else", - "return", - "continue", - "break", - "while", - "pre", - "post", - "prepare", - "execute", - "import", - "from", - "create", - "destroy", - "priv", - "pub", - "get", - "set", - "log", - "emit", - "event", - "init", - "struct", - "interface", - "fun", - "let", - "var", - "resource", - "access", - "all", - "contract", - "self", - "transaction" + 'if', + 'else', + 'return', + 'continue', + 'break', + 'while', + 'pre', + 'post', + 'prepare', + 'execute', + 'import', + 'from', + 'create', + 'destroy', + 'priv', + 'pub', + 'get', + 'set', + 'log', + 'emit', + 'event', + 'init', + 'struct', + 'interface', + 'fun', + 'let', + 'var', + 'resource', + 'access', + 'all', + 'contract', + 'self', + 'transaction', ], typeKeywords: [ - "AnyStruct", - "AnyResource", - "Void", - "Never", - "String", - "Character", - "Bool", - "Self", - "Int8", - "Int16", - "Int32", - "Int64", - "Int128", - "Int256", - "UInt8", - "UInt16", - "UInt32", - "UInt64", - "UInt128", - "UInt256", - "Word8", - "Word16", - "Word32", - "Word64", - "Word128", - "Word256", - "Fix64", - "UFix64" + 'AnyStruct', + 'AnyResource', + 'Void', + 'Never', + 'String', + 'Character', + 'Bool', + 'Self', + 'Int8', + 'Int16', + 'Int32', + 'Int64', + 'Int128', + 'Int256', + 'UInt8', + 'UInt16', + 'UInt32', + 'UInt64', + 'UInt128', + 'UInt256', + 'Word8', + 'Word16', + 'Word32', + 'Word64', + 'Word128', + 'Word256', + 'Fix64', + 'UFix64', ], operators: [ - "<-", - "<=", - ">=", - "==", - "!=", - "+", - "-", - "*", - "/", - "%", - "&", - "!", - "&&", - "||", - "?", - "??", - ":", - "=", - "@" + '<-', + '<=', + '>=', + '==', + '!=', + '+', + '-', + '*', + '/', + '%', + '&', + '!', + '&&', + '||', + '?', + '??', + ':', + '=', + '@', ], // we include these common regular expressions @@ -121,7 +120,7 @@ export default function configureCadence() { hexdigits: /[[0-9a-fA-F]+(_+[0-9a-fA-F]+)*/, tokenizer: { - root: [[/[{}]/, "delimiter.bracket"], {include: "common"}], + root: [[/[{}]/, 'delimiter.bracket'], { include: 'common' }], common: [ // identifiers and keywords @@ -129,67 +128,66 @@ export default function configureCadence() { /[a-z_$][\w$]*/, { cases: { - "@typeKeywords": "keyword", - "@keywords": "keyword", - "@default": "identifier" - } - } + '@typeKeywords': 'keyword', + '@keywords': 'keyword', + '@default': 'identifier', + }, + }, ], - [/[A-Z][\w]*/, "type.identifier"], // to show class names nicely + [/[A-Z][\w]*/, 'type.identifier'], // to show class names nicely // whitespace - {include: "@whitespace"}, + { include: '@whitespace' }, // delimiters and operators - [/[()\[\]]/, "@brackets"], - [/[<>](?!@symbols)/, "@brackets"], + [/[()\[\]]/, '@brackets'], + [/[<>](?!@symbols)/, '@brackets'], [ /@symbols/, { cases: { - "@operators": "delimiter", - "@default": "" - } - } + '@operators': 'delimiter', + '@default': '', + }, + }, ], // numbers - [/(@digits)[eE]([\-+]?(@digits))?/, "number.float"], - [/(@digits)\.(@digits)([eE][\-+]?(@digits))?/, "number.float"], - [/0[xX](@hexdigits)/, "number.hex"], - [/0[oO]?(@octaldigits)/, "number.octal"], - [/0[bB](@binarydigits)/, "number.binary"], - [/(@digits)/, "number"], + [/(@digits)[eE]([\-+]?(@digits))?/, 'number.float'], + [/(@digits)\.(@digits)([eE][\-+]?(@digits))?/, 'number.float'], + [/0[xX](@hexdigits)/, 'number.hex'], + [/0[oO]?(@octaldigits)/, 'number.octal'], + [/0[bB](@binarydigits)/, 'number.binary'], + [/(@digits)/, 'number'], // delimiter: after number because of .\d floats - [/[;,.]/, "delimiter"], + [/[;,.]/, 'delimiter'], // strings - [/"([^"\\]|\\.)*$/, "string.invalid"], // non-teminated string - [/"/, "string", "@string_double"], + [/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string + [/"/, 'string', '@string_double'], ], whitespace: [ - [/[ \t\r\n]+/, ""], - [/\/\*/, "comment", "@comment"], - [/\/\/.*$/, "comment"] + [/[ \t\r\n]+/, ''], + [/\/\*/, 'comment', '@comment'], + [/\/\/.*$/, 'comment'], ], comment: [ - [/[^\/*]+/, "comment"], - [/\*\//, "comment", "@pop"], - [/[\/*]/, "comment"] + [/[^\/*]+/, 'comment'], + [/\*\//, 'comment', '@pop'], + [/[\/*]/, 'comment'], ], string_double: [ - [/[^\\"]+/, "string"], - [/@escapes/, "string.escape"], - [/\\./, "string.escape.invalid"], - [/"/, "string", "@pop"] + [/[^\\"]+/, 'string'], + [/@escapes/, 'string.escape'], + [/\\./, 'string.escape.invalid'], + [/"/, 'string', '@pop'], ], - - } - } + }, + }; monaco.languages.setMonarchTokensProvider(CADENCE_LANGUAGE_ID, languageDef); } diff --git a/src/util/debounce.ts b/src/util/debounce.ts index 63a53db7..63e95dc0 100644 --- a/src/util/debounce.ts +++ b/src/util/debounce.ts @@ -1,6 +1,6 @@ export default function debounce(func: any, wait = 500) { let timeout: any; - return function(...args: any) { + return function (...args: any) { clearTimeout(timeout); timeout = setTimeout(() => { func.apply(this, args); diff --git a/src/util/generate-code.ts b/src/util/generate-code.ts index a0cd8ef6..4b215e58 100644 --- a/src/util/generate-code.ts +++ b/src/util/generate-code.ts @@ -1,6 +1,6 @@ export const generateCode = (project: string, id: string, type: string) => { - const API = process.env.PLAYGROUND_API - const scriptType = type.toLowerCase().replace('template','') - const src = `${API}/embed?project=${project}&type=${scriptType}&id=${id}` - return `` -} + const API = process.env.PLAYGROUND_API; + const scriptType = type.toLowerCase().replace('template', ''); + const src = `${API}/embed?project=${project}&type=${scriptType}&id=${id}`; + return ``; +}; diff --git a/src/util/google-analytics.ts b/src/util/google-analytics.ts index 9b11d79a..1c7ba0fb 100644 --- a/src/util/google-analytics.ts +++ b/src/util/google-analytics.ts @@ -1,10 +1,10 @@ -import ReactGA from "react-ga"; +import ReactGA from 'react-ga'; export const initialize = (trackingCode: string) => { ReactGA.initialize(trackingCode); }; export const pageview = (location: any) => { - const page = location.pathname + location.search + const page = location.pathname + location.search; ReactGA.pageview(page); }; diff --git a/src/util/language-client.ts b/src/util/language-client.ts index c86b43b4..c07471ac 100644 --- a/src/util/language-client.ts +++ b/src/util/language-client.ts @@ -1,5 +1,5 @@ -import {CADENCE_LANGUAGE_ID} from './cadence' -import {Callbacks} from './language-server' +import { CADENCE_LANGUAGE_ID } from './cadence'; +import { Callbacks } from './language-server'; import { createMessageConnection, DataCallback, @@ -8,85 +8,93 @@ import { Message, MessageReader, MessageWriter, - PartialMessageInfo -} from "vscode-jsonrpc" -import {ConnectionErrorHandler} from "monaco-languageclient/src/connection" -import {ConnectionCloseHandler, CloseAction, createConnection, ErrorAction, MonacoLanguageClient} from "monaco-languageclient" + PartialMessageInfo, +} from 'vscode-jsonrpc'; +import { ConnectionErrorHandler } from 'monaco-languageclient/src/connection'; +import { + ConnectionCloseHandler, + CloseAction, + createConnection, + ErrorAction, + MonacoLanguageClient, +} from 'monaco-languageclient'; export function createCadenceLanguageClient(callbacks: Callbacks) { const logger: Logger = { error(message: string) { - console.error(message) + console.error(message); }, warn(message: string) { - console.warn(message) + console.warn(message); }, info(message: string) { - console.info(message) + console.info(message); }, log(message: string) { - console.log(message) + console.log(message); }, - } + }; const writer: MessageWriter = { onClose(_: (_: void) => void): Disposable { - return Disposable.create(() => { - }) + return Disposable.create(() => {}); }, onError(_: (error: [Error, Message, number]) => void): Disposable { - return Disposable.create(() => { - }) + return Disposable.create(() => {}); }, async write(msg: Message): Promise { - callbacks.toServer(null, msg) + callbacks.toServer(null, msg); }, end() {}, dispose() { - callbacks.onClientClose() - } - } + callbacks.onClientClose(); + }, + }; const reader: MessageReader = { onError(_: (error: Error) => void): Disposable { - return Disposable.create(() => { - }) + return Disposable.create(() => {}); }, onClose(_: (_: void) => void): Disposable { - return Disposable.create(() => { - }) + return Disposable.create(() => {}); }, onPartialMessage(_: (m: PartialMessageInfo) => void): Disposable { - return Disposable.create(() => { - }) + return Disposable.create(() => {}); }, listen(dataCallback: DataCallback): Disposable { - callbacks.toClient = (message) => dataCallback(message) - return Disposable.create(() => { - }) + callbacks.toClient = (message) => dataCallback(message); + return Disposable.create(() => {}); }, dispose() { - console.log("-------------------------->", "Language Client is closed. Do something!") - callbacks.onClientClose() - } - } + console.log( + '-------------------------->', + 'Language Client is closed. Do something!', + ); + callbacks.onClientClose(); + }, + }; - const messageConnection = createMessageConnection(reader, writer, logger) + const messageConnection = createMessageConnection(reader, writer, logger); return new MonacoLanguageClient({ - name: "Cadence Language Client", + name: 'Cadence Language Client', clientOptions: { documentSelector: [CADENCE_LANGUAGE_ID], errorHandler: { error: () => ErrorAction.Continue, - closed: () => CloseAction.DoNotRestart - } + closed: () => CloseAction.DoNotRestart, + }, }, // Create a language client connection from the JSON-RPC connection on demand connectionProvider: { - get: (errorHandler: ConnectionErrorHandler, closeHandler: ConnectionCloseHandler) => { - return Promise.resolve(createConnection(messageConnection, errorHandler, closeHandler)) - } - } + get: ( + errorHandler: ConnectionErrorHandler, + closeHandler: ConnectionCloseHandler, + ) => { + return Promise.resolve( + createConnection(messageConnection, errorHandler, closeHandler), + ); + }, + }, }); } diff --git a/src/util/language-server.ts b/src/util/language-server.ts index e794f2aa..1e86dfbf 100644 --- a/src/util/language-server.ts +++ b/src/util/language-server.ts @@ -1,11 +1,11 @@ -import { DocumentUri } from "monaco-languageclient"; -import {Message} from "vscode-jsonrpc"; +import { DocumentUri } from 'monaco-languageclient'; +import { Message } from 'vscode-jsonrpc'; // The global `Go` is declared by `wasm_exec.js`. // Instead of improving the that file, we use it as-is, // because it is maintained by the Go team and -declare var Go: any +declare var Go: any; // Callbacks defines the functions that the language server calls // and that need to be implemented by the client. @@ -14,24 +14,24 @@ export interface Callbacks { // The function that the language server calls // to write a message object to the client. // The object is a JSON-RPC request/response object - toClient(message: Message): void + toClient(message: Message): void; // The function that the language server calls // to get the code for an imported address, if any - getAddressCode(address: string): string | undefined + getAddressCode(address: string): string | undefined; // The function that the language client calls // to write a message object to the server. // The object is an JSON-RPC request/response object - toServer(error: any, message: Message): void + toServer(error: any, message: Message): void; // The function that the language client can call // to notify the server that the client is closing - onClientClose(): void + onClientClose(): void; // The function that the language server can call // to notify the client that the server is closing - onServerClose(): void + onServerClose(): void; } declare global { @@ -41,133 +41,139 @@ declare global { } export namespace CadenceCheckCompleted { - export const methodName = "cadence/checkCompleted" + export const methodName = 'cadence/checkCompleted'; export interface Params { - uri: DocumentUri - valid: boolean + uri: DocumentUri; + valid: boolean; } } export class CadenceLanguageServer { - - static isLoaded = false - + static isLoaded = false; private static async load() { if (this.isLoaded) { - return + return; } - const wasm = await fetch("./cadence-language-server.wasm") - const go = new Go() - const module = await WebAssembly.instantiateStreaming(wasm, go.importObject) + const wasm = await fetch('./cadence-language-server.wasm'); + const go = new Go(); + const module = await WebAssembly.instantiateStreaming( + wasm, + go.importObject, + ); // For each file descriptor, buffer the written content until reaching a newline - const outputBuffers = new Map() - const decoder = new TextDecoder("utf-8") + const outputBuffers = new Map(); + const decoder = new TextDecoder('utf-8'); // Implementing `writeSync` is mainly just for debugging purposes: // When the language server writes to a file, e.g. standard output or standard error, // then log the output in the console - window['fs'].writeSync = function (fileDescriptor: number, buf: Uint8Array): number { + window['fs'].writeSync = function ( + fileDescriptor: number, + buf: Uint8Array, + ): number { // Get the currently buffered output for the given file descriptor, // or initialize it, if there is no buffered output yet. - let outputBuffer = outputBuffers.get(fileDescriptor) + let outputBuffer = outputBuffers.get(fileDescriptor); if (!outputBuffer) { - outputBuffer = "" + outputBuffer = ''; } // Decode the written data as UTF-8 - outputBuffer += decoder.decode(buf) + outputBuffer += decoder.decode(buf); // If the buffered output contains a newline, // log the contents up to the newline to the console - const nl = outputBuffer.lastIndexOf("\n") + const nl = outputBuffer.lastIndexOf('\n'); if (nl != -1) { - const lines = outputBuffer.substr(0, nl + 1) - console.debug(`(FD ${fileDescriptor}):`, lines) + const lines = outputBuffer.substr(0, nl + 1); + console.debug(`(FD ${fileDescriptor}):`, lines); // keep the remainder - outputBuffer = outputBuffer.substr(nl + 1) + outputBuffer = outputBuffer.substr(nl + 1); } - outputBuffers.set(fileDescriptor, outputBuffer) + outputBuffers.set(fileDescriptor, outputBuffer); - return buf.length - } + return buf.length; + }; - go.run(module.instance) + go.run(module.instance); - this.isLoaded = true + this.isLoaded = true; } - private static functionNamePrefix = "CADENCE_LANGUAGE_SERVER" + private static functionNamePrefix = 'CADENCE_LANGUAGE_SERVER'; private static functionName(name: string): string { - return `__${CadenceLanguageServer.functionNamePrefix}_${name}__` + return `__${CadenceLanguageServer.functionNamePrefix}_${name}__`; } private functionName(name: string): string { - return `__${CadenceLanguageServer.functionNamePrefix}_${this.id}_${name}__` + return `__${CadenceLanguageServer.functionNamePrefix}_${this.id}_${name}__`; } static async create(callbacks: Callbacks): Promise { + await this.load(); - await this.load() - - return new CadenceLanguageServer(callbacks) + return new CadenceLanguageServer(callbacks); } - public readonly id: number - private isClientClosed: boolean + public readonly id: number; + private isClientClosed: boolean; private constructor(callbacks: Callbacks) { - // The language server, written in Go and compiled to WebAssembly, interacts with this JS environment // by calling global functions. There does not seem to be support yet to directly import functions // from the JS environment into the WebAssembly environment - this.id = window[CadenceLanguageServer.functionName('start')]() + this.id = window[CadenceLanguageServer.functionName('start')](); window[this.functionName('toClient')] = (message: string): void => { - callbacks.toClient(JSON.parse(message)) - } + callbacks.toClient(JSON.parse(message)); + }; - window[this.functionName('getAddressCode')] = (address: string): string | undefined => { + window[this.functionName('getAddressCode')] = ( + address: string, + ): string | undefined => { if (!callbacks.getAddressCode) { - return undefined + return undefined; } - return callbacks.getAddressCode(address) - } + return callbacks.getAddressCode(address); + }; window[this.functionName('onServerClose')] = (): void => { if (!callbacks.onServerClose) { - return + return; } - callbacks.onServerClose() - } + callbacks.onServerClose(); + }; callbacks.toServer = (error: any, message: any) => { - window[this.functionName('toServer')](error, JSON.stringify(message)) - } + window[this.functionName('toServer')](error, JSON.stringify(message)); + }; callbacks.onClientClose = () => { if (this.isClientClosed) { - return + return; } - this.isClientClosed = true - window[this.functionName('onClientClose')]() - } + this.isClientClosed = true; + window[this.functionName('onClientClose')](); + }; } - updateCodeGetter(newMethod){ - window[this.functionName('getAddressCode')] = (address: string): string | undefined => { + updateCodeGetter(newMethod) { + window[this.functionName('getAddressCode')] = ( + address: string, + ): string | undefined => { if (!newMethod) { - return undefined + return undefined; } - return newMethod(address) - } + return newMethod(address); + }; } } diff --git a/src/util/mixpanel.ts b/src/util/mixpanel.ts index 36d8e73f..8be986d3 100644 --- a/src/util/mixpanel.ts +++ b/src/util/mixpanel.ts @@ -1,32 +1,28 @@ -import mixpanel from "mixpanel-browser"; -import {Dict} from "mixpanel-browser" +import mixpanel from 'mixpanel-browser'; +import { Dict } from 'mixpanel-browser'; mixpanel.init(process.env.MIXPANEL_TOKEN); -let is_dev = process.env.NODE_ENV === "development"; +let is_dev = process.env.NODE_ENV === 'development'; let actions = { identify(id: string) { - if (is_dev) - return + if (is_dev) return; mixpanel.identify(id); }, alias(id: string) { - if (is_dev) - return + if (is_dev) return; mixpanel.alias(id); }, track(name: string, props: Dict) { - if (is_dev) - return + if (is_dev) return; mixpanel.track(name, { ...props, is_dev }); }, people: { set: (props: Dict) => { - if (is_dev) - return + if (is_dev) return; mixpanel.people?.set(props); - } - } + }, + }, }; export default actions; diff --git a/src/util/onclose.ts b/src/util/onclose.ts index 4d399f6b..240da6b8 100644 --- a/src/util/onclose.ts +++ b/src/util/onclose.ts @@ -1,9 +1,9 @@ -import Mixpanel from "util/mixpanel"; +import Mixpanel from 'util/mixpanel'; export const registerOnCloseSaveMessage = () => { window.onbeforeunload = () => { - Mixpanel.track("Project closed", {}); - return "You have unsaved work in the playground, are you sure you want to exit?"; + Mixpanel.track('Project closed', {}); + return 'You have unsaved work in the playground, are you sure you want to exit?'; }; }; diff --git a/src/util/parser.ts b/src/util/parser.ts index 5c16f77a..cb72e40c 100644 --- a/src/util/parser.ts +++ b/src/util/parser.ts @@ -1,35 +1,36 @@ -export const collapseSpaces = (input: string) => input.replace(/\s+/g, " "); -export const stripNewLines = (input: string) => input.replace(/\r\n|\n|\r/g, " "); +export const collapseSpaces = (input: string) => input.replace(/\s+/g, ' '); +export const stripNewLines = (input: string) => + input.replace(/\r\n|\n|\r/g, ' '); export const generateSchema = (argsDefinition: string) => - argsDefinition - .split(",") - .map((item) => item.replace(/\s*/g, "")) - .filter((item) => item !== ""); + argsDefinition + .split(',') + .map((item) => item.replace(/\s*/g, '')) + .filter((item) => item !== ''); export const stripComments = (code: string) => { - const commentsRegExp = /(\/\*[\s\S]*?\*\/)|(\/\/.*)/g; - return code.replace(commentsRegExp, ""); + const commentsRegExp = /(\/\*[\s\S]*?\*\/)|(\/\/.*)/g; + return code.replace(commentsRegExp, ''); }; export const extract = (code: string, keyWord: string) => { - const noComments = stripComments(code); - const target = collapseSpaces(noComments.replace(/[\n\r]/g, "")); + const noComments = stripComments(code); + const target = collapseSpaces(noComments.replace(/[\n\r]/g, '')); - if (target) { - const regexp = new RegExp(keyWord, "g"); - const match = regexp.exec(target); + if (target) { + const regexp = new RegExp(keyWord, 'g'); + const match = regexp.exec(target); - if (match) { - if (match[1] === "") { - return []; - } - return generateSchema(match[1]); - } + if (match) { + if (match[1] === '') { + return []; + } + return generateSchema(match[1]); } - return []; + } + return []; }; export const extractSigners = (code: string) => { - return extract(code, `(?:prepare\\s*\\(\\s*)([^\\)]*)(?:\\))`); + return extract(code, `(?:prepare\\s*\\(\\s*)([^\\)]*)(?:\\))`); }; diff --git a/src/util/random-hash.ts b/src/util/random-hash.ts index 774516d1..471c0cf7 100644 --- a/src/util/random-hash.ts +++ b/src/util/random-hash.ts @@ -1,11 +1,15 @@ -// @ts-ignore-start -const mb32 = a => (t) => (a+1831565813|0,t=Math.imul(a^a>>>15,1|a),t=t+Math.imul(t^t>>>7,61|t)^t,(t^t>>>14)>>>0)/2**32; +const mb32 = (a) => (t) => + // @ts-ignore + ((a + 1831565813) | 0, + (t = Math.imul(a ^ (a >>> 15), 1 | a)), + (t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t), + (t ^ (t >>> 14)) >>> 0) / + 2 ** 32; export const generateRandomSeed = () => { - return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); -} + return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER); +}; export const generateHash = (seed: number, index: number, maxIndex: number) => { - return (mb32(seed * (index / maxIndex))(index)).toString(); -} -// @ts-ignore-stop + return mb32(seed * (index / maxIndex))(index).toString(); +}; diff --git a/src/util/rng.ts b/src/util/rng.ts index b7833148..03584999 100644 --- a/src/util/rng.ts +++ b/src/util/rng.ts @@ -1,9 +1,9 @@ -const CHARS = "0123456789ABCDEF".split(""); +const CHARS = '0123456789ABCDEF'.split(''); const randChar = (): string => CHARS[~~(Math.random() * CHARS.length)]; const group = (length: number): string => - Array.from({ length }, () => randChar()).join(""); + Array.from({ length }, () => randChar()).join(''); export const uuid = (): string => - [group(8), group(4), group(4), group(4), group(12)].join("-"); + [group(8), group(4), group(4), group(4), group(12)].join('-'); export const mb32 = (a: number) => { let t; @@ -19,7 +19,7 @@ export const mb32 = (a: number) => { }; export const strToSeed = (seed: string): number => { - if (typeof TextEncoder == "undefined") return Math.random() * 32; + if (typeof TextEncoder == 'undefined') return Math.random() * 32; const td = new TextEncoder(); return td.encode(seed).reduce((a, b) => a + b); }; diff --git a/src/util/storage.ts b/src/util/storage.ts index 4337be50..0aaa6de8 100644 --- a/src/util/storage.ts +++ b/src/util/storage.ts @@ -1,9 +1,8 @@ // take in the state for an account, return data for resources explorer export const getStorageData = (state: string = ''): any => { - if (state === '') { - return { storage: {}, paths: {}, types: {}}; - }; + return { storage: {}, paths: {}, types: {} }; + } const storage: { [identifier: string]: string } = {}; const paths: { [identifier: string]: string } = {}; @@ -15,37 +14,46 @@ export const getStorageData = (state: string = ''): any => { for (let key in parsed) { if (!parsed.hasOwnProperty(key)) { continue; - }; + } const tuple = key.split('\u001f'); const [domain, identifier] = tuple; - if (tuple.length === 2 && ['storage', 'public', 'private'].includes(domain)) { + if ( + tuple.length === 2 && + ['storage', 'public', 'private'].includes(domain) + ) { storage[identifier] = parsed[key]; const path = `/${domain}/${identifier}`; paths[identifier] = path; const storageItemType = parsed[key].value?.type || null; types[identifier] = storageItemType; - if (storageItemType === "Link") { + if (storageItemType === 'Link') { const borrowType = parsed[key].value.value.borrowType; - const borrowTypeSplit = borrowType.split("."); + const borrowTypeSplit = borrowType.split('.'); const contractAcctId = borrowTypeSplit[1]; - const contractAddr = `0x0${contractAcctId.substr(contractAcctId.length - 1)}`; + const contractAddr = `0x0${contractAcctId.substr( + contractAcctId.length - 1, + )}`; const contract = borrowTypeSplit[2]; const resourcePart = borrowTypeSplit[3]; - const resource = resourcePart.split("{")[0]; + const resource = resourcePart.split('{')[0]; const rxp = /{([^}]+)}/g; - const foundInterfacesRegEx = rxp.exec(borrowType) + const foundInterfacesRegEx = rxp.exec(borrowType); let interfaces: string[] = []; if (foundInterfacesRegEx) { const foundInterfaces = foundInterfacesRegEx[1]; const fullyQualifiedInterfaces = foundInterfaces.split(','); fullyQualifiedInterfaces.map((fullyQualifiedInterface) => { - interfaces.push(fullyQualifiedInterface.split(".")[2] + "." + fullyQualifiedInterface.split(".")[3]); + interfaces.push( + fullyQualifiedInterface.split('.')[2] + + '.' + + fullyQualifiedInterface.split('.')[3], + ); }); } @@ -54,12 +62,11 @@ export const getStorageData = (state: string = ''): any => { contractAddr: contractAddr, resourceContract: contract, resource: resource, - contractImplementedInterfaces: interfaces + contractImplementedInterfaces: interfaces, }; - }; - }; - }; + } + } + } - return { storage, paths, types, capabilities } - -} + return { storage, paths, types, capabilities }; +}; diff --git a/src/util/templates.ts b/src/util/templates.ts index a237ccca..1ee8c530 100644 --- a/src/util/templates.ts +++ b/src/util/templates.ts @@ -1,6 +1,12 @@ -export const getInterpolatedTemplate = (type: string, contractOwner: string, path: string, contractResource: string, interfaces: string): any => { +export const getInterpolatedTemplate = ( + type: string, + contractOwner: string, + path: string, + contractResource: string, + interfaces: string, +): any => { if (type === 'tx') { - return `// TEMPLATE TRANSACTION + return `// TEMPLATE TRANSACTION // Below, the 'borrowedCapability' constant borrows a capability from a public path // for a given account. The capability is scoped to a given contract and the implemented @@ -15,10 +21,9 @@ let borrowedCapability = getAccount(address) .getCapability(${path}) .borrow<&${contractResource}{${interfaces}}>() ?? panic("Could not borrow the capability") -*/` - +*/`; } else if (type === 'script') { - return `// TEMPLATE SCRIPT + return `// TEMPLATE SCRIPT // Below, the 'borrowedCapability' constant borrows a capability from a public path // for a given account. The capability is scoped to a given contract and the implemented @@ -51,6 +56,6 @@ import ExampleToken from 0x01 ?? panic("Could not borrow Balance capability") return vaultRef.balance - }` - }; + }`; + } }; diff --git a/src/util/url.ts b/src/util/url.ts index feb102ee..76622b3e 100644 --- a/src/util/url.ts +++ b/src/util/url.ts @@ -1,16 +1,19 @@ export const isUUUID = (projectId: string): boolean => { - const regexp = /[\w\d]{8}-([\w\d]{4}-){3}[\w\d]{12}/ - return regexp.test(projectId) -} + const regexp = /[\w\d]{8}-([\w\d]{4}-){3}[\w\d]{12}/; + return regexp.test(projectId); +}; -export const getParams = (url: string): any => { - return url.slice(1).split("&").reduce((acc:any,item: string)=>{ - const [key, value] = item.split("=") - acc[key] = value - return acc - },{}) -} +export const getParams = (url: string): any => { + return url + .slice(1) + .split('&') + .reduce((acc: any, item: string) => { + const [key, value] = item.split('='); + acc[key] = value; + return acc; + }, {}); +}; -export const scriptTypes = ["account", "tx", "script"] +export const scriptTypes = ['account', 'tx', 'script']; -export const LOCAL_PROJECT_ID = "local-project" +export const LOCAL_PROJECT_ID = 'local-project'; diff --git a/src/wasm_exec.js b/src/wasm_exec.js index 9ce6a20c..df63abea 100644 --- a/src/wasm_exec.js +++ b/src/wasm_exec.js @@ -2,553 +2,660 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -"use strict"; +'use strict'; (() => { - const enosys = () => { - const err = new Error("not implemented"); - err.code = "ENOSYS"; - return err; - }; - - if (!globalThis.fs) { - let outputBuf = ""; - globalThis.fs = { - constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused - writeSync(fd, buf) { - outputBuf += decoder.decode(buf); - const nl = outputBuf.lastIndexOf("\n"); - if (nl != -1) { - console.log(outputBuf.substr(0, nl)); - outputBuf = outputBuf.substr(nl + 1); - } - return buf.length; - }, - write(fd, buf, offset, length, position, callback) { - if (offset !== 0 || length !== buf.length || position !== null) { - callback(enosys()); - return; - } - const n = this.writeSync(fd, buf); - callback(null, n); - }, - chmod(path, mode, callback) { callback(enosys()); }, - chown(path, uid, gid, callback) { callback(enosys()); }, - close(fd, callback) { callback(enosys()); }, - fchmod(fd, mode, callback) { callback(enosys()); }, - fchown(fd, uid, gid, callback) { callback(enosys()); }, - fstat(fd, callback) { callback(enosys()); }, - fsync(fd, callback) { callback(null); }, - ftruncate(fd, length, callback) { callback(enosys()); }, - lchown(path, uid, gid, callback) { callback(enosys()); }, - link(path, link, callback) { callback(enosys()); }, - lstat(path, callback) { callback(enosys()); }, - mkdir(path, perm, callback) { callback(enosys()); }, - open(path, flags, mode, callback) { callback(enosys()); }, - read(fd, buffer, offset, length, position, callback) { callback(enosys()); }, - readdir(path, callback) { callback(enosys()); }, - readlink(path, callback) { callback(enosys()); }, - rename(from, to, callback) { callback(enosys()); }, - rmdir(path, callback) { callback(enosys()); }, - stat(path, callback) { callback(enosys()); }, - symlink(path, link, callback) { callback(enosys()); }, - truncate(path, length, callback) { callback(enosys()); }, - unlink(path, callback) { callback(enosys()); }, - utimes(path, atime, mtime, callback) { callback(enosys()); }, - }; - } - - if (!globalThis.process) { - globalThis.process = { - getuid() { return -1; }, - getgid() { return -1; }, - geteuid() { return -1; }, - getegid() { return -1; }, - getgroups() { throw enosys(); }, - pid: -1, - ppid: -1, - umask() { throw enosys(); }, - cwd() { throw enosys(); }, - chdir() { throw enosys(); }, - } - } - - if (!globalThis.crypto) { - throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)"); - } - - if (!globalThis.performance) { - throw new Error("globalThis.performance is not available, polyfill required (performance.now only)"); - } - - if (!globalThis.TextEncoder) { - throw new Error("globalThis.TextEncoder is not available, polyfill required"); - } - - if (!globalThis.TextDecoder) { - throw new Error("globalThis.TextDecoder is not available, polyfill required"); - } - - const encoder = new TextEncoder("utf-8"); - const decoder = new TextDecoder("utf-8"); - - globalThis.Go = class { - constructor() { - this.argv = ["js"]; - this.env = {}; - this.exit = (code) => { - if (code !== 0) { - console.warn("exit code:", code); - } - }; - this._exitPromise = new Promise((resolve) => { - this._resolveExitPromise = resolve; - }); - this._pendingEvent = null; - this._scheduledTimeouts = new Map(); - this._nextCallbackTimeoutID = 1; - - const setInt64 = (addr, v) => { - this.mem.setUint32(addr + 0, v, true); - this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true); - } - - const getInt64 = (addr) => { - const low = this.mem.getUint32(addr + 0, true); - const high = this.mem.getInt32(addr + 4, true); - return low + high * 4294967296; - } - - const loadValue = (addr) => { - const f = this.mem.getFloat64(addr, true); - if (f === 0) { - return undefined; - } - if (!isNaN(f)) { - return f; - } - - const id = this.mem.getUint32(addr, true); - return this._values[id]; - } - - const storeValue = (addr, v) => { - const nanHead = 0x7FF80000; - - if (typeof v === "number" && v !== 0) { - if (isNaN(v)) { - this.mem.setUint32(addr + 4, nanHead, true); - this.mem.setUint32(addr, 0, true); - return; - } - this.mem.setFloat64(addr, v, true); - return; - } - - if (v === undefined) { - this.mem.setFloat64(addr, 0, true); - return; - } - - let id = this._ids.get(v); - if (id === undefined) { - id = this._idPool.pop(); - if (id === undefined) { - id = this._values.length; - } - this._values[id] = v; - this._goRefCounts[id] = 0; - this._ids.set(v, id); - } - this._goRefCounts[id]++; - let typeFlag = 0; - switch (typeof v) { - case "object": - if (v !== null) { - typeFlag = 1; - } - break; - case "string": - typeFlag = 2; - break; - case "symbol": - typeFlag = 3; - break; - case "function": - typeFlag = 4; - break; - } - this.mem.setUint32(addr + 4, nanHead | typeFlag, true); - this.mem.setUint32(addr, id, true); - } - - const loadSlice = (addr) => { - const array = getInt64(addr + 0); - const len = getInt64(addr + 8); - return new Uint8Array(this._inst.exports.mem.buffer, array, len); - } - - const loadSliceOfValues = (addr) => { - const array = getInt64(addr + 0); - const len = getInt64(addr + 8); - const a = new Array(len); - for (let i = 0; i < len; i++) { - a[i] = loadValue(array + i * 8); - } - return a; - } - - const loadString = (addr) => { - const saddr = getInt64(addr + 0); - const len = getInt64(addr + 8); - return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len)); - } - - const timeOrigin = Date.now() - performance.now(); - this.importObject = { - go: { - // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters) - // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported - // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function). - // This changes the SP, thus we have to update the SP used by the imported function. - - // func wasmExit(code int32) - "runtime.wasmExit": (sp) => { - sp >>>= 0; - const code = this.mem.getInt32(sp + 8, true); - this.exited = true; - delete this._inst; - delete this._values; - delete this._goRefCounts; - delete this._ids; - delete this._idPool; - this.exit(code); - }, - - // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32) - "runtime.wasmWrite": (sp) => { - sp >>>= 0; - const fd = getInt64(sp + 8); - const p = getInt64(sp + 16); - const n = this.mem.getInt32(sp + 24, true); - fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n)); - }, - - // func resetMemoryDataView() - "runtime.resetMemoryDataView": (sp) => { - sp >>>= 0; - this.mem = new DataView(this._inst.exports.mem.buffer); - }, - - // func nanotime1() int64 - "runtime.nanotime1": (sp) => { - sp >>>= 0; - setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000); - }, - - // func walltime() (sec int64, nsec int32) - "runtime.walltime": (sp) => { - sp >>>= 0; - const msec = (new Date).getTime(); - setInt64(sp + 8, msec / 1000); - this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true); - }, - - // func scheduleTimeoutEvent(delay int64) int32 - "runtime.scheduleTimeoutEvent": (sp) => { - sp >>>= 0; - const id = this._nextCallbackTimeoutID; - this._nextCallbackTimeoutID++; - this._scheduledTimeouts.set(id, setTimeout( - () => { - this._resume(); - while (this._scheduledTimeouts.has(id)) { - // for some reason Go failed to register the timeout event, log and try again - // (temporary workaround for https://github.com/golang/go/issues/28975) - console.warn("scheduleTimeoutEvent: missed timeout event"); - this._resume(); - } - }, - getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early - )); - this.mem.setInt32(sp + 16, id, true); - }, - - // func clearTimeoutEvent(id int32) - "runtime.clearTimeoutEvent": (sp) => { - sp >>>= 0; - const id = this.mem.getInt32(sp + 8, true); - clearTimeout(this._scheduledTimeouts.get(id)); - this._scheduledTimeouts.delete(id); - }, - - // func getRandomData(r []byte) - "runtime.getRandomData": (sp) => { - sp >>>= 0; - crypto.getRandomValues(loadSlice(sp + 8)); - }, - - // func finalizeRef(v ref) - "syscall/js.finalizeRef": (sp) => { - sp >>>= 0; - const id = this.mem.getUint32(sp + 8, true); - this._goRefCounts[id]--; - if (this._goRefCounts[id] === 0) { - const v = this._values[id]; - this._values[id] = null; - this._ids.delete(v); - this._idPool.push(id); - } - }, - - // func stringVal(value string) ref - "syscall/js.stringVal": (sp) => { - sp >>>= 0; - storeValue(sp + 24, loadString(sp + 8)); - }, - - // func valueGet(v ref, p string) ref - "syscall/js.valueGet": (sp) => { - sp >>>= 0; - const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16)); - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 32, result); - }, - - // func valueSet(v ref, p string, x ref) - "syscall/js.valueSet": (sp) => { - sp >>>= 0; - Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32)); - }, - - // func valueDelete(v ref, p string) - "syscall/js.valueDelete": (sp) => { - sp >>>= 0; - Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16)); - }, - - // func valueIndex(v ref, i int) ref - "syscall/js.valueIndex": (sp) => { - sp >>>= 0; - storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16))); - }, - - // valueSetIndex(v ref, i int, x ref) - "syscall/js.valueSetIndex": (sp) => { - sp >>>= 0; - Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24)); - }, - - // func valueCall(v ref, m string, args []ref) (ref, bool) - "syscall/js.valueCall": (sp) => { - sp >>>= 0; - try { - const v = loadValue(sp + 8); - const m = Reflect.get(v, loadString(sp + 16)); - const args = loadSliceOfValues(sp + 32); - const result = Reflect.apply(m, v, args); - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 56, result); - this.mem.setUint8(sp + 64, 1); - } catch (err) { - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 56, err); - this.mem.setUint8(sp + 64, 0); - } - }, - - // func valueInvoke(v ref, args []ref) (ref, bool) - "syscall/js.valueInvoke": (sp) => { - sp >>>= 0; - try { - const v = loadValue(sp + 8); - const args = loadSliceOfValues(sp + 16); - const result = Reflect.apply(v, undefined, args); - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 40, result); - this.mem.setUint8(sp + 48, 1); - } catch (err) { - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 40, err); - this.mem.setUint8(sp + 48, 0); - } - }, - - // func valueNew(v ref, args []ref) (ref, bool) - "syscall/js.valueNew": (sp) => { - sp >>>= 0; - try { - const v = loadValue(sp + 8); - const args = loadSliceOfValues(sp + 16); - const result = Reflect.construct(v, args); - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 40, result); - this.mem.setUint8(sp + 48, 1); - } catch (err) { - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 40, err); - this.mem.setUint8(sp + 48, 0); - } - }, - - // func valueLength(v ref) int - "syscall/js.valueLength": (sp) => { - sp >>>= 0; - setInt64(sp + 16, parseInt(loadValue(sp + 8).length)); - }, - - // valuePrepareString(v ref) (ref, int) - "syscall/js.valuePrepareString": (sp) => { - sp >>>= 0; - const str = encoder.encode(String(loadValue(sp + 8))); - storeValue(sp + 16, str); - setInt64(sp + 24, str.length); - }, - - // valueLoadString(v ref, b []byte) - "syscall/js.valueLoadString": (sp) => { - sp >>>= 0; - const str = loadValue(sp + 8); - loadSlice(sp + 16).set(str); - }, - - // func valueInstanceOf(v ref, t ref) bool - "syscall/js.valueInstanceOf": (sp) => { - sp >>>= 0; - this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0); - }, - - // func copyBytesToGo(dst []byte, src ref) (int, bool) - "syscall/js.copyBytesToGo": (sp) => { - sp >>>= 0; - const dst = loadSlice(sp + 8); - const src = loadValue(sp + 32); - if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) { - this.mem.setUint8(sp + 48, 0); - return; - } - const toCopy = src.subarray(0, dst.length); - dst.set(toCopy); - setInt64(sp + 40, toCopy.length); - this.mem.setUint8(sp + 48, 1); - }, - - // func copyBytesToJS(dst ref, src []byte) (int, bool) - "syscall/js.copyBytesToJS": (sp) => { - sp >>>= 0; - const dst = loadValue(sp + 8); - const src = loadSlice(sp + 16); - if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) { - this.mem.setUint8(sp + 48, 0); - return; - } - const toCopy = src.subarray(0, dst.length); - dst.set(toCopy); - setInt64(sp + 40, toCopy.length); - this.mem.setUint8(sp + 48, 1); - }, - - "debug": (value) => { - console.log(value); - }, - } - }; - } - - async run(instance) { - if (!(instance instanceof WebAssembly.Instance)) { - throw new Error("Go.run: WebAssembly.Instance expected"); - } - this._inst = instance; - this.mem = new DataView(this._inst.exports.mem.buffer); - this._values = [ // JS values that Go currently has references to, indexed by reference id - NaN, - 0, - null, - true, - false, - globalThis, - this, - ]; - this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id - this._ids = new Map([ // mapping from JS values to reference ids - [0, 1], - [null, 2], - [true, 3], - [false, 4], - [globalThis, 5], - [this, 6], - ]); - this._idPool = []; // unused ids that have been garbage collected - this.exited = false; // whether the Go program has exited - - // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory. - let offset = 4096; - - const strPtr = (str) => { - const ptr = offset; - const bytes = encoder.encode(str + "\0"); - new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes); - offset += bytes.length; - if (offset % 8 !== 0) { - offset += 8 - (offset % 8); - } - return ptr; - }; - - const argc = this.argv.length; - - const argvPtrs = []; - this.argv.forEach((arg) => { - argvPtrs.push(strPtr(arg)); - }); - argvPtrs.push(0); - - const keys = Object.keys(this.env).sort(); - keys.forEach((key) => { - argvPtrs.push(strPtr(`${key}=${this.env[key]}`)); - }); - argvPtrs.push(0); - - const argv = offset; - argvPtrs.forEach((ptr) => { - this.mem.setUint32(offset, ptr, true); - this.mem.setUint32(offset + 4, 0, true); - offset += 8; - }); - - // The linker guarantees global data starts from at least wasmMinDataAddr. - // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr. - const wasmMinDataAddr = 4096 + 8192; - if (offset >= wasmMinDataAddr) { - throw new Error("total length of command line and environment variables exceeds limit"); - } - - this._inst.exports.run(argc, argv); - if (this.exited) { - this._resolveExitPromise(); - } - await this._exitPromise; - } - - _resume() { - if (this.exited) { - throw new Error("Go program has already exited"); - } - this._inst.exports.resume(); - if (this.exited) { - this._resolveExitPromise(); - } - } - - _makeFuncWrapper(id) { - const go = this; - return function () { - const event = { id: id, this: this, args: arguments }; - go._pendingEvent = event; - go._resume(); - return event.result; - }; - } - } + const enosys = () => { + const err = new Error('not implemented'); + err.code = 'ENOSYS'; + return err; + }; + + if (!globalThis.fs) { + let outputBuf = ''; + globalThis.fs = { + constants: { + O_WRONLY: -1, + O_RDWR: -1, + O_CREAT: -1, + O_TRUNC: -1, + O_APPEND: -1, + O_EXCL: -1, + }, // unused + writeSync(fd, buf) { + outputBuf += decoder.decode(buf); + const nl = outputBuf.lastIndexOf('\n'); + if (nl != -1) { + console.log(outputBuf.substr(0, nl)); + outputBuf = outputBuf.substr(nl + 1); + } + return buf.length; + }, + write(fd, buf, offset, length, position, callback) { + if (offset !== 0 || length !== buf.length || position !== null) { + callback(enosys()); + return; + } + const n = this.writeSync(fd, buf); + callback(null, n); + }, + chmod(path, mode, callback) { + callback(enosys()); + }, + chown(path, uid, gid, callback) { + callback(enosys()); + }, + close(fd, callback) { + callback(enosys()); + }, + fchmod(fd, mode, callback) { + callback(enosys()); + }, + fchown(fd, uid, gid, callback) { + callback(enosys()); + }, + fstat(fd, callback) { + callback(enosys()); + }, + fsync(fd, callback) { + callback(null); + }, + ftruncate(fd, length, callback) { + callback(enosys()); + }, + lchown(path, uid, gid, callback) { + callback(enosys()); + }, + link(path, link, callback) { + callback(enosys()); + }, + lstat(path, callback) { + callback(enosys()); + }, + mkdir(path, perm, callback) { + callback(enosys()); + }, + open(path, flags, mode, callback) { + callback(enosys()); + }, + read(fd, buffer, offset, length, position, callback) { + callback(enosys()); + }, + readdir(path, callback) { + callback(enosys()); + }, + readlink(path, callback) { + callback(enosys()); + }, + rename(from, to, callback) { + callback(enosys()); + }, + rmdir(path, callback) { + callback(enosys()); + }, + stat(path, callback) { + callback(enosys()); + }, + symlink(path, link, callback) { + callback(enosys()); + }, + truncate(path, length, callback) { + callback(enosys()); + }, + unlink(path, callback) { + callback(enosys()); + }, + utimes(path, atime, mtime, callback) { + callback(enosys()); + }, + }; + } + + if (!globalThis.process) { + globalThis.process = { + getuid() { + return -1; + }, + getgid() { + return -1; + }, + geteuid() { + return -1; + }, + getegid() { + return -1; + }, + getgroups() { + throw enosys(); + }, + pid: -1, + ppid: -1, + umask() { + throw enosys(); + }, + cwd() { + throw enosys(); + }, + chdir() { + throw enosys(); + }, + }; + } + + if (!globalThis.crypto) { + throw new Error( + 'globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)', + ); + } + + if (!globalThis.performance) { + throw new Error( + 'globalThis.performance is not available, polyfill required (performance.now only)', + ); + } + + if (!globalThis.TextEncoder) { + throw new Error( + 'globalThis.TextEncoder is not available, polyfill required', + ); + } + + if (!globalThis.TextDecoder) { + throw new Error( + 'globalThis.TextDecoder is not available, polyfill required', + ); + } + + const encoder = new TextEncoder('utf-8'); + const decoder = new TextDecoder('utf-8'); + + globalThis.Go = class { + constructor() { + this.argv = ['js']; + this.env = {}; + this.exit = (code) => { + if (code !== 0) { + console.warn('exit code:', code); + } + }; + this._exitPromise = new Promise((resolve) => { + this._resolveExitPromise = resolve; + }); + this._pendingEvent = null; + this._scheduledTimeouts = new Map(); + this._nextCallbackTimeoutID = 1; + + const setInt64 = (addr, v) => { + this.mem.setUint32(addr + 0, v, true); + this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true); + }; + + const getInt64 = (addr) => { + const low = this.mem.getUint32(addr + 0, true); + const high = this.mem.getInt32(addr + 4, true); + return low + high * 4294967296; + }; + + const loadValue = (addr) => { + const f = this.mem.getFloat64(addr, true); + if (f === 0) { + return undefined; + } + if (!isNaN(f)) { + return f; + } + + const id = this.mem.getUint32(addr, true); + return this._values[id]; + }; + + const storeValue = (addr, v) => { + const nanHead = 0x7ff80000; + + if (typeof v === 'number' && v !== 0) { + if (isNaN(v)) { + this.mem.setUint32(addr + 4, nanHead, true); + this.mem.setUint32(addr, 0, true); + return; + } + this.mem.setFloat64(addr, v, true); + return; + } + + if (v === undefined) { + this.mem.setFloat64(addr, 0, true); + return; + } + + let id = this._ids.get(v); + if (id === undefined) { + id = this._idPool.pop(); + if (id === undefined) { + id = this._values.length; + } + this._values[id] = v; + this._goRefCounts[id] = 0; + this._ids.set(v, id); + } + this._goRefCounts[id]++; + let typeFlag = 0; + switch (typeof v) { + case 'object': + if (v !== null) { + typeFlag = 1; + } + break; + case 'string': + typeFlag = 2; + break; + case 'symbol': + typeFlag = 3; + break; + case 'function': + typeFlag = 4; + break; + } + this.mem.setUint32(addr + 4, nanHead | typeFlag, true); + this.mem.setUint32(addr, id, true); + }; + + const loadSlice = (addr) => { + const array = getInt64(addr + 0); + const len = getInt64(addr + 8); + return new Uint8Array(this._inst.exports.mem.buffer, array, len); + }; + + const loadSliceOfValues = (addr) => { + const array = getInt64(addr + 0); + const len = getInt64(addr + 8); + const a = new Array(len); + for (let i = 0; i < len; i++) { + a[i] = loadValue(array + i * 8); + } + return a; + }; + + const loadString = (addr) => { + const saddr = getInt64(addr + 0); + const len = getInt64(addr + 8); + return decoder.decode( + new DataView(this._inst.exports.mem.buffer, saddr, len), + ); + }; + + const timeOrigin = Date.now() - performance.now(); + this.importObject = { + go: { + // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters) + // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported + // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function). + // This changes the SP, thus we have to update the SP used by the imported function. + + // func wasmExit(code int32) + 'runtime.wasmExit': (sp) => { + sp >>>= 0; + const code = this.mem.getInt32(sp + 8, true); + this.exited = true; + delete this._inst; + delete this._values; + delete this._goRefCounts; + delete this._ids; + delete this._idPool; + this.exit(code); + }, + + // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32) + 'runtime.wasmWrite': (sp) => { + sp >>>= 0; + const fd = getInt64(sp + 8); + const p = getInt64(sp + 16); + const n = this.mem.getInt32(sp + 24, true); + fs.writeSync( + fd, + new Uint8Array(this._inst.exports.mem.buffer, p, n), + ); + }, + + // func resetMemoryDataView() + 'runtime.resetMemoryDataView': (sp) => { + sp >>>= 0; + this.mem = new DataView(this._inst.exports.mem.buffer); + }, + + // func nanotime1() int64 + 'runtime.nanotime1': (sp) => { + sp >>>= 0; + setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000); + }, + + // func walltime() (sec int64, nsec int32) + 'runtime.walltime': (sp) => { + sp >>>= 0; + const msec = new Date().getTime(); + setInt64(sp + 8, msec / 1000); + this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true); + }, + + // func scheduleTimeoutEvent(delay int64) int32 + 'runtime.scheduleTimeoutEvent': (sp) => { + sp >>>= 0; + const id = this._nextCallbackTimeoutID; + this._nextCallbackTimeoutID++; + this._scheduledTimeouts.set( + id, + setTimeout( + () => { + this._resume(); + while (this._scheduledTimeouts.has(id)) { + // for some reason Go failed to register the timeout event, log and try again + // (temporary workaround for https://github.com/golang/go/issues/28975) + console.warn('scheduleTimeoutEvent: missed timeout event'); + this._resume(); + } + }, + getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early + ), + ); + this.mem.setInt32(sp + 16, id, true); + }, + + // func clearTimeoutEvent(id int32) + 'runtime.clearTimeoutEvent': (sp) => { + sp >>>= 0; + const id = this.mem.getInt32(sp + 8, true); + clearTimeout(this._scheduledTimeouts.get(id)); + this._scheduledTimeouts.delete(id); + }, + + // func getRandomData(r []byte) + 'runtime.getRandomData': (sp) => { + sp >>>= 0; + crypto.getRandomValues(loadSlice(sp + 8)); + }, + + // func finalizeRef(v ref) + 'syscall/js.finalizeRef': (sp) => { + sp >>>= 0; + const id = this.mem.getUint32(sp + 8, true); + this._goRefCounts[id]--; + if (this._goRefCounts[id] === 0) { + const v = this._values[id]; + this._values[id] = null; + this._ids.delete(v); + this._idPool.push(id); + } + }, + + // func stringVal(value string) ref + 'syscall/js.stringVal': (sp) => { + sp >>>= 0; + storeValue(sp + 24, loadString(sp + 8)); + }, + + // func valueGet(v ref, p string) ref + 'syscall/js.valueGet': (sp) => { + sp >>>= 0; + const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16)); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 32, result); + }, + + // func valueSet(v ref, p string, x ref) + 'syscall/js.valueSet': (sp) => { + sp >>>= 0; + Reflect.set( + loadValue(sp + 8), + loadString(sp + 16), + loadValue(sp + 32), + ); + }, + + // func valueDelete(v ref, p string) + 'syscall/js.valueDelete': (sp) => { + sp >>>= 0; + Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16)); + }, + + // func valueIndex(v ref, i int) ref + 'syscall/js.valueIndex': (sp) => { + sp >>>= 0; + storeValue( + sp + 24, + Reflect.get(loadValue(sp + 8), getInt64(sp + 16)), + ); + }, + + // valueSetIndex(v ref, i int, x ref) + 'syscall/js.valueSetIndex': (sp) => { + sp >>>= 0; + Reflect.set( + loadValue(sp + 8), + getInt64(sp + 16), + loadValue(sp + 24), + ); + }, + + // func valueCall(v ref, m string, args []ref) (ref, bool) + 'syscall/js.valueCall': (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const m = Reflect.get(v, loadString(sp + 16)); + const args = loadSliceOfValues(sp + 32); + const result = Reflect.apply(m, v, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 56, result); + this.mem.setUint8(sp + 64, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 56, err); + this.mem.setUint8(sp + 64, 0); + } + }, + + // func valueInvoke(v ref, args []ref) (ref, bool) + 'syscall/js.valueInvoke': (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const args = loadSliceOfValues(sp + 16); + const result = Reflect.apply(v, undefined, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, result); + this.mem.setUint8(sp + 48, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, err); + this.mem.setUint8(sp + 48, 0); + } + }, + + // func valueNew(v ref, args []ref) (ref, bool) + 'syscall/js.valueNew': (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const args = loadSliceOfValues(sp + 16); + const result = Reflect.construct(v, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, result); + this.mem.setUint8(sp + 48, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, err); + this.mem.setUint8(sp + 48, 0); + } + }, + + // func valueLength(v ref) int + 'syscall/js.valueLength': (sp) => { + sp >>>= 0; + setInt64(sp + 16, parseInt(loadValue(sp + 8).length)); + }, + + // valuePrepareString(v ref) (ref, int) + 'syscall/js.valuePrepareString': (sp) => { + sp >>>= 0; + const str = encoder.encode(String(loadValue(sp + 8))); + storeValue(sp + 16, str); + setInt64(sp + 24, str.length); + }, + + // valueLoadString(v ref, b []byte) + 'syscall/js.valueLoadString': (sp) => { + sp >>>= 0; + const str = loadValue(sp + 8); + loadSlice(sp + 16).set(str); + }, + + // func valueInstanceOf(v ref, t ref) bool + 'syscall/js.valueInstanceOf': (sp) => { + sp >>>= 0; + this.mem.setUint8( + sp + 24, + loadValue(sp + 8) instanceof loadValue(sp + 16) ? 1 : 0, + ); + }, + + // func copyBytesToGo(dst []byte, src ref) (int, bool) + 'syscall/js.copyBytesToGo': (sp) => { + sp >>>= 0; + const dst = loadSlice(sp + 8); + const src = loadValue(sp + 32); + if ( + !(src instanceof Uint8Array || src instanceof Uint8ClampedArray) + ) { + this.mem.setUint8(sp + 48, 0); + return; + } + const toCopy = src.subarray(0, dst.length); + dst.set(toCopy); + setInt64(sp + 40, toCopy.length); + this.mem.setUint8(sp + 48, 1); + }, + + // func copyBytesToJS(dst ref, src []byte) (int, bool) + 'syscall/js.copyBytesToJS': (sp) => { + sp >>>= 0; + const dst = loadValue(sp + 8); + const src = loadSlice(sp + 16); + if ( + !(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray) + ) { + this.mem.setUint8(sp + 48, 0); + return; + } + const toCopy = src.subarray(0, dst.length); + dst.set(toCopy); + setInt64(sp + 40, toCopy.length); + this.mem.setUint8(sp + 48, 1); + }, + + debug: (value) => { + console.log(value); + }, + }, + }; + } + + async run(instance) { + if (!(instance instanceof WebAssembly.Instance)) { + throw new Error('Go.run: WebAssembly.Instance expected'); + } + this._inst = instance; + this.mem = new DataView(this._inst.exports.mem.buffer); + this._values = [ + // JS values that Go currently has references to, indexed by reference id + NaN, + 0, + null, + true, + false, + globalThis, + this, + ]; + this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id + this._ids = new Map([ + // mapping from JS values to reference ids + [0, 1], + [null, 2], + [true, 3], + [false, 4], + [globalThis, 5], + [this, 6], + ]); + this._idPool = []; // unused ids that have been garbage collected + this.exited = false; // whether the Go program has exited + + // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory. + let offset = 4096; + + const strPtr = (str) => { + const ptr = offset; + const bytes = encoder.encode(str + '\0'); + new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes); + offset += bytes.length; + if (offset % 8 !== 0) { + offset += 8 - (offset % 8); + } + return ptr; + }; + + const argc = this.argv.length; + + const argvPtrs = []; + this.argv.forEach((arg) => { + argvPtrs.push(strPtr(arg)); + }); + argvPtrs.push(0); + + const keys = Object.keys(this.env).sort(); + keys.forEach((key) => { + argvPtrs.push(strPtr(`${key}=${this.env[key]}`)); + }); + argvPtrs.push(0); + + const argv = offset; + argvPtrs.forEach((ptr) => { + this.mem.setUint32(offset, ptr, true); + this.mem.setUint32(offset + 4, 0, true); + offset += 8; + }); + + // The linker guarantees global data starts from at least wasmMinDataAddr. + // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr. + const wasmMinDataAddr = 4096 + 8192; + if (offset >= wasmMinDataAddr) { + throw new Error( + 'total length of command line and environment variables exceeds limit', + ); + } + + this._inst.exports.run(argc, argv); + if (this.exited) { + this._resolveExitPromise(); + } + await this._exitPromise; + } + + _resume() { + if (this.exited) { + throw new Error('Go program has already exited'); + } + this._inst.exports.resume(); + if (this.exited) { + this._resolveExitPromise(); + } + } + + _makeFuncWrapper(id) { + const go = this; + return function () { + const event = { id: id, this: this, args: arguments }; + go._pendingEvent = event; + go._resume(); + return event.result; + }; + } + }; })();