├── .DS_Store
├── figure
├── logo.png
├── logo1.png
├── result.png
└── instruction.jpg
├── LICENSE
├── README-ZH.md
├── README.md
└── Overleaf-Bib-Helper.js
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLNLP-World/Overleaf-Bib-Helper/HEAD/.DS_Store
--------------------------------------------------------------------------------
/figure/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLNLP-World/Overleaf-Bib-Helper/HEAD/figure/logo.png
--------------------------------------------------------------------------------
/figure/logo1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLNLP-World/Overleaf-Bib-Helper/HEAD/figure/logo1.png
--------------------------------------------------------------------------------
/figure/result.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLNLP-World/Overleaf-Bib-Helper/HEAD/figure/result.png
--------------------------------------------------------------------------------
/figure/instruction.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MLNLP-World/Overleaf-Bib-Helper/HEAD/figure/instruction.jpg
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025 Xunjian Yin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README-ZH.md:
--------------------------------------------------------------------------------
1 |
7 | A UserScript to enhance Overleaf by allowing article searches and BibTeX retrieval from DBLP and Google Scholar directly within the Overleaf editor.
8 |
53 |
54 |
55 |
56 |
57 | ## Motivation
58 | Writing LaTeX documents often requires including numerous academic references. Manually searching for and formatting BibTeX entries can be time-consuming. Overleaf-Bib-Helper streamlines this process by integrating search functionality from DBLP and Google Scholar right into the Overleaf interface, allowing users to quickly find and copy BibTeX entries with minimal effort.
59 |
60 | ## Features
61 | - Search for academic articles from DBLP or Google Scholar within Overleaf.
62 | - Retrieve and copy BibTeX entries with a single click.
63 | - Configurable result counts (5, 10, 20, or 50 results).
64 | - Scrollable results list for easy browsing.
65 | - Keyboard shortcuts: Enter to search, Esc to close the popup.
66 | - Supports multiple Google Scholar mirrors for accessibility.
67 |
68 | ## Changelog
69 | - **2025-04-14**: Added support for advanced search options in Google Scholar (v1.3).
70 | - **2025-04-10**: Added support for cn.overleaf.com and cn.overleaf.com domains (v1.2).
71 | - **2025-04-09**: Initial release with basic functionality for DBLP and Google Scholar (v1.1).
72 |
73 |
74 | ## Installation
75 | ### Step 1: Install Tampermonkey
76 | Tampermonkey is a browser extension required to run UserScripts like Overleaf-Bib-Helper. Follow these steps:
77 | 1. **Download Tampermonkey**:
78 | - **Chrome**: [Chrome Web Store](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo)
79 | - **Firefox**: [Mozilla Add-ons](https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/)
80 | - **Edge**: [Microsoft Edge Add-ons](https://microsoftedge.microsoft.com/addons/detail/%E7%AF%A1%E6%94%B9%E7%8C%B4/iikmkjmpaadaobahmlepeloendndfphd)
81 | - **Safari**: [App Store](https://apps.apple.com/us/app/tampermonkey/id1482490089) (requires macOS)
82 | 2. **Enable Tampermonkey**:
83 | - After installation, click the Tampermonkey icon in your browser’s toolbar and ensure it’s enabled.
84 | - Note:
85 | 3. **Enable Developer Mode for the Extension**:
86 | - For Chrome, go to the extensions page (`chrome://extensions/`) and enable Developer mode.
87 |
88 | ### Step 2: Install Overleaf-Bib-Helper
89 | You can install the script in one of two ways:
90 |
91 | #### Option 1: Install from Greasy Fork (Recommended)
92 | 1. Visit the [Greasy Fork page](https://greasyfork.org/zh-CN/scripts/532304-overleaf-bib-helper).
93 | 2. Click the **"Install this script"** button.
94 | 3. Tampermonkey will open a confirmation window. Click **"Install"** to add the script.
95 | 4. The script will automatically activate on Overleaf project pages (`https://www.overleaf.com/project/*`).
96 | 5. To keep the script updated, enable auto-updates in Tampermonkey settings.
97 |
98 | #### Option 2: Install from GitHub
99 | 1. Go to the [GitHub repository](https://github.com/MLNLP-World/Overleaf-Bib-Helper).
100 | 2. Open the `Overleaf-Bib-Helper.js` file in the repository.
101 | 3. Copy the entire script content.
102 | 4. In your browser, click the Tampermonkey icon > **"Create a new script"**.
103 | 5. Paste the copied code into the editor, replacing the default template.
104 | 6. Click **File > Save** in the Tampermonkey editor.
105 | 7. The script will be active on Overleaf project pages.
106 | 8. **Note:** For manual installations from GitHub, please check the repository periodically for updates and reinstall as needed.
107 |
108 | ## Usage
109 | ### Opening the Tool
110 | 1. Open an Overleaf project in your browser (`https://www.overleaf.com/project/*`).
111 | 2. Look for a new icon in the Overleaf toolbar (a small document-like icon).
112 | 3. Click the icon to open the search popup.
113 |
114 |
115 |
116 |
117 |
118 | ### Searching for Articles
119 | 1. **Enter a Query**: Type your search term (e.g., article title, author, or keywords) into the input field.
120 | 2. **Select Source**: Choose "DBLP" or "Google Scholar" from the "Source" dropdown.
121 | - **DBLP**: Best for computer science literature with structured data.
122 | - **Google Scholar**: Broader coverage across various fields but may require CAPTCHA verification.
123 | 3. **Set Result Count**: Select 5, 10, 20, or 50 results from the "Results" dropdown.
124 | 4. **Start Search**:
125 | - Press the **Enter** key or click the magnifying glass icon.
126 | 5. Results will appear in a scrollable list below the input field.
127 |
128 | ### Copying BibTeX
129 | 1. Click on any result in the list (e.g., "Title@Author").
130 | 2. The BibTeX entry will be copied to your clipboard.
131 | 3. A notification will confirm success ("Copy successfully") or report an error ("Copy failed").
132 |
133 |
134 |
135 |
136 |
137 | ### Closing the Popup
138 | - Press **Esc** or click the toolbar icon again.
139 |
140 | ## Supported Sources
141 | - **DBLP**: A comprehensive computer science bibliography providing reliable BibTeX entries.
142 | - **Google Scholar**: A broader academic search engine that may include more recent or interdisciplinary works but might require user verification (e.g., CAPTCHA).
143 |
144 | ## Troubleshooting
145 | - **Script Not Working?**
146 | - Ensure your browser has **developer mode** enabled for extensions.
147 | - Ensure Tampermonkey is enabled and the script is active.
148 | - Verify you’re on an Overleaf project page.
149 | - Reload or reinstall from Greasy Fork.
150 | - **No Results?**
151 | - Check your query for typos.
152 | - Ensure you have granted the plugin search permissions.
153 | - Try switching between DBLP and Google Scholar.
154 | - **Google Scholar Issues?**
155 | - If CAPTCHA blocks access, complete it in the opened tab and retry.
156 |
157 | ## Disclaimer
158 | While Overleaf-Bib-Helper aims to provide a seamless experience, please note that it relies on external services (DBLP and Google Scholar) which may change their APIs or require user verification (e.g., CAPTCHA). Use this tool at your own discretion and always verify retrieved BibTeX entries before including them in your documents.
159 |
160 |
161 | ## License
162 | This project is licensed under the MIT License - see [LICENSE.md](https://github.com/MLNLP-World/Overleaf-Bib-Helper/blob/main/LICENSE.md) for details.
163 |
164 | ## Contributing
165 | Feel free to fork the [GitHub repository](https://github.com/MLNLP-World/Overleaf-Bib-Helper), submit issues, or create pull requests with improvements!
166 |
167 | ## Contact
168 | Please email [Xunjian Yin](mailto:xjyin@pku.edu.cn) or create Github issues here if you have any questions or suggestions.
169 |
170 | ## Organizers
171 |
172 |
173 | ## Contributors
174 |
175 |
176 |
177 |
178 | ## Acknowledgments
179 | Inspired by similar tools and the academic community’s need for efficient reference management.
180 |
181 |
--------------------------------------------------------------------------------
/Overleaf-Bib-Helper.js:
--------------------------------------------------------------------------------
1 | // ==UserScript==
2 | // @name Overleaf-Bib-Helper
3 | // @namespace com.Xunjian.overleaf
4 | // @version 1.3
5 | // @description Enhances Overleaf by allowing article searches and BibTeX retrieval from DBLP and Google Scholar
6 | // @author Xunjian Yin
7 | // @match https://www.overleaf.com/project/*
8 | // @match https://cn.overleaf.com/project*
9 | // @match https://latex.pku.edu.cn/project/*
10 | // @icon https://www.overleaf.com/favicon.ico
11 | // @require https://cdn.jsdelivr.net/npm/@floating-ui/core@1.6.8
12 | // @require https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.6.12
13 | // @require https://cdn.jsdelivr.net/npm/simple-notify@1.0.6/dist/simple-notify.min.js
14 | // @resource notifycss https://cdn.jsdelivr.net/npm/simple-notify/dist/simple-notify.css
15 | // @grant GM_setClipboard
16 | // @grant GM_xmlhttpRequest
17 | // @grant GM_getResourceText
18 | // @grant GM_addStyle
19 | // @grant GM_setValue
20 | // @grant GM_getValue
21 | // @grant GM_openInTab
22 | // @license MIT
23 | // ==/UserScript==
24 |
25 | (function () {
26 | 'use strict';
27 | GM_addStyle(GM_getResourceText('notifycss'));
28 | injectScript();
29 | setInterval(() => {
30 | if (!document.getElementById('toggleIcon')) {
31 | injectScript();
32 | }
33 | }, 2000);
34 | })();
35 |
36 | function injectScript() {
37 | waitUtil('div.ol-cm-toolbar-button-group.ol-cm-toolbar-end', el => {
38 | let iconBox = createToggleIcon();
39 | el.appendChild(iconBox);
40 |
41 | let popupBox = createBox();
42 | let oldPopup = document.querySelector("#popup");
43 | if (oldPopup) {
44 | popupBox = oldPopup;
45 | }
46 |
47 | document.body.appendChild(popupBox);
48 | FloatingUIDOM.autoUpdate(iconBox, popupBox, () => {
49 | FloatingUIDOM.computePosition(iconBox, popupBox, {
50 | middleware: [FloatingUICore.shift(), FloatingUICore.flip(), FloatingUICore.offset(6)],
51 | }).then(({ x, y }) => {
52 | Object.assign(popupBox.style, {
53 | top: `${y}px`,
54 | left: `${x}px`
55 | });
56 | });
57 | });
58 |
59 | iconBox.onclick = () => {
60 | togglePopup(popupBox);
61 | };
62 |
63 | let searchIcon = document.getElementById('search-word');
64 | let searchInput = document.querySelector('.search-input');
65 | searchIcon.onclick = () => {
66 | queryArticle();
67 | };
68 | searchInput.onkeydown = (env) => {
69 | if (env.key === 'Enter') {
70 | queryArticle();
71 | }
72 | };
73 |
74 | // Global Esc key listener
75 | document.onkeydown = (env) => {
76 | if (env.key === 'Escape' && showBox) {
77 | togglePopup(popupBox);
78 | }
79 | };
80 |
81 | let content = document.getElementById("search-content");
82 | content.onclick = (env) => {
83 | if (env.target.className == 'scholar-data') {
84 | let source = document.getElementById("source").value;
85 | let id = env.target.getAttribute("data-cid");
86 | if (source === "DBLP") {
87 | getBibTexDBLP(id).then(bib => {
88 | new Notify({
89 | status: 'success',
90 | title: 'Copy successfully',
91 | text: 'Bib has been copied to clipboard',
92 | effect: 'slide',
93 | type: 'filled'
94 | });
95 | GM_setClipboard(bib);
96 | }).catch(_ => {
97 | new Notify({
98 | status: 'error',
99 | title: "Copy failed",
100 | text: "Failed to get BibTeX from DBLP",
101 | effect: "slide",
102 | type: "filled"
103 | });
104 | });
105 | } else if (source === "GoogleScholar") {
106 | getBibTexGoogleScholar(id).then(bib => {
107 | new Notify({
108 | status: 'success',
109 | title: 'Copy successfully',
110 | text: 'Bib has been copied to clipboard',
111 | effect: 'slide',
112 | type: 'filled'
113 | });
114 | GM_setClipboard(bib);
115 | }).catch(_ => {
116 | new Notify({
117 | status: 'error',
118 | title: "Copy failed",
119 | text: "Failed to get BibTeX from Google Scholar",
120 | effect: "slide",
121 | type: "filled"
122 | });
123 | });
124 | }
125 | }
126 | };
127 | });
128 | }
129 |
130 | function togglePopup(popupBox) {
131 | showBox = !showBox;
132 | popupBox.style.display = showBox ? 'block' : 'none';
133 | if (showBox) {
134 | document.querySelector('.search-input').focus(); // Optional: Focus input when popup opens
135 | }
136 | }
137 |
138 | function queryArticle() {
139 | let content = document.getElementById("search-content");
140 | content.innerHTML = "Loading......";
141 | let word = document.querySelector('input.search-input').value;
142 | let source = document.getElementById("source").value;
143 | let resultCount = document.getElementById("resultCount").value;
144 | if (source === "DBLP") {
145 | getArticleIDListDBLP(word, resultCount).then(lists => {
146 | if (lists.length === 0) {
147 | content.innerHTML = "No articles found.";
148 | throw new Error("No articles found");
149 | }
150 | let searchText = "";
151 | lists.forEach(article => {
152 | searchText += scholarContent(`${article.title}@${article.author}`, article.url);
153 | });
154 | content.innerHTML = searchText;
155 | }).catch(err => {
156 | console.log("Error:", err);
157 | if (content.innerHTML !== "No articles found.") {
158 | content.innerHTML = "Failed to load articles.";
159 | }
160 | new Notify({
161 | status: 'error',
162 | title: 'Request failed',
163 | text: 'Please check your query or try again later.',
164 | effect: 'slide',
165 | type: 'filled'
166 | });
167 | });
168 | } else if (source === "GoogleScholar") {
169 | let yearFrom = document.getElementById("yearFrom").value;
170 | let yearTo = document.getElementById("yearTo").value;
171 | let sortBy = document.getElementById("sortBy").value;
172 | getArticleIDListGoogleScholar(word, resultCount, yearFrom, yearTo, sortBy).then(lists => {
173 | if (lists.length === 0) {
174 | content.innerHTML = "No articles found.";
175 | throw new Error("No articles found");
176 | }
177 | let searchText = "";
178 | lists.forEach(article => {
179 | searchText += scholarContent(`${article.title}@${article.author}`, article.id);
180 | });
181 | content.innerHTML = searchText;
182 | }).catch(err => {
183 | console.log("Error:", err);
184 | if (content.innerHTML !== "No articles found.") {
185 | content.innerHTML = "Failed to load articles.";
186 | }
187 | new Notify({
188 | status: 'error',
189 | title: 'Request failed',
190 | text: 'Please check your query or try again later.',
191 | effect: 'slide',
192 | type: 'filled'
193 | });
194 | });
195 | }
196 | }
197 |
198 | function waitUtil(el, callback, timeout = 6000) {
199 | let query = setInterval(() => {
200 | let target = document.querySelector(el);
201 | if (target) {
202 | clearInterval(query);
203 | callback(target);
204 | }
205 | });
206 | setTimeout(() => {
207 | clearInterval(query);
208 | }, timeout);
209 | }
210 |
211 | function createToggleIcon() {
212 | let iconBox = document.createElement('div');
213 | iconBox.className = 'ol-cm-toolbar-button';
214 | iconBox.style.display = 'flex';
215 | iconBox.style.justifyContent = 'center';
216 | iconBox.style.alignItems = 'center';
217 | iconBox.id = "toggleIcon";
218 | iconBox.innerHTML = '';
219 | return iconBox;
220 | }
221 |
222 | function createBox() {
223 | let box = document.createElement('div');
224 | box.id = "popup";
225 | box.style = 'width:300px;background:#eef;padding:10px;border:1px solid #ccc;border-radius:5px;position:absolute;display:none;top:0px;left:0px';
226 | box.innerHTML = `
227 |
297 |