@arshdelight/practi 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/web-default/detail.js +193 -14
- package/web-default/lang.js +2 -2
- package/web-default/style.css +24 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arshdelight/practi",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Local registry CLI for POP (Protocol of Practice): manage a personal, content-addressed collection of practice documents on top of @arshdelight/pop-sdk. Syncs to PractiHub.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/web-default/detail.js
CHANGED
|
@@ -83,8 +83,9 @@ function render() {
|
|
|
83
83
|
var node = walk(path);
|
|
84
84
|
// 三视图:向导正文 / StandardView JSON / document JSON——侧栏大纲始终是导航脊柱,
|
|
85
85
|
// 底部 Prev/Next 也常驻(在 JSON 视图里换节点=高亮跟着走)
|
|
86
|
-
app.innerHTML = topbarHtml() + (view === 'wizard' ? nodeHtml(node) : jsonSectionHtml()) + navHtml();
|
|
86
|
+
app.innerHTML = topbarHtml(node) + (view === 'wizard' ? nodeHtml(node) : jsonSectionHtml()) + navHtml();
|
|
87
87
|
enhanceCodeBlocks(app);
|
|
88
|
+
enhanceMedia(app);
|
|
88
89
|
updateTabs();
|
|
89
90
|
markSide();
|
|
90
91
|
renderNoteSide(); // 右栏跟人走:每次导航换节点都重渲染(草稿保真在 renderNoteSide 内部处理)
|
|
@@ -297,7 +298,7 @@ function nodeHtml(node) {
|
|
|
297
298
|
|
|
298
299
|
if (node.type === 'action') html += inputsHtml(node);
|
|
299
300
|
html += proseHtml(node);
|
|
300
|
-
if (node.type === 'action') html += outputsHtml(node)
|
|
301
|
+
if (node.type === 'action') html += outputsHtml(node);
|
|
301
302
|
html += childrenHtml(node) + choiceHtml(node) + setHtml(node);
|
|
302
303
|
// 笔记只住右侧栏(不进内容区):revisions 已挪到左侧大纲底部(全文档汇总);refines 同处
|
|
303
304
|
return html;
|
|
@@ -533,6 +534,132 @@ function enhanceCodeBlocks(root) {
|
|
|
533
534
|
}
|
|
534
535
|
}
|
|
535
536
|
|
|
537
|
+
// ── 内联媒体增强 + 灯箱:marked 输出的独占 <p><img></p> 与 proseLite 的 figure
|
|
538
|
+
// 统一成 figure.media,限高不撑爆内容列;图注(alt)走 data-tip 悬停气泡,
|
|
539
|
+
// 不再常驻图片下方。点击开灯箱看原图,滚轮在图片列表内循环切换。向导视图
|
|
540
|
+
// 一次只渲染一个节点,列表收集自当前内容区——天然只含本节点的图,滚不出其它节点 ──
|
|
541
|
+
function enhanceMedia(root) {
|
|
542
|
+
var figs = [];
|
|
543
|
+
var imgs = root.querySelectorAll('.prose img');
|
|
544
|
+
for (var i = 0; i < imgs.length; i++) {
|
|
545
|
+
var img = imgs[i];
|
|
546
|
+
var fig = img.closest('figure');
|
|
547
|
+
if (!fig) {
|
|
548
|
+
// marked 路径:img 独占一个 <p> 才升格 figure(行内混排的小图不动)
|
|
549
|
+
var p = img.parentElement;
|
|
550
|
+
if (!p || p.tagName !== 'P' || p.childNodes.length !== 1) continue;
|
|
551
|
+
fig = document.createElement('figure');
|
|
552
|
+
p.replaceWith(fig);
|
|
553
|
+
fig.appendChild(img);
|
|
554
|
+
} else {
|
|
555
|
+
// proseLite 路径自带 figcaption:文字转进 data-tip,元素撤下
|
|
556
|
+
var capEl = fig.querySelector('figcaption');
|
|
557
|
+
if (capEl) capEl.remove();
|
|
558
|
+
}
|
|
559
|
+
fig.classList.add('media');
|
|
560
|
+
var alt = img.getAttribute('alt') || '';
|
|
561
|
+
if (alt) fig.setAttribute('data-cap', alt); // 图注走跟随光标的浮层气泡(#media-tip)
|
|
562
|
+
figs.push(fig);
|
|
563
|
+
}
|
|
564
|
+
for (var j = 0; j < figs.length; j++) {
|
|
565
|
+
(function (fig, idx) {
|
|
566
|
+
var im = fig.querySelector('img');
|
|
567
|
+
// 悬停判定只挂 img:figure 占满整列,挂 figure 会让空白处也出气泡
|
|
568
|
+
im.addEventListener('mouseenter', function (e) { showMediaTip(fig.getAttribute('data-cap'), e); });
|
|
569
|
+
im.addEventListener('mousemove', function (e) { moveMediaTip(e); });
|
|
570
|
+
im.addEventListener('mouseleave', hideMediaTip);
|
|
571
|
+
im.addEventListener('click', function () {
|
|
572
|
+
openLightbox(figs.map(function (f) { return f.querySelector('img'); }), idx);
|
|
573
|
+
});
|
|
574
|
+
})(figs[j], j);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// 跟随光标的图注气泡:单例浮层 #media-tip,进出图片显示/隐藏、move 跟手
|
|
579
|
+
// ([data-tip]::after 是静态定位,跟不了光标;皮肤同款白底深蓝字)
|
|
580
|
+
function showMediaTip(text, e) {
|
|
581
|
+
if (!text) return;
|
|
582
|
+
var tip = ensureMediaTip();
|
|
583
|
+
tip.textContent = text;
|
|
584
|
+
tip.classList.add('show');
|
|
585
|
+
moveMediaTip(e);
|
|
586
|
+
}
|
|
587
|
+
function moveMediaTip(e) {
|
|
588
|
+
var tip = document.getElementById('media-tip');
|
|
589
|
+
if (!tip || !tip.classList.contains('show')) return;
|
|
590
|
+
// 避让光标:偏移 16/32,且靠近视口边时翻到另一侧(上→下、右→左),
|
|
591
|
+
// 光标怎么移都不会压进气泡(气泡本身 pointer-events:none,只是视觉避让)
|
|
592
|
+
var w = tip.offsetWidth, h = tip.offsetHeight;
|
|
593
|
+
var x = e.clientX + 16;
|
|
594
|
+
var y = e.clientY - h - 16;
|
|
595
|
+
if (x + w > window.innerWidth - 8) x = e.clientX - w - 16;
|
|
596
|
+
if (y < 8) y = e.clientY + 20;
|
|
597
|
+
tip.style.left = x + 'px';
|
|
598
|
+
tip.style.top = y + 'px';
|
|
599
|
+
}
|
|
600
|
+
function hideMediaTip() {
|
|
601
|
+
var tip = document.getElementById('media-tip');
|
|
602
|
+
if (tip) tip.classList.remove('show');
|
|
603
|
+
}
|
|
604
|
+
function ensureMediaTip() {
|
|
605
|
+
var tip = document.getElementById('media-tip');
|
|
606
|
+
if (!tip) {
|
|
607
|
+
tip = document.createElement('div');
|
|
608
|
+
tip.id = 'media-tip';
|
|
609
|
+
document.body.appendChild(tip);
|
|
610
|
+
}
|
|
611
|
+
return tip;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
var lbKeydown = null;
|
|
615
|
+
|
|
616
|
+
function openLightbox(list, idx) {
|
|
617
|
+
closeLightbox();
|
|
618
|
+
var cur = idx;
|
|
619
|
+
var overlay = document.createElement('div');
|
|
620
|
+
overlay.id = 'lightbox';
|
|
621
|
+
var stage = document.createElement('img');
|
|
622
|
+
var cap = document.createElement('div');
|
|
623
|
+
cap.className = 'lb-cap';
|
|
624
|
+
var count = document.createElement('div');
|
|
625
|
+
count.className = 'lb-count';
|
|
626
|
+
var close = document.createElement('button');
|
|
627
|
+
close.type = 'button';
|
|
628
|
+
close.className = 'lb-close';
|
|
629
|
+
close.setAttribute('aria-label', 'close');
|
|
630
|
+
close.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>';
|
|
631
|
+
function draw() {
|
|
632
|
+
var img = list[cur];
|
|
633
|
+
stage.src = img.getAttribute('src');
|
|
634
|
+
stage.alt = img.getAttribute('alt') || '';
|
|
635
|
+
cap.textContent = img.getAttribute('alt') || '';
|
|
636
|
+
count.textContent = (cur + 1) + ' / ' + list.length;
|
|
637
|
+
}
|
|
638
|
+
overlay.appendChild(close);
|
|
639
|
+
overlay.appendChild(stage);
|
|
640
|
+
overlay.appendChild(cap);
|
|
641
|
+
overlay.appendChild(count);
|
|
642
|
+
// 滚轮循环切换(down=下一张、up=上一张,头尾环绕)
|
|
643
|
+
overlay.addEventListener('wheel', function (e) {
|
|
644
|
+
e.preventDefault();
|
|
645
|
+
cur = (cur + (e.deltaY > 0 ? 1 : list.length - 1)) % list.length;
|
|
646
|
+
draw();
|
|
647
|
+
}, { passive: false });
|
|
648
|
+
overlay.addEventListener('click', function (e) {
|
|
649
|
+
if (e.target === overlay || e.target === close) closeLightbox();
|
|
650
|
+
});
|
|
651
|
+
lbKeydown = function (e) { if (e.key === 'Escape') closeLightbox(); };
|
|
652
|
+
document.addEventListener('keydown', lbKeydown);
|
|
653
|
+
document.body.appendChild(overlay);
|
|
654
|
+
draw();
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
function closeLightbox() {
|
|
658
|
+
var el = document.getElementById('lightbox');
|
|
659
|
+
if (el) el.remove();
|
|
660
|
+
if (lbKeydown) { document.removeEventListener('keydown', lbKeydown); lbKeydown = null; }
|
|
661
|
+
}
|
|
662
|
+
|
|
536
663
|
function flashCopied(btn) {
|
|
537
664
|
if (btn.getAttribute('data-flashing') || btn.textContent.trim() !== '') return;
|
|
538
665
|
btn.setAttribute('data-flashing', '1');
|
|
@@ -571,15 +698,70 @@ function showToast(text) {
|
|
|
571
698
|
// 本地文档没有状态/上传者/认领/浏览这些 hub 数据,弹窗只列节点数与根哈希 ──
|
|
572
699
|
var FP_SVG = '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 10a2 2 0 0 0-2 2c0 1.02-.1 2.51-.26 4"/><path d="M14 13.12c0 2.38 0 6.38-1 8.88"/><path d="M17.29 21.02c.12-.6.43-2.3.5-3.02"/><path d="M2 12a10 10 0 0 1 18-6"/><path d="M2 16h.01"/><path d="M21.8 16c.2-2 .131-5.354 0-6"/><path d="M5 19.5C5.5 18 6 15 6 12a6 6 0 0 1 .34-2"/><path d="M8.65 22c.21-.66.45-1.32.57-2"/><path d="M9 6.8a6 6 0 0 1 9 5.2v2"/></svg>';
|
|
573
700
|
var INFO_SVG = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>';
|
|
701
|
+
var CLIP_SVG = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg>';
|
|
574
702
|
var BACK_SVG = '<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m12 19-7-7 7-7"/><path d="M19 12H5"/></svg>';
|
|
575
703
|
|
|
576
|
-
|
|
704
|
+
/** 节点附件平铺(附件跟随节点:practice 无附件表,action 列自己的) */
|
|
705
|
+
function sizeLabel(bytes) {
|
|
706
|
+
if (bytes === undefined || bytes === null) return '';
|
|
707
|
+
if (bytes < 1024) return bytes + ' B';
|
|
708
|
+
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
|
|
709
|
+
return (bytes / 1024 / 1024).toFixed(1) + ' MB';
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
function collectAttachments(node) {
|
|
713
|
+
var out = [];
|
|
714
|
+
var atts = node && node.type === 'action' && node.attachments ? node.attachments : [];
|
|
715
|
+
for (var i = 0; i < atts.length; i++) {
|
|
716
|
+
var a = atts[i];
|
|
717
|
+
out.push({
|
|
718
|
+
name: a.name,
|
|
719
|
+
href: a.url || ('/blobs/' + a.hash),
|
|
720
|
+
meta: [a.mime, sizeLabel(a.size), a.hash ? shortHash(a.hash) : ''].filter(Boolean).join(' · ')
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
return out;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
function topbarHtml(node) {
|
|
727
|
+
var atts = collectAttachments(node);
|
|
728
|
+
var attachBtn = atts.length
|
|
729
|
+
? '<button type="button" class="topbar-btn" data-top="attach" aria-label="' + POP_I18N.t('docAttach') + '" data-tip="' + escapeHtml(POP_I18N.t('docAttach')) + '">' + CLIP_SVG + '<span>(' + atts.length + ')</span></button>'
|
|
730
|
+
: '';
|
|
577
731
|
return '<div class="detail-topbar">' +
|
|
578
732
|
'<button type="button" class="topbar-btn" data-top="back">' + BACK_SVG + '<span>' + POP_I18N.t('back') + '</span></button>' +
|
|
579
|
-
'<
|
|
733
|
+
'<div class="topbar-right">' + attachBtn +
|
|
734
|
+
'<button type="button" class="topbar-btn topbar-icon" data-top="info" aria-label="' + POP_I18N.t('metaInfo') + '" data-tip="' + escapeHtml(POP_I18N.t('metaInfo')) + '">' + INFO_SVG + '</button></div>' +
|
|
580
735
|
'</div>';
|
|
581
736
|
}
|
|
582
737
|
|
|
738
|
+
/** 附件弹窗:固定尺寸,列表超出内滚(多附件不撑屏) */
|
|
739
|
+
function openAttDialog(node) {
|
|
740
|
+
closeAttDialog();
|
|
741
|
+
var atts = collectAttachments(node);
|
|
742
|
+
var rows = atts.map(function (a) {
|
|
743
|
+
return '<div class="att-row"><a href="' + escapeHtml(a.href) + '" target="_blank" rel="noopener">' + escapeHtml(a.name) + '</a>' +
|
|
744
|
+
'<span class="att-meta">' + escapeHtml(a.meta) + '</span></div>';
|
|
745
|
+
}).join('');
|
|
746
|
+
var overlay = document.createElement('div');
|
|
747
|
+
overlay.id = 'att-overlay';
|
|
748
|
+
overlay.innerHTML =
|
|
749
|
+
'<div class="info-card att-card" role="dialog" aria-label="' + POP_I18N.t('docAttach') + '">' +
|
|
750
|
+
'<div class="info-head"><div class="info-title">' + POP_I18N.t('docAttach') + '</div>' +
|
|
751
|
+
'<button type="button" class="info-close" aria-label="close">' + INFO_SVG + '</button></div>' +
|
|
752
|
+
'<div class="att-scroll">' + rows + '</div>' +
|
|
753
|
+
'</div>';
|
|
754
|
+
overlay.addEventListener('click', function (e) {
|
|
755
|
+
if (e.target === overlay) closeAttDialog();
|
|
756
|
+
});
|
|
757
|
+
document.body.appendChild(overlay);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
function closeAttDialog() {
|
|
761
|
+
var el = document.getElementById('att-overlay');
|
|
762
|
+
if (el) el.remove();
|
|
763
|
+
}
|
|
764
|
+
|
|
583
765
|
function openInfoDialog() {
|
|
584
766
|
closeInfoDialog();
|
|
585
767
|
var overlay = document.createElement('div');
|
|
@@ -705,16 +887,7 @@ function outputsHtml(node) {
|
|
|
705
887
|
return '<div class="section-sm"><div class="label">' + POP_I18N.t('secOutputs') + '</div><ol class="io-list">' + outs.map(ioItem).join('') + '</ol></div>';
|
|
706
888
|
}
|
|
707
889
|
|
|
708
|
-
|
|
709
|
-
var atts = node.attachments || [];
|
|
710
|
-
if (!atts.length) return '';
|
|
711
|
-
return '<div class="section-sm"><div class="label">' + POP_I18N.t('secAttachments') + '</div><ul class="att-list">' + atts.map(function (a) {
|
|
712
|
-
var href = a.url || ('/blobs/' + a.hash);
|
|
713
|
-
var meta = [a.mime, a.hash ? shortHash(a.hash) : ''].filter(Boolean).join(' · ');
|
|
714
|
-
return '<li><a href="' + escapeHtml(href) + '">' + escapeHtml(a.name) + '</a>' +
|
|
715
|
-
(meta ? ' <span class="att-meta">' + escapeHtml(meta) + '</span>' : '') + '</li>';
|
|
716
|
-
}).join('') + '</ul></div>';
|
|
717
|
-
}
|
|
890
|
+
// 正文的附件小节已撤(信息进顶栏附件按钮弹窗,附件跟随节点)
|
|
718
891
|
|
|
719
892
|
// ── practice 的孩子呈现(按 op 分形态) ──
|
|
720
893
|
|
|
@@ -786,6 +959,8 @@ document.addEventListener('click', function (e) {
|
|
|
786
959
|
else location.href = '/';
|
|
787
960
|
} else if (top.getAttribute('data-top') === 'info') {
|
|
788
961
|
openInfoDialog();
|
|
962
|
+
} else if (top.getAttribute('data-top') === 'attach') {
|
|
963
|
+
openAttDialog(walk(path));
|
|
789
964
|
}
|
|
790
965
|
return;
|
|
791
966
|
}
|
|
@@ -793,6 +968,10 @@ document.addEventListener('click', function (e) {
|
|
|
793
968
|
closeInfoDialog();
|
|
794
969
|
return;
|
|
795
970
|
}
|
|
971
|
+
if (e.target.closest('#att-overlay .info-close')) {
|
|
972
|
+
closeAttDialog();
|
|
973
|
+
return;
|
|
974
|
+
}
|
|
796
975
|
var copyBtn = e.target.closest('[data-code-copy]');
|
|
797
976
|
if (copyBtn) {
|
|
798
977
|
var text = decodeURIComponent(copyBtn.getAttribute('data-code-copy'));
|
package/web-default/lang.js
CHANGED
|
@@ -10,7 +10,7 @@ var POP_I18N = (function () {
|
|
|
10
10
|
// 字典值:字符串,或函数(复数/拼接类文案按参数生成)
|
|
11
11
|
var M = {
|
|
12
12
|
zh: {
|
|
13
|
-
settings: '设置', language: '语言', done: '完成', copied: '已复制', back: '返回', metaInfo: '文档信息',
|
|
13
|
+
settings: '设置', language: '语言', done: '完成', copied: '已复制', back: '返回', metaInfo: '文档信息', docAttach: '附件',
|
|
14
14
|
tabWizard: '步骤', tabSv: '标准视图', tabDoc: '文档树',
|
|
15
15
|
labelDocJson: '文档 JSON', labelSvJson: '标准视图 JSON',
|
|
16
16
|
// 目录页
|
|
@@ -51,7 +51,7 @@ var POP_I18N = (function () {
|
|
|
51
51
|
backMine: '← 我的实践'
|
|
52
52
|
},
|
|
53
53
|
en: {
|
|
54
|
-
settings: 'Settings', language: 'Language', done: 'Done', copied: 'Copied', back: 'Back', metaInfo: 'Document info',
|
|
54
|
+
settings: 'Settings', language: 'Language', done: 'Done', copied: 'Copied', back: 'Back', metaInfo: 'Document info', docAttach: 'Attachments',
|
|
55
55
|
tabWizard: 'Todo', tabSv: 'StandardView', tabDoc: 'Document',
|
|
56
56
|
labelDocJson: 'Document JSON', labelSvJson: 'StandardView JSON',
|
|
57
57
|
pageTitle: 'My practices',
|
package/web-default/style.css
CHANGED
|
@@ -106,6 +106,20 @@ a:hover { text-decoration: underline; }
|
|
|
106
106
|
.codeblock .hljs-deletion { color: #ffdcd7; background-color: #67060c; }
|
|
107
107
|
.prose figure { margin: 14px 0; }
|
|
108
108
|
.prose img { max-width: 100%; border: 1px solid var(--border); border-radius: 12px; box-shadow: 0 1px 2px rgba(0, 0, 0, .08); }
|
|
109
|
+
/* 图文流内联媒体限高(大图不撑爆内容列),点开灯箱看原图;灯箱只含当前节点;
|
|
110
|
+
禁选——点击图片不落文本光标(图片两侧的 I-beam 根因) */
|
|
111
|
+
.prose figure.media { text-align: left; user-select: none; }
|
|
112
|
+
.prose figure.media img { max-height: 180px; width: auto; object-fit: contain; cursor: pointer; }
|
|
113
|
+
.prose figure.media figcaption { text-align: left; }
|
|
114
|
+
/* 图注气泡跟随光标(JS 单例浮层):皮肤同 [data-tip] */
|
|
115
|
+
#media-tip { position: fixed; background: #fff; color: var(--brand); font-family: system-ui, -apple-system, "Segoe UI", sans-serif; font-size: 12px; line-height: 1.4; padding: 2px 8px; border: 1px solid rgba(226, 232, 240, .9); border-radius: 6px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, .1), 0 2px 4px -2px rgba(0, 0, 0, .1); white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity .15s ease; z-index: 70; }
|
|
116
|
+
#media-tip.show { opacity: 1; }
|
|
117
|
+
#lightbox { position: fixed; inset: 0; background: rgba(13, 17, 23, .92); z-index: 60; display: flex; flex-direction: column; align-items: center; justify-content: center; user-select: none; cursor: default; }
|
|
118
|
+
#lightbox img { max-width: 92vw; max-height: 84vh; border-radius: 8px; }
|
|
119
|
+
#lightbox .lb-cap { color: #e6edf3; font-size: 14px; margin-top: 12px; text-align: center; max-width: 80vw; }
|
|
120
|
+
#lightbox .lb-count { color: rgba(230, 237, 243, .55); font-size: 12px; margin-top: 4px; font-variant-numeric: tabular-nums; }
|
|
121
|
+
#lightbox .lb-close { position: absolute; top: 16px; right: 16px; border: none; background: none; color: rgba(230, 237, 243, .75); cursor: pointer; padding: 4px; display: flex; }
|
|
122
|
+
#lightbox .lb-close:hover { color: #fff; }
|
|
109
123
|
.prose figcaption { font-size: 12px; color: var(--brand-40); text-align: center; margin-top: 4px; }
|
|
110
124
|
/* markdown 全语法排版(对齐 hub MarkdownView 的 prose 观感):标题品牌色、链接 primary
|
|
111
125
|
无下划线 hover 下划线、行内 code 浅底胶囊、块内 code 交还 pre 默认、blockquote 弱化竖线、
|
|
@@ -153,7 +167,6 @@ ol.io-list li { padding: 2px 0; }
|
|
|
153
167
|
.label-row .label { margin-bottom: 0; }
|
|
154
168
|
.label-row .json-copy { color: var(--brand-40); }
|
|
155
169
|
.label-row .json-copy:hover { color: var(--brand); background: rgba(0, 51, 102, .06); }
|
|
156
|
-
.att-list li { padding: 4px 0; }
|
|
157
170
|
.child-card { display: block; border: 1px solid var(--border); border-radius: 10px; padding: 10px 14px; margin-bottom: 8px; font-size: 14px; color: var(--brand-60); background: #fff; }
|
|
158
171
|
button.child-card { width: 100%; text-align: left; cursor: pointer; font: inherit; }
|
|
159
172
|
button.child-card:hover { border-color: var(--brand); color: var(--brand); }
|
|
@@ -284,6 +297,16 @@ a.side-note:hover { color: var(--brand); text-decoration: none; background: rgba
|
|
|
284
297
|
.info-title { font-size: 17px; font-weight: 700; color: var(--brand); }
|
|
285
298
|
.info-close { border: none; background: none; color: var(--brand-40); cursor: pointer; padding: 2px; display: flex; }
|
|
286
299
|
.info-close:hover { color: var(--brand); }
|
|
300
|
+
/* 附件弹窗:与 Info 弹窗同皮肤,固定尺寸(内容少不缩水)、列表内滚 */
|
|
301
|
+
#att-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, .4); z-index: 50; display: flex; align-items: center; justify-content: center; }
|
|
302
|
+
.att-card { width: 380px; height: 400px; display: flex; flex-direction: column; }
|
|
303
|
+
.att-scroll { flex: 1; min-height: 0; overflow-y: auto; }
|
|
304
|
+
.att-row { padding: 8px 0; border-bottom: 1px solid rgba(226, 232, 240, .7); font-size: 13px; }
|
|
305
|
+
.att-row:last-child { border-bottom: none; }
|
|
306
|
+
.att-row a { color: var(--primary); text-decoration: none; font-weight: 500; }
|
|
307
|
+
.att-row a:hover { text-decoration: underline; }
|
|
308
|
+
.att-row .att-meta { display: block; font-size: 11px; color: var(--brand-40); margin-top: 2px; font-family: ui-monospace, "Cascadia Code", Consolas, monospace; }
|
|
309
|
+
.topbar-right { display: flex; align-items: center; gap: 8px; }
|
|
287
310
|
.info-row { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; font-size: 13px; color: var(--brand); }
|
|
288
311
|
.info-row .info-key { color: var(--brand-60); }
|
|
289
312
|
/* 哈希整行按钮(hub InfoDialog 同款):指纹图标+等宽哈希+复制图标,hover 沉到全色 */
|