iated 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +3 -0
- data/Guardfile +24 -0
- data/LICENSE +23 -0
- data/Makefile +72 -0
- data/README.md +87 -0
- data/Rakefile +10 -0
- data/bin/iated +13 -0
- data/config.ru +5 -0
- data/extensions/chrome/background.html +5 -0
- data/extensions/chrome/background.js +105 -0
- data/extensions/chrome/contentscript.css +0 -0
- data/extensions/chrome/contentscript.js +110 -0
- data/extensions/chrome/jquery-ui.js +45 -0
- data/extensions/chrome/jquery.js +16 -0
- data/extensions/chrome/jquery.updater.js +46 -0
- data/extensions/chrome/manifest.json +19 -0
- data/extensions/chrome/yaml.js +489 -0
- data/extensions/tests/simple.html +23 -0
- data/features/extension_authenticates.feature +30 -0
- data/features/extension_edits.feature +45 -0
- data/features/step_definitions/extension_steps.rb +134 -0
- data/features/support/env.rb +47 -0
- data/features/support/hooks.rb +11 -0
- data/iated.gemspec +48 -0
- data/lib/iated.rb +111 -0
- data/lib/iated/browser_token_db.rb +76 -0
- data/lib/iated/edit_session.rb +221 -0
- data/lib/iated/helpers.rb +9 -0
- data/lib/iated/mcp.rb +144 -0
- data/lib/iated/page_helpers.rb +33 -0
- data/lib/iated/public/jquery-ui.js +101 -0
- data/lib/iated/public/jquery.js +2 -0
- data/lib/iated/public/robots.txt +5 -0
- data/lib/iated/server.rb +162 -0
- data/lib/iated/sys_pref.rb +201 -0
- data/lib/iated/version.rb +3 -0
- data/lib/iated/views/hello.haml +13 -0
- data/lib/iated/views/preferences.haml +27 -0
- data/lib/iated/views/reference.coffee +79 -0
- data/lib/iated/views/reference.haml +94 -0
- data/lib/iated/views/reference.scss +36 -0
- data/lib/iated/views/root.haml +13 -0
- data/spec/lib/iated/browser_token_db_spec.rb +68 -0
- data/spec/lib/iated/edit_session_spec.rb +157 -0
- data/spec/lib/iated/mcp_spec.rb +86 -0
- data/spec/lib/iated/sys_pref_spec.rb +40 -0
- data/spec/protocol/edit_spec.rb +88 -0
- data/spec/protocol/hello_spec.rb +18 -0
- data/spec/protocol/notfound_spec.rb +11 -0
- data/spec/protocol/ping_spec.rb +10 -0
- data/spec/protocol/preferences_spec.rb +35 -0
- data/spec/spec_helper.rb +21 -0
- metadata +460 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# More info at https://github.com/guard/guard#readme
|
3
|
+
|
4
|
+
#guard 'spork' do
|
5
|
+
# #watch('config/application.rb')
|
6
|
+
# #watch('config/environment.rb')
|
7
|
+
# #watch(%r{^config/environments/.+\.rb$})
|
8
|
+
# #watch(%r{^config/initializers/.+\.rb$})
|
9
|
+
# watch('spec/spec_helper.rb')
|
10
|
+
#end
|
11
|
+
|
12
|
+
guard 'rspec', :version => 2 do
|
13
|
+
watch(%r{^spec/.+_spec\.rb$})
|
14
|
+
watch(%r{^src/lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
15
|
+
watch('spec/spec_helper.rb') { "spec/" }
|
16
|
+
watch('src/lib/iated.rb') { "spec/" }
|
17
|
+
end
|
18
|
+
|
19
|
+
guard 'cucumber' do
|
20
|
+
watch(%r{^features/.+\.feature$})
|
21
|
+
watch(%r{^features/support/.+$}) { 'features' }
|
22
|
+
watch(%r{^features/step_definitions/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'features' }
|
23
|
+
#watch(%r{^src/lib/.+$}) { 'features' }
|
24
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
The MIT License
|
2
|
+
http://www.opensource.org/licenses/mit-license.php
|
3
|
+
|
4
|
+
Copyright (c) 2011 Christian Höltje (http://docwhat.org/)
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Makefile
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
### Makefile --- Build the doctor jar and exe.
|
2
|
+
|
3
|
+
SOURCE:=$(shell find src -type f)
|
4
|
+
BUILD_SOURCE:=$(patsubst src/%, build/%, $(SOURCE))
|
5
|
+
TEST_SOURCE := $(shell find spec -type f -iname '*.rb')
|
6
|
+
|
7
|
+
# Downloadables
|
8
|
+
LAUNCH4J_URL := http://sourceforge.net/projects/launch4j/files/launch4j-3/3.0.2/launch4j-3.0.2-macosx.tgz
|
9
|
+
|
10
|
+
# Commands
|
11
|
+
JRUBY:=jruby $(OPT)
|
12
|
+
WARBLE:=$(JRUBY) -S warble
|
13
|
+
|
14
|
+
.PHONY: all
|
15
|
+
all: build
|
16
|
+
|
17
|
+
## Execute the tool
|
18
|
+
.PHONY: exec
|
19
|
+
exec:
|
20
|
+
cd src && env RUBYLIB=./lib $(JRUBY) bin/iated --debug
|
21
|
+
|
22
|
+
## Execute tests and coverage
|
23
|
+
.PHONY: test
|
24
|
+
test:
|
25
|
+
$(JRUBY) -S rspec spec
|
26
|
+
|
27
|
+
.PHONY: coverage
|
28
|
+
coverage: $(TEST_SOURCE)
|
29
|
+
$(JRUBY) -S jrcov --output target/coverage -I src/lib $(TEST_SOURCE)
|
30
|
+
|
31
|
+
## Setup the environment
|
32
|
+
.PHONY: setup
|
33
|
+
setup: cache/launch4j/launch4j
|
34
|
+
$(JRUBY) -S jbundle
|
35
|
+
|
36
|
+
cache/launch4j/launch4j:
|
37
|
+
mkdir -p cache
|
38
|
+
cd cache && wget -N $(LAUNCH4J_URL)
|
39
|
+
cd cache && tar xf $(notdir $(LAUNCH4J_URL))
|
40
|
+
|
41
|
+
## Build the tool
|
42
|
+
.PHONY: build
|
43
|
+
build: target/iated.jar target/iated.exe
|
44
|
+
|
45
|
+
.PHONY: jar
|
46
|
+
jar: target/iated.jar
|
47
|
+
|
48
|
+
.PHONY: exe
|
49
|
+
exe: target/iated.exe
|
50
|
+
|
51
|
+
target/iated.exe: target/iated.jar
|
52
|
+
@if [ ! -x cache/launch4j/launch4j ]; then echo "Run 'make setup'"; exit 10; fi
|
53
|
+
cd target && env -u OPT ../cache/launch4j/launch4j $$(pwd)/../launch4j-config.xml
|
54
|
+
|
55
|
+
target/iated.jar: build/build.jar
|
56
|
+
mkdir -p target
|
57
|
+
cp -f $< $@
|
58
|
+
|
59
|
+
$(BUILD_SOURCE):build/%: src/%
|
60
|
+
mkdir -p $(dir $@)
|
61
|
+
cp -f $< $@
|
62
|
+
|
63
|
+
build/build.jar: $(BUILD_SOURCE)
|
64
|
+
cd build && $(WARBLE) jar:clean jar
|
65
|
+
|
66
|
+
|
67
|
+
## Clean
|
68
|
+
.PHONY: clean
|
69
|
+
clean:
|
70
|
+
rm -rf target build
|
71
|
+
|
72
|
+
### Makefile ends here
|
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
# It's All Text! Editor Daemon
|
2
|
+
|
3
|
+
This gem is the core of the *It's All Text! Editor Daemon*.
|
4
|
+
|
5
|
+
The *IAT Editor Daemon* is a restful web server that allows you to
|
6
|
+
open text data in the editor of your choice.
|
7
|
+
|
8
|
+
## Bugs and Issues
|
9
|
+
|
10
|
+
See [the github Issue tracker](https://github.com/docwhat/iated/issues)
|
11
|
+
|
12
|
+
## Developer Quickstart
|
13
|
+
|
14
|
+
1. `bundle install`
|
15
|
+
2. `rake spec`
|
16
|
+
|
17
|
+
### Requirements
|
18
|
+
|
19
|
+
* Ruby (preferrably 1.9.2+, but 1.8.7 should work)
|
20
|
+
|
21
|
+
## API
|
22
|
+
|
23
|
+
The API is documented in the `features/extension_*.feature` files. You
|
24
|
+
can run cucumber to read them.
|
25
|
+
|
26
|
+
### Open preferences
|
27
|
+
|
28
|
+
`GET /preferences` requires "token".
|
29
|
+
|
30
|
+
Opens a web-page displaying the preferences. Note, there are other
|
31
|
+
URLs that Iated supports for modifying the preferences.
|
32
|
+
|
33
|
+
`GET /preferences/set-editor` require "token".
|
34
|
+
|
35
|
+
This opens a dialog on the system running Iated to choose the editor.
|
36
|
+
|
37
|
+
## Example sessions.
|
38
|
+
|
39
|
+
The letter `b:` is the browser's requests. `s:` is the server's
|
40
|
+
response. Side-effects are in square braces (`[]`).
|
41
|
+
|
42
|
+
### Initial authentication
|
43
|
+
|
44
|
+
b: GET /hello
|
45
|
+
s: ok [a popup with the secret is shown]
|
46
|
+
b: POST /hello with data: secret=NNNN
|
47
|
+
s: token=<MMMMMMMMMMMMMMMMM>
|
48
|
+
|
49
|
+
### Editing session
|
50
|
+
|
51
|
+
b: POST /edit text=<textarea data> url=<someurl> id=<textarea-id>
|
52
|
+
s: <sid>
|
53
|
+
b: GET /edit/<sid>
|
54
|
+
s: nochange
|
55
|
+
b: GET /edit/<sid>
|
56
|
+
s: <next textarea data>
|
57
|
+
|
58
|
+
## Iated Dialogs
|
59
|
+
|
60
|
+
This is a list of dialogs that Iated needs to be able to generate:
|
61
|
+
|
62
|
+
* Set Editor -- The dialog to select an editor.
|
63
|
+
* Auth Code -- A dialog to show the auth-code for entering in the
|
64
|
+
browser.
|
65
|
+
* Select Port -- A dialog to select the port to run on for the first
|
66
|
+
time or if changing.
|
67
|
+
|
68
|
+
|
69
|
+
## Future notes
|
70
|
+
|
71
|
+
At some point I'm going to need concurrancy. I'm thinking
|
72
|
+
[jetlang](http://code.google.com/p/jetlang/) (a java library) is the
|
73
|
+
right way to go. It's Erlang style concurrancy, so it'll scale well
|
74
|
+
and should be safe without having to worry about joins, etc. There is
|
75
|
+
a ruby gem called [jretlang](http://github.com/reevesg/jretlang)
|
76
|
+
|
77
|
+
Some info here:
|
78
|
+
|
79
|
+
* [Concurrancy models in JRuby using jetlang](http://www.blog.wordaligned.com/2010/02/17/concurrency-models-in-jruby-using-jetlang/)
|
80
|
+
* [What is erlang style concurrency?](http://ulf.wiger.net/weblog/2008/02/06/what-is-erlang-style-concurrency/)
|
81
|
+
* [LWN article](http://lwn.net/Articles/441790/)
|
82
|
+
|
83
|
+
## License
|
84
|
+
|
85
|
+
Iated is licensed under the
|
86
|
+
[MIT License](http://www.opensource.org/licenses/mit-license.php). A
|
87
|
+
`LICENSE` file should have been included with this code.
|
data/Rakefile
ADDED
data/bin/iated
ADDED
data/config.ru
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
/** The base URL for requests.
|
2
|
+
*/
|
3
|
+
var base_url = 'http://127.0.0.1:9090/';
|
4
|
+
var token = '655a93c645d1bf5d5ee972caf0eeaa86';
|
5
|
+
|
6
|
+
/** Initialize the background handlers.
|
7
|
+
*/
|
8
|
+
function init() {
|
9
|
+
console.debug('IAT background loading...');
|
10
|
+
|
11
|
+
/* Defaults for ajax requests. */
|
12
|
+
$.ajaxSetup({
|
13
|
+
cache: false
|
14
|
+
});
|
15
|
+
|
16
|
+
/* Set up the listener. */
|
17
|
+
chrome.extension.onRequest.addListener(onRequest);
|
18
|
+
|
19
|
+
console.debug('IAT background loaded.');
|
20
|
+
}
|
21
|
+
|
22
|
+
/** Handles request from contentscript.js
|
23
|
+
* @param msg Object Data sent in the request.
|
24
|
+
* @param sender Object Origin of the request.
|
25
|
+
* @param callback Function The method to call when the request completes.
|
26
|
+
*/
|
27
|
+
function onRequest(msg, sender, callback) {
|
28
|
+
if ('edit' === msg.action) {
|
29
|
+
edit(msg.text, msg.url, msg.id, callback);
|
30
|
+
} else if ('update' == msg.action) {
|
31
|
+
update(msg.sid, msg.change_id, callback);
|
32
|
+
} else {
|
33
|
+
console.error("Unknown msg: ", msg);
|
34
|
+
}
|
35
|
+
};
|
36
|
+
|
37
|
+
/** Handles an edit request.
|
38
|
+
* @param text
|
39
|
+
* @param url
|
40
|
+
* @param id
|
41
|
+
*/
|
42
|
+
function edit(text, url, id, callback) {
|
43
|
+
var data = {
|
44
|
+
text : text,
|
45
|
+
token : token
|
46
|
+
};
|
47
|
+
if (url) {
|
48
|
+
data.url = url;
|
49
|
+
}
|
50
|
+
if (id) {
|
51
|
+
data.id = id;
|
52
|
+
}
|
53
|
+
data.extension = '.txt';
|
54
|
+
$.ajax({
|
55
|
+
url: base_url + 'edit',
|
56
|
+
type: 'POST',
|
57
|
+
data: data,
|
58
|
+
dataType: 'text',
|
59
|
+
success: function (resp, textStatus) {
|
60
|
+
resp = YAML.eval(resp);
|
61
|
+
console.log("NARF edit response: %o %o", resp, textStatus);
|
62
|
+
callback({sid: resp.sid});
|
63
|
+
},
|
64
|
+
error: function (jqXHR, textStatus, errorThrown) {
|
65
|
+
console.error("edit: failure: %o - %o - %o", jqXHR, textStatus, errorThrown);
|
66
|
+
callback({ error: "Unable to get update from Iated" });
|
67
|
+
}
|
68
|
+
});
|
69
|
+
}
|
70
|
+
|
71
|
+
/** Handles an update request.
|
72
|
+
*/
|
73
|
+
function update(sid, change_id, callback) {
|
74
|
+
var url = base_url + 'edit/' + sid;
|
75
|
+
if (change_id) {
|
76
|
+
url = url + '/' + change_id;
|
77
|
+
} else {
|
78
|
+
url = url + '/0';
|
79
|
+
}
|
80
|
+
console.log("logging info: %o", url);
|
81
|
+
$.ajax({
|
82
|
+
url: url,
|
83
|
+
type: 'GET',
|
84
|
+
dataType: 'text',
|
85
|
+
success: function (resp, textStatus) {
|
86
|
+
resp = YAML.eval(resp);
|
87
|
+
console.log("update: success: %o - %o", resp, textStatus);
|
88
|
+
if (resp) {
|
89
|
+
callback(resp);
|
90
|
+
} else {
|
91
|
+
callback(null);
|
92
|
+
}
|
93
|
+
},
|
94
|
+
error: function (jqXHR, textStatus, errorThrown) {
|
95
|
+
console.error("update: failure: %o - %o - %o", jqXHR, textStatus, errorThrown);
|
96
|
+
console.log('narf4');
|
97
|
+
callback({ error: "Unable to get update from Iated" });
|
98
|
+
}
|
99
|
+
});
|
100
|
+
}
|
101
|
+
|
102
|
+
/* Main */
|
103
|
+
init();
|
104
|
+
|
105
|
+
/* EOF */
|
File without changes
|
@@ -0,0 +1,110 @@
|
|
1
|
+
var is_focused = true;
|
2
|
+
var focus_queue = [];
|
3
|
+
|
4
|
+
/** jQuery plugin to assign unique ids.
|
5
|
+
*/
|
6
|
+
(function( $ ){
|
7
|
+
var last_id = 0;
|
8
|
+
$.fn.getId = function() {
|
9
|
+
var el = this.first();
|
10
|
+
if (!el.attr('id')) {
|
11
|
+
el.attr('id', 'iat-' + (++last_id));
|
12
|
+
}
|
13
|
+
return el.attr('id');
|
14
|
+
};
|
15
|
+
})( jQuery );
|
16
|
+
|
17
|
+
/** Scan the page for textareas and setup the buttons.
|
18
|
+
*/
|
19
|
+
function init() {
|
20
|
+
console.debug('IAT is loading...');
|
21
|
+
$('textarea').each(function () {
|
22
|
+
var jel = $(this), tid = jel.getId(), button = $('<button class="iat">IAT</button>');
|
23
|
+
;
|
24
|
+
jel.after(button);
|
25
|
+
|
26
|
+
button
|
27
|
+
.css('position', 'absolute')
|
28
|
+
.click(function (event) {
|
29
|
+
edit(jel);
|
30
|
+
return false;
|
31
|
+
});
|
32
|
+
});
|
33
|
+
console.debug('IAT is loaded.');
|
34
|
+
|
35
|
+
$(window).focus(function () {
|
36
|
+
is_focused = true;
|
37
|
+
while (focus_queue.length > 0) {
|
38
|
+
focus_queue.pop()();
|
39
|
+
}
|
40
|
+
}).blur(function () {
|
41
|
+
is_focused = false;
|
42
|
+
});
|
43
|
+
}
|
44
|
+
|
45
|
+
/** Called to edit a textarea.
|
46
|
+
* @param jel A single jQuery element.
|
47
|
+
*/
|
48
|
+
function edit(jel) {
|
49
|
+
var callback = function (msg) {
|
50
|
+
console.debug("IAT edit reply for ", jel, " with ", msg);
|
51
|
+
if (msg && msg.error) {
|
52
|
+
// Handle the error.
|
53
|
+
handleError(msg);
|
54
|
+
return;
|
55
|
+
}
|
56
|
+
monitor(jel, msg.sid, null);
|
57
|
+
}
|
58
|
+
chrome.extension.sendRequest({ action : 'edit',
|
59
|
+
text : jel.val(),
|
60
|
+
id : jel.getId(),
|
61
|
+
url : window.location.href,
|
62
|
+
},
|
63
|
+
callback);
|
64
|
+
}
|
65
|
+
|
66
|
+
/** Start monitoring for changes.
|
67
|
+
* @param jel A single jQuery element.
|
68
|
+
* @param sid The sid for this element.
|
69
|
+
*/
|
70
|
+
function monitor(jel, sid, change_id) {
|
71
|
+
var callback = function (msg) {
|
72
|
+
new_change_id = (msg && msg.id) ? msg.id : change_id;
|
73
|
+
console.debug("monitor callback - sid:%o msg:%o el:%o",
|
74
|
+
sid, msg, jel);
|
75
|
+
if (msg && msg.error) {
|
76
|
+
// Handle the error.
|
77
|
+
handleError(msg);
|
78
|
+
return;
|
79
|
+
}
|
80
|
+
if (msg && msg.text && msg.text != jel.val()) {
|
81
|
+
jel.val(msg.text);
|
82
|
+
jel.effect("highlight", {}, 3 * 1000);
|
83
|
+
}
|
84
|
+
if (is_focused) {
|
85
|
+
setTimeout(function () {
|
86
|
+
monitor(jel, sid, new_change_id);
|
87
|
+
}, 3000);
|
88
|
+
} else {
|
89
|
+
focus_queue.push(function () {
|
90
|
+
monitor(jel, sid, new_change_id);
|
91
|
+
});
|
92
|
+
}
|
93
|
+
}
|
94
|
+
chrome.extension.sendRequest({action : 'update',
|
95
|
+
sid : sid,
|
96
|
+
change_id : change_id},
|
97
|
+
callback);
|
98
|
+
}
|
99
|
+
|
100
|
+
/** Handle errors.
|
101
|
+
* @param msg A message object containing information on the error.
|
102
|
+
*/
|
103
|
+
function handleError(msg) {
|
104
|
+
alert("ERROR: " + msg.error);
|
105
|
+
}
|
106
|
+
|
107
|
+
/** Main **/
|
108
|
+
init();
|
109
|
+
|
110
|
+
/* EOF */
|