lyndon 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Chris Wanstrath
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,83 @@
1
+ Lyndon
2
+ ======
3
+
4
+ Lyndon is like [Johnson](http://github.com/jbarnette/johnson). But for MacRuby. And with JavaScriptCore.
5
+
6
+ Here It Goes
7
+ ------------
8
+
9
+ $ rip install git://github.com/defunkt/lyndon.git
10
+ Successfully installed lyndon (41548d2)
11
+ $ lyndon
12
+ js> 1 + 1
13
+ => 2
14
+ js> function name() { return "lyndon!" }
15
+ => undefined
16
+ js> name
17
+ => function name() { return "lyndon!" }
18
+ js> name()
19
+ => "lyndon!"
20
+ js> Ruby.puts('Ruby, I presume.')
21
+ Ruby, I presume.
22
+ => undefined
23
+ js> Ruby.File_read('hi.js')
24
+ => "// this is hi.js\n"
25
+
26
+ Stuff like that.
27
+
28
+ Oh, the DOM
29
+ -----------
30
+
31
+ $ lyndon test.html
32
+ js> Lyndon.require('jquery.min.js')
33
+ => true
34
+ js> jQuery('#hi').html()
35
+ => "Hello."
36
+ js> jQuery('#hi').html('Hi.')
37
+ => [object Object]
38
+ js> jQuery('#hi').html()
39
+ => "Hi."
40
+ => "[object HTMLBodyElement]"
41
+ js> document.body.innerHTML
42
+ => "\n <h1 id=\"hi\">Hi.</h1>\n \n\n"
43
+
44
+
45
+ HTML with JavaScript
46
+ --------------------
47
+
48
+ $ cat examples/index.html | lyndon
49
+ <html><head>
50
+ <title>It worked!</title>
51
+ </head><body>
52
+ <div id="content">
53
+ <div id="hi">Hello world!</div></div>
54
+ </body></html>
55
+
56
+ Note that the `<div id="hi">Hello world!</div></div>` does _not_ exist
57
+ in `examples/index.html` - it's added at runtime by
58
+ JavaScript. JavaScript that strips itself out and changes the
59
+ `<title`>.
60
+
61
+ Seriously.
62
+
63
+
64
+ With Ruby
65
+ ---------
66
+
67
+ If you want:
68
+
69
+ $ macirb
70
+ >> require 'lyndon'
71
+ => true
72
+ >> Lyndon.eval('1 + 1')
73
+ => 2
74
+ >> r = Lyndon::Runtime.new
75
+ => ##-<Lyndon::Runtime:...>
76
+ >> r.eval('var name = "chris"')
77
+ => undefined
78
+ >> r.eval('name')
79
+ => "chris"
80
+
81
+ That's basically it.
82
+
83
+ Chris Wanstrath // chris@ozmm.org
@@ -0,0 +1,36 @@
1
+ begin
2
+ require 'jeweler'
3
+
4
+ # We're not putting VERSION or VERSION.yml in the root,
5
+ # so we have to help Jeweler find our version.
6
+ $LOAD_PATH.unshift File.dirname(__FILE__) + '/lib'
7
+ require 'lyndon/version'
8
+
9
+ Lyndon::Version.instance_eval do
10
+ def refresh
11
+ end
12
+ end
13
+
14
+ class Jeweler
15
+ def version_helper
16
+ Lyndon::Version
17
+ end
18
+
19
+ def version_exists?
20
+ true
21
+ end
22
+ end
23
+
24
+ Jeweler::Tasks.new do |gemspec|
25
+ gemspec.name = "lyndon"
26
+ gemspec.summary = "Lyndon wraps JavaScript in a loving MacRuby embrace."
27
+ gemspec.email = "chris@ozmm.org"
28
+ gemspec.homepage = "http://github.com/defunkt/lyndon"
29
+ gemspec.description = "Lyndon wraps JavaScript in a loving MacRuby embrace."
30
+ gemspec.authors = ["Chris Wanstrath"]
31
+ gemspec.has_rdoc = false
32
+ end
33
+ rescue LoadError
34
+ puts "Jeweler not available."
35
+ puts "Install it with: gem install technicalpickles-jeweler"
36
+ end
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env macruby
2
+
3
+ __DIR__ = File.expand_path(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift File.join(__DIR__, '..', 'lib')
5
+
6
+ require 'lyndon'
7
+ require 'lyndon/repl'
8
+
9
+ if STDIN.stat.size > 0
10
+ input = STDIN.read
11
+ abort Lyndon.parse(input)
12
+ end
13
+
14
+ case ARGV.first
15
+ when '-h', '--help'
16
+ puts "Run it:"
17
+ puts " $ lyndon -e '(string to eval)'"
18
+ puts " $ lyndon -p '(string to eval; result will puts)'"
19
+ puts " $ lyndon file.js"
20
+ puts " $ lyndon file.html"
21
+ puts " $ cat file.html | lyndon"
22
+ puts " $ lyndon"
23
+ when '-e'
24
+ Lyndon.eval(ARGV.last)
25
+ when '-p'
26
+ puts Lyndon.eval(ARGV.last)
27
+ when nil
28
+ Lyndon::Repl.start
29
+ else
30
+ ARGV[-1][/\.js$/] ? Lyndon.eval_file(ARGV.last) : Lyndon::Repl.start(ARGV.last)
31
+ end
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Lyndon Test!</title>
5
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
6
+ <script>
7
+ $(function() {
8
+ $('#content').append('<div id="hi">Hello world!</div>')
9
+ $('script').remove()
10
+ document.title = 'It worked!'
11
+ })
12
+ </script>
13
+ </head>
14
+ <body>
15
+ <div id="content">
16
+ </div>
17
+ </body>
18
+ </html>
@@ -0,0 +1,25 @@
1
+ var Lyndon = {
2
+ required: {},
3
+
4
+ require: function(file) {
5
+ var directory, path, loadPath = Ruby('$LOAD_PATH')
6
+ file = Ruby.File_join(Ruby.File_dirname(file),
7
+ Ruby.File_basename(file, ".js") + ".js")
8
+
9
+ if (Lyndon.required[file]) return false
10
+
11
+ for (var i = 0; i < Ruby('$LOAD_PATH').length; i++) {
12
+ directory = loadPath[i]
13
+ path = Ruby.File_join(directory, file)
14
+
15
+ if (Ruby.File_file(path)) {
16
+ Lyndon.required[file] = true
17
+ eval(Ruby.File_read(path))
18
+
19
+ return true
20
+ }
21
+ }
22
+
23
+ throw Ruby.LoadError
24
+ }
25
+ }
@@ -0,0 +1,29 @@
1
+ #
2
+ # It's pretty much that easy.
3
+ #
4
+
5
+ if !defined?(RUBY_ENGINE) || RUBY_ENGINE != 'macruby'
6
+ abort "Lyndon requires MacRuby. http://www.macruby.org/"
7
+ end
8
+
9
+ framework 'WebKit'
10
+
11
+ require 'lyndon/runtime'
12
+ require 'lyndon/coercion'
13
+ require 'lyndon/ruby'
14
+ require 'lyndon/delegate'
15
+
16
+ module Lyndon
17
+ def self.eval(js)
18
+ Runtime.new.eval(js)
19
+ end
20
+
21
+ def self.eval_file(file)
22
+ contents = File.read(File.expand_path(file))
23
+ eval(contents)
24
+ end
25
+
26
+ def self.parse(html)
27
+ Lyndon::Runtime.new(html).to_s
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ # help convert objects WebKit's JS returns into
2
+ # things we can use
3
+
4
+ class NSCFNumber
5
+ def inspect
6
+ if Integer(self) == Float(self)
7
+ Integer(self).to_s
8
+ else
9
+ Float(self).to_s
10
+ end
11
+ end
12
+ end
13
+
14
+ class NSCFBoolean
15
+ def inspect
16
+ (self == NSNumber.numberWithBool(true)).to_s
17
+ end
18
+ end
19
+
20
+ class WebScriptObject
21
+ def inspect
22
+ callWebScriptMethod("toString", withArguments:nil)
23
+ end
24
+ end
25
+
26
+ class WebUndefined
27
+ def inspect
28
+ 'undefined'
29
+ end
30
+ end
@@ -0,0 +1,7 @@
1
+ module Lyndon
2
+ class Delegate
3
+ def webView(sender, didFinishLoadForFrame:frame)
4
+ NSApplication.sharedApplication.stop(self)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,47 @@
1
+ require 'readline'
2
+
3
+ module Lyndon
4
+ class Repl
5
+ Prompt = 'js> '
6
+ AwaitingInput = '?> '
7
+ Result = '=> '
8
+ HistoryFile = File.join(File.expand_path('~'), '.lyndon_history')
9
+
10
+ def self.start(dom = nil)
11
+ load_history
12
+ @parser = Lyndon::Runtime.new(dom)
13
+
14
+ loop do
15
+ input = Readline.readline(Prompt)
16
+ quit if input.nil?
17
+
18
+ begin
19
+ puts Result + @parser.eval(input).inspect.to_s
20
+ rescue => e
21
+ save_history
22
+ raise e
23
+ else
24
+ Readline::HISTORY.push(input)
25
+ end
26
+ end
27
+ end
28
+
29
+ def self.load_history
30
+ return unless File.exists? HistoryFile
31
+ File.readlines(HistoryFile).each do |line|
32
+ Readline::HISTORY.push line.chomp
33
+ end
34
+ end
35
+
36
+ def self.save_history
37
+ File.open(HistoryFile, 'w') do |f|
38
+ f.puts Readline::HISTORY.to_a.join("\n")
39
+ end
40
+ end
41
+
42
+ def self.quit
43
+ save_history
44
+ exit
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,35 @@
1
+ module Lyndon
2
+ class Ruby
3
+ ##
4
+ # Lets us call simple ruby methods
5
+ #
6
+ # Ruby.IO_read(file)
7
+ # Ruby.puts('hi')
8
+ # Ruby.require('uri')
9
+ def invokeUndefinedMethodFromWebScript(name, withArguments:args)
10
+ if respond_to? name
11
+ send(name, *args)
12
+ elsif Kernel.respond_to? name
13
+ Kernel.send(name, *args)
14
+ elsif name =~ /^([A-Z][A-Za-z]+)_(.+)/
15
+ const = Kernel.const_get($1)
16
+ method = $2
17
+
18
+ if const.respond_to? method
19
+ const.send(method, *args)
20
+ elsif const.respond_to?("#{method}?")
21
+ const.send("#{method}?", *args)
22
+ elsif const.respond_to?("#{method}!")
23
+ const.send("#{method}!", *args)
24
+ end
25
+ end
26
+ end
27
+
28
+ ##
29
+ # Ruby('$LOAD_PATH') => array...
30
+ # Ruby('1 + 1') => 2
31
+ def invokeDefaultMethodWithArguments(args)
32
+ eval(args[0])
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,42 @@
1
+ # http://developer.apple.com/documentation/Cocoa/Reference/WebKit/ObjC_classic/index.html
2
+
3
+ module Lyndon
4
+ class Runtime
5
+ def initialize(dom = nil)
6
+ @webView = WebView.new
7
+ @webView.setFrameLoadDelegate(Delegate.new)
8
+
9
+ @scripter = @webView.windowScriptObject
10
+ @scripter.setValue(Ruby.new, forKey:"Ruby")
11
+
12
+ load_dom(dom) if dom
13
+ eval_file File.dirname(__FILE__) + '/../js/lyndon'
14
+ end
15
+
16
+ def eval(js)
17
+ @scripter.evaluateWebScript(js)
18
+ end
19
+
20
+ def eval_file(file)
21
+ if File.exists? file = File.expand_path(file.to_s)
22
+ eval File.read(file)
23
+ elsif File.exists? file + '.js'
24
+ eval File.read(file + '.js')
25
+ end
26
+ end
27
+
28
+ def load_dom(dom, base_url = nil)
29
+ @dom = File.exists?(dom) ? File.read(dom) : dom
30
+ @webView.mainFrame.loadHTMLString(@dom, baseURL:base_url)
31
+ NSApplication.sharedApplication.run
32
+ end
33
+
34
+ def to_s
35
+ @dom ? html_source : super
36
+ end
37
+
38
+ def html_source
39
+ '<html>'+eval("document.documentElement.innerHTML")+'</html>'
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,9 @@
1
+ module Lyndon
2
+ VERSION = '0.0.1'
3
+
4
+ class Version
5
+ def self.to_s
6
+ VERSION
7
+ end
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lyndon
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Chris Wanstrath
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-10 00:00:00 -07:00
13
+ default_executable: lyndon
14
+ dependencies: []
15
+
16
+ description: Lyndon wraps JavaScript in a loving MacRuby embrace.
17
+ email: chris@ozmm.org
18
+ executables:
19
+ - lyndon
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.markdown
25
+ files:
26
+ - LICENSE
27
+ - README.markdown
28
+ - Rakefile
29
+ - bin/lyndon
30
+ - examples/index.html
31
+ - lib/js/lyndon.js
32
+ - lib/lyndon.rb
33
+ - lib/lyndon/coercion.rb
34
+ - lib/lyndon/delegate.rb
35
+ - lib/lyndon/repl.rb
36
+ - lib/lyndon/ruby.rb
37
+ - lib/lyndon/runtime.rb
38
+ - lib/lyndon/version.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/defunkt/lyndon
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --charset=UTF-8
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.3.3
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: Lyndon wraps JavaScript in a loving MacRuby embrace.
67
+ test_files: []
68
+