1+ /* eslint-env browser */
12/* global CodeMirror, $, editor, Cookies */
23import { options , Alignment , FormatType } from '@susisu/mte-kernel'
34import debounce from 'lodash/debounce'
@@ -11,6 +12,39 @@ import CodeMirrorSpellChecker, { supportLanguages, supportLanguageCodes } from '
1112import { initTableEditor } from './table-editor'
1213import { availableThemes } from './constants'
1314
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+
1448/* config section */
1549const isMac = CodeMirror . keyMap . default === CodeMirror . keyMap . macDefault
1650const defaultEditorMode = 'gfm'
@@ -183,6 +217,39 @@ export default class Editor {
183217 CodeMirror . defineMode ( 'markmap' , function ( config , modeConfig ) {
184218 return CodeMirror . overlayMode ( CodeMirror . getMode ( config , 'gfm' ) , ignoreOverlay )
185219 } )
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+ } )
186253 }
187254
188255 on ( event , cb ) {
@@ -423,24 +490,24 @@ export default class Editor {
423490 }
424491
425492 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' ) {
431498 this . editor . setOption ( 'indentWithTabs' , true )
432- if ( cookieTabSize ) {
433- this . editor . setOption ( 'indentUnit' , cookieTabSize )
499+ if ( storedTabSize ) {
500+ this . editor . setOption ( 'indentUnit' , storedTabSize )
434501 }
435- } else if ( cookieIndentType === 'space' ) {
502+ } else if ( storedIndentType === 'space' ) {
436503 this . editor . setOption ( 'indentWithTabs' , false )
437- if ( cookieSpaceUnits ) {
438- this . editor . setOption ( 'indentUnit' , cookieSpaceUnits )
504+ if ( storedSpaceUnits ) {
505+ this . editor . setOption ( 'indentUnit' , storedSpaceUnits )
439506 }
440507 }
441508 }
442- if ( cookieTabSize ) {
443- this . editor . setOption ( 'tabSize' , cookieTabSize )
509+ if ( storedTabSize ) {
510+ this . editor . setOption ( 'tabSize' , storedTabSize )
444511 }
445512
446513 var type = this . statusIndicators . find ( '.indent-type' )
@@ -449,14 +516,10 @@ export default class Editor {
449516
450517 const setType = ( ) => {
451518 if ( this . editor . getOption ( 'indentWithTabs' ) ) {
452- Cookies . set ( 'indent_type' , 'tab' , {
453- expires : 365
454- } )
519+ Storage . set ( 'indent_type' , 'tab' )
455520 type . text ( 'Tab Size:' )
456521 } else {
457- Cookies . set ( 'indent_type' , 'space' , {
458- expires : 365
459- } )
522+ Storage . set ( 'indent_type' , 'space' )
460523 type . text ( 'Spaces:' )
461524 }
462525 }
@@ -465,13 +528,9 @@ export default class Editor {
465528 const setUnit = ( ) => {
466529 var unit = this . editor . getOption ( 'indentUnit' )
467530 if ( this . editor . getOption ( 'indentWithTabs' ) ) {
468- Cookies . set ( 'tab_size' , unit , {
469- expires : 365
470- } )
531+ Storage . set ( 'tab_size' , unit )
471532 } else {
472- Cookies . set ( 'space_units' , unit , {
473- expires : 365
474- } )
533+ Storage . set ( 'space_units' , unit )
475534 }
476535 widthLabel . text ( unit )
477536 }
@@ -480,16 +539,16 @@ export default class Editor {
480539 type . click ( ( ) => {
481540 if ( this . editor . getOption ( 'indentWithTabs' ) ) {
482541 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 )
486545 }
487546 } else {
488547 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 )
493552 }
494553 }
495554 setType ( )
@@ -525,9 +584,9 @@ export default class Editor {
525584 }
526585
527586 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 )
531590 }
532591
533592 var label = this . statusIndicators . find ( '.ui-keymap-label' )
@@ -537,9 +596,7 @@ export default class Editor {
537596
538597 const setKeymapLabel = ( ) => {
539598 var keymap = this . editor . getOption ( 'keyMap' )
540- Cookies . set ( 'keymap' , keymap , {
541- expires : 365
542- } )
599+ Storage . set ( 'keymap' , keymap )
543600 label . text ( keymap )
544601 this . restoreOverrideEditorKeymap ( )
545602 this . setOverrideBrowserKeymap ( )
@@ -572,17 +629,15 @@ export default class Editor {
572629
573630 const setTheme = theme => {
574631 this . editor . setOption ( 'theme' , theme )
575- Cookies . set ( 'theme' , theme , {
576- expires : 365
577- } )
632+ Storage . set ( 'theme' , theme )
578633 this . statusIndicators . find ( '.status-theme li' ) . removeClass ( 'active' )
579634 this . statusIndicators . find ( `.status-theme li[value="${ theme } "]` ) . addClass ( 'active' )
580635 }
581636
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 )
586641 } else {
587642 activateThemeListItem ( this . editor . getOption ( 'theme' ) )
588643 }
@@ -613,10 +668,10 @@ export default class Editor {
613668 }
614669
615670 getExistingSpellcheckLang ( ) {
616- const cookieSpellcheck = Cookies . get ( 'spellcheck' )
671+ const storedSpellcheck = Storage . get ( 'spellcheck' )
617672
618- if ( cookieSpellcheck ) {
619- return cookieSpellcheck === 'false' ? undefined : cookieSpellcheck
673+ if ( storedSpellcheck ) {
674+ return storedSpellcheck === 'false' ? undefined : storedSpellcheck
620675 } else {
621676 return undefined
622677 }
@@ -637,18 +692,18 @@ export default class Editor {
637692 return $ ( `<li value="${ lang . value } "><a>${ lang . name } </a></li>` )
638693 } ) )
639694
640- const cookieSpellcheck = Cookies . get ( 'spellcheck' )
641- if ( cookieSpellcheck ) {
695+ const storedSpellcheck = Storage . get ( 'spellcheck' )
696+ if ( storedSpellcheck ) {
642697 let mode = null
643698 let lang = 'en_US'
644699
645- if ( cookieSpellcheck === 'false' || ! cookieSpellcheck ) {
700+ if ( storedSpellcheck === 'false' || ! storedSpellcheck ) {
646701 mode = defaultEditorMode
647702 this . activateSpellcheckListItem ( false )
648703 } else {
649704 mode = 'spell-checker'
650- if ( supportLanguageCodes . includes ( cookieSpellcheck ) ) {
651- lang = cookieSpellcheck
705+ if ( supportLanguageCodes . includes ( storedSpellcheck ) ) {
706+ lang = storedSpellcheck
652707 }
653708 this . setSpellcheckLang ( lang )
654709 }
@@ -674,17 +729,13 @@ export default class Editor {
674729 if ( lang === 'disabled' ) {
675730 spellcheckToggle . removeClass ( 'active' )
676731
677- Cookies . set ( 'spellcheck' , false , {
678- expires : 365
679- } )
732+ Storage . set ( 'spellcheck' , 'false' )
680733
681734 self . editor . setOption ( 'mode' , defaultEditorMode )
682735 } else {
683736 spellcheckToggle . addClass ( 'active' )
684737
685- Cookies . set ( 'spellcheck' , lang , {
686- expires : 365
687- } )
738+ Storage . set ( 'spellcheck' , lang )
688739
689740 self . editor . setOption ( 'mode' , 'spell-checker' )
690741 }
@@ -703,12 +754,10 @@ export default class Editor {
703754 if ( ! gutters . includes ( lintGutter ) ) {
704755 this . editor . setOption ( 'gutters' , [ lintGutter , ...gutters ] )
705756 }
706- Cookies . set ( 'linter' , true , {
707- expires : 365
708- } )
757+ Storage . set ( 'linter' , 'true' )
709758 } else {
710759 this . editor . setOption ( 'gutters' , gutters . filter ( g => g !== lintGutter ) )
711- Cookies . remove ( 'linter' )
760+ Storage . remove ( 'linter' )
712761 }
713762 this . editor . setOption ( 'lint' , enable ? linterOptions : false )
714763 }
@@ -726,7 +775,7 @@ export default class Editor {
726775 updateLinterStatus ( ! lintEnable )
727776 } )
728777
729- const enable = ! ! Cookies . get ( 'linter' )
778+ const enable = Storage . get ( 'linter' ) === 'true'
730779 this . toggleLinter . bind ( this ) ( enable )
731780 updateLinterStatus ( enable )
732781 }
@@ -752,12 +801,10 @@ export default class Editor {
752801 '.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
753802 )
754803 if ( overrideBrowserKeymap . is ( ':checked' ) ) {
755- Cookies . set ( 'preferences-override-browser-keymap' , true , {
756- expires : 365
757- } )
804+ Storage . set ( 'preferences-override-browser-keymap' , 'true' )
758805 this . restoreOverrideEditorKeymap ( )
759806 } else {
760- Cookies . remove ( 'preferences-override-browser-keymap' )
807+ Storage . remove ( 'preferences-override-browser-keymap' )
761808 this . resetEditorKeymapToBrowserKeymap ( )
762809 }
763810 }
@@ -766,10 +813,10 @@ export default class Editor {
766813 var overrideBrowserKeymap = $ (
767814 '.ui-preferences-override-browser-keymap label > input[type="checkbox"]'
768815 )
769- var cookieOverrideBrowserKeymap = Cookies . get (
816+ var storedOverrideBrowserKeymap = Storage . get (
770817 'preferences-override-browser-keymap'
771818 )
772- if ( cookieOverrideBrowserKeymap && cookieOverrideBrowserKeymap === 'true' ) {
819+ if ( storedOverrideBrowserKeymap && storedOverrideBrowserKeymap === 'true' ) {
773820 overrideBrowserKeymap . prop ( 'checked' , true )
774821 } else {
775822 overrideBrowserKeymap . prop ( 'checked' , false )
@@ -779,6 +826,39 @@ export default class Editor {
779826 overrideBrowserKeymap . change ( ( ) => {
780827 this . setOverrideBrowserKeymap ( )
781828 } )
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+ }
782862 }
783863
784864 init ( textit ) {
0 commit comments