Version 0.5.3
[minimalist.git] / content / minimalist.js
blobfcf5a11613563161d5b01f219170332da885fab2
1 (function() {
2   function nodeFilter(node) {
3     if (!(node.parentNode.tagName in ignore))
4       return NodeFilter.FILTER_ACCEPT
5   }
7   function metaHandler(event)
8   {
9     if (skipRefresh)
10     {
11       metaTags = event.target.getElementsByTagName('meta')
13       for (i in metaTags) {
14         metaTag = metaTags[i]
16         if (metaTag.httpEquiv.toLowerCase() == 'refresh') {
17           match = metaRE.exec(metaTag.content)
19           if (match != null) {
20             srcURL.spec = event.target.location.href
21             dstURL.spec = event.target.location.href
22             srcURL.spec = srcURL.resolve(match[1])
24             if (!srcURL.equals(dstURL))
25               event.target.location.replace(dstURL.spec)
26           }
27         }
28       }
29     }
31     if (enableLinkify)
32     {
33       nodeIterator = document.createNodeIterator(event.target, NodeFilter.SHOW_TEXT, { acceptNode: nodeFilter }, true)
34       while (currentNode = nodeIterator.nextNode()) {
35         if (nodeCarry)
36           currentNode.parentNode.removeChild(currentNode.previousSibling)
38         if (currentNode.nextSibling && currentNode.nextSibling.nodeType == 3) {
39           nodeCarry = nodeCarry + currentNode.data
40           continue
41         } else {
42           splitData = (nodeCarry + currentNode.data).split(urlRE)
43           nodeCarry = ''
44         }
46         if (splitData.length > 1) {
47           isText     = true
48           lastNode   = currentNode
49           parentNode = currentNode.parentNode
51           while (splitData.length) {
52             token = splitData.pop()
53             if (isText) {
54               isText  = false
55               newNode = document.createTextNode(carry + token)
56               carry   = ''
57             } else {
58               carry = token.split(dlimRE)
59               if (carry.length > 1) {
60                 token = carry[0]
61                 carry = carry[1]
62               } else
63                 carry = ''
65               newNode = document.createElementNS('http://www.w3.org/1999/xhtml', 'html:a')
66               newNode.appendChild(document.createTextNode(token))
68               token = token.replace(httpRE, 'http')
69               if (match = prepRE.exec(token))
70                 token = prefix[match[1]] + token
72               newNode.setAttribute('href', token)
73               isText = true
74             }
75             parentNode.insertBefore(newNode, lastNode)
76             lastNode = newNode
77           }
78           parentNode.removeChild(currentNode)
79         }
80       }
81     }
82   }
84   function observe(subject, topic, data)
85   {
86     switch (topic)
87     {
88       case 'nsPref:changed':
89         path = data.split('.')
90         switch (path[2])
91         {
92           case 'linkify':
93             enableLinkify = settings.getBoolPref(data)
94             break
96           case 'skipRefresh':
97             skipRefresh = settings.getBoolPref(data)
98             break
99         }
100         break
101     }
102   }
104   var settings = Components.classes['@mozilla.org/preferences-service;1'].getService(Components.interfaces.nsIPrefBranch)
105   settings.QueryInterface(Components.interfaces.nsIPrefBranch2)
106   settings.addObserver('extensions.minimalist.', {observe: observe}, false)
107   var enableLinkify = settings.getBoolPref('extensions.minimalist.linkify')
108   var skipRefresh   = settings.getBoolPref('extensions.minimalist.skipRefresh')
110   var nodeCarry = ''
111   var carry  = ''
112   var prefix = {'www': 'http://', 'ftp': 'ftp://', 'irc': 'irc://'}
113   var scheme = {'hxxp': 'http', 'h**p': 'http'}
114   var dlimRE = /([.,;])$/
115   var prepRE = /^(?![^:]*:\/\/)(?:.*?@)?(www|ftp|irc)/i
116   var httpRE = /^(?:hxxp|h\*\*p)/i
117   var metaRE = /url=(.+)/i
118   var urlRE  = /((?:(?:[a-zA-Z][a-zA-Z0-9+\-.*]*:\/\/|about:|mailto:)(?:(?:[a-zA-Z0-9\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF!$&'()*+,;=:]|%[0-9a-fA-F]{2})*@)?|(?:(?:[a-zA-Z0-9\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF!$&'()*+,;=:]|%[0-9a-fA-F]{2})*@)?(?:ftp|irc|www)\.)(?:(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])|(?:\[(?:(?:[0-9a-fA-F]{1,4}:){6}(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])|::(?:[0-9a-fA-F]{1,4}:){5}(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])|(?:[0-9a-fA-F]{1,4})?::(?:[0-9a-fA-F]{1,4}:){4}(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])|\r\n(?:(?:[0-9a-fA-F]{1,4}:)?[0-9a-fA-F]{1,4})?::(?:[0-9a-fA-F]{1,4}:){3}(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])|(?:(?:[0-9a-fA-F]{1,4}:){0,2}[0-9a-fA-F]{1,4})?::(?:[0-9a-fA-F]{1,4}:){2}(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])|(?:(?:[0-9a-fA-F]{1,4}:){0,3}[0-9a-fA-F]{1,4})?::[0-9a-fA-F]{1,4}:(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])|(?:(?:[0-9a-fA-F]{1,4}:){0,4}[0-9a-fA-F]{1,4})?::(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[0-9])|(?:(?:[0-9a-fA-F]{1,4}:){0,5}[0-9a-fA-F]{1,4})?::[0-9a-fA-F]{1,4}|(?:(?:[0-9a-fA-F]{1,4}:){0,6}[0-9a-fA-F]{1,4})?::)|v[0-9a-fA-F]+\.[a-zA-Z0-9\-._~!$&'()*+,;=:]+\])|(?:[a-zA-Z0-9\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF!$&'()*+,;=]|%[0-9a-fA-F]{2})*)(?::[0-9]*)?(?:\/(?:[a-zA-Z0-9\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF!$&'()*+,;=:@]|%[0-9a-fA-F]{2})*)*(?:\?(?:[a-zA-Z0-9\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF\uE000-\uF8FF!$&'()*+,;=:@\/?]|%[0-9a-fA-F]{2})*)?(?:#(?:[a-zA-Z0-9\-._~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF!$&'()*+,;=:@\/?]|%[0-9a-fA-F]{2})*)?)/
119   var ignore = {'A': true, 'HEAD': true, 'META': true, 'SCRIPT': true, 'STYLE': true, 'TITLE': true}
120   var srcURL = Components.classes['@mozilla.org/network/standard-url;1'].getService(Components.interfaces.nsIURI)
121   var dstURL = srcURL.clone()
122   getBrowser().addEventListener('DOMContentLoaded', metaHandler, false)
123 })()