Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] React FC conversion for editor file retry + codemirror update #3230

Draft
wants to merge 14 commits into
base: develop
Choose a base branch
from
1,206 changes: 649 additions & 557 deletions client/modules/IDE/components/Editor/index.jsx

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@ describe('<EditorAccessibility />', () => {
it('renders empty message with no lines', () => {
render(<EditorAccessibility lintMessages={[]} currentLine={0} />);

expect(
screen.getByRole('listitem', {
description: 'There are no lint messages'
})
).toBeInTheDocument();
expect(screen.getByText(/there are no lint messages/i)).toBeInTheDocument();
});

it('renders lint message', () => {
Expand Down
48 changes: 48 additions & 0 deletions client/modules/IDE/utils/highlightStyle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { HighlightStyle } from '@codemirror/language';
import { tags } from '@lezer/highlight';

const createHighlightStyle = (colors) =>
HighlightStyle.define([
{ tag: tags.link, class: 'cm-link' },
{ tag: tags.heading, class: 'cm-heading' },
{ tag: tags.emphasis, class: 'cm-emphasis' },
{ tag: tags.strong, class: 'cm-strong' },
{ tag: tags.keyword, color: colors.keyword },
{ tag: tags.atom, color: colors.atom },
{ tag: tags.bool, class: 'cm-bool' },
{ tag: tags.url, class: 'cm-url' },
{ tag: tags.labelName, class: 'cm-labelName' },
{ tag: tags.inserted, class: 'cm-inserted' },
{ tag: tags.deleted, class: 'cm-deleted' },
{ tag: tags.literal, class: 'cm-literal' },
{ tag: tags.string, color: colors.string },
{ tag: tags.number, color: colors.number },
{
tag: [tags.regexp, tags.escape, tags.special(tags.string)],
color: colors.regexp
},
{ tag: tags.variableName, color: colors.variable },
{ tag: tags.local(tags.variableName), class: 'cm-variableName cm-local' },
{
tag: tags.definition(tags.variableName),
class: 'cm-variableName cm-definition'
},
{ tag: tags.special(tags.variableName), color: colors.specialVariable },
{
tag: tags.definition(tags.propertyName),
class: 'cm-propertyName cm-definition'
},
{ tag: tags.typeName, color: colors.typeName },
{ tag: tags.namespace, class: 'cm-namespace' },
{ tag: tags.className, class: 'cm-className' },
{ tag: tags.macroName, class: 'cm-macroName' },
{ tag: tags.propertyName, class: 'cm-propertyName' },
{ tag: tags.operator, color: colors.operator },
{ tag: tags.comment, color: colors.comment },
{ tag: tags.meta, class: 'cm-meta' },
{ tag: tags.invalid, class: 'cm-invalid' },
{ tag: tags.punctuation, class: 'cm-punctuation' },
{ tag: tags.special(tags.variableName), class: 'p5-variable' }
]);

export default createHighlightStyle;
68 changes: 68 additions & 0 deletions client/modules/IDE/utils/p5-contrast-cm-theme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { EditorView } from '@codemirror/view';
import createHighlightStyle from './highlightStyle';
import {
createGutterStyles,
createLineStyles,
createSelectionStyles,
createCursorAndBracketStyles,
createErrorAndSearchStyles,
createHighlightClasses
} from './sharedStyles';

const contrastColors = {
background: '#1C1C1C',
text: '#FDFDFD',
gutterBackground: '#454545',
lineNumber: '#FDFDFD',
selection: 'rgba(45, 123, 182, 0.25)',
activeLine: '#999999',
activeLineGutter: '#333333',
cursor: '#FDFDFD',
bracket: '#C1C1C1',
error: '#f00',
searchMatch: '#333333',
searchSelectedTextOutline: '#FDFDFD',
qualifier: '#F5DC23',
tag: '#FFA95D',
builtin: '#F5DC23',
attribute: '#FDFDFD',
function: '#00FFFF',
variable: '#FFA9D9',
foldPlaceholderBackground: '#FDFDFD',
foldPlaceholderColor: '#333333',
keyword: '#F5DC23',
atom: '#FFA9D9',
string: '#2DE9B6',
number: '#FDFDFD',
regexp: '#2DE9B6',
specialVariable: '#FDFDFD',
typeName: '#F5DC23',
comment: '#C1C1C1',
operator: '#C1C1C1'
};

const contrastHighlightStyle = createHighlightStyle(contrastColors);
const contrastThemeStyles = {
'&': {
backgroundColor: contrastColors.background,
color: contrastColors.text,
fontFamily: 'Inconsolata, monospace',
height: '100%'
},
'&.cm-focused': {
outline: 'none'
},
...createGutterStyles(contrastColors),
...createLineStyles(),
...createSelectionStyles(contrastColors),
...createCursorAndBracketStyles(contrastColors),
...createErrorAndSearchStyles(contrastColors),
...createHighlightClasses(contrastColors),
'.CodeMirror-selectedtext': {
backgroundColor: contrastColors.activeLineGutter,
outline: `${contrastColors.searchSelectedTextOutline}`
}
};

const p5ContrastTheme = EditorView.theme(contrastThemeStyles, { dark: true });
export { p5ContrastTheme, contrastHighlightStyle };
70 changes: 70 additions & 0 deletions client/modules/IDE/utils/p5-dark-cm-theme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { EditorView } from '@codemirror/view';
import createHighlightStyle from './highlightStyle';
import {
createGutterStyles,
createLineStyles,
createSelectionStyles,
createCursorAndBracketStyles,
createErrorAndSearchStyles,
createHighlightClasses
} from './sharedStyles';

const darkColors = {
background: '#1C1C1C',
text: '#FDFDFD',
gutterBackground: '#f4f4f4',
lineNumber: '#b5b5b5',
selection: 'rgba(45, 123, 182, 0.25)',
activeLine: '#CFCFCF',
activeLineGutter: '#666666',
cursor: '#FDFDFD',
bracket: '#9B9B9B',
error: '#df3a3d',
searchMatch: 'rgba(217, 50, 143, 0.5)',
qualifier: '#0F9DD7',
tag: '#DE4A9B',
builtin: '#0F9DD7',
attribute: '#FDFDFD',
function: '#0F9DD7',
variable: '#DE4A9B',
foldPlaceholderBackground: '#FDFDFD',
foldPlaceholderColor: '#1C1C1C',
keyword: '#b58318',
atom: '#DE4A9B',
string: '#58a10b',
number: '#FDFDFD',
regexp: '#EE9900',
specialVariable: '#666666',
typeName: '#DE4A9B',
comment: '#9B9B9B',
operator: '#A67F59'
};

const darkHighlightStyle = createHighlightStyle(darkColors);
const darkThemeStyles = {
'&': {
backgroundColor: darkColors.background,
color: darkColors.text,
fontFamily: 'Inconsolata, monospace',
height: '100%'
},
'&.cm-focused': {
outline: 'none'
},
...createGutterStyles(darkColors),
...createLineStyles(),
...createSelectionStyles(darkColors),
...createCursorAndBracketStyles(darkColors),
...createErrorAndSearchStyles(darkColors),
...createHighlightClasses(darkColors),
'.CodeMirror-selectedtext': {
backgroundColor: darkColors.activeLineGutter
}
};

const p5DarkTheme = EditorView.theme(darkThemeStyles, {
dark: true,
themeClass: 'cm-s-p5-dark'
});

export { p5DarkTheme, darkHighlightStyle };
72 changes: 72 additions & 0 deletions client/modules/IDE/utils/p5-light-cm-theme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { EditorView } from '@codemirror/view';
import createHighlightStyle from './highlightStyle';
import {
createGutterStyles,
createLineStyles,
createSelectionStyles,
createCursorAndBracketStyles,
createErrorAndSearchStyles,
createHighlightClasses
} from './sharedStyles';

const lightColors = {
background: '#FDFDFD',
text: '#333333',
gutterBackground: '#F4F4F4',
lineNumber: '#B5B5B5',
selection: 'rgba(45, 123, 182, 0.25)',
activeLine: '#CFCFCF',
activeLineGutter: '#999999',
cursor: '#333333',
bracket: '#666666',
error: '#f00',
searchMatch: 'rgba(213, 40, 137, 0.5)',
qualifier: '#0B7CA9',
tag: '#D52889',
builtin: '#0B7CA9',
attribute: '#666666',
function: '#0B7CA9',
variable: '#D52889',
foldPlaceholderBackground: '#333333',
foldPlaceholderColor: '#FDFDFD',
keyword: '#7A5A3A',
atom: '#D52889',
string: '#47820A',
number: '#B5B5B5',
regexp: '#A06801',
specialVariable: '#666666',
typeName: '#D52889',
comment: '#666666',
operator: '#7A5A3A',
lintError: 'rgb(255, 95, 82)',
lintWarning: 'rgb(255, 190, 5)',
foldGutter: 'rgba(0, 0, 0, 0.2)'
};

const lightHighlightStyle = createHighlightStyle(lightColors);
const lightThemeStyles = {
'&': {
backgroundColor: lightColors.background,
color: lightColors.text,
fontFamily: 'Inconsolata, monospace',
height: '100%'
},
'&.cm-focused': {
outline: 'none'
},
...createGutterStyles(lightColors),
...createLineStyles(),
...createSelectionStyles(lightColors),
...createCursorAndBracketStyles(lightColors),
...createErrorAndSearchStyles(lightColors),
...createHighlightClasses(lightColors),
'.CodeMirror-selectedtext': {
backgroundColor: lightColors.activeLineGutter
}
};

const p5LightTheme = EditorView.theme(lightThemeStyles, {
dark: false,
themeClass: 'cm-s-p5-light'
});
export { p5LightTheme, lightHighlightStyle };
64 changes: 64 additions & 0 deletions client/modules/IDE/utils/p5ViewPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { syntaxTree } from '@codemirror/language';
import { Decoration, EditorView, ViewPlugin } from '@codemirror/view';
import {
p5FunctionKeywords,
p5VariableKeywords
} from '../../../utils/p5-keywords';

function createP5Decoration(node, text) {
const isFunction = text in p5FunctionKeywords;
const isVariable = text in p5VariableKeywords;

if (isFunction || isVariable) {
const className = isFunction ? 'cm-p5-function' : 'cm-p5-variable';
return [Decoration.mark({ class: className }).range(node.from, node.to)];
}

return [];
}

function createDecorations(view) {
const decorations = [];

view.visibleRanges.forEach(({ from, to }) => {
syntaxTree(view.state).iterate({
from,
to,
enter: (node) => {
const text = view.state.doc.sliceString(node.from, node.to);

if (
node.name === 'VariableName' ||
node.name === 'VariableDefinition'
) {
decorations.push(...createP5Decoration(node, text));
}
}
});
});

return Decoration.set(decorations);
}

const p5ViewPlugin = ViewPlugin.fromClass(
class {
constructor(view) {
this.decorations = createDecorations(view);
}

update(update) {
if (update.docChanged || update.viewportChanged) {
this.decorations = createDecorations(update.view);
}
}
},
{
decorations: (instance) => instance.decorations,
provide: (plugin) =>
EditorView.atomicRanges.of(
(view) => view.plugin(plugin)?.decorations || Decoration.none
)
}
);

export default p5ViewPlugin;
Loading
Loading