Skip to content

Instantly share code, notes, and snippets.

@Pamblam
Last active July 3, 2025 16:08
Show Gist options
  • Select an option

  • Save Pamblam/ec8cb13162f148559a4d0ae463cd7f2d to your computer and use it in GitHub Desktop.

Select an option

Save Pamblam/ec8cb13162f148559a4d0ae463cd7f2d to your computer and use it in GitHub Desktop.
Search source code of a webpage, including it's linked stylesheets and scripts.
/**
* Search the source code of the current web page.
* @param {string} needle - The string to find
* @param {string} all|js|css - the type of source code to search
* @param {boolean} caseMatch - Is search case sensitive?
* @returns {array} - An array of objects that represent matches.
*
* Usage: Paste this script into the DevTools and run it to attach
* the function to the window. Run the method, indicating the string
* you're looking for, whether you want to search the page's CSS,
* JavascScript, or Everything, and whether or not to do a case-
* sensitive search. Log the results.
*
* Example:
* shallowSourceSearch('myString', 'js', true).then(matches=>{
* console.clear();
* console.log(matches);
* });
*/
if(!window.shallowSourceSearch){
window.shallowSourceSearch = async (needle, type = 'all', caseMatch = false) => {
let matches = [], files = [];
if (!caseMatch) needle = needle.toLowerCase();
const trimContext = (context, pos, len) => {
context = context.replaceAll('\\t', "\t");
context = context.replaceAll('\\n', "\n");
let start = Math.max(0, pos-50);
let end = Math.min(pos+len+50, context.length);
return context.substring(start, end);
};
const isSameOrigin = (url) => {
const pageLocation = window.location;
const resolvedUrl = new URL(url, pageLocation.href);
return (
resolvedUrl.protocol === pageLocation.protocol &&
resolvedUrl.hostname === pageLocation.hostname &&
resolvedUrl.port === pageLocation.port
);
}
const searchFile = async path => {
if(!isSameOrigin(path)) return;
try {
let source = await fetch(path).then(r => r.text());
if (!caseMatch) source = source.toLowerCase();
for (let lines = source.split("\n"), i = lines.length; i--;) {
let offset = lines[i].indexOf(needle);
while (offset > -1) {
matches.push({
type: 'file',
file: path,
line: i,
position: offset,
context: trimContext(lines[i], offset, needle.length)
});
offset = lines[i].indexOf(needle, offset+1);
}
}
} catch (e) {}
};
const searchInlineStyles = () => document.querySelectorAll('*').forEach(ele=>{
if(ele.tagName === 'STYLE'){
let source = ele.textContent
if (!caseMatch) source = source.toLowerCase();
for (let lines = source.split("\n"), i = lines.length; i--;) {
let offset = lines[i].indexOf(needle);
while(offset > -1){
matches.push({
type: 'element',
element: ele,
line: i,
position: offset,
context: trimContext(lines[i], offset, needle.length)
});
offset = lines[i].indexOf(needle, offset+1);
}
}
}
if(ele.hasAttribute('style')){
let source = ele.getAttribute('style');
if (!caseMatch) source = source.toLowerCase();
let offset = source.indexOf(needle);
while(offset > -1){
matches.push({
type: 'inline',
element: ele,
attribute: 'style',
position: offset,
context: trimContext(source, offset, needle.length)
});
offset = source.indexOf(needle, offset+1);
}
}
});
const searchInlineScripts = () => document.querySelectorAll('*').forEach(ele=>{
if(ele.tagName === 'SCRIPT'){
let source = ele.textContent
if (!caseMatch) source = source.toLowerCase();
for (let lines = source.split("\n"), i = lines.length; i--;) {
let offset = lines[i].indexOf(needle);
while(offset > -1){
matches.push({
type: 'element',
element: ele,
line: i,
position: offset,
context: trimContext(lines[i], offset, needle.length)
});
offset = lines[i].indexOf(needle, offset+1);
}
}
}
let attributes = [...ele.attributes];
for(let i=attributes.length; i--;){
if(attributes[i].name.indexOf('on') !== 0) continue;
let source = attributes[i].value;
if (!caseMatch) source = source.toLowerCase();
let offset = source.indexOf(needle);
while(offset > -1){
matches.push({
type: 'inline',
element: ele,
attribute: attributes[i].name,
position: offset,
context: trimContext(source, offset, needle.length)
});
offset = source.indexOf(needle, offset+1);
}
}
});
if(type === 'all'){
files.push(location.href);
let links = [...document.querySelectorAll('link')].map(l => l.href).filter(l => !!l);
let scripts = [...document.querySelectorAll('script')].map(s => s.src).filter(s => !!s);
files.push(...links, ...scripts);
}
if(type === 'css'){
searchInlineStyles();
let links = [...document.querySelectorAll('link')].map(l => l.href).filter(l => !!l);
files.push(...links);
}
if(type === 'js'){
searchInlineScripts();
let scripts = [...document.querySelectorAll('script')].map(s => s.src).filter(s => !!s);
files.push(...scripts);
}
await Promise.all(files.map(path => searchFile(path)));
return matches;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment