Skip to content

Instantly share code, notes, and snippets.

@lexmihaylov
Created April 7, 2016 11:48
Show Gist options
  • Save lexmihaylov/cfe23bb074fd650cea52533af768f123 to your computer and use it in GitHub Desktop.
Save lexmihaylov/cfe23bb074fd650cea52533af768f123 to your computer and use it in GitHub Desktop.
Word processor for selection highlighter meant to be used with GoogleChrome's speechSynthesis engine.
(function() {
'use strict';
/**
* List of all punctuation marks that are allowed in the sanitized text
* Note: this can be extended in the future
* @type {String}
* @const
*/
var AllowedPunctuatio = ":!\\?\\.,'`<>\\+\\-=/\\\\";
/**
* a list of punctuation marks that should be highligted seperately if
* there is no sentence event
* @type {String}
* @const
*/
var ReadablePunctuation = ":!\\?\\.,<>\\+\\-=/\\\\";
AllowedPunctuatio = ":!\\?\\.,'`<>\\+\\-=/\\\\";
ReadablePunctuation = "<>=/\\\\";
/**
* regexp to strip unreadable symbols
* @type {RegExp}
* @const
*/
var SymbolStrip = new RegExp('[^'+AllowedPunctuatio+'\\w]', 'gi');
/**
* regexp for finding begin index
* @type {RegExp}
* @const
*/
var BeginIndexRegEx = new RegExp('[\\w'+ReadablePunctuation+']', 'gi');
/**
* regexp for finding end index
* @type {RegExp}
* @const
*/
var EndIndexRegEx = new RegExp('[\\s'+ReadablePunctuation+']', 'gi');
function sanitize(text) {
text = text.replace(/\u2013/g, '-');
text = text.replace(/\u2014/g, '-');
text = text.replace(/\u2019/g, '\'');
text = text.replace(/\u2018/g, '\'');
text = text.replace(/\n/g, ' ');
text = text.replace(/\r/g, ' ');
text = text.replace(/\t/g, ' ');
// strip unreadable symbols
text = text.replace(SymbolStrip, function(match, position) {
return Array(match.length + 1).join(' ');
}.bind(this));
return text;
}
function getTextNodesIn(elem) {
var textNodes = [];
if (elem) {
for (var nodes = elem.childNodes, i = 0; i < nodes.length; i++) {
var node = nodes[i], nodeType = node.nodeType;
if (nodeType == 3) {
textNodes.push(node);
} else if (nodeType == 1 || nodeType == 9 || nodeType == 11) {
textNodes = textNodes.concat(getTextNodesIn(node));
}
}
}
return textNodes;
}
function processItem(node, selections) {
var index = 0;
var str = sanitize(node.data);
var start;
var end;
var endReached = false;
if($(node).closest('.mjx-chtml').length > 0) {
return;
}
if($(node).closest('script').length > 0) {
return;
}
while(true) {
start = str.slice(index).search(BeginIndexRegEx);
if(start == -1) {
break;
}
start += index;
if((new RegExp('['+ReadablePunctuation+']', 'gi')).test(str[start])) {
end = start + 1;
} else {
end = str.slice(start).search(EndIndexRegEx);
if(end == -1) {
end = str.length;
endReached = true;
} else {
end += start;
}
}
var range = document.createRange();
range.setStart(node, start);
range.setEnd(node, end);
selections.push({
node: node,
range: range
});
if(endReached) {
break;
}
index = end;
}
}
function process(textNodes) {
var selections = [];
var item;
for(var i = 0; i < textNodes.length; i++) {
item = textNodes[i];
processItem(item, selections);
}
return selections;
}
var nodes = getTextNodesIn($('.text').get(0));
var selections = process(nodes);
for(var i = 0; i < selections.length; i++) {
(function(item, i) {
setTimeout(function() {
document.getSelection().removeAllRanges();
var range = item.range;
document.getSelection().addRange(range);
}, i*500)
}(selections[i], i))
}
}());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment