input.js JAVASCRIPT
✅ 就绪
bookmarklet:// INSTANT

生成的书签

📌 把我拖到书签栏 ↑ 拖动上方链接到浏览器书签栏,之后在任何网页上点击即可执行

生成结果(纯文本)

javascript:void(0)

字节

原代码: 0 字符 压缩后: 0 字符 书签总长: 0 字符

⭐ 我的收藏

0 条

⚡ 什么是 Bookmarklet Forge?

一个纯前端的书签小工具生成器。你在左边写 JavaScript,右边实时生成一个 javascript: 协议的链接,拖到浏览器书签栏——之后任何网页上点一下,代码就在那个页面里执行。

完全不需要后端、不需要登录、不需要服务器——所有数据存在你本地 localStorage。

🔧 技术栈

HTML5 CSS3 Vanilla JS LocalStorage 无框架 单文件

📖 Bookmarklet 原理

javascript:alert('hello from bookmarklet!')

浏览器允许 URL 以 javascript: 开头,点击后 JS 代码会在当前页面上下文执行。Bookmarklet 就是把 JS 包在书签链接里,利用这个机制实现"一键在任意网页执行代码"。

🚀 使用步骤

  • 写 JS 或从预设库选一个
  • 点"📌 把我拖到书签栏"
  • 在任何网页上点击那个书签
  • 页面立即被你的 JS 改造

⚠️ 安全提示

  • Bookmarklet 和普通 JS 一样有能力读取/修改你打开的网页
  • 只从你信任的来源安装 bookmarklet
  • 可以在生成器里启用"IIFE 包装"防止污染全局变量
✅ 已复制到剪贴板
'; const blob=new Blob([html],{type:'text/html;charset=utf-8'}); const a=document.createElement('a'); a.href=URL.createObjectURL(blob);a.download='bookmarklet-installer.html';a.click(); setTimeout(()=>URL.revokeObjectURL(a.href),0); toast('✅ HTML 下载完成'); } function testRun(){try{eval(input.value);toast('🧪 测试执行成功')}catch(e){toast('❌ 测试失败:'+e.message)}} /* ---- Collection ---- */ function getColl(){try{return JSON.parse(localStorage.getItem(COLL_KEY)||'[]')}catch(e){return[]}} function setColl(c){localStorage.setItem(COLL_KEY,JSON.stringify(c));renderColl()} let modalIdx=-1; function saveToColl(){ document.getElementById('m-name').value=''; document.getElementById('m-desc').value=''; document.getElementById('m-cat').value='utility'; document.getElementById('m-code').value=input.value; modalIdx=-1; document.getElementById('modal-title').textContent='⭐ 收藏这个书签'; document.getElementById('modal').classList.add('show'); } function openEdit(idx){ const c=getColl()[idx]; document.getElementById('m-name').value=c.name; document.getElementById('m-desc').value=c.desc||''; document.getElementById('m-cat').value=c.cat||'utility'; document.getElementById('m-code').value=c.code; modalIdx=idx; document.getElementById('modal-title').textContent='✏️ 编辑书签'; document.getElementById('modal').classList.add('show'); } function closeModal(){document.getElementById('modal').classList.remove('show')} function confirmModal(){ const name=document.getElementById('m-name').value.trim(); const desc=document.getElementById('m-desc').value.trim(); const cat=document.getElementById('m-cat').value.trim(); const code=document.getElementById('m-code').value; if(!name){toast('❌ 请填写名称');return} const arr=getColl(); if(modalIdx>=0){arr[modalIdx]={name,desc,cat,code,ts:Date.now()}} else{arr.unshift({name,desc,cat,code,ts:Date.now()})} setColl(arr);closeModal();toast('✅ 已保存'); } function runFromColl(i){ const c=getColl()[i]; input.value=c.code;gen();switchTab('gen'); } function delFromColl(i){ if(!confirm('确定删除这个书签?'))return; const arr=getColl();arr.splice(i,1);setColl(arr);toast('✅ 已删除'); } function exportColl(){ const arr=getColl(); if(!arr.length){toast('❌ 还没有收藏');return} const blob=new Blob([JSON.stringify(arr,null,2)],{type:'application/json;charset=utf-8'}); const a=document.createElement('a'); a.href=URL.createObjectURL(blob);a.download='bookmarklets_'+new Date().toISOString().slice(0,10)+'.json';a.click(); setTimeout(()=>URL.revokeObjectURL(a.href),0); toast('✅ 已导出 JSON'); } function importColl(el){ const f=el.files[0];if(!f)return; const r=new FileReader(); r.onload=()=>{ try{ const data=JSON.parse(r.result); if(!Array.isArray(data))throw new Error('不是数组'); const mode=confirm('合并导入点 确定,全部替换点 取消'); let arr=mode?data:getColl(); if(!mode){data.forEach(d=>{if(!arr.some(a=>a.name===d.name))arr.unshift(d)})} setColl(arr);toast('✅ 导入 '+data.length+' 条'); }catch(e){toast('❌ 导入失败:'+e.message)} };r.readAsText(f); } function clearColl(){if(confirm('确定清空全部收藏?')){setColl([]);toast('✅ 已清空')}} function renderColl(){ const arr=getColl(); document.getElementById('coll-count').textContent=arr.length+' 条'; const box=document.getElementById('coll-list'); if(!arr.length){box.innerHTML='
📭

