Skip to content

Instantly share code, notes, and snippets.

@aih
Forked from mpoulshock/gist:963725
Created May 15, 2011 04:37
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aih/972890 to your computer and use it in GitHub Desktop.
Save aih/972890 to your computer and use it in GitHub Desktop.
Transforms legal citations into hyperlinks
// ==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|§|&#167) ?([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|§|&#167|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|§|&#167|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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167)* ?(([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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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|§|&#167|(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);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment