11/* eslint-disable react-hooks/exhaustive-deps */
22import "../../../assets/stylesheets/EditorPanel.scss" ;
3- import React , { useRef , useEffect , useContext } from "react" ;
3+ import React , { useRef , useEffect , useContext , useState } from "react" ;
44import { useSelector , useDispatch } from "react-redux" ;
55import { updateProjectComponent } from "../../../redux/EditorSlice" ;
66import { useCookies } from "react-cookie" ;
@@ -11,16 +11,20 @@ import { EditorState } from "@codemirror/state";
1111import { defaultKeymap , indentWithTab } from "@codemirror/commands" ;
1212import { indentationMarkers } from "@replit/codemirror-indentation-markers" ;
1313import { indentUnit } from "@codemirror/language" ;
14+ import "material-symbols" ;
1415
1516import { html } from "@codemirror/lang-html" ;
1617import { css } from "@codemirror/lang-css" ;
1718import { python } from "@codemirror/lang-python" ;
1819import { javascript } from "@codemirror/lang-javascript" ;
1920
21+ import { Alert } from "@raspberrypifoundation/design-system-react" ;
2022import { editorLightTheme } from "../../../assets/themes/editorLightTheme" ;
2123import { editorDarkTheme } from "../../../assets/themes/editorDarkTheme" ;
2224import { SettingsContext } from "../../../utils/settings" ;
2325
26+ const MAX_CHARACTERS = 8500000 ;
27+
2428const EditorPanel = ( { extension = "html" , fileName = "index" } ) => {
2529 const editor = useRef ( ) ;
2630 const project = useSelector ( ( state ) => state . editor . project ) ;
@@ -29,6 +33,7 @@ const EditorPanel = ({ extension = "html", fileName = "index" }) => {
2933 const dispatch = useDispatch ( ) ;
3034 const { t } = useTranslation ( ) ;
3135 const settings = useContext ( SettingsContext ) ;
36+ const [ characterLimitExceeded , setCharacterLimitExceeded ] = useState ( false ) ;
3237
3338 const updateStoredProject = ( content ) => {
3439 dispatch (
@@ -86,6 +91,16 @@ const EditorPanel = ({ extension = "html", fileName = "index" }) => {
8691 customIndentUnit = " " ;
8792 }
8893
94+ const limitCharacters = EditorState . transactionFilter . of ( ( transaction ) => {
95+ const newDoc = transaction . newDoc ;
96+ if ( newDoc . length > MAX_CHARACTERS ) {
97+ setCharacterLimitExceeded ( true ) ;
98+ return [ ] ;
99+ }
100+ setCharacterLimitExceeded ( false ) ;
101+ return transaction ;
102+ } ) ;
103+
89104 const startState = EditorState . create ( {
90105 doc : code ,
91106 extensions : [
@@ -98,6 +113,7 @@ const EditorPanel = ({ extension = "html", fileName = "index" }) => {
98113 indentationMarkers ( ) ,
99114 indentUnit . of ( customIndentUnit ) ,
100115 EditorView . editable . of ( ! readOnly ) ,
116+ limitCharacters ,
101117 ] ,
102118 } ) ;
103119
@@ -123,7 +139,18 @@ const EditorPanel = ({ extension = "html", fileName = "index" }) => {
123139 } , [ cookies ] ) ;
124140
125141 return (
126- < div className = { `editor editor--${ settings . fontSize } ` } ref = { editor } > </ div >
142+ < >
143+ < div className = { `editor editor--${ settings . fontSize } ` } ref = { editor } > </ div >
144+ { characterLimitExceeded && (
145+ < Alert
146+ title = { t ( "editorPanel.characterLimitError" ) }
147+ type = "error"
148+ text = { t ( "editorPanel.characterLimitExplanation" , {
149+ maxCharacters : MAX_CHARACTERS ,
150+ } ) }
151+ />
152+ ) }
153+ </ >
127154 ) ;
128155} ;
129156
0 commit comments