1<!DOCTYPE html> 2<html lang="en"> 3<head> 4<meta charset="UTF-8"> 5<meta name="viewport" content="width=device-width, initial-scale=1"> 6<link rel="profile" href="http://gmpg.org/xfn/11"> 7 8<title>The Public Void – Page 2 – Andy West's Blog: Software Development and More</title> 9<meta name='robots' content='max-image-preview:large' /> 10<meta name="google-site-verification" content="dOt2zmeoyzy55jhej-q2J0j3r852Wu26UcuTHeKv1oM" /> 11 12<!-- Async WordPress.com Remote Login -->
13<script id="wpcom_remote_login_js"> 14var wpcom_remote_login_extra_auth = ''; 15function wpcom_remote_login_remove_dom_node_id( element_id ) { 16 var dom_node = document.getElementById( element_id ); 17 if ( dom_node ) { dom_node.parentNode.removeChild( dom_node ); } 18} 19function wpcom_remote_login_remove_dom_node_classes( class_name ) { 20 var dom_nodes = document.querySelectorAll( '.' + class_name ); 21 for ( var i = 0; i < dom_nodes.length; i++ ) { 22 dom_nodes[ i ].parentNode.removeChild( dom_nodes[ i ] ); 23 } 24} 25function wpcom_remote_login_final_cleanup() { 26 wpcom_remote_login_remove_dom_node_classes( "wpcom_remote_login_msg" ); 27 wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_key" ); 28 wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_validate" ); 29 wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_js" ); 30 wpcom_remote_login_remove_dom_node_id( "wpcom_request_access_iframe" ); 31 wpcom_remote_login_remove_dom_node_id( "wpcom_request_access_styles" ); 32} 33 34// Watch for messages back from the remote login 35window.addEventListener( "message", function( e ) { 36 if ( e.origin === "https://r-login.wordpress.com" ) { 37 var data = {}; 38 try { 39 data = JSON.parse( e.data ); 40 } catch( e ) { 41 wpcom_remote_login_final_cleanup(); 42 return; 43 } 44 45 if ( data.msg === 'LOGIN' ) { 46 // Clean up the login check iframe 47 wpcom_remote_login_remove_dom_node_id( "wpcom_remote_login_key" ); 48 49 var id_regex = new RegExp( /^[0-9]+$/ ); 50 var token_regex = new RegExp( /^.*|.*|.*$/ ); 51 if ( 52 token_regex.test( data.token ) 53 && id_regex.test( data.wpcomid ) 54 ) { 55 // We have everything we need to ask for a login 56 var script = document.createElement( "script" ); 57 script.setAttribute( "id", "wpcom_remote_login_validate" ); 58 script.src = '/remote-login.php?wpcom_remote_login=validate' 59 + '&wpcomid=' + data.wpcomid 60 + '&token=' + encodeURIComponent( data.token ) 61 + '&host=' + window.location.protocol 62 + '//' + window.location.hostname 63 + '&postid=376' 64 + '&is_singular='; 65 document.body.appendChild( script ); 66 } 67 68 return; 69 } 70 71 // Safari ITP, not logged in, so redirect 72 if ( data.msg === 'LOGIN-REDIRECT' ) { 73 window.location = 'https://wordpress.com/log-in?redirect_to=' + window.location.href; 74 return; 75 } 76 77 // Safari ITP, storage access failed, remove the request 78 if ( data.msg === 'LOGIN-REMOVE' ) { 79 var css_zap = 'html { -webkit-transition: margin-top 1s; transition: margin-top 1s; } /* 9001 */ html { margin-top: 0 !important; } * html body { margin-top: 0 !important; } @media screen and ( max-width: 782px ) { html { margin-top: 0 !important; } * html body { margin-top: 0 !important; } }'; 80 var style_zap = document.createElement( 'style' ); 81 style_zap.type = 'text/css'; 82 style_zap.appendChild( document.createTextNode( css_zap ) ); 83 document.body.appendChild( style_zap ); 84 85 var e = document.getElementById( 'wpcom_request_access_iframe' ); 86 e.parentNode.removeChild( e ); 87 88 document.cookie = 'wordpress_com_login_access=denied; path=/; max-age=31536000'; 89 90 return; 91 } 92 93 // Safari ITP 94 if ( data.msg === 'REQUEST_ACCESS' ) { 95 console.log( 'request access: safari' ); 96 97 // Check ITP iframe enable/disable knob 98 if ( wpcom_remote_login_extra_auth !== 'safari_itp_iframe' ) { 99 return; 100 } 101 102 // If we are in a "private window" there is no ITP. 103 var private_window = false; 104 try { 105 var opendb = window.openDatabase( null, null, null, null ); 106 } catch( e ) { 107 private_window = true; 108 } 109 110 if ( private_window ) { 111 console.log( 'private window' ); 112 return; 113 } 114 115 var iframe = document.createElement( 'iframe' ); 116 iframe.id = 'wpcom_request_access_iframe'; 117 iframe.setAttribute( 'scrolling', 'no' ); 118 iframe.setAttribute( 'sandbox', 'allow-storage-access-by-user-activation allow-scripts allow-same-origin allow-top-navigation-by-user-activation' ); 119 iframe.src = 'https://r-login.wordpress.com/remote-login.php?wpcom_remote_login=request_access&origin=' + encodeURIComponent( data.origin ) + '&wpcomid=' + encodeURIComponent( data.wpcomid ); 120 121 var css = 'html { -webkit-transition: margin-top 1s; transition: margin-top 1s; } /* 9001 */ html { margin-top: 46px !important; } * html body { margin-top: 46px !important; } @media screen and ( max-width: 660px ) { html { margin-top: 71px !important; } * html body { margin-top: 71px !important; } #wpcom_request_access_iframe { display: block; height: 71px !important; } } #wpcom_request_access_iframe { border: 0px; height: 46px; position: fixed; top: 0; left: 0; width: 100%; min-width: 100%; z-index: 99999; background: #23282d; } '; 122 123 var style = document.createElement( 'style' ); 124 style.type = 'text/css'; 125 style.id = 'wpcom_request_access_styles'; 126 style.appendChild( document.createTextNode( css ) ); 127 document.body.appendChild( style ); 128 129 document.body.appendChild( iframe ); 130 } 131 132 if ( data.msg === 'DONE' ) { 133 wpcom_remote_login_final_cleanup(); 134 } 135 } 136}, false ); 137 138// Inject the remote login iframe after the page has had a chance to load 139// more critical resources 140window.addEventListener( "DOMContentLoaded", function( e ) { 141 var iframe = document.createElement( "iframe" );
142 iframe.style.display = "none"; 143 iframe.setAttribute( "scrolling", "no" ); 144 iframe.setAttribute( "id", "wpcom_remote_login_key" ); 145 iframe.src = "https://r-login.wordpress.com/remote-login.php" 146 + "?wpcom_remote_login=key" 147 + "&origin=aHR0cHM6Ly9hbmRyZXd0d2VzdC5jb20%3D" 148 + "&wpcomid=12038026" 149 + "&time=" + Math.floor( Date.now() / 1000 ); 150 document.body.appendChild( iframe ); 151}, false ); 152</script>
152 153<link rel='dns-prefetch' href='//s1.wp.com' /> 154<link rel='dns-prefetch' href='//s2.wp.com' /> 155<link rel='dns-prefetch' href='//s0.wp.com' /> 156<link rel='dns-prefetch' href='//af.pubmine.com' /> 157<link rel="alternate" type="application/rss+xml" title="The Public Void » Feed" href="https://andrewtwest.com/feed/" /> 158<link rel="alternate" type="application/rss+xml" title="The Public Void » Comments Feed" href="https://andrewtwest.com/comments/feed/" /> 159
159<script type="text/javascript"> 160 /* <![CDATA[ */ 161 function addLoadEvent(func) { 162 var oldonload = window.onload; 163 if (typeof window.onload != 'function') { 164 window.onload = func; 165 } else { 166 window.onload = function () { 167 oldonload(); 168 func(); 169 } 170 } 171 } 172 /* ]]> */ 173 </script>
173 174 <style id="wp-img-auto-sizes-contain-inline-css"> 175img:is([sizes=auto i],[sizes^="auto," i]){contain-intrinsic-size:3000px 1500px} 176/*# sourceURL=wp-img-auto-sizes-contain-inline-css */ 177</style> 178<link crossorigin='anonymous' rel='stylesheet' id='all-css-2-1' href='/_static/??-eJxtjNEKwjAMRX/IGqeDPonfUro4sqVJMSllf78N9M2XC4fLOdBryCqO4lBaqNxmEoNO04xugO14dSUMnDo4lsrJ0cB8Y7xmswv8DyzoNeX1y1BUz5kaHzLJm4Qcg+WPMv94O3uv8hxijONwe9zHZQe30zrK&cssminify=yes' type='text/css' media='all' /> 179<style id="wp-emoji-styles-inline-css"> 180 181 img.wp-smiley, img.emoji { 182 display: inline !important; 183 border: none !important; 184 box-shadow: none !important; 185 height: 1em !important; 186 width: 1em !important; 187 margin: 0 0.07em !important; 188 vertical-align: -0.1em !important; 189 background: none !important; 190 padding: 0 !important; 191 } 192/*# sourceURL=wp-emoji-styles-inline-css */ 193</style> 194<style id="wp-block-library-inline-css"> 195:root{--wp-block-synced-color:#7a00df;--wp-block-synced-color--rgb:122,0,223;--wp-bound-block-color:var(--wp-block-synced-color);--wp-editor-canvas-background:#ddd;--wp-admin-theme-color:#007cba;--wp-admin-theme-color--rgb:0,124,186;--wp-admin-theme-color-darker-10:#006ba1;--wp-admin-theme-color-darker-10--rgb:0,107,160.5;--wp-admin-theme-color-darker-20:#005a87;--wp-admin-theme-color-darker-20--rgb:0,90,135;--wp-admin-border-width-focus:2px}@media (min-resolution:192dpi){:root{--wp-admin-border-width-focus:1.5px}}.wp-element-button{cursor:pointer}:root .has-very-light-gray-background-color{background-color:#eee}:root .has-very-dark-gray-background-color{background-color:#313131}:root .has-very-light-gray-color{color:#eee}:root .has-very-dark-gray-color{color:#313131}:root .has-vivid-green-cyan-to-vivid-cyan-blue-gradient-background{background:linear-gradient(135deg,#00d084,#0693e3)}:root .has-purple-crush-gradient-background{background:linear-gradient(135deg,#34e2e4,#4721fb 50%,#ab1dfe)}:root .has-hazy-dawn-gradient-background{background:linear-gradient(135deg,#faaca8,#dad0ec)}:root .has-subdued-olive-gradient-background{background:linear-gradient(135deg,#fafae1,#67a671)}:root .has-atomic-cream-gradient-background{background:linear-gradient(135deg,#fdd79a,#004a59)}:root .has-nightshade-gradient-background{background:linear-gradient(135deg,#330968,#31cdcf)}:root .has-midnight-gradient-background{background:linear-gradient(135deg,#020381,#2874fc)}:root{--wp--preset--font-size--normal:16px;
195--wp--preset--font-size--huge:42px}.has-regular-font-size{font-size:1em}.has-larger-font-size{font-size:2.625em}.has-normal-font-size{font-size:var(--wp--preset--font-size--normal)}.has-huge-font-size{font-size:var(--wp--preset--font-size--huge)}:root .has-text-align-center{text-align:center}:root .has-text-align-left{text-align:left}:root .has-text-align-right{text-align:right}.has-fit-text{white-space:nowrap!important}#end-resizable-editor-section{display:none}.aligncenter{clear:both}.items-justified-left{justify-content:flex-start}.items-justified-center{justify-content:center}.items-justified-right{justify-content:flex-end}.items-justified-space-between{justify-content:space-between}.screen-reader-text{border:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;overflow-wrap:normal!important;padding:0;position:absolute;width:1px;word-break:normal!important}.screen-reader-text:focus{background-color:#ddd;clip-path:none;color:#444;display:block;font-size:1em;height:auto;left:5px;line-height:normal;padding:15px 23px 14px;text-decoration:none;top:5px;width:auto;z-index:100000}html :where(.has-border-color){border-style:solid}html :where([style^=border-color],[style*=";border-color"],[style*="; border-color"]){border-style:solid}html :where([style^=border-top-color],[style*=";border-top-color"],[style*="; border-top-color"]){border-top-style:solid}html :where([style^=border-right-color],[style*=";border-right-color"],[style*="; border-right-color"]){border-right-style:solid}html :where([style^=border-bottom-color],[style*=";border-bottom-color"],[style*="; border-bottom-color"]){border-bottom-style:solid}html :where([style^=border-left-color],[style*=";border-left-color"],[style*="; border-left-color"]){border-left-style:solid}html :where([style^=border-width],[style*=";border-width"],[style*="; border-width"]){border-style:solid}html :where([style^=border-top-width],[style*=";border-top-width"],[style*="; border-top-width"]){border-top-style:solid}html :where([style^=border-right-width],[style*=";border-right-width"],[style*="; border-right-width"]){border-right-style:solid}html :where([style^=border-bottom-width],[style*=";border-bottom-width"],[style*="; border-bottom-width"]){border-bottom-style:solid}html :where([style^=border-left-width],[style*=";border-left-width"],[style*="; border-left-width"]){border-left-style:solid}html :where(img[class*=wp-image-]){height:auto;max-width:100%}:where(figure){margin:0 0 1em}html :where(.is-position-sticky){--wp-admin--admin-bar--position-offset:var(--wp-admin--admin-bar--height,0px)}@media screen and (max-width:600px){html :where(.is-position-sticky){--wp-admin--admin-bar--position-offset:0px}} 196 197/*# sourceURL=/wp-content/plugins/gutenberg-core/v24.1.0/build/styles/block-library/common.min.css */ 198</style> 199<style id="wp-block-library-inline-css-extra"> 200.has-text-align-justify { 201 text-align:justify; 202} 203.has-text-align-justify{text-align:justify;} 204/*# sourceURL=wp-block-library-inline-css */ 205</style> 206 207<style id="classic-theme-styles-inline-css"> 208.wp-block-button__link{background-color:#32373c;border-radius:9999px;box-shadow:none;color:#fff;font-size:1.125em;padding:calc(.667em + 2px) calc(1.333em + 2px);text-decoration:none}.wp-block-file__button{background:#32373c;color:#fff}.wp-block-accordion-heading{margin:0}.wp-block-accordion-heading__toggle{background-color:inherit!important;color:inherit!important}.wp-block-accordion-heading__toggle:not(:focus-visible){outline:none}.wp-block-accordion-heading__toggle:focus,.wp-block-accordion-heading__toggle:hover{background-color:inherit!important;border:none;box-shadow:none;color:inherit;padding:var(--wp--preset--spacing--20,1em) 0;text-decoration:none}.wp-block-accordion-heading__toggle:focus-visible{outline:auto;outline-offset:0}.wp-block-tab:not(.has-text-color){color:inherit!important}.wp-block-tab:not(.has-background){background-color:inherit!important}.wp-block-tab:focus,.wp-block-tab:hover{text-decoration:none}.wp-block-tab:focus-visible{outline:auto;outline-offset:0} 209/*# sourceURL=/wp-content/plugins/gutenberg-core/v24.1.0/build/styles/block-library/classic.min.css */ 210</style> 211 212<style id="coblocks-inline-format-inline-css"> 213.uppercase{text-transform:uppercase} 214/*# sourceURL=coblocks-inline-format-inline-css */ 215</style> 216<link crossorigin='anonymous' rel='stylesheet' id='all-css-12-1' href='/_static/??-eJx9jEEOAiEQBD/kQECjeDC+ZWEnijIwYWA3/l72op689KFTVXplCCU3zE1z6reYRYfiUwlP0VYZpwxIJE4IFRd10HOU9iFA2iuhCiI7/ROiDt9WxfETT20jCOc4YUIa2D9t5eGA91xRBMZS7ATtPkTZvCtdzNEZt7f2fHq8Afl7R7w=&cssminify=yes' type='text/css' media='all' /> 217<style id="global-styles-inline-css"> 218:root{--wp--preset--aspect-ratio--square: 1;--wp--preset--aspect-ratio--4-3: 4/3;--wp--preset--aspect-ratio--3-4: 3/4;--wp--preset--aspect-ratio--3-2: 3/2;--wp--preset--aspect-ratio--2-3: 2/3;--wp--preset--aspect-ratio--16-9: 16/9;--wp--preset--aspect-ratio--9-16: 9/16;--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #fff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--color--medium-blue: #0087be;--wp--preset--color--bright-blue: #00aadc;--wp--preset--color--dark-gray: #4d4d4b;--wp--preset--color--light-gray: #b3b3b1;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgb(6,147,227) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgb(252,185,
2180) 0%,rgb(255,105,0) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgb(255,105,0) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;--wp--preset--font-family--albert-sans: 'Albert Sans', sans-serif;--wp--preset--font-family--alegreya: Alegreya, serif;--wp--preset--font-family--arvo: Arvo, serif;--wp--preset--font-family--bodoni-moda: 'Bodoni Moda', serif;--wp--preset--font-family--bricolage-grotesque: 'Bricolage Grotesque', sans-serif;--wp--preset--font-family--cabin: Cabin, sans-serif;--wp--preset--font-family--chivo: Chivo, sans-serif;--wp--preset--font-family--commissioner: Commissioner, sans-serif;--wp--preset--font-family--cormorant: Cormorant, serif;--wp--preset--font-family--courier-prime: 'Courier Prime', monospace;--wp--preset--font-family--crimson-pro: 'Crimson Pro', serif;--wp--preset--font-family--dm-mono: 'DM Mono', monospace;--wp--preset--font-family--dm-sans: 'DM Sans', sans-serif;--wp--preset--font-family--dm-serif-display: 'DM Serif Display', serif;--wp--preset--font-family--domine: Domine, serif;--wp--preset--font-family--eb-garamond: 'EB Garamond', serif;--wp--preset--font-family--epilogue: Epilogue, sans-serif;--wp--preset--font-family--fahkwang: Fahkwang, sans-serif;--wp--preset--font-family--figtree: Figtree, sans-serif;--wp--preset--font-family--fira-sans: 'Fira Sans', sans-serif;--wp--preset--font-family--fjalla-one: 'Fjalla One', sans-serif;--wp--preset--font-family--fraunces: Fraunces, serif;--wp--preset--font-family--gabarito: Gabarito, system-ui;--wp--preset--font-family--ibm-plex-mono: 'IBM Plex Mono', monospace;--wp--preset--font-family--ibm-plex-sans: 'IBM Plex Sans', sans-serif;--wp--preset--font-family--ibarra-real-nova: 'Ibarra Real Nova', serif;--wp--preset--font-family--instrument-serif: 'Instrument Serif', serif;--wp--preset--font-family--inter: Inter, sans-serif;--wp--preset--font-family--josefin-sans: 'Josefin Sans', sans-serif;--wp--preset--font-family--jost: Jost, sans-serif;--wp--preset--font-family--libre-baskerville: 'Libre Baskerville', serif;--wp--preset--font-family--libre-franklin: 'Libre Franklin', sans-serif;--wp--preset--font-family--literata: Literata, serif;--wp--preset--font-family--lora: Lora, serif;--wp--preset--font-family--merriweather: Merriweather, serif;--wp--preset--font-family--montserrat: Montserrat, sans-serif;--wp--preset--font-family--newsreader: Newsreader, serif;--wp--preset--font-family--noto-sans-mono: 'Noto Sans Mono', sans-serif;--wp--preset--font-family--nunito: Nunito, sans-serif;--wp--preset--font-family--open-sans: 'Open Sans', sans-serif;--wp--preset--font-family--overpass: Overpass, sans-serif;--wp--preset--font-family--pt-serif: 'PT Serif', serif;--wp--preset--font-family--petrona: Petrona, serif;--wp--preset--font-family--piazzolla: Piazzolla, serif;--wp--preset--font-family--playfair-display: 'Playfair Display', serif;--wp--preset--font-family--plus-jakarta-sans: 'Plus Jakarta Sans', sans-serif;--wp--preset--font-family--poppins: Poppins, sans-serif;--wp--preset--font-family--raleway: Raleway, sans-serif;--wp--preset--font-family--roboto: Roboto, sans-serif;--wp--preset--font-family--roboto-slab: 'Roboto Slab', serif;--wp--preset--font-family--rubik: Rubik, sans-serif;--wp--preset--font-family--rufina: Rufina, serif;--wp--preset--font-family--sora: Sora, sans-serif;--wp--preset--font-family--source-sans-3: 'Source Sans 3', sans-serif;--wp--preset--font-family--source-serif-4: 'Source Serif 4', serif;--wp--preset--font-family--space-mono: 'Space Mono', monospace;--wp--preset--font-family--syne: Syne, sans-serif;--wp--preset--font-family--texturina: Texturina, serif;--wp--preset--font-family--urbanist: Urbanist, sans-serif;--wp--preset--font-family--work-sans: 'Work Sans', sans-serif;--wp--preset--text-shadow--light: 0.05em 0.05em 0.1em rgba(0, 0, 0, 0.3);--wp--preset--text-shadow--strong: 0.1em 0.1em 0.25em rgba(0, 0, 0, 0.5);--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgb(255, 255, 255), 6px 6px rgb(0, 0, 0);--wp--preset--shadow--crisp: 6px 6px 0px rgb(0, 0, 0);}.wp-block-button{--wp--preset--dimension--25: 25%;--wp--preset--dimension--50: 50%;--wp--preset--dimension--75: 75%;--wp--preset--dimension--100: 100%;}:where(body) { margin: 0; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}body{padding-top: 0px;padding-right: 0px;padding-bottom: 0px;padding-left: 0px;}:root :where(.wp-element-button, .wp-block-button__link){background-color: #32373c;border-width: 0;color: #fff;font-family: inherit;font-size: inherit;font-style: inherit;font-weight: inherit;letter-spacing: inherit;line-height: inherit;padding-top: calc(0.667em + 2px);padding-right: calc(1.333em + 2px);padding-bottom: calc(0.667em + 2px);padding-left: calc(1.333em + 2px);text-decoration: none;text-transform: inherit;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-medium-blue-color{color: var(--wp--preset--color--medium-blue) !important;}.has-bright-blue-color{color: var(--wp--preset--color--bright-blue) !important;}.has-dark-gray-color{color: var(--wp--preset--color--dark-gray) !important;}.has-light-gray-color{color: var(--wp--preset--color--light-gray) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-medium-blue-background-color{background-color: var(--wp--preset--color--medium-blue) !important;}.has-bright-blue-background-color{background-color: var(--wp--preset--color--bright-blue) !important;}.has-dark-gray-background-color{background-color: var(--wp--preset--color--dark-gray) !important;}.has-light-gray-background-color{background-color: var(--wp--preset--color--light-gray) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-medium-blue-border-color{border-color: var(--wp--preset--color--medium-blue) !important;}.has-bright-blue-border-color{border-color: var(--wp--preset--color--bright-blue) !important;}.has-dark-gray-border-color{border-color: var(--wp--preset--color--dark-gray) !important;}.has-light-gray-border-color{border-color: var(--wp--preset--color--light-gray) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}
218.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}.has-albert-sans-font-family{font-family: var(--wp--preset--font-family--albert-sans) !important;}.has-alegreya-font-family{font-family: var(--wp--preset--font-family--alegreya) !important;}.has-arvo-font-family{font-family: var(--wp--preset--font-family--arvo) !important;}.has-bodoni-moda-font-family{font-family: var(--wp--preset--font-family--bodoni-moda) !important;}.has-bricolage-grotesque-font-family{font-family: var(--wp--preset--font-family--bricolage-grotesque) !important;}.has-cabin-font-family{font-family: var(--wp--preset--font-family--cabin) !important;}.has-chivo-font-family{font-family: var(--wp--preset--font-family--chivo) !important;}.has-commissioner-font-family{font-family: var(--wp--preset--font-family--commissioner) !important;}.has-cormorant-font-family{font-family: var(--wp--preset--font-family--cormorant) !important;}.has-courier-prime-font-family{font-family: var(--wp--preset--font-family--courier-prime) !important;}.has-crimson-pro-font-family{font-family: var(--wp--preset--font-family--crimson-pro) !important;}.has-dm-mono-font-family{font-family: var(--wp--preset--font-family--dm-mono) !important;}.has-dm-sans-font-family{font-family: var(--wp--preset--font-family--dm-sans) !important;}.has-dm-serif-display-font-family{font-family: var(--wp--preset--font-family--dm-serif-display) !important;}.has-domine-font-family{font-family: var(--wp--preset--font-family--domine) !important;}.has-eb-garamond-font-family{font-family: var(--wp--preset--font-family--eb-garamond) !important;}.has-epilogue-font-family{font-family: var(--wp--preset--font-family--epilogue) !important;}.has-fahkwang-font-family{font-family: var(--wp--preset--font-family--fahkwang) !important;}.has-figtree-font-family{font-family: var(--wp--preset--font-family--figtree) !important;}.has-fira-sans-font-family{font-family: var(--wp--preset--font-family--fira-sans) !important;}.has-fjalla-one-font-family{font-family: var(--wp--preset--font-family--fjalla-one) !important;}.has-fraunces-font-family{font-family: var(--wp--preset--font-family--fraunces) !important;}.has-gabarito-font-family{font-family: var(--wp--preset--font-family--gabarito) !important;}.has-ibm-plex-mono-font-family{font-family: var(--wp--preset--font-family--ibm-plex-mono) !important;}.has-ibm-plex-sans-font-family{font-family: var(--wp--preset--font-family--ibm-plex-sans) !important;}.has-ibarra-real-nova-font-family{font-family: var(--wp--preset--font-family--ibarra-real-nova) !important;}.has-instrument-serif-font-family{font-family: var(--wp--preset--font-family--instrument-serif) !important;}.has-inter-font-family{font-family: var(--wp--preset--font-family--inter) !important;}.has-josefin-sans-font-family{font-family: var(--wp--preset--font-family--josefin-sans) !important;}.has-jost-font-family{font-family: var(--wp--preset--font-family--jost) !important;}.has-libre-baskerville-font-family{font-family: var(--wp--preset--font-family--libre-baskerville) !important;}.has-libre-franklin-font-family{font-family: var(--wp--preset--font-family--libre-franklin) !important;}.has-literata-font-family{font-family: var(--wp--preset--font-family--literata) !important;}.has-lora-font-family{font-family: var(--wp--preset--font-family--lora) !important;}.has-merriweather-font-family{font-family: var(--wp--preset--font-family--merriweather) !important;}.has-montserrat-font-family{font-family: var(--wp--preset--font-family--montserrat) !important;}.has-newsreader-font-family{font-family: var(--wp--preset--font-family--newsreader) !important;}.has-noto-sans-mono-font-family{font-family: var(--wp--preset--font-family--noto-sans-mono) !important;}.has-nunito-font-family{font-family: var(--wp--preset--font-family--nunito) !important;}.has-open-sans-font-family{font-family: var(--wp--preset--font-family--open-sans) !important;}.has-overpass-font-family{font-family: var(--wp--preset--font-family--overpass) !important;}.has-pt-serif-font-family{font-family: var(--wp--preset--font-family--pt-serif) !important;}.has-petrona-font-family{font-family: var(--wp--preset--font-family--petrona) !important;}.has-piazzolla-font-family{font-family: var(--wp--preset--font-family--piazzolla) !important;}.has-playfair-display-font-family{font-family: var(--wp--preset--font-family--playfair-display) !important;}.has-plus-jakarta-sans-font-family{font-family: var(--wp--preset--font-family--plus-jakarta-sans) !important;}.has-poppins-font-family{font-family: var(--wp--preset--font-family--poppins) !important;}.has-raleway-font-family{font-family: var(--wp--preset--font-family--raleway) !important;}.has-roboto-font-family{font-family: var(--wp--preset--font-family--roboto) !important;}.has-roboto-slab-font-family{font-family: var(--wp--preset--font-family--roboto-slab) !important;}.has-rubik-font-family{font-family: var(--wp--preset--font-family--rubik) !important;}.has-rufina-font-family{font-family: var(--wp--preset--font-family--rufina) !important;}.has-sora-font-family{font-family: var(--wp--preset--font-family--sora) !important;}.has-source-sans-3-font-family{font-family: var(--wp--preset--font-family--source-sans-3) !important;}.has-source-serif-4-font-family{font-family: var(--wp--preset--font-family--source-serif-4) !important;}.has-space-mono-font-family{font-family: var(--wp--preset--font-family--space-mono) !important;}.has-syne-font-family{font-family: var(--wp--preset--font-family--syne) !important;}.has-texturina-font-family{font-family: var(--wp--preset--font-family--texturina) !important;}.has-urbanist-font-family{font-family: var(--wp--preset--font-family--urbanist) !important;}.has-work-sans-font-family{font-family: var(--wp--preset--font-family--work-sans) !important;}.has-light-text-shadow{text-shadow: var(--wp--preset--text-shadow--light) !important;}.has-strong-text-shadow{text-shadow: var(--wp--preset--text-shadow--strong) !important;} 219/*# sourceURL=global-styles-inline-css */ 220</style> 221 222<link crossorigin='anonymous' rel='stylesheet' id='all-css-14-1' href='/_static/??-eJydkNEKwjAMRX/IGh0D7YP4KbLV2GVr09J2DP/ebAgOFB/2Eu59OPcmgSkqE7ggF/Cjim60xBl6LLExw9uDD4HhRmzAImMiIfJvuTc572AVWjr0mCGOLRDfMaIMLkq8o9xhUhXk8nS4BRQEWhfMsKl2PmepVlM0wX9FrN6RUGqsSLt0fuw/yGJQslxTSJ63NurhGkozevWX4+lcaX3Qte5fvXGUcQ==&cssminify=yes' type='text/css' media='all' /> 223<link crossorigin='anonymous' rel='stylesheet' id='print-css-15-1' href='/wp-content/mu-plugins/global-print/global-print.css?m=1465851035i&cssminify=yes' type='text/css' media='print' /> 224<style id="jetpack-global-styles-frontend-style-inline-css"> 225:root { --font-headings: unset; --font-base: unset; --font-headings-default: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif; --font-base-default: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;} 226/*# sourceURL=jetpack-global-styles-frontend-style-inline-css */ 227</style> 228<link crossorigin='anonymous' rel='stylesheet' id='all-css-18-1' href='/wp-content/themes/h4/global.css?m=1420737423i&cssminify=yes' type='text/css' media='all' />
229<script id="wpcom-actionbar-placeholder-js-extra"> 230var actionbardata = {"siteID":"12038026","postID":"0","siteURL":"https://andrewtwest.com","xhrURL":"https://andrewtwest.com/wp-admin/admin-ajax.php","nonce":"f242555163","isLoggedIn":"","statusMessage":"","statusSubscribed":"","subsEmailDefault":"instantly","proxyScriptUrl":"https://s0.wp.com/wp-content/js/wpcom-proxy-request.js?m=1513050504i&ver=20211021","i18n":{"followedText":"New posts from this site will now appear in your \u003Ca href=\"https://wordpress.com/reader\"\u003EReader\u003C/a\u003E","foldBar":"Collapse this bar","unfoldBar":"Expand this bar","shortLinkCopied":"Copied to clipboard."}}; 231//# sourceURL=wpcom-actionbar-placeholder-js-extra 232</script>
vendor: 1 bytes, line 232
232
233<script id="jetpack-mu-wpcom-settings-js-before"> 234var JETPACK_MU_WPCOM_SETTINGS = {"assetsUrl":"https://s1.wp.com/wp-content/mu-plugins/jetpack-mu-wpcom-plugin/moon/jetpack_vendor/automattic/jetpack-mu-wpcom/src/build/"}; 235//# sourceURL=jetpack-mu-wpcom-settings-js-before 236</script>
vendor: 1 bytes, line 236
236
237<script crossorigin='anonymous' type='text/javascript' src='/_static/??/wp-content/js/rlt-proxy.js,/wp-content/blog-plugins/wordads-classes/js/cmp/v2/cmp-non-gdpr.js?m=1780567333j'></script>
vendor: 1 bytes, line 237
237
238<script id="rlt-proxy-js-after"> 239 rltInitialize( {"token":null,"iframeOrigins":["https:\/\/widgets.wp.com"]} ); 240//# sourceURL=rlt-proxy-js-after 241</script>
241 242<link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://andrewtwest.wordpress.com/xmlrpc.php?rsd" /> 243<meta name="generator" content="WordPress.com" /> 244<link rel='shortlink' href='https://wp.me/OvDI' /> 245 246<!-- Jetpack Open Graph Tags --> 247<meta property="og:type" content="website" /> 248<meta property="og:title" content="The Public Void" /> 249<meta property="og:description" content="Andy West's Blog: Software Development and More" /> 250<meta property="og:url" content="https://andrewtwest.com/" /> 251<meta property="og:site_name" content="The Public Void" /> 252<meta property="og:image" content="https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=200&ts=1791051773" /> 253<meta property="og:image:width" content="200" /> 254<meta property="og:image:height" content="200" /> 255<meta property="og:image:alt" content="" /> 256<meta property="og:locale" content="en_US" /> 257 258<!-- End Jetpack Open Graph Tags --> 259<link rel="shortcut icon" type="image/x-icon" href="https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=32" sizes="16x16" /> 260<link rel="icon" type="image/x-icon" href="https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=32" sizes="16x16" /> 261<link rel="apple-touch-icon" href="https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=114" /> 262<link rel='openid.server' href='https://andrewtwest.com/?openidserver=1' /> 263<link rel='openid.delegate' href='https://andrewtwest.com/' /> 264<link rel="search" type="application/opensearchdescription+xml" href="https://andrewtwest.com/osd.xml" title="The Public Void" /> 265<link rel="search" type="application/opensearchdescription+xml" href="https://s1.wp.com/opensearch.xml" title="WordPress.com" /> 266<meta name="description" content="Andy West's Blog: Software Development and More" />
267<script> 268var wa_client = {}; wa_client.cmd = []; wa_client.config = { 'blog_id': 12038026, 'blog_language': 'en', 'is_wordads': false, 'hosting_type': 0, 'afp_account_id': null, 'afp_host_id': 5038568878849053, 'theme': 'pub/independent-publisher-2', '_': { 'title': 'Advertisement', 'privacy_settings': 'Privacy Settings' }, 'formats': [ 'belowpost', 'bottom_sticky', 'sidebar_sticky_right', 'sidebar', 'gutenberg_rectangle', 'gutenberg_leaderboard', 'gutenberg_mobile_leaderboard', 'gutenberg_skyscraper' ] }; 269</script>
269 270
270<script type="text/javascript"> 271 272 window.doNotSellCallback = function() { 273 274 var linkElements = [ 275 'a[href="https://wordpress.com/?ref=footer_blog"]', 276 'a[href="https://wordpress.com/?ref=footer_website"]', 277 'a[href="https://wordpress.com/?ref=vertical_footer"]', 278 'a[href^="https://wordpress.com/?ref=footer_segment_"]', 279 ].join(','); 280 281 var dnsLink = document.createElement( 'a' ); 282 dnsLink.href = 'https://wordpress.com/advertising-program-optout/'; 283 dnsLink.classList.add( 'do-not-sell-link' ); 284 dnsLink.rel = 'nofollow'; 285 dnsLink.style.marginLeft = '0.5em'; 286 dnsLink.textContent = 'Do Not Sell or Share My Personal Information'; 287 288 var creditLinks = document.querySelectorAll( linkElements ); 289 290 if ( 0 === creditLinks.length ) { 291 return false; 292 } 293 294 Array.prototype.forEach.call( creditLinks, function( el ) { 295 el.insertAdjacentElement( 'afterend', dnsLink ); 296 }); 297 298 return true; 299 }; 300 301 </script>
301 302
302<script type="text/javascript"> 303 window.google_analytics_uacct = "UA-52447-2"; 304</script>
304 305
306<script type="text/javascript"> 307 var _gaq = _gaq || []; 308 _gaq.push(['_setAccount', 'UA-52447-2']); 309 _gaq.push(['_gat._anonymizeIp']); 310 _gaq.push(['_setDomainName', 'none']); 311 _gaq.push(['_setAllowLinker', true]); 312 _gaq.push(['_initData']); 313 _gaq.push(['_trackPageview']); 314 315 (function() { 316 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; 317 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 318 (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(ga); 319 })(); 320</script>
320 321<link crossorigin='anonymous' rel='stylesheet' id='all-css-0-4' href='/_static/??-eJydjdEKwjAMRX/ImolC3cPYp0iXhdEtTUrTMvx7EdRHER/P4XIu7NmhSiWpkJrL3JYoBivVHHB7MSRVgVsUhIkVNwPbY6ZyRLMD/F5IOjcmAwxFmxF/Rm/xb7BGptktgZnK/Rs9D8Y0nHzfXS/e+/P6AHl7YJA=&cssminify=yes' type='text/css' media='all' /> 322 323</head> 324 325<body class="home blog paged wp-embed-responsive paged-2 wp-theme-pubindependent-publisher-2 customizer-styles-applied has-sidebar jetpack-reblog-enabled"> 326 327<div id="page" class="hfeed site"> 328 <a class="skip-link screen-reader-text" href="#content">Skip to content</a> 329 330 <div id="hero-header" class="site-hero-section"> 331 <header id="masthead" class="site-header" role="banner"> 332 <div class="inner"> 333 <div class="site-branding"> 334 335 <a class="site-logo-link" href="https://andrewtwest.com/"> 336 <img referrerpolicy="no-referrer" alt='Unknown's avatar' src='https://1.gravatar.com/avatar/48c9a549f35738b795067e5b733ada1deefd788cdaeb51662e1c39fd7fbab581?s=80&d=identicon&r=G' srcset='https://1.gravatar.com/avatar/48c9a549f35738b795067e5b733ada1deefd788cdaeb51662e1c39fd7fbab581?s=80&d=identicon&r=G 1x, https://1.gravatar.com/avatar/48c9a549f35738b795067e5b733ada1deefd788cdaeb51662e1c39fd7fbab581?s=120&d=identicon&r=G 1.5x, https://1.gravatar.com/avatar/48c9a549f35738b795067e5b733ada1deefd788cdaeb51662e1c39fd7fbab581?s=160&d=identicon&r=G 2x, https://1.gravatar.com/avatar/48c9a549f35738b795067e5b733ada1deefd788cdaeb51662e1c39fd7fbab581?s=240&d=identicon&r=G 3x, https://1.gravatar.com/avatar/48c9a549f35738b795067e5b733ada1deefd788cdaeb51662e1c39fd7fbab581?s=320&d=identicon&r=G 4x' class='avatar avatar-80 site-logo-image' height='80' width='80' loading='eager' decoding='async' /> </a><!-- .site-logo-link --> 337 <h1 class="site-title"><a href="https://andrewtwest.com/" rel="home">The Public Void</a></h1> 338 <p class="site-description">Andy West's Blog: Software Development and More</p> 339 </div><!-- .site-branding --> 340 341 342 343 </div><!-- .inner --> 344 </header><!-- #masthead --> 345 </div> 346 347 348 349 350 <div id="content-wrapper" class="content-wrapper"> 351 <div id="content" class="site-content"> 352 353 <div id="primary" class="content-area"> 354 <main id="main" class="site-main" role="main"> 355 356 357 358 359 360<article id="post-376" class="post-376 post type-post status-publish format-standard hentry category-uncategorized tag-compatibility-view tag-ie8 tag-intranet tag-web-standards"> 361 <header class="entry-header"> 362 <h1 class="entry-title"><a href="https://andrewtwest.com/2011/02/23/same-markup-same-browser-different-results/" rel="bookmark">Same Markup, Same Browser, Different Results</a></h1> </header><!-- .entry-header --> 363 <div class="entry-content"> 364 <p>Here is a simple HTML5 page I created:</p> 365<pre class="brush: xml; title: ; notranslate" title=""> 366<!DOCTYPE html> 367<html lang="en"> 368<head> 369 <meta charset="utf-8" /> 370 <title>Inconsistent Rendering</title> 371</head> 372<body> 373 <span style="height: 1px; overflow: visible; background-color: Green;"> 374 <h1>This is a test.</h1> 375 </span> 376</body> 377</html> 378</pre> 379<p>And here is that page rendered in Internet Explorer 8. Â In one case itâs being served on my laptop, and the other on the local intranet.</p> 380<p><a href="https://andrewtwest.com/wp-content/uploads/2011/02/localhost.png"><img data-attachment-id="379" data-permalink="https://andrewtwest.com/2011/02/23/same-markup-same-browser-different-results/localhost/" data-orig-file="https://andrewtwest.com/wp-content/uploads/2011/02/localhost.png" data-orig-size="376,276" data-comments-opened="1" data-image-title="Test file on localhost" data-image-description="<p>Test file on localhost</p> 381" data-image-caption="" data-large-file="https://andrewtwest.com/wp-content/uploads/2011/02/localhost.png?w=376" class="aligncenter size-full wp-image-379" title="Test file on localhost" src="https://andrewtwest.com/wp-content/uploads/2011/02/localhost.png?w=1100" alt="Test file on localhost" srcset="https://andrewtwest.com/wp-content/uploads/2011/02/localhost.png 376w, https://andrewtwest.com/wp-content/uploads/2011/02/localhost.png?w=150&h=110 150w, https://andrewtwest.com/wp-content/uploads/2011/02/localhost.png?w=300&
381h=220 300w" sizes="(max-width: 376px) 100vw, 376px" /></a></p> 382<p><a href="https://andrewtwest.com/wp-content/uploads/2011/02/localhost.png"></a><a href="https://andrewtwest.com/wp-content/uploads/2011/02/intranet1.png"><img data-attachment-id="383" data-permalink="https://andrewtwest.com/2011/02/23/same-markup-same-browser-different-results/intranet/" data-orig-file="https://andrewtwest.com/wp-content/uploads/2011/02/intranet1.png" data-orig-size="376,276" data-comments-opened="1" data-image-title="Test file on intranet" data-image-description="<p>Test file on intranet</p> 383" data-image-caption="" data-large-file="https://andrewtwest.com/wp-content/uploads/2011/02/intranet1.png?w=376" class="aligncenter size-full wp-image-383" title="Test file on intranet" src="https://andrewtwest.com/wp-content/uploads/2011/02/intranet1.png?w=1100" alt="Test file on intranet" srcset="https://andrewtwest.com/wp-content/uploads/2011/02/intranet1.png 376w, https://andrewtwest.com/wp-content/uploads/2011/02/intranet1.png?w=150&h=110 150w, https://andrewtwest.com/wp-content/uploads/2011/02/intranet1.png?w=300&h=220 300w" sizes="(max-width: 376px) 100vw, 376px" /></a></p> 384<p>The markup, the Web servers, and the browser are all set up 100% the same. Â These should be identical, shouldnât they? Â Whatâs the problem? Â The answer is Compatibility View.</p> 385<p>Compatibility View is a âfeatureâ of Internet Explorer that causes it to ignore modern Web standards. Â That would be fine, except Compatibility View settings vary by zone, and different zones have different defaults. Â Also, the Compatibility View button in the address bar isnât always available, which means thereâs no visual indicator as to what mode youâre in, and you canât change modes for the current page easily.</p> 386<p>Compatibility View settings can be accessed in the Tools –> Compatibility View Settings menu, but if youâve developed a standards compliant intranet site, you need a better fix than simply asking each individual user to reconfigure their browser. Â Group Policy is one option, but there is a much simpler solution. Â Just add the following meta tag to your pages, and it will force IE 8 to use the !DOCTYPE declaration in the page to determine the rendering mode.</p> 387<pre class="brush: xml; title: ; notranslate" title=""> 388<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE8" /> 389</pre> 390<p>If you’re experiencing rendering inconsistencies with the same markup being served from different environments, have a look into Compatibility View. It just might be the culprit.</p> 391 </div><!-- .entry-content --> 392 393 <footer class="entry-footer"> 394 395 <div class="entry-meta"> 396 <span class="byline"> 397 <a href="https://andrewtwest.com/author/divinerecursion/" rel="author">Andy West</a> </span> 398 <span class="cat-links"> 399 <a href="https://andrewtwest.com/category/uncategorized/" rel="category tag">Uncategorized</a> </span><!-- .cat-links --> 400 401 <span class="comments-link"><a href="https://andrewtwest.com/2011/02/23/same-markup-same-browser-different-results/#comments">2 Comments</a></span><!-- .comments-link --> 402 <span class="published-on"> 403 <a href="https://andrewtwest.com/2011/02/23/same-markup-same-browser-different-results/" rel="bookmark"><time class="entry-date published" datetime="2011-02-23T21:34:17-08:00">February 23, 2011</time><time class="updated" datetime="2011-02-23T22:00:31-08:00">February 23, 2011</time></a> 404 </span> 405 406 </div><!-- .entry-meta --> 407 </footer><!-- .entry-footer --> 408</article><!-- #post-## --> 409 410 411 412<article id="post-362" class="post-362 post type-post status-publish format-standard hentry category-uncategorized tag-00changelog tag-access-is-denied tag-hg tag-http-error-500 tag-mercurial tag-permissions tag-push"> 413 <header class="entry-header"> 414 <h1 class="entry-title"><a href="https://andrewtwest.com/2011/01/13/mercurial-http-error-500-access-is-denied-on-00changelog-i/" rel="bookmark">Mercurial HTTP Error 500: Access is denied on 00changelog.i</a></h1> </header><!-- .entry-header --> 415 <div class="entry-content"> 416 <p>Today I created a new Mercurial repository on a Windows server. Â I cloned it, made some changes, tried to push, and was greeted with this:</p> 417<p><code>C:\myapplication>hg push<br /> 418pushing to http://servername/myapplication<br /> 419searching for changes<br /> 420abort: HTTP Error 500: .hg\store0changelog.i: Access is denied</code></p> 421<p>My user account had write permission to the <strong>myapplication </strong>folder on the server, and the odd thing is that Iâve created repositories there before and never had a problem pushing changes. Â I compared <strong>00changelog.i</strong> to the same file in another repository that was working. Â Turns out I was using anonymous authentication and <strong>IUSR </strong>was missing write permission. Â I gave full control to <strong>IUSR </strong>on <strong>hg\store</strong> folder and…</p> 422<p><code>C:\myapplication>hg push<br /> 423pushing to http://servername/myapplication<br /> 424searching for changes<br /> 425remote: adding changesets<br /> 426remote: adding manifests<br /> 427remote: adding file changes<br /> 428remote: added 1 changesets with 114 changes to 114 files</code></p> 429<p>Success!</p> 430<p>If youâre having problems pushing to a central server with Mercurial, make sure <del>the IIS anonymous authentication account (<strong>IUSR </strong>or <strong>IUSR_<em>MachineName</em></strong>)</del> you have write permission to the <strong>hg\store</strong> folder and subfolders in your repository.</p> 431<div id="atatags-370373-6ac147fd7e200"> 432
432<script type="text/javascript"> 433 __ATA = window.__ATA || {}; 434 __ATA.cmd = window.__ATA.cmd || []; 435 __ATA.cmd.push(function() { 436 __ATA.initVideoSlot('atatags-370373-6ac147fd7e200', { 437 sectionId: '370373', 438 format: 'inread' 439 }); 440 }); 441 </script>
441 442 </div> </div><!-- .entry-content --> 443 444 <footer class="entry-footer"> 445 446 <div class="entry-meta"> 447 <span class="byline"> 448 <a href="https://andrewtwest.com/author/divinerecursion/" rel="author">Andy West</a> </span> 449 <span class="cat-links"> 450 <a href="https://andrewtwest.com/category/uncategorized/" rel="category tag">Uncategorized</a> </span><!-- .cat-links --> 451 452 <span class="comments-link"><a href="https://andrewtwest.com/2011/01/13/mercurial-http-error-500-access-is-denied-on-00changelog-i/#comments">4 Comments</a></span><!-- .comments-link --> 453 <span class="published-on"> 454 <a href="https://andrewtwest.com/2011/01/13/mercurial-http-error-500-access-is-denied-on-00changelog-i/" rel="bookmark"><time class="entry-date published" datetime="2011-01-13T21:19:47-08:00">January 13, 2011</time><time class="updated" datetime="2011-01-14T23:32:18-08:00">January 14, 2011</time></a> 455 </span> 456 457 </div><!-- .entry-meta --> 458 </footer><!-- .entry-footer --> 459</article><!-- #post-## --> 460 461 462 463<article id="post-340" class="post-340 post type-post status-publish format-standard hentry category-uncategorized tag-asp-net-mvc tag-data-annotations tag-model-state tag-validation"> 464 <header class="entry-header"> 465 <h1 class="entry-title"><a href="https://andrewtwest.com/2011/01/10/conditional-validation-with-data-annotations-in-asp-net-mvc/" rel="bookmark">Conditional Validation with Data Annotations in ASP.NET MVC</a></h1> </header><!-- .entry-header --> 466 <div class="entry-content"> 467 <p>In the <a href="https://bitbucket.org/andrewtwest/dotblog" target="_blank">simple blog engine</a> Iâm building, I encountered a scenario where I wanted to display different UI elements depending on whether the user was logged in:</p> 468<figure data-shortcode="caption" id="attachment_346" aria-describedby="caption-attachment-346" style="width: 293px" class="wp-caption aligncenter"><a href="https://andrewtwest.com/wp-content/uploads/2011/01/leave_reply.png"><img data-attachment-id="346" data-permalink="https://andrewtwest.com/2011/01/10/conditional-validation-with-data-annotations-in-asp-net-mvc/leave_reply/" data-orig-file="https://andrewtwest.com/wp-content/uploads/2011/01/leave_reply.png" data-orig-size="293,322" data-comments-opened="1" data-image-title="Comment Form" data-image-description="" data-image-caption="" data-large-file="https://andrewtwest.com/wp-content/uploads/2011/01/leave_reply.png?w=293" class="size-full wp-image-346" style="border:1px solid #999999;" title="Comment Form" src="https://andrewtwest.com/wp-content/uploads/2011/01/leave_reply.png?w=1100" alt="Comment Form" srcset="https://andrewtwest.com/wp-content/uploads/2011/01/leave_reply.png 293w, https://andrewtwest.com/wp-content/uploads/2011/01/leave_reply.png?w=136&h=150 136w" sizes="(max-width: 293px) 100vw, 293px" /></a><figcaption id="caption-attachment-346" class="wp-caption-text">Not logged in</figcaption></figure> 469<p> </p> 470<figure data-shortcode="caption" id="attachment_347" aria-describedby="caption-attachment-347" style="width: 288px" class="wp-caption aligncenter"><a href="https://andrewtwest.com/wp-content/uploads/2011/01/leave_reply_logged_in.png"><img data-attachment-id="347" data-permalink="https://andrewtwest.com/2011/01/10/conditional-validation-with-data-annotations-in-asp-net-mvc/leave_reply_logged_in/" data-orig-file="https://andrewtwest.com/wp-content/uploads/2011/01/leave_reply_logged_in.png" data-orig-size="288,232" data-comments-opened="1" data-image-title="Comment Form Logged In" data-image-description="" data-image-caption="<p>Comment Form Logged In</p> 471" data-large-file="https://andrewtwest.com/wp-content/uploads/2011/01/leave_reply_logged_in.png?w=288" loading="lazy" class="size-full wp-image-347 " style="border:1px solid #999999;" title="Comment Form Logged In" src="https://andrewtwest.com/wp-content/uploads/2011/01/leave_reply_logged_in.png?w=1100" alt="Comment Form Logged In" srcset="https://andrewtwest.com/wp-content/uploads/2011/01/leave_reply_logged_in.png 288w, https://andrewtwest.com/wp-content/uploads/2011/01/leave_reply_logged_in.png?w=150&h=121 150w" sizes="(max-width: 288px) 100vw, 288px" /></a><figcaption id="caption-attachment-347" class="wp-caption-text">Logged in</figcaption></figure> 472<p> </p> 473<p>When the user is authenticated, their name and email is known, so itâs unnecessary to display them on the comment input form. Â While it would be possible to hide just those fields, I decided to make separate partial views and display them in the Post view with the following code:</p> 474<pre class="brush: csharp; title: ; notranslate" title=""> 475<% 476 if (Model.AllowComments) 477 { 478 var commentControlName = Request.IsAuthenticated ? AuthenticatedCommentFormControl" : "CommentFormControl"; 479 Html.RenderPartial(commentControlName, new DotBlog.Models.ViewModels.CommentViewModel(Model.PostId)); 480 } 481%> 482</pre> 483<p>This is the view model I used for both partial views:</p> 484<pre class="brush: csharp; title: ; notranslate" title=""> 485public class CommentViewModel 486{ 487 ... 488 489 [Required] 490 [StringLength(50)] 491 [DisplayName("Name")] 492 public string CommenterName { get; set; } 493 494 public DateTime Date { get; set; } 495 496 [Required] 497 [StringLength(100)] 498 public string Email { get; set; } 499 500 [StringLength(100)] 501 [DisplayName("Web Site")] 502 public string WebSite { get; set; } 503 504 [Required] 505 [StringLength(1024)] 506 [DisplayName("Comment")] 507 public string CommentText { get; set; } 508 509 ... 510} 511</pre> 512<p>As you can see, Iâm using data annotations to enforce required fields and string lengths. Â The problem is, even though the name and email arenât always displayed, they are still required. Â I needed a way to validate certain fields conditionally. Â Here are the options I came up with:</p> 513<ul> 514<li>Stop using data annotations and find a different solution for validation</li> 515<li>Use two different view models: one for each partial view</li> 516<li>Use actual conditional data annotations, like <a href="http://blogs.msdn.com/b/simonince/archive/2010/06/04/conditional-validation-in-mvc.aspx" target="_blank">the library built by Simon Ince</a>.</li> 517<li>When the form is posted, remove the fields from the model state so theyâre not validated.</li> 518</ul> 519<p> </p> 520<p>Letâs look at each of these individually:</p> 521<h2>Stop Using Data Annotations</h2> 522<p>Data annotations are not the only way to specify validation rules, but theyâre easy to implement. Â xVal was fine for ASP.MVC 1.0, but is now deprecated. Â Custom validation code with ModelState.AddModelError() is flexible, but requires extra work.</p> 523<h2>Use Two Different View Models</h2> 524<p>
524Since Iâm using two partial views for the comment form (one for authenticated users and one for guests), I could use a dedicated view model for each.  One would omit the data annotations on name and email and therefore not cause any validation problems.  This was my original implementation, but lead to unnecessary code duplication and other design problems.</p> 525<h2>Use Conditional Data Annotations</h2> 526<p>Simon Ince has built <a href="http://blogs.msdn.com/b/simonince/archive/2010/06/04/conditional-validation-in-mvc.aspx" target="_blank">a cool library</a> for conditional annotations that allows you to write code like this:</p> 527<pre class="brush: csharp; title: ; notranslate" title=""> 528public class ValidationSample 529{ 530 [RequiredIf("PropertyValidationDependsOn", true)] 531 public string PropertyToValidate { get; set; } 532 533 public bool PropertyValidationDependsOn { get; set; } 534} 535</pre> 536<h2>Conditionally Remove Fields from the Model State in the Controller</h2> 537<p>In the end, this is the solution I went with.  The controller executes this code when the form is posted:</p> 538<pre class="brush: csharp; title: ; notranslate" title=""> 539if (Request.IsAuthenticated) 540{ 541 ... 542 543 // We don't need to validate user fields if user is logged in. 544 ModelState.Remove("CommenterName"); 545 ModelState.Remove("Email"); 546} 547</pre> 548<p>By removing the fields from the model state, it wonât be invalid when they are missing.  This method is simple and avoids adding additional dependencies.</p> 549 </div><!-- .entry-content --> 550 551 <footer class="entry-footer"> 552 553 <div class="entry-meta"> 554 <span class="byline"> 555 <a href="https://andrewtwest.com/author/divinerecursion/" rel="author">Andy West</a> </span> 556 <span class="cat-links"> 557 <a href="https://andrewtwest.com/category/uncategorized/" rel="category tag">Uncategorized</a> </span><!-- .cat-links --> 558 559 <span class="comments-link"><a href="https://andrewtwest.com/2011/01/10/conditional-validation-with-data-annotations-in-asp-net-mvc/#comments">7 Comments</a></span><!-- .comments-link --> 560 <span class="published-on"> 561 <a href="https://andrewtwest.com/2011/01/10/conditional-validation-with-data-annotations-in-asp-net-mvc/" rel="bookmark"><time class="entry-date published updated" datetime="2011-01-10T20:54:54-08:00">January 10, 2011</time></a> 562 </span> 563 564 </div><!-- .entry-meta --> 565 </footer><!-- .entry-footer --> 566</article><!-- #post-## --> 567 568 569 570<article id="post-324" class="post-324 post type-post status-publish format-standard hentry category-uncategorized tag-bug tag-entity-framework tag-nhibernate tag-storegeneratedpattern"> 571 <header class="entry-header"> 572 <h1 class="entry-title"><a href="https://andrewtwest.com/2010/10/24/when-will-the-entity-framework-storegeneratedpattern-bug-go-away/" rel="bookmark">Entity Framework StoreGeneratedPattern Bug Persists</a></h1> </header><!-- .entry-header --> 573 <div class="entry-content"> 574 <p>Iâm using System.Data.SQLite v1.0.66.0 with Entity Framework 4.0 and Visual Studio 2010.  I designed some tables in SQLite and generated an Entity Data Model from those tables.  One of them (weâll call it <strong>Person </strong>for the sake of argument) has an autogenerated integer primary key.  I manually set the <strong>StoreGeneratedPattern </strong>property to <strong>Identity </strong>in the designer, but when I started creating new rows in the database I encountered a problem.</p> 575<p>I create new <strong>Person </strong>entities with a dummy <strong>PersonID </strong>of -1.  The first row inserts fine, but instead of generating a new ID it uses the dummy value.  That means when I insert the second row, it fails:</p> 576<blockquote><p>Abort due to constraint violation<br /> 577PRIMARY KEY must be unique</p></blockquote> 578<p>I did a little Googling and realized Iâm not the only person experiencing this:</p> 579<ul> 580<li><a href="http://geeksharp.com/2010/05/27/ef4-bug-in-storegeneratedpattern-ssdl/" target="_blank">EF4: Bug in StoreGeneratedPattern SSDL | geek#</a></li> 581<li><a href="http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/404d3017-01b7-4129-8e05-f4aa48f15f08" target="_blank">edmx designer properties does not set StoreGeneratedPattern=”Computed” in SSDL</a></li> 582<li><a href="http://stackoverflow.com/questions/2995086/storegeneratedpattern-in-entitiy-framework" target="_blank">StoreGeneratedPattern in Entitiy framework – Stack Overflow</a></li> 583</ul> 584<p>It seems there is a bug in which the <strong>StoragePattern </strong>property is not updated in the SSDL when you change it in the designer, even though the CSDL is.</p> 585<p>The impact of this is that you have to open the .edmx file in the XML editor and manually add the <strong>StorageGeneratedPattern </strong>property to the definition for your entity in the <strong>StorageModels </strong>section:</p> 586<pre class="brush: xml; title: ; notranslate" title=""> 587<EntityType Name="Person"> 588 <Key> 589 <PropertyRef Name="PersonID" /> 590 </Key> 591 <Property Name="PersonID" Type="integer" Nullable="false" StoreGeneratedPattern="Identity" /> 592 <Property Name="Name" Type="nvarchar" Nullable="false" MaxLength="50" /> 593 <Property Name="Age" Type="integer" Nullable="false" /> 594</EntityType> 595</pre> 596<p>Even worse, youâll have to do this for every identity column every time you update the model from the database because the property gets clobbered.  The workaround does work, technically, but itâs a major nuisance during development when things change often.</p> 597<p>Identity columns are not uncommon, which means that this issue should have been uncovered early during testing.  Why didnât Microsoft fix it right away?  According to some claims, itâs been around since EF 1.0.  In a couple of weeks Iâm starting a new job where they use NHibernate.  It will be interesting to compare it to EF 4.0 and see if I run into the same kind of bugs. Perhaps it will also help to wean me off graphical designers altogether.</p> 598 </div><!-- .entry-content --> 599 600 <footer class="entry-footer"> 601 602 <div class="entry-meta"> 603 <span class="byline">
604 <a href="https://andrewtwest.com/author/divinerecursion/" rel="author">Andy West</a> </span> 605 <span class="cat-links"> 606 <a href="https://andrewtwest.com/category/uncategorized/" rel="category tag">Uncategorized</a> </span><!-- .cat-links --> 607 608 <span class="comments-link"><a href="https://andrewtwest.com/2010/10/24/when-will-the-entity-framework-storegeneratedpattern-bug-go-away/#comments">4 Comments</a></span><!-- .comments-link --> 609 <span class="published-on"> 610 <a href="https://andrewtwest.com/2010/10/24/when-will-the-entity-framework-storegeneratedpattern-bug-go-away/" rel="bookmark"><time class="entry-date published" datetime="2010-10-24T18:54:00-08:00">October 24, 2010</time><time class="updated" datetime="2010-10-24T22:01:05-08:00">October 24, 2010</time></a> 611 </span> 612 613 </div><!-- .entry-meta --> 614 </footer><!-- .entry-footer --> 615</article><!-- #post-## --> 616 617 618 619<article id="post-315" class="post-315 post type-post status-publish format-standard hentry category-uncategorized tag-sqlite tag-unique-constraint tag-unique-index"> 620 <header class="entry-header"> 621 <h1 class="entry-title"><a href="https://andrewtwest.com/2010/10/17/multi-column-unique-constraints-in-sqlite-net/" rel="bookmark">Multi-Column Unique Constraints in SQLite.NET</a></h1> </header><!-- .entry-header --> 622 <div class="entry-content"> 623 <p>While working on my blog engine project to learn ASP.NET MVC and Entity Framework, I encountered a common scenario. Â Iâm using SQLite on the back-end, and I needed a unique constraint across two columns. Â As demonstrated in <a href="http://stackoverflow.com/questions/2701877/sqlite-table-constraint-unique-on-multiple-columns" target="_blank">this stackoverflow question</a>, you can specify a unique table constraint immediately after the column definitions when using the CREATE TABLE command. Â However, for the purpose of rapid prototyping, I prefer using <a href="http://sqlite.phxsoftware.com/" target="_blank">SQLite.NET</a> and the graphical Server Explorer interface in Visual Studio rather than explicit DDL to define my tables.</p> 624<p>The problem is that the GUI-based designer is still in development and doesnât support unique table constraints. Â One solution is to create a unique index instead. Â Right-click one of the row headers in the table designer and select Indexes/Keys…</p> 625<p><a href="https://andrewtwest.com/wp-content/uploads/2010/10/table_design_context_menu.png"><img data-attachment-id="316" data-permalink="https://andrewtwest.com/2010/10/17/multi-column-unique-constraints-in-sqlite-net/table_design_context_menu/" data-orig-file="https://andrewtwest.com/wp-content/uploads/2010/10/table_design_context_menu.png" data-orig-size="281,279" data-comments-opened="1" data-image-title="Table design context menu" data-image-description="" data-image-caption="" data-large-file="https://andrewtwest.com/wp-content/uploads/2010/10/table_design_context_menu.png?w=281" loading="lazy" class="aligncenter size-full wp-image-316" title="Table design context menu" src="https://andrewtwest.com/wp-content/uploads/2010/10/table_design_context_menu.png?w=1100" alt="Table design context menu" srcset="https://andrewtwest.com/wp-content/uploads/2010/10/table_design_context_menu.png 281w, https://andrewtwest.com/wp-content/uploads/2010/10/table_design_context_menu.png?w=150&h=150 150w" sizes="(max-width: 281px) 100vw, 281px" /></a></p> 626<p>In the Index Editor, add a new index. Â Under the Misc category, set the Unique property to True, and under the Source category, list the columns you want in the index, separated by commas.</p> 627<p><a href="https://andrewtwest.com/wp-content/uploads/2010/10/index_editor.png"><img data-attachment-id="317" data-permalink="https://andrewtwest.com/2010/10/17/multi-column-unique-constraints-in-sqlite-net/index_editor/" data-orig-file="https://andrewtwest.com/wp-content/uploads/2010/10/index_editor.png" data-orig-size="633,465" data-comments-opened="1" data-image-title="Index editor" data-image-description="" data-image-caption="" data-large-file="https://andrewtwest.com/wp-content/uploads/2010/10/index_editor.png?w=633" loading="lazy" class="aligncenter size-full wp-image-317" title="Index editor" src="https://andrewtwest.com/wp-content/uploads/2010/10/index_editor.png?w=1100" alt="Index editor" srcset="https://andrewtwest.com/wp-content/uploads/2010/10/index_editor.png?w=497&h=365 497w, https://andrewtwest.com/wp-content/uploads/2010/10/index_editor.png?w=150&h=110 150w, https://andrewtwest.com/wp-content/uploads/2010/10/index_editor.png?w=300&h=220 300w, https://andrewtwest.com/wp-content/uploads/2010/10/index_editor.png 633w" sizes="(max-width: 497px) 100v
627w, 497px" /></a></p> 628<p>This works because, <a href="http://www.sqlite.org/lang_createtable.html" target="_blank">as stated in the SQLite documentation</a>:</p> 629<blockquote><p><a href="http://www.sqlite.org/lang_createtable.html#rowid" target="_blank">INTEGER PRIMARY KEY</a> columns aside, both UNIQUE and PRIMARY KEY constraints are implemented by creating an index in the database (in the same way as a<a href="http://www.sqlite.org/lang_createindex.html" target="_blank"> “CREATE UNIQUE INDEX”</a> statement would).</p></blockquote> 630<p>Using the Index Editor to create an index with Unique = True generates a âCREATE UNIQUE INDEXâ statement behind the scenes, which can be verified by using the Generate Change Script… feature.</p> 631<p>In summary, if youâre thinking about using Server Explorer to create a multi-column unique constraint in SQLite, just go with a unique index, since thatâs how itâs implemented anyway.</p> 632 </div><!-- .entry-content --> 633 634 <footer class="entry-footer"> 635 636 <div class="entry-meta"> 637 <span class="byline"> 638 <a href="https://andrewtwest.com/author/divinerecursion/" rel="author">Andy West</a> </span> 639 <span class="cat-links"> 640 <a href="https://andrewtwest.com/category/uncategorized/" rel="category tag">Uncategorized</a> </span><!-- .cat-links --> 641 642 <span class="comments-link"><a href="https://andrewtwest.com/2010/10/17/multi-column-unique-constraints-in-sqlite-net/#respond">Leave a comment</a></span><!-- .comments-link --> 643 <span class="published-on"> 644 <a href="https://andrewtwest.com/2010/10/17/multi-column-unique-constraints-in-sqlite-net/" rel="bookmark"><time class="entry-date published updated" datetime="2010-10-17T19:58:07-08:00">October 17, 2010</time></a> 645 </span> 646 647 </div><!-- .entry-meta --> 648 </footer><!-- .entry-footer --> 649</article><!-- #post-## --> 650 651 652 653<article id="post-308" class="post-308 post type-post status-publish format-standard hentry category-uncategorized tag-presentation tag-public-speaking tag-user-group"> 654 <header class="entry-header"> 655 <h1 class="entry-title"><a href="https://andrewtwest.com/2010/09/12/how-to-survive-your-technical-presentation/" rel="bookmark">How to Survive Your Technical Presentation</a></h1> </header><!-- .entry-header --> 656 <div class="entry-content"> 657 <p>A few weeks ago I did a presentation on F# at a local user group meeting. Â It was an opportunity to learn something new, network with other developers, and improve my communication skills. Â Here are some of the things I learned from the experience.</p> 658<p style="text-align:center;"><a href="https://andrewtwest.com/wp-content/uploads/2010/09/fsharp_talk.jpg"><img data-attachment-id="312" data-permalink="https://andrewtwest.com/2010/09/12/how-to-survive-your-technical-presentation/fsharp_talk/" data-orig-file="https://andrewtwest.com/wp-content/uploads/2010/09/fsharp_talk.jpg" data-orig-size="455,342" data-comments-opened="1" data-image-title="My F# presentation" data-image-description="" data-image-caption="" data-large-file="https://andrewtwest.com/wp-content/uploads/2010/09/fsharp_talk.jpg?w=455" loading="lazy" class="aligncenter size-full wp-image-312" style="border:1px solid black;" title="My F# presentation" src="https://andrewtwest.com/wp-content/uploads/2010/09/fsharp_talk.jpg?w=1100" alt="My F# presentation" srcset="https://andrewtwest.com/wp-content/uploads/2010/09/fsharp_talk.jpg 455w, https://andrewtwest.com/wp-content/uploads/2010/09/fsharp_talk.jpg?w=150&h=113 150w, https://andrewtwest.com/wp-content/uploads/2010/09/fsharp_talk.jpg?w=300&h=225 300w" sizes="(max-width: 455px) 100vw, 455px" /></a></p> 659<h2>Know your subject well in advance</h2> 660<p>Building slides, writing code snippets and demos, and coming up with talking points are all difficult enough, not to mention the time it takes to practice your presentation thoroughly. Â Donât complicate matters by trying to learn a new language or technology from scratch.</p> 661<h2>Make friends with the experts in the room</h2> 662<p>Get knowledgeable attendees on your side right away. Â During my F# talk, I turned to them when confronted with questions I couldnât answer, and they bailed me out a couple of times.</p> 663<h2>Know your equipment inside and out</h2> 664<p>Try to keep things as simple as possible. Â The fewer tools you have to manage, the less chance something will go wrong. Â Arrive early so you can test your laptop, projector, and all your software. Â Make sure to have fresh batteries for your presentation remote and microphone. Â If at all possible, do a dry run with the actual equipment youâll be using during your talk.</p> 665<h2>Donât go over the allotted time</h2> 666<p>At one point while I was talking, a meeting attendee rose from his seat and left. Â It wasnât until then that I realized I had gone several minutes too long. Â The room was packed, but everyone was too polite to mention that it was time to leave.</p> 667<p>
667Ironically, I had worked very hard to fill that time with content. Â But the important thing to remember is that talking at a user group meeting isnât about filling dead air with noise; itâs about teaching and sharing information. Â Only say what is necessary and relevant, and then let your audience go home.</p> 668<h2>Donât be boring</h2> 669<p>This is probably easier said than done, but if you want to hold your audienceâs attention, you canât be dull and predictable. Â Own your presentation and make it unique. Â Record a video of yourself speaking and make sure you donât look like a robot, with monotonous speech and stiff movements.</p> 670<h2>Read <a href="http://www.amazon.com/Confessions-Public-Speaker-Scott-Berkun/dp/0596801998" target="_blank"><em>Confessions of a Public Speaker</em></a> by Scott Berkun</h2> 671<p>I didnât have to learn all these lessons on my own, and neither do you. Â In his book, Scott captures years worth of public speaking wisdom in two hundred brief and entertaining pages. Â I only wish I had read it earlier.</p> 672 </div><!-- .entry-content --> 673 674 <footer class="entry-footer"> 675 676 <div class="entry-meta"> 677 <span class="byline"> 678 <a href="https://andrewtwest.com/author/divinerecursion/" rel="author">Andy West</a> </span> 679 <span class="cat-links"> 680 <a href="https://andrewtwest.com/category/uncategorized/" rel="category tag">Uncategorized</a> </span><!-- .cat-links --> 681 682 <span class="comments-link"><a href="https://andrewtwest.com/2010/09/12/how-to-survive-your-technical-presentation/#respond">Leave a comment</a></span><!-- .comments-link --> 683 <span class="published-on"> 684 <a href="https://andrewtwest.com/2010/09/12/how-to-survive-your-technical-presentation/" rel="bookmark"><time class="entry-date published" datetime="2010-09-12T03:24:56-08:00">September 12, 2010</time><time class="updated" datetime="2010-09-12T03:33:00-08:00">September 12, 2010</time></a> 685 </span> 686 687 </div><!-- .entry-meta --> 688 </footer><!-- .entry-footer --> 689</article><!-- #post-## --> 690 691 692 693<article id="post-294" class="post-294 post type-post status-publish format-standard hentry category-uncategorized tag-asp-net tag-book-review tag-mvc"> 694 <header class="entry-header"> 695 <h1 class="entry-title"><a href="https://andrewtwest.com/2010/08/02/book-review-professional-asp-net-mvc-2/" rel="bookmark">Book Review: Professional ASP.NET MVC 2</a></h1> </header><!-- .entry-header --> 696 <div class="entry-content"> 697 <p>ASP.NET MVC is part of the broader ASP.NET framework, and serves as an alternative development model to that of ASP.NET Web Forms. Â It adheres to the Model-View-Controller architectural pattern, and offers developers greater control by bringing them closer to the underlying HTTP protocol. Â ASP.NET MVC leaves out many of the abstractions that Web Forms uses to hide the stateless nature of HTTP, such as ViewState and events. Â This is bewildering to some developers who are comfortable with the high-level, drag-and-drop nature of Web Forms, but itâs liberating to others who feel the Web Form philosophy is too restrictive, or <a href="http://blog.wekeroad.com/blog/i-spose-ill-just-say-it-you-should-learn-mvc/" target="_blank">even deceptive</a>.</p> 698<p>Several months ago, ASP.NET MVC 2 was released, and about a month ago, <em><a href="http://www.wrox.com/WileyCDA/WroxTitle/Professional-ASP-NET-MVC-2.productCd-0470643188.html" target="_blank">Professional ASP.NET MVC 2</a></em> hit the shelves. Â Some of the authors actually work on the ASP.NET team, which gives this book an authoritative feel. Â I decided to pick it up when I chose ASP.NET MVC as the core technology for my new blog engine.</p> 699<p>The first chapter is by far the longest, and gives readers a detailed tour of a fully-functioning, nontrivial sample application called âNerdDinnerâ. Â It introduces most of the important ASP.NET MVC concepts without being too overwhelming. Â Later chapters dive into these topics in more detail. Â <a href="http://nerddinner.codeplex.com/" target="_blank">Source code</a> for the application is hosted at CodePlex. Â You can also <a href="http://tinyurl.com/aspnetmvc" target="_blank">download this chapter for free</a> from the publisherâs Web site, or <a href="http://www.nerddinner.com/" target="_blank">view the app running live</a>.</p> 700<p>In Chapter 7, âAJAXâ, I was surprised to find the considerable attention paid to disabled-scripting scenarios. Â At first I was concerned about spending too much time supporting a very small percentage of users, but as it turns out, ASP.NET MVC lightens the load a lot with <a href="http://msdn.microsoft.com/en-us
700/library/system.web.mvc.ajaxrequestextensions.isajaxrequest.aspx" target="_blank">IsAjaxRequest()</a>.</p> 701<p>Chapter 9, which covers security, has some interesting stories and anecdotes, and Iâm sure it will be a great reference when Iâm making a security checklist for my own apps.  After Chapter 1 (NerdDinner), Chapter 9 is the most important chapter in the book — donât skip it!</p> 702<p>I was impressed with a side note in Chapter 10 that addressed a pet peeve of mine.  There is a code snippet that uses string concatenation with the + operator, rather than using a StringBuilder.  The snippet is correct, but the authors went out of their way to explain to inexperienced developers why StringBuilder should <em>not </em>have been used.  This is nothing new; Google developer Jon Skeet <a href="http://www.yoda.arachsys.com/csharp/stringbuilder.html" target="_blank">wrote an article about it</a> years ago, but I still die a little inside every time I see code like this:</p> 703<pre class="brush: csharp; title: ; notranslate" title=""> 704StringBuilder sb = new StringBuilder(); 705 706sb.Append("SELECT * "); 707sb.Append("FROM customer "); 708sb.Append("LEFT JOIN order "); 709sb.Append("ON (customer.customer_id = order.customer_id "); 710sb.Append("AND YEAR(order.order_date) = 2010) "); 711sb.Append("WHERE order.order_id IS NULL"); 712 713string s = sb.ToString(); 714</pre> 715<p>Chapter 11, âTestable Design Patternsâ, wants desperately to promote testability, but is afraid to offend anyone by doing so.  The entire first page is an apology to developers for recommending that they test their code.  Everybody has an opinion — if you think people should be writing testable apps, just come out and say it.</p> 716<p>Chapter 12 discusses using Web Forms and MVC together.  With the exception of master pages, I didnât find it particularly useful.  Iâm sure there are teams out there that want to migrate an existing app from Web Forms to MVC one piece at a time, but not me.  The more I read about MVC, the more Web Forms feels like Web development with training wheels.</p> 717<p>Throughout the text, the authors mentioned several tools they thought were useful, such as:</p> 718<ul> 719<li><a href="http://wpl.codeplex.com/" target="_blank">AntiXSS</a> provides a myriad of encoding functions for user input, including HTML, HTML attributes, XML, CSS and JavaScript.</li> 720<li><a href="http://watin.sourceforge.net/" target="_blank">WaitiN</a> is developed in C# and aims to bring you an easy way to automate your tests with Internet Explorer and FireFox using .Net.</li> 721<li><a href="http://code.google.com/p/moq/" target="_blank">moq</a> is designed to be a very practical, unobtrusive and straight-forward way to quickly setup dependencies for your tests.</li> 722</ul> 723<p>There are some errata in the book.  Some are minor technical errors, while others are typos or simple grammatical problems.  Several appear to be cut-and-paste mistakes that occurred in sections that were updated from MVC 1.0 to MVC 2. In total, I found about 30 non-verified errata.  Iâve submitted a few to the Wrox Web site, and Iâll be uploading the rest soon.</p> 724<p>Overall, <em>Professional ASP.NET MVC 2</em> is a thorough and engaging book on an alternative Web development framework thatâs full of controversy.  Itâs not afraid to step outside the boundaries of library functions and markup syntax, and explores many of the related tools and techniques needed to get the most out of the MVC approach.  I recommend it.</p> 725 </div><!-- .entry-content --> 726 727 <footer class="entry-footer"> 728 729 <div class="entry-meta"> 730 <span class="byline"> 731 <a href="https://andrewtwest.com/author/divinerecursion/" rel="author">Andy West</a> </span> 732 <span class="cat-links"> 733 <a href="https://andrewtwest.com/category/uncategorized/" rel="category tag">Uncategorized</a> </span><!-- .cat-links --> 734 735 <span class="comments-link"><a href="https://andrewtwest.com/2010/08/02/book-review-professional-asp-net-mvc-2/#respond">Leave a comment</a></span><!-- .comments-link --> 736 <span class="published-on"> 737 <a href="https://andrewtwest.com/2010/08/02/book-review-professional-asp-net-mvc-2/" rel="bookmark"><time class="entry-date published" datetime="2010-08-02T00:02:13-08:00">August 2, 2010</time><time class="updated" datetime="2010-08-03T15:00:30-08:00">August 3, 2010</time></a> 738 </span> 739 740 </div><!-- .entry-meta --> 741 </footer><!-- .entry-footer --> 742</article><!-- #post-## --> 743 744 745 746<article id="post-272" class="post-272 post type-post status-publish format-standard hentry category-uncategorized tag-beta tag-prototype tag-quplo tag-redesign"> 747 <header class="entry-header"> 748 <h1 class="entry-title"><a href="https://andrewtwest.com/2010/07/21/quplos-redesign-a-website-feature/" rel="bookmark">Quplo’s “Redesign a Website” Feature</a></h1> </header><!-- .entry-header --> 749 <div class="entry-content"> 750 <p>Last month I evaluated a preview of a new Web prototyping tool called Quplo and <a href="https://andrewtwest.com/2010/06/18/test-driving-the-quplo-preview/" target="_blank">
750wrote about it here</a>.  Since that time, Quplo beta has gone live, and the development team has added several new features and bug fixes.  Perhaps the most significant of these is a feature they call âredesign a websiteâ, which imports external HTML from a URL, cleans it, and creates a new sheet.  This gives designers an alternative way to create prototypes, and comes in handy when clients have an existing Website they want tweaked.</p> 751<p>To test Quploâs redesign capability, I chose the <a href="http://gcc.gnu.org/" target="_blank">GNU Compiler Collection</a> Web site, because itâs simple and contains mostly text.  Importing the main page was quick and painless.  Quplo created a sheet called âRedesignâ with the HTML. The following message was inserted at the top:</p> 752<pre><!-- This page contains the HTML from http://gcc.gnu.org/ 753 We've added a <base href=...> element to the <head> section. 754 CSS and images below it will load from the original site. 755 Put your custom CSS above it to mockup the site. --></pre> 756<p>What this means is that resources like CSS files and images are not imported with the siteâs markup.  They are requested from the server of the original site when you view your mockup.  Slightly further down the sheet is a comment that denotes the cutoff point for your new CSS.  Anything above that line will override the original siteâs CSS.</p> 757<pre><page url="/"> 758 <html> 759 <head> 760 <meta content="text/html; charset=iso-8859-1" /> 761 <strong><span style="color:#ff0000;"><!-- Place custom CSS above this line. --></span></strong> 762 ...</pre> 763<p>After the import, itâs time to start making changes.  First, I decided to alter the menu headers on the right-hand side.  Instead of a thin, dark border, I wanted a dark background color.  I added my custom CSS link above the cutoff line.</p> 764<pre><page url="/"> 765 <html> 766 <head> 767 <meta content="text/html; charset=iso-8859-1" /> 768 <strong><span style="color:#ff0000;"><link rel="stylesheet" type="text/css" href="custom.css" /></span></strong> 769 <!-- Place custom CSS above this line. --> 770 ...</pre> 771<p>Then I added a new sheet called CustomCSS with the overriding style.</p> 772<pre><page url="/custom.css"> 773td.td_title { 774 border-style: none; 775 color: #3366cc; 776 background-color: #d2d2d9; 777 font-weight: bold; 778} 779</page></pre> 780<p>The next thing I did was add a splash of color to the News and Status sections by adding the background-color attribute to the existing inline styles.  I also changed the padding to create an even border of color around the text.</p> 781<pre><td style="width: 50%; <span style="color:#ff0000;"><strong>padding: 8px; background-color: #20b0f0;</strong></span>" valign="top"></pre> 782<pre><td style="width: 50%; <span style="color:#ff0000;"><strong>padding: 12px;</strong></span> border-left: #3366cc thin solid; <span style="color:#ff0000;"><strong>background-color: #f0b020;</strong></span>" valign="top"></pre> 783<p>Finally, I moved the GCC logo from the right-hand side to the left by removing the deprecated align attribute and adding an inline style.</p> 784<pre><img src="img/gccegg-65.png" alt="" <strong><span style="color:#ff0000;">style="float: left;</span>"</strong> /></pre> 785<p>Here are the final results:</p> 786<figure data-shortcode="caption" id="attachment_273" aria-describedby="caption-attachment-273" style="width: 455px" class="wp-caption aligncenter"><a href="https://andrewtwest.com/wp-content/uploads/2010/07/gcc_before.png"><img data-attachment-id="273" data-permalink="https://andrewtwest.com/2010/07/21/quplos-redesign-a-website-feature/gcc_before/" data-orig-file="https://andrewtwest.com/wp-content/uploads/2010/07/gcc_before.png" data-orig-size="455,370" data-comments-opened="1" data-image-title="GCC Prototype Before" data-image-description="" data-image-caption="<p>GCC Prototype Before</p> 787" data-large-file="https://andrewtwest.com/wp-content/uploads/2010/07/gcc_before.png?w=455" loading="lazy" class="size-full wp-image-273 " title="GCC Site Before" src="https://andrewtwest.com/wp-content/uploads/2010/07/gcc_before.png?w=1100" alt="GCC Site Before" srcset="https://andrewtwest.com/wp-content/uploads/2010/07/gcc_before.png 455w, https://andrewtwest.com/wp-content/uploads/2010/07/gcc_before.png?w=150&
787h=122 150w, https://andrewtwest.com/wp-content/uploads/2010/07/gcc_before.png?w=300&h=244 300w" sizes="(max-width: 455px) 100vw, 455px" /></a><figcaption id="caption-attachment-273" class="wp-caption-text">GCC Site Before</figcaption></figure> 788<figure data-shortcode="caption" id="attachment_274" aria-describedby="caption-attachment-274" style="width: 455px" class="wp-caption aligncenter"><a href="https://andrewtwest.com/wp-content/uploads/2010/07/gcc_after.png"><img data-attachment-id="274" data-permalink="https://andrewtwest.com/2010/07/21/quplos-redesign-a-website-feature/gcc_after/" data-orig-file="https://andrewtwest.com/wp-content/uploads/2010/07/gcc_after.png" data-orig-size="455,370" data-comments-opened="1" data-image-title="GCC Prototype After" data-image-description="" data-image-caption="<p>GCC Prototype After</p> 789" data-large-file="https://andrewtwest.com/wp-content/uploads/2010/07/gcc_after.png?w=455" loading="lazy" class="size-full wp-image-274" title="GCC Prototype After" src="https://andrewtwest.com/wp-content/uploads/2010/07/gcc_after.png?w=1100" alt="GCC Prototype After" srcset="https://andrewtwest.com/wp-content/uploads/2010/07/gcc_after.png 455w, https://andrewtwest.com/wp-content/uploads/2010/07/gcc_after.png?w=150&h=122 150w, https://andrewtwest.com/wp-content/uploads/2010/07/gcc_after.png?w=300&h=244 300w" sizes="(max-width: 455px) 100vw, 455px" /></a><figcaption id="caption-attachment-274" class="wp-caption-text">GCC Prototype After</figcaption></figure> 790<p>And there you have it.  My apologies to the GCC team and anyone with any design sense whatsoever.</p> 791<p>While not groundbreaking, Quploâs new Web site redesign feature is a time saver that fits within their model of designing prototypes quickly.  Give it a try if you have access to the preview, or <a href="http://quplo.com/" target="_blank">sign up today</a>.</p> 792<p><em>GCC Website content Copyright (C) Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA.</em></p> 793 </div><!-- .entry-content --> 794 795 <footer class="entry-footer"> 796 797 <div class="entry-meta"> 798 <span class="byline"> 799 <a href="https://andrewtwest.com/author/divinerecursion/" rel="author">Andy West</a> </span> 800 <span class="cat-links"> 801 <a href="https://andrewtwest.com/category/uncategorized/" rel="category tag">Uncategorized</a> </span><!-- .cat-links --> 802 803 <span class="comments-link"><a href="https://andrewtwest.com/2010/07/21/quplos-redesign-a-website-feature/#respond">Leave a comment</a></span><!-- .comments-link --> 804 <span class="published-on"> 805 <a href="https://andrewtwest.com/2010/07/21/quplos-redesign-a-website-feature/" rel="bookmark"><time class="entry-date published" datetime="2010-07-21T03:06:16-08:00">July 21, 2010</time><time class="updated" datetime="2010-08-02T00:06:30-08:00">August 2, 2010</time></a> 806 </span> 807 808 </div><!-- .entry-meta --> 809 </footer><!-- .entry-footer --> 810</article><!-- #post-## --> 811 812 813 814<article id="post-249" class="post-249 post type-post status-publish format-standard hentry category-uncategorized tag-blog-engine tag-dogfooding tag-resume tag-rob-conery"> 815 <header class="entry-header"> 816 <h1 class="entry-title"><a href="https://andrewtwest.com/2010/06/30/taking-the-rob-conery-challenge/" rel="bookmark">Taking the Rob Conery Challenge</a></h1> </header><!-- .entry-header --> 817 <div class="entry-content"> 818 <p>Last August, Tekpub co-founder and ex-Microsoft employee Rob Conery presented a challenge to all developers: <a href="http://blog.wekeroad.com/2009/08/10/be-a-good-jedi-build-your-own-blog" target="_blank">build your own blog</a>.  He suggested that a self-built blog engine would serve perfectly as a résumé, and that makes a lot of sense to me.</p> 819<p>Most of the code Iâve written over the years is either:</p> 820<p style="padding-left:30px;"><strong>a)</strong> proprietary, and owned by the company I was working for when I wrote it</p> 821<p style="text-align:center;"><em>– or –</em></p> 822<p style="padding-left:30px;"><strong>b)</strong> embarrassing throw-away code that helped me learn some concept, but isnât good enough for anyone else to see.</p> 823<p>Writing a blog engine is a great idea because once it matures I can start <a href="http://en.wikipedia.org/wiki/Eating_your_own_dog_food" target="_blank">dogfooding</a>, migrate my existing blog to it, and build in the features I want the most.  Itâs also an opportunity to practice and learn new skills.  Here are some things I havenât tried yet, or would like to use more but havenât had the chance:</p> 824<ul> 825<li>Mercurial</li> 826<li>TDD</li> 827<li>ASP.NET MVC 2.0</li> 828<li>Entity Framework 4.0</li> 829<li>jQuery</li> 830</ul> 831<p>Therefore, Iâm announcing here and now that Iâm taking the challenge.  I plan on hosting the project on <a href="http://bitbucket.org/" target="_blank">bitbucket.org</a> so anyone can see or use it.  Iâll post updates here as I make progress.</p> 832 </div><!-- .entry-content --> 833 834 <footer class="entry-footer"> 835 836 <div class="entry-meta"> 837 <span class="byline">
838 <a href="https://andrewtwest.com/author/divinerecursion/" rel="author">Andy West</a> </span> 839 <span class="cat-links"> 840 <a href="https://andrewtwest.com/category/uncategorized/" rel="category tag">Uncategorized</a> </span><!-- .cat-links --> 841 842 <span class="comments-link"><a href="https://andrewtwest.com/2010/06/30/taking-the-rob-conery-challenge/#comments">2 Comments</a></span><!-- .comments-link --> 843 <span class="published-on"> 844 <a href="https://andrewtwest.com/2010/06/30/taking-the-rob-conery-challenge/" rel="bookmark"><time class="entry-date published" datetime="2010-06-30T16:28:24-08:00">June 30, 2010</time><time class="updated" datetime="2010-06-30T16:32:23-08:00">June 30, 2010</time></a> 845 </span> 846 847 </div><!-- .entry-meta --> 848 </footer><!-- .entry-footer --> 849</article><!-- #post-## --> 850 851 852 853<article id="post-237" class="post-237 post type-post status-publish format-standard hentry category-uncategorized tag-dslr tag-iss tag-space-station"> 854 <header class="entry-header"> 855 <h1 class="entry-title"><a href="https://andrewtwest.com/2010/06/28/spotting-the-international-space-station/" rel="bookmark">Spotting the International Space Station</a></h1> </header><!-- .entry-header --> 856 <div class="entry-content"> 857 <p>Under the right conditions, you can see the International Space Station passing overhead, even without a telescope or binoculars.  In fact, the ISS travels so fast at 17,000 mph that magnification can make it difficult to track.</p> 858<p>Last night we stepped outside at about 10:30pm to see if we could catch a glimpse of it, and I managed to capture a photo. I took this, hand-held, with a Nikon D60 and the Nikkor AF-S 70-300mm lens with Vibration Reduction turned on:</p> 859<p><a href="https://andrewtwest.com/wp-content/uploads/2010/06/iss.png"><img data-attachment-id="238" data-permalink="https://andrewtwest.com/2010/06/28/spotting-the-international-space-station/iss/" data-orig-file="https://andrewtwest.com/wp-content/uploads/2010/06/iss.png" data-orig-size="400,300" data-comments-opened="1" data-image-title="International Space Station" data-image-description="" data-image-caption="" data-large-file="https://andrewtwest.com/wp-content/uploads/2010/06/iss.png?w=400" loading="lazy" class="aligncenter size-full wp-image-238" title="International Space Station" src="https://andrewtwest.com/wp-content/uploads/2010/06/iss.png?w=1100" alt="International Space Station" srcset="https://andrewtwest.com/wp-content/uploads/2010/06/iss.png 400w, https://andrewtwest.com/wp-content/uploads/2010/06/iss.png?w=150&h=113 150w, https://andrewtwest.com/wp-content/uploads/2010/06/iss.png?w=300&h=225 300w" sizes="(max-width: 400px) 100vw, 400px" /></a></p> 860<p>I expected to get a featureless, round blob, but you can just start to make out the form in this image.  Maybe next time weâll try getting some pictures with the telescope.</p> 861<p>If you want to see the ISS, you need to look up the predicted times for visible passes in your area.  I use <a href="http://www.n2yo.com/" target="_blank">www.n2yo.com</a>, but some people prefer <a href="http://www.heavens-above.com/" target="_blank">Heavens-Above</a>.  The station travels roughly west to east, and looks like a steady, fast-moving star.</p> 862<p>Itâs pretty cool to look up at an object in the sky without using any special equipment and realize that there are probably astronauts on board.</p> 863 </div><!-- .entry-content --> 864 865 <footer class="entry-footer"> 866 867 <div class="entry-meta"> 868 <span class="byline"> 869 <a href="https://andrewtwest.com/author/divinerecursion/" rel="author">Andy West</a> </span> 870 <span class="cat-links"> 871 <a href="https://andrewtwest.com/category/uncategorized/" rel="category tag">Uncategorized</a> </span><!-- .cat-links --> 872 873 <span class="comments-link"><a href="https://andrewtwest.com/2010/06/28/spotting-the-international-space-station/#respond">Leave a comment</a></span><!-- .comments-link --> 874 <span class="published-on"> 875 <a href="https://andrewtwest.com/2010/06/28/spotting-the-international-space-station/" rel="bookmark"><time class="entry-date published" datetime="2010-06-28T03:26:28-08:00">June 28, 2010</time><time class="updated" datetime="2010-06-30T16:35:17-08:00">June 30, 2010</time></a> 876 </span> 877 878 </div><!-- .entry-meta --> 879 </footer><!-- .entry-footer --> 880</article><!-- #post-## --> 881 882 883 884 <nav class="navigation posts-navigation" aria-label="Posts"> 885 <h2 class="screen-reader-text">Posts navigation</h2> 886 <div class="nav-links"><div class="nav-previous"><a href="https://andrewtwest.com/page/3/" >Older posts</a></div><div class="nav-next"><a href="https://andrewtwest.com/" >Newer posts</a></div></div> 887 </nav> 888 889 </main><!-- #main --> 890 </div><!-- #primary --> 891 892<div id="secondary" class="widget-area" role="complementary"> 893 894 <aside id="recent-posts-2" class="widget widget_recent_entries"> 895 <h1 class="widget-title">Recent Posts</h1> 896 <ul> 897 <li>
898 <a href="https://andrewtwest.com/2019/05/31/getting-started-with-machine-learning/">Getting Started with Machine Learning</a> 899 </li> 900 <li> 901 <a href="https://andrewtwest.com/2019/04/29/experimenting-with-videogrammetry/">Experimenting with Videogrammetry</a> 902 </li> 903 <li> 904 <a href="https://andrewtwest.com/2019/04/03/using-dependency-injection-with-csla/">Using Dependency Injection with CSLA</a> 905 </li> 906 <li> 907 <a href="https://andrewtwest.com/2012/08/21/micro-orms-for-net-compared-part-3/">Micro-ORMs for .NET Compared â Part 3</a> 908 </li> 909 <li> 910 <a href="https://andrewtwest.com/2012/08/20/micro-orms-for-net-compared-part-2/">Micro-ORMs for .NET Compared â Part 2</a> 911 </li> 912 </ul> 913 914 </aside><aside id="archives-4" class="widget widget_archive"><h1 class="widget-title">Archives</h1> 915 <ul> 916 <li><a href='https://andrewtwest.com/2019/05/'>May 2019</a></li> 917 <li><a href='https://andrewtwest.com/2019/04/'>April 2019</a></li> 918 <li><a href='https://andrewtwest.com/2012/08/'>August 2012</a></li> 919 <li><a href='https://andrewtwest.com/2011/07/'>July 2011</a></li> 920 <li><a href='https://andrewtwest.com/2011/04/'>April 2011</a></li> 921 <li><a href='https://andrewtwest.com/2011/03/'>March 2011</a></li> 922 <li><a href='https://andrewtwest.com/2011/02/'>February 2011</a></li> 923 <li><a href='https://andrewtwest.com/2011/01/'>January 2011</a></li> 924 <li><a href='https://andrewtwest.com/2010/10/'>October 2010</a></li> 925 <li><a href='https://andrewtwest.com/2010/09/'>September 2010</a></li> 926 <li><a href='https://andrewtwest.com/2010/08/'>August 2010</a></li> 927 <li><a href='https://andrewtwest.com/2010/07/'>July 2010</a></li> 928 <li><a href='https://andrewtwest.com/2010/06/'>June 2010</a></li> 929 <li><a href='https://andrewtwest.com/2010/05/'>May 2010</a></li> 930 <li><a href='https://andrewtwest.com/2010/04/'>April 2010</a></li> 931 <li><a href='https://andrewtwest.com/2010/02/'>February 2010</a></li> 932 </ul> 933 934 </aside></div><!-- #secondary --> 935 936 </div><!-- #content --> 937 938 <footer id="colophon" class="site-footer" role="contentinfo"> 939 <div class="site-info"> 940 <a href="https://wordpress.com/?ref=footer_custom_powered" rel="nofollow">Website Powered by WordPress.com</a>. 941 942 </div><!-- .site-info --> 943 </footer><!-- #colophon --> 944 </div><!-- #content-wrapper --> 945</div><!-- #page --> 946 947
947<script type="text/javascript"> 948 var infiniteScroll = {"settings":{"id":"main","ajaxurl":"https://andrewtwest.com/?infinity=scrolling","type":"scroll","wrapper":true,"wrapper_class":"infinite-wrap","footer":"page","click_handle":"1","text":"Older posts","totop":"Scroll back to top","currentday":"28.06.10","order":"DESC","scripts":[],"styles":[],"google_analytics":false,"offset":2,"history":{"host":"andrewtwest.com","path":"/page/%d/","use_trailing_slashes":true,"parameters":""},"query_args":{"paged":2,"error":"","m":"","p":0,"post_parent":"","subpost":"","subpost_id":"","attachment":"","attachment_id":0,"name":"","pagename":"","page_id":0,"second":"","minute":"","hour":"","day":0,"monthnum":0,"year":0,"w":0,"category_name":"","tag":"","cat":"","tag_id":"","author":"","author_name":"","feed":"","tb":"","meta_key":"","meta_value":"","preview":"","s":"","sentence":"","title":"","fields":"all","menu_order":"","embed":"","category__in":[],"category__not_in":[],"category__and":[],"post__in":[],"post__not_in":[],"post_name__in":[],"tag__in":[],"tag__not_in":[],"tag__and":[],"tag_slug__in":[],"tag_slug__and":[],"post_parent__in":[],"post_parent__not_in":[],"author__in":[],"author__not_in":[],"search_columns":[],"lazy_load_term_meta":false,"posts_per_page":10,"ignore_sticky_posts":false,"suppress_filters":false,"cache_results":true,"update_post_term_cache":true,"update_menu_item_cache":false,"update_post_meta_cache":true,"post_type":"","nopaging":false,"comments_per_page":"50","no_found_rows":false,"order":"DESC"},"query_before":"2026-10-03 10:22:53","last_post_date":"2010-06-28 03:26:28","body_class":"infinite-scroll neverending","loading_text":"Loading new page","stats":"blog=12038026\u0026v=wpcom\u0026tz=-8\u0026user_id=0\u0026arch_home=1\u0026subd=andrewtwest\u0026x_pagetype=infinite"}}; 949 </script>
949 950 <!-- -->
951<script type="speculationrules"> 952{"prefetch":[{"source":"document","where":{"and":[{"href_matches":"/*"},{"not":{"href_matches":["/wp-*.php","/wp-admin/*","/files/*","/wp-content/*","/wp-content/plugins/*","/wp-content/themes/pub/independent-publisher-2/*","/*\\?(.+)"]}},{"not":{"selector_matches":"a[rel~=\"nofollow\"]"}},{"not":{"selector_matches":".no-prefetch, .no-prefetch a"}}]},"eagerness":"conservative"}]} 953</script>
953 954 <div style="display:none"> 955 <div class="grofile-hash-map-2a9bdd97ace3d09eebc9ad502d6ae374"> 956 </div> 957 </div> 958 <div id="infinite-footer"> 959 <div class="container"> 960 <div class="blog-info"> 961 <a id="infinity-blog-title" href="https://andrewtwest.com/" rel="home"> 962 The Public Void </a> 963 </div> 964 <div class="blog-credits"> 965 <a href="https://wordpress.com/?ref=footer_custom_powered" rel="nofollow">Website Powered by WordPress.com</a>. </div> 966 </div> 967 </div><!-- #infinite-footer --> 968 <!-- CCPA [start] --> 969
969<script type="text/javascript"> 970 ( function () { 971 972 var setupPrivacy = function() { 973 974 // Minimal Mozilla Cookie library 975 // https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie/Simple_document.cookie_framework 976 var cookieLib = window.cookieLib = {getItem:function(e){return e&&decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*"+encodeURIComponent(e).replace(/[\-\.\+\*]/g,"\\$&")+"\\s*\\=\\s*([^;]*).*$)|^.*$"),"$1"))||null},setItem:function(e,o,n,t,r,i){if(!e||/^(?:expires|max\-age|path|domain|secure)$/i.test(e))return!1;var c="";if(n)switch(n.constructor){case Number:c=n===1/0?"; expires=Fri, 31 Dec 9999 23:59:59 GMT":"; max-age="+n;break;case String:c="; expires="+n;break;case Date:c="; expires="+n.toUTCString()}return"rootDomain"!==r&&".rootDomain"!==r||(r=(".rootDomain"===r?".":"")+document.location.hostname.split(".").slice(-2).join(".")),document.cookie=encodeURIComponent(e)+"="+encodeURIComponent(o)+c+(r?"; domain="+r:"")+(t?"; path="+t:"")+(i?"; secure":""),!0}}; 977 978 // Implement IAB USP API. 979 window.__uspapi = function( command, version, callback ) { 980 981 // Validate callback. 982 if ( typeof callback !== 'function' ) { 983 return; 984 } 985 986 // Validate the given command. 987 if ( command !== 'getUSPData' || version !== 1 ) { 988 callback( null, false ); 989 return; 990 } 991 992 // Check for GPC. If set, override any stored cookie. 993 if ( navigator.globalPrivacyControl ) { 994 callback( { version: 1, uspString: '1YYN' }, true ); 995 return; 996 } 997
998 // Check for cookie. 999 var consent = cookieLib.getItem( 'usprivacy' ); 1000 1001 // Invalid cookie. 1002 if ( null === consent ) { 1003 callback( null, false ); 1004 return; 1005 } 1006 1007 // Everything checks out. Fire the provided callback with the consent data. 1008 callback( { version: 1, uspString: consent }, true ); 1009 }; 1010 1011 // Initialization. 1012 document.addEventListener( 'DOMContentLoaded', function() { 1013 1014 // Internal functions. 1015 var setDefaultOptInCookie = function() { 1016 var value = '1YNN'; 1017 var domain = '.wordpress.com' === location.hostname.slice( -14 ) ? '.rootDomain' : location.hostname; 1018 cookieLib.setItem( 'usprivacy', value, 365 * 24 * 60 * 60, '/', domain ); 1019 }; 1020 1021 var setDefaultOptOutCookie = function() { 1022 var value = '1YYN'; 1023 var domain = '.wordpress.com' === location.hostname.slice( -14 ) ? '.rootDomain' : location.hostname; 1024 cookieLib.setItem( 'usprivacy', value, 24 * 60 * 60, '/', domain ); 1025 }; 1026 1027 var setDefaultNotApplicableCookie = function() { 1028 var value = '1---'; 1029 var domain = '.wordpress.com' === location.hostname.slice( -14 ) ? '.rootDomain' : location.hostname; 1030 cookieLib.setItem( 'usprivacy', value, 24 * 60 * 60, '/', domain ); 1031 }; 1032 1033 var setCcpaAppliesCookie = function( applies ) { 1034 var domain = '.wordpress.com' === location.hostname.slice( -14 ) ? '.rootDomain' : location.hostname; 1035 cookieLib.setItem( 'ccpa_applies', applies, 24 * 60 * 60, '/', domain ); 1036 } 1037 1038 var maybeCallDoNotSellCallback = function() { 1039 if ( 'function' === typeof window.doNotSellCallback ) { 1040 return window.doNotSellCallback(); 1041 } 1042 1043 return false; 1044 } 1045 1046 // Look for usprivacy cookie first. 1047 var usprivacyCookie = cookieLib.getItem( 'usprivacy' ); 1048 1049 // Found a usprivacy cookie. 1050 if ( null !== usprivacyCookie ) { 1051 1052 // If the cookie indicates that CCPA does not apply, then bail. 1053 if ( '1---' === usprivacyCookie ) { 1054 return; 1055 } 1056 1057 // CCPA applies, so call our callback to add Do Not Sell link to the page. 1058 maybeCallDoNotSellCallback(); 1059 1060 // We're all done, no more processing needed. 1061 return; 1062 } 1063 1064 // We don't have a usprivacy cookie, so check to see if we have a CCPA applies cookie. 1065 var ccpaCookie = cookieLib.getItem( 'ccpa_applies' ); 1066 1067 // No CCPA applies cookie found, so we'll need to geolocate if this visitor is from California. 1068 // This needs to happen client side because we do not have region geo data in our $SERVER headers, 1069 // only country data -- therefore we can't vary cache on the region. 1070 if ( null === ccpaCookie ) { 1071 1072 var request = new XMLHttpRequest(); 1073 request.open( 'GET', 'https://public-api.wordpress.com/geo/', true ); 1074 1075 request.onreadystatechange = function () { 1076 if ( 4 === this.readyState ) { 1077 if ( 200 === this.status ) { 1078 1079 // Got a geo response. Parse out the region data. 1080 var data = JSON.parse( this.response ); 1081 var region = data.region ? data.region.toLowerCase() : ''; 1082 var ccpa_applies = ['california', 'colorado', 'connecticut', 'delaware', 'indiana', 'iowa', 'montana', 'new jersey', 'oregon', 'tennessee', 'texas', 'utah', 'virginia'].indexOf( region ) > -1; 1083 // Set CCPA applies cookie. This keeps us from having to make a geo request too frequently. 1084 setCcpaAppliesCookie( ccpa_applies ); 1085 1086 // Check if CCPA applies to set the proper usprivacy cookie. 1087 if ( ccpa_applies ) { 1088 if ( maybeCallDoNotSellCallback() ) { 1089 // Do Not Sell link added, so set default opt-in. 1090 setDefaultOptInCookie(); 1091 } else { 1092 // Failed showing Do Not Sell link as required, so default to opt-OUT just to be safe. 1093 setDefaultOptOutCookie(); 1094 } 1095 } else { 1096 // CCPA does not apply. 1097 setDefaultNotApplicableCookie(); 1098 } 1099 } else { 1100 // Could not geo, so let's assume for now that CCPA applies to be safe. 1101 setCcpaAppliesCookie( true ); 1102 if ( maybeCallDoNotSellCallback() ) { 1103 // Do Not Sell link added, so set default opt-in. 1104 setDefaultOptInCookie(); 1105 } else { 1106 // Failed showing Do Not Sell link as required, so default to opt-OUT just to be safe. 1107 setDefaultOptOutCookie(); 1108 } 1109 } 1110 } 1111 }; 1112 1113 // Send the geo request. 1114 request.send(); 1115 } else { 1116 // We found a CCPA applies cookie. 1117 if ( ccpaCookie === 'true' ) { 1118 if ( maybeCallDoNotSellCallback() ) { 1119 // Do Not Sell link added, so set default opt-in. 1120 setDefaultOptInCookie(); 1121 } else { 1122 // Failed showing Do Not Sell link as required, so default to opt-OUT just to be safe. 1123 setDefaultOptOutCookie(); 1124 } 1125 } else { 1126 // CCPA does not apply. 1127 setDefaultNotApplicableCookie(); 1128 } 1129 } 1130 } ); 1131 }; 1132 1133 // Kickoff initialization. 1134 if ( window.defQueue && defQueue.isLOHP && defQueue.isLOHP === 2020 ) { 1135 defQueue.items.push( setupPrivacy ); 1136 } else { 1137 setupPrivacy(); 1138 } 1139 1140 } )(); 1141 </script>
1141 1142 1143 <!-- CCPA [end] --> 1144 <div class="widget widget_eu_cookie_law_widget"> 1145<div 1146 class="hide-on-button ads-active" 1147 data-hide-timeout="30" 1148 data-consent-expiration="180" 1149 id="eu-cookie-law" 1150 style="display: none" 1151> 1152 <form method="post"> 1153 <input type="submit" value="Close and accept" class="accept" /> 1154 1155 Privacy & Cookies: This site uses cookies. By continuing to use this website, you agree to their use. <br /> 1156To find out more, including how to control cookies, see here: 1157 <a href="https://automattic.com/cookies/" rel="nofollow"> 1158 Cookie Policy </a> 1159 </form> 1160</div> 1161</div> <div id="actionbar" dir="ltr" style="display: none;" 1162 class="actnbr-pub-independent-publisher-2" role="region" aria-label="Site actions"> 1163 <span class="actnbr-live" aria-live="polite"></span> 1164 <ul> 1165 <li class="actnbr-btn actnbr-hidden"> 1166 <a class="actnbr-action actnbr-actn-follow " href="" role="button" aria-haspopup="dialog" aria-expanded="false"> 1167 <svg class="actnbr-icon actnbr-icon-bell" width="20" height="20" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" fill="currentColor"><path fill-rule="evenodd" clip-rule="evenodd" d="M17 11.5c0 1.353.17 2.368.976 3 .266.209.602.376 1.024.5v1H5v-1c.422-.124.757-.291 1.024-.5.806-.632.976-1.647.976-3V9c0-2.8 2.2-5 5-5s5 2.2 5 5v2.5ZM15.5 9v2.5c0 .93.066 1.98.515 2.897l.053.103H7.932a4.018 4.018 0 0 0 .053-.103c.449-.917.515-1.967.515-2.897V9c0-1.972 1.528-3.5 3.5-3.5s3.5 1.528 3.5 3.5Zm-5.492 9.008c0-.176.023-.346.065-.508h3.854A1.996 1.996 0 0 1 12 20c-1.1 0-1.992-.892-1.992-1.992Z"/></svg> <span>Subscribe</span> 1168 </a> 1169 <a class="actnbr-action actnbr-actn-following no-display" href="" role="button"> 1170 <svg class="actnbr-icon actnbr-icon-check" width="20" height="20" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" style="fill: none" stroke="currentColor" stroke-width="1.5"><path d="M7 12L10 15L17 8" vector-effect="non-scaling-stroke"/></svg> <span>Subscribed</span> 1171 </a> 1172 <div class="actnbr-popover actnbr-panel actnbr-notice" id="follow-bubble" role="dialog" aria-label="Subscribe to The Public Void"> 1173 <div class="actnbr-follow-bubble"> 1174 <div class="actnbr-panel__group"><a class="actnbr-menu__item actnbr-sitename" href="https://andrewtwest.com"><img loading='lazy' alt='' src='https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=50&d=https%3A%2F%2Fs-ssl.wordpress.com%2Fi%2Flogo%2Fwpcom-gray-white.png' srcset='https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=50&d=https%3A%2F%2Fs-ssl.wordpress.com%2Fi%2Flogo%2Fwpcom-gray-white.png 1x, https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=75&d=https%3A%2F%2Fs-ssl.wordpress.com%2Fi%2Flogo%2Fwpcom-gray-white.png 1.5x, https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=100&d=https%3A%2F%2Fs-ssl.wordpress.com%2Fi%2Flogo%2Fwpcom-gray-white.png 2x, https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=150&d=https%3A%2F%2Fs-ssl.wordpress.com%2Fi%2Flogo%2Fwpcom-gray-white.png 3x, https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=200&d=https%3A%2F%2Fs-ssl.wordpress.com%2Fi%2Flogo%2Fwpcom-gray-white.png 4x' class='avatar avatar-50' height='50' width='50' /><span class="actnbr-menu__label">The Public Void</span></a></div> <div class="actnbr-panel__group"> 1175 <div class="actnbr-message no-display" aria-live="polite"></div> 1176 <form method="post" action="https://subscribe.wordpress.com" accept-charset="utf-8" class="no-display"> 1177 <input type="email" name="email" placeholder="Want updates? Enter your email" class="actnbr-email-field" aria-label="Email address" /> 1178 <input type="hidden" name="action" value="subscribe" /> 1179 <input type="hidden" name="blog_id" value="12038026" /> 1180 <input type="hidden" name="source" value="https://andrewtwest.com/page/2/" /> 1181 <input type="hidden" name="sub-type" value="actionbar-follow" /> 1182 <input type="hidden" id="_wpnonce" name="_wpnonce" value="6494cc5864" /> <button type="submit" class="actnbr-button">Sign me up</button> 1183 </form> 1184 <p class="actnbr-login-nudge"> 1185 Have a WordPress.com account? <a href="https://wordpress.com/log-in?redirect_to=https%3A%2F%2Fr-login.wordpress.com%2Fremote-login.php%3Faction%3Dlink%26back%3Dhttps%253A%252F%252Fandrewtwest.com%252F2011%252F02%252F23%252Fsame-markup-same-browser-different-results%252F">Log in now.</a> </p> 1186 </div> 1187 </div> 1188 </div> 1189 </li> 1190 <li class="actnbr-ellipsis actnbr-hidden"> 1191 <button type="button" class="actnbr-more-toggle" aria-haspopup="true" aria-expanded="false" aria-label="More options"> 1192 <svg class="actnbr-icon actnbr-icon-more-horizontal" width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" fill="currentColor"><path d="M11 13h2v-2h-2v2zm-6 0h2v-2H5v2zm12-2v2h2v-2h-2z"/></svg> </button> 1193 <div class="actnbr-popover actnbr-menu" role="menu" aria-label="Site options"> 1194 <div class="actnbr-menu__group" role="group"><a role="menuitem" class="actnbr-menu__item actnbr-sitename" href="https://andrewtwest.com"><img loading='lazy' alt='' src='https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=50&d=https%3A%2F%2Fs-ssl.wordpress.com%2Fi%2Flogo%2Fwpcom-gray-white.png' srcset='https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=50&d=https%3A%2F%2Fs-ssl.wordpress.com%2Fi%2Flogo%2Fwpcom-gray-white.png 1x, https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=75&d=https%3A%2F%2Fs-ssl.wordpress.com%2Fi%2Flogo%2Fwpcom-gray-white.png 1.5x, https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=100&d=https%3A%2F%2Fs-ssl.wordpress.com%2Fi%2Flogo%2Fwpcom-gray-white.png 2x, https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=150&d=https%3A%2F%2Fs-ssl.wordpress.com%2Fi%2Flogo%2Fwpcom-gray-white.png 3x, https://secure.gravatar.com/blavatar/f27dd4810b0d60e02039a2026bbe04cf2e6e4a73b015d64ca5c899a9f3a5fed0?s=200&d=https%3A%2F%2Fs-ssl.wordpress.com%2Fi%2Flogo%2Fwpcom-gray-white.png 4x' class='avatar avatar-50' height='50' width='50' /><span class="actnbr-menu__label">The Public Void</span></a></div><div class="actnbr-menu__group" role="group"><a role="menuitem" class="actnbr-menu__item actnbr-reader" href="https://wordpress.com/reader/feeds/323164"><span class="actnbr-menu__label">View site in Reader</span></a></div><div class="actnbr-menu__group" role="group"><a role="menuitem" class="actnbr-menu__item actnbr-subs" href="https://subscribe.wordpress.com/"><span class="actnbr-menu__label">Manage subscriptions</span></a><a role="menuitem" class="actnbr-menu__item actnbr-signup" href="https://wordpress.com/start/"><span class="actnbr-menu__label">Sign up</span></a><a role="menuitem" class="actnbr-menu__item actnbr-login" href="https://wordpress.com/log-in?redirect_to=https%3A%2F%2Fr-login.wordpress.com%2Fremote-login.php%3Faction%3Dlink%26back%3Dhttps%253A%252F%252Fandrewtwest.com%252F2011%252F02%252F23%252Fsame-markup-same-browser-different-results%252F"><span class="actnbr-menu__label">Log in</span></a></div><div class="actnbr-menu__group" role="group"><a role="menuitem" class="actnbr-menu__item flb-report" href="https://wordpress.com/abuse/?report_url=https://andrewtwest.com" target="_blank" rel="noopener noreferrer"><span class="actnbr-menu__label">Report this content</span><span class="actnbr-menu__icon"><svg class="actnbr-icon actnbr-icon-external" width="18" height="18" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" fill="currentColor"><path d="M19.5 4.5h-7V6h4.44l-5.97 5.97 1.06 1.06L18 7.06v4.44h1.5v-7Zm-13 1a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-3H17v3a.5.5 0 0 1-.5.5h-10a.5.5 0 0 1-.5-.5v-10a.5.5 0 0 1 .5-.5h3V5.5h-3Z"/></svg></span></a></div><div class="actnbr-menu__group" role="group"><a role="menuitem" class="actnbr-menu__item actnbr-fold" href=""><span class="actnbr-menu__label">Collapse this bar</span></a></div> </div> 1195 </li> 1196 </ul> 1197 </div> 1198
1198<script> 1199window.addEventListener( "DOMContentLoaded", function () { 1200 var link = document.createElement( "link" ); 1201 link.href = "\/wp-content\/mu-plugins\/jetpack-plugin\/moon\/jetpack_vendor\/automattic\/jetpack-newsletter\/src\/..\/build\/action-bar.css?ver=35dd33285eb46dc308dd"; 1202 link.rel = "stylesheet"; 1203 document.head.appendChild( link ); 1204 1205 var script = document.createElement( "script" ); 1206 script.src = "\/wp-content\/mu-plugins\/jetpack-plugin\/moon\/jetpack_vendor\/automattic\/jetpack-newsletter\/src\/..\/build\/action-bar.js?ver=35dd33285eb46dc308dd"; 1207 document.body.appendChild( script ); 1208 } ); 1209</script>
1209 1210<link rel="prefetch" href="/wp-content/mu-plugins/jetpack-plugin/moon/_inc/blocks/swiper.js" as="script" /> 1211 <div id="jp-carousel-loading-overlay" style="display: none;"> 1212 <div id="jp-carousel-loading-wrapper"> 1213 <span id="jp-carousel-library-loading"><svg class="jetpack-spinner" width="40" height="40" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><circle cx="50" cy="50" r="46" fill="none" stroke="#ddd" stroke-width="8"/><path d="M 50 4 A 46 46 0 0 1 96 50" fill="none" stroke="currentColor" stroke-width="8" stroke-linecap="round"><animateTransform attributeName="transform" type="rotate" dur="1.4s" from="0 50 50" to="360 50 50" repeatCount="indefinite"/></path></svg></span> 1214 </div> 1215 </div> 1216 <div class="jp-carousel-overlay" style="display: none;"> 1217 1218 <div class="jp-carousel-container"> 1219 <!-- The Carousel Swiper --> 1220 <div 1221 class="jp-carousel-wrap swiper jp-carousel-swiper-container jp-carousel-transitions" 1222 itemscope 1223 itemtype="https://schema.org/ImageGallery"> 1224 <div class="jp-carousel swiper-wrapper"></div> 1225 <div class="jp-swiper-button-prev swiper-button-prev"> 1226 <svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 1227 <mask id="maskPrev" mask-type="alpha" maskUnits="userSpaceOnUse" x="8" y="6" width="9" height="12"> 1228 <path d="M16.2072 16.59L11.6496 12L16.2072 7.41L14.8041 6L8.8335 12L14.8041 18L16.2072 16.59Z" fill="white"/> 1229 </mask> 1230 <g mask="url(#maskPrev)"> 1231 <rect x="0.579102" width="23.8823" height="24" fill="#FFFFFF"/> 1232 </g> 1233 </svg> 1234 </div> 1235 <div class="jp-swiper-button-next swiper-button-next"> 1236 <svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 1237 <mask id="maskNext" mask-type="alpha" maskUnits="userSpaceOnUse" x="8" y="6" width="8" height="12"> 1238 <path d="M8.59814 16.59L13.1557 12L8.59814 7.41L10.0012 6L15.9718 12L10.0012 18L8.59814 16.59Z" fill="white"/> 1239 </mask> 1240 <g mask="url(#maskNext)"> 1241 <rect x="0.34375" width="23.8822" height="24" fill="#FFFFFF"/> 1242 </g> 1243 </svg> 1244 </div> 1245 </div> 1246 <!-- The main close buton --> 1247 <div class="jp-carousel-close-hint"> 1248 <svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 1249 <mask id="maskClose" mask-type="alpha" maskUnits="userSpaceOnUse" x="5" y="5" width="15" height="14"> 1250 <path d="M19.3166 6.41L17.9135 5L12.3509 10.59L6.78834 5L5.38525 6.41L10.9478 12L5.38525 17.59L6.78834 19L12.3509 13.41L17.9135 19L19.3166 17.59L13.754 12L19.3166 6.41Z" fill="white"/> 1251 </mask> 1252 <g mask="url(#maskClose)"> 1253 <rect x="0.409668" width="23.8823" height="24" fill="#FFFFFF"/> 1254 </g> 1255 </svg> 1256 </div> 1257 <!-- Image info, comments and meta --> 1258 <div class="jp-carousel-info"> 1259 <div class="jp-carousel-info-footer"> 1260 <div class="jp-carousel-pagination-container"> 1261 <div class="jp-swiper-pagination swiper-pagination"></div> 1262 <div class="jp-carousel-pagination"></div> 1263 </div> 1264 <div class="jp-carousel-photo-title-container"> 1265 <div class="jp-carousel-photo-caption"></div> 1266 </div> 1267 <div class="jp-carousel-photo-icons-container"> 1268 <a href="#" class="jp-carousel-icon-btn jp-carousel-icon-info" aria-label="Toggle photo metadata visibility"> 1269 <span class="jp-carousel-icon"> 1270 <svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 1271 <mask id="maskInfo" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="21" height="20"> 1272 <path fill-rule="evenodd" clip-rule="evenodd" d="M12.7537 2C7.26076 2 2.80273 6.48 2.80273 12C2.80273 17.52 7.26076 22 12.7537 22C18.2466 22 22.7046 17.52 22.7046 12C22.7046 6.48 18.2466 2 12.7537 2ZM11.7586 7V9H13.7488V7H11.7586ZM11.7586 11V17H13.7488V11H11.7586ZM4.79292 12C4.79292 16.41 8.36531 20 12.7537 20C17.142 20 20.7144 16.41 20.7144 12C20.7144 7.59 17.142 4 12.7537 4C8.36531 4 4.79292 7.59 4.79292 12Z" fill="white"/> 1273 </mask> 1274 <g mask="url(#maskInfo)"> 1275 <rect x="0.8125" width="23.8823" height="24" fill="#FFFFFF"/> 1276 </g> 1277 </svg> 1278 </span> 1279 </a> 1280 <a href="#" class="jp-carousel-icon-btn jp-carousel-icon-comments" aria-label="Toggle photo comments visibility"> 1281 <span class="jp-carousel-icon"> 1282 <svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 1283 <mask id="maskComments" mask-type="alpha" maskUnits="userSpaceOnUse" x="2" y="2" width="21" height="20"> 1284 <path fill-rule="evenodd" clip-rule="evenodd" d="M4.3271 2H20.2486C21.3432 2 22.2388 2.9 22.2388 4V16C22.2388 17.1 21.3432 18 20.2486 18H6.31729L2.33691 22V4C2.33691 2.9 3.2325 2 4.3271 2ZM6.31729 16H20.2486V4H4.3271V18L6.31729 16Z" fill="white"/> 1285 </mask> 1286 <g mask="url(#maskComments)"> 1287 <rect x="0.34668" width="23.8823" height="24" fill="#FFFFFF"/> 1288 </g> 1289 </svg> 1290 1291 <span class="jp-carousel-has-comments-indicator" aria-label="This image has comments."></span> 1292 </span> 1293 </a> 1294 </div>
1295 </div> 1296 <div class="jp-carousel-info-extra"> 1297 <div class="jp-carousel-info-content-wrapper"> 1298 <div class="jp-carousel-photo-title-container"> 1299 <div class="jp-carousel-photo-title"></div> 1300 </div> 1301 <div class="jp-carousel-comments-wrapper"> 1302 <div id="jp-carousel-comments-loading"> 1303 <span>Loading Comments...</span> 1304 </div> 1305 <div class="jp-carousel-comments"></div> 1306 <div id="jp-carousel-comment-form-container"> 1307 <span id="jp-carousel-comment-form-spinner"><svg class="jetpack-spinner" width="20" height="20" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><circle cx="50" cy="50" r="46" fill="none" stroke="#ddd" stroke-width="8"/><path d="M 50 4 A 46 46 0 0 1 96 50" fill="none" stroke="currentColor" stroke-width="8" stroke-linecap="round"><animateTransform attributeName="transform" type="rotate" dur="1.4s" from="0 50 50" to="360 50 50" repeatCount="indefinite"/></path></svg></span> 1308 <div id="jp-carousel-comment-post-results"></div> 1309 <form id="jp-carousel-comment-form"> 1310 <label for="jp-carousel-comment-form-comment-field" class="screen-reader-text">Write a Comment...</label> 1311 <textarea 1312 name="comment" 1313 class="jp-carousel-comment-form-field jp-carousel-comment-form-textarea" 1314 id="jp-carousel-comment-form-comment-field" 1315 placeholder="Write a Comment..." 1316 ></textarea> 1317 <div id="jp-carousel-comment-form-submit-and-info-wrapper"> 1318 <div id="jp-carousel-comment-form-commenting-as"> 1319 <fieldset> 1320 <label for="jp-carousel-comment-form-email-field">Email</label> 1321 <input type="text" name="email" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-email-field" /> 1322 </fieldset> 1323 <fieldset> 1324 <label for="jp-carousel-comment-form-author-field">Name</label> 1325 <input type="text" name="author" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-author-field" /> 1326 </fieldset> 1327 <fieldset> 1328 <label for="jp-carousel-comment-form-url-field">Website</label> 1329 <input type="text" name="url" class="jp-carousel-comment-form-field jp-carousel-comment-form-text-field" id="jp-carousel-comment-form-url-field" /> 1330 </fieldset> 1331 </div> 1332 <input 1333 type="submit" 1334 name="submit" 1335 class="jp-carousel-comment-form-button" 1336 id="jp-carousel-comment-form-button-submit" 1337 value="Post Comment" /> 1338 </div> 1339 </form> 1340 </div> 1341 </div> 1342 <div class="jp-carousel-image-meta"> 1343 <div class="jp-carousel-title-and-caption"> 1344 <div class="jp-carousel-photo-info"> 1345 <div class="jp-carousel-caption" itemprop="caption description"></div> 1346 </div> 1347 1348 <div class="jp-carousel-photo-description"></div> 1349 </div> 1350 <a class="jp-carousel-image-download" href="#" aria-label="Download image" target="_blank" style="display: none;"> 1351 <svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"> 1352 <mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="3" y="3" width="19" height="18"> 1353 <path fill-rule="evenodd" clip-rule="evenodd" d="M5.84615 5V19H19.7775V12H21.7677V19C21.7677 20.1 20.8721 21 19.7775 21H5.84615C4.74159 21 3.85596 20.1 3.85596 19V5C3.85596 3.9 4.74159 3 5.84615 3H12.8118V5H5.84615ZM14.802 5V3H21.7677V10H19.7775V6.41L9.99569 16.24L8.59261 14.83L18.3744 5H14.802Z" fill="white"/> 1354 </mask> 1355 <g mask="url(#mask0)"> 1356 <rect x="0.870605" width="23.8823" height="24" fill="#FFFFFF"/> 1357 </g> 1358 </svg> 1359 <span class="jp-carousel-download-text"></span> 1360 </a> 1361 <div class="jp-carousel-image-map" style="display: none;"></div> 1362 </div> 1363 </div>
1364 </div> 1365 </div> 1366 </div> 1367 1368 </div> 1369
1369<script crossorigin='anonymous' type='text/javascript' src='/_static/??-eJzTLy/QTc7PK0nNK9EvyClNz8wr1i+uzCtJrMjITM/IAeKS1CJMEWP94uSizIISoOIM5/yiVL2sYh19yo1yKiotzojIzaGmcc7BGYlFBUAT7XNtDc1MzUyNTC1MLbIA3HVf6g=='></script>
vendor: 1 bytes, line 1369
1369
1370<script type='text/javascript'> 1371 (function(){ 1372 var corecss = document.createElement('link'); 1373 var themecss = document.createElement('link'); 1374 var corecssurl = "/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/styles/shCore.css?ver=3.0.9b"; 1375 if ( corecss.setAttribute ) { 1376 corecss.setAttribute( "rel", "stylesheet" ); 1377 corecss.setAttribute( "type", "text/css" ); 1378 corecss.setAttribute( "href", corecssurl ); 1379 } else { 1380 corecss.rel = "stylesheet"; 1381 corecss.href = corecssurl; 1382 } 1383 document.head.appendChild( corecss ); 1384 var themecssurl = "/wp-content/plugins/syntaxhighlighter/syntaxhighlighter3/styles/shThemeDefault.css?m=1363304414i&ver=3.0.9b"; 1385 if ( themecss.setAttribute ) { 1386 themecss.setAttribute( "rel", "stylesheet" ); 1387 themecss.setAttribute( "type", "text/css" ); 1388 themecss.setAttribute( "href", themecssurl ); 1389 } else { 1390 themecss.rel = "stylesheet"; 1391 themecss.href = themecssurl; 1392 } 1393 document.head.appendChild( themecss ); 1394 })(); 1395 SyntaxHighlighter.config.strings.expandSource = '+ expand source'; 1396 SyntaxHighlighter.config.strings.help = '?'; 1397 SyntaxHighlighter.config.strings.alert = 'SyntaxHighlighter\n\n'; 1398 SyntaxHighlighter.config.strings.noBrush = 'Can\'t find brush for: '; 1399 SyntaxHighlighter.config.strings.brushNotHtmlScript = 'Brush wasn\'t configured for html-script option: '; 1400 SyntaxHighlighter.defaults['pad-line-numbers'] = false; 1401 SyntaxHighlighter.defaults['toolbar'] = false; 1402 SyntaxHighlighter.all(); 1403 1404 // Infinite scroll support 1405 document.addEventListener( 'is.post-load', function () { 1406 SyntaxHighlighter.highlight(); 1407 } ); 1408</script>
1408 1409 1410
1410<script type="text/javascript"> 1411 (function () { 1412 var wpcom_reblog = { 1413 source: 'toolbar', 1414 1415 toggle_reblog_box_flair: function (obj_id, post_id) { 1416 1417 // Go to site selector. This will redirect to their blog if they only have one. 1418 const postEndpoint = `https://wordpress.com/post`; 1419 1420 // Ideally we would use the permalink here, but fortunately this will be replaced with the 1421 // post permalink in the editor. 1422 const originalURL = `${ document.location.href }?page_id=${ post_id }`; 1423 1424 const url = 1425 postEndpoint + 1426 '?url=' + 1427 encodeURIComponent( originalURL ) + 1428 '&is_post_share=true' + 1429 '&v=5'; 1430 1431 const redirect = function () { 1432 if ( 1433 ! window.open( url, '_blank' ) 1434 ) { 1435 location.href = url; 1436 } 1437 }; 1438 1439 if ( /Firefox/.test( navigator.userAgent ) ) { 1440 setTimeout( redirect, 0 ); 1441 } else { 1442 redirect(); 1443 } 1444 }, 1445 }; 1446 1447 window.wpcom_reblog = wpcom_reblog; 1448 })(); 1449 </script>
vendor: 1 bytes, line 1449
1449
1450<script id="jetpack-carousel-js-extra"> 1451var jetpackSwiperLibraryPath = {"url":"/wp-content/mu-plugins/jetpack-plugin/moon/_inc/blocks/swiper.js"}; 1452var jetpackCarouselStrings = {"widths":[370,700,1000,1200,1400,2000],"is_logged_in":"","lang":"en","ajaxurl":"https://andrewtwest.com/wp-admin/admin-ajax.php","nonce":"e5e139dc5e","display_exif":"1","display_comments":"1","single_image_gallery":"1","single_image_gallery_media_file":"","background_color":"black","comment":"Comment","post_comment":"Post Comment","write_comment":"Write a Comment...","loading_comments":"Loading Comments...","image_label":"Open image in full-screen.","download_original":"View full size \u003Cspan class=\"photo-size\"\u003E{0}\u003Cspan class=\"photo-size-times\"\u003E\u00d7\u003C/span\u003E{1}\u003C/span\u003E","no_comment_text":"Please be sure to submit some text with your comment.","no_comment_email":"Please provide an email address to comment.","no_comment_author":"Please provide your name to comment.","comment_post_error":"Sorry, but there was an error posting your comment. Please try again later.","comment_approved":"Your comment was approved.","comment_unapproved":"Your comment is in moderation.","camera":"Camera","aperture":"Aperture","shutter_speed":"Shutter Speed","focal_length":"Focal Length","copyright":"Copyright","comment_registration":"0","require_name_email":"0","login_url":"https://andrewtwest.wordpress.com/wp-login.php?redirect_to=https%3A%2F%2Fandrewtwest.com%2F2011%2F02%2F23%2Fsame-markup-same-browser-different-results%2F","blog_id":"12038026","meta_data":["camera","aperture","shutter_speed","focal_length","copyright"],"stats_query_args":"blog=12038026&v=wpcom&tz=-8&user_id=0&arch_home=1&subd=andrewtwest","is_public":"1"}; 1453//# sourceURL=jetpack-carousel-js-extra 1454</script>
vendor: 1 bytes, line 1454
1454
1455<script crossorigin='anonymous' type='text/javascript' src='/_static/??-eJydUEFOw0AM/BDuloIoHBBPqTYbJ3XitVext4Hfs5VaQD1w6MXSjD1jzYS1QFJxFA8d6wiF60hiYdWlj71B4miGFqZGRWc47TaTPYQ/slx/RdSP6Bawtq3OhMBxDY65cHS84f/xmdBLTPMFh6wq4UCSQleJ+0AykJAjWFqU+Yq/Npnk1tWPmNvnUrt21mPBNsShYSY74gK7czSJJxqjk96pt5kKMMkMg6ZqMNDnHUbnhC0SFYe1JM33N5TiotWQf+6uxKWij/z+uH/bbvfPL0+v0zckmME0'></script>
vendor: 1 bytes, line 1455
1455
1456<script data-wp-strategy="defer" defer id="tiled-gallery-js" src="/wp-content/mu-plugins/jetpack-plugin/moon/_inc/build/tiled-gallery/tiled-gallery/tiled-gallery.min.js?m=1755006225i&ver=16.3-a.8"></script>
vendor: 1 bytes, line 1456
1456
1457<script crossorigin='anonymous' type='text/javascript' src='/wp-content/mu-plugins/carousel-wpcom/carousel-wpcom.js?m=1761899756i'></script>
vendor: 1 bytes, line 1457
1457
1458<script id="wp-emoji-settings" type="application/json"> 1459{"baseUrl":"https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/72x72/","ext":".png","svgUrl":"https://s0.wp.com/wp-content/mu-plugins/wpcom-smileys/twemoji/2/svg/","svgExt":".svg","source":{"concatemoji":"/wp-includes/js/wp-emoji-release.min.js?m=1783090810i&ver=7.2-alpha-63885"}} 1460</script>
vendor: 1 bytes, line 1460
1460
1461<script type="module"> 1462/*! This file is auto-generated */ 1463var e="script#wp-emoji-settings",t=document.querySelector(e);if(!(t instanceof HTMLScriptElement))throw new Error("Element missing: "+e);const r=JSON.parse(t.text),s=(window._wpemojiSettings=r,"wpEmojiSettingsSupports"),o=["flag","emoji"];function i(e){try{var t={supportTests:e,timestamp:(new Date).valueOf()};sessionStorage.setItem(s,JSON.stringify(t))}catch(e){}}function c(e,t,n){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);t=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(n,0,0);const r=new Uint32Array(e.getImageData(0,0,e.canvas.width,e.canvas.height).data);return t.every((e,t)=>e===r[t])}function p(e,t){e.clearRect(0,0,e.canvas.width,e.canvas.height),e.fillText(t,0,0);var n=e.getImageData(16,16,1,1);for(let e=0;e<n.data.length;e++)if(0!==n.data[e])return!1;return!0}function u(e,t,n,r){switch(t){case"flag":return n(e,"\ud83c\udff3\ufe0f\u200d\u26a7\ufe0f","\ud83c\udff3\ufe0f\u200b\u26a7\ufe0f")?!1:!n(e,"\ud83c\udde8\ud83c\uddf6","\ud83c\udde8\u200b\ud83c\uddf6")&&!n(e,"\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f","\ud83c\udff4\u200b\udb40\udc67\u200b\udb40\udc62\u200b\udb40\udc65\u200b\udb40\udc6e\u200b\udb40\udc67\u200b\udb40\udc7f");case"emoji":return!r(e,"\ud83e\udec8")}return!1}function f(e,t,n,r){let a;const s=(a="undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?new OffscreenCanvas(300,150):document.createElement("canvas")).getContext("2d",{willReadFrequently:!0}),o=(s.textBaseline="top",s.font="600 32px Arial",{});return e.forEach(e=>{o[e]=t(s,e,n,r)}),o}function a(e){var t=document.createElement("script");t.src=e,t.defer=!0,document.head.appendChild(t)}r.supports={everything:!0,everythingExceptFlag:!0},new Promise(t=>{let n=function(){try{var e=JSON.parse(sessionStorage.getItem(s));if("object"==typeof e&&"number"==typeof e.timestamp&&(new Date).valueOf()<e.timestamp+604800&&"object"==typeof e.supportTests)return e.supportTests}catch(e){}return null}();if(!n){if("undefined"!=typeof Worker&&"undefined"!=typeof OffscreenCanvas&&"undefined"!=typeof URL&&URL.createObjectURL&&"undefined"!=typeof Blob)try{var e="postMessage("+f.toString()+"("+[JSON.stringify(o),u.toString(),c.toString(),p.toString()].join(",")+"));",r=new Blob([e],{type:"text/javascript"});const a=new Worker(URL.createObjectURL(r),{name:"wpTestEmojiSupports"});return void(a.onmessage=e=>{i(n=e.data),a.terminate(),t(n)})}catch(e){}i(n=f(o,u,c,p))}t(n)}).then(e=>{for(const n in e)r.supports[n]=e[n],r.supports.everything=r.supports.everything&&r.supports[n],"flag"!==n&&(r.supports.everythingExceptFlag=r.supports.everythingExceptFlag&&r.supports[n]);var t;r.supports.everythingExceptFlag=r.supports.everythingExceptFlag&&!r.supports.flag,r.supports.everything||((t=r.source||{}).concatemoji?a(t.concatemoji):t.wpemoji&&t.twemoji&&(a(t.twemoji),a(t.wpemoji)))}); 1464//# sourceURL=/wp-includes/js/wp-emoji-loader.min.js 1465</script>
1465 1466
1466<script type="text/javascript"> 1467 (function() { 1468 var extend = function(out) { 1469 out = out || {}; 1470 1471 for (var i = 1; i < arguments.length; i++) { 1472 if (!arguments[i]) 1473 continue; 1474 1475 for (var key in arguments[i]) { 1476 if (arguments[i].hasOwnProperty(key)) 1477 out[key] = arguments[i][key]; 1478 } 1479 } 1480 1481 return out; 1482 }; 1483 extend( window.infiniteScroll.settings.scripts, ["jetpack-mu-wpcom-settings","rlt-proxy","cmp-script-stub","wpcom-actionbar-placeholder","syntaxhighlighter-core","syntaxhighlighter-brush-xml","syntaxhighlighter-brush-csharp","wordads-client","eu-cookie-law-script","the-neverending-homepage","independent-publisher-2-navigation","independent-publisher-2-skip-link-focus-fix","independent-publisher-2-wpcom-functions","jetpack-carousel","tiled-gallery","carousel-wpcom"] ); 1484 extend( window.infiniteScroll.settings.styles, ["eu-cookie-law-style","the-neverending-homepage","coblocks-frontend","wpcom-core-compat-playlist-styles","wpcom-bbpress2-staff-css","genericons","independent-publisher-2-style","
1484independent-publisher-2-block-style","independent-publisher-2-wpcom-style","reblogging","geo-location-flair","a8c-global-print","h4-global","wp-img-auto-sizes-contain","wp-emoji-styles","wp-block-library","classic-theme-styles","wp-block-styles-placeholder","coblocks-inline-format","wp-global-styles-placeholder","jetpack-global-styles-frontend-style","global-styles","jetpack-swiper-library","jetpack-carousel","tiled-gallery","core-block-supports-duotone"] ); 1485 })(); 1486 </script>
1486 1487 <span id="infinite-aria" aria-live="polite"></span> 1488
1488<script src="//stats.wp.com/w.js?69" defer></script>
1488
1488<script type="text/javascript"> 1489_tkq = window._tkq || []; 1490_stq = window._stq || []; 1491_tkq.push(['storeContext', {'blog_id':'12038026','blog_tz':'-8','user_lang':'en','blog_lang':'en','user_id':'0'}]); 1492 // Prevent sending pageview tracking from WP-Admin pages. 1493 _stq.push(['view', {'blog':'12038026','v':'wpcom','tz':'-8','user_id':'0','arch_home':'1','subd':'andrewtwest'}]); 1494 _stq.push(['extra', {'crypt':'UE5XaGUuOTlwaD85flAmcm1mcmZsaDhkV11YdWtpP0NsWnVkPS9sL0ViLndld3BuVT01Uj14Ti1yYTBnX3xuYUQ3Qz1oblZbVHV3MTZ6aj0wcy01aFV6Y1RhRDhuPzkwMncsNm1ad0EldTZtNXh1JSxyYW44MzAxMFBndmg2Wy16eVsyMS1CX1JPdmxiekFZW2tNTjA4diU2aUEtZmRmbWhKVEprM3xOVCs4andhb21IOE1xdGpDVjREcy4sRzZNTFQsbm5ZYys2XWlkdStUeW9peWJ6Xy1vZHw0RGwlQXZTNVYzbDhIXXBjYzg4QVpGaENUZnBIUV9sNzlaMWxFZ19FLXwxNCU2UzQ9P0NmQUZxdEZiY2VVSVEzcF9dR2IleTlCXWwmW05ZOU5Cbm9SaGN4ZFpuUmxDQkQvP0tpcnVxUXVCfnBxY2hfbltiL1p2MU1Hd35PYm9ZRzFzV24='}]); 1495_stq.push([ 'clickTrackerInit', '12038026', '0' ]); 1496</script>
1496 1497<noscript><img src="https://pixel.wp.com/b.gif?v=noscript" style="height:1px;width:1px;overflow:hidden;position:absolute;bottom:1px;" alt="" /></noscript> 1498<meta id="bilmur" property="bilmur:data" content="" data-provider="wordpress.com" data-service="simple" data-site-tz="Etc/GMT+8" data-custom-props="{"logged_in":"0","wptheme":"pub\/independent-publisher-2","wptheme_is_block":"0"}" > 1499
1499<script defer src="/wp-content/js/bilmur.min.js?i=19&m=202640"></script>
1499 1500</body> 1501</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.