Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #139 - Convert ENS Address To Link functionality #140

Merged
merged 7 commits into from
Oct 30, 2017
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.idea/
*.iml
5 changes: 5 additions & 0 deletions css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@
color: inherit;
}

.ext-etheraddresslookup-warning {
color: red;
border-bottom: 1px dashed red;
}

#ext-etheraddresslookup-popup {
margin: 0;
padding: 0px;
Expand Down
211 changes: 185 additions & 26 deletions js/DomManipulator.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,17 @@ class EtherAddressLookup {
this.intSettingsTotalCount = 2;
}

//Gets extension settings and then converts addresses to links
/**
* @name init
* @desc Gets extension settings and applies DOM manipulation
*/
init()
{
let objBrowser = chrome ? chrome : browser;
//Get the highlight option for the user
objBrowser.runtime.sendMessage({func: "highlight_option"}, function(objResponse) {
if(objResponse && objResponse.hasOwnProperty("resp")) {
this.blHighlight = (objResponse.resp == 1 ? true : false);
this.blHighlight = (objResponse.resp == 1);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed this because it is basically the thing:

(objResponse.resp == 1 ? true : false) == (objResponse.resp == 1)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, nice spot! 👍

}
++this.intSettingsCount;
}.bind(this));
Expand All @@ -38,49 +41,205 @@ class EtherAddressLookup {

//Update the DOM once all settings have been received...
setTimeout(function() {
if(true || this.intSettingsCount === this.intSettingsTotalCount) {
if(this.blBlacklistDomains) {
this.blacklistedDomainCheck();
}
this.convertAddressToLink();
// Needs to happen after user settings have been collected
// and in the context of init();
this.setSearchAndReplaceSettings();
this.setWarningSettings();
this.manipulateDOM();
}.bind(this), 10);
}

/**
* @name Set Search And Replace Settings
* @desc
*/
setSearchAndReplaceSettings()
{
// Check user is on their favourite block explorer, on fail target blank.
this.target = (this.isBlockchainExplorerSite() ? '_self' : '_blank');

// Register RegEx Patterns
this.regExPatterns = [
// Ethereum Address Regex
/(^|\s|:|-)((?:0x)[0-9a-fA-F]{40})(\s|$)/gi,

// ENS Address Regex
/([a-z0-9][a-z0-9-\.]+[a-z0-9](?:\.eth))(\s|$)/gi
];

// Register RegEx Matching Patterns
this.matchPatterns = [
// Ethereum Match Pattern
/((?:0x)[0-9a-fA-F]{40})/gi,

// ENS Match Pattern
this.regExPatterns[1]
];

// Register Replace Patterns
this.replacePatterns = [
// Ethereum Address Replace
'$1<a title="See this address on the blockchain explorer" ' +
'href="' + this.strBlockchainExplorer + '/$2" ' +
'class="ext-etheraddresslookup-link" ' +
'target="'+ this.target +'">$2</a>$3',

// ENS Address Replace
'<a title="See this address on the blockchain explorer" ' +
'href="' + this.strBlockchainExplorer + '/$1" ' +
'class="ext-etheraddresslookup-link" ' +
'target="'+ this.target +'">$1</a>$2'
];
}

/**
* @name Set Warning Settings
* @desc
*/
setWarningSettings()
{
// The block explorers that can handle ENS addresses
this.ENSCompatiableExplorers = [
"https://etherscan.io/address",
"https://etherchain.org/account"
];

// Does the user's favorite explorer support an ENS address
for(var i=0; i<this.ENSCompatiableExplorers.length; i++){
if(this.strBlockchainExplorer == this.ENSCompatiableExplorers[i]){
this.ENSCompatiable = true;
break;
}
}.bind(this), 10)
this.ENSCompatiable = false;
}

// On failure give the user a warning.
if(!this.ENSCompatiable){
this.replacePatterns[1] = '<a title="Notification! We have spotted an ENS address, your current block explorer can\'t parse this address. Please choose a compatible block explorer." ' +
'class="ext-etheraddresslookup-link ext-etheraddresslookup-warning" href="#">$1</a>';
}
}

//Finds Ethereum addresses and converts to a link to a block explorer
convertAddressToLink()
manipulateDOM()
{
//Put the blockchain explorer into a so we can parse it.
var objBlockchainExplorer = document.createElement("a");
objBlockchainExplorer.href = this.strBlockchainExplorer;
if(true || this.intSettingsCount === this.intSettingsTotalCount) {
if(this.blBlacklistDomains) {
this.blacklistedDomainCheck();
}
this.convertAddressToLink();
}
}

var arrWhitelistedTags = new Array("code", "span", "p", "td", "li", "em", "i", "b", "strong", "small");
var strRegex = /(^|\s|:|-)((?:0x)[0-9a-fA-F]{40})(?:\s|$)/gi;
/**
* @name Convert Address To Link
* @desc Finds Ethereum addresses and converts to a link to a block explorer
*/
convertAddressToLink()
{
var arrWhitelistedTags = ["code", "span", "p", "td", "li", "em", "i", "b", "strong", "small"];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've also refactored the array instantiation, let me know if this is a problem.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's all good :)


