Skip to content

Commit 128530b

Browse files
committed
working on initial linting plugin
1 parent dea879f commit 128530b

File tree

6 files changed

+117
-58
lines changed

6 files changed

+117
-58
lines changed

packages/components/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"@codemirror/lang-yaml": "^6.1.2",
4444
"@codemirror/language": "^6.10.3",
4545
"@codemirror/legacy-modes": "^6.4.2",
46+
"@codemirror/lint": "^6.8.4",
4647
"@codemirror/state": "^6.5.0",
4748
"@codemirror/view": "^6.36.2",
4849
"@ember/render-modifiers": "^2.1.0",

packages/components/src/components/hds/code-editor/index.hbs

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
ariaLabel=@ariaLabel
5757
ariaLabelledBy=this.ariaLabelledBy
5858
value=@value
59+
isLintingEnabled=@isLintingEnabled
5960
language=@language
6061
onBlur=@onBlur
6162
onInput=this.onInput

packages/components/src/modifiers/hds-code-editor.ts

+94-55
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import type {
1919
StreamLanguage as StreamLanguageType,
2020
StreamParser as StreamParserType,
2121
} from '@codemirror/language';
22+
import type { Diagnostic } from '@codemirror/lint';
2223
import type { Extension } from '@codemirror/state';
2324
import type { EditorView, ViewUpdate } from '@codemirror/view';
2425
import type Owner from '@ember/owner';
@@ -31,6 +32,7 @@ export interface HdsCodeEditorSignature {
3132
ariaDescribedBy?: string;
3233
ariaLabel?: string;
3334
ariaLabelledBy?: string;
35+
isLintingEnabled?: boolean;
3436
language?: HdsCodeEditorLanguages;
3537
value?: string;
3638
onInput?: (newVal: string) => void;
@@ -249,80 +251,111 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
249251
}
250252
);
251253

252-
private _buildExtensionsTask = task({ drop: true }, async ({ language }) => {
253-
const [
254-
{
255-
EditorView,
256-
keymap,
257-
lineNumbers,
258-
highlightActiveLineGutter,
259-
highlightSpecialChars,
260-
highlightActiveLine,
261-
},
262-
{ defaultKeymap, history, historyKeymap },
263-
{ bracketMatching, syntaxHighlighting },
264-
] = await Promise.all([
265-
import('@codemirror/view'),
266-
import('@codemirror/commands'),
267-
import('@codemirror/language'),
268-
]);
269-
270-
const languageExtension = await this._loadLanguageTask.perform(language);
271-
272-
const handleUpdateExtension = EditorView.updateListener.of(
273-
(update: ViewUpdate) => {
274-
// toggle a class if the update has/does not have a selection
275-
if (update.selectionSet) {
276-
update.view.dom.classList.toggle(
277-
'cm-hasSelection',
278-
!update.state.selection.main.empty
279-
);
280-
}
254+
private _buildExtensionsTask = task(
255+
{ drop: true },
256+
async ({ isLintingEnabled, language }) => {
257+
const [
258+
{
259+
EditorView,
260+
keymap,
261+
lineNumbers,
262+
highlightActiveLineGutter,
263+
highlightSpecialChars,
264+
highlightActiveLine,
265+
},
266+
{ defaultKeymap, history, historyKeymap },
267+
{ bracketMatching, syntaxHighlighting },
268+
] = await Promise.all([
269+
import('@codemirror/view'),
270+
import('@codemirror/commands'),
271+
import('@codemirror/language'),
272+
]);
273+
274+
let lintingExtension: Extension | undefined;
275+
276+
if (isLintingEnabled) {
277+
const [{ linter }, { syntaxTree }] = await Promise.all([
278+
import('@codemirror/lint'),
279+
import('@codemirror/language'),
280+
]);
281+
282+
lintingExtension = linter(
283+
(view) => {
284+
console.log('Test linter triggered', view.state.doc.toString());
285+
return [];
286+
},
287+
{ delay: 0 }
288+
);
289+
}
290+
291+
console.log(lintingExtension);
292+
293+
const languageExtension = await this._loadLanguageTask.perform(language);
294+
295+
const handleUpdateExtension = EditorView.updateListener.of(
296+
(update: ViewUpdate) => {
297+
// toggle a class if the update has/does not have a selection
298+
if (update.selectionSet) {
299+
update.view.dom.classList.toggle(
300+
'cm-hasSelection',
301+
!update.state.selection.main.empty
302+
);
303+
}
281304

282-
// call the onInput callback if the document has changed
283-
if (!update.docChanged || this.onInput === undefined) {
284-
return;
305+
// call the onInput callback if the document has changed
306+
if (!update.docChanged || this.onInput === undefined) {
307+
return;
308+
}
309+
this.onInput(update.state.doc.toString());
285310
}
286-
this.onInput(update.state.doc.toString());
311+
);
312+
313+
let extensions = [
314+
bracketMatching(),
315+
highlightActiveLine(),
316+
highlightActiveLineGutter(),
317+
highlightSpecialChars(),
318+
history(),
319+
lineNumbers(),
320+
keymap.of([...defaultKeymap, ...historyKeymap]),
321+
// custom extensions
322+
handleUpdateExtension,
323+
// hds dark theme
324+
hdsDarkTheme,
325+
syntaxHighlighting(hdsDarkHighlightStyle),
326+
];
327+
328+
if (languageExtension !== undefined) {
329+
extensions = [languageExtension, ...extensions];
287330
}
288-
);
289331

290-
let extensions = [
291-
bracketMatching(),
292-
highlightActiveLine(),
293-
highlightActiveLineGutter(),
294-
highlightSpecialChars(),
295-
history(),
296-
lineNumbers(),
297-
keymap.of([...defaultKeymap, ...historyKeymap]),
298-
// custom extensions
299-
handleUpdateExtension,
300-
// hds dark theme
301-
hdsDarkTheme,
302-
syntaxHighlighting(hdsDarkHighlightStyle),
303-
];
304-
305-
if (languageExtension !== undefined) {
306-
extensions = [languageExtension, ...extensions];
307-
}
332+
if (lintingExtension !== undefined) {
333+
extensions = [...extensions, lintingExtension];
334+
}
308335

309-
return extensions;
310-
});
336+
return extensions;
337+
}
338+
);
311339

312340
private _createEditorTask = task(
313341
{ drop: true },
314342
async (
315343
element: HTMLElement,
316344
{
345+
isLintingEnabled,
317346
language,
318347
value,
319-
}: Pick<HdsCodeEditorSignature['Args']['Named'], 'language' | 'value'>
348+
}: Pick<
349+
HdsCodeEditorSignature['Args']['Named'],
350+
'isLintingEnabled' | 'language' | 'value'
351+
>
320352
) => {
321353
try {
322354
const { EditorState } = await import('@codemirror/state');
323355
const { EditorView } = await import('@codemirror/view');
324356

325357
const extensions = await this._buildExtensionsTask.perform({
358+
isLintingEnabled,
326359
language,
327360
});
328361

@@ -359,6 +392,7 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
359392
ariaDescribedBy,
360393
ariaLabel,
361394
ariaLabelledBy,
395+
isLintingEnabled,
362396
language,
363397
value,
364398
} = named;
@@ -369,6 +403,7 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
369403
this.element = element;
370404

371405
const editor = await this._createEditorTask.perform(element, {
406+
isLintingEnabled,
372407
language,
373408
value,
374409
});
@@ -389,6 +424,10 @@ export default class HdsCodeEditorModifier extends Modifier<HdsCodeEditorSignatu
389424
ariaLabelledBy,
390425
});
391426

427+
this.editor.dispatch({
428+
changes: { from: 0, to: 0, insert: ' ' },
429+
});
430+
392431
onSetup?.(this.editor);
393432
}
394433
);