还没有收藏任何 bookmarklet

在生成器里点 ⭐ 收藏 按钮保存

';return} box.innerHTML=arr.map((c,i)=>`
#${i+1}
${c.name}
${(c.desc||'')+' · '+(c.cat||'')}
`).join(''); } /* ---- Library ---- */ const LIB=[ {icon:'🌙',name:'暗色模式',cat:'accessibility',desc:'反转当前页面颜色,任何网站一秒变暗',code:"const h=document.documentElement;const s=h.style;if(h.dataset.dark==='1'){h.dataset.dark='0';s.filter='';s.transition=''}else{h.dataset.dark='1';s.filter='invert(1) hue-rotate(180deg)';s.transition='.3s'}console.log('🌙 dark mode:',h.dataset.dark==='1'?'ON':'OFF')"}, {icon:'🍪',name:'移除 Cookie 弹窗',cat:'cleanup',desc:'尝试删除页面上的 cookie 同意横幅',code:"const sels=['[class*=\"cookie\"]','[id*=\"cookie\"]','[class*=\"consent\"]','[class*=\"gdpr\"]','[class*=\"banner\"]','[class*=\"popup\"]','.cky-consent-container','#onetrust-banner-sdk','.cookie-banner'];let n=0;sels.forEach(s=>document.querySelectorAll(s).forEach(e=>{if(e.offsetHeight>0){e.remove();n++}}));toast?toast('🧹 移除了 '+n+' 个弹窗'):alert('移除了 '+n+' 个元素')"}, {icon:'✏️',name:'编辑任意页面',cat:'dev',desc:'让当前页面所有文字可编辑',code:"document.body.setAttribute('contenteditable','true');document.body.style.outline='2px dashed #ffb454';alert('✏️ 编辑模式已开启');document.addEventListener('click',function(e){if(e.detail===3){document.body.setAttribute('contenteditable','false');document.body.style.outline='';alert('编辑已关闭')}})"}, {icon:'📧',name:'提取邮箱',cat:'extraction',desc:'扫描当前页面所有 email 地址并弹窗显示',code:"const t=document.body.innerText;const r=/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g;const s=new Set(t.match(r)||[]);if(!s.size){alert('❌ 没有找到邮箱');return}alert('📧 找到 '+s.size+' 个邮箱:\\n\\n'+[...s].join('\\n'));const w=window.open();w.document.write('

📧 邮箱列表

'+[...s].join('\\n')+'
');w.document.close()"}, {icon:'🔗',name:'高亮所有链接',cat:'accessibility',desc:'给页面上所有链接加红色边框',code:"let n=0;document.querySelectorAll('a[href]').forEach(a=>{const o=a.dataset.hl;if(o){a.style.outline='';a.dataset.hl='';n--}else{a.style.outline='2px solid #f85149';a.style.outlineOffset='2px';a.dataset.hl='1';n++}});toast?toast(n>=0?'🔗 高亮 '+n+' 个':'🔗 取消高亮'):alert('处理完了')"}, {icon:'📊',name:'字数统计',cat:'analysis',desc:'统计当前页面正文的字数/字符/段落',code:"const t=document.body.innerText.replace(/\\s+$/,'');const words=t.trim()?t.trim().split(/\\s+/).length:0;const chars=t.length;const cn=(t.match(/[\\u4e00-\\u9fa5]/g)||[]).length;const paras=(t.match(/\\n\\s*\\n/g)||[]).length+1;alert('📊 页面统计\\n\\n总字符: '+chars+'\\n英文单词: '+words+'\\n中文字: '+cn+'\\n段落: '+paras)"}, {icon:'🖨️',name:'打印友好',cat:'utility',desc:'隐藏导航栏、侧边栏、广告,只留正文打印',code:"const hide=['nav','header','footer','aside','.sidebar','.nav','.ad','.ads','.advertisement','.cookie','.popup','.comment','.related','.recommend'];hide.forEach(s=>document.querySelectorAll(s).forEach(e=>e.style.display='none'));document.body.style.margin='0 auto';document.body.style.maxWidth='780px';document.body.style.padding='20px';document.body.style.background='#fff';window.print()"}, {icon:'⬆️',name:'回到顶部',cat:'navigation',desc:'一键平滑滚动到页面顶部',code:"window.scrollTo({top:0,behavior:'smooth'})"}, {icon:'🔽',name:'滚到底部',cat:'navigation',desc:'一键平滑滚动到页面底部',code:"window.scrollTo({top:document.body.scrollHeight,behavior:'smooth'})"}, {icon:'📖',name:'阅读器模式',cat:'utility',desc:'自动提取正文,去广告,居中显示',code:"const main=document.querySelector('article,main,.content,.post,.article-body')||document.body;const css='body{margin:0;background:#f5f3ef;color:#2b2b2b;font-size:18px;line-height:1.8;font-family:-apple-system,serif}*:not(main){display:none!important}main{display:block!important;max-width:720px;margin:0 auto;padding:40px 24px!important;background:#fff;border-radius:12px;box-shadow:0 4px 20px rgba(0,0,0,.08)}';const st=document.createElement('style');st.textContent=css;document.head.appendChild(st);document.body.innerHTML='
'+main.innerHTML+'
'"}, {icon:'🔍',name:'查找高亮',cat:'utility',desc:'输入关键词,在页面上全部高亮',code:"const q=prompt('🔍 输入要高亮的关键词:');if(!q)return;const walker=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT);while((n=walker.nextNode())){if(n.textContent.includes(q)&&n.parentNode.tagName!=='SCRIPT'){const r=document.createElement('mark');r.style.background='#fbbf24';r.style.padding='0 2px';r.textContent=q;n.parentNode.replaceChild(r,n);const walker2=document.createTreeWalker(document.body,NodeFilter.SHOW_TEXT);while((w=walker2.nextNode())&&w!==n){}break}else{}}}"}, {icon:'🖼️',name:'图片下载列表',cat:'extraction',desc:'列出当前页面所有图片链接',code:"const imgs=[...new Set([...document.images].map(i=>i.currentSrc||i.src))].filter(Boolean);if(!imgs.length){alert('❌ 没有图片');return}const w=window.open();w.document.write('

🖼️ 图片列表 ('+imgs.length+')

');imgs.forEach(u=>w.document.write('

'+u+'
'));w.document.close()"}, {icon:'🛑',name:'杀进程',cat:'utility',desc:'瞬间关闭所有 setTimeout/setInterval/requestAnimationFrame',code:"let k=0;for(let i=1;i<99999;i++){clearTimeout(i);clearInterval(i);cancelAnimationFrame(i);k++}alert('🛑 已清理 '+k+' 个定时器')"}, {icon:'🎨',name:'随机背景色',cat:'utility',desc:'给当前页面随机换一个背景色',code:"const c='#'+Math.floor(Math.random()*0xFFFFFF).toString(16).padStart(6,'0');document.body.style.background=c;document.body.style.color='#fff';document.body.style.transition='.4s';toast?toast('🎨 '+c):alert('🎨 背景色: '+c)"}, {icon:'📱',name:'模拟手机',cat:'utility',desc:'把页面缩到 iPhone 宽度方便看响应式',code:"const overlay=document.createElement('div');overlay.style.cssText='position:fixed;inset:0;background:rgba(0,0,0,.85);z-index:999999;display:flex;align-items:center;justify-content:center';overlay.innerHTML='';overlay.querySelector('button').onclick=()=>overlay.remove();document.body.appendChild(overlay)"}, {icon:'🔐',name:'显示密码',cat:'utility',desc:'把页面上所有密码框的类型改成 text(显示明文)',code:"const ps=document.querySelectorAll('input[type=password]');let n=0;ps.forEach(p=>{p.type='text';p.style.background='#fef3c7';n++});toast?toast('🔐 显示了 '+n+' 个密码'):alert('显示了 '+n+' 个密码')"}, {icon:'📐',name:'页面标尺',cat:'utility',desc:'显示页面鼠标位置的 X/Y 坐标',code:"const box=document.createElement('div');box.style.cssText='position:fixed;top:8px;right:8px;background:#000;color:#0f0;padding:6px 10px;border-radius:6px;font-family:monospace;font-size:12px;z-index:999999;pointer-events:none';document.body.appendChild(box);document.addEventListener('mousemove',e=>{box.textContent='X:'+e.clientX+' Y:'+e.clientY});document.addEventListener('click',()=>box.remove(),{once:true})"}, {icon:'🎲',name:'随机跳转',cat:'navigation',desc:'从当前页面所有链接里随机打开一个',code:"const links=[...document.querySelectorAll('a[href]')].map(a=>a.href).filter(h=>h.startsWith('http'));if(!links.length){alert('❌ 没有链接');return}const url=links[Math.floor(Math.random()*links.length)];location.href=url"}, {icon:'📝',name:'一键翻译',cat:'utility',desc:'在新标签页用 Google Translate 打开当前页面',code:"window.open('https://translate.google.com/translate?sl=auto&tl=zh-CN&u='+encodeURIComponent(location.href),'_blank')"}, {icon:'💾',name:'保存页面 PDF',cat:'utility',desc:'自动打开打印对话框',code:"window.print()"}, ]; const libGrid=document.getElementById('lib-grid'); let libFilter='all',libSearch=''; function renderLib(){ const arr=LIB.filter(b=>libFilter==='all'||b.cat===libFilter).filter(b=>!libSearch||b.name.toLowerCase().includes(libSearch.toLowerCase())); libGrid.innerHTML=arr.map((b,i)=>`
使用 ↵
${b.icon}
${b.cat}

${b.name}

${b.desc}

${b.code.substring(0,70)}${b.code.length>70?'…':''}
`).join(''); libGrid.querySelectorAll('.lib-card').forEach(card=>{ card.onclick=()=>{ input.value=LIB[+card.dataset.i].code; gen();switchTab('gen');toast('✅ 已载入预设:'+LIB[+card.dataset.i].name); }; }); } document.querySelectorAll('.filter-bar button[data-cat]').forEach(b=>b.onclick=()=>{document.querySelectorAll('.filter-bar button[data-cat]').forEach(x=>x.classList.remove('active'));b.classList.add('active');libFilter=b.dataset.cat;renderLib()}); document.getElementById('lib-search').oninput=e=>{libSearch=e.target.value;renderLib()}; /* ---- Tabs ---- */ function switchTab(id){ document.querySelectorAll('.view').forEach(v=>v.classList.remove('active')); document.querySelectorAll('nav button').forEach(b=>b.classList.remove('active')); document.getElementById(id).classList.add('active'); document.querySelector('nav button[data-tab="'+id+'"]').classList.add('active'); if(id==='coll')renderColl(); } document.querySelectorAll('nav button').forEach(b=>b.onclick=()=>switchTab(b.dataset.tab)); /* ---- Toast ---- */ let toastTimer; function toast(msg){ const t=document.getElementById('toast'); t.textContent=msg;t.classList.add('show'); clearTimeout(toastTimer); toastTimer=setTimeout(()=>t.classList.remove('show'),2000); } /* ---- Share ---- */ function share(){ const url=location.origin+location.pathname; if(navigator.share){navigator.share({title:'Bookmarklet Forge',url})} else{navigator.clipboard.writeText(url).then(()=>toast('✅ 链接已复制:'+url))} } /* ---- Init ---- */ gen();renderLib(); // expose toast globally for presets that call it window.toast=toast;