//Get the whitelisted nodes
for(var i=0; i<arrWhitelistedTags.length; i++) {
var objNodes = document.getElementsByTagName(arrWhitelistedTags[i]);
//Loop through the whitelisted content
for(var x=0; x<objNodes.length; x++) {
var strContent = objNodes[x].innerHTML;
if( /((?:0x)[0-9a-fA-F]{40})/gi.exec(strContent) !== null) {
//If we are on our favourite blockchain explorer, don't target blank.
objNodes[x].innerHTML = strContent.replace(
new RegExp(strRegex, "gi"),
'$1<a title="See this address on the blockchain explorer" ' +
'href="' + this.strBlockchainExplorer + '/$2" ' +
'class="ext-etheraddresslookup-link" ' +
'target="'+ (objBlockchainExplorer.hostname === window.location.hostname ? '_self' : '_blank') +'">$2</a>'
);
}
this.convertAddresses(objNodes[x]);
}
}

this.tidyUpSlots();

if(this.blHighlight) {
this.addHighlightStyle();
}
}

/**
* @name Convert Addresses
* @desc Takes a Node and checks if any of its children are textNodes. On success replace textNode with slot node
* @desc slot node contains regex replaced content; see generateReplacementContent()
* @param {Node} objNode
*/
convertAddresses(objNode)
{
// Some nodes have non-textNode children
// we need to ensure regex is applied only to text otherwise we will mess the html up
for(var i=0; i < objNode.childNodes.length; i++){
// Only check textNodes to prevent applying RegEx against element attributes
if(objNode.childNodes[i].nodeType == 3){ // nodeType 3 = a text node

var child = objNode.childNodes[i];
var childContent = child.textContent;

// Only start replacing stuff if the we get a RegEx match.
if(this.isPatternMatched(childContent)) {
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/slot
var replacement = document.createElement('slot');
replacement.setAttribute('class', 'ext-etheraddresslookup-temporary');
replacement.innerHTML = this.generateReplacementContent(childContent);
objNode.replaceChild(replacement, child);
}
}
}
}

/**
* @name Generate Replacement Content
* @desc Takes string and replaces any regex pattern matches with the associated replace patterns
* @param {string} content
* @returns {string}
*/
generateReplacementContent(content)
{
for(var i=0; i < this.regExPatterns.length; i++){
content = content.replace(this.regExPatterns[i], this.replacePatterns[i]);
}
return content;
}

/**
* @name Is Pattern Matched
* @desc Checks content matches any of the object's matchPatterns
* @param {string} content
* @returns {boolean}
*/
isPatternMatched(content)
{
for(var i=0; i < this.matchPatterns.length; i++){
if(this.matchPatterns[i].exec(content) !== null){
return true;
}
}
return false;
}

/**
* @name Is Blockchain Explorer Site
* @desc Check if the current website is the user's selected block explorer
* @returns {boolean}
*/
isBlockchainExplorerSite()
{
var objBlockchainExplorer = document.createElement("a");
objBlockchainExplorer.href = this.strBlockchainExplorer;
return (objBlockchainExplorer.hostname === window.location.hostname);
}

/**
* @name Tidy Slots
* @desc Searches document for slots adds the slot's child nodes to its parent then removes the slot
*/
tidyUpSlots()
{
var slots = document.querySelectorAll("slot.ext-etheraddresslookup-temporary");
for(var i=0; i < slots.length; i++){
while(slots[i].childNodes.length > 0){
slots[i].parentNode.appendChild(slots[i].firstChild);
}
slots[i].parentNode.removeChild(slots[i]);
}
}

//Removes the highlight style from Ethereum addresses
removeHighlightStyle()
{
Expand Down
7 changes: 5 additions & 2 deletions options.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,14 @@ <h3 class="text-center">EtherAddressLookup</h3>
<label>Preferred Blockchain Explorer</label>
<select class="form-control" name="ext-etheraddresslookup-choose_blockchain"
id="ext-etheraddresslookup-choose_blockchain">
<option value="https://etherscan.io/address">Etherscan.io</option>
<option value="https://etherchain.org/account">Etherchain.org</option>
<option value="https://etherscan.io/address">Etherscan.io *</option>
<option value="https://etherchain.org/account">Etherchain.org *</option>
<option value="https://ethplorer.io/address">Ethplorer.io</option>
<option value="http://ethergraphs.com/dashboard">Ethergraphs.com</option>
</select>
<div>
<p>* ENS address compatible.</p>
</div>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made this amendment to allow the user to know which explorers will allow them the ability view ENS addresses. We can in future add new functionality to lookup the underlying Ethereum address then link to this on the user's chosen explorer.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Copy link
Owner

@409H 409H Oct 30, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make this text smaller please?
Just a small UI change, put it in <small></small> tags. (I have selective OCD 😕)

Or do you have an idea on how to present notes/not-main-labels on the UI?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make this smaller for now, we can discuss ideas later, though UI isn't really my strong suit.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Once v1.9 is up, we can arrange a more in-depth discussion on it for later this week when both our schedules are free.


<br/><br/>
<div id="footer">
Expand Down