1. Page introspection bookmarklet (static snapshot)
Captures a full snapshot of the current page: URL, title, scripts, links, preconnects, anchors,
ARIA roles/labels, elements with IDs, modal heuristics, navigation relations, and resource timing.
Outputs a JSON blob into a new window.
1.1. Ready-to-use bookmarklet (single line)
Use this as the URL for a bookmark.
javascript:(function(){try{var d=document,w=window;function gAll(s){return Array.prototype.slice.call(d.querySelectorAll(s));}function mapNodes(nodes,fn){return nodes.map(function(n){try{return fn(n);}catch(e){return {error:e+''};}});}var perfRes=[];try{if(w.performance&&w.performance.getEntriesByType){perfRes=w.performance.getEntriesByType('resource').map(function(e){return{name:e.name,initiatorType:e.initiatorType,entryType:e.entryType,transferSize:e.transferSize,encodedBodySize:e.encodedBodySize,decodedBodySize:e.decodedBodySize,startTime:e.startTime,duration:e.duration};});}}catch(e){}var data={page:{url:w.location.href,title:d.title,referrer:d.referrer},scripts:mapNodes(gAll('script'),function(s){return{src:s.src||null,inline:!s.src&&s.textContent? (s.textContent.trim().slice(0,2000)) : null,type:s.type||null,async:!!s.async,defer:!!s.defer,crossorigin:s.getAttribute('crossorigin'),nonce:s.getAttribute('nonce'),id:s.id||null};}),links:mapNodes(gAll('link'),function(l){return{rel:l.rel||null,href:l.href||null,as:l.getAttribute('as'),crossorigin:l.getAttribute('crossorigin'),type:l.type||null,media:l.media||null,referrerpolicy:l.referrerPolicy||null,fetchpriority:l.getAttribute('fetchpriority')};}),anchors:mapNodes(gAll('a[href]'),function(a){return{href:a.href,text:(a.textContent||'').trim().slice(0,200),rel:a.rel||null,role:a.getAttribute('role'),ariaLabel:a.getAttribute('aria-label'),ariaLabelledby:a.getAttribute('aria-labelledby'),id:a.id||null};}),elementsWithId:mapNodes(gAll('[id]'),function(el){return{tag:el.tagName.toLowerCase(),id:el.id,classes:el.className||null,role:el.getAttribute('role'),ariaLabel:el.getAttribute('aria-label'),ariaLabelledby:el.getAttribute('aria-labelledby')};}),ariaElements:mapNodes(gAll('[role],[aria-label],[aria-labelledby],[aria-hidden],[aria-modal]'),function(el){return{tag:el.tagName.toLowerCase(),id:el.id||null,classes:el.className||null,role:el.getAttribute('role'),ariaLabel:el.getAttribute('aria-label'),ariaLabelledby:el.getAttribute('aria-labelledby'),ariaHidden:el.getAttribute('aria-hidden'),ariaModal:el.getAttribute('aria-modal')};}),modals:mapNodes(gAll('[role="dialog"],[role="alertdialog"],[aria-modal="true"],.modal,[data-modal],[data-dialog]'),function(el){return{tag:el.tagName.toLowerCase(),id:el.id||null,classes:el.className||null,role:el.getAttribute('role'),ariaModal:el.getAttribute('aria-modal'),ariaLabel:el.getAttribute('aria-label'),ariaLabelledby:el.getAttribute('aria-labelledby')};}),navRelations:mapNodes(gAll('link[rel]'),function(l){return{rel:l.rel,href:l.href||null,as:l.getAttribute('as'),type:l.type||null,media:l.media||null};}),resources:perfRes};var win=w.open('about:blank','_blank');if(!win){alert('Popup blocked: please allow popups for this site.');return;}var pre=win.document.createElement('pre');pre.textContent=JSON.stringify(data,null,2);win.document.body.appendChild(pre);win.document.title='Page inspection snapshot';}catch(e){alert('Error in bookmarklet: '+e);}})();
1.2. Readable version (for editing / extension)
javascript:(function () {
try {
var d = document;
var w = window;
function gAll(sel) {
return Array.prototype.slice.call(d.querySelectorAll(sel));
}
function mapNodes(nodes, fn) {
return nodes.map(function (n) {
try { return fn(n); }
catch (e) { return { error: String(e) }; }
});
}
// Resource timing: subresources & initiator types
var perfResources = [];
try {
if (w.performance && w.performance.getEntriesByType) {
perfResources = w.performance.getEntriesByType('resource').map(function (e) {
return {
name: e.name,
initiatorType: e.initiatorType,
entryType: e.entryType,
transferSize: e.transferSize,
encodedBodySize: e.encodedBodySize,
decodedBodySize: e.decodedBodySize,
startTime: e.startTime,
duration: e.duration
};
});
}
} catch (e) {}
var data = {
page: {
url: w.location.href,
title: d.title,
referrer: d.referrer
},
// <script> tags
scripts: mapNodes(gAll('script'), function (s) {
return {
src: s.src || null,
inline: !s.src && s.textContent
? s.textContent.trim().slice(0, 2000)
: null,
type: s.type || null,
async: !!s.async,
defer: !!s.defer,
crossorigin: s.getAttribute('crossorigin'),
nonce: s.getAttribute('nonce'),
id: s.id || null
};
}),
// <link> tags, including preconnect/preload/prefetch etc.
links: mapNodes(gAll('link'), function (l) {
return {
rel: l.rel || null,
href: l.href || null,
as: l.getAttribute('as'),
crossorigin: l.getAttribute('crossorigin'),
type: l.type || null,
media: l.media || null,
referrerpolicy: l.referrerPolicy || null,
fetchpriority: l.getAttribute('fetchpriority')
};
}),
// All anchors with href
anchors: mapNodes(gAll('a[href]'), function (a) {
return {
href: a.href,
text: (a.textContent || '').trim().slice(0, 200),
rel: a.rel || null,
role: a.getAttribute('role'),
ariaLabel: a.getAttribute('aria-label'),
ariaLabelledby: a.getAttribute('aria-labelledby'),
id: a.id || null
};
}),
// Every element with an ID
elementsWithId: mapNodes(gAll('[id]'), function (el) {
return {
tag: el.tagName.toLowerCase(),
id: el.id,
classes: el.className || null,
role: el.getAttribute('role'),
ariaLabel: el.getAttribute('aria-label'),
ariaLabelledby: el.getAttribute('aria-labelledby')
};
}),
// ARIA elements snapshot
ariaElements: mapNodes(
gAll('[role],[aria-label],[aria-labelledby],[aria-hidden],[aria-modal]'),
function (el) {
return {
tag: el.tagName.toLowerCase(),
id: el.id || null,
classes: el.className || null,
role: el.getAttribute('role'),
ariaLabel: el.getAttribute('aria-label'),
ariaLabelledby: el.getAttribute('aria-labelledby'),
ariaHidden: el.getAttribute('aria-hidden'),
ariaModal: el.getAttribute('aria-modal')
};
}
),
// Rough modal detection
modals: mapNodes(
gAll('[role="dialog"],[role="alertdialog"],[aria-modal="true"],.modal,[data-modal],[data-dialog]'),
function (el) {
return {
tag: el.tagName.toLowerCase(),
id: el.id || null,
classes: el.className || null,
role: el.getAttribute('role'),
ariaModal: el.getAttribute('aria-modal'),
ariaLabel: el.getAttribute('aria-label'),
ariaLabelledby: el.getAttribute('aria-labelledby')
};
}
),
// Navigation relations via link[rel]
navRelations: mapNodes(gAll('link[rel]'), function (l) {
return {
rel: l.rel,
href: l.href || null,
as: l.getAttribute('as'),
type: l.type || null,
media: l.media || null
};
}),
// Resource timing data – subresources & initiators
resources: perfResources
};
// Dump into a new window as JSON
var win = w.open('about:blank', '_blank');
if (!win) {
alert('Popup blocked: please allow popups for this site.');
return;
}
var pre = win.document.createElement('pre');
pre.textContent = JSON.stringify(data, null, 2);
win.document.body.appendChild(pre);
win.document.title = 'Page inspection snapshot';
} catch (e) {
alert('Error in bookmarklet: ' + e);
}
})();
2. Advanced page introspector (streaming observers)
This variant takes a static snapshot and also attaches PerformanceObserver and
MutationObserver for ongoing, rolling introspection. It maintains a global state
container on window.__PAGE_INTROSPECTOR__ and continuously refreshes a JSON view
in a dedicated window.
Pattern
Single global state object, idempotent setup, bounded rolling buffers, and a singleton output
window with a periodic dump(). Designed “for the interpreter”: compact, re-entrant,
and runtime-centric.
2.1. Ready-to-use bookmarklet (single line)
javascript:(function(){try{var D=document,W=window;function A(s,c){return Array.prototype.slice.call((c||D).querySelectorAll(s));}function M(xs,f){return xs.map(function(n){try{return f(n);}catch(e){return{error:String(e)}}});}function T(s,l){if(!s)return null;s=s.trim();return s.length>l?s.slice(0,l):s}var S=W.__PAGE_INTROSPECTOR__||(W.__PAGE_INTROSPECTOR__={meta:{started:Date.now()},page:{},static:{},dynamic:{mutations:[],resources:[],longtasks:[]}});S.meta.lastRun=Date.now();S.page={url:W.location.href,title:D.title,referrer:D.referrer};S.static.scripts=M(A('script'),function(s){return{src:s.src||null,inline:s.src?null:T(s.textContent||'',2000),type:s.type||null,async:!!s.async,defer:!!s.defer,crossorigin:s.getAttribute('crossorigin'),nonce:s.getAttribute('nonce'),id:s.id||null}});S.static.links=M(A('link'),function(l){return{rel:l.rel||null,href:l.href||null,as:l.getAttribute('as'),crossorigin:l.getAttribute('crossorigin'),type:l.type||null,media:l.media||null,referrerpolicy:l.referrerPolicy||null,fetchpriority:l.getAttribute('fetchpriority')}});S.static.anchors=M(A('a[href]'),function(a){return{href:a.href,text:T(a.textContent||'',200),rel:a.rel||null,role:a.getAttribute('role'),ariaLabel:a.getAttribute('aria-label'),ariaLabelledby:a.getAttribute('aria-labelledby'),id:a.id||null}});S.static.elementsWithId=M(A('[id]'),function(el){return{tag:el.tagName.toLowerCase(),id:el.id,classes:el.className||null,role:el.getAttribute('role'),ariaLabel:el.getAttribute('aria-label'),ariaLabelledby:el.getAttribute('aria-labelledby')}});S.static.ariaElements=M(A('[role],[aria-label],[aria-labelledby],[aria-hidden],[aria-modal]'),function(el){return{tag:el.tagName.toLowerCase(),id:el.id||null,classes:el.className||null,role:el.getAttribute('role'),ariaLabel:el.getAttribute('aria-label'),ariaLabelledby:el.getAttribute('aria-labelledby'),ariaHidden:el.getAttribute('aria-hidden'),ariaModal:el.getAttribute('aria-modal')}});S.static.modals=M(A('[role="dialog"],[role="alertdialog"],[aria-modal="true"],.modal,[data-modal],[data-dialog]'),function(el){return{tag:el.tagName.toLowerCase(),id:el.id||null,classes:el.className||null,role:el.getAttribute('role'),ariaModal:el.getAttribute('aria-modal'),ariaLabel:el.getAttribute('aria-label'),ariaLabelledby:el.getAttribute('aria-labelledby')}});S.static.navRelations=M(A('link[rel]'),function(l){return{rel:l.rel,href:l.href||null,as:l.getAttribute('as'),type:l.type||null,media:l.media||null}});function cap(arr,max){if(arr.length>max)arr.splice(0,arr.length-max);}if(!S.__observersSetup){S.__observersSetup=true;try{if(W.PerformanceObserver){var ro=new PerformanceObserver(function(list){list.getEntries().forEach(function(e){S.dynamic.resources.push({name:e.name,initiatorType:e.initiatorType,entryType:e.entryType,startTime:e.startTime,duration:e.duration,transferSize:e.transferSize,encodedBodySize:e.encodedBodySize,decodedBodySize:e.decodedBodySize});cap(S.dynamic.resources,400);});});try{ro.observe({type:'resource',buffered:true});}catch(_){ro.observe({entryTypes:['resource']});}var no=new PerformanceObserver(function(list){list.getEntries().forEach(function(e){S.dynamic.resources.push({name:e.name,initiatorType:e.initiatorType||'navigation',entryType:e.entryType,startTime:e.startTime,duration:e.duration,type:e.type});cap(S.dynamic.resources,450);});});try{no.observe({type:'navigation',buffered:true});}catch(_){no.observe({entryTypes:['navigation']});}var lo=new PerformanceObserver(function(list){list.getEntries().forEach(function(e){S.dynamic.longtasks.push({name:e.name||'longtask',entryType:e.entryType,startTime:e.startTime,duration:e.duration});cap(S.dynamic.longtasks,200);});});try{lo.observe({type:'longtask',buffered:true});}catch(_){lo.observe({entryTypes:['longtask']});}}}catch(e){}try{var mo=new MutationObserver(function(muts){muts.forEach(function(m){var rec={t:Date.now(),type:m.type,targetTag:m.target&&m.target.tagName?m.target.tagName.toLowerCase():null,targetId:m.target&&m.target.id||null,added:[],removed:[],attrName:m.attributeName||null};if(m.type==='attributes'){rec.attrValue=m.target && m.attributeName?m.target.getAttribute(m.attributeName):null;}if(m.type==='childList'){Array.prototype.forEach.call(m.addedNodes||[],function(n){if(n.nodeType===1){rec.added.push({tag:n.tagName.toLowerCase(),id:n.id||null,classes:n.className||null,role:n.getAttribute('role'),ariaLabel:n.getAttribute('aria-label')});}});Array.prototype.forEach.call(m.removedNodes||[],function(n){if(n.nodeType===1){rec.removed.push({tag:n.tagName.toLowerCase(),id:n.id||null,classes:n.className||null,role:n.getAttribute('role'),ariaLabel:n.getAttribute('aria-label')});}});}S.dynamic.mutations.push(rec);cap(S.dynamic.mutations,300);});});mo.observe(D.documentElement||D.body||D,{subtree:true,childList:true,attributes:true,attributeFilter:['role','id','class','aria-label','aria-labelledby','aria-hidden','aria-modal']});S.dynamic.__mo=mo;}catch(e){}}var win=S.__win;if(!win||win.closed){win=W.open('about:blank','_blank');if(!win){alert('Popup blocked: enable popups and retry bookmarklet.');return;}S.__win=win;var pre=win.document.createElement('pre');pre.style.whiteSpace='pre-wrap';pre.style.font='11px/1.4 monospace';win.document.body.style.margin='0';win.document.body.appendChild(pre);win.document.title='Page inspection stream';S.__pre=pre;}var pre=S.__pre||S.__win.document.querySelector('pre');function dump(){if(!S.__win||S.__win.closed)return;pre.textContent=JSON.stringify({meta:S.meta,page:S.page,static:S.static,dynamic:S.dynamic},null,2);}dump();if(!S.__interval){S.__interval=W.setInterval(dump,2000);} }catch(e){alert('Introspector error: '+e);}})();
2.2. Runtime structure & patterns
- Global state container:
window.__PAGE_INTROSPECTOR__ with
meta, page, static, dynamic.
- Static view: recomputed on each invocation:
scripts, links, anchors, elements with IDs, ARIA cluster, modal heuristics, navigation relations.
- Dynamic view: rolling buffers:
mutations, resources, longtasks.
- Observers:
- PerformanceObserver for
resource, navigation, longtask.
- MutationObserver on
documentElement (fallback body),
watching childList and selected attributes
(role, id, class, aria-*).
- Rolling caps: bounded arrays via
cap(arr, max)
to avoid unbounded growth.
- Output channel: singleton
about:blank window with a
<pre> element, refreshed every 2 seconds by dump().
- Idempotent setup: observers and interval created once;
subsequent runs only recompute static snapshot and refresh the view.
Comments
Post a Comment