iated 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +3 -0
  3. data/Guardfile +24 -0
  4. data/LICENSE +23 -0
  5. data/Makefile +72 -0
  6. data/README.md +87 -0
  7. data/Rakefile +10 -0
  8. data/bin/iated +13 -0
  9. data/config.ru +5 -0
  10. data/extensions/chrome/background.html +5 -0
  11. data/extensions/chrome/background.js +105 -0
  12. data/extensions/chrome/contentscript.css +0 -0
  13. data/extensions/chrome/contentscript.js +110 -0
  14. data/extensions/chrome/jquery-ui.js +45 -0
  15. data/extensions/chrome/jquery.js +16 -0
  16. data/extensions/chrome/jquery.updater.js +46 -0
  17. data/extensions/chrome/manifest.json +19 -0
  18. data/extensions/chrome/yaml.js +489 -0
  19. data/extensions/tests/simple.html +23 -0
  20. data/features/extension_authenticates.feature +30 -0
  21. data/features/extension_edits.feature +45 -0
  22. data/features/step_definitions/extension_steps.rb +134 -0
  23. data/features/support/env.rb +47 -0
  24. data/features/support/hooks.rb +11 -0
  25. data/iated.gemspec +48 -0
  26. data/lib/iated.rb +111 -0
  27. data/lib/iated/browser_token_db.rb +76 -0
  28. data/lib/iated/edit_session.rb +221 -0
  29. data/lib/iated/helpers.rb +9 -0
  30. data/lib/iated/mcp.rb +144 -0
  31. data/lib/iated/page_helpers.rb +33 -0
  32. data/lib/iated/public/jquery-ui.js +101 -0
  33. data/lib/iated/public/jquery.js +2 -0
  34. data/lib/iated/public/robots.txt +5 -0
  35. data/lib/iated/server.rb +162 -0
  36. data/lib/iated/sys_pref.rb +201 -0
  37. data/lib/iated/version.rb +3 -0
  38. data/lib/iated/views/hello.haml +13 -0
  39. data/lib/iated/views/preferences.haml +27 -0
  40. data/lib/iated/views/reference.coffee +79 -0
  41. data/lib/iated/views/reference.haml +94 -0
  42. data/lib/iated/views/reference.scss +36 -0
  43. data/lib/iated/views/root.haml +13 -0
  44. data/spec/lib/iated/browser_token_db_spec.rb +68 -0
  45. data/spec/lib/iated/edit_session_spec.rb +157 -0
  46. data/spec/lib/iated/mcp_spec.rb +86 -0
  47. data/spec/lib/iated/sys_pref_spec.rb +40 -0
  48. data/spec/protocol/edit_spec.rb +88 -0
  49. data/spec/protocol/hello_spec.rb +18 -0
  50. data/spec/protocol/notfound_spec.rb +11 -0
  51. data/spec/protocol/ping_spec.rb +10 -0
  52. data/spec/protocol/preferences_spec.rb +35 -0
  53. data/spec/spec_helper.rb +21 -0
  54. metadata +460 -0
@@ -0,0 +1,6 @@
1
+ *~
2
+ /pkg/
3
+ /.bundle/
4
+ /.yardoc/
5
+ /Gemfile.lock
6
+ /doc/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -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.
@@ -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
@@ -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.
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+ require "yard"
5
+ require "yard/rake/yardoc_task"
6
+
7
+ RSpec::Core::RakeTask.new
8
+ YARD::Rake::YardocTask.new do |t|
9
+ t.files = ['lib/**/*.rb']
10
+ end
@@ -0,0 +1,13 @@
1
+ #!ruby
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ Bundler.setup(:default)
6
+ require 'pathname'
7
+ $: << (Pathname.new(__FILE__).dirname.dirname + 'lib').to_s
8
+
9
+ require 'iated'
10
+
11
+ Iated::Application.new.run
12
+
13
+ # EOF
@@ -0,0 +1,5 @@
1
+
2
+ $: << ::File.expand_path('../lib', __FILE__)
3
+ require 'iated/server'
4
+
5
+ run Iated::Server
@@ -0,0 +1,5 @@
1
+ <!DOCTYPE html>
2
+ <meta charset=utf-8>
3
+ <script src="jquery.js"></script>
4
+ <script src="yaml.js"></script>
5
+ <script src="background.js"></script>
@@ -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 */