showcase/app/controllers/components/code-editor.js

+1
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ sayMessage();
9494
{
9595
value: 'json',
9696
label: 'JSON',
97+
isLintingEnabled: true,
9798
code: `{
9899
"message": "Hello, world!",
99100
"status": "success",

showcase/app/templates/components/code-editor.hbs

+6-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,12 @@
121121
<Shw::Flex @direction="column" as |SF|>
122122
{{#each this.languages as |lang|}}
123123
<SF.Item @label={{lang.label}}>
124-
<Hds::CodeEditor @language={{lang.value}} @value={{lang.code}} as |CE|>
124+
<Hds::CodeEditor
125+
@language={{lang.value}}
126+
@value={{lang.code}}
127+
@isLintingEnabled={{lang.isLintingEnabled}}
128+
as |CE|
129+
>
125130
<CE.Title>{{lang.label}}</CE.Title>
126131
</Hds::CodeEditor>
127132
</SF.Item>

yarn.lock

+14-2
Original file line numberDiff line numberDiff line change
@@ -2201,7 +2201,7 @@ __metadata:
22012201
languageName: node
22022202
linkType: hard
22032203

2204-
"@codemirror/lint@npm:^6.0.0":
2204+
"@codemirror/lint@npm:^6.0.0, @codemirror/lint@npm:^6.8.4":
22052205
version: 6.8.4
22062206
resolution: "@codemirror/lint@npm:6.8.4"
22072207
dependencies:
@@ -2221,7 +2221,7 @@ __metadata:
22212221
languageName: node
22222222
linkType: hard
22232223

2224-
"@codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0, @codemirror/view@npm:^6.27.0, @codemirror/view@npm:^6.35.0, @codemirror/view@npm:^6.36.2":
2224+
"@codemirror/view@npm:^6.17.0, @codemirror/view@npm:^6.23.0, @codemirror/view@npm:^6.27.0, @codemirror/view@npm:^6.36.2":
22252225
version: 6.36.2
22262226
resolution: "@codemirror/view@npm:6.36.2"
22272227
dependencies:
@@ -2232,6 +2232,17 @@ __metadata:
22322232
languageName: node
22332233
linkType: hard
22342234

2235+
"@codemirror/view@npm:^6.35.0":
2236+
version: 6.36.3
2237+
resolution: "@codemirror/view@npm:6.36.3"
2238+
dependencies:
2239+
"@codemirror/state": "npm:^6.5.0"
2240+
style-mod: "npm:^4.1.0"
2241+
w3c-keyname: "npm:^2.2.4"
2242+
checksum: 10/a41b9af6c57c74cab2dc3e7a3e5a6d3912253514667878f7cacb5b889892e445e514e68200a7ac4d4c3eefc1a221ae5f7b5a85f211c3b7fdd6749475086e4dff
2243+
languageName: node
2244+
linkType: hard
2245+
22352246
"@colors/colors@npm:1.5.0":
22362247
version: 1.5.0
22372248
resolution: "@colors/colors@npm:1.5.0"
@@ -3956,6 +3967,7 @@ __metadata:
39563967
"@codemirror/lang-yaml": "npm:^6.1.2"
39573968
"@codemirror/language": "npm:^6.10.3"
39583969
"@codemirror/legacy-modes": "npm:^6.4.2"
3970+
"@codemirror/lint": "npm:^6.8.4"
39593971
"@codemirror/state": "npm:^6.5.0"
39603972
"@codemirror/view": "npm:^6.36.2"
39613973
"@ember/render-modifiers": "npm:^2.1.0"

0 commit comments

Comments
 (0)