@@ -24,9 +24,12 @@ import 'github-markdown-css/github-markdown.css'
2424import { insertExampleFunc } from "./examples.js" ;
2525
2626import Alpine from 'alpinejs'
27+
28+ // En tu archivo principal (e.g., app.js o index.js)
29+ import { clearFragment , loadFromFragment , createFragmentLink , onFragmentChange } from './fragmentLoader.js' ;
2730
2831window . Alpine = Alpine
29-
32+
3033Alpine . start ( )
3134
3235const md = markdownit ( { html : true } )
@@ -41,6 +44,7 @@ const tabsField = document.getElementById("tabs")
4144const insertButton = document . getElementById ( 'exampleInsert' )
4245const exampleSelect = document . getElementById ( 'exampleSelector' )
4346const outputs = document . getElementById ( "OUTPUT" )
47+ const shareLinkButton = document . getElementById ( "shareLink" )
4448const numberOfSessions = 20
4549const listOfSessions = Array . from ( { length : numberOfSessions } , ( _ , i ) => i + 1 )
4650let workerState = initialState
@@ -50,7 +54,52 @@ let lastTab = localStorage.getItem("lastTab") === null ? 1 : localStorage.getIte
5054
5155let sessions = [ ]
5256let sessionNames = [ ]
57+ let firstEmptySession = findEmptySession ( )
58+ // Phase 1: cleanup, dedupe and compact sessions in localStorage
59+ const seen = new Set ( ) ;
60+ const nonEmptyUnique = [ ] ;
61+
62+ // Gather, remove empties and duplicates
63+ for ( let ID of listOfSessions ) {
64+ const key = getSessionName ( ID ) ;
65+ const text = localStorage . getItem ( key ) ;
66+
67+ if ( text === null ) continue ;
68+
69+ if ( text . trim ( ) === "" ) {
70+ localStorage . removeItem ( key ) ;
71+ continue ;
72+ }
73+
74+ if ( seen . has ( text ) ) {
75+ localStorage . removeItem ( key ) ;
76+ continue ;
77+ }
78+
79+ seen . add ( text ) ;
80+ nonEmptyUnique . push ( { text, ID , isCurrent : ID == lastTab } ) ;
81+ }
82+
83+ // Reassign compacted non-empty sessions to lowest IDs, clear the rest
84+ for ( let idx = 0 ; idx < listOfSessions . length ; idx ++ ) {
85+ const ID = listOfSessions [ idx ] ;
86+ const key = getSessionName ( ID ) ;
87+ if ( idx < nonEmptyUnique . length ) {
88+ if ( nonEmptyUnique [ idx ] . isCurrent ) {
89+ lastTab = idx + 1 ;
90+ }
91+ localStorage . setItem ( key , nonEmptyUnique [ idx ] . text ) ;
92+ } else {
93+ localStorage . removeItem ( key ) ;
94+ }
95+ }
96+
97+ // First empty session is right after the last non-empty one (if any space left)
98+ firstEmptySession = nonEmptyUnique . length < listOfSessions . length
99+ ? listOfSessions [ nonEmptyUnique . length ]
100+ : null ;
53101
102+ // Phase 2: create HTML elements and initialize session arrays
54103for ( let ID of listOfSessions ) {
55104 // Create tabs
56105 const radioInput = document . createElement ( 'input' ) ;
@@ -67,16 +116,8 @@ for (let ID of listOfSessions) {
67116 label . textContent = ID ;
68117 tabsField . appendChild ( label ) ;
69118
70- // Create sessions
71- const thisSession = getSessionName ( ID ) ;
72- const sessionText = localStorage . getItem ( thisSession )
73- sessions [ ID ] = null
74-
75- // Remove empty sessions
76- if ( sessionText && ! sessionText . trim ( ) ) {
77- localStorage . removeItem ( thisSession )
78- }
79-
119+ // Initialize session slots; names after label exists
120+ sessions [ ID ] = null ;
80121 sessionNames [ ID ] = setSessionName ( ID ) ;
81122}
82123
@@ -85,7 +126,16 @@ tabIDs.value = lastTab
85126
86127let timer ;
87128
129+ const codeFromUrl = loadFromFragment ( ) ;
130+ if ( codeFromUrl ) {
131+ lastTab = firstEmptySession !== null ? firstEmptySession : lastTab
132+ localStorage . setItem ( "lastTab" , lastTab )
133+ localStorage . setItem ( getSessionName ( lastTab ) , codeFromUrl )
134+ tabIDs . value = lastTab
135+ clearFragment ( )
136+ }
88137sessions [ lastTab ] = createState ( lastTab )
138+
89139let editor = new EditorView ( {
90140 state : sessions [ lastTab ] ,
91141 parent : document . querySelector ( '#INPUT' )
@@ -104,6 +154,16 @@ tabsField.addEventListener('change', () => {
104154 lastTab = ID
105155} )
106156
157+ shareLinkButton . addEventListener ( 'click' , ( ) => {
158+ const code = editor . state . doc . toString ( ) ;
159+ const shareableLink = createFragmentLink ( code ) ;
160+ navigator . clipboard . writeText ( shareableLink ) . then ( ( ) => {
161+ alert ( 'Shareable link copied to clipboard!' ) ;
162+ } , ( err ) => {
163+ alert ( 'Failed to copy link: ' , err ) ;
164+ } ) ;
165+ } )
166+
107167insertButton . addEventListener ( 'click' , ( ) => {
108168 const exampleToInsert = insertExampleFunc ( exampleSelect . value )
109169 editor . dispatch ( {
@@ -200,7 +260,7 @@ function createState(ID) {
200260 if ( update . docChanged ) {
201261 const text = update . state . doc . toString ( )
202262 clearTimeout ( timer ) ;
203- timer = setTimeout ( sendWorkToMathWorker , wait , text ) ;
263+ timer = setTimeout ( sendWorkToMathWorker , wait , text ) ;
204264 } else if ( update . selectionSet ) {
205265 updateSelection ( )
206266 }
@@ -271,12 +331,34 @@ function saveSession(sessionID) {
271331 }
272332}
273333
274- function sendWorkToMathWorker ( mathExpressoins ) {
275- if ( mathExpressoins != "" ) {
276- const expressions = mathExpressoins
334+ function sendWorkToMathWorker ( mathExpressions ) {
335+ if ( mathExpressions != "" ) {
336+ const expressions = mathExpressions
277337 . replace ( / \r ? \n / g, '\n' )
278338 //.trim()
279339 const request = { expr : expressions }
280340 mathWorker . postMessage ( JSON . stringify ( request ) )
281341 }
282342}
343+
344+
345+ onFragmentChange ( ( code ) => {
346+ firstEmptySession = findEmptySession ( )
347+ lastTab = firstEmptySession !== null ? firstEmptySession : lastTab
348+ localStorage . setItem ( "lastTab" , lastTab )
349+ localStorage . setItem ( getSessionName ( lastTab ) , code )
350+ tabIDs . value = lastTab
351+ editor . setState ( createState ( lastTab ) )
352+ clearFragment ( )
353+ } ) ;
354+
355+ function findEmptySession ( ) {
356+ for ( let ID of listOfSessions ) {
357+ const key = getSessionName ( ID ) ;
358+ const text = localStorage . getItem ( key ) ;
359+ if ( text === null || text . trim ( ) === "" ) {
360+ return ID ;
361+ }
362+ }
363+ return null ;
364+ }
0 commit comments