aboutsummaryrefslogtreecommitdiff
path: root/scripts/theme-studio/previews.js
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/theme-studio/previews.js')
-rw-r--r--scripts/theme-studio/previews.js170
1 files changed, 139 insertions, 31 deletions
diff --git a/scripts/theme-studio/previews.js b/scripts/theme-studio/previews.js
index afba6b0c9..658da3700 100644
--- a/scripts/theme-studio/previews.js
+++ b/scripts/theme-studio/previews.js
@@ -151,14 +151,6 @@ function renderElfeedPreview(){const a='elfeed',L=[];
L.push(os(a,'elfeed-log-date-face','02:24:03')+' '+os(a,'elfeed-log-error-level-face','ERROR')+' failed: bad.example');
L.push(os(a,'elfeed-log-date-face','02:24:04')+' '+os(a,'elfeed-log-debug-level-face','DEBUG')+' parsed 340 entries');
return previewLines(L);}
-function renderGhostelPreview(){const a='ghostel',L=[];
- L.push(os(a,'ghostel-default','craig@host')+' '+os(a,'ghostel-color-green','~/code')+' $ ls'+os(a,'ghostel-fake-cursor',' ')+os(a,'ghostel-fake-cursor-box','[ ]'));
- L.push('');
- L.push(os(a,'ghostel-default','normal:')+' '+os(a,'ghostel-color-black','black')+' '+os(a,'ghostel-color-red','red')+' '+os(a,'ghostel-color-green','green')+' '+os(a,'ghostel-color-yellow','yellow')+' '+os(a,'ghostel-color-blue','blue')+' '+os(a,'ghostel-color-magenta','magenta')+' '+os(a,'ghostel-color-cyan','cyan')+' '+os(a,'ghostel-color-white','white'));
- L.push(os(a,'ghostel-default','bright:')+' '+os(a,'ghostel-color-bright-black','black')+' '+os(a,'ghostel-color-bright-red','red')+' '+os(a,'ghostel-color-bright-green','green')+' '+os(a,'ghostel-color-bright-yellow','yellow')+' '+os(a,'ghostel-color-bright-blue','blue')+' '+os(a,'ghostel-color-bright-magenta','magenta')+' '+os(a,'ghostel-color-bright-cyan','cyan')+' '+os(a,'ghostel-color-bright-white','white'));
- L.push('');
- L.push(os(a,'ghostel-default','default terminal output, 256-color text and a blinking ')+os(a,'ghostel-fake-cursor','cursor')+'.');
- return previewLines(L);}
function renderDashboardPreview(){const a='dashboard',L=[];
L.push(os(a,'dashboard-text-banner',' [ dashboard banner image ]'));
L.push(os(a,'dashboard-banner-logo-title','Emacs: The Editor That Saves Your Soul'));
@@ -293,17 +285,60 @@ function renderGitGutterPreview(){const a='git-gutter',L=[];
L.push(os(a,'git-gutter:deleted','_')+os(a,'git-gutter:separator','|')+' (deleted lines marker)');
L.push(os(a,'git-gutter:unchanged',' ')+os(a,'git-gutter:separator','|')+' '+os(a,'git-gutter:unchanged','unchanged line of code'));
return previewLines(L);}
-function renderEatPreview(){const a='eat',L=[];
- L.push(os(a,'eat-shell-prompt-annotation-success','✔')+' ~/projects $ ls --color');
- L.push(os(a,'eat-term-color-blue','build/')+' '+os(a,'eat-term-color-blue','src/')+' '+os(a,'eat-term-color-green','run.sh')+' README.md');
- L.push('');
- L.push('palette '+os(a,'eat-term-color-black','■')+os(a,'eat-term-color-red','■')+os(a,'eat-term-color-green','■')+os(a,'eat-term-color-yellow','■')+os(a,'eat-term-color-blue','■')+os(a,'eat-term-color-magenta','■')+os(a,'eat-term-color-cyan','■')+os(a,'eat-term-color-white','■')+' normal');
- L.push(' '+os(a,'eat-term-color-bright-black','■')+os(a,'eat-term-color-bright-red','■')+os(a,'eat-term-color-bright-green','■')+os(a,'eat-term-color-bright-yellow','■')+os(a,'eat-term-color-bright-blue','■')+os(a,'eat-term-color-bright-magenta','■')+os(a,'eat-term-color-bright-cyan','■')+os(a,'eat-term-color-bright-white','■')+' bright');
- L.push('');
- L.push(os(a,'eat-term-bold','bold')+' '+os(a,'eat-term-faint','faint')+' '+os(a,'eat-term-italic','italic')+' '+os(a,'eat-term-slow-blink','slow-blink')+' '+os(a,'eat-term-fast-blink','fast-blink'));
- L.push('');
- L.push(os(a,'eat-shell-prompt-annotation-running','…')+' running tests');
- L.push(os(a,'eat-shell-prompt-annotation-failure','✘')+' build failed');
+function renderEatPreview(){const a='eat',L=[],c=(f,t)=>os(a,'eat-term-color-'+f,t),x=(f,t)=>os(a,'eat-term-'+f,t),an=(g,t)=>os(a,'eat-shell-prompt-annotation-'+g,t);
+ const p=g=>an(g,g==='success'?'✔':g==='failure'?'✘':'…')+' ~/projects/app $ ';
+ // 1. directory listing -- the widest palette block (dircolors)
+ L.push(p('success')+'eza -la --color');
+ L.push('drwxr-xr-x - 14:02 '+c('blue','.git/'));
+ L.push('.rw-r--r-- 120 09:11 .gitignore');
+ L.push('drwxr-xr-x - 14:02 '+c('blue','src/'));
+ L.push('drwxr-xr-x - 13:48 '+c('blue','tests/'));
+ L.push('.rwxr-xr-x 2.1k 14:00 '+c('bright-green','run.sh'));
+ L.push('lrwxr-xr-x - 14:01 '+c('cyan','latest')+' -> '+c('blue','v2.1/'));
+ L.push('.rw-r--r-- 4.5M 22:30 '+c('red','backup.tar.gz'));
+ L.push('.rw-r--r-- 88k 18:05 '+c('magenta','logo.png'));
+ L.push('.rw-r--r-- 3.2k 14:02 README.md');
+ L.push('');
+ // 2. git status -- staged green, unstaged/untracked red
+ L.push(p('success')+'git status -sb');
+ L.push(c('bright-cyan','## main...origin/main [ahead 2]'));
+ L.push(c('green','A src/eat-preview.js'));
+ L.push(c('green','A src/cache.el'));
+ L.push(c('green','M README.md'));
+ L.push(c('red',' M init.el'));
+ L.push(c('red',' M modules/term-config.el'));
+ L.push(c('red',' D modules/old-vterm.el'));
+ L.push(c('red','?? docs/design/eat.org'));
+ L.push(c('red','?? scratch.txt'));
+ L.push('');
+ // 3. git log --decorate -- yellow hashes, colored refs, a merge
+ L.push(p('success')+'git log --oneline --graph --decorate');
+ L.push(c('bright-black','* ')+c('yellow','a1b2c3d')+' '+c('bright-cyan','(HEAD -> ')+c('bright-green','main')+c('bright-cyan',')')+' richer eat preview blocks');
+ L.push(c('bright-black','* ')+c('yellow','9f8e7d6')+' '+c('bright-yellow','(tag: v2.1, ')+c('bright-red','origin/main')+c('bright-yellow',')')+' lowercase the labels');
+ L.push(c('bright-black','* ')+c('yellow','3c4d5e6')+' Merge branch '+c('green',"'eat-faces'"));
+ L.push(c('bright-black','|\\ '));
+ L.push(c('bright-black','| * ')+c('yellow','7a8b9c0')+' expose eat faces to studio');
+ L.push(c('bright-black','| * ')+c('yellow','1d2e3f4')+' add eat-term-color docstrings');
+ L.push(c('bright-black','|/ '));
+ L.push(c('bright-black','* ')+c('yellow','5f6a7b8')+' default video player to mpv');
+ L.push(c('bright-black','* ')+c('yellow','2c3d4e5')+' calendar-sync robustness fixes');
+ L.push('');
+ // 4. test run -- pass green, skip yellow, fail red, bold summary, faint detail
+ L.push(p('failure')+'make test');
+ L.push(c('green','✔ PASS')+' term-toggle '+x('faint','(19 tests)'));
+ L.push(c('green','✔ PASS')+' ai-term '+x('faint','(158 tests)'));
+ L.push(c('green','✔ PASS')+' calendar-sync '+x('faint','(575 tests)'));
+ L.push(c('green','✔ PASS')+' dashboard '+x('faint','(18 tests)'));
+ L.push(c('yellow','⚠ SKIP')+' network-sync '+x('faint','(2 tests, offline)'));
+ L.push(c('green','✔ PASS')+' transcription '+x('faint','(44 tests)'));
+ L.push(c('red','✘ FAIL')+' org-roam-refile '+x('faint','(1 test)'));
+ L.push(' '+x('italic','expected 3 refile targets, got 0'));
+ L.push(x('bold','Ran 817 tests, 815 passed, ')+c('yellow','1 skipped, ')+c('red','1 failed')+' '+x('faint','0.84s'));
+ L.push('');
+ // swatch reference key, below the realistic blocks
+ L.push(x('faint','palette')+' '+c('black','■')+c('red','■')+c('green','■')+c('yellow','■')+c('blue','■')+c('magenta','■')+c('cyan','■')+c('white','■')+' '+c('bright-black','■')+c('bright-red','■')+c('bright-green','■')+c('bright-yellow','■')+c('bright-blue','■')+c('bright-magenta','■')+c('bright-cyan','■')+c('bright-white','■'));
+ L.push(x('faint','attrs')+' '+x('bold','bold')+' '+x('faint','faint')+' '+x('italic','italic')+' '+x('slow-blink','slow-blink')+' '+x('fast-blink','fast-blink'));
+ L.push(x('faint','prompt')+' '+an('success','✔ ok')+' '+an('running','… running')+' '+an('failure','✘ failed'));
return previewLines(L);}
function renderFlycheckPreview(){const a='flycheck',L=[];
L.push(os(a,'flycheck-fringe-error','E')+os(a,'flycheck-fringe-warning','W')+os(a,'flycheck-fringe-info','I')+' x = '+os(a,'flycheck-error','undefined_name')+'('+os(a,'flycheck-warning','unused_arg')+') '+os(a,'flycheck-info','# note'));
@@ -327,18 +362,59 @@ function renderDiredPreview(){const a='dired',L=[];
L.push(' '+os(a,'dired-special','prw-r--r--')+' craig 0 fifo.pipe');
L.push(os(a,'dired-warning','! disk space low on /home'));
return previewLines(L);}
-function renderDirvishPreview(){const a='dirvish',L=[];
- L.push(os(a,'dirvish-inactive','~/code')+' '+os(a,'dirvish-free-space','[free 24G]'));
- L.push(os(a,'dirvish-hl-line',' '+os(a,'dirvish-file-modes','-rw-r--r--')+' '+os(a,'dirvish-file-link-number','1')+' '+os(a,'dirvish-file-user-id','craig')+' '+os(a,'dirvish-file-group-id','staff')+' '+os(a,'dirvish-file-size','4.0K')+' '+os(a,'dirvish-file-time','Jun 8 02:24')+' init.el '));
- L.push(' '+os(a,'dirvish-file-modes','drwxr-xr-x')+' '+os(a,'dirvish-file-link-number','5')+' '+os(a,'dirvish-file-user-id','craig')+' '+os(a,'dirvish-file-group-id','staff')+' '+os(a,'dirvish-file-size',' - ')+' '+os(a,'dirvish-file-time','Jun 7 18:00')+' '+os(a,'dirvish-collapse-dir-face','src')+os(a,'dirvish-subtree-state','+')+os(a,'dirvish-subtree-guide',' |'));
- L.push(os(a,'dirvish-hl-line-inactive',' inactive-window current line '));
- L.push(' inode '+os(a,'dirvish-file-inode-number','1048576')+' dev '+os(a,'dirvish-file-device-number','8,1')+' '+os(a,'dirvish-collapse-empty-dir-face','empty/')+' '+os(a,'dirvish-collapse-file-face','file.txt'));
- L.push(' VC '+os(a,'dirvish-vc-added-state','A')+os(a,'dirvish-vc-edited-state','M')+os(a,'dirvish-vc-removed-state','D')+os(a,'dirvish-vc-conflict-state','C')+os(a,'dirvish-vc-locked-state','L')+os(a,'dirvish-vc-missing-state','!')+os(a,'dirvish-vc-needs-merge-face','m')+os(a,'dirvish-vc-needs-update-state','u')+os(a,'dirvish-vc-unregistered-face','?'));
- L.push(' git '+os(a,'dirvish-git-commit-message-face','feat: enlarge the picker'));
- L.push(' '+os(a,'dirvish-media-info-heading','Media')+' '+os(a,'dirvish-media-info-property-key','Dimensions:')+' 1920x1080');
- L.push(' proc '+os(a,'dirvish-proc-running','running')+' / '+os(a,'dirvish-proc-finished','finished')+' / '+os(a,'dirvish-proc-failed','failed'));
- L.push(' narrow '+os(a,'dirvish-narrow-match-face-0','m0')+' '+os(a,'dirvish-narrow-match-face-1','m1')+' '+os(a,'dirvish-narrow-match-face-2','m2')+' '+os(a,'dirvish-narrow-match-face-3','m3')+os(a,'dirvish-narrow-split',' | ')+os(a,'dirvish-emerge-group-title','Group: images'));
- return previewLines(L);}
+// A believable two-pane dirvish: an active directory listing on the left
+// (nerd-icon per file type, dir-entry counts / file sizes, the hl-line on the
+// selected row, a dimmed backup) and the selected dir's ls-l preview on the
+// right. Faces that don't fit a calm listing (vc, git, subtree, media, proc,
+// narrow, emerge) live in a labeled extras strip below so theme coverage stays
+// complete. Glyphs/colors mirror what nerd-icons actually emits per type.
+function renderDirvishPreview(){
+ const D='dirvish', N='nerd-icons', DR='dired';
+ // foreground-only span, so a row background (the hl-line) shows through it
+ const fg=(app,face,t)=>`<span style="color:${effFg(pkgEffFg(app,face))}">${t}</span>`;
+ const ic=(face,g)=>os(N,face,g);
+ const pad=(name,w)=>esc(name)+' '.repeat(Math.max(1,w-name.length));
+ const HL=pkgEffBg(D,'dirvish-hl-line')||MAP['bg'];
+
+ // ---- left pane: the active directory ----
+ const left=[os(DR,'dired-header','~/code/emacs-wttrin:')];
+ for(const [name,cnt,sel] of [['assets','4',true],['examples','1'],['githooks','1'],
+ ['inbox','3'],['scripts','1'],['tests','71']]){
+ if(sel) left.push(`<span style="background:${HL}">`+fg(N,'nerd-icons-yellow','')+' '
+ +fg(DR,'dired-directory',pad(name,21))+fg(D,'dirvish-file-size',cnt)+`</span>`);
+ else left.push(ic('nerd-icons-yellow','')+' '+os(DR,'dired-directory',pad(name,21))
+ +os(D,'dirvish-file-size',cnt));
+ }
+ for(const [face,g,name,size] of [['nerd-icons-lblue','','CLAUDE.md','4.9k'],
+ ['nerd-icons-blue','','Eask','518'],['nerd-icons-blue','','LICENSE','34k'],
+ ['nerd-icons-dorange','','Makefile','12k'],['nerd-icons-lcyan','','README.org','24k'],
+ ['nerd-icons-lgreen','','todo.org','23k'],['nerd-icons-purple','','wttrin.el','69k'],
+ ['nerd-icons-dsilver','','wttrin.elc','4.3k']])
+ left.push(ic(face,g)+' '+pad(name,21)+os(D,'dirvish-file-size',size));
+ left.push(ic('nerd-icons-lgreen','')+' '+os(DR,'dired-ignored',pad('todo.org~',21))
+ +os(D,'dirvish-file-size','8.8k'));
+
+ // ---- right pane: ls -l preview of the selected dir ----
+ const ll=(size,time,name)=>os(D,'dirvish-file-modes','-rw-r--r--')+' '
+ +os(D,'dirvish-file-link-number','1')+' '+os(D,'dirvish-file-user-id','cjennings')+' '
+ +os(D,'dirvish-file-group-id','cjennings')+' '+os(D,'dirvish-file-size',size)+' '
+ +os(D,'dirvish-file-time',time)+' '+ic('nerd-icons-orange','\u{F0E2D}')+' '+esc(name);
+ const right=[os(DR,'dired-header','assets:'),
+ ll('54K','Jun 26 10:53','geolocation.png'),ll('52K','Jun 26 10:53','location-menu.png'),
+ ll('3.1K','Apr 10 12:03','made-for-emacs.svg'),ll('346K','Jun 26 10:53','wttrin.png')];
+
+ // ---- extras: remaining dirvish faces, kept for theme coverage ----
+ const ex=[
+ os(D,'dirvish-inactive','inactive pane')+' '+os(D,'dirvish-hl-line-inactive',' inactive current line ')+' '+os(D,'dirvish-free-space','[free 24G]'),
+ 'vc '+os(D,'dirvish-vc-added-state','A')+os(D,'dirvish-vc-edited-state','M')+os(D,'dirvish-vc-removed-state','D')+os(D,'dirvish-vc-conflict-state','C')+os(D,'dirvish-vc-locked-state','L')+os(D,'dirvish-vc-missing-state','!')+os(D,'dirvish-vc-needs-merge-face','m')+os(D,'dirvish-vc-needs-update-state','u')+os(D,'dirvish-vc-unregistered-face','?')+' git '+os(D,'dirvish-git-commit-message-face','feat: enlarge the picker'),
+ 'subtree '+os(D,'dirvish-collapse-dir-face','src')+os(D,'dirvish-subtree-state','+')+os(D,'dirvish-subtree-guide',' | ')+os(D,'dirvish-collapse-empty-dir-face','empty/')+' '+os(D,'dirvish-collapse-file-face','file.txt')+' inode '+os(D,'dirvish-file-inode-number','1048576')+' dev '+os(D,'dirvish-file-device-number','8,1'),
+ 'media '+os(D,'dirvish-media-info-heading','Media')+' '+os(D,'dirvish-media-info-property-key','Dimensions:')+' 1920x1080 proc '+os(D,'dirvish-proc-running','running')+'/'+os(D,'dirvish-proc-finished','finished')+'/'+os(D,'dirvish-proc-failed','failed'),
+ 'narrow '+os(D,'dirvish-narrow-match-face-0','m0')+' '+os(D,'dirvish-narrow-match-face-1','m1')+' '+os(D,'dirvish-narrow-match-face-2','m2')+' '+os(D,'dirvish-narrow-match-face-3','m3')+os(D,'dirvish-narrow-split',' | ')+os(D,'dirvish-emerge-group-title','Group: images')];
+
+ const col=(lines)=>`<div style="white-space:pre">${lines.join('\n')}</div>`;
+ return `<div style="padding:12px 16px;font:12pt/1.7 ${PREVIEW_FONT}">`
+ +`<div style="display:flex;gap:2.5em">${col(left)}${col(right)}</div>`
+ +`<div style="margin-top:1.2em;opacity:0.9">${col(ex)}</div></div>`;}
function renderCalibredbPreview(){const a='calibredb',L=[];
L.push(os(a,'calibredb-search-header-library-name-face','Calibre')+' '+os(a,'calibredb-search-header-library-path-face','~/books')+' '+os(a,'calibredb-search-header-total-face','412 books')+' '+os(a,'calibredb-search-header-filter-face','tag:scifi')+' '+os(a,'calibredb-search-header-sort-face','sort:date')+' '+os(a,'calibredb-search-header-highlight-face','[*]'));
L.push('');
@@ -392,6 +468,38 @@ function renderShrPreview(){const a='shr',L=[];
L.push(os(a,'shr-text','some ')+os(a,'shr-code','inline_code()')+os(a,'shr-text',', a ')+os(a,'shr-mark','highlighted mark')+os(a,'shr-text',', ')+os(a,'shr-strike-through','struck out')+os(a,'shr-text',', a footnote')+os(a,'shr-sup','[1]')+os(a,'shr-text',','));
L.push(os(a,'shr-text','an ')+os(a,'shr-abbreviation','HTML')+os(a,'shr-text',' abbreviation, and an ')+os(a,'shr-sliced-image','[image]')+os(a,'shr-text',' slice.'));
return previewLines(L);}
+// nov-reading: a realistic book page per palette, not the line-based format.
+// Each palette face supplies the page bg+fg (via ofs); the serif typography and
+// hierarchy are CSS so the preview reads like an actual novel page. Tuning a
+// palette face repaints its page. data-owner-app/-face keep face-locate working.
+function novReadingPage(a,face,label){
+ const cls=isLocateOnPane(a,curApp())?' class="locate-onpane"':'';
+ const title=attresc(formatLocateTitle(locateFaceMeta(a,face,LOCATE_REG)));
+ const page=ofs(a,face)+";width:34em;max-width:100%;border-radius:6px;box-shadow:0 1px 8px #0007;padding:24px 30px 18px;font:13pt/1.62 Georgia,'Times New Roman',serif";
+ // Structural faces recolor the title (heading) and an inline link, derived by
+ // suffix from the palette face so tuning them in the studio repaints the page.
+ const hface=face+'-heading',lface=face+'-link';
+ const htitle=attresc(formatLocateTitle(locateFaceMeta(a,hface,LOCATE_REG)));
+ const hfg=effFg(pkgEffFg(a,hface));
+ return `<div data-owner-app="${a}" data-face="${face}"${cls} title="${title}" style="${page}">`
+ +`<div style="text-align:center;font-variant:small-caps;letter-spacing:.08em;font-size:10pt;opacity:.72;margin-bottom:3px">Nathaniel Hawthorne &middot; Twice-Told Tales</div>`
+ +`<div data-owner-app="${a}" data-face="${hface}"${cls} title="${htitle}" style="text-align:center;font:italic 600 16pt/1.3 Georgia,serif;margin:.15em 0 1em;color:${hfg}">Dr. Heidegger&rsquo;s Experiment</div>`
+ +`<p style="margin:0 0 .75em">`
+ +`<span style="float:left;font:600 320%/.74 Georgia,serif;padding:6px 8px 0 0">T</span>`
+ +`hat very singular man, old Dr. Heidegger, once invited four venerable friends to meet him in his study. There were three white-bearded gentlemen, Mr. Medbourne, Colonel Killigrew, and Mr. Gascoigne, and a withered gentlewoman whose name was the Widow Wycherly.</p>`
+ +`<p style="margin:0 0 .75em;text-indent:1.4em">They were all melancholy old creatures, who had been unfortunate in life. <em>If the powder be genuine,</em> said the doctor, `+os(a,lface,'the rose of half a century')+` should bloom again.</p>`
+ +`<div style="text-align:center;font-size:9.5pt;opacity:.6;margin-top:.7em">${esc(label)} &middot; 12</div>`
+ +`</div>`;}
+function renderNovReadingPreview(){
+ const a='nov-reading',faces=(APPS[a]&&APPS[a].faces)||[];
+ if(!faces.length)return genericPreview(a);
+ // One book page per base palette (the bg/fg faces); the per-palette heading
+ // and link faces color the title and inline link within each page rather than
+ // getting a page of their own.
+ const base=faces.filter(r=>!/-heading$|-link$/.test(r[0]));
+ let h='<div style="padding:14px 16px;display:flex;flex-direction:column;gap:18px;align-items:center">';
+ for(const row of base)h+=novReadingPage(a,row[0],row[1]);
+ return h+'</div>';}
function renderSlackPreview(){const a='slack',L=[];
L.push(os(a,'slack-room-info-title-room-name-face','#general')+' '+os(a,'slack-room-info-title-face','Acme Workspace'));
L.push(os(a,'slack-room-info-section-title-face','Topic')+' '+os(a,'slack-room-info-section-label-face','daily standup')+' '+os(a,'slack-room-unread-face','3 unread'));