diff --git a/client/common/icons.jsx b/client/common/icons.jsx index ff526c63f4..b6ab99c5d4 100644 --- a/client/common/icons.jsx +++ b/client/common/icons.jsx @@ -4,6 +4,8 @@ import styled from 'styled-components'; import { prop } from '../theme'; import SortArrowUp from '../images/sort-arrow-up.svg'; import SortArrowDown from '../images/sort-arrow-down.svg'; +import DownArrow from '../images/down-arrow.svg'; +import UpArrow from '../images/up-arrow.svg'; import Github from '../images/github.svg'; import Google from '../images/google.svg'; import Plus from '../images/plus-icon.svg'; @@ -78,6 +80,8 @@ function withLabel(SvgComponent) { export const SortArrowUpIcon = withLabel(SortArrowUp); export const SortArrowDownIcon = withLabel(SortArrowDown); +export const DownArrowIcon = withLabel(DownArrow); +export const UpArrowIcon = withLabel(UpArrow); export const GithubIcon = withLabel(Github); export const GoogleIcon = withLabel(Google); export const PlusIcon = withLabel(Plus); diff --git a/client/modules/CodeMirror/CodeMirrorEditor.jsx b/client/modules/CodeMirror/CodeMirrorEditor.jsx new file mode 100644 index 0000000000..b678266d56 --- /dev/null +++ b/client/modules/CodeMirror/CodeMirrorEditor.jsx @@ -0,0 +1,527 @@ +import { defaultKeymap, history, historyKeymap } from '@codemirror/commands'; +import { + bracketMatching, + syntaxHighlighting, + codeFolding, + foldGutter +} from '@codemirror/language'; +import { linter, lintGutter } from '@codemirror/lint'; +import { + openSearchPanel, + replaceNext, + search, + searchKeymap +} from '@codemirror/search'; +import { + Compartment, + StateField, + StateEffect, + RangeSetBuilder +} from '@codemirror/state'; +import { + EditorView, + highlightActiveLine, + highlightActiveLineGutter, + keymap, + lineNumbers, + Decoration, + DecorationSet, + ViewUpdate, + ViewPlugin +} from '@codemirror/view'; +import { + abbreviationTracker, + emmetConfig, + expandAbbreviation +} from '@emmetio/codemirror6-plugin'; +import { classHighlighter } from '@lezer/highlight'; +import { color, colorView, colorTheme } from '@uiw/codemirror-extensions-color'; +import classNames from 'classnames'; +import { debounce } from 'lodash'; +import PropTypes from 'prop-types'; +import React, { useRef } from 'react'; +import { createPortal } from 'react-dom'; +import { connect, useDispatch } from 'react-redux'; +import StackTrace from 'stacktrace-js'; +import beepUrl from '../../sounds/audioAlert.mp3'; +import { metaKey } from '../../utils/metaKey'; +import { selectActiveFile } from '../IDE/selectors/files'; +import CodeMirrorSearch from './CodeMirrorSearch'; +import CoreStyled from './CoreStyled'; +import p5StylePlugin from './highlightP5Vars'; +import p5Autocomplete from './p5Autocomplete'; +import tidyCode from './tidyCode'; +import { getFileExtension, getLanguageSupport } from './language'; +import lintSource from './linting'; +import { + updateLintMessage, + clearLintMessage +} from '../IDE/actions/editorAccessibility'; +import { + setUnsavedChanges, + setSelectedFile, + expandConsole, + startSketch, + showRuntimeErrorWarning, + hideRuntimeErrorWarning +} from '../IDE/actions/ide'; +import baseP5Theme from './baseTheme'; +import runtimeErrorExt, { + clearRuntimeErrorsEffect, + clearRuntimeErrors, + setRuntimeErrorsEffect +} from './runtimeErrors'; + +// TODO: setup/check emmet & fix class names +// https://github.com/emmetio/codemirror6-plugin/blob/de142116cbe4003c22a79436351ead9b600ae6e3/src/lib/syntax.ts#LL113C17-L113C28 +// https://docs.emmet.io/actions/ + +// TODO: autocomplete prevents 'div' + tab from auto-closing + +const INDENTATION_AMOUNT = 2; + +const searchContainer = document.createElement('div'); +searchContainer.id = 'p5-search-panel'; + +const EditorNew = ({ provideController }) => { + const dispatch = useDispatch(); + + const containerRef = useRef(null); + + const editorRef = useRef(null); + + const compartments = useRef({ + language: new Compartment(), + lineWrap: new Compartment(), + lineNumbers: new Compartment(), + emmet: new Compartment(), + abbrTracker: new Compartment() + }); +}; + +EditorNew.propTypes = { + provideController: PropTypes.func.isRequired +}; + +/** + * @property {CodeMirror} _cm5 + * @property {EditorView} _cm + */ +class Editor extends React.Component { + constructor(props) { + super(props); + this.tidyCode = this.tidyCode.bind(this); + + this.updateLintingMessageAccessibility = debounce((annotations) => { + this.props.dispatch(clearLintMessage()); + annotations.forEach((x) => { + if (x.from.line > -1) { + this.props.dispatch( + updateLintMessage(x.severity, x.from.line + 1, x.message) + ); + } + }); + if (this.props.lintMessages.length > 0 && this.props.lintWarning) { + this.beep.play(); + } + }, 2000); + this.showFind = this.showFind.bind(this); + this.showReplace = this.showReplace.bind(this); + this.getContent = this.getContent.bind(this); + } + + componentDidMount() { + this.beep = new Audio(beepUrl); + // TODO: see + // https://codesandbox.io/s/codemirror6-vanilla-g78yw?file=/src/editor.js + // https://discuss.codemirror.net/t/is-there-a-way-to-dynamically-remove-disable-extension/3454/6 + this.compartments = { + language: new Compartment(), + lineWrap: new Compartment(), + lineNumbers: new Compartment(), + emmet: new Compartment(), + abbrTracker: new Compartment() + }; + const fileExt = getFileExtension(this.props.file.name); + const currentLangSupport = getLanguageSupport(fileExt); + this._cm = new EditorView({ + extensions: [ + history(), + keymap.of([ + ...defaultKeymap, + ...historyKeymap, + ...searchKeymap, + { + key: 'Mod-e', // TODO + run: expandAbbreviation + } + ]), + this.compartments.language.of(currentLangSupport), + this.compartments.lineWrap.of( + this.props.linewrap ? EditorView.lineWrapping : [] + ), + this.compartments.emmet.of( + emmetConfig.of({ + // Note: not all file extensions are valid + syntax: fileExt + }) + ), + this.compartments.abbrTracker.of( + abbreviationTracker({ + syntax: fileExt + }) + ), + syntaxHighlighting(classHighlighter), + highlightActiveLine(), + highlightActiveLineGutter(), + p5Autocomplete, + // TODO: switch + // p5LightCodemirrorTheme, + baseP5Theme, + p5StylePlugin, + bracketMatching(), + linter(lintSource), + lintGutter(), + runtimeErrorExt, + // TODO: switch to an alpha bg to keep numbers visible. #00000005 + this.compartments.lineNumbers.of( + this.props.lineNumbers ? lineNumbers() : [] + ), + codeFolding(), + foldGutter({ + /* markerDOM: (open) => { + const img = document.createElement('img'); + img.src = arrowIconUrl; + img.style.transform = `rotate(${open ? '90deg' : 0})`; + return img; + // TODO: correct color based on theme + } */ + openText: '▼', + closedText: '▶' + }), + // TODO: remove + search({ + top: true, + createPanel: () => ({ + dom: searchContainer + }) + }), + color + // highlightSelectionMatches() // Not enabled currently, no sure if wanted + ], + parent: this.codemirrorContainer + }); + + const replaceCommand = + metaKey === 'Ctrl' ? `${metaKey}-H` : `${metaKey}-Option-F`; + // this._cm5.setOption('extraKeys', { + const extraKeys = { + Tab: (cm) => { + if (!cm.execCommand('emmetExpandAbbreviation')) return; + // might need to specify and indent more? + const hasSelection = this._cm.state.selection.ranges.some( + (r) => !r.empty + ); + if (hasSelection) { + cm.execCommand('indentMore'); + } else { + cm.replaceSelection(' '.repeat(INDENTATION_AMOUNT)); + } + }, + Enter: 'emmetInsertLineBreak', + Esc: 'emmetResetAbbreviation', + [`${metaKey}-Enter`]: () => null, + [`Shift-${metaKey}-Enter`]: () => null, + [`${metaKey}-F`]: 'findPersistent', + [`${metaKey}-G`]: 'findPersistentNext', + [`Shift-${metaKey}-G`]: 'findPersistentPrev', + [replaceCommand]: 'replace', + // Cassie Tarakajian: If you don't set a default color, then when you + // choose a color, it deletes characters inline. This is a + // hack to prevent that. + [`${metaKey}-K`]: (cm, event) => + cm.state.colorpicker.popup_color_picker({ length: 0 }), + [`${metaKey}-.`]: 'toggleComment' // Note: most adblockers use the shortcut ctrl+. + }; + // }); + + this.replaceFileContent(this.props.file.content); + + const eFacet = EditorView.updateListener; + /** + * @param {ViewUpdate} update + */ + const onViewUpdate = (update) => {}; + // TODO + /* this._cm5.on( + 'change', + debounce(() => { + this.props.dispatch(setUnsavedChanges(true)); + this.props.dispatch(hideRuntimeErrorWarning()); + this.props.dispatch(updateFileContent( + this.props.file.id, + this._cm.state.doc.toString() + )); + if (this.props.autorefresh && this.props.isPlaying) { + this.props.dispatch(clearConsole()); + this.props.dispatch(startSketch()); + } + }, 1000) + ); + */ + + /* + this._cm5.on('keyup', () => { + const temp = this.props.t('Editor.KeyUpLineNumber', { + lineNumber: this._cm.doc.lineAt(this._cm.state.selection.main.head) + .number + }); + document.getElementById('current-line').innerHTML = temp; + }); +*/ + /* + this._cm5.on('keydown', (_cm, e) => { + // 70 === f + if ( + ((metaKey === 'Cmd' && e.metaKey) || + (metaKey === 'Ctrl' && e.ctrlKey)) && + e.shiftKey && + e.keyCode === 70 + ) { + e.preventDefault(); + this.tidyCode(); + } + }); +*/ + + this.props.provideController({ + tidyCode: this.tidyCode, + showFind: this.showFind, + showReplace: this.showReplace, + getContent: this.getContent + }); + } + + componentDidUpdate(prevProps) { + if (this.props.file.content !== prevProps.file.content) { + this.replaceFileContent(this.props.file.content); + this._cm.focus(); + + if (!prevProps.unsavedChanges) { + setTimeout(() => this.props.dispatch(setUnsavedChanges(false)), 400); + } + } + if (this.props.file.name !== prevProps.file.name) { + const fileExt = getFileExtension(this.props.file.name); + this._cm.dispatch({ + effects: [ + this.compartments.language.reconfigure(getLanguageSupport(fileExt)), + this.compartments.emmet.reconfigure( + emmetConfig.of({ + syntax: fileExt + }) + ), + this.compartments.abbrTracker.reconfigure( + abbreviationTracker({ + syntax: fileExt + }) + ) + ] + }); + } + if (this.props.linewrap !== prevProps.linewrap) { + this._cm.dispatch({ + effects: this.compartments.lineWrap.reconfigure( + this.props.linewrap ? EditorView.lineWrapping : [] + ) + }); + } + if (this.props.theme !== prevProps.theme) { + // this._cm5.setOption('theme', `p5-${this.props.theme}`); + } + if (this.props.lineNumbers !== prevProps.lineNumbers) { + this._cm.dispatch({ + effects: this.compartments.lineNumbers.reconfigure( + this.props.lineNumbers ? lineNumbers() : [] + ) + }); + } + if ( + this.props.autocloseBracketsQuotes !== prevProps.autocloseBracketsQuotes + ) { + /* this._cm5.setOption( + 'autoCloseBrackets', + this.props.autocloseBracketsQuotes + ); */ + } + + // TODO: figure out how it works currently with the show/hide. + if (this.props.runtimeErrorWarningVisible) { + if (this.props.consoleEvents.length !== prevProps.consoleEvents.length) { + this.props.consoleEvents.forEach((consoleEvent) => { + if (consoleEvent.method === 'error') { + // It doesn't work if you create a new Error, but this works + // LOL + const errorObj = { stack: consoleEvent.data[0].toString() }; + StackTrace.fromError(errorObj).then((stackLines) => { + this.props.dispatch(expandConsole()); + const line = stackLines.find( + (l) => l.fileName && l.fileName.startsWith('/') + ); + if (!line) return; + const fileNameArray = line.fileName.split('/'); + const fileName = fileNameArray.slice(-1)[0]; + const filePath = fileNameArray.slice(0, -1).join('/'); + const fileWithError = this.props.files.find( + (f) => f.name === fileName && f.filePath === filePath + ); + this.props.dispatch(setSelectedFile(fileWithError.id)); + // Note: will only show max 1 at a time. + // TODO: instead of addLineClass, use line decorations: + // https://codemirror.net/examples/zebra/ + // https://discuss.codemirror.net/t/how-to-add-line-class-to-a-specific-line-dynamically/6230 + // https://discuss.codemirror.net/t/equivalent-for-addlineclass-in-cm6/4356 + // https://discuss.codemirror.net/t/how-to-add-classes-to-lines/3039/3 + console.log('error', line); + // TODO: why doesn't the decoration show up? + this._cm.dispatch({ + effects: [ + setRuntimeErrorsEffect.of({ + // TODO: pass the message and show it in a lint tooltip + message: '', + line: line.lineNumber + }) + ] + }); + }); + } + }); + } else { + clearRuntimeErrors(this._cm); + } + } + + if (this.props.file.id !== prevProps.file.id) { + clearRuntimeErrors(this._cm); + } + } + + componentWillUnmount() { + this._cm5 = null; + this._cm.destroy(); + this._cm = null; + this.props.provideController(null); + } + + getContent() { + return { + ...this.props.file, + content: this._cm.state.doc.toString() + }; + } + + showFind() { + openSearchPanel(this._cm); + } + + showReplace() { + // this._cm5.execCommand('replace'); + // TODO: how to open with replace section expanded? + // openSearchPanel(this._cm); + replaceNext(this._cm); + } + + tidyCode() { + tidyCode(this._cm, this.props.file.name); + } + + replaceFileContent(content) { + this._cm.dispatch({ + changes: { from: 0, to: this._cm.state.doc.length, insert: content } + }); + } + + render() { + const editorHolderClass = classNames({ + 'editor-holder': true, + 'editor-holder--hidden': + this.props.file.fileType === 'folder' || this.props.file.url, + [`cm-s-p5-${this.props.theme}`]: true + }); + + return ( + <> + { + this.codemirrorContainer = element; + }} + className={editorHolderClass} + /> + {this._cm && + createPortal( +
+ +
, + searchContainer + )} + + ); + } +} + +Editor.propTypes = { + autocloseBracketsQuotes: PropTypes.bool.isRequired, + lineNumbers: PropTypes.bool.isRequired, + lintWarning: PropTypes.bool.isRequired, + linewrap: PropTypes.bool.isRequired, + lintMessages: PropTypes.arrayOf( + PropTypes.shape({ + severity: PropTypes.string.isRequired, + line: PropTypes.number.isRequired, + message: PropTypes.string.isRequired, + id: PropTypes.number.isRequired + }) + ).isRequired, + consoleEvents: PropTypes.arrayOf( + PropTypes.shape({ + method: PropTypes.string.isRequired, + args: PropTypes.arrayOf(PropTypes.string) + }) + ).isRequired, + file: PropTypes.shape({ + name: PropTypes.string.isRequired, + content: PropTypes.string.isRequired, + id: PropTypes.string.isRequired, + fileType: PropTypes.string.isRequired, + url: PropTypes.string + }).isRequired, + // autorefresh: PropTypes.bool.isRequired, + // isPlaying: PropTypes.bool.isRequired, + theme: PropTypes.string.isRequired, + unsavedChanges: PropTypes.bool.isRequired, + files: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + content: PropTypes.string.isRequired + }) + ).isRequired, + runtimeErrorWarningVisible: PropTypes.bool.isRequired, + provideController: PropTypes.func.isRequired, + dispatch: PropTypes.func.isRequired +}; + +function mapStateToProps(state) { + return { + files: state.files, + file: selectActiveFile(state), + consoleEvents: state.console, + ...state.preferences, + ...state.ide, + lintMessages: state.editorAccessibility.lintMessages, + unsavedChanges: state.ide.unsavedChanges, + runtimeErrorWarningVisible: state.ide.runtimeErrorWarningVisible + }; +} + +export default connect(mapStateToProps)(Editor); diff --git a/client/modules/CodeMirror/CodeMirrorSearch.jsx b/client/modules/CodeMirror/CodeMirrorSearch.jsx new file mode 100644 index 0000000000..66a0ba59c0 --- /dev/null +++ b/client/modules/CodeMirror/CodeMirrorSearch.jsx @@ -0,0 +1,299 @@ +import { + getSearchQuery, + setSearchQuery, + SearchQuery, + replaceNext, + replaceAll, + findNext, + findPrevious, + selectMatches, + closeSearchPanel +} from '@codemirror/search'; +import PropTypes from 'prop-types'; +import React, { useEffect, useState, useRef } from 'react'; +import { useTranslation } from 'react-i18next'; +import { + ExitIcon, + PlayIcon, + DownArrowIcon, + UpArrowIcon +} from '../../common/icons'; + +// TODO: is this a valid check? +function isMouseClick(event) { + return event.detail > 0; +} + +// TODO: codemirror event handlers won't take effect when the focus is on the react element. +// Expand these keymaps: https://github.com/codemirror/search/blob/3c1346e213a9635f56f92b23066ea0638319de25/src/search.ts#L576 +// https://github.com/codemirror/view/blob/772e5a5102d96c25f54c4b9516e6a2d845336d65/src/keymap.ts#L34 +// https://github.com/codemirror/dev/issues/865 + +// TODO: number of hits +// https://discuss.codemirror.net/t/get-number-of-hits-of-searchquery/3939 +/* +state.posFrom = cursor.from(); + state.posTo = cursor.to(); + var num_match = cm.state.search.annotate.matches.length; + var next = cm.state.search.annotate.matches + .findIndex(s => s.from.ch === cursor.from().ch && s.from.line === cursor.from().line) + 1; + var text_match = next + '/' + num_match; + cm.display.wrapper.querySelector('.CodeMirror-search-results').innerText = text_match; + */ + +// TODO: v5 showMatchesOnScrollbar +// https://codemirror.net/5/addon/search/matchesonscrollbar.js +// https://codemirror.net/5/doc/manual.html + +/** + * @param {import("@codemirror/view").EditorView} editor + * @return {JSX.Element} + */ +function CodeMirrorSearch({ editor }) { + const { t } = useTranslation(); + + const [modifiers, setModifiers] = useState({ + caseSensitive: false, + regexp: false, + wholeWord: false + }); + + const [searchText, setSearchText] = useState(''); + const [replaceText, setReplaceText] = useState(''); + + const [isReplace, setIsReplace] = useState(false); + + const searchQuery = getSearchQuery(editor.state); + + const searchRef = useRef(null); + const replaceRef = useRef(null); + + console.log(searchQuery); + + console.log(editor.state); + + console.log(editor.state.search); + + useEffect(() => { + const nextQuery = new SearchQuery({ + search: searchText, + replace: isReplace ? replaceText : '', + ...modifiers + }); + editor.dispatch({ + effects: setSearchQuery.of(nextQuery) + }); + console.log(nextQuery); + console.log(nextQuery.getCursor(editor.state)); + // TODO: throttle? + // TODO: this makes them all "selected" but I just want "highlighted" + // selectMatches(editor); + }, [modifiers, searchText, replaceText, isReplace]); + + const createToggleButton = (field, label, children) => ( + + ); + + const handleReplace = (operation) => { + if (!replaceText) { + replaceRef.current?.focus(); + return; + } + if (!searchText.length > 1) { + searchRef.current?.focus(); + return; + } + editor.focus(); + operation(editor); + }; + + const handlePrevNext = (operation) => { + if (!searchText.length > 1) { + searchRef.current?.focus(); + return; + } + editor.focus(); + operation(editor); + }; + + const handleReplaceEnter = () => { + // TODO: flips between replacing the selected and selecting the next + /* + var state = getSearchState(cm); + var query = parseQuery(searchField.value, state); + var withText = parseString(replaceField.value); + if (e.keyCode === 13) // if enter + { + var cursor = getSearchCursor(cm, query, cm.getCursor("from")); + var start = cursor.from(); + var match = cursor.findNext(); + if (!match) { + cursor = getSearchCursor(cm, query); + if (!(match = cursor.findNext()) || (start && cursor.from().line == start.line && cursor.from().ch == start.ch)) return; + } + cm.setSelection(cursor.from(), cursor.to()); + state.replaceStarted = true; + doReplace(match, cursor, query, withText); + */ + }; + + return ( +
+
+ +
+
+
+
handlePrevNext(findNext)}> + setSearchText(e.target.value)} + ref={searchRef} + /> +
+
+
+
handleReplaceEnter()}> + setReplaceText(e.target.value)} + ref={replaceRef} + /> +
+
+
+
+
+ + +
+
+
+ {createToggleButton( + 'regexp', + t('CodemirrorFindAndReplace.Regex'), + '.*' + )} + {createToggleButton( + 'caseSensitive', + t('CodemirrorFindAndReplace.CaseSensitive'), + 'Aa' + )} + {createToggleButton( + 'wholeWord', + t('CodemirrorFindAndReplace.WholeWords'), + '" "' + )} +
+
+

+ {t('CodemirrorFindAndReplace.NoResults')} +

