mirror of
https://github.com/paradoxxxzero/butterfly.git
synced 2026-05-31 17:39:41 +00:00
Linkify as an extension. Finally fix #97
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
(function() {
|
||||
var Popup, Selection, _set_theme_href, _theme, alt, cancel, clean_ansi, copy, ctrl, first, nextLeaf, popup, previousLeaf, selection, setAlarm, virtualInput,
|
||||
var Popup, Selection, _set_theme_href, _theme, alt, cancel, clean_ansi, copy, ctrl, first, linkify, nextLeaf, popup, previousLeaf, selection, setAlarm, virtualInput, walk,
|
||||
indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
|
||||
|
||||
clean_ansi = function(data) {
|
||||
@@ -156,6 +156,47 @@
|
||||
}
|
||||
});
|
||||
|
||||
walk = function(node, callback) {
|
||||
var child, j, len1, ref, results;
|
||||
ref = node.childNodes;
|
||||
results = [];
|
||||
for (j = 0, len1 = ref.length; j < len1; j++) {
|
||||
child = ref[j];
|
||||
callback.call(child);
|
||||
results.push(walk(child, callback));
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
linkify = function(text) {
|
||||
var emailAddressPattern, pseudoUrlPattern, urlPattern;
|
||||
urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;
|
||||
pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
|
||||
emailAddressPattern = /[\w.]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim;
|
||||
return text.replace(urlPattern, '<a href="$&">$&</a>').replace(pseudoUrlPattern, '$1<a href="http://$2">$2</a>').replace(emailAddressPattern, '<a href="mailto:$&">$&</a>');
|
||||
};
|
||||
|
||||
Terminal.on('change', function(lines) {
|
||||
var j, len1, line, results;
|
||||
results = [];
|
||||
for (j = 0, len1 = lines.length; j < len1; j++) {
|
||||
line = lines[j];
|
||||
results.push(walk(line, function() {
|
||||
var linkified, newNode;
|
||||
if (this.nodeType === 3) {
|
||||
linkified = linkify(this.nodeValue);
|
||||
if (linkified !== this.nodeValue) {
|
||||
newNode = document.createElement('span');
|
||||
newNode.innerHTML = linkified;
|
||||
this.parentElement.replaceChild(newNode, this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
return results;
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (!(e.altKey && e.keyCode === 79)) {
|
||||
return true;
|
||||
|
||||
4
butterfly/static/ext.min.js
vendored
4
butterfly/static/ext.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -145,6 +145,22 @@
|
||||
};
|
||||
|
||||
Terminal = (function() {
|
||||
Terminal.hooks = {};
|
||||
|
||||
Terminal.on = function(hook, fun) {
|
||||
if (Terminal.hooks[hook] == null) {
|
||||
Terminal.hooks[hook] = [];
|
||||
}
|
||||
return Terminal.hooks[hook].push(fun);
|
||||
};
|
||||
|
||||
Terminal.off = function(hook, fun) {
|
||||
if (Terminal.hooks[hook] == null) {
|
||||
Terminal.hooks[hook] = [];
|
||||
}
|
||||
return Terminal.hooks[hook].pop(fun);
|
||||
};
|
||||
|
||||
function Terminal(parent, out1, ctl1) {
|
||||
var div, px;
|
||||
this.parent = parent;
|
||||
@@ -201,8 +217,24 @@
|
||||
return _this.resize();
|
||||
};
|
||||
})(this));
|
||||
this.emit('load');
|
||||
}
|
||||
|
||||
Terminal.prototype.emit = function() {
|
||||
var args, fun, hook, k, len, ref, results;
|
||||
hook = arguments[0], args = 2 <= arguments.length ? slice.call(arguments, 1) : [];
|
||||
if (Terminal.hooks[hook] == null) {
|
||||
Terminal.hooks[hook] = [];
|
||||
}
|
||||
ref = Terminal.hooks[hook];
|
||||
results = [];
|
||||
for (k = 0, len = ref.length; k < len; k++) {
|
||||
fun = ref[k];
|
||||
results.push(fun.apply(this, args));
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
Terminal.prototype.cloneAttr = function(a, char) {
|
||||
if (char == null) {
|
||||
char = null;
|
||||
@@ -502,25 +534,8 @@
|
||||
})(this));
|
||||
};
|
||||
|
||||
Terminal.prototype.linkify = function(t) {
|
||||
var emailAddressPattern, part, pseudoUrlPattern, urlPattern;
|
||||
urlPattern = /\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim;
|
||||
pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim;
|
||||
emailAddressPattern = /[\w.]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim;
|
||||
return ((function() {
|
||||
var k, len, ref, results;
|
||||
ref = t.split(' ');
|
||||
results = [];
|
||||
for (k = 0, len = ref.length; k < len; k++) {
|
||||
part = ref[k];
|
||||
results.push(part.replace(urlPattern, '<a href="$&">$&</a>').replace(pseudoUrlPattern, '$1<a href="http://$2">$2</a>').replace(emailAddressPattern, '<a href="mailto:$&">$&</a>'));
|
||||
}
|
||||
return results;
|
||||
})()).join(' ');
|
||||
};
|
||||
|
||||
Terminal.prototype.refresh = function(force) {
|
||||
var active, attr, ch, classes, cursor, data, fg, group, i, j, k, len, len1, len2, len3, len4, line, lines, m, newOut, o, out, q, ref, ref1, ref2, ref3, ref4, ref5, skipnext, styles, u, v, x;
|
||||
var active, attr, ch, classes, cursor, data, fg, group, i, j, k, len, len1, len2, len3, len4, line, lines, m, modified, newOut, o, out, q, ref, ref1, ref2, ref3, ref4, ref5, skipnext, styles, u, v, x;
|
||||
if (force == null) {
|
||||
force = false;
|
||||
}
|
||||
@@ -535,6 +550,7 @@
|
||||
active.classList.remove('active');
|
||||
}
|
||||
newOut = '';
|
||||
modified = [];
|
||||
ref2 = this.screen;
|
||||
for (j = o = 0, len2 = ref2.length; o < len2; j = ++o) {
|
||||
line = ref2[j];
|
||||
@@ -659,14 +675,12 @@
|
||||
if (!this.equalAttr(attr, this.defAttr)) {
|
||||
out += "</span>";
|
||||
}
|
||||
if (!(j === this.y + this.shift || data.html)) {
|
||||
out = this.linkify(out);
|
||||
}
|
||||
if (line.wrap) {
|
||||
out += '\u23CE';
|
||||
}
|
||||
if (this.children[j]) {
|
||||
this.children[j].innerHTML = out;
|
||||
modified.push(this.children[j]);
|
||||
if (x !== -Infinity) {
|
||||
this.children[j].classList.add('active');
|
||||
}
|
||||
@@ -679,6 +693,7 @@
|
||||
group = this.document.createElement('div');
|
||||
group.className = 'group';
|
||||
group.innerHTML = newOut;
|
||||
modified.push(group);
|
||||
this.body.appendChild(group);
|
||||
this.screen = this.screen.slice(-this.rows);
|
||||
this.shift = 0;
|
||||
@@ -698,7 +713,8 @@
|
||||
}
|
||||
this.children = Array.prototype.slice.call(lines, -this.rows);
|
||||
}
|
||||
return this.nativeScrollTo();
|
||||
this.nativeScrollTo();
|
||||
return this.emit('change', modified);
|
||||
};
|
||||
|
||||
Terminal.prototype._cursorBlink = function() {
|
||||
|
||||
4
butterfly/static/main.min.js
vendored
4
butterfly/static/main.min.js
vendored
File diff suppressed because one or more lines are too long
26
coffees/ext/linkify.coffee
Normal file
26
coffees/ext/linkify.coffee
Normal file
@@ -0,0 +1,26 @@
|
||||
walk = (node, callback) ->
|
||||
for child in node.childNodes
|
||||
callback.call(child)
|
||||
walk child, callback
|
||||
|
||||
linkify = (text) ->
|
||||
# http://stackoverflow.com/questions/37684/how-to-replace-plain-urls-with-links
|
||||
urlPattern = (
|
||||
/\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim)
|
||||
pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim
|
||||
emailAddressPattern = /[\w.]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim
|
||||
text
|
||||
.replace(urlPattern, '<a href="$&">$&</a>')
|
||||
.replace(pseudoUrlPattern, '$1<a href="http://$2">$2</a>')
|
||||
.replace(emailAddressPattern, '<a href="mailto:$&">$&</a>')
|
||||
|
||||
Terminal.on 'change', (lines) ->
|
||||
for line in lines
|
||||
walk line, ->
|
||||
if @nodeType is 3
|
||||
linkified = linkify @nodeValue
|
||||
if linkified isnt @nodeValue
|
||||
newNode = document.createElement('span')
|
||||
newNode.innerHTML = linkified
|
||||
@parentElement.replaceChild newNode, @
|
||||
true
|
||||
@@ -28,7 +28,6 @@
|
||||
# http://bellard.org/jslinux/
|
||||
|
||||
|
||||
|
||||
cancel = (ev) ->
|
||||
ev.preventDefault() if ev.preventDefault
|
||||
ev.stopPropagation() if ev.stopPropagation
|
||||
@@ -45,7 +44,20 @@ State =
|
||||
dcs: s++
|
||||
ignore: s++
|
||||
|
||||
|
||||
class Terminal
|
||||
@hooks: {}
|
||||
# Mini implementation of event
|
||||
@on: (hook, fun) ->
|
||||
unless Terminal.hooks[hook]?
|
||||
Terminal.hooks[hook] = []
|
||||
Terminal.hooks[hook].push(fun)
|
||||
|
||||
@off: (hook, fun) ->
|
||||
unless Terminal.hooks[hook]?
|
||||
Terminal.hooks[hook] = []
|
||||
Terminal.hooks[hook].pop(fun)
|
||||
|
||||
constructor: (@parent, @out, @ctl=->) ->
|
||||
# Global elements
|
||||
@document = @parent.ownerDocument
|
||||
@@ -102,6 +114,13 @@ class Terminal
|
||||
|
||||
@initmouse()
|
||||
addEventListener 'load', => @resize()
|
||||
@emit 'load'
|
||||
|
||||
emit: (hook, args...) ->
|
||||
unless Terminal.hooks[hook]?
|
||||
Terminal.hooks[hook] = []
|
||||
for fun in Terminal.hooks[hook]
|
||||
fun.apply(@, args)
|
||||
|
||||
cloneAttr: (a, char=null) ->
|
||||
bg: a.bg
|
||||
@@ -396,18 +415,6 @@ class Terminal
|
||||
sendButton ev
|
||||
cancel ev
|
||||
|
||||
linkify: (t) ->
|
||||
# http://stackoverflow.com/questions/37684/how-to-replace-plain-urls-with-links
|
||||
urlPattern = (
|
||||
/\b(?:https?|ftp):\/\/[a-z0-9-+&@#\/%?=~_|!:,.;]*[a-z0-9-+&@#\/%=~_|]/gim)
|
||||
pseudoUrlPattern = /(^|[^\/])(www\.[\S]+(\b|$))/gim
|
||||
emailAddressPattern = /[\w.]+@[a-zA-Z_-]+?(?:\.[a-zA-Z]{2,6})+/gim
|
||||
(part
|
||||
.replace(urlPattern, '<a href="$&">$&</a>')
|
||||
.replace(pseudoUrlPattern, '$1<a href="http://$2">$2</a>')
|
||||
.replace(emailAddressPattern, '<a href="mailto:$&">$&</a>'
|
||||
) for part in t.split(' ')).join(' ')
|
||||
|
||||
refresh: (force=false) ->
|
||||
for cursor in @body.querySelectorAll(".cursor")
|
||||
cursor.parentNode.replaceChild(
|
||||
@@ -416,7 +423,7 @@ class Terminal
|
||||
active.classList.remove('active')
|
||||
|
||||
newOut = ''
|
||||
|
||||
modified = []
|
||||
for line, j in @screen
|
||||
continue unless line.dirty or force
|
||||
out = ""
|
||||
@@ -518,10 +525,10 @@ class Terminal
|
||||
out += "</span>" if i is x
|
||||
attr = data
|
||||
out += "</span>" unless @equalAttr attr, @defAttr
|
||||
out = @linkify(out) unless j is @y + @shift or data.html
|
||||
out += '\u23CE' if line.wrap
|
||||
if @children[j]
|
||||
@children[j].innerHTML = out
|
||||
modified.push @children[j]
|
||||
if x isnt -Infinity
|
||||
@children[j].classList.add 'active'
|
||||
else
|
||||
@@ -533,6 +540,7 @@ class Terminal
|
||||
group = @document.createElement('div')
|
||||
group.className = 'group'
|
||||
group.innerHTML = newOut
|
||||
modified.push group
|
||||
@body.appendChild group
|
||||
@screen = @screen.slice(-@rows)
|
||||
@shift = 0
|
||||
@@ -549,6 +557,7 @@ class Terminal
|
||||
lines, -@rows)
|
||||
|
||||
@nativeScrollTo()
|
||||
@emit 'change', modified
|
||||
|
||||
_cursorBlink: ->
|
||||
@cursorState ^= 1
|
||||
|
||||
Reference in New Issue
Block a user