您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a floating "NASA ADS" button to IOP/AAS article pages, robustly extracting DOI even for /pdf URLs
// ==UserScript== // @name NASA ADS Link on AAS/IOP pages (Robust DOI extraction) // @namespace http://tampermonkey.net/ // @version 0.3 // @description Adds a floating "NASA ADS" button to IOP/AAS article pages, robustly extracting DOI even for /pdf URLs // @match https://iopscience.iop.org/article/* // @license MIT // ==/UserScript== (function() { 'use strict'; const stopSegments = new Set(['pdf','abstract','full','epub','supp','supplementary','figures','references','full-text','text','download']); function cleanCandidate(c){ if(!c) return null; c = c.split(/[?#]/)[0]; // strip query/hash c = c.replace(/\/+$/,''); // strip trailing slashes return c; } function doiFromMeta(){ const selectors = [ 'meta[name="citation_doi"]', 'meta[name="dc.Identifier"]', 'meta[name="DC.Identifier"]', 'meta[name="dc.identifier"]', 'meta[name="DOI"]', 'meta[property="og:doi"]' ]; for(const sel of selectors){ const m = document.querySelector(sel); if(m && m.content) return cleanCandidate(m.content); } // fallback: canonical link may contain DOI const canonical = document.querySelector('link[rel="canonical"]'); if(canonical && canonical.href){ const match = canonical.href.match(/10\.\d{4,9}\/[-._;()\/:A-Z0-9]+/i); if(match) return cleanCandidate(match[0]); } return null; } function doiFromLinks(){ const a = document.querySelector('a[href*="doi.org"], a[href*="/doi/"], a[href*="/article/10."]'); if(a){ const href = a.href; const match = href.match(/10\.\d{4,9}\/[-._;()\/:A-Z0-9]+/i); if(match) return cleanCandidate(match[0]); } return null; } function doiFromPath(path){ if(!path) return null; const parts = path.split('/').filter(Boolean); // find 'article' segment OR first segment that starts with '10.' let idx = parts.indexOf('article'); if(idx === -1) idx = parts.findIndex(p => p.startsWith('10.')); if(idx === -1) return null; const start = (parts[idx] === 'article') ? idx + 1 : idx; if(start >= parts.length) return null; const out = []; for(let i = start; i < parts.length; i++){ const seg = parts[i]; if(stopSegments.has(seg.toLowerCase())) break; out.push(seg); } if(out.length === 0) return null; const candidate = out.join('/'); return (/10\.\d{4,9}\/\S+/.test(candidate)) ? cleanCandidate(candidate) : null; } function doiFromReferrer(){ try{ const ref = document.referrer; if(ref){ const url = new URL(ref); const doi = doiFromPath(url.pathname) || (ref.match(/10\.\d{4,9}\/[-._;()\/:A-Z0-9]+/i) || [])[0]; if(doi) return cleanCandidate(doi); } }catch(e){} return null; } // try sources in order of reliability let doi = null; try { doi = doiFromMeta() || doiFromLinks() || doiFromPath(window.location.pathname) || doiFromReferrer(); } catch(e) { console.error('DOI extraction error', e); } if(!doi) return; // nothing we can do const adsUrl = `https://ui.adsabs.harvard.edu/abs/${doi}/abstract`; // floating button (bottom-right) const btn = document.createElement('a'); btn.href = adsUrl; btn.target = '_blank'; btn.rel = 'noopener noreferrer'; btn.textContent = 'NASA ADS'; Object.assign(btn.style, { position: 'fixed', bottom: '20px', right: '20px', backgroundColor: '#003366', color: '#fff', padding: '10px 14px', borderRadius: '8px', textDecoration: 'none', fontWeight: '600', zIndex: '2147483647', boxShadow: '0 4px 12px rgba(0,0,0,0.25)', fontFamily: 'system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial', cursor: 'pointer', }); btn.addEventListener('mouseenter', ()=> btn.style.transform = 'translateY(-2px)'); btn.addEventListener('mouseleave', ()=> btn.style.transform = 'translateY(0)'); document.body.appendChild(btn); })();