Eza's Homestuck Simplifier

A mobile-friendly "reader app" for MSPaintAdventures.com

  1. // ==UserScript==
  2. // @name Eza's Homestuck Simplifier
  3. // @namespace https://inkbunny.net/ezalias
  4. // @description A mobile-friendly "reader app" for MSPaintAdventures.com
  5. // @license MIT
  6. // @license Public domain / No rights reserved
  7. // @include http://www.mspaintadventures.com/*
  8. // @version 1.2
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. // MSPA on mobile is painful, so let's replace the page with an AJAX updater that only cares about the comic area.
  13.  
  14. // Backgrounds in Scratch and Trickster pages aren't quite right. E.g. Trickster pages should be all garish Z's. (Trickster mode: p=007614)
  15. // Mobile link does not appear on Trickster pages. The whole nav bar is wacko.
  16. // Oh shit, password pages. That'll screw with preloading... but... oh well?
  17. // Password pages work, but redirect you outside of #mobile. (c. p=008948, first password is HOME. No, not HOM3.)
  18. // Oh shit, Openbound doesn't work. (c. p=007208)
  19. // Or... it does now? Okay, sure.
  20. // Going there from the previous page doesn't work. Balls. I guess I could force a reload, but that's hard not to loop.
  21. // Key seems to be:
  22. // <script type="text/javascript" src="storyfiles/hs2/05305/Sburb.min.js" >
  23. //... <body bgcolor="5a5a5a" bottommargin="0" topmargin="0" onload="Sburb.initialize('JterniaDeploy','storyfiles/hs2/05305/levels/init.xml',false);">
  24. // which is obviously outside the comic content.
  25. // I could probably test for the onload portion. Dunno how I'd cleanly get the script in, though. Special cases suck.
  26. // Ugh, I need to include the script aaaand then call the right Sburb.initialize thing from the page context (document.body.Sburb.etc).
  27. // Double pages? x2 pesterlogs or whatever. Where are those damn things? Ah, p=007686.
  28. // Ahh, the first link (which is supposed to scroll up and right, to the top anchor for the other side) is the first '?s=' link. Arg.
  29. // And then #TWO stays in window.location, so naturally it scrolls right on every subsequent page. What a mess.
  30. // Special-case #TWO links to point to window.location.href + '#TWO'.
  31. // Sorta-kinda fixed by excluding them from link-diddling. Window.onpopstate complains 'event.state is null' for anchors, but whatever.
  32. // There's no return to the left when you load the next pair of pages. Autoscroll's only vertical, for mobile's sake. Hmm. #TWO does correctly clear from the address bar.
  33. // Next_page is wrong because the actual next-page link is preceded by the first column's load/save/go-back/start-over links.
  34. // ... multipage loading? Flash pages with sound make this a questionable idea, but they always have [S] in the link. (Oh, also stop at '???' for Passwords.)
  35. // Hmm, dunno if I can link to an anchor on the next div without removing #mirror from the URL.
  36. // '&' works as well as '#' for tagging the URL. &mobile vs. #mobile. Only seemed relevant because it broke x2 combo pages for a while.
  37. // Crowbar page super doesn't work. I think it's the special URL - http://www.mspaintadventures.com/007680/007680.html - with no ?s= etc.
  38. // But... it still returns HTML... which has the right flash. Hmm.
  39. // Ugh, same deal for Game Over. It's the special URL - Cascade is cascade.php?s=etc, but some pages are /gameover/gameover.html or similar. Ugh.
  40. // Game Over works, ish, but you can't leave. The link (in the flash!) doesn't work correctly.
  41. // Should autoscroll ignore back/forward events?
  42. // Minor issue: single-indexOf content filtering (i.e., start of page to 'end of comic content') changes background colors one page early, because of preloading.
  43. // Should I stretch the images of text in e.g. Trickster mode, to match the zoomed text? Might break formatting, since it's wrapped at a standard width. (Ehh.)
  44.  
  45. // Noteworthy pages: Scratch, 005663. Cascade, 006009. Openbound, 007208. Trickster mode, 007614. Game Over, 008800. Passwords (HOME), 008948. Collide, 009986.
  46. // Caliborn whacking the page, 007680. Act 5 Act 2 Act 1 x2 combo, 007686. Act 6 Act 6 Homosuck, 008142.
  47. // Very tall page, 005627. Haunting piano refrain, 001977.
  48.  
  49. // Narrow Mode didn't have intended effect; implemented text zooming instead. Font sizes go up.
  50.  
  51. if( window.location.href.indexOf( '#mobile' ) > 0 ) { // On a #mobile page, blank everything and attempt to present a comic page.
  52. // Replace the page with some simple divs and dummy text
  53. document.body.innerHTML = "<center><div id='content'>What content?</div>" + // Main div, one visible comic page
  54. "<div id='hidden_preload' style='display: none;'>DUNKASS</div>" + // Invisible div for preloading. ALL WEBCOMICS SHOULD HAVE THIS.
  55. "<a id='exit_link'><font color='ffffff'>Exit Mobile Mode</a><font color='c0c0c0'>" + // When in doubt, fail
  56.  
  57. "<span id='scrollcontrols' class='noscroll'>" + // Autoscroll on/off, with one option visible at once, and setting contained in parent span
  58. " <span class='ontoggle'> - <a href ='javascript:void(0);' onclick=\"javascript:document.getElementById('scrollcontrols').className='autoscroll'\">" +
  59. "<font color='c0c0c0'>Autoscroll is off</a></span>" +
  60. " <span class='offtoggle'>- <a href ='javascript:void(0);' onclick=\"javascript:document.getElementById('scrollcontrols').className='noscroll'\">" +
  61. "<font color='c0c0c0'>Autoscroll is on</a></span>" +
  62. "</span>" +
  63.  
  64. "<span id='zoomcontrols' class=''>" + // "Narrow mode" on/off, with one option visible at once, and setting contained in parent span
  65. " <span class='zoomtext'> - <a href ='javascript:void(0);' onclick=\"javascript:document.body.className='zoomed'\">" +
  66. "<font color='c0c0c0'>Text is normal</a></span>" +
  67. " <span class='normaltext'>- <a href ='javascript:void(0);' onclick=\"javascript:document.body.className='unzoomed'\">" +
  68. "<font color='c0c0c0'>Text is zoomed</a></span>" +
  69. "</span>" +
  70.  
  71. "<style> .autoscroll .ontoggle { display: none; } .noscroll .offtoggle { display: none; } " + // Hide offtoggle or ontoggle as appropriate
  72. ".unzoomed .normaltext { display: none; } .zoomed .zoomtext { display: none; } " + // Hide zoomtext or normaltext as appropriate
  73. ".zoomed div span { font-size: 20px; } " + // Bump up text size in pesterlogs
  74. ".zoomed div p { font-size: 20px; } " + // Bump up text size in narrative
  75. "</style>" +
  76. " - <a href=\"javascript:location.reload();\"><font color='c0c0c0'>Page not working? Reload</a>";
  77. document.body.className = 'unzoomed'; // Can't do this in the injected HTML because fuck you.
  78.  
  79. // Setup the fake history for our fake links
  80. window.onpopstate = function( event ) { update( event.state.update, 'content' ); }; // Faking the Back button: update() to a previous history state, which we also fake
  81. history.replaceState( { update: window.location.href }, 'MS Paint Adventures', window.location.href ); // You are here. JS doesn't do this itself because fuck you.
  82.  
  83. // Call Update for whatever page we're on
  84. update( window.location.href, 'content' );
  85.  
  86. } else { // If it's not #mobile then we're on unaugmented MSPA. Augment it with a link to the appropriate #mobile version.
  87. // Mobile link from the front page has to be different because '/?s=...&#mobile' works, but '/&?s=...' doesn't. Dunno why it's a CORS error, though.
  88. var mobile_link = window.location.href + "&#mobile"; // The '&' forces a reload despite being a misused anchor link
  89. if( window.location.href.indexOf( '?s=' ) < 0 ) { mobile_link = "/?s=6#mobile"; } // Frontpage is Homestuck? Link Homestuck.
  90.  
  91. // "Mobile" link goes after the "Credits" link
  92. var credits_index = document.body.innerHTML.indexOf( "CREDITS</font></a>" ) + "CREDITS</font></a>".length;
  93. if( credits_index <= 17 ) { credits_index = document.body.innerHTML.indexOf( "WHATEVER.</font></a>" ) + "WHATEVER.</font></a>".length; } // A6A6 hack
  94. if( credits_index > 20 ) { // Sloppy not to check for indexOf > -1, but fuck, am I ever tired of verbose indexOf nonsense. Gimme some spliceAtText function.
  95. document.body.innerHTML =
  96. document.body.innerHTML.substring( 0, credits_index ) +
  97. " | <a href='" + mobile_link + "'><font color='88ff44'>MOBILE</font></a>" +
  98. document.body.innerHTML.substring( credits_index );
  99. }
  100. }
  101.  
  102. // End of main execution.
  103.  
  104.  
  105.  
  106. // Grab a page, put the important stuff in one of our divs
  107. function update( page_path, target_div ) {
  108. var ajax = new XMLHttpRequest(); // Create AJAX object with which to fetch page
  109. ajax.onreadystatechange = function () { // When the AJAX object updates -
  110. if( ajax.readyState == 4 ) { // If the update state means "finished" -
  111.  
  112. // Grab comic content from the fetched HTML
  113. var replacement_html = '';
  114. var stop_strings = [ '<!-- end comic content -->', // This works on "normal" pages, i.e. everywhere outside Homestuck
  115. '<!-- FULL LOGO HEADER -->', // This is for Scratch pages
  116. '<!------------------------end comic content----------------------------------->' ] // This is for Cascade
  117. for( var n = 0; n < stop_strings.length; n++ ) {
  118. if( replacement_html == '' ) { replacement_html = ajax.responseText.substring( 0, ajax.responseText.indexOf( stop_strings[n] ) ); }
  119. }
  120.  
  121. // Dumb Cascade fix: changing the Flash's src URL gets "fixed" by some other script, but remove src entirely and the "name" property gets used. Aggravating.
  122. replacement_html = replacement_html.replace( 'src="/cascade', 'sauce="/cascade' ); // Relative URLs and CORS are a regular pain in my ass.
  123.  
  124. // Some pages are unique but simple, so treat the whole page as content
  125. if( replacement_html == '' ) { // This is for crowbar-whacking, Collide, & EOA7
  126. var whitelist = [ '05777_2', 'p=009988', 'p=010028' ]; // These aren't the affected pages, these are pages that the affected pages link to.
  127. for( page in whitelist ) {
  128. if( ajax.responseText.indexOf( page ) > 0 ) {
  129. replacement_html = ajax.responseText; // There's nothing but comic content on these pages, so grab everything.
  130. replacement_html = replacement_html.replace( 'src="05777_2.swf"', 'sauce="05777_2.swf"' ); // Crowbar hack, page 007680. Damn relative src links.
  131. }
  132. } // End of 'for whitelist' loop
  133. }
  134.  
  135. // Enable Flash content
  136. while( replacement_html.indexOf( '<noscript>' ) > 0 ) { // Dunno why AC_RunActiveContent.js doesn't run, but the results are right here anyway -
  137. replacement_html = replacement_html.replace( '<noscript>', '' ); // Flash pages provide NoScript-friendly best-guess results. Let's use those.
  138. }
  139.  
  140. // Update our fake page to show the comic and text
  141. document.getElementById( target_div ).innerHTML = replacement_html;
  142. document.getElementById( 'exit_link' ).href = window.location.href.replace( '#mobile', '&#' ); // Update "Exit Mobile Mode" link (as a real no-kidding link)
  143.  
  144. // On visible updates, change links into Update calls and preload the next page
  145. if( target_div == 'content' ) { // If we're updating the main div -
  146.  
  147. // Scroll back up (if autoscroll is enabled)
  148. if( document.getElementById( 'scrollcontrols' ).className.indexOf( 'autoscroll' ) > -1 ) // If control span class includes 'autoscroll' -
  149. { window.scrollBy( 0, -10000 ); } // Scroll up by some large number
  150.  
  151. // Diddle the next-page link to allow preloading and prevent actual link behavior
  152. var links = document.getElementById( 'content' ).getElementsByTagName( 'a' ); // Wish people would ID their fuckin' links.
  153. var next_page = ''; // It'll be the first ?s= etc link on the page, so we'll do for(links) backwards and use the final value.
  154.  
  155. for( var n = links.length - 1; n >= 0; n-- ) {
  156. // If it's a page link, but not a Save / Load / Etc. '?game' link, and not a x2 Combo second-column anchor -
  157. if( links[n].href.indexOf( '?s=' ) > 0 && links[n].href.indexOf( '?game' ) == -1 && links[n].href.indexOf( '#TWO' ) == -1 ) {
  158. next_page = links[n].fake_href = links[n].href.replace( '/mobile', '' ); // Store links[n]'s original target inside that link, because callbacks are dumb
  159. links[n].addEventListener ( "click", function() {
  160. update( this.fake_href, 'content' ); // Grab the link with this script instead of visiting it
  161. history.pushState( { update: this.fake_href + "#mobile" }, 'MS Paint Adventures', this.fake_href + "#mobile" ); // So the Back button works on a fake link
  162. } , false );
  163. links[n].href = 'javascript:void(0)'; // Break link, so the script's function predominates.
  164. } // End of if() block checking for page links
  165. } // End of for() loop over links in 'content' div
  166.  
  167. update( next_page, 'hidden_preload' ); // Load the next page in a hidden div, so images download while you're reading. EVERY WEBCOMIC SHOULD DO THIS.
  168. } // End of if() block for 'content'-specific code
  169.  
  170. } // End of if() block for when page is fully fetched
  171. } // End of anonymous AJAX-update function
  172. if( page_path.indexOf( '://' ) < 0 ) { page_path = "http://www.mspaintadventures.com/" + page_path; } // Some links read as '/?s=etc', others as 'http...' - make all 'http'.
  173. ajax.open( "GET", page_path, true ); // GET this URL, false = synchronous
  174. ajax.send();
  175. } // End of Update function
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216.  
  217.  
  218.  
  219.  
  220.  
  221.  
  222.  
  223.  
  224.  
  225.  
  226.  
  227.  
  228.  
  229.  
  230.  

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址