-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Monaco Mode - Phase 2 - Mode & Worker (#1459)
* custom `graphqlDev` language, graphql webworker and mode * diagnostics, completion, hover, formatting * schema loading via config * new, simplified language service * example project using webpack, with netlify preview Co-authored-by: Rikki Schulte <[email protected]> Co-authored-by: Peng Lyu <[email protected]> Co-authored-by: rebornix <[email protected]>
- Loading branch information
1 parent
fddc11d
commit bc95fb4
Showing
34 changed files
with
1,677 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
module.exports = { | ||
sourceMaps: true, | ||
presets: [ | ||
[ | ||
require.resolve('@babel/preset-env'), | ||
{ | ||
// corejs: { version: 3, proposals: true }, | ||
// useBuiltIns: 'usage', | ||
targets: { browsers: ['last 2 chrome versions'] }, | ||
bugfixes: true, | ||
}, | ||
], | ||
require.resolve('@babel/preset-typescript'), | ||
], | ||
plugins: [ | ||
require.resolve('@babel/plugin-syntax-dynamic-import'), | ||
require.resolve('@babel/plugin-proposal-class-properties'), | ||
[ | ||
'@babel/plugin-transform-runtime', | ||
{ | ||
regenerator: true, | ||
}, | ||
], | ||
], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
{ | ||
"name": "example-monaco-graphql-webpack", | ||
"version": "1.0.0-alpha.3", | ||
"private": true, | ||
"license": "MIT", | ||
"description": "A simple monaco example with webpack and typescript", | ||
"scripts": { | ||
"build": "cross-env NODE_ENV=production webpack ", | ||
"build-demo": "yarn build && yarn copy-demo", | ||
"copy-demo": "mkdirp ../../packages/graphiql/monaco && copy 'bundle/*' '../../packages/graphiql/monaco'", | ||
"start": "cross-env NODE_ENV=development webpack-dev-server" | ||
}, | ||
"dependencies": { | ||
"graphql": "14.6.0", | ||
"monaco-graphql": "^2.3.4-alpha.4", | ||
"prettier": "^2.0.2" | ||
}, | ||
"devDependencies": { | ||
"@babel/plugin-proposal-class-properties": "7.8.3", | ||
"@babel/plugin-syntax-dynamic-import": "7.8.3", | ||
"@babel/preset-env": "7.9.5", | ||
"@types/prettier": "^2.0.0", | ||
"babel-loader": "^8.1.0", | ||
"cross-env": "^7.0.0", | ||
"css-loader": "^3.5.1", | ||
"html-webpack-plugin": "^4.2.0", | ||
"monaco-editor": "^0.20.0", | ||
"monaco-editor-webpack-plugin": "^1.9.0", | ||
"react-dom": "^16.12.0", | ||
"style-loader": "^1.1.3", | ||
"webpack": "4.42.1", | ||
"webpack-cli": "^3.3.11", | ||
"webpack-dev-server": "^3.10.1", | ||
"worker-loader": "^2.0.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<!DOCTYPE html> | ||
<html lang="en" dir="ltr"> | ||
|
||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /> | ||
<title>Monaco Example!</title> | ||
<style> | ||
.div { | ||
margin: 0; | ||
padding: 0; | ||
} | ||
.full-height { | ||
height: 100vh; | ||
} | ||
.column { | ||
width: 50%; | ||
} | ||
</style> | ||
</head> | ||
|
||
<body style="margin: 0; padding:0;"> | ||
<div style="display: flex;"> | ||
<div class="full-height column"> | ||
<div id="operation" style="height:70vh;"></div> | ||
<div id="variables" style="height:30vh;"></div> | ||
</div> | ||
<div id="results" class="full-height column"></div> | ||
</div> | ||
</body> | ||
|
||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'; | ||
|
||
import 'regenerator-runtime/runtime'; | ||
import 'monaco-graphql/esm/monaco.contribution'; | ||
|
||
// NOTE: using loader syntax becuase Yaml worker imports editor.worker directly and that | ||
// import shouldn't go through loader syntax. | ||
// @ts-ignore | ||
import EditorWorker from 'worker-loader!monaco-editor/esm/vs/editor/editor.worker'; | ||
// @ts-ignore | ||
import JSONWorker from 'worker-loader!monaco-editor/esm/vs/language/json/json.worker'; | ||
// @ts-ignore | ||
import GraphQLWorker from 'worker-loader!monaco-graphql/esm/graphql.worker'; | ||
|
||
const SCHEMA_URL = 'https://swapi-graphql.netlify.com/.netlify/functions/index'; | ||
|
||
// @ts-ignore | ||
window.MonacoEnvironment = { | ||
getWorker(_workerId: string, label: string) { | ||
if (label === 'graphqlDev') { | ||
return new GraphQLWorker(); | ||
} | ||
if (label === 'json') { | ||
return new JSONWorker(); | ||
} | ||
return new EditorWorker(); | ||
}, | ||
}; | ||
|
||
// const schemaInput = document.createElement('input'); | ||
// schemaInput.type = 'text' | ||
|
||
// // @ts-ignore | ||
// schemaInput.value = SCHEMA_URL | ||
|
||
// schemaInput.onchange = (e) => { | ||
// e.preventDefault() | ||
// console.log(e.target.value) | ||
// } | ||
|
||
// const toolbar = document.getElementById('toolbar') | ||
// toolbar?.appendChild(schemaInput) | ||
|
||
const variablesModel = monaco.editor.createModel( | ||
`{}`, | ||
'json', | ||
monaco.Uri.file('/1/variables.json'), | ||
); | ||
|
||
const resultsEditor = monaco.editor.create( | ||
document.getElementById('results') as HTMLElement, | ||
{ | ||
model: variablesModel, | ||
}, | ||
); | ||
const variablesEditor = monaco.editor.create( | ||
document.getElementById('variables') as HTMLElement, | ||
{ | ||
value: `{ }`, | ||
language: 'json', | ||
}, | ||
); | ||
const model = monaco.editor.createModel( | ||
` | ||
query Example { | ||
allFilms { | ||
films { | ||
id | ||
} | ||
} | ||
} | ||
`, | ||
'graphqlDev', | ||
monaco.Uri.file('/1/operation.graphql'), | ||
); | ||
|
||
const operationEditor = monaco.editor.create( | ||
document.getElementById('operation') as HTMLElement, | ||
{ | ||
model, | ||
}, | ||
); | ||
|
||
/** | ||
* Basic Operation Exec Example | ||
*/ | ||
|
||
async function executeCurrentOp() { | ||
try { | ||
const operation = operationEditor.getValue(); | ||
const variables = variablesEditor.getValue(); | ||
const body: { variables?: string; query: string } = { query: operation }; | ||
const parsedVariables = JSON.parse(variables); | ||
if (parsedVariables && Object.keys(parsedVariables).length) { | ||
body.variables = variables; | ||
} | ||
const result = await fetch(SCHEMA_URL, { | ||
method: 'POST', | ||
headers: { 'content-type': 'application/json' }, | ||
body: JSON.stringify(body), | ||
}); | ||
const resultText = await result.text(); | ||
resultsEditor.setValue(JSON.stringify(JSON.parse(resultText), null, 2)); | ||
} catch (err) { | ||
resultsEditor.setValue(err.toString()); | ||
} | ||
} | ||
|
||
const opAction: monaco.editor.IActionDescriptor = { | ||
id: 'graphql-run', | ||
label: 'Run Operation', | ||
contextMenuOrder: 0, | ||
contextMenuGroupId: 'graphql', | ||
keybindings: [ | ||
// eslint-disable-next-line no-bitwise | ||
monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, | ||
], | ||
run: executeCurrentOp, | ||
}; | ||
|
||
operationEditor.addAction(opAction); | ||
variablesEditor.addAction(opAction); | ||
resultsEditor.addAction(opAction); | ||
|
||
// add your own diagnostics? why not! | ||
// monaco.editor.setModelMarkers( | ||
// model, | ||
// 'graphql', | ||
// [{ | ||
// severity: 5, | ||
// message: 'An example diagnostic error', | ||
// startColumn: 2, | ||
// startLineNumber: 4, | ||
// endLineNumber: 4, | ||
// endColumn: 0, | ||
// }], | ||
// ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"extends": "../../resources/tsconfig.base.cjs.json", | ||
"compilerOptions": { | ||
"rootDir": "./src", | ||
"outDir": "./dist", | ||
"composite": true, | ||
"jsx": "preserve", | ||
"baseUrl": ".", | ||
"strictPropertyInitialization": false, | ||
"types": ["node", "jest"], | ||
"typeRoots": ["../../node_modules/@types", "node_modules/@types"], | ||
"lib": ["dom"], | ||
"module": "umd" | ||
}, | ||
"references": [{ "path": "../../packages/monaco-graphql" }], | ||
"include": ["src"], | ||
"exclude": ["**/__tests__/**", "**/build/**.*", "../../node_modules"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
const path = require('path'); | ||
const webpack = require('webpack'); | ||
|
||
const HtmlWebpackPlugin = require('html-webpack-plugin'); | ||
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); | ||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin'); | ||
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin'); | ||
const isDev = process.env.NODE_ENV === 'development'; | ||
|
||
const relPath = (...args) => path.resolve(__dirname, ...args); | ||
const rootPath = (...args) => relPath(...args); | ||
|
||
const resultConfig = { | ||
mode: process.env.NODE_ENV, | ||
entry: { | ||
app: './index.ts', | ||
'editor.worker': 'monaco-editor/esm/vs/editor/editor.worker.js', | ||
// 'json.worker': 'monaco-editor/esm/vs/language/json/json.worker.js', | ||
'graphql.worker': 'monaco-graphql/esm/graphql.worker.js', | ||
}, | ||
context: rootPath('src'), | ||
output: { | ||
path: rootPath('bundle'), | ||
filename: '[name].js', | ||
globalObject: 'self', | ||
}, | ||
devServer: { | ||
// bypass simple localhost CORS restrictions by setting | ||
// these to 127.0.0.1 in /etc/hosts | ||
allowedHosts: ['local.example.com', 'monaco-graphql.com'], | ||
}, | ||
devtool: isDev ? 'cheap-module-eval-source-map' : 'source-map', | ||
node: { | ||
fs: 'empty', | ||
module: 'empty', | ||
}, | ||
module: { | ||
rules: [ | ||
// for graphql module, which uses .mjs | ||
{ | ||
type: 'javascript/auto', | ||
test: /\.mjs$/, | ||
use: [], | ||
include: /node_modules/, | ||
exclude: /\.(ts|d\.ts|d\.ts\.map)$/, | ||
}, | ||
// i think we need to add another rule for | ||
// codemirror-graphql esm.js files to load | ||
{ | ||
test: /\.(js|jsx|ts|tsx)$/, | ||
use: [{ loader: 'babel-loader' }], | ||
exclude: /\.(d\.ts|d\.ts\.map|spec\.tsx)$/, | ||
}, | ||
{ | ||
test: /\.css$/, | ||
use: ['style-loader', 'css-loader'], | ||
}, | ||
{ | ||
test: /\.svg$/, | ||
use: [{ loader: 'svg-inline-loader' }], | ||
}, | ||
{ | ||
test: /\.(woff|woff2|eot|ttf|otf)$/, | ||
use: ['file-loader'], | ||
}, | ||
], | ||
}, | ||
plugins: [ | ||
// in order to prevent async modules for CDN builds | ||
// until we can guarantee it will work with the CDN properly | ||
// and so that graphiql.min.js can retain parity | ||
new HtmlWebpackPlugin({ | ||
template: relPath('src/index.html.ejs'), | ||
filename: 'index.html', | ||
}), | ||
new ForkTsCheckerWebpackPlugin({ | ||
async: isDev, | ||
tsconfig: rootPath('tsconfig.json'), | ||
}), | ||
|
||
new MonacoWebpackPlugin({ | ||
languages: ['json'], | ||
}), | ||
], | ||
resolve: { | ||
extensions: ['.mjs', '.js', '.json', '.jsx', '.css', '.ts', '.tsx'], | ||
}, | ||
}; | ||
|
||
if (process.env.ANALYZE) { | ||
resultConfig.plugins.push( | ||
new BundleAnalyzerPlugin({ | ||
analyzerMode: 'static', | ||
openAnalyzer: false, | ||
reportFilename: rootPath('build/analyzer.html'), | ||
}), | ||
); | ||
} | ||
|
||
module.exports = resultConfig; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Oops, something went wrong.