@lixiangtian/webbridge 0.1.0 → 0.2.0

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.
@@ -0,0 +1 @@
1
+ import{C as e,D as t,E as n,O as r,S as i,T as a,_ as o,a as s,b as c,c as l,d as u,f as d,g as f,h as p,i as m,l as h,m as g,n as _,o as v,p as y,r as b,s as x,t as S,u as C,v as w,w as T,x as E,y as D}from"./registry-BEPWwAh_.js";var O=`bridge-guide`,k=`setupDone`;async function A(){return await b(O,k)===!0}async function j(e){await m(O,k,e)}var M={class:`mx-2.5 mb-3.5 rounded-xl border border-ink-200/70 p-3.5 dark:border-ink-800`},N={class:`mb-3 flex items-center gap-2.5 text-[11px] text-ink-500 dark:text-ink-400`},P={class:`flex items-center gap-1.5 whitespace-nowrap`},F={class:`m-0 list-none p-0`},I={class:`flex items-center gap-2.5`},L={class:`flex flex-1 items-center gap-1.5 text-[13px] font-medium`},R={key:0,class:`rounded-full bg-amber-500/10 px-1.5 py-px text-[10px] font-normal text-amber-600 dark:text-amber-400`},z={class:`flex items-center gap-2.5`},B={class:`flex flex-1 items-center gap-1.5 text-[13px] font-medium`},V={key:0,class:`rounded-full bg-amber-500/10 px-1.5 py-px text-[10px] font-normal text-amber-600 dark:text-amber-400`},H={class:`ml-[30px] mt-2 text-xs leading-relaxed text-ink-400`},U={key:0,class:`text-emerald-500`},W={class:`flex items-center gap-2.5`},G={class:`flex flex-1 items-center gap-1.5 text-[13px] font-medium`},K={key:0,class:`rounded-full bg-amber-500/10 px-1.5 py-px text-[10px] font-normal text-amber-600 dark:text-amber-400`},q=[`disabled`],J={key:0,class:`ml-[30px] mt-1.5 text-[11px] text-amber-600 dark:text-amber-400`},Y=`npm i -g @lixiangtian/webbridge`,X=`webbridge start`,Z=_(f({__name:`BridgeGuide`,setup(i){let c=T(!1),u=T(!1),f=T(!1),p=T(null),m=T(1),_=null,v=h(()=>c.value?u.value?3:2:1);async function b(){try{let e=await s.runtime.sendMessage({_bridgeStatus:!0});u.value=!!e?.connected}catch{u.value=!1}}async function S(){f.value=!0,p.value=null;try{await b();let e=u.value;p.value=e?{ok:!0,message:`服务正常 · WebSocket 连接已建立`}:{ok:!1,message:`未能连上 Bridge(ws://127.0.0.1:8765),请确认服务已启动`},e&&(c.value=!0,await j(!0))}catch(e){p.value={ok:!1,message:e instanceof Error?e.message:String(e)}}finally{f.value=!1}}function O(e){m.value=m.value===e?null:e}async function k(e,t){try{await navigator.clipboard.writeText(e),Z.value=t,setTimeout(()=>{Z.value===t&&(Z.value=``)},1500)}catch{}}let Z=T(``);return o(async()=>{c.value=await A(),m.value=v.value,await b(),_=setInterval(b,3e3)}),e(v,e=>{m.value=e}),w(()=>{_&&clearInterval(_)}),(e,i)=>(D(),y(`section`,M,[C(`div`,N,[i[9]||=C(`span`,{class:`flex items-center gap-1.5 whitespace-nowrap`},[C(`span`,{class:`size-[7px] shrink-0 rounded-full bg-signal-500`}),g(` 浏览器扩展 `)],-1),C(`span`,{class:n([`relative h-0.5 min-w-6 flex-1`,u.value?`bg-emerald-500`:`bg-ink-200 dark:bg-ink-700`]),"aria-hidden":`true`},[(D(),y(l,null,E(3,e=>C(`span`,{key:e,class:n([`absolute top-[-1.5px] size-[5px] rounded-full bg-emerald-500`,u.value?`signal-dot`:`opacity-0`]),style:t({animationDelay:`${(e-1)*.3}s`})},null,6)),64))],2),C(`span`,P,[C(`span`,{class:n([`size-[7px] shrink-0 rounded-full`,u.value?`bg-emerald-500 ring-[3px] ring-emerald-500/20`:`bg-ink-300 dark:bg-ink-600`])},null,2),i[8]||=g(` 本地 Bridge `,-1)])]),C(`ol`,F,[C(`li`,{class:`cursor-pointer border-t border-dashed border-ink-200/70 py-2.5 first:border-t-0 first:pt-0 dark:border-ink-800`,onClick:i[3]||=e=>O(1)},[C(`div`,I,[C(`span`,{class:n([`grid size-5 shrink-0 place-items-center rounded-full border text-[11px] font-semibold`,c.value?`border-emerald-500 bg-emerald-500 text-white`:`border-ink-300 text-ink-500 dark:border-ink-600 dark:text-ink-400`])},r(c.value?`✓`:`1`),3),C(`div`,L,[i[10]||=g(` 安装本地 Bridge `,-1),v.value===1?(D(),y(`span`,R,`待完成`)):d(``,!0)]),(D(),y(`svg`,{class:n([`size-3 shrink-0 text-ink-400 transition-transform`,m.value===1?`rotate-180`:``]),viewBox:`0 0 12 12`,fill:`none`},[...i[11]||=[C(`path`,{d:`M3 5l3 3 3-3`,stroke:`currentColor`,"stroke-width":`1.2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},null,-1)]],2))]),m.value===1?(D(),y(l,{key:0},[i[12]||=C(`p`,{class:`ml-[30px] mt-2 text-xs leading-relaxed text-ink-400`},` Bridge 是运行在你电脑上的本地服务,AI 的文件读写、脚本执行都经它完成,数据不出本机。需 Node 22+。 `,-1),C(`div`,{class:`ml-[30px] mt-2 flex items-center gap-1.5`,onClick:i[1]||=x(()=>{},[`stop`])},[C(`code`,{class:`min-w-0 flex-1 truncate rounded-md bg-ink-100 px-2 py-1.5 font-mono text-[11px] text-ink-700 dark:bg-ink-800 dark:text-ink-200`},r(Y)),C(`button`,{class:`whitespace-nowrap rounded-md border border-ink-300 px-2.5 py-1.5 text-[11px] text-ink-500 hover:bg-ink-100 dark:border-ink-600 dark:text-ink-300 dark:hover:bg-ink-800`,onClick:i[0]||=e=>k(Y,`install`)},r(Z.value===`install`?`已复制`:`复制`),1)]),i[13]||=C(`p`,{class:`ml-[30px] mt-1.5 text-[11px] text-ink-400`},`在终端执行,装一次即可`,-1),c.value?d(``,!0):(D(),y(`button`,{key:0,class:`ml-[30px] mt-2.5 rounded-lg bg-signal-500 px-3.5 py-1.5 text-xs font-medium text-white hover:bg-signal-600`,onClick:i[2]||=x(e=>{c.value=!0,a(j)(!0),m.value=2},[`stop`])},` 我已安装 `))],64)):d(``,!0)]),C(`li`,{class:`cursor-pointer border-t border-dashed border-ink-200/70 py-2.5 dark:border-ink-800`,onClick:i[6]||=e=>O(2)},[C(`div`,z,[C(`span`,{class:n([`grid size-5 shrink-0 place-items-center rounded-full border text-[11px] font-semibold`,c.value&&u.value?`border-emerald-500 bg-emerald-500 text-white`:`border-ink-300 text-ink-500 dark:border-ink-600 dark:text-ink-400`])},r(c.value&&u.value?`✓`:`2`),3),C(`div`,B,[i[14]||=g(` 启动 Bridge `,-1),c.value&&!u.value?(D(),y(`span`,V,`待完成`)):d(``,!0)]),(D(),y(`svg`,{class:n([`size-3 shrink-0 text-ink-400 transition-transform`,m.value===2?`rotate-180`:``]),viewBox:`0 0 12 12`,fill:`none`},[...i[15]||=[C(`path`,{d:`M3 5l3 3 3-3`,stroke:`currentColor`,"stroke-width":`1.2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},null,-1)]],2))]),m.value===2?(D(),y(l,{key:0},[C(`p`,H,[i[16]||=g(` 在终端执行以下命令(后台常驻,开机后跑一次即可)。启动成功后顶部链路会自动亮起`,-1),u.value?(D(),y(`span`,U,`(已检测到连接 ✓)`)):d(``,!0),i[17]||=g(`。 `,-1)]),C(`div`,{class:`ml-[30px] mt-2 flex items-center gap-1.5`,onClick:i[5]||=x(()=>{},[`stop`])},[C(`code`,{class:`min-w-0 flex-1 truncate rounded-md bg-ink-100 px-2 py-1.5 font-mono text-[11px] text-ink-700 dark:bg-ink-800 dark:text-ink-200`},r(X)),C(`button`,{class:`whitespace-nowrap rounded-md border border-ink-300 px-2.5 py-1.5 text-[11px] text-ink-500 hover:bg-ink-100 dark:border-ink-600 dark:text-ink-300 dark:hover:bg-ink-800`,onClick:i[4]||=e=>k(X,`start`)},r(Z.value===`start`?`已复制`:`复制`),1)]),i[18]||=C(`p`,{class:`ml-[30px] mt-1.5 text-[11px] text-ink-400`},`停止用 webbridge stop · 查看状态 webbridge status`,-1)],64)):d(``,!0)]),C(`li`,{class:`cursor-pointer border-t border-dashed border-ink-200/70 py-2.5 dark:border-ink-800`,onClick:i[7]||=e=>O(3)},[C(`div`,W,[C(`span`,{class:n([`grid size-5 shrink-0 place-items-center rounded-full border text-[11px] font-semibold`,p.value?.ok?`border-emerald-500 bg-emerald-500 text-white`:`border-ink-300 text-ink-500 dark:border-ink-600 dark:text-ink-400`])},r(p.value?.ok?`✓`:`3`),3),C(`div`,G,[i[19]||=g(` 验证服务 `,-1),c.value&&u.value&&!p.value?.ok?(D(),y(`span`,K,`待完成`)):d(``,!0)]),(D(),y(`svg`,{class:n([`size-3 shrink-0 text-ink-400 transition-transform`,m.value===3?`rotate-180`:``]),viewBox:`0 0 12 12`,fill:`none`},[...i[20]||=[C(`path`,{d:`M3 5l3 3 3-3`,stroke:`currentColor`,"stroke-width":`1.2`,"stroke-linecap":`round`,"stroke-linejoin":`round`},null,-1)]],2))]),m.value===3?(D(),y(l,{key:0},[i[21]||=C(`p`,{class:`ml-[30px] mt-2 text-xs leading-relaxed text-ink-400`},` 检测扩展到本地 Bridge 的 WebSocket 连接(ws://127.0.0.1:8765)是否畅通。 `,-1),C(`button`,{class:`ml-[30px] mt-2.5 rounded-lg bg-signal-500 px-3.5 py-1.5 text-xs font-medium text-white hover:bg-signal-600 disabled:cursor-default disabled:opacity-45`,disabled:f.value||!u.value,onClick:x(S,[`stop`])},r(f.value?`验证中…`:u.value?`开始验证`:`等待 Bridge 连接…`),9,q),u.value?d(``,!0):(D(),y(`p`,J,` Bridge 未连接,请先完成上一步 `)),p.value?(D(),y(`p`,{key:1,class:n([`ml-[30px] mt-1.5 text-[11px]`,p.value.ok?`text-emerald-500`:`text-red-500`])},r(p.value.message),3)):d(``,!0)],64)):d(``,!0)])])]))}}),[[`__scopeId`,`data-v-7e8675eb`]]),Q={key:1,class:`flex h-screen flex-col overflow-y-auto`},$=[`onClick`],ee={class:`text-[22px]`},te={class:`flex min-w-0 flex-1 flex-col gap-0.5`},ne={class:`text-sm font-medium`},re={key:0,class:`truncate text-xs text-ink-400`};v(f({__name:`App`,setup(e){let t=T(null),n=h(()=>S.find(e=>e.id===t.value));c(`goHome`,()=>{t.value=null});let o=0,f=null;function m(e){n.value&&(Math.abs(e.deltaX)<=Math.abs(e.deltaY)||(o+=e.deltaX,f&&clearTimeout(f),f=setTimeout(()=>o=0,200),o<-120&&(o=0,t.value=null)))}function g(){s.runtime.openOptionsPage().catch(()=>{s.tabs.create({url:s.runtime.getURL(`/dashboard.html`)})})}return(e,o)=>(D(),y(`div`,{class:`h-screen bg-white text-ink-800 dark:bg-ink-900 dark:text-ink-100`,onWheel:m},[n.value?(D(),u(i(n.value.sidepanelComponent),{key:0})):(D(),y(`div`,Q,[C(`header`,{class:`flex items-center justify-between px-4 pt-4`},[o[1]||=C(`div`,{class:`flex items-center gap-2`},[C(`span`,{class:`grid size-7 place-items-center rounded-lg bg-signal-500 text-[14px] font-semibold text-white`},`灵`),C(`span`,{class:`text-[17px] font-semibold tracking-wide`},`灵犀`)],-1),C(`button`,{class:`rounded-lg p-1.5 text-ink-400 hover:bg-ink-50 hover:text-ink-600 dark:hover:bg-ink-800 dark:hover:text-ink-200`,title:`打开配置页`,onClick:g},[...o[0]||=[C(`svg`,{class:`size-[18px]`,viewBox:`0 0 16 16`,fill:`none`},[C(`circle`,{cx:`8`,cy:`8`,r:`2.2`,stroke:`currentColor`,"stroke-width":`1.2`}),C(`path`,{d:`M8 1.8v1.6M8 12.6v1.6M1.8 8h1.6M12.6 8h1.6M3.6 3.6l1.1 1.1M11.3 11.3l1.1 1.1M12.4 3.6l-1.1 1.1M4.7 11.3l-1.1 1.1`,stroke:`currentColor`,"stroke-width":`1.2`,"stroke-linecap":`round`})],-1)]])]),o[3]||=C(`p`,{class:`px-[17px] pt-1 pb-3.5 text-xs text-ink-400`},`浏览器里的 AI 工作台`,-1),p(Z),o[4]||=C(`h2`,{class:`px-[17px] pb-1.5 pt-1.5 text-[11px] font-medium uppercase tracking-widest text-ink-400`},` 功能 `,-1),(D(!0),y(l,null,E(a(S),e=>(D(),y(`button`,{key:e.id,class:`mx-2.5 mb-2 flex items-center gap-3 rounded-xl border border-ink-200/70 px-3.5 py-3 text-left transition-colors hover:bg-ink-50 dark:border-ink-800 dark:hover:bg-ink-800`,onClick:n=>t.value=e.id},[C(`span`,ee,r(e.icon),1),C(`span`,te,[C(`span`,ne,r(e.name),1),e.description?(D(),y(`span`,re,r(e.description),1)):d(``,!0)]),o[2]||=C(`svg`,{class:`size-3.5 shrink-0 text-ink-400`,viewBox:`0 0 16 16`,fill:`none`},[C(`path`,{d:`M6 3.5L10.5 8 6 12.5`,stroke:`currentColor`,"stroke-width":`1.5`,"stroke-linecap":`round`,"stroke-linejoin":`round`})],-1)],8,$))),128))]))],32))}})).mount(`#app`);
@@ -0,0 +1,2 @@
1
+ (function(){function e(e){return e}var t=globalThis.browser?.runtime?.id?globalThis.browser:globalThis.chrome,n=e({matches:[`<all_urls>`],main(){document.addEventListener(`contextmenu`,e=>{i=e.target instanceof Element?e.target:null},!0),t.runtime.onMessage.addListener((e,t,n)=>{if(e?.type===`DOM_OP`)return r(e.op).then(e=>n({ok:!0,data:e})).catch(e=>n({ok:!1,error:e instanceof Error?e.message:String(e)})),!0})}});async function r(e){let t=e.params??{};switch(e.action){case`read-full`:return b(Number(t.maxLength??2e4));case`snapshot`:return _(Number(t.limit??150));case`get-rect`:return v(t);case`click`:return x(t);case`fill`:return S(t,String(t.value??``));case`scroll`:return C(Number(t.deltaY??600));case`extract`:return w(String(t.selector),Number(t.limit??50));case`get-context-element`:return a();default:throw Error(`未知 DOM 操作: ${e.action}`)}}var i=null;function a(){let e=i;if(!e||!e.isConnected)throw Error(`右键目标元素已失效,请在目标元素上重新右键`);let t=e.getBoundingClientRect();return{tag:e.tagName.toLowerCase(),cssPath:o(e),text:d(e.textContent??``,300),html:s(e.outerHTML,2e3),rect:`${Math.round(t.left)},${Math.round(t.top)} ${Math.round(t.width)}x${Math.round(t.height)}`,url:location.href}}function o(e){let t=[],n=e;for(;n&&n!==document.body;){let e=n.tagName.toLowerCase();if(n.id){t.unshift(`${e}#${n.id}`);break}let r=n.parentElement;if(r){let t=[...r.children].filter(e=>e.tagName===n.tagName);t.length>1&&(e+=`:nth-of-type(${t.indexOf(n)+1})`)}t.unshift(e),n=r}return t.join(` > `)}function s(e,t){return e.length>t?`${e.slice(0,t)}…(截断,共 ${e.length} 字符)`:e}function c(e){if(!e)throw Error(`缺少 selector`);let t=document.querySelector(e);if(!t)throw Error(`未找到元素: ${e}`);if(!(t instanceof HTMLElement))throw Error(`元素非可交互节点: ${e}`);return t}var l=new Map,u=[`a[href]`,`button`,`input`,`select`,`textarea`,`summary`,`[role]`,`[contenteditable="true"]`,`[tabindex]:not([tabindex="-1"])`].join(`,`);function d(e,t){let n=(e??``).replace(/\s+/g,` `).trim();return n.length>t?`${n.slice(0,t)}…`:n}var f={a:`link`,button:`button`,input:`textbox`,select:`combobox`,textarea:`textbox`,summary:`summary`,nav:`navigation`,header:`banner`,footer:`contentinfo`,main:`main`,aside:`complementary`,form:`form`,h1:`heading`,h2:`heading`,h3:`heading`,h4:`heading`,h5:`heading`,h6:`heading`,ul:`list`,ol:`list`,li:`listitem`,table:`table`,img:`image`,svg:`image`,label:`label`,section:`section`,article:`article`,dialog:`dialog`,video:`video`,audio:`audio`},p=new Set([`nav`,`header`,`footer`,`main`,`aside`,`form`,`section`,`article`,`dialog`,`ul`,`ol`,`table`]);function m(e){let t=e.getAttribute(`role`);if(t)return t;let n=e.tagName.toLowerCase();if(n===`input`){let t=e.type;return t===`checkbox`||t===`radio`?t:t===`submit`||t===`button`||t===`reset`?`button`:t===`file`?`file`:`textbox`}return f[n]??null}function h(e){if(!(e instanceof HTMLElement))return!1;if(e.getAttribute(`aria-hidden`)===`true`||e.getClientRects().length===0)return!0;let t=getComputedStyle(e);return t.display===`none`||t.visibility===`hidden`}function g(e){let t=e.getAttribute(`aria-label`)??e.getAttribute(`title`);return t?d(t,40):e instanceof HTMLInputElement?e.type===`checkbox`||e.type===`radio`?d(e.labels?.[0]?.textContent??``,30):e.type===`password`?d(e.placeholder||`(密码已隐藏)`,30):d(e.placeholder||e.value||``,30):e instanceof HTMLTextAreaElement?d(e.placeholder||e.value||``,30):d(e.textContent??``,40)}function _(e){l.clear();let t=window.innerWidth,n=window.innerHeight,r=[],i=0,a=!1,o=(t,n)=>{if(a||i>=e||r.length>=400){a=!0;return}if(n>12||h(t))return;let s=t.tagName.toLowerCase();if(t.matches(u)){i+=1;let e=`e${i}`;l.set(e,t);let a=g(t),o=`${` `.repeat(n)}${m(t)??s}`;if(a&&(o+=` "${a}"`),t instanceof HTMLSelectElement){let e=[...t.options].slice(0,5).map(e=>d(e.text,15)).join(`|`);e&&(o+=` {${e}}`)}r.push(`${o} [${e}]`);return}let c=m(t);if(p.has(s)||t.getAttribute(`role`)!=null){let e=`${` `.repeat(n)}${c??s}`;if(c===`heading`){let n=d(t.textContent??``,50);n&&(e+=` "${n}"`)}r.push(e);for(let e of t.children)o(e,n+1);return}for(let e of t.children)o(e,n)};return o(document.body,0),{title:document.title,url:location.href,scrollY:Math.round(window.scrollY),pageHeight:document.documentElement.scrollHeight,viewport:`${t}x${n}`,interactive:i,truncated:a,tree:r.join(`
2
+ `)}}function v(e){let t=y(e);t.scrollIntoView({block:`center`});let n=t.getBoundingClientRect();return{x:Math.round(n.left+n.width/2),y:Math.round(n.top+n.height/2),w:Math.round(n.width),h:Math.round(n.height),text:d(t.textContent??``,30)}}function y(e){let t=e.ref?String(e.ref):``;if(t){let e=l.get(t);if(!e)throw Error(`引用 ${t} 不存在(页面可能已变化或尚未 snapshot),请先调用 browser_snapshot`);if(!e.isConnected)throw Error(`引用 ${t} 的元素已从页面移除,请重新 browser_snapshot`);if(!(e instanceof HTMLElement))throw Error(`引用 ${t} 不是可交互元素`);return e}return c(String(e.selector??``))}function b(e){let t=document.title,n=location.href,r=document.body?.innerText??``;return r.length>e&&(r=`${r.slice(0,e)}…(截断,共 ${r.length} 字符)`),{title:t,url:n,text:r}}function x(e){let t=y(e);return t.scrollIntoView({block:`center`}),t.dispatchEvent(new MouseEvent(`click`,{bubbles:!0,cancelable:!0,view:window})),{clicked:e.ref?`ref:${e.ref}`:String(e.selector),tag:t.tagName,text:d(t.textContent??``,30)}}function S(e,t){let n=y(e),r=n instanceof HTMLTextAreaElement?HTMLTextAreaElement.prototype:HTMLInputElement.prototype,i=Object.getOwnPropertyDescriptor(r,`value`)?.set;return i?i.call(n,t):n.value=t,n.dispatchEvent(new Event(`input`,{bubbles:!0})),n.dispatchEvent(new Event(`change`,{bubbles:!0})),{filled:e.ref?`ref:${e.ref}`:String(e.selector),length:t.length}}function C(e){return window.scrollBy({top:e,behavior:`smooth`}),{scrolled:e,position:window.scrollY}}function w(e,t){let n=[...document.querySelectorAll(e)].slice(0,t);return{count:n.length,items:n.map(e=>({tag:e.tagName,text:(e.textContent??``).trim().slice(0,200),href:e.href??void 0}))}}var T={debug:(...e)=>([...e],void 0),log:(...e)=>([...e],void 0),warn:(...e)=>([...e],void 0),error:(...e)=>([...e],void 0)},E=class e extends Event{static EVENT_NAME=D(`wxt:locationchange`);constructor(t,n){super(e.EVENT_NAME,{}),this.newUrl=t,this.oldUrl=n}};function D(e){return`${t?.runtime?.id}:content:${e}`}var O=typeof globalThis.navigation?.addEventListener==`function`;function k(e){let t,n=!1;return{run(){n||(n=!0,t=new URL(location.href),O?globalThis.navigation.addEventListener(`navigate`,e=>{let n=new URL(e.destination.url);n.href!==t.href&&(window.dispatchEvent(new E(n,t)),t=n)},{signal:e.signal}):e.setInterval(()=>{let e=new URL(location.href);e.href!==t.href&&(window.dispatchEvent(new E(e,t)),t=e)},1e3))}}}var A=class e{static SCRIPT_STARTED_MESSAGE_TYPE=D(`wxt:content-script-started`);id;abortController;locationWatcher=k(this);constructor(e,t){this.contentScriptName=e,this.options=t,this.id=Math.random().toString(36).slice(2),this.abortController=new AbortController,this.stopOldScripts(),this.listenForNewerScripts()}get signal(){return this.abortController.signal}abort(e){return this.abortController.abort(e)}get isInvalid(){return t.runtime?.id??this.notifyInvalidated(),this.signal.aborted}get isValid(){return!this.isInvalid}onInvalidated(e){return this.signal.addEventListener(`abort`,e),()=>this.signal.removeEventListener(`abort`,e)}block(){return new Promise(()=>{})}setInterval(e,t){let n=setInterval(()=>{this.isValid&&e()},t);return this.onInvalidated(()=>clearInterval(n)),n}setTimeout(e,t){let n=setTimeout(()=>{this.isValid&&e()},t);return this.onInvalidated(()=>clearTimeout(n)),n}requestAnimationFrame(e){let t=requestAnimationFrame((...t)=>{this.isValid&&e(...t)});return this.onInvalidated(()=>cancelAnimationFrame(t)),t}requestIdleCallback(e,t){let n=requestIdleCallback((...t)=>{this.signal.aborted||e(...t)},t);return this.onInvalidated(()=>cancelIdleCallback(n)),n}addEventListener(e,t,n,r){t===`wxt:locationchange`&&this.isValid&&this.locationWatcher.run(),e.addEventListener?.(t.startsWith(`wxt:`)?D(t):t,n,{...r,signal:this.signal})}notifyInvalidated(){this.abort(`Content script context invalidated`),T.debug(`Content script "${this.contentScriptName}" context invalidated`)}stopOldScripts(){document.dispatchEvent(new CustomEvent(e.SCRIPT_STARTED_MESSAGE_TYPE,{detail:{contentScriptName:this.contentScriptName,messageId:this.id}})),this.options?.noScriptStartedPostMessage||window.postMessage({type:e.SCRIPT_STARTED_MESSAGE_TYPE,contentScriptName:this.contentScriptName,messageId:this.id},`*`)}verifyScriptStartedEvent(e){let t=e.detail?.contentScriptName===this.contentScriptName,n=e.detail?.messageId===this.id;return t&&!n}listenForNewerScripts(){let t=e=>{!(e instanceof CustomEvent)||!this.verifyScriptStartedEvent(e)||this.notifyInvalidated()};document.addEventListener(e.SCRIPT_STARTED_MESSAGE_TYPE,t),this.onInvalidated(()=>document.removeEventListener(e.SCRIPT_STARTED_MESSAGE_TYPE,t))}},j={debug:(...e)=>([...e],void 0),log:(...e)=>([...e],void 0),warn:(...e)=>([...e],void 0),error:(...e)=>([...e],void 0)};return(async()=>{try{let{main:e,...t}=n;return await e(new A(`content`,t))}catch(e){throw j.error(`The content script "content" crashed on startup!`,e),e}})()})();
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>主页</title>
7
+ <script type="module" crossorigin src="/chunks/dashboard-9CnyaZzA.js"></script>
8
+ <link rel="modulepreload" crossorigin href="/chunks/registry-BEPWwAh_.js">
9
+ <link rel="stylesheet" crossorigin href="/assets/registry-DcscwPiE.css">
10
+ <link rel="stylesheet" crossorigin href="/assets/dashboard-CoFwATJG.css">
11
+ </head>
12
+ <body>
13
+ <div id="app"></div>
14
+ </body>
15
+ </html>
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1 @@
1
+ {"manifest_version":3,"name":"wxt-vue-starter","description":"manifest.json description","version":"0.0.0","icons":{"16":"icon/16.png","32":"icon/32.png","48":"icon/48.png","96":"icon/96.png","128":"icon/128.png"},"permissions":["sidePanel","scripting","tabs","storage","activeTab","debugger","contextMenus"],"optional_host_permissions":["https://*/*","http://*/*"],"host_permissions":["ws://127.0.0.1:8765/*","https://news.10jqka.com.cn/*","https://feed.mix.sina.com.cn/*","https://hacker-news.firebaseio.com/*","https://sspai.com/*","https://www.ifanr.com/*","https://rss.sciencedaily.com/*","https://api.deepseek.com/*","https://api.moonshot.cn/*","https://api.openai.com/*","https://api.anthropic.com/*","https://openrouter.ai/*"],"action":{},"options_page":"dashboard.html","web_accessible_resources":[{"resources":["sidepanel.html","chunks/*","assets/*","icon/*"],"matches":["<all_urls>"]}],"side_panel":{"default_path":"sidepanel.html"},"background":{"service_worker":"background.js"},"content_scripts":[{"matches":["<all_urls>"],"js":["content-scripts/content.js"]}]}
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>侧边栏</title>
7
+ <script type="module" crossorigin src="/chunks/sidepanel-jk4KxNMa.js"></script>
8
+ <link rel="modulepreload" crossorigin href="/chunks/registry-BEPWwAh_.js">
9
+ <link rel="stylesheet" crossorigin href="/assets/registry-DcscwPiE.css">
10
+ <link rel="stylesheet" crossorigin href="/assets/sidepanel-Y5vXaYhq.css">
11
+ </head>
12
+ <body>
13
+ <div id="app"></div>
14
+ </body>
15
+ </html>
@@ -0,0 +1,15 @@
1
+ <svg width="72" height="72" viewBox="0 0 72 72" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g clip-path="url(#clip0_305_516)">
3
+ <g clip-path="url(#clip1_305_516)">
4
+ <path d="M49.0229 69.1875C54.1272 69.1875 58.265 65.0497 58.265 59.9454V50.7033H59.9454C65.0497 50.7033 69.1875 46.5655 69.1875 41.4612C69.1875 36.357 65.0497 32.2191 59.9454 32.2191H58.265V22.9771C58.265 17.8728 54.1272 13.735 49.0229 13.735H39.7809V12.0546C39.7809 6.95032 35.643 2.8125 30.5388 2.8125C25.4345 2.8125 21.2967 6.95032 21.2967 12.0546V13.735H12.0546C6.95032 13.735 2.8125 17.8728 2.8125 22.9771V32.2191H4.49288C9.59714 32.2191 13.735 36.357 13.735 41.4612C13.735 46.5655 9.59714 50.7033 4.49288 50.7033H2.8125V69.1875H21.2967V67.5071C21.2967 62.4029 25.4345 58.265 30.5388 58.265C35.643 58.265 39.7809 62.4029 39.7809 67.5071V69.1875H49.0229Z" stroke="#67D55E" stroke-width="5.625"/>
5
+ </g>
6
+ </g>
7
+ <defs>
8
+ <clipPath id="clip0_305_516">
9
+ <rect width="72" height="72" fill="white"/>
10
+ </clipPath>
11
+ <clipPath id="clip1_305_516">
12
+ <rect width="72" height="72" fill="white"/>
13
+ </clipPath>
14
+ </defs>
15
+ </svg>
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@lixiangtian/webbridge",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "tsx watch src/index.ts",
8
8
  "start": "tsx src/index.ts",
