Replace and highlight

Your own censor list for 4chan

  1. // ==UserScript==
  2. // @name Replace and highlight
  3. // @namespace wordreplace
  4. // @version 2015.08.21
  5. // @include *://boards.4chan.org/*
  6. // @grant unsafeWindow
  7. // @grant GM_getValue
  8. // @grant GM_setValue
  9. // @description Your own censor list for 4chan
  10. // ==/UserScript==
  11. 'use strict';
  12.  
  13. // Create element function
  14. function element(){
  15. var parent
  16. var toreturn={}
  17. for(var i=0;i<arguments.length;i++){
  18. var current=arguments[i]
  19. if(current.nodeType){
  20. parent=current
  21. }else{
  22. if(Array.isArray(current)){
  23. var tagname=current[0].split('#')
  24. var newtag=document.createElement(tagname[0])
  25. if(tagname[1]){
  26. toreturn[tagname[1]]=newtag
  27. }
  28. for(var j=1;j<current.length;j++){
  29. if(current[j].constructor==Object){
  30. for(var value in current[j]){
  31. if(value!='style'&&value in newtag){
  32. newtag[value]=current[j][value]
  33. }else{
  34. newtag.setAttribute(value,current[j][value])
  35. }
  36. }
  37. }else{
  38. var returned=element(newtag,current[j])
  39. for(var k in returned){
  40. toreturn[k]=returned[k]
  41. }
  42. }
  43. }
  44. }else{
  45. var newtag=document.createTextNode(current)
  46. }
  47. if(parent){
  48. parent.appendChild(newtag)
  49. }
  50. }
  51. }
  52. return toreturn
  53. }
  54.  
  55. //Update posts
  56. function updateposts(event){
  57. if(event){
  58. var replies=document.querySelectorAll('#t'+event.detail.threadId+' .postContainer:not(.wordreplace)')
  59. }else{
  60. var replies=document.querySelectorAll('.thread .postContainer:not(.wordreplace)')
  61. }
  62. if(replies.length){
  63. if(replies.length>200){
  64. var end=200
  65. }else{
  66. var end=replies.length
  67. }
  68. for(var i=0;i<end;i++){
  69. if(i==200){
  70. var j=0
  71. }else{
  72. var j=i
  73. }
  74. replies[j].classList.add('wordreplace')
  75. //Remove wbr tags
  76. if(thesettings.wrremwbr){
  77. var wbr=replies[j].getElementsByTagName('wbr')
  78. for(var k=wbr.length;k--;){
  79. var pre=wbr[k].previousSibling
  80. var nex=wbr[k].nextSibling
  81. if(pre&&nex&&pre.nodeType==3&&nex.nodeType==3){
  82. pre.nodeValue+=nex.nodeValue
  83. nex.parentNode.removeChild(nex)
  84. }
  85. wbr[k].parentNode.removeChild(wbr[k])
  86. }
  87. }
  88. //Replace and highlight
  89. wordreplacing(replies[j])
  90. }
  91. }
  92. }
  93.  
  94. //Add new settings
  95. function updatesettings(){
  96. setTimeout(function(){
  97. unsafeWindow.SettingsMenu.options['Replace and highlight']={
  98. wordreplace:['Replace and highlight words [<a href="javascript:wordreplace()">Edit</a>]','Your own censor list',1],
  99. wronlyin:['Instead of replacing everything, replace only in:','',1],
  100. wrbody:['Comment body','',1,1],
  101. wrsubject:['Subject','',1,1],
  102. wrfilename:['Filename','',1,1],
  103. wrposter:['Poster name','',0,1],
  104. wrtitle:['Page title','',1,1],
  105. wrremwbr:['Remove all &lt;wbr&gt; tags from the posts','&lt;wbr&gt; tags are inserted every 35 characters in long words, which may prevent some patterns from working',1],
  106. wrtooltip:['Reveal original line in a tooltip when hovered over','',0]
  107. }
  108. unsafeWindow.wordreplace=function(event,action){
  109. var norefresh=0
  110. var order={on:1,pattern:0,case:1,replace:0,js:1,caps:1,mark:1,board:0}
  111. if(!action){
  112. wr_temp=JSON.parse(JSON.stringify(wr_strings))
  113. var menu=element(
  114. document.body,
  115. ['div',{
  116. class:'UIPanel',
  117. id:'wr-body',
  118. onclick:closepanel
  119. },
  120. ['div',{
  121. class:'extPanel reply',
  122. style:'width:600px;margin-left:-300px'
  123. },
  124. ['div',{
  125. class:'panelHeader'
  126. },
  127. 'Replace and highlight words',
  128. ['span',
  129. ['img',{
  130. alt:'Close',
  131. title:'Close',
  132. class:'pointer',
  133. src:unsafeWindow.Main.icons.cross
  134. }]
  135. ]
  136. ],
  137. ['table',{
  138. style:'text-align:center'
  139. },
  140. ['thead',
  141. ['tr',
  142. ['th'],
  143. ['th','On'],
  144. ['th','Pattern'],
  145. ['th','Case'],
  146. ['th','Replace'],
  147. ['th','JS'],
  148. ['th','Caps'],
  149. ['th','Mark'],
  150. ['th','Board'],
  151. ['th','Del']
  152. ]
  153. ],
  154. ['tbody',{
  155. id:'wr-list'
  156. }],
  157. ],
  158. ['div',{
  159. style:'float:left'
  160. },
  161. ['input',{
  162. type:'button',
  163. value:'Add',
  164. onclick:function(event){
  165. wordreplace(event,'add')
  166. }
  167. }],
  168. ['input',{
  169. type:'button',
  170. value:'Import/Export',
  171. onclick:function(event){
  172. wordreplace(event,'port')
  173. }
  174. }]
  175. ],
  176. ['div',{
  177. style:'float:right'
  178. },
  179. ['input',{
  180. type:'button',
  181. value:'Save',
  182. onclick:function(event){
  183. wordreplace(event,'save')
  184. }
  185. }],
  186. ['input',{
  187. type:'button',
  188. value:'Save and close',
  189. onclick:function(event){
  190. wordreplace(event,'save')
  191. document.getElementById('wr-body').click()
  192. }
  193. }]
  194. ],
  195. ['table',{
  196. style:'width:100%'
  197. },
  198. ['tr',{
  199. style:'vertical-align:top'
  200. },
  201. ['td',
  202. ['textarea#input',{
  203. id:'wr-input',
  204. paceholder:'Test it here',
  205. style:'width:280px;height:50px'
  206. }]
  207. ],
  208. ['td',{
  209. style:'vertical-align:top;text-align:left'
  210. },
  211. ['div',{
  212. id:'wr-output',
  213. style:'width:294px;word-wrap:break-word;overflow:hidden'
  214. }]
  215. ]
  216. ]
  217. ]
  218. ],
  219. ['style','\
  220. #wr-body input[type="text"],#wr-body .wr-replace{\
  221. font:13px monospace;\
  222. width:135px;\
  223. }\
  224. #wr-body .wr-board{\
  225. width:60px!important;\
  226. }\
  227. #wr-body textarea.wr-replace{\
  228. height:50px;\
  229. resize:none!important;\
  230. overflow:hidden;\
  231. cursor:text;\
  232. }\
  233. #wr-body [error],#wr-body .js{\
  234. vertical-align:top;\
  235. }\
  236. #wr-body [error]::after{\
  237. content:attr(error);\
  238. display:block;\
  239. position:absolute;\
  240. overflow:hidden;\
  241. left:0;\
  242. text-overflow:ellipsis;\
  243. width:100%;\
  244. white-space:nowrap;\
  245. margin-top:25px;\
  246. height:20px;\
  247. font-size:12px;\
  248. color:#d00\
  249. }\
  250. #wr-body [error] .wr-replace{\
  251. margin-bottom:20px!important;\
  252. }\
  253. #wr-body .js[error]::after{\
  254. margin-top:60px;\
  255. }']
  256. ]
  257. )
  258. menu.input.onkeydown=menu.input.onkeyup=menu.input.onchange=menu.input.onclick=function(event){
  259. wordreplace(event,'type')
  260. }
  261. }
  262. var list=document.getElementById('wr-list')
  263. var trs=list.getElementsByTagName('tr')
  264. if(action!='imported'){
  265. for(var i=0;i<wr_temp.length;i++){
  266. if(trs[i]){
  267. for(var j in order){
  268. var input=trs[i].getElementsByClassName('wr-'+j)[0]
  269. if(order[j]){
  270. wr_temp[i][j]=input.checked
  271. }else{
  272. wr_temp[i][j]=input.value
  273. }
  274. }
  275. }
  276. }
  277. }
  278. switch(action){
  279. case 'add':{
  280. wr_temp.push({on:1,caps:1})
  281. break
  282. }
  283. case 'up':{
  284. var id=event.target.parentNode.parentNode.id.match(/filter-(\d+)/)[1]*1
  285. if(id>0){
  286. var temp=wr_temp[id]
  287. wr_temp[id]=wr_temp[id-1]
  288. wr_temp[id-1]=temp
  289. }else{
  290. norefresh=1
  291. }
  292. break
  293. }
  294. case 'del':{
  295. var id=event.target.parentNode.parentNode.id.match(/filter-(\d+)/)[1]*1
  296. wr_temp.splice(id,1)
  297. break
  298. }
  299. case 'save':{
  300. for(var i=wr_temp.length;i--;){
  301. if(!wr_temp[i].pattern&&!wr_temp[i].replace){
  302. wr_temp.splice(i,1)
  303. }
  304. }
  305. wr_strings=wr_temp.slice()
  306. GM_setValue('wordreplace',JSON.stringify(wr_temp))
  307. norefresh=1
  308. break
  309. }
  310. case 'type':
  311. case 'imported':{
  312. var input=document.getElementById('wr-input').value
  313. input=input.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/(&gt;&gt;\d+|&gt;&gt;&gt;\/\w+\/\d*)/g,'<a class="quotelink pointer">$1</a>').replace(/\n/g,'<br>').replace(/\[(\/)?spoiler\]/g,'<$1s>').replace(/^(&gt;[^\n]*)$/gm,'<span style="color:#789922">$1</span>')
  314. var output=document.getElementById('wr-output')
  315. output.innerHTML=input
  316. output.classList.remove('replacedtext')
  317. wordreplacing(output,1,wr_temp)
  318. if(action!='imported'&&!event.target.classList.contains('wr-js')){
  319. norefresh=1
  320. }
  321. break
  322. }
  323. case 'port':{
  324. var port=element(
  325. document.body,
  326. ['div#panel',{
  327. class:'UIPanel',
  328. onclick:closepanel
  329. },
  330. ['div',{
  331. class:'extPanel reply',
  332. style:'text-align:center'
  333. },
  334. ['div',{
  335. class:'panelHeader'
  336. },
  337. 'Import/Export patterns',
  338. ['span',
  339. ['img',{
  340. alt:'Close',
  341. title:'Close',
  342. class:'pointer',
  343. src:unsafeWindow.Main.icons.cross
  344. }]
  345. ]
  346. ],
  347. ['textarea#txt',{
  348. style:'width:100%;height:100px;box-sizing:border-box',
  349. value:JSON.stringify(wr_temp)
  350. }],
  351. ['div',{
  352. style:'float:left'
  353. },
  354. ['input',{
  355. type:'button',
  356. value:'Save to file',
  357. onclick:function(){
  358. var txt=port.txt.value
  359. txt=btoa(encodeURIComponent(txt).replace(/%([0-9A-F]{2})/g,function(a,b){
  360. return String.fromCharCode('0x'+b)
  361. }))
  362. element(
  363. ['a#link',{
  364. href:'data:application/json;base64,'+txt,
  365. download:'wordreplace.json'
  366. }]
  367. ).link.click()
  368. }
  369. }],
  370. ['input',{
  371. type:'button',
  372. value:'Load from file',
  373. onclick:function(){
  374. port.file.click()
  375. }
  376. }],
  377. ],
  378. ['div',{
  379. style:'float:right'
  380. },
  381. ['input',{
  382. type:'button',
  383. value:'Replace all',
  384. onclick:function(event){
  385. var temp
  386. try{
  387. temp=fromimport(JSON.parse(port.txt.value))
  388. }catch(e){
  389. alert('This is not a valid JSON')
  390. }
  391. if(temp){
  392. wr_temp=temp
  393. wordreplace(event,'imported',1)
  394. port.panel.click()
  395. }
  396. }
  397. }],
  398. ['input',{
  399. type:'button',
  400. value:'Import and append',
  401. onclick:function(event){
  402. var temp
  403. try{
  404. temp=fromimport(JSON.parse(port.txt.value))
  405. }catch(e){
  406. alert('This is not a valid JSON')
  407. }
  408. if(temp){
  409. wr_temp=wr_temp.concat(temp)
  410. wordreplace(event,'type',1)
  411. port.panel.click()
  412. }
  413. }
  414. }]
  415. ],
  416. ['form',
  417. ['input#file',{
  418. type:'file',
  419. style:'display:none',
  420. onchange:function(event){
  421. if(event.target.files.length){
  422. var reader=new FileReader()
  423. reader.onload=function(read){
  424. port.txt.value=read.target.result
  425. event.target.parentNode.reset()
  426. }
  427. reader.readAsText(event.target.files[0])
  428. }
  429. }
  430. }]
  431. ]
  432. ]
  433. ]
  434. )
  435. norefresh=1
  436. break
  437. }
  438. case 'editjs':{
  439. var target=event.target
  440. var editor=element(
  441. document.body,
  442. ['div',{
  443. class:'UIPanel',
  444. id:'wr-body',
  445. onclick:function(event){
  446. if(event.target.className=='UIPanel'||event.target.tagName=='IMG'){
  447. target.value=editor.txt.value
  448. closepanel(event)
  449. wordreplace(event,'type')
  450. }
  451. }
  452. },
  453. ['div',{
  454. class:'extPanel reply',
  455. style:'width:600px;margin-left:-300px'
  456. },
  457. ['div',{
  458. class:'panelHeader'
  459. },
  460. 'Edit function',
  461. ['span',
  462. ['img',{
  463. alt:'Close',
  464. title:'Close',
  465. class:'pointer',
  466. src:unsafeWindow.Main.icons.cross
  467. }]
  468. ]
  469. ],
  470. ['textarea#txt',{
  471. value:target.value,
  472. onkeydown:function(event){
  473. if(event.keyCode==9){ //Tab
  474. event.preventDefault()
  475. var input=event.target
  476. var start=input.selectionStart
  477. input.value=input.value.slice(0,start)+'\t'+input.value.slice(input.selectionEnd)
  478. input.setSelectionRange(start+1,start+1)
  479. }
  480. },
  481. style:'width:100%;height:500px;box-sizing:border-box;font:13px monospace'
  482. }]
  483. ]
  484. ]
  485. )
  486. editor.txt.setSelectionRange(0,0)
  487. norefresh=1
  488. break
  489. }
  490. }
  491. if(!norefresh){
  492. list.innerHTML=''
  493. if(!wr_temp.length){
  494. wr_temp=[{on:1,caps:1}]
  495. }
  496. for(var i in wr_temp){
  497. var table=element(
  498. list,
  499. ['tr#tr',{
  500. id:'filter-'+i
  501. },
  502. ['td',
  503. ['span',{
  504. class:'pointer',
  505. onclick:function(event){
  506. wordreplace(event,'up')
  507. }
  508. },'\u2191']
  509. ]
  510. ]
  511. )
  512. for(var j in order){
  513. var tagname='input'
  514. var js=j=='replace'&&wr_temp[i].js
  515. if(js){
  516. tagname='textarea'
  517. }
  518. var td=element(
  519. table.tr,
  520. ['td',
  521. [tagname+'#input',{
  522. class:'wr-'+j,
  523. onchange:function(event){
  524. wordreplace(event,'type')
  525. }
  526. }]
  527. ]
  528. )
  529. if(order[j]){
  530. td.input.type='checkbox'
  531. if(j=='on'&&wr_temp[i][j]==undefined){
  532. td.input.checked=1
  533. }else{
  534. td.input.checked=wr_temp[i][j]
  535. }
  536. }else{
  537. if(js){
  538. table.tr.classList.add('js')
  539. td.input.readOnly=1
  540. td.input.onclick=function(event){
  541. wordreplace(event,'editjs')
  542. }
  543. }else{
  544. td.input.type='text'
  545. }
  546. td.input.value=wr_temp[i][j]||''
  547. }
  548. }
  549. element(
  550. table.tr,
  551. ['td',
  552. ['span',{
  553. class:'pointer',
  554. onclick:function(event){
  555. wordreplace(event,'del')
  556. }
  557. },'\xD7']
  558. ]
  559. )
  560. }
  561. }
  562. for(var i in wr_temp){
  563. var errors=[]
  564. try{
  565. var a=RegExp(wr_temp[i].pattern)
  566. }catch(e){
  567. errors.push('Error in regex: '+e.message.replace(/.*:.*: /,''))
  568. }
  569. if(wr_temp[i].js){
  570. try{
  571. eval('!function(){'+wr_temp[i].replace+'}')
  572. }catch(e){
  573. errors.push('Error in function: '+e.message)
  574. }
  575. }
  576. if(errors.length){
  577. document.getElementById('filter-'+i).setAttribute('error',errors.join(' | '))
  578. }else{
  579. document.getElementById('filter-'+i).removeAttribute('error')
  580. }
  581. }
  582. }
  583. },1000)
  584. }
  585. function closepanel(event){
  586. if(event.target.className=='UIPanel'){
  587. event.target.parentNode.removeChild(event.target)
  588. }
  589. if(event.target.tagName=='IMG'){
  590. var target=event.target.parentNode.parentNode.parentNode.parentNode
  591. target.parentNode.removeChild(target)
  592. }
  593. }
  594. function fromimport(json){
  595. var order={on:1,pattern:0,case:1,replace:0,js:1,caps:1,mark:1,board:0}
  596. try{
  597. if(json.patterns){
  598. json=json.patterns
  599. }
  600. var temp=[]
  601. for(var i in json){
  602. temp[i]={}
  603. for(var j in order){
  604. if(json[i][j]==undefined){
  605. if(j=='on'||j=='caps'){
  606. temp[i][j]=1
  607. }else{
  608. if(order[j]){
  609. temp[i][j]=0
  610. }else{
  611. temp[i][j]=''
  612. }
  613. }
  614. }else{
  615. temp[i][j]=json[i][j]
  616. }
  617. }
  618. }
  619. return temp
  620. }catch(e){
  621. alert('This JSON cannot be imported because it is corrupt')
  622. console.log(e.message)
  623. }
  624. }
  625.  
  626. //Word replace
  627. function wordreplacing(post,main,strings){
  628. if(!post||!post.classList){
  629. return
  630. }
  631. if(post.classList.contains('replacedtext')){
  632. return
  633. }
  634. post.classList.add('replacedtext')
  635. if(main){
  636. var comments=[post]
  637. }else{
  638. var props=[]
  639. if(thesettings.wronlyin){
  640. if(thesettings.wrbody){
  641. props.push('blockquote')
  642. }
  643. if(thesettings.wrsubject){
  644. props.push('.subject')
  645. }
  646. if(thesettings.wrfilename){
  647. props.push('.fileText>a')
  648. }
  649. if(thesettings.wrposter){
  650. props.push('.nameBlock')
  651. }
  652. }else{
  653. props=['.nameBlock','.fileText>a','.subject','blockquote']
  654. }
  655. if(!props.length){
  656. return
  657. }
  658. var comments=post.querySelectorAll(props.join(','))
  659. }
  660. for(var i=0;i<comments.length;i++){
  661. var textnodes=[]
  662. var walk=document.createTreeWalker(comments[i],4,null,0)
  663. var newnode
  664. while(newnode=walk.nextNode()){
  665. textnodes.push(newnode)
  666. }
  667. for(var j in textnodes){
  668. var currentnode=textnodes[j]
  669. var out=teststring(currentnode.nodeValue.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'),strings)
  670. if(out!=null){
  671. if(thesettings.wrtooltip||/[<>]/.test(out)){
  672. var newspan=element(
  673. ['span#span',{
  674. innerHTML:out
  675. }]
  676. )
  677. if(thesettings.wrtooltip){
  678. newspan.span.title=currentnode.nodeValue
  679. }
  680. currentnode.parentNode.insertBefore(newspan.span,currentnode)
  681. currentnode.parentNode.removeChild(currentnode)
  682. }else{
  683. currentnode.nodeValue=out.replace(/&gt;/g,'>').replace(/&lt;/g,'<').replace(/&amp;/g,'&')
  684. }
  685. }
  686. }
  687. }
  688. }
  689. function teststring(text,replaces){
  690. if(text.length){
  691. var oldtext=text
  692. if(replaces){
  693. var patterns=replaces
  694. }else{
  695. var patterns=wr_strings
  696. }
  697. for(var i in patterns){
  698. try{
  699. if(
  700. patterns[i].on&&
  701. patterns[i].pattern&&(
  702. !patterns[i].board||
  703. patterns[i].board.toLowerCase().replace(/[,;]/g,' ').replace(/[^a-z\d\s]/g,'').trim().split(/\s+/).indexOf(currentboard)+1
  704. )
  705. ){
  706. var replacewith=patterns[i].replace+''
  707. if(patterns[i].js){
  708. replacewith=function(){
  709. return eval('(function(){'+patterns[i].replace+'}).apply(undefined,arguments)')
  710. }
  711. }else if(patterns[i].mark){
  712. replacewith='<span class="highlighttext">'+(replacewith||'$&')+'</span>'
  713. }
  714. if(patterns[i].caps){
  715. var replacestring=replacewith
  716. replacewith=function(){
  717. if(patterns[i].js){
  718. var returned=replacestring.apply(undefined,arguments)
  719. var s=[returned,arguments[0]]
  720. }else{
  721. var args=arguments
  722. var s=[replacestring,args[0]]
  723. s[0]=s[0].replace(/\$&/g,'$$0').replace(/\$(\d+)/g,function(){
  724. var num=arguments[1]*1
  725. return args[num]||''
  726. })
  727. }
  728. var al=s[0].length
  729. var bl=s[1].length
  730. if(al>bl){
  731. var l=bl
  732. }else{
  733. var l=al
  734. }
  735. if(l<2){
  736. return s[0]
  737. }
  738. s=s.map(function(a){
  739. return [a.slice(0,l-l/2),a.slice(l-l/2,-l/2),a.slice(-l/2)]
  740. })
  741. for(var j=0;j<3;j+=2){
  742. s[0][j]=s[0][j].toLowerCase().split('')
  743. for(var k=0;k<s[0][j].length;k++){
  744. var c=s[1][j][k]
  745. if(c==c.toUpperCase()&&c!=c.toLowerCase()){
  746. s[0][j][k]=s[0][j][k].toUpperCase()
  747. }
  748. }
  749. s[0][j]=s[0][j].join('')
  750. }
  751. if(s[0][1]){
  752. var u=0
  753. if(s[1][1]){
  754. var c=s[1][1]
  755. if(c==c.toUpperCase()&&c!=c.toLowerCase()){
  756. u=2
  757. }
  758. }else{
  759. var c=s[1][0][(l/2|0)-1]
  760. if(c==c.toUpperCase()){
  761. u++
  762. }
  763. var c=s[1][2][0]
  764. if(c==c.toUpperCase()){
  765. u++
  766. }
  767. }
  768. if(u==2){
  769. s[0][1]=s[0][1].toUpperCase()
  770. }
  771. }
  772. return s[0].join('')
  773. }
  774. }else if(!patterns[i].js){
  775. replacewith=replacewith.replace(/\$0/g,'$$&')
  776. }
  777. var ig=patterns[i].case?'g':'ig'
  778. text=text.replace(new RegExp(patterns[i].pattern,ig),replacewith)
  779. }
  780. }catch(e){
  781. if(!replaces){
  782. wr_strings[i].on=0
  783. }
  784. console.error('Error in regex: '+patterns[i].pattern,',',e.message)
  785. }
  786. }
  787. if(oldtext!=text){
  788. return text
  789. }else{
  790. return null
  791. }
  792. }else{
  793. return null
  794. }
  795. }
  796.  
  797. if(document.getElementsByTagName('meta').length){
  798. //Get settings
  799. var thesettings=localStorage['4chan-settings']
  800. var thedefault='wordreplace wronlyin wrbody wrsubject wrfilename wrtitle wrremwbr'.split(' ')
  801. if(thesettings){
  802. thesettings=JSON.parse(thesettings)
  803. var changed=0
  804. for(var i in thedefault){
  805. if(thesettings[thedefault[i]]==undefined){
  806. thesettings[thedefault[i]]=true
  807. changed=1
  808. }
  809. }
  810. if(changed){
  811. localStorage['4chan-settings']=JSON.stringify(thesettings)
  812. }
  813. }else{
  814. thesettings={}
  815. var gmsetting=GM_getValue('wordreplace')
  816. if(gmsetting){
  817. thesettings.wordreplace=gmsetting=='true'?1:0
  818. }
  819. }
  820. //Determine current page format, board name, and thread id
  821. if(document.body.classList.contains('is_index')){
  822. var activepage='index'
  823. }else if(document.getElementById('content')){
  824. var activepage='catalog'
  825. }else if(location.pathname.indexOf('/thread/')+1){
  826. var activepage='thread'
  827. }else{
  828. var activepage='main'
  829. }
  830. var currentboard=''
  831. var match=document.body.classList[0]
  832. if(match){
  833. match=match.match(/^board_(\w+)$/)
  834. if(match){
  835. var currentboard=match[1]
  836. }else if(activepage!='main'){
  837. match=location.pathname.match(/^\/(\w+)\//)
  838. if(match){
  839. var currentboard=match[1]
  840. }
  841. }
  842. }
  843. //Retrieve pattern list
  844. var wr_strings=GM_getValue('wordreplace')
  845. if(wr_strings){
  846. wr_strings=JSON.parse(wr_strings)
  847. }else{
  848. wr_strings=[
  849. {
  850. on:1,
  851. pattern:'newfag',
  852. case:0,
  853. replace:'newfig',
  854. js:0,
  855. caps:1,
  856. mark:0,
  857. board:'s4s'
  858. },
  859. {
  860. on:1,
  861. pattern:'shitpost',
  862. case:0,
  863. replace:'funpost',
  864. js:0,
  865. caps:1,
  866. mark:0,
  867. board:'s4s'
  868. }
  869. ]
  870. }
  871. var wr_temp
  872. if(thesettings.wordreplace&&(thesettings.wrtitle||!thesettings.wronlyin)){
  873. var newtitle=teststring(document.title.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'))
  874. if(newtitle!=null){
  875. document.title=newtitle.replace(/[\r\n]/g,'').replace(/<[^>]*>/g,'').replace(/&gt;/g,'>').replace(/&lt;/g,'<').replace(/&amp;/g,'&')
  876. }
  877. }
  878. if(activepage=='index'||activepage=='thread'){
  879. if(thesettings.wordreplace){
  880. updateposts()
  881. document.addEventListener('4chanParsingDone',updateposts)
  882. }
  883. if(unsafeWindow.Main){
  884. updatesettings()
  885. }else{
  886. document.addEventListener('4chanMainInit',updatesettings)
  887. }
  888. }
  889. if(activepage=='catalog'&&thesettings.wordreplace){
  890. for(var i in unsafeWindow.catalog.threads){
  891. var props=[]
  892. if(thesettings.wronlyin){
  893. if(thesettings.wrbody){
  894. props.push('teaser')
  895. }
  896. if(thesettings.wrsubject){
  897. props.push('sub')
  898. }
  899. if(thesettings.wrfilename){
  900. props.push('file')
  901. }
  902. if(thesettings.wrposter){
  903. props.push('author')
  904. }
  905. }else{
  906. props=['author','file','sub','teaser']
  907. }
  908. props.forEach(function(prop){
  909. var out=teststring(unsafeWindow.catalog.threads[i][prop])
  910. if(out!=null){
  911. unsafeWindow.catalog.threads[i][prop]=out
  912. }
  913. if(prop=='author'&&unsafeWindow.catalog.threads[i].lr.author){
  914. var out=teststring(unsafeWindow.catalog.threads[i].lr.author)
  915. if(out!=null){
  916. unsafeWindow.catalog.threads[i].lr.author=out
  917. }
  918. }
  919. })
  920. }
  921. document.getElementById('size-ctrl').dispatchEvent(new Event('change'))
  922. }
  923. }