diff --git a/packages/tools/cli/bin/ua.js b/packages/tools/cli/bin/ua.js
index 8f0e24d..309d010 100644
--- a/packages/tools/cli/bin/ua.js
+++ b/packages/tools/cli/bin/ua.js
@@ -402,6 +402,10 @@ iframe.demo{width:100%;height:430px;border:1px dashed var(--border);border-radiu
.sw code{color:var(--muted)}
.sw span{font-size:12px;color:var(--muted)}
.swatches{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:4px 20px}
+.comp h4{display:flex;align-items:center;gap:8px;justify-content:space-between}
+.copy{margin-left:auto;flex:none;padding:3px 10px;border:1px solid var(--border);border-radius:6px;background:var(--surface);color:var(--muted);font:inherit;font-size:12px;cursor:pointer;transition:color .15s,border-color .15s}
+.copy:hover{color:var(--text);border-color:var(--accent)}
+.copy:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.empty{color:var(--muted);text-align:center;padding:40px 0}
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
footer{max-width:960px;margin:0 auto;padding:0 20px 40px;color:var(--muted);font-size:12px}
@@ -424,9 +428,49 @@ function propsTable(c){
}).join('');
return '
';
}
+var ALLCOMPS=[];
+DATA.forEach(function(p){ (p.docs&&p.docs.components||[]).forEach(function(c){ ALLCOMPS.push(c); }); });
+var TICK=String.fromCharCode(96); // 反引号:生成器本身是模板串,这里不写裸反引号,避免把模板串提前截断
+function mdOf(c){
+ var bar=String.fromCharCode(124); // 竖线:Markdown 表格分隔符的转义源
+ var cell=function(v){ return String(v||'').split(bar).join('\\\\'+bar); }; // 输出 \\| 给 Markdown 表格转义
+ var out='### '+c.id+' · '+(c.title||c.id)+'\\n\\n';
+ if(c.props&&c.props.length){
+ out+='| 参数 | 类型 | 必填 | 说明 |\\n| --- | --- | --- | --- |\\n';
+ c.props.forEach(function(p){ out+='| '+TICK+cell(p.n)+TICK+' | '+TICK+cell(p.t)+TICK+' | '+(p.r?'是':'否')+' | '+cell(p.d)+' |\\n'; });
+ out+='\\n';
+ }
+ if(c.steps&&c.steps.length){
+ out+='**用法**\\n\\n';
+ c.steps.forEach(function(s,i){ out+=(i+1)+'. '+s+'\\n'; });
+ out+='\\n';
+ }
+ if(c.example) out+=TICK+TICK+TICK+'ts\\n'+c.example+'\\n'+TICK+TICK+TICK+'\\n';
+ return out;
+}
+function legacyCopy(text){
+ var ta=document.createElement('textarea');
+ ta.value=text; ta.setAttribute('readonly','');
+ ta.style.position='fixed'; ta.style.opacity='0';
+ document.body.appendChild(ta); ta.select();
+ try { document.execCommand('copy'); } catch(e) {}
+ document.body.removeChild(ta);
+}
+document.addEventListener('click',function(e){
+ var btn=e.target.closest('[data-copy]');
+ if(!btn) return;
+ var c=ALLCOMPS.filter(function(x){return x.id===btn.getAttribute('data-copy')})[0];
+ if(!c) return;
+ var done=function(){ var old=btn.textContent; btn.textContent='已复制'; setTimeout(function(){ btn.textContent=old; },1200); };
+ // 剪贴板 API 在 file:// 或未授权时会 reject,退回 textarea + execCommand
+ if(navigator.clipboard&&navigator.clipboard.writeText){
+ navigator.clipboard.writeText(mdOf(c)).then(done).catch(function(){ legacyCopy(mdOf(c)); done(); });
+ } else { legacyCopy(mdOf(c)); done(); }
+});
function compBlock(c){
var steps=(c.steps||[]).map(function(s){return ''+esc(s)+''}).join('');
- return ''+esc(c.id)+' · '+esc(c.title||'')+'
'
+ return '
'+esc(c.id)+' · '+esc(c.title||'')
+ +'
'
+(c.props?propsTable(c):'')
+(c.example?'
'+esc(c.example)+'
':'')
+(steps?'
手把手
'+steps+'
':'')