k-l-lambda commited on
Commit
e5a3bec
·
1 Parent(s): 43d70fc

added live-editor link.

Browse files
app.py CHANGED
@@ -350,6 +350,11 @@ def build_head ():
350
  # the mount/bridge script that wires it to the hidden #ls-editor-state textbox.
351
  os.path.join(vendor, 'lyl-editor.bundle.js'),
352
  os.path.join(WEB_DIR, 'lyl-editor-mount.js'),
 
 
 
 
 
353
  # computes --ls-fill-h so the bottom Score List | editor row fills the height
354
  # left under Compose + Logs (robust against Gradio's flex-nesting quirks).
355
  os.path.join(WEB_DIR, 'layout-fit.js'),
@@ -510,13 +515,62 @@ function () {
510
  }
511
  '''
512
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
513
  # Render the editor text to SVG. The text is passed in by Gradio as the event's
514
  # input value (the hidden #ls-editor-state textbox, kept in sync with the embedded
515
  # CodeMirror editor) — taking the value as an argument gives the full text directly,
516
- # no DOM scraping needed.
 
517
  _JS_RENDER = '''
518
  function (text) {
519
  if (window.LilyScore) window.LilyScore.render(text || '');
 
 
 
 
520
  return [];
521
  }
522
  '''
@@ -747,12 +801,19 @@ def build_ui ():
747
  with gr.Column(scale=5, elem_id='editor-col'):
748
  with gr.Group():
749
  gr.Markdown('## Lilylet editor')
750
- # Share button: copies the current deep-link URL (#score=<file>)
751
- # to the clipboard. js-only handler (_JS_SHARE) — see its comment
752
- # for the iframe URL/clipboard caveats. A transient hint span next
753
- # to it shows the copy result.
754
- share_btn = gr.Button('🔗 Share link', elem_id='ls-share-btn',
755
- size='sm', scale=0, min_width=110)
 
 
 
 
 
 
 
756
  # Our own CodeMirror 6 editor (lyl-editor.bundle.js) mounts into
757
  # this div and bridges to the hidden textbox below — Gradio's
758
  # gr.Code can't be syntax-highlighted (its CM is sealed), so we
@@ -813,6 +874,8 @@ def build_ui ():
813
  # Share: copy the current deep-link URL (the #score hash kept current by the
814
  # select listener above) to the clipboard. js-only — see _JS_SHARE.
815
  share_btn.click(None, inputs=None, outputs=None, js=_JS_SHARE)
 
 
816
 
817
  return demo
818
 
 
350
  # the mount/bridge script that wires it to the hidden #ls-editor-state textbox.
351
  os.path.join(vendor, 'lyl-editor.bundle.js'),
352
  os.path.join(WEB_DIR, 'lyl-editor-mount.js'),
353
+ # pako (deflate) + js-base64: used by the "Open in live-editor" share link to
354
+ # compress+url-safe-base64 the editor text into a ?code= param, matching
355
+ # lilylet-live-editor's share.ts encoding exactly. Expose window.pako/Base64.
356
+ os.path.join(vendor, 'pako_deflate.min.js'),
357
+ os.path.join(vendor, 'js-base64.js'),
358
  # computes --ls-fill-h so the bottom Score List | editor row fills the height
359
  # left under Compose + Logs (robust against Gradio's flex-nesting quirks).
360
  os.path.join(WEB_DIR, 'layout-fit.js'),
 
515
  }
516
  '''
517
 
518
+ # Open the current editor text in lilylet-live-editor. We compress the text exactly
519
+ # as the editor's share.ts does — JSON.stringify({code}) -> pako.deflate(level 9) ->
520
+ # URL-safe base64 — and put it in ?code=<...>, then open the deployed editor in a new
521
+ # tab. window.pako / window.Base64 come from the vendored UMD bundles (build_head).
522
+ # Reads the text from the hidden #ls-editor-state <textarea> (the canonical editor
523
+ # value). No-op with a hint if empty or the libs failed to load.
524
+ _LIVE_EDITOR_URL = 'https://k-l-lambda.github.io/lilylet-live-editor/'
525
+ _JS_LIVE_EDITOR = '''
526
+ function () {
527
+ const flash = (msg, ok) => {
528
+ const btn = document.getElementById('ls-live-btn');
529
+ if (!btn) return;
530
+ let hint = document.getElementById('ls-share-hint');
531
+ if (!hint) {
532
+ hint = document.createElement('span');
533
+ hint.id = 'ls-share-hint';
534
+ hint.className = 'ls-share-hint';
535
+ const sb = document.getElementById('ls-share-btn');
536
+ (sb || btn).insertAdjacentElement('afterend', hint);
537
+ }
538
+ hint.textContent = msg;
539
+ hint.classList.toggle('ls-share-err', !ok);
540
+ hint.classList.add('show');
541
+ clearTimeout(hint._t);
542
+ hint._t = setTimeout(() => hint.classList.remove('show'), 2200);
543
+ };
544
+ try {
545
+ const ta = document.querySelector('#ls-editor-state textarea');
546
+ const code = ta && ta.value;
547
+ if (!code || !code.trim()) { flash('Editor is empty', false); return []; }
548
+ if (!window.pako || !window.Base64) { flash('Encoder not loaded', false); return []; }
549
+ const json = JSON.stringify({ code: code });
550
+ const compressed = window.pako.deflate(json, { level: 9 });
551
+ const encoded = window.Base64.fromUint8Array(compressed, true); // URL-safe
552
+ const url = '%s' + '?code=' + encoded;
553
+ window.open(url, '_blank', 'noopener');
554
+ } catch (e) {
555
+ flash('Could not build link', false);
556
+ }
557
+ return [];
558
+ }
559
+ ''' % _LIVE_EDITOR_URL
560
+
561
+
562
  # Render the editor text to SVG. The text is passed in by Gradio as the event's
563
  # input value (the hidden #ls-editor-state textbox, kept in sync with the embedded
564
  # CodeMirror editor) — taking the value as an argument gives the full text directly,
565
+ # no DOM scraping needed. Also toggles the "Open in live-editor" button: shown only
566
+ # when the editor has non-empty text (the link needs content to encode).
567
  _JS_RENDER = '''
568
  function (text) {
569
  if (window.LilyScore) window.LilyScore.render(text || '');
570
+ try {
571
+ const live = document.getElementById('ls-live-btn');
572
+ if (live) live.classList.toggle('ls-hidden', !(text && text.trim()));
573
+ } catch (e) {}
574
  return [];
575
  }
576
  '''
 
801
  with gr.Column(scale=5, elem_id='editor-col'):
802
  with gr.Group():
803
  gr.Markdown('## Lilylet editor')
804
+ with gr.Row(elem_id='ls-editor-actions'):
805
+ # Share button: copies the current deep-link URL (#score=<file>)
806
+ # to the clipboard. js-only handler (_JS_SHARE) see its comment
807
+ # for the iframe URL/clipboard caveats. A transient hint span next
808
+ # to it shows the copy result.
809
+ share_btn = gr.Button('🔗 Share link', elem_id='ls-share-btn',
810
+ size='sm', scale=0, min_width=110)
811
+ # Open the current editor text in lilylet-live-editor: builds a
812
+ # ?code=<pako+base64> URL (matching the editor's share.ts) and
813
+ # opens it in a new tab. Hidden via CSS until the editor has text
814
+ # (toggled by _JS_RENDER, which receives the full text each change).
815
+ live_btn = gr.Button('🎹 Open in live-editor', elem_id='ls-live-btn',
816
+ size='sm', scale=0, min_width=150, elem_classes=['ls-hidden'])
817
  # Our own CodeMirror 6 editor (lyl-editor.bundle.js) mounts into
818
  # this div and bridges to the hidden textbox below — Gradio's
819
  # gr.Code can't be syntax-highlighted (its CM is sealed), so we
 
874
  # Share: copy the current deep-link URL (the #score hash kept current by the
875
  # select listener above) to the clipboard. js-only — see _JS_SHARE.
876
  share_btn.click(None, inputs=None, outputs=None, js=_JS_SHARE)
877
+ # Open in live-editor: encode the editor text into a ?code= URL and open it.
878
+ live_btn.click(None, inputs=None, outputs=None, js=_JS_LIVE_EDITOR)
879
 
880
  return demo
881
 
web/lyl-editor.css CHANGED
@@ -31,18 +31,28 @@
31
  outline: none;
32
  }
33
 
34
- /* Share button: a compact, unobtrusive button under the "Lilylet editor" title. */
35
- #ls-share-btn {
 
 
 
 
 
 
 
 
 
36
  flex: 0 0 auto;
37
  width: auto;
38
  min-width: 0;
39
- align-self: flex-start;
40
- margin: 0 0 6px 2px;
41
  font-size: 12px;
42
  padding: 3px 10px;
43
  }
44
 
45
- /* Transient "Link copied!" hint shown beside the share button. Fades in on .show. */
 
 
 
46
  .ls-share-hint {
47
  display: inline-block;
48
  margin-left: 8px;
 
31
  outline: none;
32
  }
33
 
34
+ /* Editor action buttons row (Share link + Open in live-editor) under the title. */
35
+ #ls-editor-actions {
36
+ flex: 0 0 auto;
37
+ gap: 6px;
38
+ align-items: center;
39
+ margin: 0 0 6px 2px;
40
+ }
41
+
42
+ /* Share / live-editor buttons: compact and unobtrusive. */
43
+ #ls-share-btn,
44
+ #ls-live-btn {
45
  flex: 0 0 auto;
46
  width: auto;
47
  min-width: 0;
 
 
48
  font-size: 12px;
49
  padding: 3px 10px;
50
  }
51
 
52
+ /* "Open in live-editor" is hidden until the editor has content (toggled in JS). */
53
+ #ls-live-btn.ls-hidden { display: none !important; }
54
+
55
+ /* Transient "Link copied!" hint shown beside the buttons. Fades in on .show. */
56
  .ls-share-hint {
57
  display: inline-block;
58
  margin-left: 8px;
web/vendor/js-base64.js ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:cc4803fc4f373cbbeecac84bad8ccfefe791062191a6675141f7df870652989f
3
+ size 13006
web/vendor/pako_deflate.min.js ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9429785d1e7f805d46640c4155957fd0f286144dec05cea09f6f2eaa646adb21
3
+ size 27876