Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make original text smilies selectable (closes #2)
* Make smilies a background image of an <abbrev> element with transparent text. This leaves the original text in place, so copying and pasting will keep the original text smiley * Updated tests. Now they're probably a bit more fragile than they were, but it shouldn't be too bad.
- Loading branch information
Showing
5 changed files
with
314 additions
and
246 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -1,33 +1,46 @@ | |||
var SmileyParser = function(smileyTable) { this.init(smileyTable); }; | var SmileyParser = function(smileyTable) { this.init(smileyTable); }; | ||
(function () | (function () | ||
{ | { | ||
this._smileyTable = {}; | this._smileyTable = {}; | ||
this.init = function(smileyTable) { | this.init = function(smileyTable) { | ||
this._smileyTable = smileyTable || defaultSmileyTable; | /* Returns a function that receives the matched text and the | ||
this._handlers = []; | first matched group in the regular expression. The first group | ||
for (var smiley in this._smileyTable) { | is always a fake lookbehind. If there's anything, we should | ||
if (this._smileyTable.hasOwnProperty(smiley)) { | return the text back, without creating any graphical smiley */ | ||
var self = this; | function replaceFunction(s) { | ||
this._handlers.push({pattern: new RegExp('(["a-zA-Z0-9#])?' + smiley, "g"), | return function(text, lb) { | ||
replacement: (function (s) { | if (lb) return document.createTextNode(text); | ||
return function(text, lb) { | var smileyInfo = self._smileyTable[s]; | ||
if (lb) return document.createTextNode(text); | var smileyDom = document.createElement('abbrev'); | ||
var img = | smileyDom.innerHTML = text.replace(/&/g, '&'). | ||
document.createElement('img'); | replace(/</g, '<'). | ||
img.src = self._smileyTable[s]; | replace(/>/g, '>'); | ||
img.alt = img.title = | var url = "data:image/png;base64," + smileyInfo.imageDataBase64; | ||
text.replace(/&/g, '&'). | smileyDom.style.backgroundImage = "url(" + url + ")"; | ||
replace(/</g, '<'). | if (smileyInfo.height !== undefined) | ||
replace(/>/g, '>'); | smileyDom.style.height = smileyInfo.height + "px"; | ||
return img; | if (smileyInfo.width !== undefined) | ||
}; | smileyDom.style.width = smileyInfo.width + "px"; | ||
})(smiley)}); | smileyDom.style.display = 'inline-block'; | ||
} | smileyDom.style.color = 'transparent'; | ||
} | smileyDom.style.overflow = 'hidden'; | ||
}; | return smileyDom; | ||
}; | |||
} | |||
this._smileyTable = smileyTable || defaultSmileyTable; | |||
this._handlers = []; | |||
for (var smiley in this._smileyTable) { | |||
if (this._smileyTable.hasOwnProperty(smiley)) { | |||
var self = this; | |||
this._handlers.push({pattern: new RegExp('(["a-zA-Z0-9#])?' + | |||
smiley, "g"), | |||
replacement: replaceFunction(smiley)}); | |||
} | |||
} | |||
}; | |||
|
|
||
this.parseSmileys = function(element) { | this.parseSmileys = function(element) { | ||
replaceTextWithElements(element, {excludedTags: /textarea/, | replaceTextWithElements(element, {excludedTags: /textarea/, | ||
handlers: this._handlers}); | handlers: this._handlers}); | ||
}; | }; | ||
}).call(SmileyParser.prototype); | }).call(SmileyParser.prototype); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -1,41 +1,68 @@ | |||
function isHtmlEquivalent(one, two) { | |||
var domElement = document.createElement('div'); | |||
var domElement2 = document.createElement('div'); | |||
domElement.innerHTML = one; | |||
domElement2.innerHTML = two; | |||
return canonicalHtml(domElement) === canonicalHtml(domElement2); | |||
} | |||
|
|||
describe("canonicalHtml", function() { | describe("canonicalHtml", function() { | ||
var domElement; | beforeEach(function() { | ||
this.addMatchers({ | |||
toBeCanonically: function(expected) { | |||
return isHtmlEquivalent(this.actual, expected); | |||
}, | |||
toNotBeCanonically: function(expected) { | |||
return ! isHtmlEquivalent(this.actual, expected); | |||
} | |||
}); | |||
}); | |||
|
|
||
beforeEach(function() { | it("should return the same string when there isn't any markup", function() { | ||
domElement = document.createElement('div'); | var someString = "Some string without any markup"; | ||
expect(someString).toBeCanonically(someString); | |||
}); | |||
|
|
||
this.addMatchers({ | it("should return the same string when there are simple elements", function() { | ||
toBeCanonically: function(expected) { | var someString = "Some string with <strong>some</strong> markup"; | ||
domElement.innerHTML = this.actual; | expect(someString).toBeCanonically(someString); | ||
return this.env.equals_(canonicalHtml(domElement), expected); | }); | ||
} | |||
}); | |||
}); | |||
|
|
||
it("should return the same string when there isn't any markup", function() { | it("should return attributes in alphabetical order", function() { | ||
var someString = "Some string without any markup"; | var source = 'Some <a title="foo" href="http://example.com">link</a>'; | ||
expect(someString).toBeCanonically(someString); | var expected = 'Some <a href="http://example.com" title="foo">link</a>'; | ||
}); | expect(source).toBeCanonically(expected); | ||
}); | |||
|
|
||
it("should return the same string when there are simple elements", function() { | it("should return self-closing tags correctly", function() { | ||
var someString = "Some string with <strong>some</strong> markup"; | var source = 'An <img src="image.png">'; | ||
expect(someString).toBeCanonically(someString); | var expected = 'An <img src="image.png" />'; | ||
}); | expect(source).toBeCanonically(expected); | ||
}); | |||
|
|
||
it("should return attributes in alphabetical order", function() { | it("should return HTML entities correctly", function() { | ||
var source = 'Some <a title="foo" href="http://example.com">link</a>'; | var source = 'A Smith & Wesson weapon'; | ||
var expected = 'Some <a href="http://example.com" title="foo">link</a>'; | expect(source).toBeCanonically(source); | ||
expect(source).toBeCanonically(expected); | }); | ||
}); | |||
|
|
||
it("should return self-closing tags correctly", function() { | it("should recognise a simple smiley correctly", function() { | ||
var source = 'An <img src="image.png">'; | var source1 = 'A smiley: <abbrev style="background-image: url(foo.png); width: 30px; height: 25px">some text</abbrev>'; | ||
var expected = 'An <img src="image.png" />'; | var source2 = 'A smiley: <abbrev style="background-image: url(foo.png); height: 25px; width: 30px">some text</abbrev>'; | ||
expect(source).toBeCanonically(expected); | var source3 = 'A smiley: <abbrev style="background-image: url(foo.png); height: 25px; width: 30px">some other text</abbrev>'; | ||
}); | expect(source1).toBeCanonically(source2); | ||
expect(source1).toNotBeCanonically(source3); | |||
expect(source2).toNotBeCanonically(source3); | |||
}); | |||
|
|
||
it("should return HTML entities correctly", function() { | it("should recognise a smiley w/ extra properties as different", function() { | ||
var source = 'A Smith & Wesson weapon'; | var source1 = 'A smiley: <abbrev style="background-image: url(foo.png); width: 30px">some text</abbrev>'; | ||
expect(source).toBeCanonically(source); | var source2 = 'A smiley: <abbrev style="background-image: url(foo.png); width: 30px; height: 25px">some text</abbrev>'; | ||
}); | expect(source1).toNotBeCanonically(source2); | ||
}); | |||
|
|||
it("should recognise a smiley w/ angle brackets", function() { | |||
var source1 = 'A smiley: <abbrev style="background-image: url(foo.png); height: 25px; width: 30px"></troll></abbrev>'; | |||
var source2 = 'A smiley: <abbrev style="background-image: url(foo.png); width: 30px; height: 25px"></troll></abbrev>'; | |||
expect(source1).toBeCanonically(source2); | |||
}); | |||
}); | }); |
Oops, something went wrong.