@@ -11,6 +11,39 @@ import CodeMirrorSpellChecker, { supportLanguages, supportLanguageCodes } from '
1111import { initTableEditor } from './table-editor'
1212import { availableThemes } from './constants'
1313
14+ // Storage utility class for localStorage operations
15+ class Storage {
16+ static get ( key , defaultValue = null ) {
17+ try {
18+ const value = localStorage . getItem ( key )
19+ return value !== null ? value : defaultValue
20+ } catch ( e ) {
21+ console . error ( 'Error getting from localStorage:' , e )
22+ return defaultValue
23+ }
24+ }
25+
26+ static set ( key , value , options = { } ) {
27+ try {
28+ localStorage . setItem ( key , value )
29+ return true
30+ } catch ( e ) {
31+ console . error ( 'Error setting to localStorage:' , e )
32+ return false
33+ }
34+ }
35+
36+ static remove ( key ) {
37+ try {
38+ localStorage . removeItem ( key )
39+ return true
40+ } catch ( e ) {
41+ console . error ( 'Error removing from localStorage:' , e )
42+ return false
43+ }
44+ }
45+ }
46+
1447/* config section */
1548const isMac = CodeMirror . keyMap . default === CodeMirror . keyMap . macDefault
1649const defaultEditorMode = 'gfm'
@@ -183,6 +216,39 @@ export default class Editor {
183216 CodeMirror . defineMode ( 'markmap' , function ( config , modeConfig ) {
184217 return CodeMirror . overlayMode ( CodeMirror . getMode ( config , 'gfm' ) , ignoreOverlay )
185218 } )
219+
220+ // Migrate preferences from cookies to localStorage
221+ this . migratePreferences ( )
222+ }
223+
224+ // Migrate preferences from cookies to localStorage
225+ migratePreferences ( ) {
226+ // Only run migration if window and localStorage are available
227+ if ( typeof window === 'undefined' || typeof localStorage === 'undefined' || typeof Cookies === 'undefined' ) {
228+ return
229+ }
230+
231+ const preferencesToMigrate = [
232+ 'indent_type' ,
233+ 'tab_size' ,
234+ 'space_units' ,
235+ 'keymap' ,
236+ 'theme' ,
237+ 'spellcheck' ,
238+ 'linter' ,
239+ 'preferences-override-browser-keymap' ,
240+ 'preferences-disable-table-shortcuts'
241+ ]
242+
243+ preferencesToMigrate . forEach ( key => {
244+ // Check if preference exists in cookies but not in localStorage
245+ const cookieValue = Cookies . get ( key )
246+ if ( cookieValue !== undefined && Storage . get ( key ) === null ) {
247+ // Migrate the preference to localStorage
248+ Storage . set ( key , cookieValue )
249+ console . log ( `Migrated preference ${ key } from cookies to localStorage` )
250+ }
251+ } )
186252 }
187253
188254 on ( event , cb ) {
@@ -423,24 +489,24 @@ export default class Editor {
423489 }
424490
425491 setIndent ( ) {
426- var cookieIndentType = Cookies . get ( 'indent_type' )
427- var cookieTabSize = parseInt ( Cookies . get ( 'tab_size' ) )
428- var cookieSpaceUnits = parseInt ( Cookies . get ( 'space_units' ) )
429- if ( cookieIndentType ) {
430- if ( cookieIndentType === 'tab' ) {
492+ var storedIndentType = Storage . get ( 'indent_type' )
493+ var storedTabSize = parseInt ( Storage . get ( 'tab_size' ) )
494+ var storedSpaceUnits = parseInt ( Storage . get ( 'space_units' ) )
495+ if ( storedIndentType ) {
496+ if ( storedIndentType === 'tab' ) {
431497 this . editor . setOption ( 'indentWithTabs' , true )
432- if ( cookieTabSize ) {
433- this . editor . setOption ( 'indentUnit' , cookieTabSize )
498+ if ( storedTabSize ) {
499+ this . editor . setOption ( 'indentUnit' , storedTabSize )
434500 }
435- } else if ( cookieIndentType === 'space' ) {
501+ } else if ( storedIndentType === 'space' ) {
436502 this . editor . setOption ( 'indentWithTabs' , false )
437- if ( cookieSpaceUnits ) {
438- this . editor . setOption ( 'indentUnit' , cookieSpaceUnits )
503+ if ( storedSpaceUnits ) {
504+ this . editor . setOption ( 'indentUnit' , storedSpaceUnits )
439505 }
440506 }
441507 }
442- if ( cookieTabSize ) {
443- this . editor . setOption ( 'tabSize' , cookieTabSize )
508+ if ( storedTabSize ) {
509+ this . editor . setOption ( 'tabSize' , storedTabSize )
444510 }
445511
446512 var type = this . statusIndicators . find ( '.indent-type' )
@@ -449,14 +515,10 @@ export default class Editor {
449515
450516 const setType = ( ) => {
451517 if ( this . editor . getOption ( 'indentWithTabs' ) ) {
452- Cookies . set ( 'indent_type' , 'tab' , {
453- expires : 365
454- } )
518+ Storage . set ( 'indent_type' , 'tab' )
455519 type . text ( 'Tab Size:' )
456520 } else {
457- Cookies . set ( 'indent_type' , 'space' , {
458- expires : 365
459- } )
521+ Storage . set ( 'indent_type' , 'space' )
460522 type . text ( 'Spaces:' )
461523 }
462524 }
@@ -465,13 +527,9 @@ export default class Editor {
465527 const setUnit = ( ) => {
466528 var unit = this . editor . getOption ( 'indentUnit' )
467529 if ( this . editor . getOption ( 'indentWithTabs' ) ) {
468- Cookies . set ( 'tab_size' , unit , {
469- expires : 365
470- } )
530+ Storage . set ( 'tab_size' , unit )
471531 } else {
472- Cookies . set ( 'space_units' , unit , {
473- expires : 365
474- } )
532+ Storage . set ( 'space_units' , unit )
475533 }
476534 widthLabel . text ( unit )
477535 }
@@ -480,16 +538,16 @@ export default class Editor {
480538 type . click ( ( ) => {
481539 if ( this . editor . getOption ( 'indentWithTabs' ) ) {
482540 this . editor . setOption ( 'indentWithTabs' , false )
483- cookieSpaceUnits = parseInt ( Cookies . get ( 'space_units' ) )
484- if ( cookieSpaceUnits ) {
485- this . editor . setOption ( 'indentUnit' , cookieSpaceUnits )
541+ storedSpaceUnits = parseInt ( Storage . get ( 'space_units' ) )
542+ if ( storedSpaceUnits ) {
543+ this . editor . setOption ( 'indentUnit' , storedSpaceUnits )
486544 }
487545 } else {
488546 this . editor . setOption ( 'indentWithTabs' , true )
489- cookieTabSize = parseInt ( Cookies . get ( 'tab_size' ) )
490- if ( cookieTabSize ) {
491- this . editor . setOption ( 'indentUnit' , cookieTabSize )
492- this . editor . setOption ( 'tabSize' , cookieTabSize )
547+ storedTabSize = parseInt ( Storage . get ( 'tab_size' ) )
548+ if ( storedTabSize ) {
549+ this . editor . setOption ( 'indentUnit' , storedTabSize )
550+ this . editor . setOption ( 'tabSize' , storedTabSize )
493551 }
494552 }
495553 setType ( )
@@ -525,9 +583,9 @@ export default class Editor {
525583 }
526584
527585 setKeymap ( ) {
528- var cookieKeymap = Cookies . get ( 'keymap' )
529- if ( cookieKeymap ) {
530- this . editor . setOption ( 'keyMap' , cookieKeymap )
586+ var storedKeymap = Storage . get ( 'keymap' )
587+ if ( storedKeymap ) {
588+ this . editor . setOption ( 'keyMap' , storedKeymap )
531589 }
532590
533591 var label = this . statusIndicators . find ( '.ui-keymap-label' )
@@ -537,9 +595,7 @@ export default class Editor {
537595
538596 const setKeymapLabel = ( ) => {
539597 var keymap = this . editor . getOption ( 'keyMap' )
540- Cookies . set ( 'keymap' , keymap , {
541- expires : 365
542- } )
598+ Storage . set ( 'keymap' , keymap )
543599 label . text ( keymap )
544600 this . restoreOverrideEditorKeymap ( )
545601 this . setOverrideBrowserKeymap ( )
@@ -572,17 +628,15 @@ export default class Editor {
572628
573629 const setTheme = theme => {
574630 this . editor . setOption ( 'theme' , theme )
575- Cookies . set ( 'theme' , theme , {
576- expires : 365
577- } )
631+ Storage . set ( 'theme' , theme )
578632 this . statusIndicators . find ( '.status-theme li' ) . removeClass ( 'active' )
579633 this . statusIndicators . find ( `.status-theme li[value="${ theme } "]` ) . addClass ( 'active' )
580634 }
581635
582- const cookieTheme = Cookies . get ( 'theme' )
583- if ( cookieTheme && availableThemes . find ( theme => cookieTheme === theme . value ) ) {
584- setTheme ( cookieTheme )
585- activateThemeListItem ( cookieTheme )
636+ const storedTheme = Storage . get ( 'theme' )
637+ if ( storedTheme && availableThemes . find ( theme => storedTheme === theme . value ) ) {
638+ setTheme ( storedTheme )
639+ activateThemeListItem ( storedTheme )
586640 } else {
587641 activateThemeListItem ( this . editor . getOption ( 'theme' ) )
588642 }
@@ -613,10 +667,10 @@ export default class Editor {
613667 }
614668
615669 getExistingSpellcheckLang ( ) {
616- const cookieSpellcheck = Cookies . get ( 'spellcheck' )
670+ const storedSpellcheck = Storage . get ( 'spellcheck' )
617671
618- if ( cookieSpellcheck ) {
619- return cookieSpellcheck === 'false' ? undefined : cookieSpellcheck
672+ if ( storedSpellcheck ) {
673+ return storedSpellcheck === 'false' ? undefined : storedSpellcheck
620674 } else {
621675 return undefined
622676 }
@@ -637,18 +691,18 @@ export default class Editor {
637691 return $ ( `<li value="${ lang . value } "><a>${ lang . name } </a></li>` )
638692 } ) )
639693
640- const cookieSpellcheck = Cookies . get ( 'spellcheck' )
641- if ( cookieSpellcheck ) {
694+ const storedSpellcheck = Storage . get ( 'spellcheck' )
695+ if ( storedSpellcheck ) {
642696 let mode = null
643697 let lang = 'en_US'
644698
645- if ( cookieSpellcheck === 'false' || ! cookieSpellcheck ) {
699+ if ( storedSpellcheck === 'false' || ! storedSpellcheck ) {
646700 mode = defaultEditorMode
647701 this . activateSpellcheckListItem ( false )
648702 } else {
649703 mode = 'spell-checker'
650- if ( supportLanguageCodes . includes ( cookieSpellcheck ) ) {
651- lang = cookieSpellcheck
704+ if ( supportLanguageCodes . includes ( storedSpellcheck ) ) {
705+ lang = storedSpellcheck
652706 }
653707 this . setSpellcheckLang ( lang )
654708 }
@@ -674,17 +728,13 @@ export default class Editor {
674728 if ( lang === 'disabled' ) {
675729 spellcheckToggle . removeClass ( 'active' )
676730
677- Cookies . set ( 'spellcheck' , false , {
678- expires : 365
679- } )
731+ Storage . set ( 'spellcheck' , 'false' )
680732
681733 self . editor . setOption ( 'mode' , defaultEditorMode )
682734 } else {
683735 spellcheckToggle . addClass ( 'active' )
684736
685- Cookies . set ( 'spellcheck' , lang , {
686- expires : 365
687- } )
737+ Storage . set ( 'spellcheck' , lang )
688738
689739 self . editor . setOption ( 'mode' , 'spell-checker' )
690740 }
@@ -703,12 +753,10 @@ export default class Editor {
703753 if ( ! gutters . includes ( lintGutter ) ) {
704754 this . editor . setOption ( 'gutters' , [ lintGutter , ...gutters ] )
705755 }
706- Cookies . set ( 'linter' , true , {
707- expires : 365
708- } )
756+ Storage . set ( 'linter' , 'true' )
709757 } else {
710758 this . editor . setOption ( 'gutters' , gutters . filter ( g => g !== lintGutter ) )
711- Cookies . remove ( 'linter' )
759+ Storage . remove ( 'linter' )
712760 }
713761 this . editor . setOption ( 'lint' , enable ? linterOptions : false )
714762 }
@@ -726,7 +774,7 @@ export default class Editor {
726774 updateLinterStatus ( ! lintEnable )
727775 } )
728776
729- const enable = ! ! Cookies . get ( 'linter' )
777+ const enable = Storage . get ( 'linter' ) === 'true'
730778 this . toggleLinter . bind ( this ) ( enable )
731779 updateLinterStatus ( enable )
732780 }
@@ -752,12 +800,10 @@ export default class Editor {
752800 '.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
753801 )
754802 if ( overrideBrowserKeymap . is ( ':checked' ) ) {
755- Cookies . set ( 'preferences-override-browser-keymap' , true , {
756- expires : 365
757- } )
803+ Storage . set ( 'preferences-override-browser-keymap' , 'true' )
758804 this . restoreOverrideEditorKeymap ( )
759805 } else {
760- Cookies . remove ( 'preferences-override-browser-keymap' )
806+ Storage . remove ( 'preferences-override-browser-keymap' )
761807 this . resetEditorKeymapToBrowserKeymap ( )
762808 }
763809 }
@@ -766,10 +812,10 @@ export default class Editor {
766812 var overrideBrowserKeymap = $ (
767813 '.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
768814 )
769- var cookieOverrideBrowserKeymap = Cookies . get (
815+ var storedOverrideBrowserKeymap = Storage . get (
770816 'preferences-override-browser-keymap'
771817 )
772- if ( cookieOverrideBrowserKeymap && cookieOverrideBrowserKeymap === 'true' ) {
818+ if ( storedOverrideBrowserKeymap && storedOverrideBrowserKeymap === 'true' ) {
773819 overrideBrowserKeymap . prop ( 'checked' , true )
774820 } else {
775821 overrideBrowserKeymap . prop ( 'checked' , false )
@@ -784,10 +830,10 @@ export default class Editor {
784830 var disableTableShortcuts = $ (
785831 '.ui-preferences-disable-table-shortcuts label > input[type="checkbox"]'
786832 )
787- var cookieDisableTableShortcuts = Cookies . get (
833+ var storedDisableTableShortcuts = Storage . get (
788834 'preferences-disable-table-shortcuts'
789835 )
790- if ( cookieDisableTableShortcuts && cookieDisableTableShortcuts === 'true' ) {
836+ if ( storedDisableTableShortcuts && storedDisableTableShortcuts === 'true' ) {
791837 disableTableShortcuts . prop ( 'checked' , true )
792838 } else {
793839 disableTableShortcuts . prop ( 'checked' , false )
@@ -804,11 +850,9 @@ export default class Editor {
804850 '.ui-preferences-disable-table-shortcuts label > input[type="checkbox"]'
805851 )
806852 if ( disableTableShortcuts . is ( ':checked' ) ) {
807- Cookies . set ( 'preferences-disable-table-shortcuts' , true , {
808- expires : 365
809- } )
853+ Storage . set ( 'preferences-disable-table-shortcuts' , 'true' )
810854 } else {
811- Cookies . remove ( 'preferences-disable-table-shortcuts' )
855+ Storage . remove ( 'preferences-disable-table-shortcuts' )
812856 }
813857 // Notify table editor about the preference change
814858 if ( this . tableEditor ) {
0 commit comments