| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284 |
- <style>
- .cake-debug {
- --color-bg: #ecece9;
- --color-highlight-bg: #fcf8e3;
- --color-control-bg: hsla(0, 0%, 50%, 0.2);
- --color-blue: #4070a0;
- --color-green: #0b6125;
- --color-grey: #5f5f5f;
- --color-orange: #c44f24;
- --color-violet: #a71d5d;
- --color-dark-grey: #222;
- --color-cyan: #234aa0;
- --color-red: #d33c44;
- --indent: 20px;
- font-family: monospace;
- background: var(--color-bg);
- padding: 5px;
- line-height: 16px;
- font-size: 14px;
- margin-bottom: 10px;
- position: relative;
- }
- .cake-debug:last-child {
- margin-bottom: 0;
- }
- .cake-debug-object {
- display: inline;
- }
- .cake-debug-object[data-highlighted=true],
- .cake-debug-object[data-highlighted=true] samp {
- background: var(--color-highlight-bg);
- }
- /*
- Array item container and each items are blocks so
- nesting works.
- */
- .cake-debug-object-props,
- .cake-debug-array-items {
- display: block;
- }
- .cake-debug-prop,
- .cake-debug-array-item {
- display: block;
- padding-left: var(--indent);
- min-height: 18px;
- }
- /** Collapser buttons **/
- [data-hidden=true] {
- display: none;
- }
- .cake-debug-collapse {
- display: inline-block;
- width: 14px;
- height: 14px;
- vertical-align: middle;
- border-radius: 3px;
- color: var(--color-blue);
- background: var(--color-control-bg);
- /* Image is an rawurlencoded SVG */
- background-image: url("data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20height%3D%2212%22%20width%3D%2212%22%20viewBox%3D%220%200%2012%2012%22%3E%3Cpolygon%20points%3D%223%2C1%203%2C11%208%2C6%22 style%3D%22fill%3A%234070a0%3B%22%2F%3E%3C%2Fsvg%3E");
- background-position: 2px 1px;
- background-repeat: no-repeat;
- }
- .cake-debug-collapse[data-open=true] {
- transform: rotate(90deg);
- }
- /* Copy button */
- .cake-debug-copy {
- position: absolute;
- top: 0;
- right: 0;
- padding: 6px;
- background: var(--color-control-bg);
- color: var(--color-blue);
- border-radius: 0 0 0 3px;
- }
- /* Textual elements */
- .cake-debug-class {
- color: var(--color-cyan);
- }
- .cake-debug-property {
- color: var(--color-dark-grey);
- }
- .cake-debug-visibility {
- color: var(--color-violet);
- }
- .cake-debug-punct {
- color: var(--color-grey);
- }
- .cake-debug-string {
- color: var(--color-green);
- white-space: pre-wrap;
- }
- .cake-debug-number {
- color: var(--color-blue);
- font-weight: bold;
- }
- .cake-debug-const {
- color: var(--color-orange);
- font-weight: bold;
- }
- .cake-debug-ref {
- color: var(--color-red);
- }
- .cake-debug-special {
- color: var(--color-red);
- font-style: italic;
- }
- </style>
- <script>
- ( function( win, doc ) {
- function initialize() {
- createCollapsibles( doc.querySelectorAll( '.cake-debug-array-items' ) );
- createCollapsibles( doc.querySelectorAll( '.cake-debug-object-props' ) );
- attachRefEvents( doc.querySelectorAll( '.cake-debug' ) );
- openBlocks( doc.querySelectorAll( '.cake-debug[data-open-all="true"]' ) );
- attachCopyButton( doc.querySelectorAll( '.cake-debug' ) );
- }
- // Add a name on window so DebugKit can add controls to dump blocks
- win.__cakeDebugBlockInit = initialize;
- /**
- * Open all the collapsed sections in a block.
- */
- function openBlocks( blocks ) {
- blocks.forEach( function( block ) {
- block.querySelectorAll( '.cake-debug-collapse[data-open="false"]' ).forEach( function( el ) {
- el.click();
- } );
- } );
- }
- /**
- * Create collapse toggles and attach events
- */
- function createCollapsibles( nodes ) {
- nodes.forEach( function( node ) {
- // Hide the childnode container if it is not
- // a direct parent of the container.
- if( !node.parentNode.parentNode.classList.contains( 'cake-debug' ) ) {
- node.dataset.hidden = true;
- }
- // Don't show toggles for empty arrays/objects
- if( node.childNodes.length == 0 ) {
- return;
- }
- let collapser = doc.createElement( 'a' );
- collapser.classList.add( 'cake-debug-collapse' );
- collapser.dataset.open = !node.dataset.hidden;
- collapser.setAttribute( 'href', '#' )
- collapser.setAttribute( 'title', 'Toggle items' );
- // Add open/close behavior
- collapser.addEventListener( 'click', function( event ) {
- event.preventDefault();
- event.stopPropagation();
- node.dataset.hidden = node.dataset.hidden === 'true' ? 'false' : 'true';
- collapser.dataset.open = collapser.dataset.open === 'true' ? 'false' : 'true';
- } );
- node.parentNode.insertBefore( collapser, node );
- } );
- }
- /**
- * When ref links are clicked open the path to that
- * element and highlight the reference
- */
- function attachRefEvents( nodes ) {
- nodes.forEach( function( container ) {
- let refLinks = container.querySelectorAll( '.cake-debug-ref' );
- refLinks.forEach( function( ref ) {
- ref.addEventListener( 'click', function( event ) {
- event.preventDefault();
- event.stopPropagation();
- let target = document.getElementById( ref.getAttribute( 'href' ).substr( 1 ) );
- openPath( container, target );
- } );
- } );
- } );
- }
- function openPath( container, target ) {
- // Open the target element
- let expander = target.querySelector( '.cake-debug-collapse' );
- if( expander.dataset.open === 'false' ) {
- expander.click();
- }
- container.querySelectorAll( '.cake-debug-object' ).forEach( function( el ) {
- el.dataset.highlighted = 'false';
- } )
- target.dataset.highlighted = 'true';
- let current = target;
- // Traverse up the tree opening all closed containers.
- while( true ) {
- let parent = current.parentNode;
- if( parent == container ) {
- break;
- }
- if( parent.classList.contains( 'cake-debug-object' ) || parent.classList.contains( 'cake-debug-array' ) ) {
- expander = parent.querySelector( '.cake-debug-collapse' );
- if( expander.dataset.open === 'false' ) {
- expander.click();
- }
- }
- current = parent;
- }
- }
- // https://www.30secondsofcode.org/js/s/copy-to-clipboard
- function copyToClipboard( str ) {
- let el = document.createElement( 'textarea' );
- el.value = str;
- el.setAttribute( 'readonly', '' );
- el.style.position = 'absolute';
- el.style.left = '-9999px';
- document.body.appendChild( el );
- let selected = document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt( 0 ) : false;
- el.select();
- document.execCommand( 'copy' );
- document.body.removeChild( el );
- if( selected ) {
- document.getSelection().removeAllRanges();
- document.getSelection().addRange( selected );
- }
- }
- function attachCopyButton( nodes ) {
- nodes.forEach( function( container ) {
- let copy = doc.createElement( 'a' );
- copy.classList.add( 'cake-debug-copy' );
- copy.setAttribute( 'href', '#' );
- copy.setAttribute( 'title', 'Copy contents of debug output' );
- copy.appendChild( doc.createTextNode( 'Copy' ) );
- // Add copy behavior
- copy.addEventListener( 'click', function( event ) {
- event.preventDefault();
- event.stopPropagation();
- let lineNo = '';
- if( container.parentNode && container.parentNode.classList.contains( 'cake-debug' ) ) {
- let line = container.parentNode.querySelector( 'span' );
- lineNo = line.textContent + "\n";
- }
- // Chop off last 4 to exclude copy button text.
- copyToClipboard( lineNo + container.textContent.substring( 0, container.textContent.length - 4 ) );
- } );
- container.appendChild( copy );
- } );
- }
- doc.addEventListener( 'DOMContentLoaded', initialize );
- }( window, document ) )
- </script>
|