Spaces:
Running on Zero
Running on Zero
Download studio.js from fishaudio/Drama-3: direct link, hf CLI and curl.
- Browser
- Download file 3.66 kB
-
https://huggingface.co/spaces/fishaudio/Drama-3/resolve/main/studio.js
- Command line
-
hf download hf://spaces/fishaudio/Drama-3/studio.js
-
curl -L -o studio.js https://huggingface.co/spaces/fishaudio/Drama-3/resolve/main/studio.js
3.66 kB
| () => { | |
| const applyTheme = dark => { | |
| document.body.classList.toggle('dark', dark); | |
| const frame = document.querySelector('iframe[title="Drama 3 Workflow"]'); | |
| try { frame?.contentDocument?.body.classList.toggle('dark', dark); } catch {} | |
| }; | |
| try { const saved = localStorage.getItem('drama3:theme'); if (saved) applyTheme(saved === 'dark'); } catch {} | |
| window.dramaToggleTheme = () => { | |
| const dark = !document.body.classList.contains('dark'); | |
| applyTheme(dark); | |
| try { localStorage.setItem('drama3:theme', dark ? 'dark' : 'light'); } catch {} | |
| }; | |
| window.dramaInsert = (text, tag, kind) => { | |
| const field = document.querySelector('#script textarea'); | |
| const start = field?.selectionStart ?? text.length; | |
| const end = field?.selectionEnd ?? start; | |
| const selected = text.slice(start, end); | |
| let snippet = kind === 'scope' ? `<${tag}>${selected || 'your words here'}</${tag}>` : `[${tag}]`; | |
| if (kind === 'mood') return snippet + ' ' + text.replace(/^\[[^\]]+\]\s*/, ''); | |
| const before = text.slice(0, start), after = text.slice(end); | |
| return before + (before && !/\s$/.test(before) ? ' ' : '') + snippet + | |
| (after && !/^\s/.test(after) ? ' ' : '') + after; | |
| }; | |
| const escape = text => text.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); | |
| const highlight = text => { | |
| let result = escape(text); | |
| result = result.replace(/(^|\n)(Direction:|Line:)/g, '$1<span class="h-note">$2</span>'); | |
| result = result.replace(/<(\/?[A-Za-z][\w-]*)>/g, '<span class="h-tag"><$1></span>'); | |
| return result.replace(/\[([^\[\]\n]*)\]/g, (match, inner) => | |
| `<span class="${inner.trim().split(/\s+/).length >= 3 || inner === 'icy calm' ? 'h-style' : 'h-point'}">${match}</span>`); | |
| }; | |
| const installMirror = () => { | |
| const field = document.querySelector('#script textarea'); | |
| if (!field || field.dataset.dramaMirror) return; | |
| field.dataset.dramaMirror = 'true'; | |
| const wrapper = field.parentElement; | |
| const mirror = document.createElement('div'); | |
| mirror.className = 'drama-script-mirror'; mirror.setAttribute('aria-hidden', 'true'); | |
| wrapper.style.position = 'relative'; wrapper.append(mirror); | |
| field.classList.add('drama-highlighted'); | |
| const render = () => { | |
| const style = getComputedStyle(field); | |
| Object.assign(mirror.style, {left:field.offsetLeft+'px',top:field.offsetTop+'px',width:field.offsetWidth+'px',height:field.offsetHeight+'px', | |
| fontFamily:style.fontFamily,fontSize:style.fontSize,fontWeight:style.fontWeight,lineHeight:style.lineHeight,letterSpacing:style.letterSpacing, | |
| padding:style.padding,border:style.borderWidth+' solid transparent',borderRadius:style.borderRadius}); | |
| mirror.innerHTML = highlight(field.value) + '\n\u200b'; mirror.scrollTop = field.scrollTop; | |
| }; | |
| field.addEventListener('input', render); field.addEventListener('scroll', render); | |
| new ResizeObserver(render).observe(field); | |
| // Gradio can replace the textbox value without firing a DOM input event. | |
| let previous = field.value; | |
| const tick = setInterval(() => { | |
| if (!field.isConnected) { clearInterval(tick); return; } | |
| if (previous !== field.value) { previous = field.value; render(); } | |
| }, 100); | |
| render(); | |
| }; | |
| new MutationObserver(installMirror).observe(document.body, {childList:true,subtree:true}); | |
| installMirror(); | |
| document.addEventListener('keydown', event => { | |
| if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') { | |
| event.preventDefault(); document.querySelector(event.target.closest('#stage-note') ? '#retake' : '#perform')?.click(); | |
| } | |
| }); | |
| } | |