@@ -11,6 +11,39 @@ import CodeMirrorSpellChecker, { supportLanguages, supportLanguageCodes } from '
11
11
import { initTableEditor } from './table-editor'
12
12
import { availableThemes } from './constants'
13
13
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
+
14
47
/* config section */
15
48
const isMac = CodeMirror . keyMap . default === CodeMirror . keyMap . macDefault
16
49
const defaultEditorMode = 'gfm'
@@ -183,6 +216,39 @@ export default class Editor {
183
216
CodeMirror . defineMode ( 'markmap' , function ( config , modeConfig ) {
184
217
return CodeMirror . overlayMode ( CodeMirror . getMode ( config , 'gfm' ) , ignoreOverlay )
185
218
} )
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
+ } )
186
252
}
187
253
188
254
on ( event , cb ) {
@@ -423,24 +489,24 @@ export default class Editor {
423
489
}
424
490
425
491
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' ) {
431
497
this . editor . setOption ( 'indentWithTabs' , true )
432
- if ( cookieTabSize ) {
433
- this . editor . setOption ( 'indentUnit' , cookieTabSize )
498
+ if ( storedTabSize ) {
499
+ this . editor . setOption ( 'indentUnit' , storedTabSize )
434
500
}
435
- } else if ( cookieIndentType === 'space' ) {
501
+ } else if ( storedIndentType === 'space' ) {
436
502
this . editor . setOption ( 'indentWithTabs' , false )
437
- if ( cookieSpaceUnits ) {
438
- this . editor . setOption ( 'indentUnit' , cookieSpaceUnits )
503
+ if ( storedSpaceUnits ) {
504
+ this . editor . setOption ( 'indentUnit' , storedSpaceUnits )
439
505
}
440
506
}
441
507
}
442
- if ( cookieTabSize ) {
443
- this . editor . setOption ( 'tabSize' , cookieTabSize )
508
+ if ( storedTabSize ) {
509
+ this . editor . setOption ( 'tabSize' , storedTabSize )
444
510
}
445
511
446
512
var type = this . statusIndicators . find ( '.indent-type' )
@@ -449,14 +515,10 @@ export default class Editor {
449
515
450
516
const setType = ( ) => {
451
517
if ( this . editor . getOption ( 'indentWithTabs' ) ) {
452
- Cookies . set ( 'indent_type' , 'tab' , {
453
- expires : 365
454
- } )
518
+ Storage . set ( 'indent_type' , 'tab' )
455
519
type . text ( 'Tab Size:' )
456
520
} else {
457
- Cookies . set ( 'indent_type' , 'space' , {
458
- expires : 365
459
- } )
521
+ Storage . set ( 'indent_type' , 'space' )
460
522
type . text ( 'Spaces:' )
461
523
}
462
524
}
@@ -465,13 +527,9 @@ export default class Editor {
465
527
const setUnit = ( ) => {
466
528
var unit = this . editor . getOption ( 'indentUnit' )
467
529
if ( this . editor . getOption ( 'indentWithTabs' ) ) {
468
- Cookies . set ( 'tab_size' , unit , {
469
- expires : 365
470
- } )
530
+ Storage . set ( 'tab_size' , unit )
471
531
} else {
472
- Cookies . set ( 'space_units' , unit , {
473
- expires : 365
474
- } )
532
+ Storage . set ( 'space_units' , unit )
475
533
}
476
534
widthLabel . text ( unit )
477
535
}
@@ -480,16 +538,16 @@ export default class Editor {
480
538
type . click ( ( ) => {
481
539
if ( this . editor . getOption ( 'indentWithTabs' ) ) {
482
540
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 )
486
544
}
487
545
} else {
488
546
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 )
493
551
}
494
552
}
495
553
setType ( )
@@ -525,9 +583,9 @@ export default class Editor {
525
583
}
526
584
527
585
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 )
531
589
}
532
590
533
591
var label = this . statusIndicators . find ( '.ui-keymap-label' )
@@ -537,9 +595,7 @@ export default class Editor {
537
595
538
596
const setKeymapLabel = ( ) => {
539
597
var keymap = this . editor . getOption ( 'keyMap' )
540
- Cookies . set ( 'keymap' , keymap , {
541
- expires : 365
542
- } )
598
+ Storage . set ( 'keymap' , keymap )
543
599
label . text ( keymap )
544
600
this . restoreOverrideEditorKeymap ( )
545
601
this . setOverrideBrowserKeymap ( )
@@ -572,17 +628,15 @@ export default class Editor {
572
628
573
629
const setTheme = theme => {
574
630
this . editor . setOption ( 'theme' , theme )
575
- Cookies . set ( 'theme' , theme , {
576
- expires : 365
577
- } )
631
+ Storage . set ( 'theme' , theme )
578
632
this . statusIndicators . find ( '.status-theme li' ) . removeClass ( 'active' )
579
633
this . statusIndicators . find ( `.status-theme li[value="${ theme } "]` ) . addClass ( 'active' )
580
634
}
581
635
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 )
586
640
} else {
587
641
activateThemeListItem ( this . editor . getOption ( 'theme' ) )
588
642
}
@@ -613,10 +667,10 @@ export default class Editor {
613
667
}
614
668
615
669
getExistingSpellcheckLang ( ) {
616
- const cookieSpellcheck = Cookies . get ( 'spellcheck' )
670
+ const storedSpellcheck = Storage . get ( 'spellcheck' )
617
671
618
- if ( cookieSpellcheck ) {
619
- return cookieSpellcheck === 'false' ? undefined : cookieSpellcheck
672
+ if ( storedSpellcheck ) {
673
+ return storedSpellcheck === 'false' ? undefined : storedSpellcheck
620
674
} else {
621
675
return undefined
622
676
}
@@ -637,18 +691,18 @@ export default class Editor {
637
691
return $ ( `<li value="${ lang . value } "><a>${ lang . name } </a></li>` )
638
692
} ) )
639
693
640
- const cookieSpellcheck = Cookies . get ( 'spellcheck' )
641
- if ( cookieSpellcheck ) {
694
+ const storedSpellcheck = Storage . get ( 'spellcheck' )
695
+ if ( storedSpellcheck ) {
642
696
let mode = null
643
697
let lang = 'en_US'
644
698
645
- if ( cookieSpellcheck === 'false' || ! cookieSpellcheck ) {
699
+ if ( storedSpellcheck === 'false' || ! storedSpellcheck ) {
646
700
mode = defaultEditorMode
647
701
this . activateSpellcheckListItem ( false )
648
702
} else {
649
703
mode = 'spell-checker'
650
- if ( supportLanguageCodes . includes ( cookieSpellcheck ) ) {
651
- lang = cookieSpellcheck
704
+ if ( supportLanguageCodes . includes ( storedSpellcheck ) ) {
705
+ lang = storedSpellcheck
652
706
}
653
707
this . setSpellcheckLang ( lang )
654
708
}
@@ -674,17 +728,13 @@ export default class Editor {
674
728
if ( lang === 'disabled' ) {
675
729
spellcheckToggle . removeClass ( 'active' )
676
730
677
- Cookies . set ( 'spellcheck' , false , {
678
- expires : 365
679
- } )
731
+ Storage . set ( 'spellcheck' , 'false' )
680
732
681
733
self . editor . setOption ( 'mode' , defaultEditorMode )
682
734
} else {
683
735
spellcheckToggle . addClass ( 'active' )
684
736
685
- Cookies . set ( 'spellcheck' , lang , {
686
- expires : 365
687
- } )
737
+ Storage . set ( 'spellcheck' , lang )
688
738
689
739
self . editor . setOption ( 'mode' , 'spell-checker' )
690
740
}
@@ -703,12 +753,10 @@ export default class Editor {
703
753
if ( ! gutters . includes ( lintGutter ) ) {
704
754
this . editor . setOption ( 'gutters' , [ lintGutter , ...gutters ] )
705
755
}
706
- Cookies . set ( 'linter' , true , {
707
- expires : 365
708
- } )
756
+ Storage . set ( 'linter' , 'true' )
709
757
} else {
710
758
this . editor . setOption ( 'gutters' , gutters . filter ( g => g !== lintGutter ) )
711
- Cookies . remove ( 'linter' )
759
+ Storage . remove ( 'linter' )
712
760
}
713
761
this . editor . setOption ( 'lint' , enable ? linterOptions : false )
714
762
}
@@ -726,7 +774,7 @@ export default class Editor {
726
774
updateLinterStatus ( ! lintEnable )
727
775
} )
728
776
729
- const enable = ! ! Cookies . get ( 'linter' )
777
+ const enable = Storage . get ( 'linter' ) === 'true'
730
778
this . toggleLinter . bind ( this ) ( enable )
731
779
updateLinterStatus ( enable )
732
780
}
@@ -752,12 +800,10 @@ export default class Editor {
752
800
'.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
753
801
)
754
802
if ( overrideBrowserKeymap . is ( ':checked' ) ) {
755
- Cookies . set ( 'preferences-override-browser-keymap' , true , {
756
- expires : 365
757
- } )
803
+ Storage . set ( 'preferences-override-browser-keymap' , 'true' )
758
804
this . restoreOverrideEditorKeymap ( )
759
805
} else {
760
- Cookies . remove ( 'preferences-override-browser-keymap' )
806
+ Storage . remove ( 'preferences-override-browser-keymap' )
761
807
this . resetEditorKeymapToBrowserKeymap ( )
762
808
}
763
809
}
@@ -766,10 +812,10 @@ export default class Editor {
766
812
var overrideBrowserKeymap = $ (
767
813
'.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
768
814
)
769
- var cookieOverrideBrowserKeymap = Cookies . get (
815
+ var storedOverrideBrowserKeymap = Storage . get (
770
816
'preferences-override-browser-keymap'
771
817
)
772
- if ( cookieOverrideBrowserKeymap && cookieOverrideBrowserKeymap === 'true' ) {
818
+ if ( storedOverrideBrowserKeymap && storedOverrideBrowserKeymap === 'true' ) {
773
819
overrideBrowserKeymap . prop ( 'checked' , true )
774
820
} else {
775
821
overrideBrowserKeymap . prop ( 'checked' , false )
@@ -784,10 +830,10 @@ export default class Editor {
784
830
var disableTableShortcuts = $ (
785
831
'.ui-preferences-disable-table-shortcuts label > input[type="checkbox"]'
786
832
)
787
- var cookieDisableTableShortcuts = Cookies . get (
833
+ var storedDisableTableShortcuts = Storage . get (
788
834
'preferences-disable-table-shortcuts'
789
835
)
790
- if ( cookieDisableTableShortcuts && cookieDisableTableShortcuts === 'true' ) {
836
+ if ( storedDisableTableShortcuts && storedDisableTableShortcuts === 'true' ) {
791
837
disableTableShortcuts . prop ( 'checked' , true )
792
838
} else {
793
839
disableTableShortcuts . prop ( 'checked' , false )
@@ -804,11 +850,9 @@ export default class Editor {
804
850
'.ui-preferences-disable-table-shortcuts label > input[type="checkbox"]'
805
851
)
806
852
if ( disableTableShortcuts . is ( ':checked' ) ) {
807
- Cookies . set ( 'preferences-disable-table-shortcuts' , true , {
808
- expires : 365
809
- } )
853
+ Storage . set ( 'preferences-disable-table-shortcuts' , 'true' )
810
854
} else {
811
- Cookies . remove ( 'preferences-disable-table-shortcuts' )
855
+ Storage . remove ( 'preferences-disable-table-shortcuts' )
812
856
}
813
857
// Notify table editor about the preference change
814
858
if ( this . tableEditor ) {
0 commit comments