Robust search for raw content on GitHub with Turbo support
// ==UserScript==
// @name GitHub Deep Raw Search (Fixed)
// @namespace http://tampermonkey.net
// @version 7.2
// @description Robust search for raw content on GitHub with Turbo support
// @author Assistant
// @match https://github.com*
// @grant none
// ==/UserScript==
(function() {
'use strict';
function injectSearch() {
// Find the file header using multiple common selectors
const target = document.querySelector('[data-testid="file-header"]') ||
document.querySelector('.Box-header') ||
document.querySelector('.file-header');
if (!target || document.getElementById('raw-search-box')) return;
const container = document.createElement('div');
container.id = 'raw-search-box';
container.style = 'padding: 10px; background: #161b22; border: 1px solid #30363d; border-radius: 6px; margin: 8px 0; display: flex; gap: 8px; align-items: center;';
const input = document.createElement('input');
input.placeholder = 'Type word and press Enter...';
input.style = 'flex-grow: 1; padding: 4px 10px; background: #0d1117; border: 1px solid #30363d; color: #c9d1d9; border-radius: 4px; font-size: 13px;';
const status = document.createElement('span');
status.style = 'color: #8b949e; font-size: 12px; min-width: 80px;';
status.innerText = 'Ready';
container.append(input, status);
target.after(container);
input.onkeydown = async (e) => {
if (e.key !== 'Enter') return;
const query = input.value.trim().toLowerCase();
if (!query) return;
status.innerText = 'Searching...';
const rawUrl = window.location.href.replace('/blob/', '/raw/');
try {
const res = await fetch(rawUrl);
const text = await res.text();
const lines = text.split('\n');
const count = lines.filter(l => l.toLowerCase().includes(query)).length;
status.innerText = `${count} matches`;
} catch (err) {
status.innerText = 'Error';
}
};
}
// Use MutationObserver to detect when GitHub finishes rendering the file view
const observer = new MutationObserver(() => injectSearch());
observer.observe(document.body, { childList: true, subtree: true });
// Initial run
injectSearch();
})();