9
- "build": "esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/webbridge.bundle.mjs --external:node-pty --external:fsevents --banner:js=\"import { createRequire as __cr } from 'node:module'; globalThis.require = __cr(import.meta.url);\"",
9
+ "build": "esbuild src/index.ts --bundle --platform=node --format=esm --outfile=dist/webbridge.bundle.mjs --external:node-pty --external:fsevents --banner:js=\"import { createRequire as __cr } from 'node:module'; globalThis.require = __cr(import.meta.url);\" && node scripts/copy-extension.mjs",
10
10
  "prepublishOnly": "npm run build",
11
11
  "postinstall": "chmod +x node_modules/node-pty/prebuilds/*/spawn-helper || true"
12
12
  },
@@ -27,7 +27,9 @@
27
27
  },
28
28
  "files": [
29
29
  "bin",
30
- "dist"
30
+ "dist",
31
+ "extension",
32
+ "scripts/copy-extension.mjs"
31
33
  ],
32
34
  "engines": {
33
35
  "node": ">=22"
@@ -0,0 +1,21 @@
1
+ /**
2
+ * 把扩展构建产物(wxt build 的 .output/chrome-mv3)拷进 npm 包的 extension/ 目录。
3
+ * 扩展产物不存在时警告但不失败(bridge 可独立发布)。
4
+ */
5
+ import * as fs from 'node:fs';
6
+ import * as path from 'node:path';
7
+ import { fileURLToPath } from 'node:url';
8
+
9
+ const here = path.dirname(fileURLToPath(import.meta.url));
10
+ const extOut = path.resolve(here, '../../.output/chrome-mv3');
11
+ const dest = path.resolve(here, '../extension');
12
+
13
+ if (!fs.existsSync(path.join(extOut, 'manifest.json'))) {
14
+ console.warn('⚠ 未找到扩展产物(.output/chrome-mv3),本次包不含扩展。先在扩展根目录跑 npx wxt build。');
15
+ process.exit(0);
16
+ }
17
+
18
+ fs.rmSync(dest, { recursive: true, force: true });
19
+ fs.cpSync(extOut, dest, { recursive: true });
20
+ const files = fs.readdirSync(dest).length;
21
+ console.log(`✓ 扩展产物已拷入 extension/(${files} 个顶层条目)`);