├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── go.mod ├── go.sum ├── goplus.org ├── .eslintrc.json ├── .gitignore ├── README.md ├── apis │ └── play.ts ├── components │ ├── Centered │ │ ├── index.tsx │ │ └── style.module.scss │ ├── Code │ │ ├── Block │ │ │ ├── index.tsx │ │ │ ├── style.module.scss │ │ │ └── syntax-highlight-style.ts │ │ ├── Editor │ │ │ ├── index.tsx │ │ │ └── style.module.scss │ │ └── Run │ │ │ ├── index.tsx │ │ │ └── style.module.scss │ ├── CodeForMD │ │ └── index.tsx │ ├── EnsureReady.tsx │ ├── Footer │ │ ├── index.tsx │ │ └── style.module.scss │ ├── Header │ │ ├── GitHubIcon │ │ │ ├── index.tsx │ │ │ └── style.module.scss │ │ ├── Mobile │ │ │ ├── index.tsx │ │ │ └── style.module.scss │ │ ├── Pc │ │ │ ├── index.tsx │ │ │ └── style.module.scss │ │ ├── common.ts │ │ └── index.tsx │ ├── Home │ │ ├── Applications │ │ │ ├── 2d-games.jpg │ │ │ ├── data-processing.jpg │ │ │ ├── dev-ops-tools.jpg │ │ │ ├── index.tsx │ │ │ └── style.module.scss │ │ ├── Guide │ │ │ ├── bg.jpg │ │ │ ├── index.tsx │ │ │ └── style.module.scss │ │ ├── Intro │ │ │ ├── examples.ts │ │ │ ├── examples │ │ │ │ ├── basic.xgo │ │ │ │ ├── error.xgo │ │ │ │ ├── hello.xgo │ │ │ │ ├── listmap.xgo │ │ │ │ ├── range.xgo │ │ │ │ ├── rational.xgo │ │ │ │ └── slice.xgo │ │ │ ├── index.tsx │ │ │ └── style.module.scss │ │ └── KeyFeatures │ │ │ ├── index.tsx │ │ │ └── style.module.scss │ ├── Icon │ │ ├── DownArrow.tsx │ │ ├── Logo.tsx │ │ ├── QiniuLogo.tsx │ │ └── UpArrow.tsx │ ├── Layout │ │ ├── index.tsx │ │ └── style.module.scss │ ├── TextWrapper │ │ ├── index.tsx │ │ └── style.module.scss │ └── UI │ │ ├── Button │ │ ├── index.tsx │ │ └── style.module.scss │ │ ├── IconLoading │ │ ├── index.tsx │ │ └── style.module.scss │ │ ├── LinkButton │ │ ├── index.tsx │ │ └── style.module.scss │ │ └── Select │ │ ├── arrow.svg │ │ ├── index.tsx │ │ └── style.module.scss ├── hooks │ ├── index.ts │ └── url.ts ├── next-env.d.ts ├── next.config.js ├── package-lock.json ├── package.json ├── pages │ ├── _app.tsx │ ├── dev │ │ ├── README.md │ │ └── code.tsx │ ├── download │ │ ├── index.tsx │ │ └── style.module.scss │ ├── global.scss │ └── index.tsx ├── public │ ├── favicon.svg │ └── qiniu_doll.png ├── tsconfig.json ├── types │ └── index.d.ts ├── utils │ ├── index.scss │ ├── index.ts │ └── variables.module.scss ├── vercel.json └── widgets │ ├── README.md │ ├── build.js │ ├── dev.html │ ├── entries │ ├── code.tsx │ ├── footer.tsx │ └── header.tsx │ ├── global │ ├── .gitignore │ ├── loader.ts │ ├── polyfill.ts │ └── tsconfig.json │ ├── host.scss │ └── widget.tsx └── playground ├── AUTHORS ├── CONTRIBUTING.md ├── CONTRIBUTORS ├── Dockerfile ├── LICENSE ├── Makefile ├── PATENTS ├── README.md ├── app.yaml ├── cache.go ├── client.go ├── codereview.cfg ├── deploy ├── deploy.json ├── go_trigger.json └── playground_trigger.json ├── edit.go ├── edit.html ├── enable-fake-time.patch ├── examples ├── basic.txt ├── error.txt ├── hello.txt ├── listmap.txt ├── range.txt ├── rational.txt └── slice.txt ├── fake_fs.lst ├── fmt.go ├── fmt_test.go ├── goplus.go ├── internal ├── gcpdial │ ├── gcpdial.go │ └── gcpdialtool │ │ └── gcpdialtool.go ├── internal.go └── internal_test.go ├── logger.go ├── main.go ├── play.go ├── play_test.go ├── playground ├── sandbox.go ├── sandbox ├── Dockerfile ├── Dockerfile.gvisor ├── Makefile ├── cloud-init.yaml ├── konlet.yaml ├── metrics.go ├── sandbox.go ├── sandbox.tf ├── sandbox_test.go └── sandboxtypes │ └── types.go ├── sandbox_test.go ├── server.go ├── server_test.go ├── share.go ├── static ├── favicon.svg ├── godoc.css ├── gopher.png ├── jquery-linedtextarea.js ├── playground-embed.js ├── playground.js └── style.css ├── store.go ├── tests.go ├── txtar.go ├── txtar_test.go └── vet.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | playground/share/ 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - "1.14" 4 | script: 5 | - go install -v ./... 6 | - go test -race -coverprofile=coverage.txt -covermode=atomic ./... 7 | after_success: 8 | - bash <(curl -s https://codecov.io/bash) 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # https://xgo.dev 2 | 3 | [![LICENSE](https://img.shields.io/github/license/goplus/www.svg)](https://github.com/goplus/www/blob/master/LICENSE) 4 | [![Build Status](https://travis-ci.org/goplus/www.png?branch=master)](https://travis-ci.org/goplus/www) 5 | [![Go Report Card](https://goreportcard.com/badge/github.com/goplus/www)](https://goreportcard.com/report/github.com/goplus/www) 6 | [![GitHub release](https://img.shields.io/github/v/tag/goplus/www.svg?label=release)](https://github.com/goplus/www/releases) 7 | [![Coverage Status](https://codecov.io/gh/goplus/www/branch/master/graph/badge.svg)](https://codecov.io/gh/goplus/www) 8 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/goplus/www 2 | 3 | go 1.12 4 | 5 | require ( 6 | cloud.google.com/go v0.75.0 7 | contrib.go.opencensus.io/exporter/prometheus v0.3.0 8 | contrib.go.opencensus.io/exporter/stackdriver v0.13.8 9 | github.com/aws/aws-sdk-go v1.37.0 10 | github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b 11 | github.com/google/go-cmp v0.5.5 12 | github.com/shurcooL/webdavfs v0.0.0-20190527155401-0680c3c63e3c 13 | go.opencensus.io v0.23.0 14 | golang.org/x/mod v0.5.1 15 | golang.org/x/net v0.0.0-20210119194325-5f4716e94777 16 | golang.org/x/tools v0.1.7 17 | google.golang.org/api v0.37.0 18 | google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506 19 | google.golang.org/grpc v1.39.0 // indirect 20 | ) 21 | 22 | replace ( 23 | cloud.google.com/go => cloud.google.com/go v0.58.0 24 | cloud.google.com/go/bigquery => cloud.google.com/go/bigquery v1.8.0 25 | github.com/golang/protobuf => github.com/golang/protobuf v1.4.2 26 | golang.org/x/mod => golang.org/x/mod v0.3.0 27 | golang.org/x/net => golang.org/x/net v0.0.0-20200602114024-627f9648deb9 28 | golang.org/x/sys => golang.org/x/sys v0.0.0-20200523222454-059865788121 29 | golang.org/x/tools => golang.org/x/tools v0.0.0-20200619180055-7c47624df98f 30 | google.golang.org/api => google.golang.org/api v0.28.0 31 | google.golang.org/genproto => google.golang.org/genproto v0.0.0-20200619004808-3e7fca5c55db 32 | google.golang.org/grpc => google.golang.org/grpc v1.29.1 33 | ) 34 | -------------------------------------------------------------------------------- /goplus.org/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals", 3 | "rules": { 4 | "indent": ["error", 2], 5 | "semi": ["error", "never"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /goplus.org/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env.local 29 | .env.development.local 30 | .env.test.local 31 | .env.production.local 32 | 33 | # vercel 34 | .vercel 35 | 36 | # widgets 37 | /public/widgets 38 | .widget 39 | -------------------------------------------------------------------------------- /goplus.org/README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | ``` 12 | 13 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 14 | 15 | You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file. 16 | 17 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`. 18 | 19 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. 20 | 21 | ## Learn More 22 | 23 | To learn more about Next.js, take a look at the following resources: 24 | 25 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 26 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 27 | 28 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 29 | 30 | ## Deploy on Vercel 31 | 32 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 33 | 34 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 35 | -------------------------------------------------------------------------------- /goplus.org/apis/play.ts: -------------------------------------------------------------------------------- 1 | const host = 'https://seplay.xgo.dev' 2 | 3 | export type CompileOptions = { 4 | body: string 5 | /** Whether client supports vet response in a /compile request */ 6 | withVet?: boolean 7 | } 8 | 9 | export type CompileEvent = { 10 | /** Time to wait before printing Message */ 11 | Delay: number 12 | Kind: 'stdout' | 'stderr' 13 | Message: string 14 | } 15 | 16 | export type CompileResult = { 17 | Errors: string 18 | Events: CompileEvent[] | null 19 | IsTest: boolean 20 | /** Exit Code */ 21 | Status: number 22 | /** Number of `--- FAIL ...` */ 23 | TestsFailed: number 24 | /** 25 | * VetErrors, if non-empty, contains any vet errors. It is 26 | * only populated if request.WithVet was true. 27 | */ 28 | VetErrors?: string 29 | /** 30 | * VetOK reports whether vet ran & passsed. It is only 31 | * populated if request.WithVet was true. Only one of 32 | * VetErrors or VetOK can be non-zero. 33 | */ 34 | VetOK?: boolean 35 | } 36 | 37 | export async function compile({ body, withVet = false }: CompileOptions): Promise { 38 | const resp = await fetch(`${host}/compile`, { 39 | method: 'POST', 40 | mode: 'cors', 41 | body: new URLSearchParams({ 42 | body, 43 | withVet: withVet + '' 44 | }), 45 | }) 46 | if (!resp.ok) { 47 | throw new Error(`Status ${resp.status}`) 48 | } 49 | return resp.json() 50 | } 51 | 52 | export async function share(code: string) { 53 | const resp = await fetch(`${host}/share`, { 54 | method: 'POST', 55 | mode: 'cors', 56 | body: code 57 | }) 58 | if (!resp.ok) { 59 | throw new Error(`Status ${resp.status}`) 60 | } 61 | const hash = await resp.text() 62 | return `${host}/p/${hash}` 63 | } 64 | -------------------------------------------------------------------------------- /goplus.org/components/Centered/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { PropsWithChildren } from 'react' 2 | 3 | import styles from './style.module.scss' 4 | 5 | export default function Centered({ children }: PropsWithChildren<{}>) { 6 | return
{children}
7 | } 8 | -------------------------------------------------------------------------------- /goplus.org/components/Centered/style.module.scss: -------------------------------------------------------------------------------- 1 | @import '~utils/index.scss'; 2 | 3 | .centered { 4 | @include centered; 5 | 6 | @include mobile { 7 | padding: 16px; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /goplus.org/components/Code/Block/style.module.scss: -------------------------------------------------------------------------------- 1 | @import '~utils/index.scss'; 2 | 3 | .wrapper { 4 | position: relative; 5 | min-height: 28px + (20px * 2); // opBtn height + padding top + padding bottom 6 | line-height: 1.5; 7 | 8 | p { 9 | margin: 0; 10 | } 11 | } 12 | 13 | .code { 14 | font-family: monospace; 15 | white-space: pre; 16 | overflow-x: auto; 17 | background-color: #FAFAFA !important; 18 | border: 1px solid #E5E5E5; 19 | } 20 | 21 | .hasRunResult .codeSegment:last-child .code { 22 | border-bottom-left-radius: 0; 23 | border-bottom-right-radius: 0; 24 | } 25 | 26 | @include pc { 27 | .code { 28 | border-top-width: 0; 29 | border-bottom-width: 0; 30 | } 31 | .codeSegment:first-child .code { 32 | border-top-left-radius: 8px; 33 | border-top-right-radius: 8px; 34 | border-top-width: 1px; 35 | } 36 | .codeSegment:last-child .code { 37 | border-bottom-left-radius: 8px; 38 | border-bottom-right-radius: 8px; 39 | border-bottom-width: 1px; 40 | } 41 | .halfCode:not(.hasDoc) { 42 | width: 50%; 43 | } 44 | } 45 | 46 | @include mobile { 47 | .code { 48 | border-radius: 8px; 49 | } 50 | } 51 | 52 | @include pc { 53 | .codeSegment { 54 | display: flex; 55 | flex-direction: row; 56 | 57 | .doc, .code { 58 | flex: 1 1; 59 | } 60 | 61 | .doc { 62 | margin-bottom: 1em; 63 | padding: 0 40px 6px 0; 64 | } 65 | 66 | .code { 67 | padding: 0 20px 6px; 68 | } 69 | 70 | &:first-child { 71 | .doc, .code { 72 | padding-top: 20px; 73 | } 74 | } 75 | 76 | &:last-child { 77 | .doc { 78 | margin-bottom: 0; 79 | } 80 | .doc, .code { 81 | padding-bottom: 20px; 82 | } 83 | } 84 | } 85 | 86 | .hasDoc .codeSegment { 87 | .doc, .code { 88 | flex: 0 0 50%; 89 | } 90 | } 91 | } 92 | 93 | @include mobile { 94 | .hasDoc { 95 | padding: 10px; 96 | border-radius: 4px; 97 | border: 1px solid #F0F0F0; 98 | 99 | .code, .doc:not(:empty) { 100 | margin-bottom: 1em; 101 | } 102 | 103 | .codeSegment:last-child .code { 104 | margin-bottom: 0; 105 | } 106 | } 107 | 108 | .code { 109 | padding: 20px; 110 | } 111 | } 112 | 113 | .ops { 114 | display: flex; 115 | } 116 | 117 | .ops { 118 | position: absolute; 119 | right: 20px; 120 | top: 20px; 121 | visibility: hidden; 122 | } 123 | 124 | .wrapper:hover .ops { 125 | visibility: visible; 126 | } 127 | 128 | .opBtn { 129 | flex: 0 0 auto; 130 | width: 28px; 131 | height: 28px; 132 | padding: 0; 133 | display: flex; 134 | align-items: center; 135 | justify-content: center; 136 | 137 | color: #666; 138 | background-color: #FAFAFA; 139 | border: 1px solid #BFBFBF; 140 | border-radius: 4px; 141 | transition: background-color .2s, color .2s, border-color .2s; 142 | 143 | &:disabled { 144 | cursor: not-allowed; 145 | } 146 | 147 | &:hover:not(:disabled) { 148 | background-color: #F5F5F5; 149 | } 150 | 151 | &:active:not(:disabled) { 152 | background-color: #F0F0F0; 153 | } 154 | 155 | &.highlight { 156 | color: #2c84ff; 157 | border-color: #2c84ff; 158 | } 159 | 160 | + .opBtn { 161 | margin-left: 16px; 162 | } 163 | } 164 | 165 | @include pc { 166 | .hasDoc .runResult { 167 | margin-left: 50%; 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /goplus.org/components/Code/Block/syntax-highlight-style.ts: -------------------------------------------------------------------------------- 1 | const syntaxHighlightStyle = { 2 | "code[class*=\"language-\"]": { 3 | "color": "#393A34", 4 | "fontFamily": "inherit", 5 | "fontSize": "inherit", 6 | "borderRadius": "initial", 7 | "backgroundColor": "initial", 8 | "padding": "0", 9 | "direction": "ltr", 10 | "textAlign": "left", 11 | "whiteSpace": "pre", 12 | "wordSpacing": "normal", 13 | "wordBreak": "normal", 14 | "MozTabSize": "4", 15 | "OTabSize": "4", 16 | "tabSize": "4", 17 | "WebkitHyphens": "none", 18 | "MozHyphens": "none", 19 | "msHyphens": "none", 20 | "hyphens": "none" 21 | }, 22 | "code[class*=\"language-\"]::-moz-selection": { 23 | "background": "#b3d4fc" 24 | }, 25 | "code[class*=\"language-\"] ::-moz-selection": { 26 | "background": "#b3d4fc" 27 | }, 28 | "code[class*=\"language-\"]::selection": { 29 | "background": "#b3d4fc" 30 | }, 31 | "code[class*=\"language-\"] ::selection": { 32 | "background": "#b3d4fc" 33 | }, 34 | ":not(pre) > code[class*=\"language-\"]": { 35 | "padding": ".2em", 36 | "paddingTop": "1px", 37 | "paddingBottom": "1px", 38 | "background": "#f8f8f8", 39 | "border": "1px solid #dddddd" 40 | }, 41 | "key": { 42 | "color": "#a71d5d", 43 | "fontWeight": "bolder" 44 | }, 45 | "keyword": { 46 | "color": "#a71d5d", 47 | "fontWeight": "bolder" 48 | }, 49 | "attr-name": { 50 | "color": "#0086b3" 51 | }, 52 | "selector": {}, 53 | "comment": { 54 | "color": "#969896", 55 | "fontFamily": "inherit", 56 | "fontStyle": "italic" 57 | }, 58 | "block-comment": { 59 | "color": "#969896", 60 | "fontFamily": "inherit", 61 | "fontStyle": "italic" 62 | }, 63 | "function-name": { 64 | "color": "#63a35c" 65 | }, 66 | "class-name": { 67 | "color": "#63a35c" 68 | }, 69 | "doctype": { 70 | "color": "#333333" 71 | }, 72 | "substr": { 73 | "color": "#333333" 74 | }, 75 | "namespace": { 76 | "color": "#63a35c" 77 | }, 78 | "builtin": { 79 | "color": "#333333" 80 | }, 81 | "entity": { 82 | "color": "#0086b3" 83 | }, 84 | "bullet": { 85 | "color": "#0086b3" 86 | }, 87 | "code": { 88 | "color": "#333333" 89 | }, 90 | "addition": { 91 | "color": "#55a532" 92 | }, 93 | "regex": { 94 | "color": "#333333" 95 | }, 96 | "symbol": { 97 | "color": "#0086b3" 98 | }, 99 | "variable": { 100 | "color": "#df5000" 101 | }, 102 | "url": { 103 | "color": "#0366d6" 104 | }, 105 | "selector-attr": { 106 | "color": "#a71d5d" 107 | }, 108 | "selector-pseudo": {}, 109 | "type": { 110 | "color": "#a71d5d" 111 | }, 112 | "string": { 113 | "color": "#df5000" 114 | }, 115 | "quote": { 116 | "color": "#df5000" 117 | }, 118 | "tag": { 119 | "color": "#333333" 120 | }, 121 | "deletion": { 122 | "color": "#bd2c00" 123 | }, 124 | "title": { 125 | "color": "#795da3" 126 | }, 127 | "section": { 128 | "color": "#63a35c" 129 | }, 130 | "meta-keyword": { 131 | "color": "#333333" 132 | }, 133 | "meta": { 134 | "color": "#969896" 135 | }, 136 | "italic": { 137 | "fontStyle": "italic" 138 | }, 139 | "bold": { 140 | "fontWeight": "bolder" 141 | }, 142 | "function": { 143 | "color": "#333333" 144 | }, 145 | "number": { 146 | "color": "#333333" 147 | } 148 | } 149 | 150 | export default syntaxHighlightStyle 151 | -------------------------------------------------------------------------------- /goplus.org/components/Code/Editor/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Code Editor for XGo (with "Run" button) 3 | * @desc Edit & run xgo code 4 | */ 5 | 6 | import React, { ReactNode, useEffect, useRef, useState } from 'react' 7 | import Editor, { EditorProps, Monaco, loader } from '@monaco-editor/react' 8 | import { editor } from 'monaco-editor/esm/vs/editor/editor.api' 9 | 10 | import { cns } from 'utils' 11 | import { useMobile } from 'hooks' 12 | import Button from 'components/UI/Button' 13 | import IconLoading from 'components/UI/IconLoading' 14 | import { useCodeRun, RunResult } from '../Run' 15 | import styles from './style.module.scss' 16 | 17 | function getMonacoOptions(isMobile: boolean) { 18 | const scrollbarSize = isMobile ? 4 : 8 19 | const monacoOptions: EditorProps['options'] = { 20 | lineNumbers: 'off', 21 | fontSize: 16, 22 | minimap: { enabled: false }, 23 | folding: false, 24 | lineDecorationsWidth: 0, 25 | scrollbar: { 26 | vertical: 'auto', 27 | horizontalScrollbarSize: scrollbarSize, 28 | verticalScrollbarSize: scrollbarSize 29 | }, 30 | scrollBeyondLastLine: false, 31 | overviewRulerLanes: 0 32 | } 33 | return monacoOptions 34 | } 35 | 36 | const editorBackground = '#3F4450' 37 | 38 | const theme: editor.IStandaloneThemeData = { 39 | base: 'vs-dark', 40 | inherit: true, 41 | rules: [], 42 | colors: { 43 | 'editor.background': editorBackground, 44 | 'editor.lineHighlightBackground': '#b8b5ae18' 45 | } 46 | } 47 | 48 | export interface Props { 49 | code: string 50 | runImmediately?: boolean 51 | footerExtra?: ReactNode 52 | className?: string 53 | editorClassName?: string 54 | } 55 | 56 | loader.config({ 57 | paths: { 58 | vs: 'https://static.gopluscdn.com/libs/monaco-editor/0.28.1/min/vs' 59 | } 60 | }) 61 | 62 | export default function CodeEditor({ 63 | code: codeFromProps, 64 | runImmediately = false, 65 | footerExtra, 66 | className, 67 | editorClassName 68 | }: Props) { 69 | const isMobile = useMobile() 70 | const [code, setCode] = useState(codeFromProps) 71 | 72 | const { result, loading: loadingResult, run } = useCodeRun(code) 73 | const [editorReady, setEditorReady] = useState(false) 74 | const hasRunResult = result != null 75 | 76 | const runImmediatelyRef = useRef(runImmediately) 77 | runImmediatelyRef.current = runImmediately 78 | const runRef = useRef(run) 79 | runRef.current = run 80 | 81 | useEffect(() => { 82 | setCode(codeFromProps) 83 | if (runImmediatelyRef.current) runRef.current(codeFromProps) 84 | }, [codeFromProps]) 85 | 86 | className = cns( 87 | styles.wrapper, 88 | hasRunResult && styles.hasRunResult, 89 | editorReady && styles.editorReady, 90 | className 91 | ) 92 | 93 | function handleEditorMount(_: unknown, monaco: Monaco) { 94 | const themeName = 'xgo' 95 | monaco.editor.defineTheme(themeName, theme) 96 | monaco.editor.setTheme(themeName) 97 | setEditorReady(true) 98 | } 99 | 100 | return ( 101 |
102 | setCode(v ?? '')} 107 | options={getMonacoOptions(isMobile)} 108 | onMount={handleEditorMount} 109 | loading="" 110 | /> 111 |
112 | 113 | Loading Editor... 114 |
115 | 116 |
117 |
{footerExtra}
118 | 119 |
120 |
121 | ) 122 | } 123 | -------------------------------------------------------------------------------- /goplus.org/components/Code/Editor/style.module.scss: -------------------------------------------------------------------------------- 1 | @import '~utils/index.scss'; 2 | 3 | .wrapper {} 4 | 5 | .editorLoading, .editor { 6 | width: 100%; 7 | height: 300px; 8 | padding: 20px; 9 | overflow: hidden; 10 | border-radius: 8px; 11 | border: 1px solid #E5E5E5; 12 | background-color: var(--editor-background); 13 | } 14 | 15 | .editorLoading { 16 | display: flex; 17 | align-items: center; 18 | justify-content: center; 19 | color: #D4D4D4; 20 | font-size: 14px; 21 | 22 | .iconLoading { 23 | margin-right: 12px; 24 | } 25 | } 26 | 27 | .editor { 28 | display: none; 29 | } 30 | 31 | .editorReady { 32 | .editorLoading { 33 | display: none; 34 | } 35 | .editor { 36 | display: block; 37 | } 38 | } 39 | 40 | .hasRunResult .editor, .hasRunResult .editorLoading { 41 | border-radius: 8px 8px 0 0; 42 | } 43 | 44 | .footer { 45 | margin-top: 24px; 46 | display: flex; 47 | justify-content: space-between; 48 | 49 | @include mobile { 50 | margin-top: 16px; 51 | flex-direction: column; 52 | align-items: flex-end; 53 | 54 | .extra { 55 | margin-bottom: 16px; 56 | width: 100%; 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /goplus.org/components/Code/Run/index.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Run result for xgo code 3 | * @desc includes states like running, error, success, etc 4 | */ 5 | 6 | import React, { PropsWithChildren, ReactNode, useCallback, useEffect, useRef, useState } from 'react' 7 | 8 | import { compile, CompileResult } from 'apis/play' 9 | import { cns } from 'utils' 10 | import IconLoading from 'components/UI/IconLoading' 11 | 12 | import styles from './style.module.scss' 13 | 14 | export interface Props { 15 | result: ReactNode 16 | autoScroll?: boolean 17 | className?: string 18 | } 19 | 20 | /** Display run result for xgo code */ 21 | export function RunResult({ 22 | result, 23 | autoScroll = true, 24 | className 25 | }: Props) { 26 | const runResultRef = useRef(null) 27 | 28 | const autoScrollRef = useRef(autoScroll) 29 | autoScrollRef.current = autoScroll 30 | 31 | useEffect(() => { 32 | if (!autoScrollRef.current) return 33 | runResultRef.current?.scrollIntoView({ 34 | behavior: 'smooth', 35 | block: 'nearest' 36 | }) 37 | }, [result]) 38 | 39 | if (result == null) return null 40 | 41 | return ( 42 |
 43 |       {result}
 44 |     
45 | ) 46 | } 47 | 48 | /** Control running process of xgo code & outputs result */ 49 | export function useCodeRun(code: string) { 50 | const [loading, setLoading] = useState(false) 51 | const [result, setResult] = useState(null) 52 | 53 | function startWaiting() { 54 | setLoading(true) 55 | setResult(Waiting for remote server...) 56 | } 57 | 58 | function endWaiting(result: ReactNode) { 59 | setLoading(false) 60 | setResult(result) 61 | } 62 | 63 | const run = useCallback(async (currentCode: string = code) => { 64 | startWaiting() 65 | 66 | let result: CompileResult 67 | try { 68 | result = await compile({ body: currentCode }) 69 | } catch (e: unknown) { 70 | const message = `Request failed: ${e && (e as any).message || 'Unkown'}` 71 | endWaiting({message}) 72 | return 73 | } 74 | endWaiting( 75 | result.Errors 76 | ? <> 77 | Error encountered: 78 |

{result.Errors}

79 | 80 | : 81 | ) 82 | }, [code]) 83 | 84 | return { 85 | loading, 86 | result, 87 | run 88 | } 89 | } 90 | 91 | function Events({ events }: { events: CompileResult['Events'] }) { 92 | if (events == null) return No output. 93 | return

{events.map(e => e.Message).join('\n')}

94 | } 95 | 96 | function ExitStatus({ status }: { status: CompileResult['Status'] }) { 97 | return Program exited with {status}. 98 | } 99 | 100 | function EventsWithStatus({ result }: { result: CompileResult }) { 101 | return <> 102 | 103 | 104 | 105 | } 106 | 107 | function Tip(props: PropsWithChildren<{}>) { 108 | return

109 | } 110 | 111 | function Warning(props: PropsWithChildren<{}>) { 112 | return

113 | } 114 | 115 | function Error(props: PropsWithChildren<{}>) { 116 | return

117 | } 118 | 119 | function Loading({ children, ...restProps }: PropsWithChildren<{}>) { 120 | return ( 121 |

122 | 123 | {children} 124 |

125 | ) 126 | } 127 | -------------------------------------------------------------------------------- /goplus.org/components/Code/Run/style.module.scss: -------------------------------------------------------------------------------- 1 | @import '~utils/index.scss'; 2 | 3 | .runResult { 4 | position: relative; 5 | margin: 0; 6 | 7 | max-height: 136px; 8 | @include mobile { 9 | max-height: 125px; 10 | } 11 | 12 | padding: 20px; 13 | overflow-x: auto; 14 | background-color: #F5F5F5; 15 | border: 1px solid #E5E5E5; 16 | border-top: none; 17 | border-radius: 0 0 8px 8px; 18 | 19 | p { 20 | margin: 0; 21 | } 22 | 23 | > p + p { 24 | margin-top: 12px; 25 | } 26 | } 27 | 28 | .tip { 29 | color: #666; 30 | } 31 | 32 | .warning { 33 | color: #FA8C16; 34 | } 35 | 36 | .error { 37 | color: #EF4149; 38 | } 39 | 40 | .loading { 41 | display: flex; 42 | align-items: center; 43 | 44 | .iconLoading { 45 | flex: 0 0 auto; 46 | margin-right: 12px; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /goplus.org/components/CodeForMD/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactNode, isValidElement, Children } from 'react' 2 | 3 | import CodeBlock from 'components/Code/Block' 4 | 5 | export interface Props { 6 | inline?: boolean 7 | className?: string 8 | children?: ReactNode 9 | } 10 | 11 | export default function CodeForMD({ inline = false, children, className }: Props) { 12 | if (inline) { 13 | return {children} 14 | } 15 | const language = getLang(className) 16 | const code = getSourceCode(children) 17 | return 18 | } 19 | 20 | const classNamePattern = /^language-(.*)$/ 21 | 22 | function getLang(className: string | undefined) { 23 | if (className == null) return undefined 24 | const matched = classNamePattern.exec(className) 25 | if (matched == null) return undefined 26 | return matched[1] 27 | } 28 | 29 | function getSourceCode(children: ReactNode) { 30 | const sources = Children.map(children, element => { 31 | while (isValidElement(element)) { 32 | element = element.props.children 33 | } 34 | return typeof element === 'string' ? element : '' 35 | }) 36 | return (sources || []).join('') 37 | } 38 | -------------------------------------------------------------------------------- /goplus.org/components/EnsureReady.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 在内容就绪(一般即 mounted)前隐藏内容的容器 3 | * @desc 因为 React SSR/SSG 的限制,在客户端首次 render 时其状态值需要与 SSR/SSG 时一致,所以首次 4 | * render 结果可能是不正确的;如在移动端对于是否 mobile 的判断可能是错的(初始状态值为 `false`) 5 | * 此时会有一个内容的闪烁,即从 PC 端视图变成移动端视图;对于这种情况,将页面使用 `EnsureReady` 包裹, 6 | * 确保首次渲染的内容不可见,界面更加稳定,对用户的体验会更好 7 | */ 8 | 9 | import React, { ReactNode, useEffect, useState } from 'react' 10 | 11 | export interface Props { 12 | children: ReactNode 13 | extra?: Array> 14 | } 15 | 16 | export default function EnsureReady({ children, extra = [] }: Props) { 17 | const [ready, setReady] = useState(false) 18 | useEffect(() => { 19 | if (extra.length === 0) { 20 | setReady(true) 21 | return 22 | } 23 | Promise.all(extra).then(() => { 24 | setReady(true) 25 | }) 26 | }, [extra]) 27 | return
{children}
28 | } 29 | -------------------------------------------------------------------------------- /goplus.org/components/Footer/index.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @next/next/no-img-element */ 2 | 3 | import React from 'react' 4 | 5 | import QiniuLogo from 'components/Icon/QiniuLogo' 6 | import imgDoll from 'public/qiniu_doll.png' 7 | 8 | import styles from './style.module.scss' 9 | 10 | export default function Footer(props: { className?: string }) { 11 | const className = [styles.footer, props.className].filter(Boolean).join(' ') 12 | return ( 13 |
14 |
15 | Qiniu Doll Logo 16 |
17 | 31 |
32 | Powered by 33 | 34 | 35 | 36 |
37 |
38 | ) 39 | } 40 | 41 | function ArrowIcon() { 42 | return ( 43 | 44 | 45 | 46 | ) 47 | } 48 | -------------------------------------------------------------------------------- /goplus.org/components/Footer/style.module.scss: -------------------------------------------------------------------------------- 1 | @import '~utils/index.scss'; 2 | 3 | @include pc { 4 | 5 | .footer { 6 | @include centered; 7 | 8 | position: relative; 9 | display: flex; 10 | align-items: center; 11 | padding: 0; 12 | font-size: 16px; 13 | line-height: 1.5; 14 | } 15 | 16 | .qiniuDoll { 17 | padding-top: 10px; 18 | img { 19 | display: block; 20 | } 21 | } 22 | 23 | .links { 24 | margin-left: 170px; 25 | flex-grow: 1; 26 | } 27 | 28 | .links a { 29 | position: relative; 30 | margin-right: 81px; 31 | } 32 | 33 | .links a:hover { 34 | color: #2c84ff; 35 | } 36 | 37 | .links a::after { 38 | content: ' '; 39 | position: absolute; 40 | top: 50%; 41 | right: -40px; 42 | width: 1px; 43 | height: 20px; 44 | transform: translateY(-50%); 45 | background: #e5e5e5; 46 | } 47 | 48 | .links a:last-child::after { 49 | content: none; 50 | } 51 | 52 | .arrow { 53 | display: none; 54 | } 55 | 56 | .powerBy { 57 | display: flex; 58 | align-items: center; 59 | } 60 | 61 | .powerBy span { 62 | margin-right: 12px; 63 | } 64 | 65 | } 66 | 67 | @include mobile { 68 | .qiniuDoll { 69 | display: none; 70 | } 71 | 72 | .links a { 73 | display: flex; 74 | padding: 0 16px; 75 | height: 48px; 76 | align-items: center; 77 | justify-content: space-between; 78 | } 79 | 80 | .arrow { 81 | margin-left: 16px; 82 | } 83 | 84 | .powerBy { 85 | height: 80px; 86 | display: flex; 87 | align-items: center; 88 | justify-content: center; 89 | 90 | span { 91 | font-size: 16px; 92 | color: #666; 93 | margin-right: 8px; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /goplus.org/components/Header/GitHubIcon/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | export default function GitHubIcon() { 4 | return ( 5 | 6 | 7 | 8 | ) 9 | } -------------------------------------------------------------------------------- /goplus.org/components/Header/GitHubIcon/style.module.scss: -------------------------------------------------------------------------------- 1 | .icon { 2 | fill: #666; 3 | } -------------------------------------------------------------------------------- /goplus.org/components/Header/Mobile/index.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @next/next/no-img-element */ 2 | /* eslint-disable @next/next/no-html-link-for-pages */ 3 | 4 | import React, { useState } from 'react' 5 | 6 | import { NavItemInfo, navItems } from '../common' 7 | import GitHubIcon from '../GitHubIcon' 8 | import Logo from '../../Icon/Logo' 9 | import styles from './style.module.scss' 10 | 11 | export default function Header() { 12 | const [expanded, setExpanded] = useState(false) 13 | 14 | function handleExpandBtnClick() { 15 | setExpanded(v => !v) 16 | } 17 | 18 | const overlay = ( 19 |
20 | {navItems.map((item, i) => )} 21 |
22 | ) 23 | 24 | return ( 25 |
26 |
27 | 28 | 29 | 30 |
31 | 32 | 33 | 34 | 38 |
39 |
40 | {overlay} 41 |
42 | ) 43 | } 44 | 45 | function NavItem({ children, href, isBlank }: NavItemInfo) { 46 | return ( 47 |
  • 48 | {children} 49 |
  • 50 | ) 51 | } 52 | 53 | interface OperationIconProps { 54 | visible: boolean 55 | } 56 | 57 | function MenuIcon({ visible }: OperationIconProps) { 58 | return ( 59 | 60 | 61 | 62 | ) 63 | } 64 | 65 | function CloseIcon({ visible }: OperationIconProps) { 66 | return ( 67 | 68 | 69 | 70 | ) 71 | } 72 | -------------------------------------------------------------------------------- /goplus.org/components/Header/Mobile/style.module.scss: -------------------------------------------------------------------------------- 1 | @import '~utils/index.scss'; 2 | 3 | $operation-area-size: 40px; 4 | 5 | .header { 6 | top: 0; 7 | position: sticky; 8 | z-index: 11; 9 | background-color: white; 10 | } 11 | 12 | .main { 13 | height: $mobile-header-height; 14 | padding: 0 6px 0 16px; 15 | display: flex; 16 | justify-content: space-between; 17 | align-items: center; 18 | } 19 | 20 | .logoLink { 21 | display: flex; 22 | height: $operation-area-size; 23 | align-items: center; 24 | } 25 | 26 | .operations { 27 | display: flex; 28 | align-items: center; 29 | } 30 | 31 | .operations > * { 32 | flex: 0 0 auto; 33 | display: flex; 34 | width: $operation-area-size; 35 | height: $operation-area-size; 36 | align-items: center; 37 | justify-content: center; 38 | 39 | svg { 40 | fill: #666; 41 | &:active { 42 | fill: #333; 43 | } 44 | } 45 | } 46 | 47 | .githubLink { 48 | text-decoration: none; 49 | } 50 | 51 | .expandBtn { 52 | position: relative; 53 | border: none; 54 | background: none; 55 | 56 | svg { 57 | position: absolute; 58 | left: 50%; 59 | top: 50%; 60 | transform: translateX(-50%) translateY(-50%); 61 | transition: opacity .2s .1s; 62 | 63 | &.invisible { 64 | transition: opacity .3s; 65 | opacity: 0; 66 | fill: #666; 67 | } 68 | } 69 | } 70 | 71 | .overlay { 72 | position: absolute; 73 | width: 100%; 74 | padding: 12px; 75 | background-color: white; 76 | visibility: hidden; 77 | opacity: 0; 78 | transition: opacity .2s, visibility 0s .3s; 79 | 80 | &.visible { 81 | opacity: 1; 82 | visibility: visible; 83 | transition: opacity .2s, visibility 0s; 84 | } 85 | } 86 | 87 | .navItem { 88 | list-style: none; 89 | } 90 | 91 | .navLink { 92 | display: block; 93 | padding: 0 12px; 94 | line-height: 48px; 95 | border-radius: 4px; 96 | font-size: 16px; 97 | color: #000; 98 | 99 | &:active { 100 | color: #2c84ff; 101 | background-color: rgba(#2c84ff, 0.1); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /goplus.org/components/Header/Pc/index.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable @next/next/no-html-link-for-pages */ 2 | 3 | import React from 'react' 4 | 5 | import { useUrl } from 'hooks/url' 6 | import { NavItemInfo, navItems } from '../common' 7 | import GitHubIcon from '../GitHubIcon' 8 | import Logo from '../../Icon/Logo' 9 | import styles from './style.module.scss' 10 | 11 | export default function Nav() { 12 | return ( 13 |
    14 |
    15 | 16 | 17 | 18 |
    19 | {navItems.map((item, index) => ( 20 | 21 | ))} 22 | 23 | 24 | 25 |
    26 |
    27 |
    28 | ) 29 | } 30 | 31 | function NavItem({ href, isBlank, children }: NavItemInfo) { 32 | const urlStr = useUrl() 33 | const currentUrl = urlStr != null ? new URL(urlStr) : null 34 | const itemUrl = new URL(href) 35 | // TODO: for tutorial, we may want to compare host instead of host + path 36 | const selected = currentUrl != null && currentUrl.host === itemUrl.host && currentUrl.pathname === itemUrl.pathname 37 | return ( 38 | 39 | {children} 40 | 41 | ) 42 | } 43 | -------------------------------------------------------------------------------- /goplus.org/components/Header/Pc/style.module.scss: -------------------------------------------------------------------------------- 1 | @import '~utils/index.scss'; 2 | 3 | .header { 4 | position: sticky; 5 | top: 0px; 6 | z-index: 11; 7 | background-color: white; 8 | } 9 | 10 | .nav { 11 | @include centered; 12 | 13 | display: flex; 14 | justify-content: space-between; 15 | align-items: center; 16 | height: 72px; 17 | padding: 0; 18 | margin: auto; 19 | } 20 | 21 | .links { 22 | display: flex; 23 | justify-content: space-between; 24 | align-items: center; 25 | } 26 | 27 | .links .linkItem { 28 | font-size: 16px; 29 | margin: 0 24px; 30 | } 31 | 32 | .links .linkItem:hover { 33 | color: #2c84ff; 34 | } 35 | 36 | .links a:last-child { 37 | margin-right: 0; 38 | line-height: 1; 39 | } 40 | 41 | .links .selected { 42 | position: relative; 43 | color: #2c84ff; 44 | line-height: 24px; 45 | } 46 | 47 | .links .selected:hover { 48 | color: #2c84ff; 49 | } 50 | 51 | .links .selected::after { 52 | content: ' '; 53 | position: absolute; 54 | left: 50%; 55 | bottom: -24px; 56 | transform: translateX(-50%); 57 | width: 32px; 58 | height: 2px; 59 | background: #2c84ff; 60 | } 61 | 62 | .githubLink { 63 | svg { 64 | transition: all 0.3s; 65 | fill: #666; 66 | &:hover { 67 | fill: #333; 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /goplus.org/components/Header/common.ts: -------------------------------------------------------------------------------- 1 | import { ReactNode } from 'react' 2 | import { getOrigin } from 'utils' 3 | 4 | export interface NavItemInfo { 5 | children: ReactNode 6 | href: string 7 | isBlank: boolean 8 | } 9 | 10 | export const navItems: NavItemInfo[] = [ 11 | { 12 | children: 'Overview', 13 | href: getOrigin(), 14 | isBlank: false 15 | }, 16 | { 17 | children: 'Tutorial', 18 | href: 'https://tutorial.xgo.dev', 19 | isBlank: false 20 | }, 21 | { 22 | children: 'Download', 23 | href: getOrigin() + '/download', 24 | isBlank: false 25 | }, 26 | { 27 | children: 'Playground', 28 | href: 'https://play.xgo.dev', 29 | isBlank: true 30 | }, 31 | { 32 | children: 'Contributing', 33 | href: 'https://github.com/goplus/gop#contributing', 34 | isBlank: true 35 | }, 36 | { 37 | children: 'IDE Plugins', 38 | href: 'https://github.com/goplus/gop#ide-plugins', 39 | isBlank: true 40 | } 41 | ] 42 | -------------------------------------------------------------------------------- /goplus.org/components/Header/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import { useMobile } from '../../hooks' 4 | import PcHeader from './Pc' 5 | import MobileHeader from './Mobile' 6 | 7 | export default function Header() { 8 | if (useMobile()) return 9 | return 10 | } 11 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Applications/2d-games.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goplus/www/842da442b416aafed7dbb789d5702488362f2aad/goplus.org/components/Home/Applications/2d-games.jpg -------------------------------------------------------------------------------- /goplus.org/components/Home/Applications/data-processing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goplus/www/842da442b416aafed7dbb789d5702488362f2aad/goplus.org/components/Home/Applications/data-processing.jpg -------------------------------------------------------------------------------- /goplus.org/components/Home/Applications/dev-ops-tools.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goplus/www/842da442b416aafed7dbb789d5702488362f2aad/goplus.org/components/Home/Applications/dev-ops-tools.jpg -------------------------------------------------------------------------------- /goplus.org/components/Home/Applications/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import gamesPic from './2d-games.jpg' 4 | import dataProcessingPic from './data-processing.jpg' 5 | import devOpsToolsPic from './dev-ops-tools.jpg' 6 | 7 | import styles from './style.module.scss' 8 | 9 | export default function Applications() { 10 | return ( 11 |
    12 |

    Applications written in XGo

    13 |
    14 | 19 | 24 | 29 |
    30 |
    31 | ) 32 | } 33 | 34 | interface CardProps { 35 | title: string 36 | pic: string 37 | link: string 38 | } 39 | 40 | function Card({ pic, title, link }: CardProps) { 41 | return ( 42 | 43 |
    44 |
    45 |

    {title}

    46 | 47 |
    48 |
    49 | ) 50 | } 51 | 52 | function IconArrow() { 53 | return ( 54 | 55 | 56 | 57 | ) 58 | } 59 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Applications/style.module.scss: -------------------------------------------------------------------------------- 1 | @import '~utils/index.scss'; 2 | 3 | .section { 4 | @include centered; 5 | 6 | padding: 48px 0 72px; 7 | @include mobile { 8 | padding: 40px 16px 16px; 9 | } 10 | } 11 | 12 | .title { 13 | @include section-title; 14 | } 15 | 16 | .cards { 17 | display: grid; 18 | grid-template-columns: 1fr 1fr 1fr; 19 | gap: 40px; 20 | 21 | @include mobile { 22 | grid-template-columns: 1fr; 23 | } 24 | } 25 | 26 | .card { 27 | display: flex; 28 | flex-direction: column; 29 | 30 | border: 1px solid #E5EAF4; 31 | border-radius: 16px; 32 | overflow: hidden; 33 | 34 | transition: box-shadow .3s; 35 | &:hover { 36 | box-shadow: 0px 15px 35px rgba(0, 0, 0, 0.08); 37 | } 38 | 39 | .pic { 40 | padding-bottom: 66.7%; 41 | background-size: cover; 42 | background-position: center; 43 | } 44 | 45 | .footer { 46 | height: 72px; 47 | padding: 0 16px 0 24px; 48 | display: flex; 49 | flex-direction: row; 50 | align-items: center; 51 | justify-content: space-between; 52 | 53 | border-top: 1px solid #E5EAF4; 54 | 55 | @include mobile { 56 | height: 66px; 57 | padding: 0 16px 0 22px; 58 | } 59 | 60 | .cardTitle { 61 | font-size: 24px; 62 | line-height: 32px; 63 | 64 | @include mobile { 65 | font-size: 22px; 66 | line-height: 30px; 67 | } 68 | } 69 | 70 | .iconArrow { 71 | color: #2c84ff; 72 | width: 24px; 73 | height: 24px; 74 | 75 | @include mobile { 76 | width: 22px; 77 | height: 22px; 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Guide/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goplus/www/842da442b416aafed7dbb789d5702488362f2aad/goplus.org/components/Home/Guide/bg.jpg -------------------------------------------------------------------------------- /goplus.org/components/Home/Guide/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import LinkButton from 'components/UI/LinkButton' 4 | 5 | import styles from './style.module.scss' 6 | 7 | export default function Guide() { 8 | return ( 9 |
    10 |
    11 |

    Get Started with XGo

    12 |

    Enable everyone to become a builder of the world

    13 |
    14 | 15 | Quick Start 16 | 17 | 18 | Install XGo 19 | 20 |
    21 |
    22 |
    23 | ) 24 | } 25 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Guide/style.module.scss: -------------------------------------------------------------------------------- 1 | @import '~utils/index.scss'; 2 | 3 | .wrapper { 4 | @include centered; 5 | 6 | height: 354px; 7 | margin-top: 48px; 8 | padding: 90px 96px; 9 | display: flex; 10 | flex-direction: row; 11 | align-items: center; 12 | 13 | @include pc { 14 | border-radius: 16px; 15 | background-image: url('./bg.jpg'); 16 | background-size: cover; 17 | } 18 | 19 | @include mobile { 20 | height: auto; 21 | margin-top: 40px; 22 | padding: 80px 25px; 23 | 24 | background-color: #F8FAFA; 25 | } 26 | } 27 | 28 | .content { 29 | width: 100%; 30 | } 31 | 32 | .title { 33 | margin: 0; 34 | font-size: 40px; 35 | line-height: 48px; 36 | 37 | @include mobile { 38 | text-align: center; 39 | font-size: 28px; 40 | line-height: 36px; 41 | } 42 | } 43 | 44 | .slogan { 45 | margin-top: 16px; 46 | font-size: 18px; 47 | line-height: 26px; 48 | color: #666; 49 | 50 | @include mobile { 51 | text-align: center; 52 | font-size: 14px; 53 | line-height: 22px; 54 | } 55 | } 56 | 57 | .btnsWrap { 58 | display: flex; 59 | margin-top: 36px; 60 | 61 | @include mobile { 62 | flex-direction: column; 63 | align-items: center; 64 | } 65 | 66 | & > :not(:first-child) { 67 | @include pc { 68 | margin-left: 20px; 69 | } 70 | @include mobile { 71 | margin-top: 16px; 72 | } 73 | } 74 | } 75 | 76 | .btn { 77 | width: 178px; 78 | } 79 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Intro/examples.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Examples for Intro 3 | * @todo Use the same resource with `playground/examples/` 4 | */ 5 | 6 | import basic from './examples/basic.xgo' 7 | import error from './examples/error.xgo' 8 | import hello from './examples/hello.xgo' 9 | import listmap from './examples/listmap.xgo' 10 | import range from './examples/range.xgo' 11 | import rational from './examples/rational.xgo' 12 | import slice from './examples/slice.xgo' 13 | 14 | const examples = [ 15 | { name: 'Hello, XGo', code: hello }, 16 | { name: 'XGo Basic', code: basic }, 17 | { name: 'Error wrap', code: error }, 18 | { name: 'List/Map comprehension', code: listmap }, 19 | { name: 'Range', code: range }, 20 | { name: 'Rational', code: rational }, 21 | { name: 'Slice literal', code: slice } 22 | ] 23 | 24 | export default examples 25 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Intro/examples/basic.xgo: -------------------------------------------------------------------------------- 1 | println "Hello, XGo" 2 | 3 | println 1r<<129 4 | println 1/3r+2/7r*2 5 | 6 | arr := [1, 3, 5, 7, 11, 13, 17, 19] 7 | println arr 8 | println [x*x for x <- arr, x > 3] 9 | 10 | m := {"Hi": 1, "XGo": 2} 11 | println m 12 | println {v: k for k, v <- m} 13 | println [k for k, _ <- m] 14 | println [v for v <- m] 15 | 16 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Intro/examples/error.xgo: -------------------------------------------------------------------------------- 1 | import ( 2 | "strconv" 3 | ) 4 | 5 | func add(x, y string) (int, error) { 6 | return strconv.atoi(x)? + strconv.atoi(y)?, nil 7 | } 8 | 9 | func addSafe(x, y string) int { 10 | return strconv.atoi(x)?:0 + strconv.atoi(y)?:0 11 | } 12 | 13 | // Error handling 14 | // We reinvent the error handling specification in XGo. We call them ErrWrap expressions: 15 | 16 | // expr! // panic if err 17 | // expr? // return if err 18 | // expr?:defval // use defval if err 19 | 20 | println `add("100", "23"):`, add("100", "23")! 21 | 22 | sum, err := add("10", "abc") 23 | println `add("10", "abc"):`, sum, err 24 | 25 | println `addSafe("10", "abc"):`, addSafe("10", "abc") 26 | 27 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Intro/examples/hello.xgo: -------------------------------------------------------------------------------- 1 | languages := [ 2 | "C", 3 | "Go", 4 | "Python", 5 | "JavaScript", 6 | ] 7 | 8 | echo "XGo :=", languages.join(" * "), "+ Scratch" 9 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Intro/examples/listmap.xgo: -------------------------------------------------------------------------------- 1 | a := [x*x for x <- [1, 3, 5, 7, 11]] 2 | println a 3 | b := [x*x for x <- [1, 3, 5, 7, 11], x > 3] 4 | println b 5 | c := [i+v for i, v <- [1, 3, 5, 7, 11], i%2 == 1] 6 | println c 7 | d := [k+","+s for k, s <- {"Hello": "xsw", "Hi": "XGo"}] 8 | println d 9 | 10 | arr := [1, 2, 3, 4, 5, 6] 11 | e := [[a, b] for a <- arr, a < b for b <- arr, b > 2] 12 | println e 13 | 14 | x := {x: i for i, x <- [1, 3, 5, 7, 11]} 15 | println x 16 | y := {x: i for i, x <- [1, 3, 5, 7, 11], i%2 == 1} 17 | println y 18 | z := {v: k for k, v <- {1: "Hello", 3: "Hi", 5: "xsw", 7: "XGo"}, k > 3} 19 | println z 20 | 21 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Intro/examples/range.xgo: -------------------------------------------------------------------------------- 1 | a := [1, 3, 5, 7, 11] 2 | b := [x*x for x <- a, x > 3] 3 | println b // output: [25 49 121] 4 | 5 | mapData := {"Hi": 1, "Hello": 2, "XGo": 3} 6 | reversedMap := {v: k for k, v <- mapData} 7 | println reversedMap // output: map[1:Hi 2:Hello 3:XGo] 8 | 9 | sum := 0 10 | for x <- [1, 3, 5, 7, 11, 13, 17], x > 3 { 11 | sum += x 12 | } 13 | println sum 14 | 15 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Intro/examples/rational.xgo: -------------------------------------------------------------------------------- 1 | a := 1r << 65 // bigint, large than int64 2 | b := 4/5r // bigrat 3 | c := b - 1/3r + 3*1/2r 4 | println a, b, c 5 | 6 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Intro/examples/slice.xgo: -------------------------------------------------------------------------------- 1 | // in Go we do: 2 | a := []float64{1, 2, 3.4} 3 | println a 4 | 5 | // in XGo we do: 6 | b := [1, 2, 3.4] 7 | println b 8 | 9 | //slice literal 10 | c := [1, 3.4] // []float64 11 | printf "%#v %T\n", c, c 12 | 13 | d := [1] // []int 14 | printf "%#v %T\n", d, d 15 | 16 | e := [1+2i, "xsw"] // []interface{} 17 | printf "%#v %T\n", e, e 18 | 19 | f := [1, 3.4, 3+4i] // []complex128 20 | printf "%#v %T\n", f, f 21 | 22 | g := [5+6i] // []complex128 23 | printf "%#v %T\n", g, g 24 | 25 | h := ["xsw", 3] // []interface{} 26 | printf "%#v %T\n", h, h 27 | 28 | empty := [] // []interface{} 29 | printf "%#v %T\n", empty, empty 30 | 31 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Intro/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | 3 | import Logo from 'components/Icon/Logo' 4 | import CodeEditor from 'components/Code/Editor' 5 | import Select, { Option } from 'components/UI/Select' 6 | import LinkButton from 'components/UI/LinkButton' 7 | import { getOrigin } from 'utils' 8 | 9 | import examples from './examples' 10 | import styles from './style.module.scss' 11 | 12 | export default function Intro() { 13 | return ( 14 |
    15 |
    16 | 17 |
    18 |
    XGo := C * Go * Python * JavaScript + Scratch
    19 |
    20 | The first AI-native programming language that integrates software engineering into a unified whole 21 |
    22 |
    23 | 24 | Get Started 25 | 26 | 27 | Download 28 | 29 |
    30 |

    Try XGo

    31 | 32 |
    33 | ) 34 | } 35 | 36 | function CodeExamples() { 37 | const [codeName, setCodeName] = useState(examples[0].name) 38 | const code = examples.find(e => e.name === codeName)?.code ?? '' 39 | 40 | const codeSelect = ( 41 | 46 | ) 47 | 48 | return ( 49 | 56 | ) 57 | } 58 | 59 | function IconArrowRight() { 60 | return ( 61 | 62 | 63 | 64 | ) 65 | } 66 | -------------------------------------------------------------------------------- /goplus.org/components/Home/Intro/style.module.scss: -------------------------------------------------------------------------------- 1 | @import '~utils/index.scss'; 2 | 3 | .section { 4 | @include centered; 5 | 6 | display: flex; 7 | flex-direction: column; 8 | align-items: center; 9 | margin: auto; 10 | padding-top: 72px; 11 | padding-bottom: 48px; 12 | 13 | @include mobile { 14 | padding: 40px 16px 0; 15 | } 16 | } 17 | 18 | .logo { 19 | display: flex; 20 | margin-bottom: 24px; 21 | 22 | svg { 23 | width: 128px; 24 | height: auto; 25 | } 26 | 27 | @include mobile { 28 | margin-bottom: 20px; 29 | svg { 30 | width: 100px; 31 | } 32 | } 33 | } 34 | 35 | .slogan { 36 | text-align: center; 37 | font-size: 28px; 38 | line-height: 38px; 39 | 40 | @include mobile { 41 | font-size: 22px; 42 | line-height: 34px; 43 | margin: 0 9px; 44 | } 45 | } 46 | 47 | .sloganDesc { 48 | text-align: center; 49 | font-size: 16px; 50 | line-height: 28px; 51 | margin-top: 8px; 52 | 53 | @include mobile { 54 | font-size: 14px; 55 | line-height: 24px; 56 | margin-top: 4px; 57 | margin-left: 16px; 58 | margin-right: 16px; 59 | } 60 | } 61 | 62 | .btnsWrap { 63 | display: flex; 64 | margin: 48px 0; 65 | 66 | @include mobile { 67 | flex-direction: column; 68 | margin: 40px 0; 69 | } 70 | 71 | & > :not(:first-child) { 72 | @include pc { 73 | margin-left: 24px; 74 | } 75 | @include mobile { 76 | margin-top: 16px; 77 | } 78 | } 79 | } 80 | 81 | .iconArrowRight { 82 | margin-left: 20px; 83 | } 84 | 85 | .title { 86 | @include section-title; 87 | margin: 32px 0 48px; 88 | 89 | @include mobile { 90 | margin: 16px 0 24px; 91 | } 92 | } 93 | 94 | .codeEditorWrapper { 95 | width: 1024px; 96 | font-size: 16px; 97 | 98 | @include mobile { 99 | width: 100%; 100 | margin-bottom: 16px; 101 | } 102 | } 103 | 104 | .codeEditor { 105 | height: 268px; 106 | 107 | @include pc { 108 | resize: vertical; 109 | } 110 | @include mobile { 111 | height: 220px; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /goplus.org/components/Home/KeyFeatures/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactMarkdown from 'react-markdown' 3 | import rehypeRaw from 'rehype-raw' 4 | 5 | import TextWrapper from '../../TextWrapper' 6 | 7 | import styles from './style.module.scss' 8 | 9 | // Copied from https://github.com/goplus/gop/blob/main/README.md#key-features-of-go 10 | // with doc link address normalized 11 | const content = ` 12 | * Approaching natural language expression and intuitive (see [How XGo simplifies Go's expressions](https://github.com/goplus/gop/blob/main/README.md#how-go-simplifies-gos-expressions)). 13 | * Smallest but Turing-complete syntax set in best practices (see [The XGo Mini Specification](https://github.com/goplus/gop/blob/main/doc/spec-mini.md)). 14 | * Fully compatible with [Go](https://github.com/golang/go) and can mix Go/XGo code in the same package (see [The XGo Full Specification](https://github.com/goplus/gop/blob/main/doc/spec.md) and [Go/XGo Hybrid Programming](https://github.com/goplus/gop/blob/main/doc/docs.md#gogo-hybrid-programming)). 15 | * Integrating with the C ecosystem including Python and providing limitless possibilities based on [LLGo](https://github.com/goplus/llgo) (see [Importing C/C++ and Python libraries](https://github.com/goplus/gop/blob/main/README.md#importing-cc-and-python-libraries)). 16 | * Does not support DSL (Domain-Specific Languages), but supports SDF (Specific Domain Friendliness) (see [XGo Classfiles](https://github.com/goplus/gop/blob/main/doc/classfile.md) and [Domain Text Literal](https://github.com/goplus/gop/blob/main/doc/domian-text-lit.md)). 17 | ` 18 | 19 | export default function KeyFeatures() { 20 | return ( 21 |
    22 |

    Key Features of XGo

    23 | 24 | {content} 25 | 26 |
    27 | ) 28 | } 29 | -------------------------------------------------------------------------------- /goplus.org/components/Home/KeyFeatures/style.module.scss: -------------------------------------------------------------------------------- 1 | @import '~utils/index.scss'; 2 | 3 | .section { 4 | display: flex; 5 | flex-direction: column; 6 | align-items: center; 7 | padding: 48px 0 72px; 8 | background-color: #F9FAFB; 9 | 10 | @include mobile { 11 | padding: 40px 16px 16px; 12 | background: none; 13 | } 14 | } 15 | 16 | .title { 17 | @include section-title; 18 | } -------------------------------------------------------------------------------- /goplus.org/components/Icon/DownArrow.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | export default function ArrowDown(props: SVGProps) { 4 | return ( 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ) 14 | } -------------------------------------------------------------------------------- /goplus.org/components/Icon/Logo.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Logo for XGo 3 | */ 4 | 5 | import React, { SVGProps } from 'react' 6 | 7 | export default function Logo(props: SVGProps) { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | ) 15 | } 16 | -------------------------------------------------------------------------------- /goplus.org/components/Icon/QiniuLogo.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @file Logo for Qiniu Company 3 | */ 4 | 5 | import React, { SVGProps } from 'react' 6 | 7 | export default function QiniuLogo(props: SVGProps) { 8 | return ( 9 | 10 | 11 | 12 | ) 13 | } 14 | -------------------------------------------------------------------------------- /goplus.org/components/Icon/UpArrow.tsx: -------------------------------------------------------------------------------- 1 | import React, { SVGProps } from 'react' 2 | 3 | const flipStyle = { 4 | transform: 'rotate(180deg)', 5 | } 6 | 7 | export default function ArrowUp(props: SVGProps) { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | ) 18 | } -------------------------------------------------------------------------------- /goplus.org/components/Layout/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Head from 'next/head' 3 | 4 | import Header from '../Header' 5 | import Footer from '../Footer' 6 | 7 | import styles from './style.module.scss' 8 | 9 | export interface Props { 10 | meta?: { 11 | title?: string 12 | } 13 | } 14 | 15 | export default function Layout({ meta: pageMeta, children }: React.PropsWithChildren) { 16 | const meta = { 17 | title: 'XGo - Enable everyone to become a builder of the world', 18 | ...pageMeta 19 | } 20 | 21 | return ( 22 | <> 23 | 24 | {meta.title} 25 | 26 | 27 | 28 |
    29 |
    {children}
    30 |