1
+ /* eslint-env browser */
1
2
/* global CodeMirror, $, editor, Cookies */
2
3
import { options , Alignment , FormatType } from '@susisu/mte-kernel'
3
4
import debounce from 'lodash/debounce'
@@ -11,6 +12,39 @@ import CodeMirrorSpellChecker, { supportLanguages, supportLanguageCodes } from '
11
12
import { initTableEditor } from './table-editor'
12
13
import { availableThemes } from './constants'
13
14
15
+ // Storage utility class for localStorage operations
16
+ class Storage {
17
+ static get ( key , defaultValue = null ) {
18
+ try {
19
+ const value = localStorage . getItem ( key )
20
+ return value !== null ? value : defaultValue
21
+ } catch ( e ) {
22
+ console . error ( 'Error getting from localStorage:' , e )
23
+ return defaultValue
24
+ }
25
+ }
26
+
27
+ static set ( key , value , options = { } ) {
28
+ try {
29
+ localStorage . setItem ( key , value )
30
+ return true
31
+ } catch ( e ) {
32
+ console . error ( 'Error setting to localStorage:' , e )
33
+ return false
34
+ }
35
+ }
36
+
37
+ static remove ( key ) {
38
+ try {
39
+ localStorage . removeItem ( key )
40
+ return true
41
+ } catch ( e ) {
42
+ console . error ( 'Error removing from localStorage:' , e )
43
+ return false
44
+ }
45
+ }
46
+ }
47
+
14
48
/* config section */
15
49
const isMac = CodeMirror . keyMap . default === CodeMirror . keyMap . macDefault
16
50
const defaultEditorMode = 'gfm'
@@ -183,6 +217,39 @@ export default class Editor {
183
217
CodeMirror . defineMode ( 'markmap' , function ( config , modeConfig ) {
184
218
return CodeMirror . overlayMode ( CodeMirror . getMode ( config , 'gfm' ) , ignoreOverlay )
185
219
} )
220
+
221
+ // Migrate preferences from cookies to localStorage
222
+ this . migratePreferences ( )
223
+ }
224
+
225
+ // Migrate preferences from cookies to localStorage
226
+ migratePreferences ( ) {
227
+ // Only run migration if window and localStorage are available
228
+ if ( typeof window === 'undefined' || typeof localStorage === 'undefined' || typeof Cookies === 'undefined' ) {
229
+ return
230
+ }
231
+
232
+ const preferencesToMigrate = [
233
+ 'indent_type' ,
234
+ 'tab_size' ,
235
+ 'space_units' ,
236
+ 'keymap' ,
237
+ 'theme' ,
238
+ 'spellcheck' ,
239
+ 'linter' ,
240
+ 'preferences-override-browser-keymap' ,
241
+ 'preferences-disable-table-shortcuts'
242
+ ]
243
+
244
+ preferencesToMigrate . forEach ( key => {
245
+ // Check if preference exists in cookies but not in localStorage
246
+ const cookieValue = Cookies . get ( key )
247
+ if ( cookieValue !== undefined && Storage . get ( key ) === null ) {
248
+ // Migrate the preference to localStorage
249
+ Storage . set ( key , cookieValue )
250
+ console . log ( `Migrated preference ${ key } from cookies to localStorage` )
251
+ }
252
+ } )
186
253
}
187
254
188
255
on ( event , cb ) {
@@ -423,24 +490,24 @@ export default class Editor {
423
490
}
424
491
425
492
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' ) {
493
+ var storedIndentType = Storage . get ( 'indent_type' )
494
+ var storedTabSize = parseInt ( Storage . get ( 'tab_size' ) )
495
+ var storedSpaceUnits = parseInt ( Storage . get ( 'space_units' ) )
496
+ if ( storedIndentType ) {
497
+ if ( storedIndentType === 'tab' ) {
431
498
this . editor . setOption ( 'indentWithTabs' , true )
432
- if ( cookieTabSize ) {
433
- this . editor . setOption ( 'indentUnit' , cookieTabSize )
499
+ if ( storedTabSize ) {
500
+ this . editor . setOption ( 'indentUnit' , storedTabSize )
434
501
}
435
- } else if ( cookieIndentType === 'space' ) {
502
+ } else if ( storedIndentType === 'space' ) {
436
503
this . editor . setOption ( 'indentWithTabs' , false )
437
- if ( cookieSpaceUnits ) {
438
- this . editor . setOption ( 'indentUnit' , cookieSpaceUnits )
504
+ if ( storedSpaceUnits ) {
505
+ this . editor . setOption ( 'indentUnit' , storedSpaceUnits )
439
506
}
440
507
}
441
508
}
442
- if ( cookieTabSize ) {
443
- this . editor . setOption ( 'tabSize' , cookieTabSize )
509
+ if ( storedTabSize ) {
510
+ this . editor . setOption ( 'tabSize' , storedTabSize )
444
511
}
445
512
446
513
var type = this . statusIndicators . find ( '.indent-type' )
@@ -449,14 +516,10 @@ export default class Editor {
449
516
450
517
const setType = ( ) => {
451
518
if ( this . editor . getOption ( 'indentWithTabs' ) ) {
452
- Cookies . set ( 'indent_type' , 'tab' , {
453
- expires : 365
454
- } )
519
+ Storage . set ( 'indent_type' , 'tab' )
455
520
type . text ( 'Tab Size:' )
456
521
} else {
457
- Cookies . set ( 'indent_type' , 'space' , {
458
- expires : 365
459
- } )
522
+ Storage . set ( 'indent_type' , 'space' )
460
523
type . text ( 'Spaces:' )
461
524
}
462
525
}
@@ -465,13 +528,9 @@ export default class Editor {
465
528
const setUnit = ( ) => {
466
529
var unit = this . editor . getOption ( 'indentUnit' )
467
530
if ( this . editor . getOption ( 'indentWithTabs' ) ) {
468
- Cookies . set ( 'tab_size' , unit , {
469
- expires : 365
470
- } )
531
+ Storage . set ( 'tab_size' , unit )
471
532
} else {
472
- Cookies . set ( 'space_units' , unit , {
473
- expires : 365
474
- } )
533
+ Storage . set ( 'space_units' , unit )
475
534
}
476
535
widthLabel . text ( unit )
477
536
}
@@ -480,16 +539,16 @@ export default class Editor {
480
539
type . click ( ( ) => {
481
540
if ( this . editor . getOption ( 'indentWithTabs' ) ) {
482
541
this . editor . setOption ( 'indentWithTabs' , false )
483
- cookieSpaceUnits = parseInt ( Cookies . get ( 'space_units' ) )
484
- if ( cookieSpaceUnits ) {
485
- this . editor . setOption ( 'indentUnit' , cookieSpaceUnits )
542
+ storedSpaceUnits = parseInt ( Storage . get ( 'space_units' ) )
543
+ if ( storedSpaceUnits ) {
544
+ this . editor . setOption ( 'indentUnit' , storedSpaceUnits )
486
545
}
487
546
} else {
488
547
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 )
548
+ storedTabSize = parseInt ( Storage . get ( 'tab_size' ) )
549
+ if ( storedTabSize ) {
550
+ this . editor . setOption ( 'indentUnit' , storedTabSize )
551
+ this . editor . setOption ( 'tabSize' , storedTabSize )
493
552
}
494
553
}
495
554
setType ( )
@@ -525,9 +584,9 @@ export default class Editor {
525
584
}
526
585
527
586
setKeymap ( ) {
528
- var cookieKeymap = Cookies . get ( 'keymap' )
529
- if ( cookieKeymap ) {
530
- this . editor . setOption ( 'keyMap' , cookieKeymap )
587
+ var storedKeymap = Storage . get ( 'keymap' )
588
+ if ( storedKeymap ) {
589
+ this . editor . setOption ( 'keyMap' , storedKeymap )
531
590
}
532
591
533
592
var label = this . statusIndicators . find ( '.ui-keymap-label' )
@@ -537,9 +596,7 @@ export default class Editor {
537
596
538
597
const setKeymapLabel = ( ) => {
539
598
var keymap = this . editor . getOption ( 'keyMap' )
540
- Cookies . set ( 'keymap' , keymap , {
541
- expires : 365
542
- } )
599
+ Storage . set ( 'keymap' , keymap )
543
600
label . text ( keymap )
544
601
this . restoreOverrideEditorKeymap ( )
545
602
this . setOverrideBrowserKeymap ( )
@@ -572,17 +629,15 @@ export default class Editor {
572
629
573
630
const setTheme = theme => {
574
631
this . editor . setOption ( 'theme' , theme )
575
- Cookies . set ( 'theme' , theme , {
576
- expires : 365
577
- } )
632
+ Storage . set ( 'theme' , theme )
578
633
this . statusIndicators . find ( '.status-theme li' ) . removeClass ( 'active' )
579
634
this . statusIndicators . find ( `.status-theme li[value="${ theme } "]` ) . addClass ( 'active' )
580
635
}
581
636
582
- const cookieTheme = Cookies . get ( 'theme' )
583
- if ( cookieTheme && availableThemes . find ( theme => cookieTheme === theme . value ) ) {
584
- setTheme ( cookieTheme )
585
- activateThemeListItem ( cookieTheme )
637
+ const storedTheme = Storage . get ( 'theme' )
638
+ if ( storedTheme && availableThemes . find ( theme => storedTheme === theme . value ) ) {
639
+ setTheme ( storedTheme )
640
+ activateThemeListItem ( storedTheme )
586
641
} else {
587
642
activateThemeListItem ( this . editor . getOption ( 'theme' ) )
588
643
}
@@ -613,10 +668,10 @@ export default class Editor {
613
668
}
614
669
615
670
getExistingSpellcheckLang ( ) {
616
- const cookieSpellcheck = Cookies . get ( 'spellcheck' )
671
+ const storedSpellcheck = Storage . get ( 'spellcheck' )
617
672
618
- if ( cookieSpellcheck ) {
619
- return cookieSpellcheck === 'false' ? undefined : cookieSpellcheck
673
+ if ( storedSpellcheck ) {
674
+ return storedSpellcheck === 'false' ? undefined : storedSpellcheck
620
675
} else {
621
676
return undefined
622
677
}
@@ -637,18 +692,18 @@ export default class Editor {
637
692
return $ ( `<li value="${ lang . value } "><a>${ lang . name } </a></li>` )
638
693
} ) )
639
694
640
- const cookieSpellcheck = Cookies . get ( 'spellcheck' )
641
- if ( cookieSpellcheck ) {
695
+ const storedSpellcheck = Storage . get ( 'spellcheck' )
696
+ if ( storedSpellcheck ) {
642
697
let mode = null
643
698
let lang = 'en_US'
644
699
645
- if ( cookieSpellcheck === 'false' || ! cookieSpellcheck ) {
700
+ if ( storedSpellcheck === 'false' || ! storedSpellcheck ) {
646
701
mode = defaultEditorMode
647
702
this . activateSpellcheckListItem ( false )
648
703
} else {
649
704
mode = 'spell-checker'
650
- if ( supportLanguageCodes . includes ( cookieSpellcheck ) ) {
651
- lang = cookieSpellcheck
705
+ if ( supportLanguageCodes . includes ( storedSpellcheck ) ) {
706
+ lang = storedSpellcheck
652
707
}
653
708
this . setSpellcheckLang ( lang )
654
709
}
@@ -674,17 +729,13 @@ export default class Editor {
674
729
if ( lang === 'disabled' ) {
675
730
spellcheckToggle . removeClass ( 'active' )
676
731
677
- Cookies . set ( 'spellcheck' , false , {
678
- expires : 365
679
- } )
732
+ Storage . set ( 'spellcheck' , 'false' )
680
733
681
734
self . editor . setOption ( 'mode' , defaultEditorMode )
682
735
} else {
683
736
spellcheckToggle . addClass ( 'active' )
684
737
685
- Cookies . set ( 'spellcheck' , lang , {
686
- expires : 365
687
- } )
738
+ Storage . set ( 'spellcheck' , lang )
688
739
689
740
self . editor . setOption ( 'mode' , 'spell-checker' )
690
741
}
@@ -703,12 +754,10 @@ export default class Editor {
703
754
if ( ! gutters . includes ( lintGutter ) ) {
704
755
this . editor . setOption ( 'gutters' , [ lintGutter , ...gutters ] )
705
756
}
706
- Cookies . set ( 'linter' , true , {
707
- expires : 365
708
- } )
757
+ Storage . set ( 'linter' , 'true' )
709
758
} else {
710
759
this . editor . setOption ( 'gutters' , gutters . filter ( g => g !== lintGutter ) )
711
- Cookies . remove ( 'linter' )
760
+ Storage . remove ( 'linter' )
712
761
}
713
762
this . editor . setOption ( 'lint' , enable ? linterOptions : false )
714
763
}
@@ -726,7 +775,7 @@ export default class Editor {
726
775
updateLinterStatus ( ! lintEnable )
727
776
} )
728
777
729
- const enable = ! ! Cookies . get ( 'linter' )
778
+ const enable = Storage . get ( 'linter' ) === 'true'
730
779
this . toggleLinter . bind ( this ) ( enable )
731
780
updateLinterStatus ( enable )
732
781
}
@@ -752,12 +801,10 @@ export default class Editor {
752
801
'.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
753
802
)
754
803
if ( overrideBrowserKeymap . is ( ':checked' ) ) {
755
- Cookies . set ( 'preferences-override-browser-keymap' , true , {
756
- expires : 365
757
- } )
804
+ Storage . set ( 'preferences-override-browser-keymap' , 'true' )
758
805
this . restoreOverrideEditorKeymap ( )
759
806
} else {
760
- Cookies . remove ( 'preferences-override-browser-keymap' )
807
+ Storage . remove ( 'preferences-override-browser-keymap' )
761
808
this . resetEditorKeymapToBrowserKeymap ( )
762
809
}
763
810
}
@@ -766,10 +813,10 @@ export default class Editor {
766
813
var overrideBrowserKeymap = $ (
767
814
'.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
768
815
)
769
- var cookieOverrideBrowserKeymap = Cookies . get (
816
+ var storedOverrideBrowserKeymap = Storage . get (
770
817
'preferences-override-browser-keymap'
771
818
)
772
- if ( cookieOverrideBrowserKeymap && cookieOverrideBrowserKeymap === 'true' ) {
819
+ if ( storedOverrideBrowserKeymap && storedOverrideBrowserKeymap === 'true' ) {
773
820
overrideBrowserKeymap . prop ( 'checked' , true )
774
821
} else {
775
822
overrideBrowserKeymap . prop ( 'checked' , false )
@@ -779,6 +826,39 @@ export default class Editor {
779
826
overrideBrowserKeymap . change ( ( ) => {
780
827
this . setOverrideBrowserKeymap ( )
781
828
} )
829
+
830
+ // Handle table editor shortcuts preference
831
+ var disableTableShortcuts = $ (
832
+ '.ui-preferences-disable-table-shortcuts label > input[type="checkbox"]'
833
+ )
834
+ var storedDisableTableShortcuts = Storage . get (
835
+ 'preferences-disable-table-shortcuts'
836
+ )
837
+ if ( storedDisableTableShortcuts && storedDisableTableShortcuts === 'true' ) {
838
+ disableTableShortcuts . prop ( 'checked' , true )
839
+ } else {
840
+ disableTableShortcuts . prop ( 'checked' , false )
841
+ }
842
+ this . setTableShortcutsPreference ( )
843
+
844
+ disableTableShortcuts . change ( ( ) => {
845
+ this . setTableShortcutsPreference ( )
846
+ } )
847
+ }
848
+
849
+ setTableShortcutsPreference ( ) {
850
+ var disableTableShortcuts = $ (
851
+ '.ui-preferences-disable-table-shortcuts label > input[type="checkbox"]'
852
+ )
853
+ if ( disableTableShortcuts . is ( ':checked' ) ) {
854
+ Storage . set ( 'preferences-disable-table-shortcuts' , 'true' )
855
+ } else {
856
+ Storage . remove ( 'preferences-disable-table-shortcuts' )
857
+ }
858
+ // Notify table editor about the preference change
859
+ if ( this . tableEditor ) {
860
+ this . tableEditor . setShortcutsEnabled ( ! disableTableShortcuts . is ( ':checked' ) )
861
+ }
782
862
}
783
863
784
864
init ( textit ) {
0 commit comments