Skip to content

Commit eafb0d8

Browse files
author
Ives van Hoorne
committed
Add Vue warning handler, fix codemirror corrections
1 parent 73ebe57 commit eafb0d8

File tree

7 files changed

+107
-29
lines changed

7 files changed

+107
-29
lines changed

packages/app/src/app/components/CodeEditor/CodeMirror/index.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ class CodemirrorEditor extends React.Component<Props, State> implements Editor {
9898
linterWorker: ?Worker;
9999

100100
validate = (code: string = '', updateLinting: Function) => {
101+
if (!this.currentModule || !/\.jsx?$/.test(this.currentModule.title)) {
102+
updateLinting([]);
103+
return;
104+
}
105+
101106
if (code.trim() === '') {
102107
updateLinting([]);
103108
return;
@@ -232,6 +237,7 @@ class CodemirrorEditor extends React.Component<Props, State> implements Editor {
232237
if (settings.lintEnabled) {
233238
if (!this.linterWorker) {
234239
this.linterWorker = new LinterWorker();
240+
235241
this.codemirror.setOption('lint', {
236242
getAnnotations: this.validate,
237243
async: true,
@@ -241,6 +247,8 @@ class CodemirrorEditor extends React.Component<Props, State> implements Editor {
241247
this.codemirror.setOption('lint', false);
242248
}
243249

250+
this.codemirror.setOption('tabSize', this.props.settings.tabWidth);
251+
244252
this.forceUpdate();
245253
};
246254

@@ -251,6 +259,7 @@ class CodemirrorEditor extends React.Component<Props, State> implements Editor {
251259

252260
if (!documentCache[currentModule.id]) {
253261
const mode = await this.getMode(currentModule.title);
262+
254263
documentCache[currentModule.id] = new CodeMirror.Doc(
255264
currentModule.code || '',
256265
mode
@@ -288,7 +297,14 @@ class CodemirrorEditor extends React.Component<Props, State> implements Editor {
288297
await import(/* webpackChunkName: 'codemirror-html' */ 'codemirror/mode/htmlmixed/htmlmixed');
289298

290299
if (kind[1] === 'vue') {
291-
return 'text/x-vue';
300+
await Promise.all([
301+
import(/* webpackChunkName: 'codemirror-css' */ 'codemirror/mode/css/css'),
302+
import(/* webpackChunkName: 'codemirror-sass' */ 'codemirror/mode/sass/sass'),
303+
import(/* webpackChunkName: 'codemirror-stylus' */ 'codemirror/mode/stylus/stylus'),
304+
import(/* webpackChunkName: 'codemirror-handlebars' */ 'codemirror/mode/handlebars/handlebars'),
305+
import(/* webpackChunkName: 'codemirror-vue' */ 'codemirror/mode/vue/vue'),
306+
]);
307+
return { name: 'vue' };
292308
}
293309

294310
return 'htmlmixed';
@@ -301,7 +317,7 @@ class CodemirrorEditor extends React.Component<Props, State> implements Editor {
301317
await import(/* webpackChunkName: 'codemirror-sass' */ 'codemirror/mode/sass/sass');
302318
return 'sass';
303319
} else if (kind[1] === 'styl') {
304-
await import(/* webpackChunkName: 'codemirror-sass' */ 'codemirror/mode/stylus/stylus');
320+
await import(/* webpackChunkName: 'codemirror-stylus' */ 'codemirror/mode/stylus/stylus');
305321
return 'stylus';
306322
}
307323
}

packages/app/src/app/components/CodeEditor/Monaco/elements.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ export const CodeContainer = styled.div`
1313
height: 100%;
1414
z-index: 30;
1515
16+
.greensquiggly {
17+
background: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23ffd399'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")
18+
repeat-x bottom left !important;
19+
}
20+
1621
.jest-success {
1722
display: flex;
1823
align-items: center;

packages/app/src/app/components/CodeEditor/Monaco/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,7 @@ class MonacoEditor extends React.Component<Props, State> implements Editor {
386386
setCorrections = (corrections: Array<ModuleCorrection>) => {
387387
if (corrections.length > 0) {
388388
const correctionMarkers = corrections
389+
.filter(correction => correction.moduleId === this.currentModule.id)
389390
.map(correction => {
390391
if (correction) {
391392
return {

packages/app/src/app/pages/Sandbox/Editor/Content/Preview/index.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,7 @@ class Preview extends React.Component<Props, State> {
235235
settings={store.preferences.settings}
236236
initialPath={store.editor.initialPath}
237237
isInProjectView={store.editor.isInProjectView}
238-
onClearErrors={() =>
239-
store.editor.errors.length && signals.editor.errorsCleared()
240-
}
238+
onClearErrors={() => signals.editor.errorsCleared()}
241239
onAction={action =>
242240
signals.editor.previewActionReceived({ action })
243241
}

packages/app/src/app/store/modules/editor/actions.js

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -136,23 +136,25 @@ export function addErrorFromPreview({ state, props, utils }) {
136136
const sandbox = state.get('editor.currentSandbox');
137137

138138
try {
139-
const module = utils.resolveModule(
140-
props.action.path.replace(/^\//, ''),
141-
sandbox.modules,
142-
sandbox.directories
143-
);
139+
let module = null;
140+
141+
if (props.action.path) {
142+
module = utils.resolveModule(
143+
props.action.path.replace(/^\//, ''),
144+
sandbox.modules,
145+
sandbox.directories
146+
);
147+
}
144148

145149
const error = {
146-
moduleId: module.id,
150+
moduleId: module ? module.id : undefined,
147151
column: props.action.column,
148152
line: props.action.line,
149153
message: props.action.message,
150154
title: props.action.title,
151155
};
152156

153-
if (module) {
154-
state.push('editor.errors', error);
155-
}
157+
state.push('editor.errors', error);
156158
} catch (e) {
157159
/* ignore, module not found */
158160
}
@@ -178,22 +180,26 @@ export function addGlyphFromPreview({ state, props, utils }) {
178180

179181
export function addCorrectionFromPreview({ state, props, utils }) {
180182
const sandbox = state.get('editor.currentSandbox');
181-
const module = utils.resolveModule(
182-
props.action.path.replace(/^\//, ''),
183-
sandbox.modules,
184-
sandbox.directories
185-
);
183+
184+
let module = null;
185+
186+
if (props.action.path) {
187+
module = utils.resolveModule(
188+
props.action.path.replace(/^\//, ''),
189+
sandbox.modules,
190+
sandbox.directories
191+
);
192+
}
186193
const correction = {
187-
moduleId: module.id,
194+
moduleId: module ? module.id : undefined,
188195
column: props.action.column,
189196
line: props.action.line,
190197
message: props.action.message,
191198
source: props.action.source,
199+
severity: props.action.severity,
192200
};
193201

194-
if (module) {
195-
state.push('editor.corrections', correction);
196-
}
202+
state.push('editor.corrections', correction);
197203
}
198204

199205
export function moveTab({ state, props }) {

packages/app/src/app/store/modules/editor/model.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export default {
110110
line: types.maybe(types.number),
111111
message: types.string,
112112
title: types.string,
113-
moduleId: types.string,
113+
moduleId: types.maybe(types.string),
114114
})
115115
),
116116
glyphs: types.array(
@@ -126,7 +126,8 @@ export default {
126126
line: types.maybe(types.number),
127127
message: types.string,
128128
source: types.string,
129-
moduleId: types.string,
129+
moduleId: types.maybe(types.string),
130+
severity: types.maybe(types.string),
130131
})
131132
),
132133
isInProjectView: types.boolean,

packages/app/src/sandbox/eval/presets/vue-cli/index.js

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import { dispatch, actions } from 'codesandbox-api';
2+
3+
import type Manager from '../../manager';
4+
15
import babelTranspiler from '../../transpilers/babel';
26
import typescriptTranspiler from '../../transpilers/typescript';
37
import jsonTranspiler from '../../transpilers/json';
@@ -18,11 +22,58 @@ import base64Transpiler from '../../transpilers/base64';
1822

1923
import Preset from '../';
2024

25+
const getFileNameFromVm = vm => {
26+
if (vm) {
27+
const options =
28+
typeof vm === 'function' && vm.cid != null
29+
? vm.options
30+
: vm._isVue ? vm.$options || vm.constructor.options : vm || {};
31+
32+
return options.__file;
33+
}
34+
};
35+
2136
export default function initialize() {
22-
const vuePreset = new Preset('vue-cli', ['vue', 'json', 'js'], {
23-
'@': '{{sandboxRoot}}',
24-
vue$: 'vue/dist/vue.common.js',
25-
});
37+
const vuePreset = new Preset(
38+
'vue-cli',
39+
['vue', 'json', 'js'],
40+
{
41+
'@': '{{sandboxRoot}}',
42+
vue$: 'vue/dist/vue.common.js',
43+
},
44+
{
45+
setup: async (manager: Manager) => {
46+
try {
47+
const vueModule = manager.resolveTranspiledModule('vue', '/');
48+
49+
if (!vueModule.source) {
50+
await vueModule.transpile(manager);
51+
}
52+
const Vue = vueModule.evaluate(manager);
53+
54+
if (Vue) {
55+
Vue.config.warnHandler = (msg, vm, trace) => {
56+
console.error('[Vue warn]: ' + msg + trace);
57+
58+
const file = getFileNameFromVm(vm);
59+
60+
dispatch(
61+
actions.correction.show(msg, {
62+
line: 1,
63+
column: 1,
64+
path: file,
65+
severity: 'warning',
66+
source: 'Vue',
67+
})
68+
);
69+
};
70+
}
71+
} catch (e) {
72+
/* ignore */
73+
}
74+
},
75+
}
76+
);
2677

2778
const sassWithConfig = {
2879
transpiler: sassTranspiler,

0 commit comments

Comments
 (0)