// ==UserScript== // @name Jureeka // @namespace http://www.jureeka.org // @description Turns legal citations in webpages into hyperlinks that direct you to online legal source material. // ==/UserScript== /* Warnings: * This triggers a memory leak bug in Firefox. * This triggers a dataloss bug in Firefox when editing long Wikipedia pages. Original author of AutoLink: Jesse Ruderman - http://www.squarefree.com/ - wrote the original script of Autolink. Original author of Jureeka: Michael Poulshock. License: MPL, GPL, LGPL. */ const timeBefore = new Date(); /*********************************** * Filters * ***********************************/ const theDomain = "www.jureeka.net/Jureeka"; /*********************************** * Filters * ***********************************/ //href (function) - returns the URL to be used for a link, or |null| to cancel link creation. //If multiple filters match a string, the first filter will win. const filters = [ { name: "U.S. and State Constitutions", regexp: /([A-Za-z\.]+) Const.,? (((a|A)rt\.|(a|A)mend\.|(p|P)mbl\.|(p|P)reamble) ([XVI]+))?(, ?(§|s|S|§|§) ?([0-9]+))?(, ?cl\. ?([0-9]+))?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=Constitutions&juris=" + match[1] + "&part=" + match[3] + "&art=" + match[8] + "&sec=" + match[11] + "&cl=" + match[13]; } }, { name: "U.S. Supreme Court", //regexp: /([0-9]+) (US|U\.S\.|U\. S\.) ([0-9]+)(, ?([0-9]+)(\.|;|,|-))?/ig, regexp: /([0-9]|[1-9][0-9]|[1-5][0-9][0-9]) (US|U\.S\.|U\. S\.) ([0-9]+)(, ?([0-9]+)(\.|;|,|-))?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=U.S.&vol=" + match[1] + "&page=" + match[3] + "&pinpoint=" + match[5]; } }, { name: "U.S. Code", regexp: /([0-9]+) U\.? ?S\.? ?C\.?( ?S\.?|A\.?)? (§|s|S|§|§|Sect?\.?|sect?\.?)* ?([0-9]+)(([a-z]+)(-([0-9])([a-z])?)?)?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=U.S.C.&vol=" + match[1] + "&sec=" + match[4] + "&sec2=" + match[6] + "&sec3=" + match[8] + "&sec4=" + match[9] ; } }, { name: "Code of Federal Regulations", regexp: /([0-9]+) (C\.?F\.?R\.?|Code of Federal Regulations) (§|s|S|Parts?)* ?([0-9aA]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=CFR&title=" + match[1] + "&part=" + match[4]; } }, { name: "Treasury Regulations", regexp: /Treas\.? ?Reg\.? ?(§|s|S|§|§|Sec\.?|sec\.?|Parts?)* ?([0-9aA]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=CFR&title=26&part=" + match[2]; } }, { name: "Fed. R. Civ. P.", regexp: /(F\.?R\.?C\.?P\.?|Fed\.? ?R\.? ?Civ\.? ?Pr?o?c?\.?|Federal Rules? of Civil Procedure) ?(Rule)? ?([0-9]+)?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=FRCP&rule=" + match[3]; } }, { name: "Federal Register", regexp: /((6|7)[0-9]) (F\.?R\.?|Fed\. ?Reg\.) ([0-9,]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=FedRegister&vol=" + match[1] + "&page=" + match[4]; } }, { name: "Federal Reporter, Second Series", //regexp: /(4[5-9][0-9]|[5-9][0-9][0-9]) ?F\.? ?2d\.? ?([0-9]+)/g, regexp: /(17[8-9]|1[8-9][0-9]|[2-9][0-9][0-9]) ?F\.? ?2d\.? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=F2d&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Federal Reporter, Third Series", //regexp: / ([1-9]|[1-7][0-9]|8[0-5]) ?F\.? ?3d\.? ?([0-9]+)/g, regexp: /([1-9]|[1-9][0-9]|[1-9][0-9][0-9]) F\.? ?3d\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=F3d&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Federal Reporter, First Series", regexp: /([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-7][0-9]|28[0-1]) F\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=F1d&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Fed. R. Evid.", regexp: /(FRE | fre |Fed\.? ?R\.? ?Evid\.?|Federal Rules? of Evidence)( ?[0-9]+)?/g, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=FRE&rule=" + match[2]; } }, { name: "Fed. R. Crim. P.", regexp: /(FRCrP|Fed\.? ?R\.? ?Crim\.? ?Pr?o?c?\.?|Federal Rules? of Criminal Procedure) (([0-9]+)\.?([0-9])?)?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=FRCrimP&rule=" + match[3] + "&ruleDec=" + match[4]; } }, { name: "Fed. R. App. P.", regexp: /(FRAP|Fed\.? ?R\.? ?App\.? ?Pr?o?c?\.?|Federal Rules? of Appellate Procedure) ([0-9]+(\.1)?)?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=FRAP&rule=" + match[2]; } }, { name: "Uniform Commercial Code", regexp: /(UCC|U\.C\.C\.|Uniform Commercial Code) ?(§|§|§)* ?(([1-9A]+)-([0-9]+))/g, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=UCC&part=" + match[4] + "&prov=" + match[5]; } }, { name: "Regional State Reporters (U.S. - 3d ser.)", //regexp: /([1-9]|[1-9][0-9]|[1-9][0-9][0-9]) (So\.( ?2d\.?)?|P\.?( ?2d\.?| ?3d\.?)?|A\.?( ?2d\.?)?|(N|S)\.?(W|E)\.?( ?3d\.?)?) ([0-9]+)/ig, regexp: /([1-9]|[1-9][0-9]|[1-9][0-9][0-9]) ((So\.?|P\.?|S\.?W\.?|S\.?E\.?|N\.?W\.?|N\.?E\.?|A\.?) ?3d\.?) ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&vol=" + match[1] + "&rptr=" + match[2] + "&page=" + match[4]; } }, { name: "Regional State Reporters (U.S. - P)", regexp: /([0-9]|[1-9][0-9]|1[0-9][0-9]|20[0-8]) P\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=p&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Regional State Reporters (U.S. - P2d)", regexp: /(9[3-9][0-9]) P\.? ?2d\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=p2d&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Regional State Reporters (U.S. - SW)", regexp: /(9[2-9]|1[0-9][0-9]|2[0-3][0-9]|24[0-2]) S\.? ?W\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=sw&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Regional State Reporters (U.S. - SW2d)", regexp: /(9[3-9][0-9]) S\.? ?W\.? ?2d ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=sw2d&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Regional State Reporters (U.S. - NW)", regexp: /(3[2-9]|[4-9][0-9]|1[0-8][0-9]) N\.? ?W\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=nw&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Regional State Reporters (U.S. - NW2d)", regexp: /(559|5[6-9][0-9]|[6-9][0-9][0-9]) N\.? ?W\.? ?2d ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=nw2d&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Regional State Reporters (U.S. - So.)", regexp: /(3[8-9]|[4-8][0-9]|9[0-2]) So\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=so&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Regional State Reporters (U.S. - So2d)", regexp: /(6[8-9][0-9]|7[0-9][0-9]) So\.? ?2d\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=p&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Regional State Reporters (U.S. - SE)", regexp: /(2[1-9]|[3-7][0-9]|8[0-8]) S\.? ?E\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=se&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Regional State Reporters (U.S. - SE2d)", regexp: /(48[1-9]|49[0-9]|[5-9][0-9][0-9]) S\.? ?E\.? ?2d ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=se2d&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Regional State Reporters (U.S. - NE)", regexp: /(3[1-9]|[4-9][0-9]|1[0-2][0-9]|13[0-5]) N\.? ?E\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=ne&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Regional State Reporters (U.S. - NE2d)", regexp: /(67[5-9]|6[8-9][0-9]|[7-9][0-9][0-9]) N\.? ?E\.? ?2d ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=ne2d&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Regional State Reporters (U.S. - A)", regexp: /(3[1-9]|[4-9][0-9]|10[0-9]|11[0-6]) A\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=a&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Regional State Reporters (U.S. - A2d)", regexp: /(68[6-9]|69[0-9]|[7-9][0-9][0-9]) A\.? ?2d ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RegionalRptrs&rptr=a2d&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Code of Alabama", regexp: /(Alabama |Ala\.? ?)Code/g, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=AlabamaCode"; } }, { name: "Alabama Appellate Courts", regexp: /[0-9]+ Ala\.?( ?Civ\.? ?App\.? ?)? [0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=AlabamaCases"; } }, { name: "Alaska Statutes", regexp: /Alaska Stat(\.?|utes?)/g, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=AlaskaCode"; } }, { name: "Alaska Appellate Courts", regexp: /([0-9]+) P\.?(2|3)d ([0-9]+)(, ?[-0-9 n\.]+)? \(Alaska ((Ct\.)? ?App\.?)? ?[0-9]+\)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=AlaskaCases&vol=" + match[1] + "&reporter=" + match[2] + "&page=" + match[3]; } }, { name: "Arizona Statutes", regexp: /Ariz(\.|ona) (Rev\.)? ?Stat(\.?|utes?)( Ann\.?)? (§|s|S|§|§|(s|S)ection)* ?([0-9]+)-([-0-9A\.]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=ArizonaStatutes&title=" + match[7] + "&sec=" + match[8]; ; } }, { name: "Arizona Supreme Court", regexp: /[0-9]+ Ariz\.? [0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=ArizonaCases"; } }, { name: "Arkansas Code", regexp: /Ark(\.?|ansas) Code( Ann\.?)?/g, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=ArkansasCode"; } }, { name: "Arkansas cases", regexp: /[0-9]+ (Ark\.?|Ark\.? ?App.) [0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=ArkansasCases&ct=" + match[1]; } }, { name: "California cases", regexp: /[0-9]+ Cal\.? ?(App\.?)? ?(2d|3d|4th)?\.? ?(Supp\.?)? [0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=CAcases"; } }, { name: "Colorado Statutes", regexp: /Colo(\.?|rado) (Rev\.?)? ?Stat(\.?|utes?)( Ann\.?)? (§|s|S|§|§|(s|S)ection)* ?([-0-9\.]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=ColoradoStatutes&prov=" + match[7]; } }, { name: "Connecticut Statutes", regexp: /Conn(\.?|ecticut) ?Gen(\.?|eral) ?Stat(\.?|utes?)( Ann\.?)? (§|s|S|§|§|(s|S)ection)* ?([0-9]+(A|a)?)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=ConnStatutes&title=" + match[7]; } }, { name: "Connecticut cases", regexp: /[0-9]+ Conn\.? (App\.?)? [0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=ConnCases"; } }, { name: "Delaware Code", regexp: /Del(\.?|aware) ?Code ?( Ann\.?)? (t|T)it\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=DelawareCode&title=" + match[4]; } }, { name: "Delaware cases", regexp: /Del\.? (Ch\.?)? 2[0-9]+/g, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=DelawareCases"; } }, { name: "D.C. Code", regexp: /(D\.?C\.?|District of Columbia) Code (Ann.?)?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=DCCode"; } }, { name: "D.C. Court of Appeals", regexp: /D\.? ?C\.? ?App\.? (1999|2[0-9]+)/g, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=DCCases"; } }, { name: "Florida Statutes", regexp: /Fla\.? Stat\.? ( Ann\.?)? ?(§|s|S|§|§|(s|S)ection)* ?([0-9]+)\.([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=FloridaStatutes&ch=" + match[4] + "&sec=" + match[5]; } }, { name: "Florida cases", regexp: /Fla\.? (Dist\.?)? ?(App\.?)? ?[1-5]? ?(Dist\.)? ?(199|200)[0-9]/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=FloridaCases"; } }, { name: "Georgia Code", regexp: /Ga\.? Code ( Ann\.?)? ?(§|s|S|§|§|(s|S)ection)* ?([0-9]+)-([-0-9A\.]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=GeorgiaCode&title=" + match[4] + "&sec=" + match[5]; } }, { name: "Georgia Supreme Court", regexp: /[0-9]+ Ga\.? [0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=GeorgiaCases"; } }, { name: "Hawai'i Statutes", regexp: /Haw(\.?|ai'?i) Rev(\.?|ised) Stat(\.?|utes)?( Ann\.?)?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=HawaiiStatutes"; } }, { name: "Hawai'i Appellate Courts", regexp: /(8[7-9]|9[0-9]|1[0-9]+) Haw(\.?|ai'?i) [0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=HawaiiCases"; } }, { name: "Idaho Code", regexp: /Idaho Code/g, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=IdahoCode"; } }, { name: "Idaho Supreme Court", regexp: /[0-9]+ Idaho [0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=IdahoCases"; } }, { name: "Illinois Statutes", regexp: /([0-9]+) (ILCS|Ill\.? Comp\.? Stat\.?( Ann\.)?)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=IllinoisStatutes&ch=" + match[1]; } }, { name: "Illinois Cases", regexp: /[0-9]+ Ill\.? ?(2d|App\.? ?3d) ?[0-9][0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=IllinoisCases"; } }, { name: "Indiana Code", regexp: /(I\.?C\.?|Ind(\.?|iana) ?Code ?(Ann(\.?|otated))?) ?(§|s|S|§|§|(s|S)ection)* ?([0-9\.]+)-([0-9\.]+)-([0-9\.]+)-([0-9\.]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=IndianaCode&title=" + match[7] + "&art=" + match[8] + "&sec=" + match[9]; } }, { name: "Iowa Code", regexp: /Iowa ?Code ?(Ann(\.?|otated))? ?(§|s|S|§|§|(s|S)ection)* ?([0-9A-Z\.]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=IowaCode&sec=" + match[5]; } }, { name: "Iowa Cases", regexp: /\(Iowa (App\.?)? ?(199(8|9)|200[0-9])\)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=IowaCases"; } }, { name: "Kansas Statutes", regexp: /(K\.?S\.?A\.?|Kan(\.?|sas) ?Stat\.? ?( Ann\.?)?) ?(§|s|S|§|§|(s|S)ection)? ?([0-9a]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=KansasStatutes&ch=" + match[6]; } }, { name: "Kansas Cases", regexp: /\((Kan\.? ?(App\.?)?) ?(199(7|8|9)|200[0-9])\)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=KansasCases&ct=" + match[1]; } }, { name: "Kentucky Statutes", //regexp: /K(y\.|entucky) ?Rev(\.|ised) ?Stat(\.|utes) ?( Ann(\.|otated))? ?(§|s|S|§|§)* ?(([0-9]+)([A-G])\.(([0-9]+)-)?([0-9a]+)/g, regexp: /K(y\.|entucky) ?Rev(\.|ised) ?Stat(\.|utes) ?(Ann(\.|otated))?/ig, // href: function(match) { return "http://" + theDomain + "/US.aspx?doc=KentuckyStatutes&ch=" + match[7] + "&chltr=" + match[9] + "&subch=" + match //[9] + "&sec=" + match[10]; href: function(match) { return "http://" + theDomain + "/US.aspx?doc=KentuckyStatutes"; } }, { name: "Kentucky Cases", regexp: /Ky\.? (App\.?)? ?(199(6|7|8|9)|200[0-9])/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=KentuckyCases"; } }, { name: "Maine Statutes", regexp: /Me\.? ?Rev\.? ?Stat\.? ?(Ann\.?)?,? ?(T|t)it(\.?|le) ?([-0-9A]+),? (§|s|S|§|§|(s|S)ection)* ?([-0-9A]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MaineStatutes&title=" + match[4] + "&sec=" + match[7]; } }, { name: "Maine Supreme Court", regexp: /(199[7-9]|200[0-9]) ME ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MaineSupCt&year=" + match[1] + "&no=" + match[2]; } }, { name: "Maryland Court of Appeals", regexp: /(33[7-9]|3[4-9][0-9]|4[0-9][0-9]) Md\.? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MDCourtApp&vol=" + match[1]; } }, { name: "Maryland Court of Special Appeals", regexp: /(10[4-9]|1[1-9][0-9]) Md\.? ?App\.? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MDCourtSpApp&vol=" + match[1]; } }, { name: "Massachusetts General Laws", regexp: /Mass\.? ?Gen\.? ?Laws ?ch\.? ?([0-9A-Z]+),? ?(§|s|S|§|§|(s|S)ection)* ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MassGenLaws&ch=" + match[1] + "&sec=" + match[4]; } }, { name: "Massachusetts SJC Cases", regexp: /([3-4][0-9][0-9]) Mass\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MassSJCCases&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Massachusetts Ct. App. Cases", regexp: /([1-9]|[1-9][0-9]) Mass\.? App\.? Ct\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MassCtAppCases&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Michigan Compiled Laws", regexp: /Mich\.? ?Comp\.? ?Laws ?(Ann\.?)? ?(§|s|S|§|§|(s|S)ection)* ?([0-9\.]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MichStatutes&sec=" + match[4]; } }, { name: "Michigan Supreme Court", regexp: /([0-9]+) Mich\.? ?[0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MichSupremeCt&vol=" + match[1]; } }, { name: "Michigan Court of Appeals", regexp: /([0-9]+) Mich\.? ?(Ct\.?)? ?App\.? ?[0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MichCtApp&vol=" + match[1]; } }, { name: "Minnesota Statutes", regexp: /Minn\.? ?Stat\.? ?(Ann\.?)? ?(§|s|S|§|§|(s|S)ection)* ?([0-9][0-9A-Z\.]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MinnStatutes&sec=" + match[4]; } }, { name: "Minnesota Cases", regexp: /\(Minn\.? ?(Ct\.? ?App\.?)? ?(199[6-9]|200[0-9])\)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MinnCases"; } }, { name: "Mississippi Code", regexp: /Miss\.? ?Code ?Ann\.?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MississippiCode"; } }, { name: "Mississippi Cases", regexp: /Miss\.? ?(Ct\.? ?App\.?)? ?(199[6-9]|200[0-9])/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=MississippiCases"; } }, { name: "New Jersey Statutes", regexp: /(N\.?J\.?S\.?A\.?|N\.?J\.? Stat\.? Ann\.?)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=NJSA"; } }, { name: "New Jersey Administrative Code", regexp: /(N\.?J\.?A\.?C\.?|N\.?J\.? Administrative Code)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=NJAC"; } }, { name: "New Jersey Appellate Cases", regexp: /[0-9]+ N\.? ?J\.?( Super\.?)? [0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=NJAppCases&cite=" + match[0]; } }, { name: "New Mexico Statutes", regexp: /(NMSA|N\.?M\.? ?Stat\.? ?(Ann\.)?)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=NMStatutes"; } }, { name: "New Mexico Cases", regexp: /(199[8-9]|200[0-9]) ?-?(NMCA|NMSC) ?-?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=NMCases&year=" + match[1] + "&ct=" + match[2] + "&no=" + match[3]; } }, { name: "New York Court of Appeals", regexp: /(79|[8-9][0-9]|[1-4][0-9][0-9]) N\.?Y\.?2d\.? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=NYCtApp&vol=" + match[1] + "&page=" + match[2]; } }, { name: "North Dakota Code", regexp: /N\.?D\.? ?Cent\.? ?Code (§|s|S|§|§|(s|S)ection)* ?([0-9\.]+)-([0-9\.]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=NDCode&title=" + match[3] + "&ch=" + match[4]; } }, { name: "North Dakota Supreme Court", regexp: /(199[7-9]|200[0-9]) ?ND ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=NDSupremeCases&year=" + match[1] + "&no=" + match[2]; } }, { name: "North Dakota Ct. of Appeals", regexp: /(199[8-9]|200[0-9]) ?ND App\.? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=NDAppealsCases"; } }, { name: "North Dakota Cases", regexp: /([0-9]+) N\.?W\.?2d\.? ([0-9]+)(, [0-9]+)? ?\(N\.D\. ?(Ct. ?App.)? ?[0-9]+\)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=NDNW2dCases&vol=" + match[1]; } }, { name: "N.Y. C.P.L.R.", regexp: /(New York|N\.?Y\.? ?)?(C\.?P\.?L\.?R\.?|Civil Practice Law and Rules)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=NYCPLR"; } }, { name: "Ohio Code", regexp: /Ohio ?Rev\.? ?Code ?(Ann\.?)? ?(§|s|S|§|§|(s|S)ection)* ?([-0-9\.A]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=OhioCode&sec=" + match[4]; } }, { name: "Ohio Administrative Code", regexp: /Ohio ?Admin\.? ?Code ?(§|s|S|§|§|(s|S)ection)* ?([-0-9\.:]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=OhioAdminCode&sec=" + match[3]; } }, { name: "Ohio Supreme Court", regexp: /(199[2-9]|200[0-9])-Ohio-([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=OhioSupCt&year=" + match[1] + "&no=" + match[2]; } }, { name: "Oregon Statutes", regexp: /Ore?(\.?|egon) ?Rev\.? ?Stat\.? ?(§|s|S|§|§|(s|S)ection)* ?([-0-9a-d]+)(.([-0-9a-d]+))?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=OregonStatutes&ch=" + match[4] + "&sec=" + match[5]; } }, { name: "Pennsylvania Statutes", regexp: /([0-9]+) Pa\. ?C(ons\.)? ?S(tat\.)? ?(Ann\.)?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=PAStatutes&title=" + match[1]; } }, { name: "Pennsylvania Code of Regulations", regexp: /([0-9]+) Pa\.? ?Code ?(§|s|S|§|§|(s|S)ection)* ?([0-9]+)(\.([0-9]+))?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=PACode&title=" + match[1] + "&ch=" + match[4] + "&sec=" + match[6]; } }, { name: "Pennsylvania Supreme Court", regexp: /\(Pa\.? ?(199[7-9]|200[0-9])\)/g, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=PASupremeCt"; } }, { name: "Laws of Puerto Rico", regexp: /P\.?R\.? ?Laws ?Ann\.?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=PRLaws"; } }, { name: "General Laws of Rhode Island", regexp: /R\.?I\.? ?Gen\.? ?Laws ?(§|s|S|§|§|(s|S)ection)* ?([0-9\.A]+)-([-0-9\.]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RIGenLaws&title=" + match[3] + "&sec=" + match[4]; } }, { name: "South Carolina Codes", regexp: /S\.?C\.? ?Code (Ann\.?)? ?(Regs\.?)? ?(§|s|S|§|§|(s|S)ection)* ?([0-9\.A]+)-([0-9\.]+)(-([0-9\.]+))?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=SCCodes&type=" + match[2] + "&title=" + match[5] + "&ch=" + match[6] + "&sec=" + match[8]; } }, { name: "Tennessee Code", regexp: /Tenn(\.?|essee) ?Code ?(Ann(\.?|otated))?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=TNCode"; } }, { name: "UtahCode", regexp: /Utah Code ?Ann\.? ?(§|s|S|§|§|(s|S)ection)* ?([0-9A-F]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=UTCode&title=" + match[3]; } }, { name: "Vermont Supreme Court", regexp: /(15[4-9]|16[0-9]|17[0-8]) Vt\. [0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=VTSupremeCt&vol=" + match[1]; } }, { name: "Vermont Code", regexp: /Vt\.? ?Stat\.? ?Ann\.? ?tit\.? ?([0-9A]+), ?(§|s|S|§|§|(s|S)ection)* ?([0-9]+)([a-z]+)?/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=VTCode&title=" + match[1] + "&sec=" + match[4] + "&sec2=" + match[5]; } }, { name: "Virginia Code", regexp: /Va\.? ?Code ?Ann\.? ?(§|s|S|§|§|(s|S)ection)* ?([-0-9A\.:]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=VACode&sec=" + match[3]; } }, { name: "Virginia Cases", regexp: /[0-9]+ Va\.? ?(App\.?)? ?[0-9]+/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=VACases"; } }, { name: "Revised Code of Washington", regexp: /Wash\.? ?Rev\.? ?Code? ?(Ann\.?)? ?(§|s|S|§|§|(s|S)ection)* ?([0-9A-Z\.]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=RevCodeWash&sec=" + match[4]; } }, { name: "Wisconsin Statutes", regexp: /Wis\.? ?Stat\.? ?(Ann\.?)? ?(§|s|S|§|§|(s|S)ection)* ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=WIStatutes&ch=" + match[4]; } }, { name: "U.S. Public Laws", regexp: /Pub(\.?|lic) ?L(\.?|aw) ?(No\.?)? ?(10[4-9]|11[0-9])-([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=USPubLaws&cong=" + match[4] + "&no=" + match[5]; } }, { name: "Congressional Resolutions", regexp: /(S\.? ?((Con\.?|J\.?)? ?Res\.?)?|H\.? ?R\.? ?((Con\.?|J\.?)? ?Res\.?)?) ?([0-9]+),? ?(10[3-9]|11[0-9])(th|rd) Cong\./ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=CongRes&type=" + match[1] + "&no=" + match[6] + "&cong=" + match[7]; } }, // { // name: "Congressional Reports", // regexp: /(H\.? ?(R\.)?|S\.?) ?Rep\.? ?Nos?\.? (109|110)-([0-9]+)/ig, // href: function(match) { return "http://" + theDomain + "/US.aspx?doc=CongReps&type=" + match[1] + "&cong=" + match[3] + "&no=" + match[4]; } // }, { name: "NLRB Cases", regexp: /([0-9]+) N\.?L\.?R\.?B\.? ?(No\.?)? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=NLRB&vol=" + match[1] + "&page=" + match[3]; } }, { name: "BIA Cases", regexp: /([0-9]+) I\.? ?& ?N\.? ?Dec\.? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=BIA&vol=" + match[1] + "&page=" + match[2]; } }, { name: "Decisions of the Comptroller General", regexp: /([0-9]+) (Comp|COMP)\.? ?(Gen|GEN)\.? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=GOA&vol=" + match[1] + "&page=" + match[4]; } }, { name: "U.S. Patents", regexp: /U\.? ?S\.? ?Patent\.? ?Nos?\.? ([0-9,]+)/ig, href: function(match) { return "http://" + theDomain + "/US.aspx?doc=USPatents&no=" + match[1]; } }, // INTERNATIONAL LAW { name: "International Court of Justice", regexp: /I\.?C\.?J\.? Reports ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=ICJ&year=" + match[1]; } }, { name: "International Court of Justice", regexp: /\[?\(?([0-9]+)\)?\]? I\.?C\.?J\.?/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=ICJ&year=" + match[1]; } }, { name: "Permanent Court of International Justice", regexp: /P\.?C\.?I\.?J\.?,? ?\(?(S|s)er(\.?|ies) ([ABC/])\)?,? ?No\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=PCIJ&ser=" + match[3] + "&no=" + match[4]; } }, { name: "European Court Reports", regexp: /\[?\(?(1969|19[7-9][0-9]|200[0-9])\)?\]? E\.?C\.?R\.? (([I]+)-)?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=ECR&year=" + match[1] + "&page=" + match[4] + "&part=" + match[3]; } }, { name: "European Court of Human RIghts", regexp: /(E\.?Ct\.?H\.?R\.?|Eur\.? ?Ct\.? ?H\.?R\.?)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=ECtHR"; } }, { //European citation form name: "Official Journal of the European Union", regexp: /O\.?J\.? ?(No\.? ?)?(L|C)?\.? ?([0-9]+),? ?[0-9]+\. ?[0-9]+\. ?([0-9]+)((,|\/)? ?(p\.)? ?([0-9]+))?/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=OJEU&ser=" + match[2] + "&issue=" + match[3] + "&year=" + match[4] + "&page=" + match[8]; } }, { //U.S. citation form name: "Official Journal of the European Union", regexp: /\[?\(?(19[0-9][0-9]|20[0-9][0-9])\)?\]? O\.?J\.? \(?(L|C)?\.? ?([0-9]+)\)?((,|\/)? ?(p\.?)? ?([0-9]+))?/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=OJEU&year=" + match[1] + "&ser=" + match[2] + "&issue=" + match[3] + "&page=" + match[7]; } }, { name: "Inter-American Court of Human Rights", regexp: /Inter-Am(\.|erican) ?Ct?\.? ?H\.?R\.?,? ?\(?(S|s)er(\.?|ies) ([AC])\)?,? ?No\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=IACtHR&ser=" + match[4] + "&no=" + match[5]; } }, { name: "United Nations Documents", regexp: /U\.?N\.? Doc\.?( No\.?)? ([A-Z0-9ubdmenorvay\/\.]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=UNDoc&docsymbol=" + match[2]; } }, { name: "UN Committee Against Torture", regexp: /(CAT\/[A-Z0-9ubdmenorvay\/\.]+)/g, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=UNDoc&docsymbol=" + match[1]; } }, { name: "World Trade Organization documents", regexp: /(WT\/[A-Za-z0-9\/\.]+)/g, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=WTODoc&docsymbol=" + match[1]; } }, { name: "International Labor Organization Conventions", regexp: /I\.?L\.?O\.? Conv(\.?|ention) ?\(?(No\.? )? ?([0-9]+)\)?/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=ILO&conv=" + match[3]; } }, { name: "UN Reports of International Arbitral Awards (RIAA)", regexp: /([0-9]+) R\.?I\.?A\.?A\.? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=RIAA&vol=" + match[1] + "&page=" + match[2]; } }, //CANADA { name: "Canada - Federal Courts", regexp: /([\[0-9+\] [0-9]+) (S\.?C\.?R\.?|F\.?C\.?) ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=CanadaFedCases&vol=" + match[1] + "&rptr=" + match[2] + "&page=" + match[3]; } }, { name: "Supreme Court of Canada", regexp: /([0-9]+) (S\.?C\.?C\.?) ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=CanadaFedCases&vol=" + match[1] + "&rptr=" + match[2] + "&page=" + match[3]; } }, { name: "Constitution Act (Canada)", regexp: /Constitution Act, (1867|1982)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=CanadaConst&year=" + match[1]; } }, { name: "Consolidated Statutes of Canada", regexp: /(((R\.?)?S\.?C\.?|C\.?R\.?C\.?) [0-9]+, c\. [-0-9A-Z]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=CanadaStatutes&cite=" + match[1]; } }, { name: "Consolidated Regulations of Canada", regexp: /((S\.?I\.?|S\.?O\.?R\.?)\/[-0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=CanadaRegs&cite=" + match[1]; } }, // UNITED KINGDOM { name: "UK Appeals Cases", regexp: /\[?\(?(19[0-9][0-9]|200[0-9])\)?\]? ([0-9]+)? ?A\.?C\.? ([0-9]+)/g, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=UKAppealsCases&cite=" + match[0]; } }, { name: "UK House of Lords", regexp: /\[?\(?(19[0-9][0-9]|200[0-9])\)?\]? ([0-9]+)? ?U\.?K\.?H\.?L\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=UKHL&cite=" + match[0]; } }, { name: "UK Privy Council", regexp: /\[?\(?(19[0-9][0-9]|200[0-9])\)?\]? ([0-9]+)? ?U\.?K\.?P\.?C\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=UKPC&cite=" + match[0]; } }, { name: "UK Queen's Bench", regexp: /\[?\(?(19[0-9][0-9]|200[0-9])\)?\]? ([0-9]+)? ?Q\.?B\.? ([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=UKQB&cite=" + match[0]; } }, { name: "England and Wales Court of Appeal", regexp: /\[?\(?(19[0-9][0-9]|200[0-9])\)?\]? ([0-9]+)? ?E\.?W\.?C\.?A\.? (Civ\.?|Crim\.?|Admin\.?)? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=EWCA&cite=" + match[0]; } }, { name: "England and Wales High Court", regexp: /\[?\(?(19[0-9][0-9]|200[0-9])\)?\]? ([0-9]+)? ?E\.?W\.?H\.?C\.? (Civ\.?|Crim\.?|Admin\.?|Ch\.?)? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=EWCA&cite=" + match[0]; } }, { name: "UK Weekly Law Reports", regexp: /\[?\(?(19[0-9][0-9]|200[0-9])\)?\]? ? ?([0-9]+)? ?W\.?L\.?R\.? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=WLR&cite=" + match[0]; } }, { name: "UK All England Reports", regexp: /\[?\(?(19[0-9][0-9]|200[0-9])\)?\]? ([0-9]+)? ?All E\.?R\.? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=AllER&cite=" + match[0]; } }, { name: "Supreme Court of Ireland", regexp: /\[?\(?(19[0-9][0-9]|200[0-9])\)?\]? ? ?([0-9]+)? ?I\.?E\.?S\.?C\.? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=IESC&cite=" + match[0]; } }, { name: "Court of Appeal in Northern Ireland", regexp: /\[?\(?(19[0-9][0-9]|200[0-9])\)?\]? ? ?([0-9]+)? ?N\.?I\.?C\.?A\.? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=NICA&cite=" + match[0]; } }, // AUSTRALIA { name: "Australia Commonwealth Law Reports", regexp: /\[?\(?(19[0-9][0-9]|200[0-9])\)?\]? ? ?([0-9]+)? ?C\.?L\.?R\.? ?([0-9]+)/ig, href: function(match) { return "http://" + theDomain + "/Intl.aspx?doc=AustraliaCLR&cite=" + match[0]; } } ]; /*********************************** * Helper functions for filters * ***********************************/ function digits(s) { return s.replace(/[^0-9]/g, ""); } function alphanumerics(s) { return s.replace(/[^0-9a-z]/ig, ""); } /*********************************** * Link styling * ***********************************/ /* You can make links generated by AutoLink look different from normal links by editing styleLink below and/or by setting up user style sheet rules. Example: on squarefree.com, make autolinked plain text links green. (Firefox trunk only.) @-moz-document domain(squarefree.com) { .autolink-plain-text-link { color: green ! important; } } */ function styleLink(a, filter) { a.style.borderBottom = "1px solid green"; } /*********************************** * Fix filters * ***********************************/ function fixFilters() { var i, r; for (i = 0; r = filters[i]; ++i) { // lowercase, and replace each run of non-alphanumerics with a single hyphen r.classNamePart = r.name.toLowerCase().replace(/[^0-9a-z]+/ig, "-"); if(!r.regexp.global) alert("AutoLink filter " + r.name + " is not global! This will break stuff!"); } } fixFilters(); /*********************************** * When and where to run * ***********************************/ var moddingDOM = false; window.addEventListener("load", init, false); function init() { document.addEventListener("DOMNodeInserted", nodeInserted, false); setTimeout(go, 50, document.body); } // This makes it work at Gmail. // 20% performance penalty on a plain text file with a link on almost every line. // Tiny performance penalty on pages with few automatically added links. function nodeInserted(e) { // our own modifications should not trigger this. // (we don't want our regular expression objects getting confused) // (we want better control over when we recurse) //GM_log("Inserted: " + e.target); if (!moddingDOM) go(e.target); } /*********************************** * DOM traversal * ***********************************/ /* This script uses manual DOM traversal, in an iterative way without a stack! Advantages of snapshot XPath: * Much less code * 20-40% faster * May be possible to get another speed boost by including the regexp in the XPath expression - http://www.developer.com/xml/article.php/10929_3344421_3 * All the cool people are using it Advantages of manual DOM traversal: * Lets us stop+continue (snapshot xpath doesn't let us) * Lets us modify DOM in strange ways without worrying. * Easier to control which elements we recurse into. */ // Ignore all children of these elements. const skippedElements = { a: true, // keeps us from screwing with existing links. keeps us from recursing to death :) noscript: true, // noscript has uninterpreted, unshown text children; don't waste time+sanity there. head: true, script: true, style: true, textarea: true, label: true, select: true, button: true } const gmail = (location.host == "gmail.google.com"); function skipChildren(node) { if (node.tagName) // ! { if (skippedElements[node.tagName.toLowerCase()]) { return true; } if (gmail) { if (node.className == "ac") // gmail autocomplete (fake dropdown) return true; if (node.className == "ilc sxs") // invite foo to gmail (fake link/button) return true; } } return false; } // Don't insert hyperlinks on certain legal research sites function go(traversalRoot) { var currentURL = location.host; if(currentURL.indexOf('lexis') == -1 && currentURL.indexOf('westlaw') == -1 && currentURL.indexOf('loislaw') == -1 && currentURL.indexOf('fastcase') == -1) { go2(traversalRoot); } } function go2(traversalRoot) { var m; // Ensure we're not already in a forbidden element. for (m = traversalRoot; m != undefined; m = m.parentNode) { if (skipChildren(m)) { return; } } // work around bug, or in case previous user scripts did crazy stuff traversalRoot.normalize(); function cont(n, didChildren) { var k = 0; // split work into chunks so Firefox doesn't freeze var q; while (n && k < 100) { ++k; // Do stuff at this node if (!didChildren && n.nodeType == 3) { if((q = runFiltersOnTextNode(n))) { n = q[0]; // if there were changes, run filters again on the new text node that's here if (q[1]) continue; } } // Traverse to the "next" node in depth-first order if (!n.firstChild) didChildren = true; if (didChildren && n == traversalRoot) break; else if (!didChildren && n.firstChild && !skipChildren(n)) { n = n.firstChild; // didChildren is already false and should stay false } else { if (n.nextSibling) { n = n.nextSibling; didChildren = false; } else { n = n.parentNode; didChildren = true; } } } // end while if (!n) { //GM_log("Odd. traversalRoot was " + traversalRoot); } else if (n == traversalRoot) { //GM_log("Done"); //alert("AutoLink time: " + (new Date() - timeBefore)) } else { // Continue after 10ms. //GM_log("will have to continue"); setTimeout(cont, 10, n, didChildren); } } // end function cont cont(traversalRoot, false); } /*********************************** * Running filters * ***********************************/ // runFiltersOnTextNode // Return: node at which to continue traversal, or |null| to mean no changes were made. function runFiltersOnTextNode(node) { // Too many variables. Good hint that I need to split this function up :P var source, j, regexp, match, lastLastIndex, k, filter, href, anyChanges; // things var used, unused, firstUnused, lastUnused, a, parent, nextSibling; // nodes source = node.data; anyChanges = false; // runFiltersOnTextNode has its own do-too-much-at-once avoider thingie. // assumption: if there is one text node with a lot of matches, // it's more important to finish quickly than be transparent. // (e.g. plain text file FULL of links) // assumption: 40 * 100 = 140. k=0; for (j = 0; filter = filters[j]; ++j) { regexp = filter.regexp; if (regexp.test(source)) { parent = node.parentNode; nextSibling = node.nextSibling; regexp.lastIndex = 0; firstUnused = null; // Optimization from the linkify that came with Greasemonkey(?): // instead of splitting a text node multiple times, take advantage // of global regexps and substring. for (match = null, lastLastIndex = 0; k < 40 && (match = regexp.exec(source)); ) { // this should happen first, so RegExp.foo is still good :) href = genLink(filter, match); if (href != null && href != location.href) { ++k; unused = document.createTextNode(source.substring(lastLastIndex, match.index)); if (!anyChanges) { anyChanges = true; parent.removeChild(node); firstUnused = unused; moddingDOM = true; } parent.insertBefore(unused, nextSibling); used = document.createTextNode(match[0]) a = document.createElement("a"); a.href = href; a.title = "Link to " + filter.name + " added by Cornell LII"; a.className = "autolink autolink-" + filter.classNamePart; styleLink(a, filter); a.appendChild(used); parent.insertBefore(a, nextSibling); lastLastIndex = regexp.lastIndex; } } if (anyChanges) { lastUnused = document.createTextNode(source.substring(lastLastIndex)); parent.insertBefore(lastUnused, nextSibling); moddingDOM = false; return [firstUnused, true] } return [node, false]; } } return null; } function genLink(filter, match) { try { return filter.href(match); } catch(er) { return "data:text/plain,Error running AutoLink function for filter: " + encodeURIComponent(filter.name) + "%0A%0A" + encodeURIComponent(er); } }