+ + +
+
+ +
+
+
+
+ ); +} + +CodeMirrorSearch.propTypes = { + // eslint-disable-next-line react/forbid-prop-types + editor: PropTypes.object.isRequired +}; + +export default CodeMirrorSearch; diff --git a/client/modules/CodeMirror/CoreStyled.jsx b/client/modules/CodeMirror/CoreStyled.jsx new file mode 100644 index 0000000000..f714c2e972 --- /dev/null +++ b/client/modules/CodeMirror/CoreStyled.jsx @@ -0,0 +1,48 @@ +import styled from 'styled-components'; +import classNames from 'classnames'; +import { useSelector } from 'react-redux'; +import React, { forwardRef } from 'react'; +import PropTypes from 'prop-types'; + +const StyledRoot = styled.article` + font-size: ${(props) => props.fontSize}px; + .cm-editor.cm-focused { + outline: none; + } +`; + +StyledRoot.propTypes = { + fontSize: PropTypes.number.isRequired, + lineWrap: PropTypes.bool.isRequired, + lineNumbers: PropTypes.bool.isRequired +}; + +const ElementWithClasses = forwardRef((props, ref) => { + const theme = useSelector((state) => state.preferences.theme); + const lineNumbers = useSelector((state) => state.preferences.lineNumbers); + const lineWrap = useSelector((state) => state.preferences.linewrap); + const fontSize = useSelector((state) => state.preferences.fontSize); + + return ( + + ); +}); + +ElementWithClasses.propTypes = { + className: PropTypes.string, + children: PropTypes.element +}; + +ElementWithClasses.defaultProps = { + className: '', + children: null +}; + +export default ElementWithClasses; diff --git a/client/modules/CodeMirror/_p5-light-codemirror-theme.js b/client/modules/CodeMirror/_p5-light-codemirror-theme.js new file mode 100644 index 0000000000..95e131c178 --- /dev/null +++ b/client/modules/CodeMirror/_p5-light-codemirror-theme.js @@ -0,0 +1,151 @@ +import { HighlightStyle } from '@codemirror/language'; +import { EditorView } from '@codemirror/view'; +import { tags } from '@lezer/highlight'; +import rootTheme, { colors, grays, remSize, Theme } from '../../theme'; + +const pink = '#D52889'; +const blue = '#0B7CA9'; + +const themeVars = rootTheme[Theme.light]; + +export const mixedHighlightStyle = 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: '#7A5A3A' }, + { tag: tags.atom, color: pink }, + { 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: '#47820A' }, + { tag: tags.number, color: grays.dark }, + { + tag: [tags.regexp, tags.escape, tags.special(tags.string)], + color: '#A06801' + }, + { tag: tags.variableName, color: blue }, + { 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: grays.dark }, + { + tag: tags.definition(tags.propertyName), + class: 'cm-propertyName cm-definition' + }, + { tag: tags.typeName, color: pink }, + { 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: '#7A5A3A' }, + { tag: tags.comment, color: grays.middleGray }, + { 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' } +]); + +const p5LightCodemirrorTheme = EditorView.theme( + { + '&': { + backgroundColor: grays.lighter, + color: grays.dark, + fontFamily: 'Inconsolata, monospace', + height: '100%' + }, + '&.cm-focused': { + outline: 'none' + }, + '.cm-gutters': { + // background-color: getThemifyVariable('editor-gutter-color'); + // border-color: getThemifyVariable('ide-border-color'); + // width: remSize(48), + width: '2.7em' + }, + '.cm-lineNumbers': { + paddingRight: remSize(10), + '& .cm-gutterElement': { + width: remSize(32), + left: remSize(-3), // !important + color: themeVars.inactiveTextColor + } + }, + '.cm-line': { + wordWrap: 'break-word', + whiteSpace: 'pre-wrap', + wordBreak: 'normal' + }, + '.cm-content': { + maxWidth: 'calc(100% - 2.7em)' // TODO + }, + // copied from previous + '.tok-definition': { + color: blue + }, + '.tok-propertyName': { + color: grays.dark + }, + '.cm-linenumber': { + color: '#b5b5b5' + }, + '.CodeMirror-selected': { + backgroundColor: 'rgba(45, 123, 182, 25)' + }, + '.cm-activeLine': { + backgroundColor: grays.light + }, + '.cm-activeLineGutter': { + backgroundColor: grays.light, + borderRight: `1px solid ${grays.mediumLight}` + }, + '.cm-error': { + color: colors.red + }, + '.cm-matchingBracket': { + outline: `1px solid ${grays.mediumDark}`, + outlineOffset: '1px', + color: `${grays.dark} !important` + }, + '.cm-qualifier': { + color: blue + }, + '.cm-tag': { + color: pink + }, + '.cm-builtin': { + color: blue + }, + '.cm-attribute': { + color: grays.dark + }, + '.cm-p5-function': { + color: blue, + fontWeight: 'bold' + }, + '.cm-p5-variable': { + color: pink + }, + '.cm-foldPlaceholder': { + backgroundColor: grays.dark, + color: colors.white + }, + '.CodeMirror-cursor': { + borderLeft: `1px solid ${grays.dark}` + }, + '.cm-searchMatch': { + backgroundColor: `${colors.p5jsPink}80` + }, + '.CodeMirror-selectedtext': { + backgroundColor: grays.mediumLight + } + }, + { dark: false } +); + +export default p5LightCodemirrorTheme; diff --git a/client/modules/CodeMirror/baseTheme.js b/client/modules/CodeMirror/baseTheme.js new file mode 100644 index 0000000000..0529ee9d5c --- /dev/null +++ b/client/modules/CodeMirror/baseTheme.js @@ -0,0 +1,50 @@ +import { EditorView } from '@codemirror/view'; +import { remSize } from '../../theme'; + +const lintStyleOverrides = EditorView.baseTheme({ + '.cm-gutter-lint': { + '& .cm-gutterElement': { + padding: 0, + '& .cm-lint-marker': { + width: '100%', + height: '100%', + opacity: 0.2 + }, + '& .cm-lint-marker-error': { + content: 'none', + backgroundColor: 'rgb(255, 95, 82)' + }, + '& .cm-lint-marker-warning': { + content: 'none', + backgroundColor: 'rgb(255, 190, 5)' + } + } + } +}); +// TODO: lintPoint, zig-zag underline + +const foldStyleOverrides = EditorView.baseTheme({ + '.cm-foldGutter .cm-gutterElement': { + cursor: 'pointer', + textAlign: 'right', + color: 'rgba(0,0,0,0.2)' // TODO: correct color based on theme + }, + '.cm-foldPlaceholder': { + // TODO: is currently in _editor.scss + } +}); + +const baseP5Theme = EditorView.baseTheme({ + '.cm-scroller': { + fontFamily: 'Inconsolata, monospace' + }, + '.cm-gutters': { + width: remSize(48) + }, + '.cm-gutter': { + width: '100%', + position: 'absolute' + } +}); + +export default [lintStyleOverrides, foldStyleOverrides, baseP5Theme]; diff --git a/client/utils/codemirror-search.js b/client/modules/CodeMirror/codemirror-search.js similarity index 98% rename from client/utils/codemirror-search.js rename to client/modules/CodeMirror/codemirror-search.js index 3096edcea7..b9133c688d 100644 --- a/client/utils/codemirror-search.js +++ b/client/modules/CodeMirror/codemirror-search.js @@ -9,13 +9,13 @@ // Ctrl-G (or whatever is bound to findNext) press. You prevent a // replace by making sure the match is no longer selected when hitting // Ctrl-G. -import i18n from '../i18n'; +import i18n from '../../i18n'; import CodeMirror from 'codemirror'; -import triangleArrowRight from '../images/triangle-arrow-right.svg?byContent'; -import triangleArrowDown from '../images/triangle-arrow-down.svg?byContent'; -import downArrow from '../images/down-arrow.svg?byContent'; -import upArrow from '../images/up-arrow.svg?byContent'; -import exitIcon from '../images/exit.svg?byContent'; +import triangleArrowRight from '../../images/triangle-arrow-right.svg?byContent'; +import triangleArrowDown from '../../images/triangle-arrow-down.svg?byContent'; +import downArrow from '../../images/down-arrow.svg?byContent'; +import upArrow from '../../images/up-arrow.svg?byContent'; +import exitIcon from '../../images/exit.svg?byContent'; function searchOverlay(query, caseInsensitive) { if (typeof query == 'string') query = new RegExp(query.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&'), caseInsensitive ? 'gi' : 'g'); diff --git a/client/modules/CodeMirror/highlightP5Vars.js b/client/modules/CodeMirror/highlightP5Vars.js new file mode 100644 index 0000000000..ee302eb7b5 --- /dev/null +++ b/client/modules/CodeMirror/highlightP5Vars.js @@ -0,0 +1,124 @@ +import { syntaxTree } from '@codemirror/language'; +import { + Decoration, + EditorView, + ViewPlugin, + WidgetType +} from '@codemirror/view'; + +import { + p5FunctionKeywords, + p5VariableKeywords +} from '../../utils/p5-keywords'; + +class P5StyleWidget extends WidgetType { + constructor(text) { + super(); + this.text = text; + } + + eq(other) { + return this.text === other.text; + } + + toDOM(view) { + const wrap = document.createElement('span'); + wrap.className = 'p5-styled'; + wrap.innerText = this.text; + const source = document.createElement('a'); + source.href = `https://p5js.org/reference/#/p5/${this.text}`; + source.innerText = 'doc'; + source.target = '_blank'; + wrap.append(source); + return wrap; + } +} + +class P5ReferenceLink extends WidgetType { + constructor(text) { + super(); + this.text = text; + } + + eq(other) { + return this.text === other.text; + } + + toDOM(view) { + const link = document.createElement('a'); + link.href = `https://p5js.org/reference/#/p5/${this.text}`; + link.innerText = '*'; + link.target = '_blank'; + return link; + } +} + +function createDecorations(view) { + const widgets = []; + const marks = []; + 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); + // console.log(node.name, text, node); + if (node.name === 'CallExpression/VariableName') { + console.log('!!!!!'); + } + // Note: VariableDefinition is for setup/draw/etc + if ( + node.name === 'VariableName' || + node.name === 'VariableDefinition' + ) { + if (text in p5FunctionKeywords) { + const mark = Decoration.mark({ + class: 'p5-function' + }); + decorations.push(mark.range(node.from, node.to)); + const deco = Decoration.widget({ + widget: new P5ReferenceLink(text), + side: 1 + }); + decorations.push(deco.range(node.to)); + } else if (text in p5VariableKeywords) { + const mark = Decoration.mark({ + class: 'p5-variable' + }); + decorations.push(mark.range(node.from, node.to)); + const deco = Decoration.widget({ + widget: new P5ReferenceLink(text), + side: 1 + }); + decorations.push(deco.range(node.to)); + } + } + } + }); + }); + return Decoration.set(decorations); +} + +const p5StylePlugin = ViewPlugin.fromClass( + class { + constructor(view) { + this.placeholders = createDecorations(view); + } + update(viewUpdate) { + if (viewUpdate.docChanged || viewUpdate.viewportChanged) { + this.placeholders = createDecorations(viewUpdate.view); + } + } + }, + { + decorations: (instance) => instance.placeholders, + provide: (plugin) => + EditorView.atomicRanges.of( + (view) => view.plugin(plugin)?.placeholders || Decoration.none + ), + eventHandlers: {} + } +); + +export default p5StylePlugin; diff --git a/client/modules/CodeMirror/language.js b/client/modules/CodeMirror/language.js new file mode 100644 index 0000000000..bcdc1e8c1f --- /dev/null +++ b/client/modules/CodeMirror/language.js @@ -0,0 +1,36 @@ +import { css } from '@codemirror/lang-css'; +import { html } from '@codemirror/lang-html'; +import { javascript } from '@codemirror/lang-javascript'; +import { json } from '@codemirror/lang-json'; + +/** + * @param {string} fileName + * @return {string} + */ +export const getFileExtension = (fileName) => + fileName.match(/\.(\w+)$/)?.[1]?.toLowerCase(); + +/** + * @param {string} fileExtension + * @return {import('@codemirror/language').LanguageSupport | []} + */ +export const getLanguageSupport = (fileExtension) => { + switch (fileExtension) { + case 'js': + return javascript({ jsx: false, typescript: false }); + case 'ts': + return javascript({ jsx: false, typescript: true }); + case 'jsx': + return javascript({ jsx: true, typescript: false }); + case 'tsx': + return javascript({ jsx: true, typescript: true }); + case 'css': + return css(); + case 'html': + return html(); // Note: has many options + case 'json': + return json(); + default: + return []; + } +}; diff --git a/client/modules/CodeMirror/linting.js b/client/modules/CodeMirror/linting.js new file mode 100644 index 0000000000..88d50ebf7a --- /dev/null +++ b/client/modules/CodeMirror/linting.js @@ -0,0 +1,62 @@ +import { cssLanguage } from '@codemirror/lang-css'; +import { htmlLanguage } from '@codemirror/lang-html'; +import { javascriptLanguage } from '@codemirror/lang-javascript'; +import { CSSLint } from 'csslint'; +import { HTMLHint } from 'htmlhint'; +import { JSHINT } from 'jshint'; + +// Note: probably not needed in v6 +window.JSHINT = JSHINT; +window.CSSLint = CSSLint; +window.HTMLHint = HTMLHint; + +/** + * Find the sections of the document in each language. + * Lint with the appropriate linter. + * Map warnings/errors to the correct format. + * + * @param {import('@codemirror/view').EditorView} view + * @return {Array} + */ +export default function lintSource(view) { + const cssRegions = cssLanguage.findRegions(view.state); + const diagnostics = cssRegions.flatMap(({ from, to }) => { + const content = view.state.doc.sliceString(from, to); + const errors = CSSLint.verify(content).messages; + console.log(errors); + return errors.map((error) => { + const line = view.state.doc.line(error.line); + return { + severity: error.type, + message: error.message, + source: 'CSSLint', + from: from + line.from + error.col - 1, + to: from + line.from + error.col - 1 // TODO: length + }; + }); + }); + + const jsRegions = javascriptLanguage.findRegions(view.state); + diagnostics.push( + ...jsRegions.flatMap(({ from, to }) => { + const content = view.state.doc.sliceString(from, to); + JSHINT(content, { esversion: 6 }); + console.log(JSHINT.errors, JSHINT); + return JSHINT.errors.map((error) => { + const line = view.state.doc.line(error.line); + return { + severity: 'error', // TODO + message: error.reason, + source: 'JSHINT', + from: from + line.from + error.character - 1, + to: from + line.from + error.character - 1 // TODO: length + }; + }); + }) + ); + + const htmlRegions = htmlLanguage.findRegions(view.state); + // TODO: HTML + + return diagnostics; +} diff --git a/client/modules/CodeMirror/p5Autocomplete.js b/client/modules/CodeMirror/p5Autocomplete.js new file mode 100644 index 0000000000..eb06ed78fa --- /dev/null +++ b/client/modules/CodeMirror/p5Autocomplete.js @@ -0,0 +1,28 @@ +import { autocompletion, completeFromList } from '@codemirror/autocomplete'; +import { + p5FunctionKeywords, + p5VariableKeywords +} from '../../utils/p5-keywords'; + +const p5AutocompleteSource = completeFromList( + Object.keys(p5FunctionKeywords) + .map((keyword) => ({ + label: keyword, + type: 'function', + boost: 99 // TODO: detail + })) + .concat( + Object.keys(p5VariableKeywords).map((keyword) => ({ + label: keyword, + type: 'constant', + boost: 50 // TODO: detail + })) + ) +); + +// TODO: only if language is js!! +const p5AutocompleteExt = autocompletion({ + override: [p5AutocompleteSource] // TODO: include native JS +}); + +export default p5AutocompleteExt; diff --git a/client/modules/CodeMirror/runtimeErrors.js b/client/modules/CodeMirror/runtimeErrors.js new file mode 100644 index 0000000000..8d52f3324f --- /dev/null +++ b/client/modules/CodeMirror/runtimeErrors.js @@ -0,0 +1,75 @@ +import { EditorView, Decoration } from '@codemirror/view'; +import { + StateEffect, + StateField, + RangeSet, + RangeSetBuilder +} from '@codemirror/state'; + +export const setRuntimeErrorsEffect = StateEffect.define(); + +export const clearRuntimeErrorsEffect = StateEffect.define(); + +export const clearRuntimeErrors = (view) => { + view.dispatch({ + effects: clearRuntimeErrorsEffect.of() + }); + return true; // TODO: only return true if there were errors to clear. +}; + +const lineError = Decoration.line({ + attributes: { class: 'line-runtime-error' } +}); + +function createDecorations(errors, doc) { + console.log('creating', errors); + const builder = new RangeSetBuilder(); + errors.forEach((error) => { + const line = doc.line(error.line); + // Could add additional deco with the character range of the error. + builder.add(line.from, line.to, lineError); + }); + return builder.finish(); +} + +const emptyState = () => { + console.log('cleared error deco'); + return { + lastClearedTime: Date.now(), + decorations: RangeSet.empty + }; +}; + +const runtimeErrorState = StateField.define({ + create() { + return emptyState(); + }, + update(prevState, transaction) { + let state = prevState; + + if (transaction.docChanged) { + state = emptyState(); + } + + transaction.effects.forEach((effect) => { + if (effect.is(setRuntimeErrorsEffect)) { + state.decorations = createDecorations( + [effect.value], + transaction.state.doc + ); + } else if (effect.is(clearRuntimeErrorsEffect)) { + state = emptyState(); + } + }); + + console.log('decorations', state.decorations.size); + + return state; + }, + provide: (field) => + EditorView.decorations.from(field, (state) => state.decorations) +}); + +export default runtimeErrorState; + +// Can also define plugin with EditorView.decorations.compute() diff --git a/client/modules/CodeMirror/tidyCode.js b/client/modules/CodeMirror/tidyCode.js new file mode 100644 index 0000000000..c525ba75e6 --- /dev/null +++ b/client/modules/CodeMirror/tidyCode.js @@ -0,0 +1,53 @@ +import babelParser from 'prettier/parser-babel'; +import htmlParser from 'prettier/parser-html'; +import cssParser from 'prettier/parser-postcss'; +import prettier from 'prettier/standalone'; +import { getFileExtension } from './language'; +import { replaceContent } from './util'; + +// TODO: should this be a CodeMirror extension? + +export default function tidyCode(editor, fileName) { + /** + * @param {import('prettier').BuiltInParserName} parser + * @param {Array} plugins + */ + function prettierFormatWithCursor(parser, plugins) { + try { + const { formatted, cursorOffset } = prettier.formatWithCursor( + editor.state.doc.toString(), + { + cursorOffset: editor.state.selection.main.head, + parser, + plugins + // TODO: use filepath option? https://prettier.io/docs/en/options.html#file-path + } + ); + // const { left, top } = this._cm5.getScrollInfo(); + replaceContent(editor, formatted); // TODO: make sure this syncs to redux + editor.focus(); + editor.dispatch({ + selection: { anchor: cursorOffset } + }); + // this._cm5.scrollTo(left, top); + } catch (error) { + console.error(error); + } + } + + // TODO: more parsers: https://prettier.io/docs/en/options.html#parser + const fileExt = getFileExtension(fileName); + if (fileExt === 'js') { + // .jsx? .ts? .tsx? + prettierFormatWithCursor('babel', [babelParser]); + } else if (fileExt === 'css') { + // .less? .scss? + prettierFormatWithCursor('css', [cssParser]); + } else if (fileExt === 'html' || fileExt === 'xml') { + prettierFormatWithCursor('html', [htmlParser]); + } + // TODO: remove this, for dev only + else { + console.log(`No formatter for file type ${fileExt}`); + } +} diff --git a/client/modules/CodeMirror/util.js b/client/modules/CodeMirror/util.js new file mode 100644 index 0000000000..231486d903 --- /dev/null +++ b/client/modules/CodeMirror/util.js @@ -0,0 +1,20 @@ +/** + * @param {import('@codemirror/view').EditorView} editor + * @param {string} content + * @return {void} + */ +// eslint-disable-next-line import/prefer-default-export +export function replaceContent(editor, content) { + editor.dispatch({ + changes: { from: 0, to: editor.state.doc.length, insert: content } + }); +} + +/** + * @param {import('@codemirror/view').EditorView} editor + * @return {number} + */ +export function cursorLineNumber(editor) { + const cursor = editor.state.selection.main.head; + return editor.state.doc.lineAt(cursor).number; +} diff --git a/client/modules/IDE/components/Console.jsx b/client/modules/IDE/components/Console.jsx index f4f8f32396..5b9826b748 100644 --- a/client/modules/IDE/components/Console.jsx +++ b/client/modules/IDE/components/Console.jsx @@ -275,7 +275,6 @@ const Console = () => { {isExpanded && isPlaying && ( diff --git a/client/modules/IDE/components/ConsoleInput.jsx b/client/modules/IDE/components/ConsoleInput.jsx index 759ccdd10d..5ff7e24023 100644 --- a/client/modules/IDE/components/ConsoleInput.jsx +++ b/client/modules/IDE/components/ConsoleInput.jsx @@ -1,143 +1,157 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import CodeMirror from 'codemirror'; +import { defaultKeymap, historyKeymap } from '@codemirror/commands'; +import { syntaxHighlighting } from '@codemirror/language'; +import { classHighlighter } from '@lezer/highlight'; +import React, { useRef, useState, useEffect } from 'react'; +import { EditorView, keymap } from '@codemirror/view'; import { Encode } from 'console-feed'; +import { javascript } from '@codemirror/lang-javascript'; +import { useDispatch, useSelector } from 'react-redux'; import RightArrowIcon from '../../../images/right-arrow.svg'; import { dispatchMessage, MessageTypes } from '../../../utils/dispatcher'; +import { replaceContent, cursorLineNumber } from '../../CodeMirror/util'; +import CoreStyled from '../../CodeMirror/CoreStyled'; +import { dispatchConsoleEvent } from '../actions/console'; // heavily inspired by // https://github.com/codesandbox/codesandbox-client/blob/92a1131f4ded6f7d9c16945dc7c18aa97c8ada27/packages/app/src/app/components/Preview/DevTools/Console/Input/index.tsx -class ConsoleInput extends React.Component { - constructor(props) { - super(props); - this.state = { - commandHistory: [], - commandCursor: -1 - }; - } +// TODO: Tab causes loss of focus +// TODO: remove margin at top - componentDidMount() { - this._cm = CodeMirror(this.codemirrorContainer, { - // eslint-disable-line - theme: `p5-${this.props.theme}`, - scrollbarStyle: null, - keymap: 'sublime', - mode: 'javascript', - inputStyle: 'contenteditable' - }); +/** + * @property {CodeMirror} _cm5 + * @property {EditorView} _cm + */ - this._cm.on('keydown', (cm, e) => { - if (e.key === 'Enter' && !e.shiftKey) { - e.preventDefault(); - e.stopPropagation(); - const value = cm.getValue(); - if (value.trim(' ') === '') { - return false; - } - const messages = [ - { log: Encode({ method: 'command', data: [value] }) } - ]; - const consoleEvent = [{ method: 'command', data: [value] }]; - dispatchMessage({ - type: MessageTypes.EXECUTE, - payload: { - source: 'console', - messages - } - }); - this.props.dispatchConsoleEvent(consoleEvent); - cm.setValue(''); - this.setState((state) => ({ - commandCursor: -1, - commandHistory: [value, ...state.commandHistory] - })); - } else if (e.key === 'ArrowUp') { - const lineNumber = this._cm.getDoc().getCursor().line; - if (lineNumber !== 0) { - return false; - } +/* + this._cm5 = CodeMirror(this.codemirrorContainer, { + // eslint-disable-line + theme: `p5-${this.props.theme}`, + scrollbarStyle: null, + keymap: 'sublime', + mode: 'javascript', + inputStyle: 'contenteditable' + }); +*/ - this.setState((state) => { - const newCursor = Math.min( - state.commandCursor + 1, - state.commandHistory.length - 1 - ); - this._cm.getDoc().setValue(state.commandHistory[newCursor] || ''); - const cursorPos = this._cm.getDoc().getLine(0).length - 1; - this._cm.getDoc().setCursor({ line: 0, ch: cursorPos }); - return { commandCursor: newCursor }; - }); - } else if (e.key === 'ArrowDown') { - const lineNumber = this._cm.getDoc().getCursor().line; - const lineCount = this._cm.getValue().split('\n').length; - if (lineNumber + 1 !== lineCount) { - return false; - } +function ConsoleInput() { + const dispatch = useDispatch(); - this.setState((state) => { - const newCursor = Math.max(state.commandCursor - 1, -1); - this._cm.getDoc().setValue(state.commandHistory[newCursor] || ''); - const newLineCount = this._cm.getValue().split('\n').length; - const newLine = this._cm.getDoc().getLine(newLineCount); - const cursorPos = newLine ? newLine.length - 1 : 1; - this._cm.getDoc().setCursor({ line: lineCount, ch: cursorPos }); - return { commandCursor: newCursor }; - }); - } - return true; - }); + const fontSize = useSelector((state) => state.preferences.fontSize); - this._cm.getWrapperElement().style[ - 'font-size' - ] = `${this.props.fontSize}px`; - } + const [state, setState] = useState({ + commandHistory: [], + commandCursor: -1 + }); - componentDidUpdate(prevProps) { - this._cm.setOption('theme', `p5-${this.props.theme}`); - this._cm.getWrapperElement().style[ - 'font-size' - ] = `${this.props.fontSize}px`; - this._cm.refresh(); - } + const containerRef = useRef(null); - componentWillUnmount() { - this._cm = null; - } + useEffect(() => { + const cm6 = new EditorView({ + extensions: [ + javascript(), + syntaxHighlighting(classHighlighter), + keymap.of([ + { + key: 'Enter', + run: (view, e) => { + console.log(e); + // e.preventDefault(); + // e.stopPropagation(); + const value = view.state.doc.toString(); + if (value.trim() === '') { + return false; + } + const consoleEvent = { method: 'command', data: [value] }; + dispatchMessage({ + type: MessageTypes.EXECUTE, + payload: { + source: 'console', + messages: [{ log: Encode(consoleEvent) }] + } + }); + dispatch(dispatchConsoleEvent([consoleEvent])); + replaceContent(view, ''); + setState((prevState) => ({ + commandCursor: -1, + commandHistory: [value, ...prevState.commandHistory] + })); + return true; + }, + shift: () => false + }, + { + key: 'ArrowUp', + run: (view) => { + console.log('ArrowUp handler'); + const lineNumber = cursorLineNumber(view); + console.log(lineNumber); + if (lineNumber !== 1) { + return false; + } + setState((prevState) => { + const newCursor = Math.min( + prevState.commandCursor + 1, + prevState.commandHistory.length - 1 + ); + replaceContent(view, prevState.commandHistory[newCursor] || ''); + const cursorPos = view.state.doc.lineAt(1).length - 1; + view.dispatch({ selection: { anchor: cursorPos } }); + return { ...prevState, commandCursor: newCursor }; + }); + return true; + } + }, + { + key: 'ArrowDown', + run: (view) => { + console.log('ArrowDown handler'); + const lineNumber = cursorLineNumber(view); + const lineCount = view.state.doc.lines; + if (lineNumber !== lineCount) { + return false; + } + setState((prevState) => { + const newCursor = Math.max(prevState.commandCursor - 1, -1); + replaceContent(view, prevState.commandHistory[newCursor] || ''); + const newLineCount = view.state.doc.lines; + const newLine = view.state.doc.line(newLineCount); + view.dispatch({ selection: { anchor: newLine.to } }); + return { ...prevState, commandCursor: newCursor }; + }); + return true; + } + }, + ...defaultKeymap + ]) + // history? + // theme? + ], + parent: containerRef.current + }); + return () => cm6.destroy(); + }, [containerRef, setState, dispatch]); - render() { - return ( -
-
-
-
{ - this.codemirrorContainer = element; + return ( +
+
+
- ); - } + +
+ ); } -ConsoleInput.propTypes = { - theme: PropTypes.string.isRequired, - dispatchConsoleEvent: PropTypes.func.isRequired, - fontSize: PropTypes.number.isRequired -}; - export default ConsoleInput; diff --git a/client/modules/IDE/components/Editor.jsx b/client/modules/IDE/components/Editor.jsx index e1899e0bfe..ca2e9bde93 100644 --- a/client/modules/IDE/components/Editor.jsx +++ b/client/modules/IDE/components/Editor.jsx @@ -1,84 +1,132 @@ +import { autocompletion, completeFromList } from '@codemirror/autocomplete'; +import { defaultKeymap, history, historyKeymap } from '@codemirror/commands'; +import { bracketMatching, syntaxHighlighting } from '@codemirror/language'; +import { linter, lintGutter } from '@codemirror/lint'; +import { + openSearchPanel, + replaceNext, + search, + searchKeymap +} from '@codemirror/search'; +import { Compartment } from '@codemirror/state'; +import { + EditorView, + highlightActiveLine, + highlightActiveLineGutter, + keymap, + lineNumbers +} from '@codemirror/view'; +import { + abbreviationTracker, + emmetConfig, + expandAbbreviation +} from '@emmetio/codemirror6-plugin'; +import { classHighlighter } from '@lezer/highlight'; +import classNames from 'classnames'; +import { debounce } from 'lodash'; import PropTypes from 'prop-types'; -import React from 'react'; -import CodeMirror from 'codemirror'; -import emmet from '@emmetio/codemirror-plugin'; -import prettier from 'prettier/standalone'; -import babelParser from 'prettier/parser-babel'; -import htmlParser from 'prettier/parser-html'; -import cssParser from 'prettier/parser-postcss'; +import React, { useRef } from 'react'; +import { createPortal } from 'react-dom'; import { withTranslation } from 'react-i18next'; +import { connect, useDispatch } from 'react-redux'; import StackTrace from 'stacktrace-js'; -import 'codemirror/mode/css/css'; -import 'codemirror/mode/clike/clike'; -import 'codemirror/addon/selection/active-line'; -import 'codemirror/addon/lint/lint'; -import 'codemirror/addon/lint/javascript-lint'; -import 'codemirror/addon/lint/css-lint'; -import 'codemirror/addon/lint/html-lint'; -import 'codemirror/addon/fold/brace-fold'; -import 'codemirror/addon/fold/comment-fold'; -import 'codemirror/addon/fold/foldcode'; -import 'codemirror/addon/fold/foldgutter'; -import 'codemirror/addon/fold/indent-fold'; -import 'codemirror/addon/comment/comment'; -import 'codemirror/keymap/sublime'; -import 'codemirror/addon/search/searchcursor'; -import 'codemirror/addon/search/matchesonscrollbar'; -import 'codemirror/addon/search/match-highlighter'; -import 'codemirror/addon/search/jump-to-line'; -import 'codemirror/addon/edit/matchbrackets'; -import 'codemirror/addon/edit/closebrackets'; -import 'codemirror/addon/selection/mark-selection'; -import 'codemirror-colorpicker'; - -import { JSHINT } from 'jshint'; -import { CSSLint } from 'csslint'; -import { HTMLHint } from 'htmlhint'; -import classNames from 'classnames'; -import { debounce } from 'lodash'; -import { connect } from 'react-redux'; -import { bindActionCreators } from 'redux'; -import '../../../utils/htmlmixed'; -import '../../../utils/p5-javascript'; -import Timer from '../components/Timer'; -import EditorAccessibility from '../components/EditorAccessibility'; +import beepUrl from '../../../sounds/audioAlert.mp3'; import { metaKey } from '../../../utils/metaKey'; +import { + p5FunctionKeywords, + p5VariableKeywords +} from '../../../utils/p5-keywords'; +import CodeMirrorSearch from '../../CodeMirror/CodeMirrorSearch'; +import CoreStyled from '../../CodeMirror/CoreStyled'; +import p5StylePlugin from '../../CodeMirror/highlightP5Vars'; +import tidyCode from '../../CodeMirror/tidyCode'; +import { + getFileExtension, + getLanguageSupport +} from '../../CodeMirror/language'; +import lintSource from '../../CodeMirror/linting'; +import { + updateLintMessage, + clearLintMessage +} from '../actions/editorAccessibility'; +import { updateFileContent } from '../actions/files'; +import { + setUnsavedChanges, + setSelectedFile, + expandConsole, + startSketch, + showRuntimeErrorWarning, + hideRuntimeErrorWarning +} from '../actions/ide'; + +// TODO: setup/check emmet & fix class names +// https://github.com/emmetio/codemirror6-plugin/blob/de142116cbe4003c22a79436351ead9b600ae6e3/src/lib/syntax.ts#LL113C17-L113C28 +// https://docs.emmet.io/actions/ + +// TODO: autocomplete prevents 'div' + tab from auto-closing -import '../../../utils/codemirror-search'; +const INDENTATION_AMOUNT = 2; -import beepUrl from '../../../sounds/audioAlert.mp3'; -import UnsavedChangesDotIcon from '../../../images/unsaved-changes-dot.svg'; -import RightArrowIcon from '../../../images/right-arrow.svg'; -import LeftArrowIcon from '../../../images/left-arrow.svg'; -import { getHTMLFile } from '../reducers/files'; - -import * as FileActions from '../actions/files'; -import * as IDEActions from '../actions/ide'; -import * as ProjectActions from '../actions/project'; -import * as EditorAccessibilityActions from '../actions/editorAccessibility'; -import * as PreferencesActions from '../actions/preferences'; -import * as UserActions from '../../User/actions'; -import * as ToastActions from '../actions/toast'; -import * as ConsoleActions from '../actions/console'; - -emmet(CodeMirror); - -window.JSHINT = JSHINT; -window.CSSLint = CSSLint; -window.HTMLHint = HTMLHint; +const p5AutocompleteSource = completeFromList( + Object.keys(p5FunctionKeywords) + .map((keyword) => ({ + label: keyword, + type: 'function', + boost: 99 // TODO: detail + })) + .concat( + Object.keys(p5VariableKeywords).map((keyword) => ({ + label: keyword, + type: 'constant', + boost: 50 // TODO: detail + })) + ) +); -const INDENTATION_AMOUNT = 2; +// TODO: only if language is js!! +const p5AutocompleteExt = autocompletion({ + override: [p5AutocompleteSource] // TODO: include native JS +}); + +const searchContainer = document.createElement('div'); +searchContainer.id = 'p5-search-panel'; + +const EditorNew = ({ provideController }) => { + const dispatch = useDispatch(); + const containerRef = useRef(null); + + const editorRef = useRef(null); + + const compartments = useRef({ + language: new Compartment(), + lineWrap: new Compartment(), + lineNumbers: new Compartment(), + emmet: new Compartment(), + abbrTracker: new Compartment() + }); +}; + +EditorNew.propTypes = { + provideController: PropTypes.func.isRequired +}; + +/** + * @property {CodeMirror} _cm5 + * @property {EditorView} _cm + */ class Editor extends React.Component { constructor(props) { super(props); this.tidyCode = this.tidyCode.bind(this); this.updateLintingMessageAccessibility = debounce((annotations) => { - this.props.clearLintMessage(); + this.props.dispatch(clearLintMessage()); annotations.forEach((x) => { if (x.from.line > -1) { - this.props.updateLintMessage(x.severity, x.from.line + 1, x.message); + this.props.dispatch( + updateLintMessage(x.severity, x.from.line + 1, x.message) + ); } }); if (this.props.lintMessages.length > 0 && this.props.lintWarning) { @@ -92,55 +140,81 @@ class Editor extends React.Component { componentDidMount() { this.beep = new Audio(beepUrl); - this.widgets = []; - this._cm = CodeMirror(this.codemirrorContainer, { - // eslint-disable-line - theme: `p5-${this.props.theme}`, - lineNumbers: this.props.lineNumbers, - styleActiveLine: true, - inputStyle: 'contenteditable', - lineWrapping: this.props.linewrap, - fixedGutter: false, - foldGutter: true, - foldOptions: { widget: '\u2026' }, - gutters: ['CodeMirror-foldgutter', 'CodeMirror-lint-markers'], - keyMap: 'sublime', - highlightSelectionMatches: true, // highlight current search match - matchBrackets: true, - emmet: { - preview: ['html'], - markTagPairs: true, - autoRenameTags: true - }, - autoCloseBrackets: this.props.autocloseBracketsQuotes, - styleSelectedText: true, - lint: { - onUpdateLinting: (annotations) => { - this.updateLintingMessageAccessibility(annotations); - }, - options: { - asi: true, - eqeqeq: false, - '-W041': false, - esversion: 7 - } - }, - colorpicker: { - type: 'sketch', - mode: 'edit' - } + // TODO: see + // https://codesandbox.io/s/codemirror6-vanilla-g78yw?file=/src/editor.js + // https://discuss.codemirror.net/t/is-there-a-way-to-dynamically-remove-disable-extension/3454/6 + this.compartments = { + language: new Compartment(), + lineWrap: new Compartment(), + lineNumbers: new Compartment(), + emmet: new Compartment(), + abbrTracker: new Compartment() + }; + const fileExt = getFileExtension(this.props.file.name); + const currentLangSupport = getLanguageSupport(fileExt); + this._cm = new EditorView({ + extensions: [ + history(), + keymap.of([ + ...defaultKeymap, + ...historyKeymap, + ...searchKeymap, + { + key: 'Mod-e', // TODO + run: expandAbbreviation + } + ]), + this.compartments.language.of(currentLangSupport), + this.compartments.lineWrap.of( + this.props.linewrap ? EditorView.lineWrapping : [] + ), + this.compartments.lineNumbers.of( + this.props.lineNumbers ? lineNumbers() : [] + ), + this.compartments.emmet.of( + emmetConfig.of({ + // Note: not all file extensions are valid + syntax: fileExt + }) + ), + this.compartments.abbrTracker.of( + abbreviationTracker({ + syntax: fileExt + }) + ), + syntaxHighlighting(classHighlighter), + highlightActiveLine(), + highlightActiveLineGutter(), + p5AutocompleteExt, + // TODO: switch + // p5LightCodemirrorTheme, + p5StylePlugin, + bracketMatching(), + linter(lintSource), + lintGutter(), + // TODO: remove + search({ + top: true, + createPanel: () => ({ + dom: searchContainer + }) + }) + // highlightSelectionMatches() // Not enabled currently, no sure if wanted + ], + parent: this.codemirrorContainer }); - delete this._cm.options.lint.options.errors; - const replaceCommand = metaKey === 'Ctrl' ? `${metaKey}-H` : `${metaKey}-Option-F`; - this._cm.setOption('extraKeys', { + // this._cm5.setOption('extraKeys', { + const extraKeys = { Tab: (cm) => { if (!cm.execCommand('emmetExpandAbbreviation')) return; // might need to specify and indent more? - const selection = cm.doc.getSelection(); - if (selection.length > 0) { + const hasSelection = this._cm.state.selection.ranges.some( + (r) => !r.empty + ); + if (hasSelection) { cm.execCommand('indentMore'); } else { cm.replaceSelection(' '.repeat(INDENTATION_AMOUNT)); @@ -160,32 +234,45 @@ class Editor extends React.Component { [`${metaKey}-K`]: (cm, event) => cm.state.colorpicker.popup_color_picker({ length: 0 }), [`${metaKey}-.`]: 'toggleComment' // Note: most adblockers use the shortcut ctrl+. - }); - - this.initializeDocuments(this.props.files); - this._cm.swapDoc(this._docs[this.props.file.id]); - - this._cm.on( + }; + // }); + + this.replaceFileContent(this.props.file.content); + + const eFacet = EditorView.updateListener; + /** + * @param {ViewUpdate} update + */ + const onViewUpdate = (update) => {}; + // TODO + /* this._cm5.on( 'change', debounce(() => { - this.props.setUnsavedChanges(true); - this.props.hideRuntimeErrorWarning(); - this.props.updateFileContent(this.props.file.id, this._cm.getValue()); + this.props.dispatch(setUnsavedChanges(true)); + this.props.dispatch(hideRuntimeErrorWarning()); + this.props.dispatch(updateFileContent( + this.props.file.id, + this._cm.state.doc.toString() + )); if (this.props.autorefresh && this.props.isPlaying) { - this.props.clearConsole(); - this.props.startSketch(); + this.props.dispatch(clearConsole()); + this.props.dispatch(startSketch()); } }, 1000) ); + */ - this._cm.on('keyup', () => { + /* + this._cm5.on('keyup', () => { const temp = this.props.t('Editor.KeyUpLineNumber', { - lineNumber: parseInt(this._cm.getCursor().line + 1, 10) + lineNumber: this._cm.doc.lineAt(this._cm.state.selection.main.head) + .number }); document.getElementById('current-line').innerHTML = temp; }); - - this._cm.on('keydown', (_cm, e) => { +*/ + /* + this._cm5.on('keydown', (_cm, e) => { // 70 === f if ( ((metaKey === 'Cmd' && e.metaKey) || @@ -197,10 +284,7 @@ class Editor extends React.Component { this.tidyCode(); } }); - - this._cm.getWrapperElement().style[ - 'font-size' - ] = `${this.props.fontSize}px`; +*/ this.props.provideController({ tidyCode: this.tidyCode, @@ -210,48 +294,57 @@ class Editor extends React.Component { }); } - componentWillUpdate(nextProps) { - // check if files have changed - if (this.props.files[0].id !== nextProps.files[0].id) { - // then need to make CodeMirror documents - this.initializeDocuments(nextProps.files); - } - if (this.props.files.length !== nextProps.files.length) { - this.initializeDocuments(nextProps.files); - } - } - componentDidUpdate(prevProps) { - if (this.props.file.id !== prevProps.file.id) { - const oldDoc = this._cm.swapDoc(this._docs[this.props.file.id]); - this._docs[prevProps.file.id] = oldDoc; + if (this.props.file.content !== prevProps.file.content) { + this.replaceFileContent(this.props.file.content); this._cm.focus(); if (!prevProps.unsavedChanges) { - setTimeout(() => this.props.setUnsavedChanges(false), 400); + setTimeout(() => this.props.dispatch(setUnsavedChanges(false)), 400); } } - if (this.props.fontSize !== prevProps.fontSize) { - this._cm.getWrapperElement().style[ - 'font-size' - ] = `${this.props.fontSize}px`; + if (this.props.file.name !== prevProps.file.name) { + const fileExt = getFileExtension(this.props.file.name); + this._cm.dispatch({ + effects: [ + this.compartments.language.reconfigure(getLanguageSupport(fileExt)), + this.compartments.emmet.reconfigure( + emmetConfig.of({ + syntax: fileExt + }) + ), + this.compartments.abbrTracker.reconfigure( + abbreviationTracker({ + syntax: fileExt + }) + ) + ] + }); } if (this.props.linewrap !== prevProps.linewrap) { - this._cm.setOption('lineWrapping', this.props.linewrap); + this._cm.dispatch({ + effects: this.compartments.lineWrap.reconfigure( + this.props.linewrap ? EditorView.lineWrapping : [] + ) + }); } if (this.props.theme !== prevProps.theme) { - this._cm.setOption('theme', `p5-${this.props.theme}`); + // this._cm5.setOption('theme', `p5-${this.props.theme}`); } if (this.props.lineNumbers !== prevProps.lineNumbers) { - this._cm.setOption('lineNumbers', this.props.lineNumbers); + this._cm.dispatch({ + effects: this.compartments.lineNumbers.reconfigure( + this.props.lineNumbers ? lineNumbers() : [] + ) + }); } if ( this.props.autocloseBracketsQuotes !== prevProps.autocloseBracketsQuotes ) { - this._cm.setOption( + /* this._cm5.setOption( 'autoCloseBrackets', this.props.autocloseBracketsQuotes - ); + ); */ } if (this.props.runtimeErrorWarningVisible) { @@ -262,7 +355,7 @@ class Editor extends React.Component { // LOL const errorObj = { stack: consoleEvent.data[0].toString() }; StackTrace.fromError(errorObj).then((stackLines) => { - this.props.expandConsole(); + this.props.dispatch(expandConsole()); const line = stackLines.find( (l) => l.fileName && l.fileName.startsWith('/') ); @@ -273,164 +366,93 @@ class Editor extends React.Component { const fileWithError = this.props.files.find( (f) => f.name === fileName && f.filePath === filePath ); - this.props.setSelectedFile(fileWithError.id); - this._cm.addLineClass( + this.props.dispatch(setSelectedFile(fileWithError.id)); + // TODO: instead of addLineClass, use line decorations: + // https://codemirror.net/examples/zebra/ + // https://discuss.codemirror.net/t/how-to-add-line-class-to-a-specific-line-dynamically/6230 + // https://discuss.codemirror.net/t/equivalent-for-addlineclass-in-cm6/4356 + // https://discuss.codemirror.net/t/how-to-add-classes-to-lines/3039/3 + /* this._cm5.addLineClass( line.lineNumber - 1, 'background', 'line-runtime-error' - ); + ); */ }); } }); } else { - for (let i = 0; i < this._cm.lineCount(); i += 1) { - this._cm.removeLineClass(i, 'background', 'line-runtime-error'); + for (let i = 0; i < this._cm.state.doc.lines; i += 1) { + // this._cm5.removeLineClass(i, 'background', 'line-runtime-error'); } } } if (this.props.file.id !== prevProps.file.id) { - for (let i = 0; i < this._cm.lineCount(); i += 1) { - this._cm.removeLineClass(i, 'background', 'line-runtime-error'); + for (let i = 0; i < this._cm.state.doc.lines; i += 1) { + // this._cm5.removeLineClass(i, 'background', 'line-runtime-error'); } } } componentWillUnmount() { + this._cm5 = null; + this._cm.destroy(); this._cm = null; this.props.provideController(null); } - getFileMode(fileName) { - let mode; - if (fileName.match(/.+\.js$/i)) { - mode = 'javascript'; - } else if (fileName.match(/.+\.css$/i)) { - mode = 'css'; - } else if (fileName.match(/.+\.(html|xml)$/i)) { - mode = 'htmlmixed'; - } else if (fileName.match(/.+\.json$/i)) { - mode = 'application/json'; - } else if (fileName.match(/.+\.(frag|glsl)$/i)) { - mode = 'x-shader/x-fragment'; - } else if (fileName.match(/.+\.(vert|stl)$/i)) { - mode = 'x-shader/x-vertex'; - } else { - mode = 'text/plain'; - } - return mode; - } - getContent() { - const content = this._cm.getValue(); - const updatedFile = Object.assign({}, this.props.file, { content }); - return updatedFile; + return { + ...this.props.file, + content: this._cm.state.doc.toString() + }; } showFind() { - this._cm.execCommand('findPersistent'); + openSearchPanel(this._cm); } showReplace() { - this._cm.execCommand('replace'); - } - - prettierFormatWithCursor(parser, plugins) { - try { - const { formatted, cursorOffset } = prettier.formatWithCursor( - this._cm.doc.getValue(), - { - cursorOffset: this._cm.doc.indexFromPos(this._cm.doc.getCursor()), - parser, - plugins - } - ); - const { left, top } = this._cm.getScrollInfo(); - this._cm.doc.setValue(formatted); - this._cm.focus(); - this._cm.doc.setCursor(this._cm.doc.posFromIndex(cursorOffset)); - this._cm.scrollTo(left, top); - } catch (error) { - console.error(error); - } + // this._cm5.execCommand('replace'); + // TODO: how to open with replace section expanded? + // openSearchPanel(this._cm); + replaceNext(this._cm); } tidyCode() { - const mode = this._cm.getOption('mode'); - if (mode === 'javascript') { - this.prettierFormatWithCursor('babel', [babelParser]); - } else if (mode === 'css') { - this.prettierFormatWithCursor('css', [cssParser]); - } else if (mode === 'htmlmixed') { - this.prettierFormatWithCursor('html', [htmlParser]); - } + tidyCode(this._cm, this.props.file.name); } - initializeDocuments(files) { - this._docs = {}; - files.forEach((file) => { - if (file.name !== 'root') { - this._docs[file.id] = CodeMirror.Doc( - file.content, - this.getFileMode(file.name) - ); // eslint-disable-line - } + replaceFileContent(content) { + this._cm.dispatch({ + changes: { from: 0, to: this._cm.state.doc.length, insert: content } }); } render() { - const editorSectionClass = classNames({ - editor: true, - 'sidebar--contracted': !this.props.isExpanded - }); - const editorHolderClass = classNames({ 'editor-holder': true, 'editor-holder--hidden': - this.props.file.fileType === 'folder' || this.props.file.url + this.props.file.fileType === 'folder' || this.props.file.url, + [`cm-s-p5-${this.props.theme}`]: true }); return ( -
-
- - -
- - {this.props.file.name} - - {this.props.unsavedChanges ? ( - - ) : null} - - - -
-
-
+ { this.codemirrorContainer = element; }} className={editorHolderClass} /> - -
+ {this._cm && + createPortal( +
+ +
, + searchContainer + )} + ); } } @@ -454,10 +476,6 @@ Editor.propTypes = { args: PropTypes.arrayOf(PropTypes.string) }) ).isRequired, - updateLintMessage: PropTypes.func.isRequired, - clearLintMessage: PropTypes.func.isRequired, - updateFileContent: PropTypes.func.isRequired, - fontSize: PropTypes.number.isRequired, file: PropTypes.shape({ name: PropTypes.string.isRequired, content: PropTypes.string.isRequired, @@ -465,10 +483,8 @@ Editor.propTypes = { fileType: PropTypes.string.isRequired, url: PropTypes.string }).isRequired, - setUnsavedChanges: PropTypes.func.isRequired, - startSketch: PropTypes.func.isRequired, - autorefresh: PropTypes.bool.isRequired, - isPlaying: PropTypes.bool.isRequired, + // autorefresh: PropTypes.bool.isRequired, + // isPlaying: PropTypes.bool.isRequired, theme: PropTypes.string.isRequired, unsavedChanges: PropTypes.bool.isRequired, files: PropTypes.arrayOf( @@ -478,17 +494,9 @@ Editor.propTypes = { content: PropTypes.string.isRequired }) ).isRequired, - isExpanded: PropTypes.bool.isRequired, - collapseSidebar: PropTypes.func.isRequired, - expandSidebar: PropTypes.func.isRequired, - clearConsole: PropTypes.func.isRequired, - // showRuntimeErrorWarning: PropTypes.func.isRequired, - hideRuntimeErrorWarning: PropTypes.func.isRequired, runtimeErrorWarningVisible: PropTypes.bool.isRequired, provideController: PropTypes.func.isRequired, - t: PropTypes.func.isRequired, - setSelectedFile: PropTypes.func.isRequired, - expandConsole: PropTypes.func.isRequired + dispatch: PropTypes.func.isRequired }; function mapStateToProps(state) { @@ -498,40 +506,13 @@ function mapStateToProps(state) { state.files.find((file) => file.isSelectedFile) || state.files.find((file) => file.name === 'sketch.js') || state.files.find((file) => file.name !== 'root'), - htmlFile: getHTMLFile(state.files), - ide: state.ide, - preferences: state.preferences, - editorAccessibility: state.editorAccessibility, - user: state.user, - project: state.project, - toast: state.toast, consoleEvents: state.console, - ...state.preferences, ...state.ide, - ...state.project, - ...state.editorAccessibility, - isExpanded: state.ide.sidebarIsExpanded + lintMessages: state.editorAccessibility.lintMessages, + unsavedChanges: state.ide.unsavedChanges, + runtimeErrorWarningVisible: state.ide.runtimeErrorWarningVisible }; } -function mapDispatchToProps(dispatch) { - return bindActionCreators( - Object.assign( - {}, - EditorAccessibilityActions, - FileActions, - ProjectActions, - IDEActions, - PreferencesActions, - UserActions, - ToastActions, - ConsoleActions - ), - dispatch - ); -} - -export default withTranslation()( - connect(mapStateToProps, mapDispatchToProps)(Editor) -); +export default connect(mapStateToProps)(Editor); diff --git a/client/modules/IDE/components/EditorAccessibility.jsx b/client/modules/IDE/components/EditorAccessibility.jsx index 5095f07ff6..70e3b9858a 100644 --- a/client/modules/IDE/components/EditorAccessibility.jsx +++ b/client/modules/IDE/components/EditorAccessibility.jsx @@ -1,9 +1,29 @@ import PropTypes from 'prop-types'; -import React from 'react'; +import React, { useEffect, useRef } from 'react'; import { useTranslation } from 'react-i18next'; +import { useSelector } from 'react-redux'; +import beepUrl from '../../../sounds/audioAlert.mp3'; + +// TODO: need to pass down the line number (or store in redux) instead of modifying the DOM. const EditorAccessibility = ({ lintMessages = [] }) => { const { t } = useTranslation(); + + const audioWarningEnabled = useSelector( + (state) => state.preferences.lintWarning + ); + + // const lintMessages = useSelector((state) => state.editorAccessibility.lintMessages); + + const beep = useRef(new Audio(beepUrl)); + + useEffect(() => { + if (audioWarningEnabled && lintMessages.length > 0) { + beep.play(); + // TODO: check that this works. + } + }, [beep, lintMessages, audioWarningEnabled]); + return (
    diff --git a/client/modules/IDE/components/EditorSection.jsx b/client/modules/IDE/components/EditorSection.jsx new file mode 100644 index 0000000000..cb1e1f49a8 --- /dev/null +++ b/client/modules/IDE/components/EditorSection.jsx @@ -0,0 +1,75 @@ +import classNames from 'classnames'; +import PropTypes from 'prop-types'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import { useDispatch, useSelector } from 'react-redux'; +import LeftArrowIcon from '../../../images/left-arrow.svg'; +import RightArrowIcon from '../../../images/right-arrow.svg'; +import UnsavedChangesDotIcon from '../../../images/unsaved-changes-dot.svg'; +import { collapseSidebar, expandSidebar } from '../actions/ide'; +import EditorAccessibility from '../components/EditorAccessibility'; +import Timer from '../components/Timer'; +// import { selectActiveFile } from '../selectors/files'; +const selectActiveFile = () => 'fix'; + +function EditorSection({ children }) { + const { t } = useTranslation(); + + const dispatch = useDispatch(); + + const sidebarIsExpanded = useSelector((state) => state.ide.sidebarIsExpanded); + const currentFile = useSelector(selectActiveFile); + const hasUnsavedChanges = useSelector((state) => state.ide.unsavedChanges); + const lintMessages = useSelector( + (state) => state.editorAccessibility.lintMessages + ); + + const editorSectionClass = classNames({ + editor: true, + 'sidebar--contracted': !sidebarIsExpanded + }); + + return ( +
    +
    + + +
    + + {currentFile.name} + + {hasUnsavedChanges ? ( + + ) : null} + + + +
    +
    + {children} + +
    + ); +} + +EditorSection.propTypes = { + children: PropTypes.node.isRequired +}; + +export default EditorSection; diff --git a/client/modules/IDE/pages/IDEView.jsx b/client/modules/IDE/pages/IDEView.jsx index 3c323fe88c..34adf3c355 100644 --- a/client/modules/IDE/pages/IDEView.jsx +++ b/client/modules/IDE/pages/IDEView.jsx @@ -6,7 +6,7 @@ import { withRouter } from 'react-router'; import { withTranslation } from 'react-i18next'; import { Helmet } from 'react-helmet'; import SplitPane from 'react-split-pane'; -import Editor from '../components/Editor'; +import EditorSection from '../components/EditorSection'; import Sidebar from '../components/Sidebar'; import PreviewFrame from '../components/PreviewFrame'; import Toolbar from '../components/Toolbar'; @@ -35,6 +35,7 @@ import Feedback from '../components/Feedback'; import { CollectionSearchbar } from '../components/Searchbar'; import { getIsUserOwner } from '../selectors/users'; import RootPage from '../../../components/RootPage'; +import CodeMirrorEditor from '../../CodeMirror/CodeMirrorEditor'; function getTitle(props) { const { id } = props.project; @@ -345,11 +346,13 @@ class IDEView extends React.Component { allowResize={this.props.ide.consoleIsExpanded} className="editor-preview-subpanel" > - { - this.cmController = ctl; - }} - /> + + { + this.cmController = ctl; + }} + /> +
    diff --git a/client/modules/IDE/selectors/files.js b/client/modules/IDE/selectors/files.js new file mode 100644 index 0000000000..e2044b6d89 --- /dev/null +++ b/client/modules/IDE/selectors/files.js @@ -0,0 +1,15 @@ +import { createSelector } from 'reselect'; + +const selectFiles = (state) => state.files; + +export const selectRootFile = createSelector(selectFiles, (files) => + files.find((file) => file.name === 'root') +); + +export const selectActiveFile = createSelector( + selectFiles, + (files) => + files.find((file) => file.isSelectedFile) || + files.find((file) => file.name === 'sketch.js') || + files.find((file) => file.name !== 'root') +); diff --git a/client/styles/components/_console-input.scss b/client/styles/components/_console-input.scss index 84db1f3387..7b2e3a5b1b 100644 --- a/client/styles/components/_console-input.scss +++ b/client/styles/components/_console-input.scss @@ -29,24 +29,24 @@ .console__editor { margin-left: #{15 / $base-font-size}rem; flex: 1; - & .CodeMirror { + & .cm-editor { height: auto; } - & .CodeMirror-lines { + & .cm-content { padding-top: #{2 / $base-font-size}rem; } } -.console__editor .CodeMirror { +.console__editor .cm-editor { border: none; font-family: Inconsolata,monospace; @include themify() { background-color: getThemifyVariable('console-input-background-color'); } - .CodeMirror-line { + .cm-line { @include themify() { color: getThemifyVariable('console-color'); } } -} \ No newline at end of file +} diff --git a/client/styles/components/_editor.scss b/client/styles/components/_editor.scss index 01b4b66db1..190d55df2a 100644 --- a/client/styles/components/_editor.scss +++ b/client/styles/components/_editor.scss @@ -1,65 +1,28 @@ -.CodeMirror { +.cm-editor { font-family: Inconsolata, monospace; height: 100%; } -.CodeMirror-linenumbers { - padding-right: #{10 / $base-font-size}rem; - +.cm-lineNumbers { + align-items: flex-end; + padding-right: #{10 / $base-font-size}rem; } -.CodeMirror-linenumber { - width: #{32 / $base-font-size}rem; - left: #{-3 / $base-font-size}rem !important; +.cm-lineNumbers .cm-gutterElement { @include themify() { color: getThemifyVariable('inactive-text-color'); } } -.CodeMirror-lines { +.cm-scroller .cm-content { padding-top: #{25 / $base-font-size}rem; } -pre.CodeMirror-line { +.cm-line { padding-left: #{5 / $base-font-size}rem; } -.CodeMirror-gutter-wrapper { - right: 100%; - top: 0; - bottom: 0; -} - -.CodeMirror-lint-marker-warning, .CodeMirror-lint-marker-error, .CodeMirror-lint-marker-multiple { - background-image: none; - width: #{49 / $base-font-size}rem; - position: absolute; - height: 100%; - right: 100%; -} - -.CodeMirror-lint-message-error, .CodeMirror-lint-message-warning { - background-image: none; - padding-left: inherit; -} - -.CodeMirror-lint-marker-warning { - background-color: rgb(255, 190, 5); -} - -.CodeMirror-lint-marker-error { - background-color: rgb(255, 95, 82); -} - -.CodeMirror-gutter-elt:not(.CodeMirror-linenumber) { - opacity: 0.2; - width: #{49 / $base-font-size}rem !important; - height: 100%; - left: 49px !important; - // background-color: rgb(255, 95, 82); -} - -.CodeMirror-lint-tooltip { +.cm-tooltip-lint { @include themify() { background-color: getThemifyVariable('modal-background-color'); border: 1px solid getThemifyVariable('modal-border-color'); @@ -70,13 +33,11 @@ pre.CodeMirror-line { font-family: Montserrat, sans-serif; } -.CodeMirror-gutters { +.cm-gutters { @include themify() { background-color: getThemifyVariable('editor-gutter-color'); border-color: getThemifyVariable('ide-border-color'); } - // left: 0 !important; - width: #{48 / $base-font-size}rem; } /* @@ -107,12 +68,12 @@ pre.CodeMirror-line { .CodeMirror-find-popup-container { display: flex; - flex-wrap: wrap; + flex-wrap: wrap-reverse; justify-content: space-between; + align-items: stretch; } .Toggle-replace-btn-div { - height: #{40 / $base-font-size}rem; padding: 0; } @@ -146,7 +107,7 @@ pre.CodeMirror-line { .CodeMirror-search-controls { width: 60%; display: flex; - flex-wrap: wrap-reverse; + flex-wrap: wrap; justify-content: flex-start; align-items: flex-end; } @@ -211,9 +172,7 @@ pre.CodeMirror-line { align-items: center; } -.CodeMirror-regexp-button, -.CodeMirror-case-button, -.CodeMirror-word-button { +.CodeMirror-search-modifier-button { @include themify() { // @extend %button; padding: #{2 / $base-font-size}rem #{7 / $base-font-size}rem; @@ -232,19 +191,13 @@ pre.CodeMirror-line { word-break: keep-all; white-space: nowrap; -} - -.CodeMirror-regexp-button .label, -.CodeMirror-case-button .label, -.CodeMirror-word-button .label { - @extend %hidden-element; -} -[aria-checked="true"] { - @include themify() { - color: getThemifyVariable("heavy-text-color"); - background-color: getThemifyVariable("button-secondary-background-color"); - border-color: getThemifyVariable("button-border-color"); + &[aria-checked="true"] { + @include themify() { + color: getThemifyVariable("heavy-text-color"); + background-color: getThemifyVariable("button-secondary-background-color"); + border-color: getThemifyVariable("button-border-color"); + } } } @@ -261,6 +214,7 @@ pre.CodeMirror-line { margin-right: #{10 / $base-font-size}rem; } +// LP: this is for the right gutter scrollbar -- need to implement .CodeMirror-search-match { background: gold; border-top: #{1 / $base-font-size}rem solid orange; @@ -278,61 +232,7 @@ pre.CodeMirror-line { } // foldgutter -.CodeMirror-foldmarker { - text-shadow: -1px 0 #ed225d, 0 1px #ed225d, 1px 0 #ed225d, 0 -1px #ed225d; - color: #FFF; - /* background-color: rgba(237, 34, 93, 0.42); */ - /* border-radius: 3px; */ - font-weight: bold; - font-family: arial; - line-height: .3; - cursor: pointer; - opacity: 0.75; -} -.CodeMirror-foldgutter { - width: 2.7em; -} -.CodeMirror-foldgutter-open, -.CodeMirror-foldgutter-folded { - cursor: pointer; - padding-bottom: 0.4em; - text-align: right; - line-height: 1.0; -} -.CodeMirror-foldgutter-open:after { - content: "\25BE"; -} -.CodeMirror-foldgutter-folded:after { - content: "\25B8"; -} - -.CodeMirror-foldgutter-open, .CodeMirror-foldgutter-folded { - position: absolute; - right: 100%; -} - -.CodeMirror-foldgutter-open:after { - @include themify() { - background-image: getThemifyVariable('codefold-icon-open'); - } -} - -.CodeMirror-foldgutter-folded:after { - @include themify() { - background-image: getThemifyVariable('codefold-icon-closed'); - } -} - -.CodeMirror-foldgutter-folded:after, -.CodeMirror-foldgutter-open:after { - background-size: 10px 10px; - content: ""; - padding-left: 15px; - background-repeat: no-repeat; - background-position: center center; -} - -.CodeMirror-foldmarker { +.cm-foldPlaceholder { text-shadow: none; border-radius: 5px; opacity: 1; @@ -343,10 +243,11 @@ pre.CodeMirror-line { line-height: 0.7; padding: 0 #{5 / $base-font-size}rem; font-family: serif; + cursor: pointer; } -.line-runtime-error + .CodeMirror-activeline-gutter { +.line-runtime-error + .cm-activeLineGutter { background-color: rgb(255, 95, 82); opacity: 0.3; } @@ -390,16 +291,21 @@ pre.CodeMirror-line { /** Inline abbreviation preview */ -.emmet-abbreviation-preview { + +// TODO: style tags within the modal -- has an autogenerated CSS class +// https://github.com/emmetio/codemirror6-plugin/blob/de142116cbe4003c22a79436351ead9b600ae6e3/src/tracker/index.ts#L295 + +.emmet-preview { @extend %modal; position: absolute; @include themify() { background: getThemifyVariable('background-color'); } - & .CodeMirror-lines { + // Note: unsets padding added by .cm-scroller .cm-content + & .cm-scroller .cm-content { padding: 0; } - & .CodeMirror { + & .cm-editor { height: auto; max-width: #{400 / $base-font-size}rem; max-height: #{300 / $base-font-size}rem; @@ -407,22 +313,19 @@ pre.CodeMirror-line { } } -.emmet-abbreviation-preview:not(.has-error) .emmet-abbreviation-preview-error { - display: none; -} - -.emmet-abbreviation-preview.has-error .CodeMirror { +.emmet-preview_error { display: none; } -.emmet-abbreviation-preview .CodeMirror-cursors { +.emmet-preview .CodeMirror-cursors { visibility: hidden !important; } -.emmet-abbreviation-preview .emmet-error-snippet-message { +.emmet-preview .emmet-error-snippet-message { padding: 5px; } +// TODO: don't see an equivalent .emmet-open-tag, .emmet-close-tag { text-decoration: underline; } diff --git a/client/styles/components/_p5-contrast-codemirror-theme.scss b/client/styles/components/_p5-contrast-codemirror-theme.scss index b5ae00d991..63a96bdea8 100644 --- a/client/styles/components/_p5-contrast-codemirror-theme.scss +++ b/client/styles/components/_p5-contrast-codemirror-theme.scss @@ -31,47 +31,47 @@ $p5-contrast-activeline: #999999; color: $p5-contrast-white; } -.cm-s-p5-contrast span .cm-comment { +.cm-s-p5-contrast span.tok-comment { color: $p5-contrast-lightgray; } -.cm-s-p5-contrast span .cm-def { - color: $p5-contrast-blue; -} - -.cm-s-p5-contrast span .cm-string { +.cm-s-p5-contrast span.tok-string { color: $p5-contrast-green; } -.cm-s-p5-contrast span .cm-string-2 { +.cm-s-p5-contrast span.tok-string2 { color: $p5-contrast-green; } -.cm-s-p5-contrast span .cm-number { +.cm-s-p5-contrast span.tok-number { color: $p5-contrast-pink; } -.cm-s-p5-contrast span .cm-keyword { +.cm-s-p5-contrast span.tok-keyword { color: $p5-contrast-yellow; } -.cm-s-p5-contrast span .cm-variable { +.cm-s-p5-contrast span.tok-variableName { color: $p5-contrast-white; } -.cm-s-p5-contrast span .cm-variable-2 { +.cm-s-p5-contrast span.tok-variableName2 { color: $p5-contrast-white; } -.cm-s-p5-contrast span .cm-property { +.cm-s-p5-contrast span.tok-definition { + color: $p5-contrast-blue; +} + +.cm-s-p5-contrast span.tok-propertyName { color: $p5-contrast-white; } -.cm-s-p5-contrast span .cm-atom { +.cm-s-p5-contrast span.tok-atom { color: $p5-contrast-pink; } -.cm-s-p5-contrast span .cm-operator { +.cm-s-p5-contrast span.tok-operator { color: $p5-contrast-lightgray; } @@ -83,20 +83,19 @@ $p5-contrast-activeline: #999999; background-color: $p5-contrast-selected; } -.cm-s-p5-contrast .CodeMirror-activeline-background { +.cm-s-p5-contrast .cm-activeLine { background-color: $dark; } -.cm-s-p5-contrast .CodeMirror-activeline-gutter { +.cm-s-p5-contrast .cm-activeLineGutter { background-color: $dark; - border-right: 1px solid $middle-dark; } .cm-s-p5-contrast .cm-error { color: #f00; } -.cm-s-p5-contrast span .CodeMirror-matchingbracket { +.cm-s-p5-contrast span .cm-matchingBracket { outline: 1px solid $p5-contrast-lightgray; outline-offset: 1px; color: $p5-contrast-white !important; @@ -118,16 +117,20 @@ $p5-contrast-activeline: #999999; color: $p5-contrast-white; } -.cm-s-p5-contrast .cm-p5-function { - color: $p5-contrast-blue; +.cm-s-p5-contrast .p5-function { + &, & > .tok-variableName { + color: $p5-contrast-blue; + } } -.cm-s-p5-contrast .cm-p5-variable { - color: $p5-contrast-pink; - font-weight: bold; +.cm-s-p5-contrast .p5-variable { + &, & > .tok-variableName { + color: $p5-contrast-pink; + font-weight: bold; + } } -.cm-s-p5-contrast .CodeMirror-foldmarker { +.cm-s-p5-contrast .cm-foldPlaceholder { background-color: white; color: #333; } @@ -136,12 +139,12 @@ $p5-contrast-activeline: #999999; border-left: 1px solid $p5-contrast-white; } -.cm-s-p5-contrast .cm-searching { +.cm-s-p5-contrast .cm-searchMatch { // background-color: $p5js-pink-opacity; background-color: $medium-dark; } -.cm-s-p5-contrast .cm-searching.CodeMirror-selectedtext { +.cm-s-p5-contrast .cm-searchMatch.cm-searchMatch-selected { // background-color: $medium-dark; outline: #{1 / $base-font-size}rem solid $p5-contrast-white; } diff --git a/client/styles/components/_p5-dark-codemirror-theme.scss b/client/styles/components/_p5-dark-codemirror-theme.scss index 68925469ac..8734ce10af 100644 --- a/client/styles/components/_p5-dark-codemirror-theme.scss +++ b/client/styles/components/_p5-dark-codemirror-theme.scss @@ -36,47 +36,43 @@ $p5-dark-error: #df3a3d; color: $p5-dark-white; } -.cm-s-p5-dark span.cm-comment { +.cm-s-p5-dark span.tok-comment { color: $p5-dark-gray; } -.cm-s-p5-dark span.cm-def { - color: $p5-dark-lightblue; -} - -.cm-s-p5-dark span.cm-string { +.cm-s-p5-dark span.tok-string { color: $p5-dark-green; } -.cm-s-p5-dark span.cm-string-2 { +.cm-s-p5-dark span.tok-string2 { color: $p5-dark-orange; } -.cm-s-p5-dark span.cm-number { +.cm-s-p5-dark span.tok-number { color: $p5-dark-white; } -.cm-s-p5-dark span.cm-keyword { +.cm-s-p5-dark span.tok-keyword { color: $p5-dark-goldbrown; } -.cm-s-p5-dark span.cm-variable { +.cm-s-p5-dark span.tok-variableName { color: $p5-dark-lightblue; } -.cm-s-p5-dark span.cm-variable-2 { +.cm-s-p5-dark span.tok-variableName2 { color: $p5-dark-white; } -.cm-s-p5-dark span.cm-property { +.cm-s-p5-dark span.tok-propertyName { color: $p5-dark-white; } -.cm-s-p5-dark span.cm-atom { +.cm-s-p5-dark span.tok-atom { color: $p5-dark-pink; } -.cm-s-p5-dark span.cm-operator { +.cm-s-p5-dark span.tok-operator { color: $p5-dark-white; } @@ -88,16 +84,15 @@ $p5-dark-error: #df3a3d; background-color: $p5-dark-selected; } -.cm-s-p5-dark .CodeMirror-activeline-background { +.cm-s-p5-dark .cm-activeLine { background-color: $dark; } -.cm-s-p5-dark .CodeMirror-activeline-gutter { +.cm-s-p5-dark .cm-activeLineGutter { background-color: $dark; - border-right: 1px solid $middle-dark; } -.cm-s-p5-dark span.CodeMirror-matchingbracket { +.cm-s-p5-dark span.cm-matchingBracket { outline: 1px solid $p5-dark-gray; outline-offset: 1px; color: $p5-dark-white !important; @@ -124,17 +119,21 @@ $p5-dark-error: #df3a3d; color: $p5-dark-lightblue; } -.cm-s-p5-dark .cm-p5-function { - color: $p5-dark-lightblue; - font-weight: bold !important; +.cm-s-p5-dark .p5-function { + &, & > .tok-variableName { + color: $p5-dark-lightblue; + font-weight: bold !important; + } } -.cm-s-p5-dark .cm-p5-variable { - color: $p5-dark-pink; - font-weight: bold; +.cm-s-p5-dark .p5-variable { + &, & > .tok-variableName { + color: $p5-dark-pink; + font-weight: bold; + } } -.cm-s-p5-dark .CodeMirror-foldmarker { +.cm-s-p5-dark .cm-foldPlaceholder { background-color: white; color: #333; } @@ -143,11 +142,11 @@ $p5-dark-error: #df3a3d; border-left: 1px solid $p5-dark-white; } -.cm-s-p5-dark .cm-searching { +.cm-s-p5-dark .cm-searchMatch { background-color: $p5js-pink-opacity; } -.cm-s-p5-dark .CodeMirror-selectedtext { +.cm-s-p5-dark .cm-searchMatch.cm-searchMatch-selected { background-color: $medium-dark; } diff --git a/client/styles/components/_p5-light-codemirror-theme.scss b/client/styles/components/_p5-light-codemirror-theme.scss index ca30e2d854..5e0001d42a 100644 --- a/client/styles/components/_p5-light-codemirror-theme.scss +++ b/client/styles/components/_p5-light-codemirror-theme.scss @@ -31,47 +31,43 @@ $p5-light-activeline: rgb(207, 207, 207); color: $p5-light-black; } -.cm-s-p5-light span .cm-comment { +.cm-s-p5-light span.tok-comment { color: $p5-light-lightgray; } -.cm-s-p5-light span .cm-def { - color: $p5-light-blue; -} - -.cm-s-p5-light span .cm-string { +.cm-s-p5-light span.tok-string { color: $p5-light-green; } -.cm-s-p5-light span .cm-string-2 { +.cm-s-p5-light span.tok-string2 { color: $p5-light-orange; } -.cm-s-p5-light span .cm-number { +.cm-s-p5-light span.tok-number { color: $p5-light-black; } -.cm-s-p5-light .cm-keyword { +.cm-s-p5-light .tok-keyword { color: $p5-light-brown; } -.cm-s-p5-light span .cm-variable { +.cm-s-p5-light span.tok-variableName { color: $p5-light-blue; } -.cm-s-p5-light span .cm-variable2 { +.cm-s-p5-light span.tok-variableName2 { color: $p5-light-black; } -.cm-s-p5-light span .cm-property { +.cm-s-p5-light span.tok-propertyName { color: $p5-light-black; } -.cm-s-p5-light span .cm-atom { +.cm-s-p5-light span.tok-atom { color: $p5-light-pink; } -.cm-s-p5-light span .cm-operator { +.cm-s-p5-light span.tok-operator { color: $p5-light-brown; } @@ -83,20 +79,19 @@ $p5-light-activeline: rgb(207, 207, 207); background-color: $p5-light-selected; } -.cm-s-p5-light .CodeMirror-activeline-background { +.cm-s-p5-light .cm-activeLine { background-color: $light; } -.cm-s-p5-light .CodeMirror-activeline-gutter { +.cm-s-p5-light .cm-activeLineGutter { background-color: $light; - border-right: 1px solid $medium-light; } .cm-s-p5-light .cm-error { color: #f00; } -.cm-s-p5-light span .CodeMirror-matchingbracket { +.cm-s-p5-light span .cm-matchingBracket { outline: 1px solid $p5-light-gray; outline-offset: 1px; color: $p5-light-black !important; @@ -106,6 +101,7 @@ $p5-light-activeline: rgb(207, 207, 207); color: $p5-light-blue; } +// TODO: cm-tag in HTML is now tok-typeName & tok-punctuation .cm-s-p5-light span .cm-tag { color: $p5-light-pink; } @@ -118,16 +114,20 @@ $p5-light-activeline: rgb(207, 207, 207); color: $p5-light-black; } -.cm-s-p5-light .cm-p5-function { - color: $p5-light-blue; - font-weight: bold; +.cm-s-p5-light .p5-function { + &, & > .tok-variableName { + color: $p5-light-blue; + font-weight: bold; + } } -.cm-s-p5-light .cm-p5-variable { - color: $p5-light-pink; +.cm-s-p5-light .p5-variable { + &, & > .tok-variableName { + color: $p5-light-pink; + } } -.cm-s-p5-light .CodeMirror-foldmarker { +.cm-s-p5-light .cm-foldPlaceholder { background-color: #333; color: white; } @@ -136,10 +136,10 @@ $p5-light-activeline: rgb(207, 207, 207); border-left: 1px solid $p5-light-black; } -.cm-s-p5-light .cm-searching { +.cm-s-p5-light .cm-searchMatch { background-color: $p5js-pink-opacity; } -.cm-s-p5-light .CodeMirror-selectedtext { +.cm-s-p5-light .cm-searchMatch.cm-searchMatch-selected { background-color: $medium-light; } diff --git a/client/styles/main.scss b/client/styles/main.scss index 61397cbc32..768ce6e358 100644 --- a/client/styles/main.scss +++ b/client/styles/main.scss @@ -12,9 +12,9 @@ @import 'node_modules/dropzone/dist/dropzone'; @import 'node_modules/primer-tooltips/build/build'; -@import 'components/p5-light-codemirror-theme'; @import 'components/p5-dark-codemirror-theme'; @import 'components/p5-contrast-codemirror-theme'; +@import 'components/p5-light-codemirror-theme'; @import 'components/account'; @import 'components/api-key'; @import 'components/editor'; diff --git a/client/utils/htmlmixed.js b/client/utils/htmlmixed.js deleted file mode 100644 index 23a0eacf05..0000000000 --- a/client/utils/htmlmixed.js +++ /dev/null @@ -1,153 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: http://codemirror.net/LICENSE -/* eslint-disable */ - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("codemirror"), require("codemirror/mode/xml/xml"), require("./p5-javascript"), require("codemirror/mode/css/css")); - else if (typeof define == "function" && define.amd) // AMD - define(["codemirror", "codemirror/mode/xml/xml", "./p5-javascript", "codemirror/mode/css/css"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { - "use strict"; - - var defaultTags = { - script: [ - ["lang", /(javascript|babel)/i, "javascript"], - ["type", /^(?:text|application)\/(?:x-)?(?:java|ecma)script$|^$/i, "javascript"], - ["type", /./, "text/plain"], - [null, null, "javascript"] - ], - style: [ - ["lang", /^css$/i, "css"], - ["type", /^(text\/)?(x-)?(stylesheet|css)$/i, "css"], - ["type", /./, "text/plain"], - [null, null, "css"] - ] - }; - - function maybeBackup(stream, pat, style) { - var cur = stream.current(), close = cur.search(pat); - if (close > -1) { - stream.backUp(cur.length - close); - } else if (cur.match(/<\/?$/)) { - stream.backUp(cur.length); - if (!stream.match(pat, false)) stream.match(cur); - } - return style; - } - - var attrRegexpCache = {}; - function getAttrRegexp(attr) { - var regexp = attrRegexpCache[attr]; - if (regexp) return regexp; - return attrRegexpCache[attr] = new RegExp("\\s+" + attr + "\\s*=\\s*('|\")?([^'\"]+)('|\")?\\s*"); - } - - function getAttrValue(text, attr) { - var match = text.match(getAttrRegexp(attr)) - return match ? /^\s*(.*?)\s*$/.exec(match[2])[1] : "" - } - - function getTagRegexp(tagName, anchored) { - return new RegExp((anchored ? "^" : "") + "<\/\s*" + tagName + "\s*>", "i"); - } - - function addTags(from, to) { - for (var tag in from) { - var dest = to[tag] || (to[tag] = []); - var source = from[tag]; - for (var i = source.length - 1; i >= 0; i--) - dest.unshift(source[i]) - } - } - - function findMatchingMode(tagInfo, tagText) { - for (var i = 0; i < tagInfo.length; i++) { - var spec = tagInfo[i]; - if (!spec[0] || spec[1].test(getAttrValue(tagText, spec[0]))) return spec[2]; - } - } - - CodeMirror.defineMode("htmlmixed", function (config, parserConfig) { - var htmlMode = CodeMirror.getMode(config, { - name: "xml", - htmlMode: true, - multilineTagIndentFactor: parserConfig.multilineTagIndentFactor, - multilineTagIndentPastTag: parserConfig.multilineTagIndentPastTag - }); - - var tags = {}; - var configTags = parserConfig && parserConfig.tags, configScript = parserConfig && parserConfig.scriptTypes; - addTags(defaultTags, tags); - if (configTags) addTags(configTags, tags); - if (configScript) for (var i = configScript.length - 1; i >= 0; i--) - tags.script.unshift(["type", configScript[i].matches, configScript[i].mode]) - - function html(stream, state) { - var style = htmlMode.token(stream, state.htmlState), tag = /\btag\b/.test(style), tagName - if (tag && !/[<>\s\/]/.test(stream.current()) && - (tagName = state.htmlState.tagName && state.htmlState.tagName.toLowerCase()) && - tags.hasOwnProperty(tagName)) { - state.inTag = tagName + " " - } else if (state.inTag && tag && />$/.test(stream.current())) { - var inTag = /^([\S]+) (.*)/.exec(state.inTag) - state.inTag = null - var modeSpec = stream.current() == ">" && findMatchingMode(tags[inTag[1]], inTag[2]) - var mode = CodeMirror.getMode(config, modeSpec) - var endTagA = getTagRegexp(inTag[1], true), endTag = getTagRegexp(inTag[1], false); - state.token = function (stream, state) { - if (stream.match(endTagA, false)) { - state.token = html; - state.localState = state.localMode = null; - return null; - } - return maybeBackup(stream, endTag, state.localMode.token(stream, state.localState)); - }; - state.localMode = mode; - state.localState = CodeMirror.startState(mode, htmlMode.indent(state.htmlState, "")); - } else if (state.inTag) { - state.inTag += stream.current() - if (stream.eol()) state.inTag += " " - } - return style; - }; - - return { - startState: function () { - var state = CodeMirror.startState(htmlMode); - return {token: html, inTag: null, localMode: null, localState: null, htmlState: state}; - }, - - copyState: function (state) { - var local; - if (state.localState) { - local = CodeMirror.copyState(state.localMode, state.localState); - } - return {token: state.token, inTag: state.inTag, - localMode: state.localMode, localState: local, - htmlState: CodeMirror.copyState(htmlMode, state.htmlState)}; - }, - - token: function (stream, state) { - return state.token(stream, state); - }, - - indent: function (state, textAfter) { - if (!state.localMode || /^\s*<\//.test(textAfter)) - return htmlMode.indent(state.htmlState, textAfter); - else if (state.localMode.indent) - return state.localMode.indent(state.localState, textAfter); - else - return CodeMirror.Pass; - }, - - innerMode: function (state) { - return {state: state.localState || state.htmlState, mode: state.localMode || htmlMode}; - } - }; - }, "xml", "javascript", "css"); - - CodeMirror.defineMIME("text/html", "htmlmixed"); -}); diff --git a/client/utils/p5-javascript.js b/client/utils/p5-javascript.js deleted file mode 100644 index af34681c07..0000000000 --- a/client/utils/p5-javascript.js +++ /dev/null @@ -1,957 +0,0 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: https://codemirror.net/LICENSE - -/*eslint-disable*/ -var p5_javascript_template = require("./p5-keywords"); -var p5FunctionKeywords = p5_javascript_template.p5FunctionKeywords; -var p5VariableKeywords = p5_javascript_template.p5VariableKeywords; - -(function(mod) { - if (typeof exports == "object" && typeof module == "object") // CommonJS - mod(require("codemirror")); - else if (typeof define == "function" && define.amd) // AMD - define(["codemirror"], mod); - else // Plain browser env - mod(CodeMirror); -})(function(CodeMirror) { -"use strict"; - -CodeMirror.defineMode("javascript", function(config, parserConfig) { - var indentUnit = config.indentUnit; - var statementIndent = parserConfig.statementIndent; - var jsonldMode = parserConfig.jsonld; - var jsonMode = parserConfig.json || jsonldMode; - var isTS = parserConfig.typescript; - var wordRE = parserConfig.wordCharacters || /[\w$\xa1-\uffff]/; - - // Tokenizer - var keywords = function(){ - function kw(type) {return {type: type, style: "keyword"};} - var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c"); - var operator = kw("operator"), atom = {type: "atom", style: "atom"}; - - var jsKeywords = { - "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B, - "return": C, "break": C, "continue": C, "new": kw("new"), "delete": C, "throw": C, "debugger": C, - "var": kw("var"), "const": kw("var"), "let": kw("var"), - "function": kw("function"), "catch": kw("catch"), - "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"), - "in": operator, "typeof": operator, "instanceof": operator, - "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom, - "this": kw("this"), "class": kw("class"), "super": kw("atom"), - "yield": C, "export": kw("export"), "import": kw("import"), "extends": C, - "await": C, "async": kw("async") - }; - - for (var attr in p5FunctionKeywords) { - jsKeywords[attr] = p5FunctionKeywords[attr]; - } - - for (var attr in p5VariableKeywords) { - jsKeywords[attr] = p5VariableKeywords[attr]; - } - - // Extend the 'normal' keywords with the TypeScript language extensions - if (isTS) { - var type = {type: "variable", style: "variable-3"}; - var tsKeywords = { - // object-like things - "interface": kw("class"), - "implements": C, - "namespace": C, - "module": kw("module"), - "enum": kw("module"), - "type": kw("type"), - - // scope modifiers - "public": kw("modifier"), - "private": kw("modifier"), - "protected": kw("modifier"), - "abstract": kw("modifier"), - - // operators - "as": operator, - - // types - "string": type, "number": type, "boolean": type, "any": type - }; - - for (var attr in tsKeywords) { - jsKeywords[attr] = tsKeywords[attr]; - } - } - - return jsKeywords; -}(); - - var isOperatorChar = /[+\-*&%=<>!?|~^@]/; - var isJsonldKeyword = /^@(context|id|value|language|type|container|list|set|reverse|index|base|vocab|graph)"/; - - function readRegexp(stream) { - var escaped = false, next, inSet = false; - while ((next = stream.next()) != null) { - if (!escaped) { - if (next == "/" && !inSet) return; - if (next == "[") inSet = true; - else if (inSet && next == "]") inSet = false; - } - escaped = !escaped && next == "\\"; - } - } - - // Used as scratch variables to communicate multiple values without - // consing up tons of objects. - var type, content; - function ret(tp, style, cont) { - type = tp; content = cont; - return style; - } - function tokenBase(stream, state) { - var ch = stream.next(); - if (ch == '"' || ch == "'") { - state.tokenize = tokenString(ch); - return state.tokenize(stream, state); - } else if (ch == "." && stream.match(/^\d+(?:[eE][+\-]?\d+)?/)) { - return ret("number", "number"); - } else if (ch == "." && stream.match("..")) { - return ret("spread", "meta"); - } else if (/[\[\]{}\(\),;\:\.]/.test(ch)) { - return ret(ch); - } else if (ch == "=" && stream.eat(">")) { - return ret("=>", "operator"); - } else if (ch == "0" && stream.match(/^(?:x[\da-f]+|o[0-7]+|b[01]+)n?/i)) { - return ret("number", "number"); - } else if (/\d/.test(ch)) { - stream.match(/^\d*(?:n|(?:\.\d*)?(?:[eE][+\-]?\d+)?)?/); - return ret("number", "number"); - } else if (ch == "/") { - if (stream.eat("*")) { - state.tokenize = tokenComment; - return tokenComment(stream, state); - } else if (stream.eat("/")) { - stream.skipToEnd(); - return ret("comment", "comment"); - } else if (expressionAllowed(stream, state, 1)) { - readRegexp(stream); - stream.match(/^\b(([gimyus])(?![gimyus]*\2))+\b/); - return ret("regexp", "string-2"); - } else { - stream.eat("="); - return ret("operator", "operator", stream.current()); - } - } else if (ch == "`") { - state.tokenize = tokenQuasi; - return tokenQuasi(stream, state); - } else if (ch == "#") { - stream.skipToEnd(); - return ret("error", "error"); - } else if (isOperatorChar.test(ch)) { - if (ch != ">" || !state.lexical || state.lexical.type != ">") { - if (stream.eat("=")) { - if (ch == "!" || ch == "=") stream.eat("=") - } else if (/[<>*+\-]/.test(ch)) { - stream.eat(ch) - if (ch == ">") stream.eat(ch) - } - } - return ret("operator", "operator", stream.current()); - } else if (wordRE.test(ch)) { - stream.eatWhile(wordRE); - var word = stream.current() - if (keywords.propertyIsEnumerable(word)) { - var kw = keywords[word] - return ret(kw.type, kw.style, word) - } - if (state.lastType != "." && word == "async" && stream.match(/^(\s|\/\*.*?\*\/)*[\[\(\w]/, false)) - return ret("async", "keyword", word) - return ret("variable", "variable", word) - } - } - - function tokenString(quote) { - return function(stream, state) { - var escaped = false, next; - if (jsonldMode && stream.peek() == "@" && stream.match(isJsonldKeyword)){ - state.tokenize = tokenBase; - return ret("jsonld-keyword", "meta"); - } - while ((next = stream.next()) != null) { - if (next == quote && !escaped) break; - escaped = !escaped && next == "\\"; - } - if (!escaped) state.tokenize = tokenBase; - return ret("string", "string"); - }; - } - - function tokenComment(stream, state) { - var maybeEnd = false, ch; - while (ch = stream.next()) { - if (ch == "/" && maybeEnd) { - state.tokenize = tokenBase; - break; - } - maybeEnd = (ch == "*"); - } - return ret("comment", "comment"); - } - - function tokenQuasi(stream, state) { - var escaped = false, next; - while ((next = stream.next()) != null) { - if (!escaped && (next == "`" || next == "$" && stream.eat("{"))) { - state.tokenize = tokenBase; - break; - } - escaped = !escaped && next == "\\"; - } - return ret("quasi", "string-2", stream.current()); - } - - var brackets = "([{}])"; - // This is a crude lookahead trick to try and notice that we're - // parsing the argument patterns for a fat-arrow function before we - // actually hit the arrow token. It only works if the arrow is on - // the same line as the arguments and there's no strange noise - // (comments) in between. Fallback is to only notice when we hit the - // arrow, and not declare the arguments as locals for the arrow - // body. - function findFatArrow(stream, state) { - if (state.fatArrowAt) state.fatArrowAt = null; - var arrow = stream.string.indexOf("=>", stream.start); - if (arrow < 0) return; - - if (isTS) { // Try to skip TypeScript return type declarations after the arguments - var m = /:\s*(?:\w+(?:<[^>]*>|\[\])?|\{[^}]*\})\s*$/.exec(stream.string.slice(stream.start, arrow)) - if (m) arrow = m.index - } - - var depth = 0, sawSomething = false; - for (var pos = arrow - 1; pos >= 0; --pos) { - var ch = stream.string.charAt(pos); - var bracket = brackets.indexOf(ch); - if (bracket >= 0 && bracket < 3) { - if (!depth) { ++pos; break; } - if (--depth == 0) { if (ch == "(") sawSomething = true; break; } - } else if (bracket >= 3 && bracket < 6) { - ++depth; - } else if (wordRE.test(ch)) { - sawSomething = true; - } else if (/["'\/]/.test(ch)) { - return; - } else if (sawSomething && !depth) { - ++pos; - break; - } - } - if (sawSomething && !depth) state.fatArrowAt = pos; - } - - // Parser - - var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true, "jsonld-keyword": true}; - - function JSLexical(indented, column, type, align, prev, info) { - this.indented = indented; - this.column = column; - this.type = type; - this.prev = prev; - this.info = info; - if (align != null) this.align = align; - } - - function inScope(state, varname) { - for (var v = state.localVars; v; v = v.next) - if (v.name == varname) return true; - for (var cx = state.context; cx; cx = cx.prev) { - for (var v = cx.vars; v; v = v.next) - if (v.name == varname) return true; - } - } - - function parseJS(state, style, type, content, stream) { - var cc = state.cc; - // Communicate our context to the combinators. - // (Less wasteful than consing up a hundred closures on every call.) - cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc; cx.style = style; - - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = true; - - while(true) { - var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement; - if (combinator(type, content)) { - while(cc.length && cc[cc.length - 1].lex) - cc.pop()(); - if (style?.slice(0, 2) === "p5") return style; - if (cx.marked) return cx.marked; - if (type == "variable" && inScope(state, content)) return "variable-2"; - return style; - } - } - } - - // Combinator utils - - var cx = {state: null, column: null, marked: null, cc: null}; - function pass() { - for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]); - } - function cont() { - pass.apply(null, arguments); - return true; - } - function inList(name, list) { - for (var v = list; v; v = v.next) if (v.name == name) return true - return false; - } - function register(varname) { - var state = cx.state; - cx.marked = "def"; - if (state.context) { - if (state.lexical.info == "var" && state.context && state.context.block) { - // FIXME function decls are also not block scoped - var newContext = registerVarScoped(varname, state.context) - if (newContext != null) { - state.context = newContext - return - } - } else if (!inList(varname, state.localVars)) { - state.localVars = new Var(varname, state.localVars) - return - } - } - window.register = register; - // Fall through means this is global - if (parserConfig.globalVars && !inList(varname, state.globalVars)) - state.globalVars = new Var(varname, state.globalVars) - } - function registerVarScoped(varname, context) { - if (!context) { - return null - } else if (context.block) { - var inner = registerVarScoped(varname, context.prev) - if (!inner) return null - if (inner == context.prev) return context - return new Context(inner, context.vars, true) - } else if (inList(varname, context.vars)) { - return context - } else { - return new Context(context.prev, new Var(varname, context.vars), false) - } - } - - function isModifier(name) { - return name == "public" || name == "private" || name == "protected" || name == "abstract" || name == "readonly" - } - - // Combinators - - function Context(prev, vars, block) { this.prev = prev; this.vars = vars; this.block = block } - function Var(name, next) { this.name = name; this.next = next } - - var defaultVars = new Var("this", new Var("arguments", null)) - function pushcontext() { - cx.state.context = new Context(cx.state.context, cx.state.localVars, false) - cx.state.localVars = defaultVars - } - function pushblockcontext() { - cx.state.context = new Context(cx.state.context, cx.state.localVars, true) - cx.state.localVars = null - } - function popcontext() { - cx.state.localVars = cx.state.context.vars - cx.state.context = cx.state.context.prev - } - popcontext.lex = true - function pushlex(type, info) { - var result = function() { - var state = cx.state, indent = state.indented; - if (state.lexical.type == "stat") indent = state.lexical.indented; - else for (var outer = state.lexical; outer && outer.type == ")" && outer.align; outer = outer.prev) - indent = outer.indented; - state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info); - }; - result.lex = true; - return result; - } - function poplex() { - var state = cx.state; - if (state.lexical.prev) { - if (state.lexical.type == ")") - state.indented = state.lexical.indented; - state.lexical = state.lexical.prev; - } - } - poplex.lex = true; - - function expect(wanted) { - function exp(type) { - if (type == wanted) return cont(); - else if (wanted == ";" || type == "}" || type == ")" || type == "]") return pass(); - else return cont(exp); - }; - return exp; - } - - function statement(type, value) { - if (type == "var") return cont(pushlex("vardef", value), vardef, expect(";"), poplex); - if (type == "keyword a") return cont(pushlex("form"), parenExpr, statement, poplex); - if (type == "keyword b") return cont(pushlex("form"), statement, poplex); - if (type == "keyword d") return cx.stream.match(/^\s*$/, false) ? cont() : cont(pushlex("stat"), maybeexpression, expect(";"), poplex); - if (type == "debugger") return cont(expect(";")); - if (type == "{") return cont(pushlex("}"), pushblockcontext, block, poplex, popcontext); - if (type == ";") return cont(); - if (type == "if") { - if (cx.state.lexical.info == "else" && cx.state.cc[cx.state.cc.length - 1] == poplex) - cx.state.cc.pop()(); - return cont(pushlex("form"), parenExpr, statement, poplex, maybeelse); - } - if (type == "function") return cont(functiondef); - if (type == "for") return cont(pushlex("form"), forspec, statement, poplex); - if (type == "class" || (isTS && value == "interface")) { - cx.marked = "keyword" - return cont(pushlex("form", type == "class" ? type : value), className, poplex) - } - if (type == "variable") { - if (isTS && value == "declare") { - cx.marked = "keyword" - return cont(statement) - } else if (isTS && (value == "module" || value == "enum" || value == "type") && cx.stream.match(/^\s*\w/, false)) { - cx.marked = "keyword" - if (value == "enum") return cont(enumdef); - else if (value == "type") return cont(typeexpr, expect("operator"), typeexpr, expect(";")); - else return cont(pushlex("form"), pattern, expect("{"), pushlex("}"), block, poplex, poplex) - } else if (isTS && value == "namespace") { - cx.marked = "keyword" - return cont(pushlex("form"), expression, statement, poplex) - } else if (isTS && value == "abstract") { - cx.marked = "keyword" - return cont(statement) - } else { - return cont(pushlex("stat"), maybelabel); - } - } - if (type == "switch") return cont(pushlex("form"), parenExpr, expect("{"), pushlex("}", "switch"), pushblockcontext, - block, poplex, poplex, popcontext); - if (type == "case") return cont(expression, expect(":")); - if (type == "default") return cont(expect(":")); - if (type == "catch") return cont(pushlex("form"), pushcontext, maybeCatchBinding, statement, poplex, popcontext); - if (type == "export") return cont(pushlex("stat"), afterExport, poplex); - if (type == "import") return cont(pushlex("stat"), afterImport, poplex); - if (type == "async") return cont(statement) - if (value == "@") return cont(expression, statement) - return pass(pushlex("stat"), expression, expect(";"), poplex); - } - function maybeCatchBinding(type) { - if (type == "(") return cont(funarg, expect(")")) - } - function expression(type, value) { - return expressionInner(type, value, false); - } - function expressionNoComma(type, value) { - return expressionInner(type, value, true); - } - function parenExpr(type) { - if (type != "(") return pass() - return cont(pushlex(")"), expression, expect(")"), poplex) - } - function expressionInner(type, value, noComma) { - if (cx.state.fatArrowAt == cx.stream.start) { - var body = noComma ? arrowBodyNoComma : arrowBody; - if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, expect("=>"), body, popcontext); - else if (type == "variable") return pass(pushcontext, pattern, expect("=>"), body, popcontext); - } - - var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma; - if (atomicTypes.hasOwnProperty(type)) return cont(maybeop); - if (type == "function") return cont(functiondef, maybeop); - if (type == "class" || (isTS && value == "interface")) { cx.marked = "keyword"; return cont(pushlex("form"), classExpression, poplex); } - if (type == "keyword c" || type == "async") return cont(noComma ? expressionNoComma : expression); - if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop); - if (type == "operator" || type == "spread") return cont(noComma ? expressionNoComma : expression); - if (type == "[") return cont(pushlex("]"), arrayLiteral, poplex, maybeop); - if (type == "{") return contCommasep(objprop, "}", null, maybeop); - if (type == "quasi") return pass(quasi, maybeop); - if (type == "new") return cont(maybeTarget(noComma)); - if (type == "import") return cont(expression); - return cont(); - } - function maybeexpression(type) { - if (type.match(/[;\}\)\],]/)) return pass(); - return pass(expression); - } - - function maybeoperatorComma(type, value) { - if (type == ",") return cont(expression); - return maybeoperatorNoComma(type, value, false); - } - function maybeoperatorNoComma(type, value, noComma) { - var me = noComma == false ? maybeoperatorComma : maybeoperatorNoComma; - var expr = noComma == false ? expression : expressionNoComma; - if (type == "=>") return cont(pushcontext, noComma ? arrowBodyNoComma : arrowBody, popcontext); - if (type == "operator") { - if (/\+\+|--/.test(value) || isTS && value == "!") return cont(me); - if (isTS && value == "<" && cx.stream.match(/^([^>]|<.*?>)*>\s*\(/, false)) - return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, me); - if (value == "?") return cont(expression, expect(":"), expr); - return cont(expr); - } - if (type == "quasi") { return pass(quasi, me); } - if (type == ";") return; - if (type == "(") return contCommasep(expressionNoComma, ")", "call", me); - if (type == ".") return cont(property, me); - if (type == "[") return cont(pushlex("]"), maybeexpression, expect("]"), poplex, me); - if (isTS && value == "as") { cx.marked = "keyword"; return cont(typeexpr, me) } - if (type == "regexp") { - cx.state.lastType = cx.marked = "operator" - cx.stream.backUp(cx.stream.pos - cx.stream.start - 1) - return cont(expr) - } - } - function quasi(type, value) { - if (type != "quasi") return pass(); - if (value.slice(value.length - 2) != "${") return cont(quasi); - return cont(expression, continueQuasi); - } - function continueQuasi(type) { - if (type == "}") { - cx.marked = "string-2"; - cx.state.tokenize = tokenQuasi; - return cont(quasi); - } - } - function arrowBody(type) { - findFatArrow(cx.stream, cx.state); - return pass(type == "{" ? statement : expression); - } - function arrowBodyNoComma(type) { - findFatArrow(cx.stream, cx.state); - return pass(type == "{" ? statement : expressionNoComma); - } - function maybeTarget(noComma) { - return function(type) { - if (type == ".") return cont(noComma ? targetNoComma : target); - else if (type == "variable" && isTS) return cont(maybeTypeArgs, noComma ? maybeoperatorNoComma : maybeoperatorComma) - else return pass(noComma ? expressionNoComma : expression); - }; - } - function target(_, value) { - if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorComma); } - } - function targetNoComma(_, value) { - if (value == "target") { cx.marked = "keyword"; return cont(maybeoperatorNoComma); } - } - function maybelabel(type) { - if (type == ":") return cont(poplex, statement); - return pass(maybeoperatorComma, expect(";"), poplex); - } - function property(type) { - if (type == "variable") {cx.marked = "property"; return cont();} - } - function objprop(type, value) { - if (type == "async") { - cx.marked = "property"; - return cont(objprop); - } else if (type == "variable" || cx.style == "keyword") { - cx.marked = "property"; - if (value == "get" || value == "set") return cont(getterSetter); - var m // Work around fat-arrow-detection complication for detecting typescript typed arrow params - if (isTS && cx.state.fatArrowAt == cx.stream.start && (m = cx.stream.match(/^\s*:\s*/, false))) - cx.state.fatArrowAt = cx.stream.pos + m[0].length - return cont(afterprop); - } else if (type == "number" || type == "string") { - cx.marked = jsonldMode ? "property" : (cx.style + " property"); - return cont(afterprop); - } else if (type == "jsonld-keyword") { - return cont(afterprop); - } else if (isTS && isModifier(value)) { - cx.marked = "keyword" - return cont(objprop) - } else if (type == "[") { - return cont(expression, maybetype, expect("]"), afterprop); - } else if (type == "spread") { - return cont(expressionNoComma, afterprop); - } else if (value == "*") { - cx.marked = "keyword"; - return cont(objprop); - } else if (type == ":") { - return pass(afterprop) - } - } - function getterSetter(type) { - if (type != "variable") return pass(afterprop); - cx.marked = "property"; - return cont(functiondef); - } - function afterprop(type) { - if (type == ":") return cont(expressionNoComma); - if (type == "(") return pass(functiondef); - } - function commasep(what, end, sep) { - function proceed(type, value) { - if (sep ? sep.indexOf(type) > -1 : type == ",") { - var lex = cx.state.lexical; - if (lex.info == "call") lex.pos = (lex.pos || 0) + 1; - return cont(function(type, value) { - if (type == end || value == end) return pass() - return pass(what) - }, proceed); - } - if (type == end || value == end) return cont(); - if (sep && sep.indexOf(";") > -1) return pass(what) - return cont(expect(end)); - } - return function(type, value) { - if (type == end || value == end) return cont(); - return pass(what, proceed); - }; - } - function contCommasep(what, end, info) { - for (var i = 3; i < arguments.length; i++) - cx.cc.push(arguments[i]); - return cont(pushlex(end, info), commasep(what, end), poplex); - } - function block(type) { - if (type == "}") return cont(); - return pass(statement, block); - } - function maybetype(type, value) { - if (isTS) { - if (type == ":") return cont(typeexpr); - if (value == "?") return cont(maybetype); - } - } - function mayberettype(type) { - if (isTS && type == ":") { - if (cx.stream.match(/^\s*\w+\s+is\b/, false)) return cont(expression, isKW, typeexpr) - else return cont(typeexpr) - } - } - function isKW(_, value) { - if (value == "is") { - cx.marked = "keyword" - return cont() - } - } - function typeexpr(type, value) { - if (value == "keyof" || value == "typeof") { - cx.marked = "keyword" - return cont(value == "keyof" ? typeexpr : expressionNoComma) - } - if (type == "variable" || value == "void") { - cx.marked = "type" - return cont(afterType) - } - if (type == "string" || type == "number" || type == "atom") return cont(afterType); - if (type == "[") return cont(pushlex("]"), commasep(typeexpr, "]", ","), poplex, afterType) - if (type == "{") return cont(pushlex("}"), commasep(typeprop, "}", ",;"), poplex, afterType) - if (type == "(") return cont(commasep(typearg, ")"), maybeReturnType) - if (type == "<") return cont(commasep(typeexpr, ">"), typeexpr) - } - function maybeReturnType(type) { - if (type == "=>") return cont(typeexpr) - } - function typeprop(type, value) { - if (type == "variable" || cx.style == "keyword") { - cx.marked = "property" - return cont(typeprop) - } else if (value == "?") { - return cont(typeprop) - } else if (type == ":") { - return cont(typeexpr) - } else if (type == "[") { - return cont(expression, maybetype, expect("]"), typeprop) - } else if (type == "(") { - return cont(pushlex(")"), commasep(funarg, ")"), poplex, typeprop) - } - } - function typearg(type, value) { - if (type == "variable" && cx.stream.match(/^\s*[?:]/, false) || value == "?") return cont(typearg) - if (type == ":") return cont(typeexpr) - return pass(typeexpr) - } - function afterType(type, value) { - if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType) - if (value == "|" || type == "." || value == "&") return cont(typeexpr) - if (type == "[") return cont(expect("]"), afterType) - if (value == "extends" || value == "implements") { cx.marked = "keyword"; return cont(typeexpr) } - } - function maybeTypeArgs(_, value) { - if (value == "<") return cont(pushlex(">"), commasep(typeexpr, ">"), poplex, afterType) - } - function typeparam() { - return pass(typeexpr, maybeTypeDefault) - } - function maybeTypeDefault(_, value) { - if (value == "=") return cont(typeexpr) - } - function vardef(_, value) { - if (value == "enum") {cx.marked = "keyword"; return cont(enumdef)} - return pass(pattern, maybetype, maybeAssign, vardefCont); - } - function pattern(type, value) { - if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(pattern) } - if (type == "variable") { register(value); return cont(); } - if (type == "spread") return cont(pattern); - if (type == "[") return contCommasep(eltpattern, "]"); - if (type == "{") return contCommasep(proppattern, "}"); - } - function proppattern(type, value) { - if (type == "variable" && !cx.stream.match(/^\s*:/, false)) { - register(value); - return cont(maybeAssign); - } - if (type == "variable") cx.marked = "property"; - if (type == "spread") return cont(pattern); - if (type == "}") return pass(); - if (type == "[") return cont(expression, expect(']'), expect(':'), proppattern); - return cont(expect(":"), pattern, maybeAssign); - } - function eltpattern() { - return pass(pattern, maybeAssign) - } - function maybeAssign(_type, value) { - if (value == "=") return cont(expressionNoComma); - } - function vardefCont(type) { - if (type == ",") return cont(vardef); - } - function maybeelse(type, value) { - if (type == "keyword b" && value == "else") return cont(pushlex("form", "else"), statement, poplex); - } - function forspec(type, value) { - if (value == "await") return cont(forspec); - if (type == "(") return cont(pushlex(")"), forspec1, expect(")"), poplex); - } - function forspec1(type) { - if (type == "var") return cont(vardef, expect(";"), forspec2); - if (type == ";") return cont(forspec2); - if (type == "variable") return cont(formaybeinof); - return pass(expression, expect(";"), forspec2); - } - function formaybeinof(_type, value) { - if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } - return cont(maybeoperatorComma, forspec2); - } - function forspec2(type, value) { - if (type == ";") return cont(forspec3); - if (value == "in" || value == "of") { cx.marked = "keyword"; return cont(expression); } - return pass(expression, expect(";"), forspec3); - } - function forspec3(type) { - if (type != ")") cont(expression); - } - function functiondef(type, value) { - if (value == "*") {cx.marked = "keyword"; return cont(functiondef);} - if (type == "variable") {register(value); return cont(functiondef);} - if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, statement, popcontext); - if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondef) - } - function functiondecl(type, value) { - if (value == "*") {cx.marked = "keyword"; return cont(functiondecl);} - if (type == "variable") {register(value); return cont(functiondecl);} - if (type == "(") return cont(pushcontext, pushlex(")"), commasep(funarg, ")"), poplex, mayberettype, popcontext); - if (isTS && value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, functiondecl) - } - function funarg(type, value) { - if (value == "@") cont(expression, funarg) - if (type == "spread") return cont(funarg); - if (isTS && isModifier(value)) { cx.marked = "keyword"; return cont(funarg); } - return pass(pattern, maybetype, maybeAssign); - } - function classExpression(type, value) { - // Class expressions may have an optional name. - if (type == "variable") return className(type, value); - return classNameAfter(type, value); - } - function className(type, value) { - if (type == "variable") {register(value); return cont(classNameAfter);} - } - function classNameAfter(type, value) { - if (value == "<") return cont(pushlex(">"), commasep(typeparam, ">"), poplex, classNameAfter) - if (value == "extends" || value == "implements" || (isTS && type == ",")) { - if (value == "implements") cx.marked = "keyword"; - return cont(isTS ? typeexpr : expression, classNameAfter); - } - if (type == "{") return cont(pushlex("}"), classBody, poplex); - } - function classBody(type, value) { - if (type == "async" || - (type == "variable" && - (value == "static" || value == "get" || value == "set" || (isTS && isModifier(value))) && - cx.stream.match(/^\s+[\w$\xa1-\uffff]/, false))) { - cx.marked = "keyword"; - return cont(classBody); - } - if (type == "variable" || cx.style == "keyword") { - cx.marked = "property"; - return cont(isTS ? classfield : functiondef, classBody); - } - if (type == "[") - return cont(expression, maybetype, expect("]"), isTS ? classfield : functiondef, classBody) - if (value == "*") { - cx.marked = "keyword"; - return cont(classBody); - } - if (type == ";") return cont(classBody); - if (type == "}") return cont(); - if (value == "@") return cont(expression, classBody) - } - function classfield(type, value) { - if (value == "?") return cont(classfield) - if (type == ":") return cont(typeexpr, maybeAssign) - if (value == "=") return cont(expressionNoComma) - var context = cx.state.lexical.prev, isInterface = context && context.info == "interface" - return pass(isInterface ? functiondecl : functiondef) - } - function afterExport(type, value) { - if (value == "*") { cx.marked = "keyword"; return cont(maybeFrom, expect(";")); } - if (value == "default") { cx.marked = "keyword"; return cont(expression, expect(";")); } - if (type == "{") return cont(commasep(exportField, "}"), maybeFrom, expect(";")); - return pass(statement); - } - function exportField(type, value) { - if (value == "as") { cx.marked = "keyword"; return cont(expect("variable")); } - if (type == "variable") return pass(expressionNoComma, exportField); - } - function afterImport(type) { - if (type == "string") return cont(); - if (type == "(") return pass(expression); - return pass(importSpec, maybeMoreImports, maybeFrom); - } - function importSpec(type, value) { - if (type == "{") return contCommasep(importSpec, "}"); - if (type == "variable") register(value); - if (value == "*") cx.marked = "keyword"; - return cont(maybeAs); - } - function maybeMoreImports(type) { - if (type == ",") return cont(importSpec, maybeMoreImports) - } - function maybeAs(_type, value) { - if (value == "as") { cx.marked = "keyword"; return cont(importSpec); } - } - function maybeFrom(_type, value) { - if (value == "from") { cx.marked = "keyword"; return cont(expression); } - } - function arrayLiteral(type) { - if (type == "]") return cont(); - return pass(commasep(expressionNoComma, "]")); - } - function enumdef() { - return pass(pushlex("form"), pattern, expect("{"), pushlex("}"), commasep(enummember, "}"), poplex, poplex) - } - function enummember() { - return pass(pattern, maybeAssign); - } - - function isContinuedStatement(state, textAfter) { - return state.lastType == "operator" || state.lastType == "," || - isOperatorChar.test(textAfter.charAt(0)) || - /[,.]/.test(textAfter.charAt(0)); - } - - function expressionAllowed(stream, state, backUp) { - return state.tokenize == tokenBase && - /^(?:operator|sof|keyword [bcd]|case|new|export|default|spread|[\[{}\(,;:]|=>)$/.test(state.lastType) || - (state.lastType == "quasi" && /\{\s*$/.test(stream.string.slice(0, stream.pos - (backUp || 0)))) - } - - // Interface - - return { - startState: function(basecolumn) { - var state = { - tokenize: tokenBase, - lastType: "sof", - cc: [], - lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false), - localVars: parserConfig.localVars, - context: parserConfig.localVars && new Context(null, null, false), - indented: basecolumn || 0 - }; - if (parserConfig.globalVars && typeof parserConfig.globalVars == "object") - state.globalVars = parserConfig.globalVars; - return state; - }, - - token: function(stream, state) { - if (stream.sol()) { - if (!state.lexical.hasOwnProperty("align")) - state.lexical.align = false; - state.indented = stream.indentation(); - findFatArrow(stream, state); - } - if (state.tokenize != tokenComment && stream.eatSpace()) return null; - var style = state.tokenize(stream, state); - if (type == "comment") return style; - state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type; - return parseJS(state, style, type, content, stream); - }, - - indent: function(state, textAfter) { - if (state.tokenize == tokenComment) return CodeMirror.Pass; - if (state.tokenize != tokenBase) return 0; - var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical, top - // Kludge to prevent 'maybelse' from blocking lexical scope pops - if (!/^\s*else\b/.test(textAfter)) for (var i = state.cc.length - 1; i >= 0; --i) { - var c = state.cc[i]; - if (c == poplex) lexical = lexical.prev; - else if (c != maybeelse) break; - } - while ((lexical.type == "stat" || lexical.type == "form") && - (firstChar == "}" || ((top = state.cc[state.cc.length - 1]) && - (top == maybeoperatorComma || top == maybeoperatorNoComma) && - !/^[,\.=+\-*:?[\(]/.test(textAfter)))) - lexical = lexical.prev; - if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat") - lexical = lexical.prev; - var type = lexical.type, closing = firstChar == type; - - if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? lexical.info.length + 1 : 0); - else if (type == "form" && firstChar == "{") return lexical.indented; - else if (type == "form") return lexical.indented + indentUnit; - else if (type == "stat") - return lexical.indented + (isContinuedStatement(state, textAfter) ? statementIndent || indentUnit : 0); - else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false) - return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit); - else if (lexical.align) return lexical.column + (closing ? 0 : 1); - else return lexical.indented + (closing ? 0 : indentUnit); - }, - - electricInput: /^\s*(?:case .*?:|default:|\{|\})$/, - blockCommentStart: jsonMode ? null : "/*", - blockCommentEnd: jsonMode ? null : "*/", - blockCommentContinue: jsonMode ? null : " * ", - lineComment: jsonMode ? null : "//", - fold: "brace", - closeBrackets: "()[]{}''\"\"``", - - helperType: jsonMode ? "json" : "javascript", - jsonldMode: jsonldMode, - jsonMode: jsonMode, - - expressionAllowed: expressionAllowed, - - skipExpression: function(state) { - var top = state.cc[state.cc.length - 1] - if (top == expression || top == expressionNoComma) state.cc.pop() - } - }; -}); - -CodeMirror.registerHelper("wordChars", "javascript", /[\w$]/); - -CodeMirror.defineMIME("text/javascript", "javascript"); -CodeMirror.defineMIME("text/ecmascript", "javascript"); -CodeMirror.defineMIME("application/javascript", "javascript"); -CodeMirror.defineMIME("application/x-javascript", "javascript"); -CodeMirror.defineMIME("application/ecmascript", "javascript"); -CodeMirror.defineMIME("application/json", {name: "javascript", json: true}); -CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true}); -CodeMirror.defineMIME("application/ld+json", {name: "javascript", jsonld: true}); -CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true }); -CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true }); - -}); diff --git a/package-lock.json b/package-lock.json index 7ff5e27fc1..8312f9fac7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,10 +12,23 @@ "@auth0/s3": "^1.0.0", "@babel/core": "^7.14.6", "@babel/register": "^7.14.5", - "@emmetio/codemirror-plugin": "^1.2.4", + "@codemirror/autocomplete": "^6.7.1", + "@codemirror/commands": "^6.2.4", + "@codemirror/lang-css": "^6.2.0", + "@codemirror/lang-html": "^6.4.3", + "@codemirror/lang-javascript": "^6.1.8", + "@codemirror/lang-json": "^6.0.1", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.2.1", + "@codemirror/search": "^6.4.0", + "@codemirror/state": "^6.2.0", + "@codemirror/view": "^6.11.2", + "@emmetio/codemirror6-plugin": "^0.3.0", + "@lezer/highlight": "^1.1.4", "@redux-devtools/core": "^3.11.0", "@redux-devtools/dock-monitor": "^2.1.0", "@redux-devtools/log-monitor": "^3.1.0", + "@uiw/codemirror-extensions-color": "^4.20.2", "async": "^3.2.3", "axios": "^0.21.2", "babel-plugin-styled-components": "^1.13.2", @@ -2380,6 +2393,133 @@ "node": ">=0.1.95" } }, + "node_modules/@codemirror/autocomplete": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.7.1.tgz", + "integrity": "sha512-hSxf9S0uB+GV+gBsjY1FZNo53e1FFdzPceRfCfD1gWOnV6o21GfB5J5Wg9G/4h76XZMPrF0A6OCK/Rz5+V1egg==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.6.0", + "@lezer/common": "^1.0.0" + }, + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.2.4.tgz", + "integrity": "sha512-42lmDqVH0ttfilLShReLXsDfASKLXzfyC36bzwcqzox9PlHulMcsUOfHXNo2X2aFMVNUoQ7j+d4q5bnfseYoOA==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.2.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-css": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.0.tgz", + "integrity": "sha512-oyIdJM29AyRPM3+PPq1I2oIk8NpUfEN3kAM05XWDDs6o3gSneIKaVJifT2P+fqONLou2uIgXynFyMUDQvo/szA==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-html": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.3.tgz", + "integrity": "sha512-VKzQXEC8nL69Jg2hvAFPBwOdZNvL8tMFOrdFwWpU+wc6a6KEkndJ/19R5xSaglNX6v2bttm8uIEFYxdQDcIZVQ==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.2.2", + "@lezer/common": "^1.0.0", + "@lezer/css": "^1.1.0", + "@lezer/html": "^1.3.0" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.1.8.tgz", + "integrity": "sha512-5cIA6IOkslTu1DtldcYnj7hsBm3p+cD37qSaKvW1kV16M6q9ysKvKrveCOWgbrj4+ilSWRL2JtSLudbeB158xg==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-json": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz", + "integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@lezer/json": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.6.0.tgz", + "integrity": "sha512-cwUd6lzt3MfNYOobdjf14ZkLbJcnv4WtndYaoBkbor/vF+rCNguMPK0IRtvZJG4dsWiaWPcK8x1VijhvSxnstg==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.2.1.tgz", + "integrity": "sha512-y1muai5U/uUPAGRyHMx9mHuHLypPcHWxzlZGknp/U5Mdb5Ol8Q5ZLp67UqyTbNFJJ3unVxZ8iX3g1fMN79S1JQ==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.4.0.tgz", + "integrity": "sha512-zMDgaBXah+nMLK2dHz9GdCnGbQu+oaGRXS1qviqNZkvOCv/whp5XZFyoikLp/23PM9RBcbuKUUISUmQHM1eRHw==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.0.tgz", + "integrity": "sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA==" + }, + "node_modules/@codemirror/view": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.11.2.tgz", + "integrity": "sha512-AzxJ9Aub6ubBvoPBGvjcd4zITqcBBiLpJ89z0ZjnphOHncbvUvQcb9/WMVGpuwTT95+jW4knkH6gFIy0oLdaUQ==", + "dependencies": { + "@codemirror/state": "^6.1.4", + "style-mod": "^4.0.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@csstools/convert-colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", @@ -2408,10 +2548,55 @@ "vue": "^2.6.10 || ^3.0.0" } }, - "node_modules/@emmetio/codemirror-plugin": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@emmetio/codemirror-plugin/-/codemirror-plugin-1.2.4.tgz", - "integrity": "sha512-wVw2gqI6X+uVWYVRtTVymzTgbo4hEZIcPCNj4xrXw4l/+L3Qa+tAC/yf+Xy9nenRPCqRq0RLqGiQL+Qf/wYE9Q==" + "node_modules/@emmetio/abbreviation": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.3.3.tgz", + "integrity": "sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==", + "dependencies": { + "@emmetio/scanner": "^1.0.4" + } + }, + "node_modules/@emmetio/codemirror6-plugin": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@emmetio/codemirror6-plugin/-/codemirror6-plugin-0.3.0.tgz", + "integrity": "sha512-w9KlUG/RHFVF1+98el7tr4GUyM3J4kBVHqIp4eCChY9MmF0HbfMiP6id6eoZEpHd7ATINVnzEYlXx5zTBkUGzw==", + "dependencies": { + "@emmetio/math-expression": "^1.0.4", + "emmet": "^2.4.2" + }, + "peerDependencies": { + "@codemirror/autocomplete": "^6.1.0", + "@codemirror/commands": "^6.0.1", + "@codemirror/highlight": "^0.19.8", + "@codemirror/history": "^0.19.2", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-html": "^6.1.0", + "@codemirror/language": "^6.2.1", + "@codemirror/state": "^6.1.1", + "@codemirror/view": "^6.2.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@emmetio/css-abbreviation": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@emmetio/css-abbreviation/-/css-abbreviation-2.1.8.tgz", + "integrity": "sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==", + "dependencies": { + "@emmetio/scanner": "^1.0.4" + } + }, + "node_modules/@emmetio/math-expression": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@emmetio/math-expression/-/math-expression-1.0.5.tgz", + "integrity": "sha512-qf5SXD/ViS04rXSeDg9CRGM10xLC9dVaKIbMHrrwxYr5LNB/C0rOfokhGSBwnVQKcidLmdRJeNWH1V1tppZ84Q==", + "dependencies": { + "@emmetio/scanner": "^1.0.4" + } + }, + "node_modules/@emmetio/scanner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emmetio/scanner/-/scanner-1.0.4.tgz", + "integrity": "sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==" }, "node_modules/@emotion/cache": { "version": "10.0.29", @@ -2672,7 +2857,6 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.1.1", @@ -2692,7 +2876,6 @@ "version": "13.10.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", - "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -2707,7 +2890,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, "engines": { "node": ">= 4" } @@ -2716,7 +2898,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -2732,7 +2913,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "engines": { "node": ">=4" } @@ -2741,7 +2921,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -2753,7 +2932,6 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -2803,7 +2981,6 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.0", "debug": "^4.1.1", @@ -2816,8 +2993,7 @@ "node_modules/@humanwhocodes/object-schema": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", - "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", - "dev": true + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==" }, "node_modules/@hypnosphi/create-react-context": { "version": "0.3.1", @@ -5521,6 +5697,64 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@lezer/common": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.2.tgz", + "integrity": "sha512-SVgiGtMnMnW3ActR8SXgsDhw7a0w0ChHSYAyAUxxrOiJ1OqYWEKk/xJd84tTSPo1mo6DXLObAJALNnd0Hrv7Ng==" + }, + "node_modules/@lezer/css": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.1.tgz", + "integrity": "sha512-mSjx+unLLapEqdOYDejnGBokB5+AiJKZVclmud0MKQOKx3DLJ5b5VTCstgDDknR6iIV4gVrN6euzsCnj0A2gQA==", + "dependencies": { + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/highlight": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.4.tgz", + "integrity": "sha512-IECkFmw2l7sFcYXrV8iT9GeY4W0fU4CxX0WMwhmhMIVjoDdD1Hr6q3G2NqVtLg/yVe5n7i4menG3tJ2r4eCrPQ==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/html": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.4.tgz", + "integrity": "sha512-HdJYMVZcT4YsMo7lW3ipL4NoyS2T67kMPuSVS5TgLGqmaCjEU/D6xv7zsa1ktvTK5lwk7zzF1e3eU6gBZIPm5g==", + "dependencies": { + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/javascript": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.3.tgz", + "integrity": "sha512-k7Eo9z9B1supZ5cCD4ilQv/RZVN30eUQL+gGbr6ybrEY3avBAL5MDiYi2aa23Aj0A79ry4rJRvPAwE2TM8bd+A==", + "dependencies": { + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.0.tgz", + "integrity": "sha512-zbAuUY09RBzCoCA3lJ1+ypKw5WSNvLqGMtasdW6HvVOqZoCpPr8eWrsGnOVWGKGn8Rh21FnrKRVlJXrGAVUqRw==", + "dependencies": { + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.4.tgz", + "integrity": "sha512-7o+e4og/QoC/6btozDPJqnzBhUaD1fMfmvnEKQO1wRRiTse1WxaJ3OMEXZJnkgT6HCcTVOctSoXK9jGJw2oe9g==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, "node_modules/@mdx-js/loader": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-1.6.22.tgz", @@ -11039,6 +11273,21 @@ "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", "dev": true }, + "node_modules/@uiw/codemirror-extensions-color": { + "version": "4.20.2", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-color/-/codemirror-extensions-color-4.20.2.tgz", + "integrity": "sha512-z9mHBibvajeyI9PQGzaGoBIFAI+S+64+Y60ukwBYoje67lzDX407AMExw8QNC+Shoswegmf0AgJEiR9aT90ebw==", + "dependencies": { + "colors-named": "^1.0.0", + "colors-named-hex": "^1.0.0", + "hsl-matcher": "^1.2.3" + }, + "peerDependencies": { + "@codemirror/language": ">=6.0.0", + "@codemirror/state": ">=6.0.0", + "@codemirror/view": ">=6.0.0" + } + }, "node_modules/@vue/compiler-core": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.1.5.tgz", @@ -11523,7 +11772,6 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } @@ -11852,7 +12100,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "dependencies": { "sprintf-js": "~1.0.2" } @@ -12406,7 +12653,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, "engines": { "node": ">=8" } @@ -15599,6 +15845,22 @@ "node": ">=0.1.90" } }, + "node_modules/colors-named": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/colors-named/-/colors-named-1.0.1.tgz", + "integrity": "sha512-MGhZwJ6SPSdrg5qsr3YB3sD4zB2bfm3bPj9iIdkjxruUYNQakiBBWL+kFM3SXnyfkZClj3Bq7vofBKbgeJRJ/Q==", + "engines": { + "node": ">=14.16" + } + }, + "node_modules/colors-named-hex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/colors-named-hex/-/colors-named-hex-1.0.1.tgz", + "integrity": "sha512-2uoNWhxAPRn3GVpbuaQ2p5LAMhsjd9r/ZqQNJTUcEr1XQCkMFWh9zPLJLjg1l51xYApdDCMIEjkDNpoAXK2vMw==", + "engines": { + "node": ">=14.16" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -17082,6 +17344,11 @@ "loose-envify": "^1.0.0" } }, + "node_modules/crelt": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz", + "integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==" + }, "node_modules/cross-env": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.1.tgz", @@ -19010,7 +19277,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, "dependencies": { "esutils": "^2.0.2" }, @@ -19335,6 +19601,15 @@ "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, + "node_modules/emmet": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/emmet/-/emmet-2.4.4.tgz", + "integrity": "sha512-v8Mwpjym55CS3EjJgiCLWUB3J2HSR93jhzXW325720u8KvYxdI2voYLstW3pHBxFz54H6jFjayR9G4LfTG0q+g==", + "dependencies": { + "@emmetio/abbreviation": "^2.3.3", + "@emmetio/css-abbreviation": "^2.1.8" + } + }, "node_modules/emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -19413,7 +19688,6 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, "dependencies": { "ansi-colors": "^4.1.1" }, @@ -19425,7 +19699,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, "engines": { "node": ">=6" } @@ -19652,7 +19925,6 @@ "version": "7.31.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.31.0.tgz", "integrity": "sha512-vafgJpSh2ia8tnTkNUkwxGmnumgckLh5aAbLa1xRmIn9+owi8qBNGKL+B881kNKNTy7FFqTEkpNkUvmw0n6PkA==", - "dev": true, "dependencies": { "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.4.3", @@ -20304,7 +20576,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, "dependencies": { "eslint-visitor-keys": "^1.1.0" }, @@ -20319,7 +20590,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, "engines": { "node": ">=4" } @@ -20464,7 +20734,6 @@ "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, "dependencies": { "@babel/highlight": "^7.10.4" } @@ -20473,7 +20742,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -20482,7 +20750,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -20498,7 +20765,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -20513,7 +20779,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -20525,7 +20790,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -20536,14 +20800,12 @@ "node_modules/eslint/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/eslint/node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -20557,7 +20819,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, "engines": { "node": ">=10" }, @@ -20569,7 +20830,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, "engines": { "node": ">=10" } @@ -20577,14 +20837,12 @@ "node_modules/eslint/node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/eslint/node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -20596,7 +20854,6 @@ "version": "13.10.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", - "dev": true, "dependencies": { "type-fest": "^0.20.2" }, @@ -20611,7 +20868,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -20620,7 +20876,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true, "engines": { "node": ">= 4" } @@ -20629,7 +20884,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -20645,7 +20899,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -20654,7 +20907,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -20666,7 +20918,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -20679,7 +20930,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "dependencies": { "yallist": "^4.0.0" }, @@ -20691,7 +20941,6 @@ "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -20708,7 +20957,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -20717,7 +20965,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, "engines": { "node": ">= 0.8.0" } @@ -20726,7 +20973,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, "engines": { "node": ">=4" } @@ -20735,7 +20981,6 @@ "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, "dependencies": { "lru-cache": "^6.0.0" }, @@ -20750,7 +20995,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -20762,7 +21006,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -20771,7 +21014,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.0" }, @@ -20783,7 +21025,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, "engines": { "node": ">=8" }, @@ -20795,7 +21036,6 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, "dependencies": { "prelude-ls": "^1.2.1" }, @@ -20807,7 +21047,6 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, "engines": { "node": ">=10" }, @@ -20819,7 +21058,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -20833,14 +21071,12 @@ "node_modules/eslint/node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/espree": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, "dependencies": { "acorn": "^7.4.0", "acorn-jsx": "^5.3.1", @@ -20854,7 +21090,6 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -20866,7 +21101,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true, "engines": { "node": ">=4" } @@ -20887,7 +21121,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, "dependencies": { "estraverse": "^5.1.0" }, @@ -20899,7 +21132,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true, "engines": { "node": ">=4.0" } @@ -22102,7 +22334,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, "dependencies": { "flat-cache": "^3.0.4" }, @@ -22339,7 +22570,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, "dependencies": { "flatted": "^3.1.0", "rimraf": "^3.0.2" @@ -22352,7 +22582,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -22366,8 +22595,7 @@ "node_modules/flatted": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.1.tgz", - "integrity": "sha512-OMQjaErSFHmHqZe+PSidH5n8j3O0F2DdnVh8JB4j4eUQ2k6KvB0qGfrKIhapvez5JerBbmWkaLYUYWISaESoXg==", - "dev": true + "integrity": "sha512-OMQjaErSFHmHqZe+PSidH5n8j3O0F2DdnVh8JB4j4eUQ2k6KvB0qGfrKIhapvez5JerBbmWkaLYUYWISaESoXg==" }, "node_modules/flatten": { "version": "1.0.2", @@ -23878,8 +24106,7 @@ "node_modules/functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, "node_modules/functions-have-names": { "version": "1.2.2", @@ -24758,6 +24985,14 @@ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, + "node_modules/hsl-matcher": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/hsl-matcher/-/hsl-matcher-1.2.3.tgz", + "integrity": "sha512-irW1socbRjPPAtX/jdl2AWntFB2cCv5W0BGoeZW4uFURCWzupsyAqnw0wPB1qh5wKjdrEYVRV++IuLko+P31OA==", + "engines": { + "node": ">=14.16" + } + }, "node_modules/html-encoding-sniffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", @@ -25755,7 +25990,6 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, "engines": { "node": ">=0.8.19" } @@ -33781,7 +34015,6 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -34491,8 +34724,7 @@ "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, "node_modules/json-stringify-safe": { "version": "5.0.1", @@ -35335,8 +35567,7 @@ "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" }, "node_modules/lodash.curry": { "version": "4.1.1", @@ -35449,8 +35680,7 @@ "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=" }, "node_modules/lodash.unescape": { "version": "4.0.1", @@ -38486,8 +38716,7 @@ "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, "node_modules/negotiator": { "version": "0.6.2", @@ -42532,7 +42761,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -44751,7 +44979,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, "engines": { "node": ">=8" }, @@ -46551,7 +46778,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -46568,7 +46794,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -46583,7 +46808,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -46594,14 +46818,12 @@ "node_modules/slice-ansi/node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -46985,8 +47207,7 @@ "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "node_modules/sshpk": { "version": "1.16.1", @@ -47704,6 +47925,11 @@ "webpack": "^5.0.0" } }, + "node_modules/style-mod": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.3.tgz", + "integrity": "sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw==" + }, "node_modules/style-to-object": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", @@ -48006,7 +48232,6 @@ "version": "6.7.1", "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", - "dev": true, "dependencies": { "ajv": "^8.0.1", "lodash.clonedeep": "^4.5.0", @@ -48023,7 +48248,6 @@ "version": "8.6.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -48039,7 +48263,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -48047,20 +48270,17 @@ "node_modules/table/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "node_modules/table/node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/table/node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "engines": { "node": ">=8" } @@ -48068,14 +48288,12 @@ "node_modules/table/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "node_modules/table/node_modules/string-width": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -48089,7 +48307,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.0" }, @@ -48415,8 +48632,7 @@ "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "node_modules/thenify": { "version": "3.3.0", @@ -49481,8 +49697,7 @@ "node_modules/v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" }, "node_modules/v8-to-istanbul": { "version": "8.1.0", @@ -49693,6 +49908,11 @@ "browser-process-hrtime": "^1.0.0" } }, + "node_modules/w3c-keyname": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", + "integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==" + }, "node_modules/w3c-xmlserializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", @@ -51070,7 +51290,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -52942,6 +53161,127 @@ "minimist": "^1.2.0" } }, + "@codemirror/autocomplete": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.7.1.tgz", + "integrity": "sha512-hSxf9S0uB+GV+gBsjY1FZNo53e1FFdzPceRfCfD1gWOnV6o21GfB5J5Wg9G/4h76XZMPrF0A6OCK/Rz5+V1egg==", + "requires": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.6.0", + "@lezer/common": "^1.0.0" + } + }, + "@codemirror/commands": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.2.4.tgz", + "integrity": "sha512-42lmDqVH0ttfilLShReLXsDfASKLXzfyC36bzwcqzox9PlHulMcsUOfHXNo2X2aFMVNUoQ7j+d4q5bnfseYoOA==", + "requires": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.2.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "@codemirror/lang-css": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.0.tgz", + "integrity": "sha512-oyIdJM29AyRPM3+PPq1I2oIk8NpUfEN3kAM05XWDDs6o3gSneIKaVJifT2P+fqONLou2uIgXynFyMUDQvo/szA==", + "requires": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.0.0" + } + }, + "@codemirror/lang-html": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.3.tgz", + "integrity": "sha512-VKzQXEC8nL69Jg2hvAFPBwOdZNvL8tMFOrdFwWpU+wc6a6KEkndJ/19R5xSaglNX6v2bttm8uIEFYxdQDcIZVQ==", + "requires": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.2.2", + "@lezer/common": "^1.0.0", + "@lezer/css": "^1.1.0", + "@lezer/html": "^1.3.0" + } + }, + "@codemirror/lang-javascript": { + "version": "6.1.8", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.1.8.tgz", + "integrity": "sha512-5cIA6IOkslTu1DtldcYnj7hsBm3p+cD37qSaKvW1kV16M6q9ysKvKrveCOWgbrj4+ilSWRL2JtSLudbeB158xg==", + "requires": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "@codemirror/lang-json": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.1.tgz", + "integrity": "sha512-+T1flHdgpqDDlJZ2Lkil/rLiRy684WMLc74xUnjJH48GQdfJo/pudlTRreZmKwzP8/tGdKf83wlbAdOCzlJOGQ==", + "requires": { + "@codemirror/language": "^6.0.0", + "@lezer/json": "^1.0.0" + } + }, + "@codemirror/language": { + "version": "6.6.0", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.6.0.tgz", + "integrity": "sha512-cwUd6lzt3MfNYOobdjf14ZkLbJcnv4WtndYaoBkbor/vF+rCNguMPK0IRtvZJG4dsWiaWPcK8x1VijhvSxnstg==", + "requires": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "@codemirror/lint": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.2.1.tgz", + "integrity": "sha512-y1muai5U/uUPAGRyHMx9mHuHLypPcHWxzlZGknp/U5Mdb5Ol8Q5ZLp67UqyTbNFJJ3unVxZ8iX3g1fMN79S1JQ==", + "requires": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "@codemirror/search": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.4.0.tgz", + "integrity": "sha512-zMDgaBXah+nMLK2dHz9GdCnGbQu+oaGRXS1qviqNZkvOCv/whp5XZFyoikLp/23PM9RBcbuKUUISUmQHM1eRHw==", + "requires": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "@codemirror/state": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.0.tgz", + "integrity": "sha512-69QXtcrsc3RYtOtd+GsvczJ319udtBf1PTrr2KbLWM/e2CXUPnh0Nz9AUo8WfhSQ7GeL8dPVNUmhQVgpmuaNGA==" + }, + "@codemirror/view": { + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.11.2.tgz", + "integrity": "sha512-AzxJ9Aub6ubBvoPBGvjcd4zITqcBBiLpJ89z0ZjnphOHncbvUvQcb9/WMVGpuwTT95+jW4knkH6gFIy0oLdaUQ==", + "requires": { + "@codemirror/state": "^6.1.4", + "style-mod": "^4.0.0", + "w3c-keyname": "^2.2.4" + } + }, "@csstools/convert-colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", @@ -52958,12 +53298,46 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@egoist/vue-to-react/-/vue-to-react-1.2.0.tgz", "integrity": "sha512-uUtkzw+jtB1t++XjgwmzD/cgPVs7ZWyypw/IjciwZHNWODb/Ij19KJIkwxxKqokzopxmgbJKK4a5Zj9d9+WrPA==", - "dev": true + "dev": true, + "requires": {} }, - "@emmetio/codemirror-plugin": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@emmetio/codemirror-plugin/-/codemirror-plugin-1.2.4.tgz", - "integrity": "sha512-wVw2gqI6X+uVWYVRtTVymzTgbo4hEZIcPCNj4xrXw4l/+L3Qa+tAC/yf+Xy9nenRPCqRq0RLqGiQL+Qf/wYE9Q==" + "@emmetio/abbreviation": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.3.3.tgz", + "integrity": "sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==", + "requires": { + "@emmetio/scanner": "^1.0.4" + } + }, + "@emmetio/codemirror6-plugin": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@emmetio/codemirror6-plugin/-/codemirror6-plugin-0.3.0.tgz", + "integrity": "sha512-w9KlUG/RHFVF1+98el7tr4GUyM3J4kBVHqIp4eCChY9MmF0HbfMiP6id6eoZEpHd7ATINVnzEYlXx5zTBkUGzw==", + "requires": { + "@emmetio/math-expression": "^1.0.4", + "emmet": "^2.4.2" + } + }, + "@emmetio/css-abbreviation": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@emmetio/css-abbreviation/-/css-abbreviation-2.1.8.tgz", + "integrity": "sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==", + "requires": { + "@emmetio/scanner": "^1.0.4" + } + }, + "@emmetio/math-expression": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@emmetio/math-expression/-/math-expression-1.0.5.tgz", + "integrity": "sha512-qf5SXD/ViS04rXSeDg9CRGM10xLC9dVaKIbMHrrwxYr5LNB/C0rOfokhGSBwnVQKcidLmdRJeNWH1V1tppZ84Q==", + "requires": { + "@emmetio/scanner": "^1.0.4" + } + }, + "@emmetio/scanner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@emmetio/scanner/-/scanner-1.0.4.tgz", + "integrity": "sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==" }, "@emotion/cache": { "version": "10.0.29", @@ -53223,7 +53597,6 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==", - "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.1.1", @@ -53240,7 +53613,6 @@ "version": "13.10.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", - "dev": true, "requires": { "type-fest": "^0.20.2" } @@ -53248,14 +53620,12 @@ "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -53264,20 +53634,17 @@ "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" } } }, @@ -53319,7 +53686,6 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz", "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==", - "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.0", "debug": "^4.1.1", @@ -53329,8 +53695,7 @@ "@humanwhocodes/object-schema": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.0.tgz", - "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==", - "dev": true + "integrity": "sha512-wdppn25U8z/2yiaT6YGquE6X8sSv7hNMWSXYSSU1jGv/yd6XqjXgTDJ8KP4NgjTXfJ3GbRjeeb8RTV7a/VpM+w==" }, "@hypnosphi/create-react-context": { "version": "0.3.1", @@ -53357,7 +53722,8 @@ "version": "0.2.4", "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==", - "dev": true + "dev": true, + "requires": {} }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -55453,6 +55819,64 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "@lezer/common": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.2.tgz", + "integrity": "sha512-SVgiGtMnMnW3ActR8SXgsDhw7a0w0ChHSYAyAUxxrOiJ1OqYWEKk/xJd84tTSPo1mo6DXLObAJALNnd0Hrv7Ng==" + }, + "@lezer/css": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.1.tgz", + "integrity": "sha512-mSjx+unLLapEqdOYDejnGBokB5+AiJKZVclmud0MKQOKx3DLJ5b5VTCstgDDknR6iIV4gVrN6euzsCnj0A2gQA==", + "requires": { + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "@lezer/highlight": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.4.tgz", + "integrity": "sha512-IECkFmw2l7sFcYXrV8iT9GeY4W0fU4CxX0WMwhmhMIVjoDdD1Hr6q3G2NqVtLg/yVe5n7i4menG3tJ2r4eCrPQ==", + "requires": { + "@lezer/common": "^1.0.0" + } + }, + "@lezer/html": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.4.tgz", + "integrity": "sha512-HdJYMVZcT4YsMo7lW3ipL4NoyS2T67kMPuSVS5TgLGqmaCjEU/D6xv7zsa1ktvTK5lwk7zzF1e3eU6gBZIPm5g==", + "requires": { + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "@lezer/javascript": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.3.tgz", + "integrity": "sha512-k7Eo9z9B1supZ5cCD4ilQv/RZVN30eUQL+gGbr6ybrEY3avBAL5MDiYi2aa23Aj0A79ry4rJRvPAwE2TM8bd+A==", + "requires": { + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "@lezer/json": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.0.tgz", + "integrity": "sha512-zbAuUY09RBzCoCA3lJ1+ypKw5WSNvLqGMtasdW6HvVOqZoCpPr8eWrsGnOVWGKGn8Rh21FnrKRVlJXrGAVUqRw==", + "requires": { + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "@lezer/lr": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.4.tgz", + "integrity": "sha512-7o+e4og/QoC/6btozDPJqnzBhUaD1fMfmvnEKQO1wRRiTse1WxaJ3OMEXZJnkgT6HCcTVOctSoXK9jGJw2oe9g==", + "requires": { + "@lezer/common": "^1.0.0" + } + }, "@mdx-js/loader": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-1.6.22.tgz", @@ -55549,7 +55973,8 @@ "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-1.6.22.tgz", "integrity": "sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg==", - "dev": true + "dev": true, + "requires": {} }, "@mdx-js/util": { "version": "1.6.22", @@ -58721,49 +59146,57 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz", "integrity": "sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-remove-jsx-attribute": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz", "integrity": "sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-remove-jsx-empty-expression": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz", "integrity": "sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-replace-jsx-attribute-value": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz", "integrity": "sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-svg-dynamic-title": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz", "integrity": "sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-svg-em-dimensions": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz", "integrity": "sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-transform-react-native-svg": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz", "integrity": "sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-plugin-transform-svg-component": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz", "integrity": "sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg==", - "dev": true + "dev": true, + "requires": {} }, "@svgr/babel-preset": { "version": "6.2.0", @@ -59823,6 +60256,16 @@ "integrity": "sha512-7tFImggNeNBVMsn0vLrpn1H1uPrUBdnARPTpZoitY37ZrdJREzf7I16tMrlK3hen349gr1NYh8CmZQa7CTG6Aw==", "dev": true }, + "@uiw/codemirror-extensions-color": { + "version": "4.20.2", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-extensions-color/-/codemirror-extensions-color-4.20.2.tgz", + "integrity": "sha512-z9mHBibvajeyI9PQGzaGoBIFAI+S+64+Y60ukwBYoje67lzDX407AMExw8QNC+Shoswegmf0AgJEiR9aT90ebw==", + "requires": { + "colors-named": "^1.0.0", + "colors-named-hex": "^1.0.0", + "hsl-matcher": "^1.2.3" + } + }, "@vue/compiler-core": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.1.5.tgz", @@ -60186,7 +60629,8 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.1.1.tgz", "integrity": "sha512-1FBc1f9G4P/AxMqIgfZgeOTuRnwZMten8E7zap5zgpPInnCrP8D4Q81+4CWIch8i/Nf7nXjP0v6CjjbHOrXhKg==", - "dev": true + "dev": true, + "requires": {} }, "@webpack-cli/info": { "version": "1.4.1", @@ -60201,7 +60645,8 @@ "version": "1.6.1", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.6.1.tgz", "integrity": "sha512-gNGTiTrjEVQ0OcVnzsRSqTxaBSr+dmTfm+qJsCDluky8uhdLWep7Gcr62QsAKHTMxjCS/8nEITsmFAhfIx+QSw==", - "dev": true + "dev": true, + "requires": {} }, "@xmldom/xmldom": { "version": "0.7.5", @@ -60271,7 +60716,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true + "requires": {} }, "acorn-walk": { "version": "7.2.0", @@ -60360,7 +60805,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", - "dev": true + "dev": true, + "requires": {} }, "ajv-formats": { "version": "2.1.1", @@ -60396,7 +60842,8 @@ "ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==" + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "requires": {} }, "ansi-align": { "version": "3.0.0", @@ -60526,7 +60973,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -60941,8 +61387,7 @@ "astral-regex": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" }, "async": { "version": "3.2.3", @@ -61166,7 +61611,8 @@ "version": "7.0.0-bridge.0", "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", - "dev": true + "dev": true, + "requires": {} }, "babel-helper-evaluate-path": { "version": "0.5.0", @@ -61886,7 +62332,8 @@ "version": "0.3.7", "resolved": "https://registry.npmjs.org/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.7.tgz", "integrity": "sha512-squySRkf+6JGnvjoUtDEjSREJEBirnXi9NqP6rjSYsylxQxqBTz+pkmf395i9E2zsvmYUaI40BHo6SqZUdydlw==", - "dev": true + "dev": true, + "requires": {} }, "babel-plugin-polyfill-corejs2": { "version": "0.3.1", @@ -63412,7 +63859,8 @@ "codemirror-colorpicker": { "version": "1.9.80", "resolved": "https://registry.npmjs.org/codemirror-colorpicker/-/codemirror-colorpicker-1.9.80.tgz", - "integrity": "sha512-7lGqNxf5haBJXLnVR1ynPiPkN2d1Whm0jdy8Z9QsSOhRWVyK2C2ihgm1dX4DCks57ht/jKMdpL9lYv+zAphxWQ==" + "integrity": "sha512-7lGqNxf5haBJXLnVR1ynPiPkN2d1Whm0jdy8Z9QsSOhRWVyK2C2ihgm1dX4DCks57ht/jKMdpL9lYv+zAphxWQ==", + "requires": {} }, "collapse-white-space": { "version": "1.0.6", @@ -63490,6 +63938,16 @@ "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==", "dev": true }, + "colors-named": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/colors-named/-/colors-named-1.0.1.tgz", + "integrity": "sha512-MGhZwJ6SPSdrg5qsr3YB3sD4zB2bfm3bPj9iIdkjxruUYNQakiBBWL+kFM3SXnyfkZClj3Bq7vofBKbgeJRJ/Q==" + }, + "colors-named-hex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/colors-named-hex/-/colors-named-hex-1.0.1.tgz", + "integrity": "sha512-2uoNWhxAPRn3GVpbuaQ2p5LAMhsjd9r/ZqQNJTUcEr1XQCkMFWh9zPLJLjg1l51xYApdDCMIEjkDNpoAXK2vMw==" + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -64680,6 +65138,11 @@ } } }, + "crelt": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.5.tgz", + "integrity": "sha512-+BO9wPPi+DWTDcNYhr/W90myha8ptzftZT+LwcmUbbok0rcP/fequmFYCw8NMoH7pkAZQzU78b3kYrlua5a9eA==" + }, "cross-env": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-5.2.1.tgz", @@ -65016,7 +65479,8 @@ "version": "6.2.2", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.2.2.tgz", "integrity": "sha512-Ufadglr88ZLsrvS11gjeu/40Lw74D9Am/Jpr3LlYm5Q4ZP5KdlUhG+6u2EjyXeZcxmZ2h1ebCKngDjolpeLHpg==", - "dev": true + "dev": true, + "requires": {} }, "css-select": { "version": "4.3.0", @@ -65217,25 +65681,29 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.1.tgz", "integrity": "sha512-5JscyFmvkUxz/5/+TB3QTTT9Gi9jHkcn8dcmmuN68JQcv3aQg4y88yEHHhwFB52l/NkaJ43O0dbksGMAo49nfQ==", - "dev": true + "dev": true, + "requires": {} }, "postcss-discard-duplicates": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-discard-empty": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", - "dev": true + "dev": true, + "requires": {} }, "postcss-discard-overridden": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-merge-longhand": { "version": "5.1.4", @@ -65303,7 +65771,8 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", - "dev": true + "dev": true, + "requires": {} }, "postcss-normalize-display-values": { "version": "5.1.0", @@ -65599,7 +66068,8 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", - "dev": true + "dev": true, + "requires": {} }, "csso": { "version": "4.2.0", @@ -66062,7 +66532,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, "requires": { "esutils": "^2.0.2" } @@ -66368,6 +66837,15 @@ "integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==", "dev": true }, + "emmet": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/emmet/-/emmet-2.4.4.tgz", + "integrity": "sha512-v8Mwpjym55CS3EjJgiCLWUB3J2HSR93jhzXW325720u8KvYxdI2voYLstW3pHBxFz54H6jFjayR9G4LfTG0q+g==", + "requires": { + "@emmetio/abbreviation": "^2.3.3", + "@emmetio/css-abbreviation": "^2.1.8" + } + }, "emoji-regex": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", @@ -66432,7 +66910,6 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "dev": true, "requires": { "ansi-colors": "^4.1.1" }, @@ -66440,8 +66917,7 @@ "ansi-colors": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" } } }, @@ -66620,7 +67096,6 @@ "version": "7.31.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.31.0.tgz", "integrity": "sha512-vafgJpSh2ia8tnTkNUkwxGmnumgckLh5aAbLa1xRmIn9+owi8qBNGKL+B881kNKNTy7FFqTEkpNkUvmw0n6PkA==", - "dev": true, "requires": { "@babel/code-frame": "7.12.11", "@eslint/eslintrc": "^0.4.3", @@ -66668,7 +67143,6 @@ "version": "7.12.11", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, "requires": { "@babel/highlight": "^7.10.4" } @@ -66676,14 +67150,12 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "chalk": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", - "dev": true, "requires": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -66693,7 +67165,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -66702,7 +67173,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, "requires": { "has-flag": "^4.0.0" } @@ -66713,7 +67183,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -66721,14 +67190,12 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, "requires": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -66738,26 +67205,22 @@ "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, "eslint-visitor-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==" }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -66766,7 +67229,6 @@ "version": "13.10.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.10.0.tgz", "integrity": "sha512-piHC3blgLGFjvOuMmWZX60f+na1lXFDhQXBf1UYp2fXPXqvEUbOhNwi6BsQ0bQishwedgnjkwv1d9zKf+MWw3g==", - "dev": true, "requires": { "type-fest": "^0.20.2" } @@ -66774,20 +67236,17 @@ "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", - "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", - "dev": true + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==" }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -66796,14 +67255,12 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-glob": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -66812,7 +67269,6 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, "requires": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -66822,7 +67278,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, "requires": { "yallist": "^4.0.0" } @@ -66831,7 +67286,6 @@ "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, "requires": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", @@ -66844,26 +67298,22 @@ "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==" }, "resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", - "dev": true, "requires": { "lru-cache": "^6.0.0" } @@ -66872,7 +67322,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "requires": { "shebang-regex": "^3.0.0" } @@ -66880,14 +67329,12 @@ "shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" }, "strip-ansi": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "requires": { "ansi-regex": "^5.0.0" } @@ -66895,14 +67342,12 @@ "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, "requires": { "prelude-ls": "^1.2.1" } @@ -66910,14 +67355,12 @@ "type-fest": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "requires": { "isexe": "^2.0.0" } @@ -66925,8 +67368,7 @@ "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } }, @@ -66952,7 +67394,8 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz", "integrity": "sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg==", - "dev": true + "dev": true, + "requires": {} }, "eslint-import-resolver-node": { "version": "0.3.4", @@ -67376,7 +67819,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", - "dev": true, "requires": { "eslint-visitor-keys": "^1.1.0" }, @@ -67384,8 +67826,7 @@ "eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" } } }, @@ -67483,7 +67924,6 @@ "version": "7.3.1", "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, "requires": { "acorn": "^7.4.0", "acorn-jsx": "^5.3.1", @@ -67493,14 +67933,12 @@ "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" }, "eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" } } }, @@ -67513,7 +67951,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, "requires": { "estraverse": "^5.1.0" }, @@ -67521,8 +67958,7 @@ "estraverse": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", - "dev": true + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==" } } }, @@ -68492,7 +68928,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, "requires": { "flat-cache": "^3.0.4" } @@ -68675,7 +69110,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, "requires": { "flatted": "^3.1.0", "rimraf": "^3.0.2" @@ -68685,7 +69119,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "requires": { "glob": "^7.1.3" } @@ -68695,8 +69128,7 @@ "flatted": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.1.tgz", - "integrity": "sha512-OMQjaErSFHmHqZe+PSidH5n8j3O0F2DdnVh8JB4j4eUQ2k6KvB0qGfrKIhapvez5JerBbmWkaLYUYWISaESoXg==", - "dev": true + "integrity": "sha512-OMQjaErSFHmHqZe+PSidH5n8j3O0F2DdnVh8JB4j4eUQ2k6KvB0qGfrKIhapvez5JerBbmWkaLYUYWISaESoXg==" }, "flatten": { "version": "1.0.2", @@ -69870,8 +70302,7 @@ "functional-red-black-tree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=" }, "functions-have-names": { "version": "1.2.2", @@ -70568,6 +70999,11 @@ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", "dev": true }, + "hsl-matcher": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/hsl-matcher/-/hsl-matcher-1.2.3.tgz", + "integrity": "sha512-irW1socbRjPPAtX/jdl2AWntFB2cCv5W0BGoeZW4uFURCWzupsyAqnw0wPB1qh5wKjdrEYVRV++IuLko+P31OA==" + }, "html-encoding-sniffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", @@ -71157,7 +71593,8 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", - "dev": true + "dev": true, + "requires": {} }, "ieee754": { "version": "1.1.13", @@ -71311,8 +71748,7 @@ "imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" }, "indent-string": { "version": "4.0.0", @@ -75138,7 +75574,8 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", - "dev": true + "dev": true, + "requires": {} }, "jest-regex-util": { "version": "24.9.0", @@ -77518,7 +77955,6 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -77987,7 +78423,8 @@ "ws": { "version": "8.8.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", - "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==" + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", + "requires": {} } } }, @@ -78084,8 +78521,7 @@ "json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=" }, "json-stringify-safe": { "version": "5.0.1", @@ -78729,8 +79165,7 @@ "lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", - "dev": true + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" }, "lodash.curry": { "version": "4.1.1", @@ -78843,8 +79278,7 @@ "lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=", - "dev": true + "integrity": "sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=" }, "lodash.unescape": { "version": "4.0.1", @@ -80712,7 +81146,8 @@ "mockingoose": { "version": "2.15.2", "resolved": "https://registry.npmjs.org/mockingoose/-/mockingoose-2.15.2.tgz", - "integrity": "sha512-50mtbAk29Go5hdhzqTmjmE67Z/cB0yPz45u2jrHoGm4nkYnnBq224viWgyKwnxzWw8birnqn98viM2cRBTnJvw==" + "integrity": "sha512-50mtbAk29Go5hdhzqTmjmE67Z/cB0yPz45u2jrHoGm4nkYnnBq224viWgyKwnxzWw8birnqn98viM2cRBTnJvw==", + "requires": {} }, "mongodb": { "version": "2.2.36", @@ -80835,7 +81270,8 @@ "mongoose-legacy-pluralize": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", - "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==", + "requires": {} }, "move-concurrently": { "version": "1.0.1", @@ -81311,8 +81747,7 @@ "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=" }, "negotiator": { "version": "0.6.2", @@ -83395,7 +83830,8 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/postcss-focus/-/postcss-focus-5.0.1.tgz", "integrity": "sha512-iVP+4VLenlI0tHHJD+7HyE+7pQ6Hlg3+Zm/xTwNE1LT7OgmYC4r1ale6AnEkABGNKKE3j1LkF/BNcv89lDoICw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-focus-visible": { "version": "4.0.0", @@ -83758,7 +84194,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true + "dev": true, + "requires": {} }, "postcss-modules-local-by-default": { "version": "4.0.0", @@ -84393,8 +84830,7 @@ "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, "promise": { "version": "7.3.1", @@ -85323,7 +85759,8 @@ "react-ga": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/react-ga/-/react-ga-3.3.0.tgz", - "integrity": "sha512-o8RScHj6Lb8cwy3GMrVH6NJvL+y0zpJvKtc0+wmH7Bt23rszJmnqEQxRbyrqUzk9DTJIHoP42bfO5rswC9SWBQ==" + "integrity": "sha512-o8RScHj6Lb8cwy3GMrVH6NJvL+y0zpJvKtc0+wmH7Bt23rszJmnqEQxRbyrqUzk9DTJIHoP42bfO5rswC9SWBQ==", + "requires": {} }, "react-helmet": { "version": "5.2.1", @@ -86181,8 +86618,7 @@ "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==" }, "regexpu-core": { "version": "5.0.1", @@ -87611,7 +88047,8 @@ "sinon-mongoose": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/sinon-mongoose/-/sinon-mongoose-2.3.0.tgz", - "integrity": "sha512-d0rrL53wuDDs91GMCFAvQam64IpdVfkaxA4cGLTZfw1d5tTg6+F/D7F080d1n3d1gSHJBZLUf9pGpijC/x7xKQ==" + "integrity": "sha512-d0rrL53wuDDs91GMCFAvQam64IpdVfkaxA4cGLTZfw1d5tTg6+F/D7F080d1n3d1gSHJBZLUf9pGpijC/x7xKQ==", + "requires": {} }, "sisteransi": { "version": "1.0.5", @@ -87629,7 +88066,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, "requires": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -87640,7 +88076,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -87649,7 +88084,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "requires": { "color-name": "~1.1.4" } @@ -87657,14 +88091,12 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" } } }, @@ -87980,8 +88412,7 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sshpk": { "version": "1.16.1", @@ -88531,7 +88962,13 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", - "dev": true + "dev": true, + "requires": {} + }, + "style-mod": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.3.tgz", + "integrity": "sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw==" }, "style-to-object": { "version": "0.3.0", @@ -88770,7 +89207,6 @@ "version": "6.7.1", "resolved": "https://registry.npmjs.org/table/-/table-6.7.1.tgz", "integrity": "sha512-ZGum47Yi6KOOFDE8m223td53ath2enHcYLgOCjGr5ngu8bdIARQk6mN/wRMv4yMRcHnCSnHbCEha4sobQx5yWg==", - "dev": true, "requires": { "ajv": "^8.0.1", "lodash.clonedeep": "^4.5.0", @@ -88784,7 +89220,6 @@ "version": "8.6.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.6.2.tgz", "integrity": "sha512-9807RlWAgT564wT+DjeyU5OFMPjmzxVobvDFmNAhY+5zD6A2ly3jDp6sgnfyDtlIQ+7H97oc/DGCzzfu9rjw9w==", - "dev": true, "requires": { "fast-deep-equal": "^3.1.1", "json-schema-traverse": "^1.0.0", @@ -88795,38 +89230,32 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" }, "json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" }, "string-width": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", - "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -88837,7 +89266,6 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, "requires": { "ansi-regex": "^5.0.0" } @@ -89068,8 +89496,7 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "thenify": { "version": "3.3.0", @@ -89831,7 +90258,8 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.2.5.tgz", "integrity": "sha512-gN3vgMISAgacF7sqsLPByqoePooY3n2emTH59Ur5d/M8eg4WTWu1xp8i8DHjohftIyEx0S08RiYxbffr4j8Peg==", - "dev": true + "dev": true, + "requires": {} }, "use-sidecar": { "version": "1.0.5", @@ -89886,8 +90314,7 @@ "v8-compile-cache": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==" }, "v8-to-istanbul": { "version": "8.1.0", @@ -90047,6 +90474,11 @@ "browser-process-hrtime": "^1.0.0" } }, + "w3c-keyname": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.6.tgz", + "integrity": "sha512-f+fciywl1SJEniZHD6H+kUO8gOnwIr7f4ijKA6+ZvJFjeGi1r4PDLl53Ayud9O/rk64RqgoQine0feoeOU0kXg==" + }, "w3c-xmlserializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz", @@ -90605,7 +91037,8 @@ "acorn-import-assertions": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==" + "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "requires": {} }, "glob-to-regexp": { "version": "0.4.1", @@ -91137,8 +91570,7 @@ "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==" }, "wordwrap": { "version": "1.0.0", @@ -91258,7 +91690,8 @@ "version": "7.5.5", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", - "dev": true + "dev": true, + "requires": {} }, "xdg-basedir": { "version": "4.0.0", diff --git a/package.json b/package.json index 7efb4a35f2..f982891042 100644 --- a/package.json +++ b/package.json @@ -147,11 +147,24 @@ "@auth0/s3": "^1.0.0", "@babel/core": "^7.14.6", "@babel/register": "^7.14.5", - "@emmetio/codemirror-plugin": "^1.2.4", + "@codemirror/autocomplete": "^6.7.1", + "@codemirror/commands": "^6.2.4", + "@codemirror/lang-css": "^6.2.0", + "@codemirror/lang-html": "^6.4.3", + "@codemirror/lang-javascript": "^6.1.8", + "@codemirror/lang-json": "^6.0.1", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.2.1", + "@codemirror/search": "^6.4.0", + "@codemirror/state": "^6.2.0", + "@codemirror/view": "^6.11.2", + "@emmetio/codemirror6-plugin": "^0.3.0", "@gatsbyjs/webpack-hot-middleware": "^2.25.3", + "@lezer/highlight": "^1.1.4", "@redux-devtools/core": "^3.11.0", "@redux-devtools/dock-monitor": "^2.1.0", "@redux-devtools/log-monitor": "^3.1.0", + "@uiw/codemirror-extensions-color": "^4.20.2", "async": "^3.2.3", "axios": "^0.21.2", "babel-plugin-styled-components": "^1.13.2",