flammarion 0.0.13 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Readme.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/flammarion.svg)](https://badge.fury.io/rb/flammarion)
4
4
 
5
+ * [Source](https://github.com/zach-capalbo/flammarion)
6
+ * [Documentation](http://zach-capalbo.github.io/flammarion/doc/)
7
+
5
8
  ## Overview
6
9
 
7
10
  Flammarion is an easy-to-use library for displaying information that you might
@@ -13,8 +16,11 @@ without going through too much trouble.
13
16
 
14
17
  ## Installation
15
18
 
16
- First you need to install [electron](http://electron.atom.io/)
17
- and make sure it's in your path. Then you can install the gem:
19
+ First, you need to install [electron](http://electron.atom.io/) or [chrome](http://www.google.com/chrome)
20
+ and make sure it's in your path. (*Note:* On Windows, currently only chrome
21
+ works, but you don't need to worry about putting it in your path.)
22
+
23
+ Then you can install the gem:
18
24
 
19
25
  ```
20
26
  gem install flammarion
@@ -70,7 +76,9 @@ f.button("Click Here!!!") {f.puts "You clicked the button!"}
70
76
  f.input("Placeholder > ") {|msg| f.puts "You wrote: #{msg['text'].light_magenta}"}
71
77
  ```
72
78
 
73
- The (_almost_) full [api documetaion](http://zach-capalbo.github.io/flammarion/doc/) is available at http://zach-capalbo.github.io/flammarion/doc/
79
+ The (_almost_) full [api documetaion](http://zach-capalbo.github.io/flammarion/doc/)
80
+ is available at <http://zach-capalbo.github.io/flammarion/doc/>. See especially
81
+ the [Writeable Module](http://zach-capalbo.github.io/flammarion/doc/Flammarion/Writeable.html)
74
82
 
75
83
  ## Screenshots / Samples
76
84
 
@@ -148,7 +156,7 @@ f.pane("sidebar").pane("side2").puts Faker::Hipster.paragraph.green
148
156
 
149
157
  ## Examples
150
158
 
151
- There are a number of useful examples in the [examples directory.](https://github.com/zach-capalbo/flammarion)
159
+ There are a number of useful examples in the [examples directory.](https://github.com/zach-capalbo/flammarion/tree/master/examples)
152
160
 
153
161
  # Bundled Packages
154
162
 
data/lib/flammarion.rb CHANGED
@@ -6,11 +6,14 @@ require 'colorize'
6
6
  require 'filewatcher'
7
7
  require 'rbconfig'
8
8
 
9
- # Optional requires
10
- require 'sass'
11
- require 'slim'
12
- require 'coffee-script'
13
- require 'redcarpet'
9
+ begin
10
+ # Optional Requires
11
+ require 'sass'
12
+ require 'slim'
13
+ require 'coffee-script'
14
+ require 'redcarpet'
15
+ rescue LoadError
16
+ end
14
17
 
15
18
  require_relative 'flammarion/writeable.rb'
16
19
  require_relative 'flammarion/pane.rb'
@@ -18,134 +21,10 @@ require_relative 'flammarion/server.rb'
18
21
  require_relative 'flammarion/version.rb'
19
22
  require_relative 'flammarion/revelator.rb'
20
23
  require_relative 'flammarion/about.rb'
24
+ require_relative 'flammarion/engraving.rb'
21
25
 
26
+ # This is the main namespace for Flammarion.
27
+ # @see Engraving
28
+ # @see Writeable
22
29
  module Flammarion
23
- class Engraving
24
- include Revelator
25
- attr_reader :chrome
26
- attr_accessor :callbacks, :sockets, :on_disconnect, :on_connect, :actions
27
- include Writeable
28
-
29
- # Creates a new Engraving (i.e., a new display window)
30
- # @option options [Proc] :on_connect Called when the display window is
31
- # connected (i.e., displayed)
32
- # @option options [Proc] :on_disconnect Called when the display windows is
33
- # disconnected (i.e., closed)
34
- def initialize(options = {})
35
- @chrome = OpenStruct.new
36
- @sockets = []
37
- @actions = {}
38
- @engraving = self
39
- @pane_name = "default"
40
- @on_connect = options[:on_connect]
41
- @on_disconnect = options[:on_disconnect]
42
- @exit_on_disconnect = options.fetch(:exit_on_disconnect, false)
43
-
44
- start_server
45
- @window_id = @@server.register_window(self)
46
- open_a_window unless options[:no_chrome]
47
- @callbacks = {}
48
- wait_for_a_connection unless options[:no_wait]
49
-
50
- at_exit {close} if options.fetch(:close_on_exit, false)
51
- end
52
-
53
- def disconnect(ws)
54
- @sockets.delete ws
55
- exit 0 if @exit_on_disconnect
56
- @on_disconnect.call if @on_disconnect
57
- end
58
-
59
- def wait_until_closed
60
- sleep 1 until @sockets.empty?
61
- end
62
-
63
- def process_message(msg)
64
- @last_msg = msg
65
- m = {}
66
- begin
67
- m = JSON.parse(msg)
68
- rescue JSON::ParserError
69
- log "Invalid JSON String"
70
- return
71
- end
72
-
73
- case m["action"]
74
- when 'callback'
75
- callback = @callbacks[m['id']]
76
- unless callback.nil?
77
- if callback.arity == 1
78
- callback.call(m)
79
- else
80
- callback.call
81
- end
82
- end
83
- end
84
- @actions[m["action"]].call(m) if @actions.include?(m["action"])
85
- end
86
-
87
- def make_id
88
- @id ||= 0
89
- @id += 1
90
- "i#{@id}"
91
- end
92
-
93
- def start_server
94
- @@server ||= Server.new
95
- end
96
-
97
- def server; @@server; end;
98
-
99
- def wait_for_a_connection
100
- sleep 0.5 while @sockets.empty?
101
- end
102
-
103
- def window_open?
104
- not @sockets.empty?
105
- end
106
-
107
- def send_json(val)
108
- if @sockets.empty? then
109
- open_a_window
110
- wait_for_a_connection
111
- end
112
- @sockets.each{|ws| ws.send val.to_json}
113
- nil
114
- end
115
-
116
- def alert(text)
117
- send_json(action:'alert', text:text)
118
- end
119
-
120
- def orientation=(orientation)
121
- raise ArgumentError.new("Orientation must be :horizontal or :vertical") unless [:horizontal, :vertical].include?(orientation)
122
- send_json({action:'reorient', orientation:orientation})
123
- end
124
-
125
- def title(str)
126
- send_json({action:'title', title:str})
127
- end
128
-
129
- def layout(file)
130
- data = Slim::Template.new(file).render
131
- send_json({action:'layout', data:data})
132
- end
133
-
134
- def close
135
- send_json({action:'close'})
136
- end
137
-
138
- def live_reload_layout(file)
139
- layout(file); yield if block_given?
140
- FileWatcher.new(file).watch {|file| layout(file); yield if block_given? }
141
- end
142
-
143
- def get_save_path
144
- if Gem.win_platform?
145
- `powershell "Add-Type -AssemblyName System.windows.forms|Out-Null;$f=New-Object System.Windows.Forms.SaveFileDialog;$f.InitialDirectory='%cd%';$f.Filter='All Files (*.*)|*.*';$f.showHelp=$true;$f.ShowDialog()|Out-Null;$f.FileName"`.strip
146
- else
147
- `zenity --file-selection --save --confirm-overwrite`.strip
148
- end
149
- end
150
- end
151
30
  end
@@ -1,4 +1,6 @@
1
1
  module Flammarion
2
+
3
+ # Pops up a little about box.
2
4
  def self.about
3
5
  f = Engraving.new(close_on_exit:true)
4
6
  f.title "Flammarion #{VERSION}"
@@ -0,0 +1,171 @@
1
+ module Flammarion
2
+
3
+ # The engraving class represents a window. It contains everything you need to
4
+ # display on the screen and interacts with a user. An +Engraving+ contains
5
+ # one or more panes, which are containers for writeable areas. Most of the
6
+ # power of the panes comes from the +Writeable+ module, which is also included
7
+ # in +Engraving+ (operating on the default pane) for convenience.
8
+ # @see Writeable
9
+ # @note Right now, there is no persistence of Engravings. Once it is closed,
10
+ # everything is erased, and you'll need to set it up all over again.
11
+ # @note If you try to display something to a closed window, it will open a new
12
+ # blank window, and then display that thing.
13
+ class Engraving
14
+ include Revelator
15
+ attr_reader :chrome
16
+ attr_accessor :callbacks, :sockets, :on_disconnect, :on_connect, :actions
17
+ include Writeable
18
+
19
+ # Creates a new Engraving (i.e., a new display window)
20
+ # @option options [Proc] :on_connect Called when the display window is
21
+ # connected (i.e., displayed)
22
+ # @option options [Proc] :on_disconnect Called when the display windows is
23
+ # disconnected (i.e., closed)
24
+ # @option options [Boolean] :exit_on_disconnect (false) Will call +exit+
25
+ # when the widow is closed if this option is true.
26
+ # @option options [Boolean] :close_on_exit (false) Will close the window
27
+ # when the process exits if this is true. Otherwise, it will just stay
28
+ # around, but not actually be interactive.
29
+ # @opion options [String] :title The initial title of the engraving. If
30
+ # empty, a random title will be generated.
31
+ def initialize(options = {})
32
+ options = {:title => options} if options.is_a?(String)
33
+ @chrome = OpenStruct.new
34
+ @sockets = []
35
+ @actions = {}
36
+ @engraving = self
37
+ @pane_name = "default"
38
+ @on_connect = options[:on_connect]
39
+ @on_disconnect = options[:on_disconnect]
40
+ @exit_on_disconnect = options.fetch(:exit_on_disconnect, false)
41
+
42
+ start_server
43
+ @window_id = @@server.register_window(self)
44
+ open_a_window(options) unless options[:no_window]
45
+ @callbacks = {}
46
+ wait_for_a_connection unless options[:no_wait]
47
+
48
+ at_exit {close if window_open?} if options.fetch(:close_on_exit, true)
49
+
50
+ title options[:title] if options[:title]
51
+ end
52
+
53
+ # Blocks the current thread until the window has been closed. All user
54
+ # interactions and callbacks will continue in other threads.
55
+ def wait_until_closed
56
+ sleep 1 until @sockets.empty?
57
+ end
58
+
59
+ # Is thie Engraving displayed on the screen.
60
+ def window_open?
61
+ not @sockets.empty?
62
+ end
63
+
64
+ # Pops up an alert message containing +text+.
65
+ def alert(text)
66
+ send_json(action:'alert', text:text)
67
+ end
68
+
69
+ # Changes the orientation of the panes in this engraving. Options are
70
+ # - :horizontal
71
+ # - :vertical
72
+ def orientation=(orientation)
73
+ raise ArgumentError.new("Orientation must be :horizontal or :vertical") unless [:horizontal, :vertical].include?(orientation)
74
+ send_json({action:'reorient', orientation:orientation})
75
+ end
76
+
77
+ # Sets the title of the window
78
+ def title(str)
79
+ send_json({action:'title', title:str})
80
+ end
81
+
82
+ # Attempts to close the window.
83
+ def close
84
+ send_json({action:'close'})
85
+ end
86
+
87
+ # Opens a native "Save File" Dialog box, prompting the user for a file.
88
+ def get_save_path
89
+ if Gem.win_platform?
90
+ `powershell "Add-Type -AssemblyName System.windows.forms|Out-Null;$f=New-Object System.Windows.Forms.SaveFileDialog;$f.InitialDirectory='%cd%';$f.Filter='All Files (*.*)|*.*';$f.showHelp=$true;$f.ShowDialog()|Out-Null;$f.FileName"`.strip
91
+ else
92
+ `zenity --file-selection --save --confirm-overwrite`.strip
93
+ end
94
+ end
95
+
96
+ # Allows you to load a custom layout file. This replaces all html in the
97
+ # window with a custom slim layout. You probably don't want this unless your
98
+ # writing a very complex application.
99
+ def layout(file)
100
+ data = Slim::Template.new(file).render
101
+ send_json({action:'layout', data:data})
102
+ end
103
+
104
+ def live_reload_layout(file)
105
+ layout(file); yield if block_given?
106
+ FileWatcher.new(file).watch {|file| layout(file); yield if block_given? }
107
+ end
108
+
109
+ # @api private
110
+ def disconnect(ws)
111
+ @sockets.delete ws
112
+ exit 0 if @exit_on_disconnect
113
+ @on_disconnect.call if @on_disconnect
114
+ end
115
+
116
+ # @api private
117
+ def process_message(msg)
118
+ @last_msg = msg
119
+ m = {}
120
+ begin
121
+ m = JSON.parse(msg)
122
+ rescue JSON::ParserError
123
+ log "Invalid JSON String"
124
+ return
125
+ end
126
+
127
+ case m["action"]
128
+ when 'callback'
129
+ callback = @callbacks[m['id']]
130
+ unless callback.nil?
131
+ if callback.arity == 1
132
+ callback.call(m)
133
+ else
134
+ callback.call
135
+ end
136
+ end
137
+ end
138
+ @actions[m["action"]].call(m) if @actions.include?(m["action"])
139
+ end
140
+
141
+ # @api private
142
+ def make_id
143
+ @id ||= 0
144
+ @id += 1
145
+ "i#{@id}"
146
+ end
147
+
148
+ # @api private
149
+ def start_server
150
+ @@server ||= Server.new
151
+ end
152
+
153
+ # @api private
154
+ def server; @@server; end;
155
+
156
+ # @api private
157
+ def wait_for_a_connection
158
+ sleep 0.5 while @sockets.empty?
159
+ end
160
+
161
+ # @api private
162
+ def send_json(val)
163
+ if @sockets.empty? then
164
+ open_a_window
165
+ wait_for_a_connection
166
+ end
167
+ @sockets.each{|ws| ws.send val.to_json}
168
+ nil
169
+ end
170
+ end
171
+ end
@@ -1,6 +1,7 @@
1
1
  require_relative 'writeable.rb'
2
2
 
3
3
  module Flammarion
4
+ # @see Writeable
4
5
  class Pane
5
6
  attr_reader :pane_name
6
7
  include Writeable
@@ -1,36 +1,24 @@
1
1
  module Flammarion
2
+ # @api private
3
+ # @todo This all needs a lot of clean up
2
4
  module Revelator
3
- def which(cmd)
4
- exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
5
- ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
6
- exts.each do |ext|
7
- exe = File.join(path, "#{cmd}#{ext}")
8
- return exe if File.executable?(exe) && !File.directory?(exe)
9
- end
10
- end
11
- return nil
12
- end
13
-
14
5
  CHROME_PATH = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
15
- def open_a_window_on_windows
6
+ def open_a_window_on_windows(options)
16
7
  file_path = File.absolute_path(File.join(File.dirname(__FILE__), ".."))
17
8
  file_path = `cygpath -w '#{file_path}'`.strip if RbConfig::CONFIG["host_os"] == "cygwin"
18
9
  resource = %[file\://#{file_path}/html/build/index.html]
19
10
  chrome_path = CHROME_PATH
20
11
  chrome_path = `cygpath -u '#{CHROME_PATH}'`.strip if RbConfig::CONFIG["host_os"] == "cygwin"
21
- spawn(chrome_path, %[--app=#{resource}?path=#{@window_id}&port=#{server.port}])
12
+ Process.detach(spawn(chrome_path, %[--app=#{resource}?path=#{@window_id}&port=#{server.port}&title="#{options[:title] || "Flammarion%20Engraving"}"]))
22
13
  end
23
14
 
24
- def open_a_window
25
- return open_a_window_on_windows if RbConfig::CONFIG["host_os"] =~ /cygwin|mswin|mingw/
26
- developmentMode = system("lsof -i:#{4567}", out: '/dev/null')
15
+ def open_a_window(options = {})
16
+ return open_a_window_on_windows(options) if RbConfig::CONFIG["host_os"] =~ /cygwin|mswin|mingw/
17
+ developmentMode = system("lsof -i:#{4567}", out: '/dev/null') and File.exist?("#{File.dirname(__FILE__)}/../html/source/index.html.slim")
27
18
  host = "file://#{File.dirname(File.absolute_path(__FILE__))}/../html/build/index.html"
28
19
  host = "http://localhost:4567/" if developmentMode
29
20
 
30
- # data_dir = Dir.mktmpdir("flammarion")
31
- # File.open("#{data_dir}/First\ Run", "w") {}
32
-
33
- @expect_title = "Flammarion-#{rand.to_s[2..-1]}"
21
+ @expect_title = options[:title] || "Flammarion-#{rand.to_s[2..-1]}"
34
22
 
35
23
  if which('electron') then
36
24
  Process.detach(spawn("electron #{File.dirname(File.absolute_path(__FILE__))}/../../electron '#{host}?path=#{@window_id}&port=#{server.port}&title=#{@expect_title}'"))
@@ -44,5 +32,17 @@ module Flammarion
44
32
 
45
33
  raise StandardError.new("Cannot launch any browser") unless @chrome.in
46
34
  end
35
+
36
+ private
37
+ def which(cmd)
38
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
39
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
40
+ exts.each do |ext|
41
+ exe = File.join(path, "#{cmd}#{ext}")
42
+ return exe if File.executable?(exe) && !File.directory?(exe)
43
+ end
44
+ end
45
+ return nil
46
+ end
47
47
  end
48
48
  end
@@ -1,4 +1,5 @@
1
1
  module Flammarion
2
+ # @api private
2
3
  class Server
3
4
  attr_reader :port
4
5
  def initialize
@@ -1,3 +1,3 @@
1
1
  module Flammarion
2
- VERSION = "0.0.13"
2
+ VERSION = "0.0.14"
3
3
  end
@@ -55,6 +55,13 @@ module Flammarion
55
55
  # @note Don't forget to set the :escape_html option to false when including
56
56
  # this string.
57
57
 
58
+ # @!macro [new] add_options
59
+ # @option options [Boolean] :replace If true, will replace any existing
60
+ # contents of the writeable area.
61
+ # @option options [Hash] :style A map of css style attributes and values to
62
+ # be applied to the element before it is added.
63
+
64
+ # @api private
58
65
  def send_json(hash)
59
66
  @engraving.send_json({target: @pane_name}.merge(hash))
60
67
  end
@@ -98,7 +105,7 @@ module Flammarion
98
105
 
99
106
  # Creates a new plot to display single axis data
100
107
  # @param [Array<Number>] values A list of numbers to plot
101
- # TODO: @options
108
+ # @todo finish documenting options
102
109
  # @return [Spectrum] A Spectrum object for manipulation after creation.
103
110
  def plot(values, options = {})
104
111
  id = @engraving.make_id
@@ -159,7 +166,7 @@ module Flammarion
159
166
  # Creates a string representing a Font Awesome icon.
160
167
  # @macro string_representation
161
168
  # @param name [String] The name of a Font Awesome icon class. See
162
- # @see https://fortawesome.github.io/Font-Awesome/icons/ for the list.
169
+ # @see https://fortawesome.github.io/Font-Awesome/icons/
163
170
  def icon(name, additional_classes = [])
164
171
  %|<i class="fa fa-#{name} #{additional_classes.collect{|c| "fa-#{c}"}.join(" ")}"></i>|
165
172
  end
@@ -259,15 +266,27 @@ module Flammarion
259
266
  send_json({action:'replace', text:data, raw:true})
260
267
  end
261
268
 
262
- def script(coffee, options = {})
263
- data = options.fetch(:coffee, true) ? CoffeeScript.compile(coffee) : coffee
269
+ # Runs a script in the engraving window.
270
+ # @param text [String] The script to run. Lanuage of the script depends on
271
+ # the options given. Defaults to CoffeeScript
272
+ # @option options [Boolean] :coffee (true) If true, will compile +text+ from
273
+ # CoffeeScript to JavaScript. If false, will pass text as plain JavaScript
274
+ def script(text, options = {})
275
+ data = options.fetch(:coffee, true) ? CoffeeScript.compile(text) : text
264
276
  send_json({action:'script', data:data}.merge(options))
265
277
  end
266
278
 
279
+ # Sets a CSS styles attribute on the current pane.
280
+ # @param attribute [String] The css attribute to set. Currently does not
281
+ # support selectors or anything.
282
+ # @param value [#to_s] The value to set the attribute to. (Don't forget
283
+ # units!)
267
284
  def style(attribute, value)
268
285
  send_json({action: 'style', attribute: attribute, value: value})
269
286
  end
270
287
 
288
+ # Will render the given Slim template into the pane
289
+ # @param file [String] Path to the template file to render
271
290
  def template(file)
272
291
  data = Slim::Template.new(file).render
273
292
  send_json({action:'replace', text:data, raw:true})
@@ -277,6 +296,11 @@ module Flammarion
277
296
  FileWatcher.new(file).watch {|file| template(file) }
278
297
  end
279
298
 
299
+ # Renders the given markdown text into the pane.
300
+ # @param text [String] The markdown text to render.
301
+ # @option options [Hash] :markdown_extensions Additional Redcarpet
302
+ # extensions to enable.
303
+ # @macro add_options
280
304
  def markdown(text, options = {})
281
305
  markdown_html = Redcarpet::Markdown.new(Redcarpet::Render::HTML, {
282
306
  tables: true,
@@ -288,19 +312,50 @@ module Flammarion
288
312
  send_json({action:'markdown', text: markdown_html}.merge(options))
289
313
  end
290
314
 
315
+ # Hides (but doesn't close) the pane. This allows the pane to be written
316
+ # to without it opening up again.
317
+ # @see show
291
318
  def hide
292
319
  send_json({action:'hidepane'})
293
320
  end
294
321
 
322
+ # Shows a hidden pane.
323
+ # @see hide
295
324
  def show
296
325
  send_json({action:'showpane'})
297
326
  end
298
327
 
328
+ # @!macro [new] pane_difference
329
+ # @note The difference between pane and subpane is that a pane is
330
+ # automatically scaled depending on the number of other panes and the
331
+ # current orientation, while subpanes are automatically the size of their
332
+ # contents.
333
+ # Another way to think about it might be that pane creates structural
334
+ # layout elements, while subpane creates embedded sections within other
335
+ # panes.
336
+
337
+ # Creates a writeable area within the current writeable area. This lets you
338
+ # update the contents of the writeable later, without disturbing the rest
339
+ # of the curent pane. If a pane or subpane with the given name already
340
+ # exists, it will just use that one instead.
341
+ # @param name [String] an identifier for the subpane. All panes and subpanes
342
+ # share the same scope, so you want to be careful with your naming.
343
+ # @return [Pane] The newly created or already existing pane.
344
+ # @macro pane_difference
345
+ # @see pane
299
346
  def subpane(name, options = {})
300
347
  send_json({action:'subpane', name:name}.merge(options))
301
348
  return Pane.new(@engraving, name)
302
349
  end
303
350
 
351
+ # Creates a scaled pane within the current writeable area. Where it goes
352
+ # depends on the orientation.
353
+ # @param name [String] an identifier for the subpane. All panes and subpanes
354
+ # share the same scope, so you want to be careful with your naming.
355
+ # @return [Pane] The newly created or already existing pane.
356
+ # @macro pane_difference
357
+ # @see pane
358
+ # @see orientation=
304
359
  def pane(name, options = {})
305
360
  send_json({action:'addpane', name:name}.merge(options))
306
361
  return Pane.new(@engraving, name)
@@ -343,6 +398,18 @@ module Flammarion
343
398
  return str
344
399
  end
345
400
 
401
+ # Adds an interactive street map of a specified location.
402
+ # @option options [Integer] :zoom (13) The initial zoom level
403
+ # @option options [Boolean] :marker (true) Display a marker on the
404
+ # identified address or coordinates
405
+ # @macro add_options
406
+ # @overload map(options)
407
+ # @overload map(address, options = {})
408
+ # @param address [String] The address or landmark to look up and display.
409
+ # @overload map(latitude, longitude, options = {})
410
+ # @param latitude [Float] The latitude to display
411
+ # @param longitude [Float] The longitude to display
412
+ # @note Street map provided by http://openstreetmap.org
346
413
  def map(*args)
347
414
  case (args.size)
348
415
  when 1
@@ -58,7 +58,8 @@ void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?voi
58
58
 
59
59
  }).call(this);
60
60
  (function() {
61
- var WSClient;
61
+ var WSClient,
62
+ hasProp = {}.hasOwnProperty;
62
63
 
63
64
  WSClient = (function() {
64
65
  function WSClient() {
@@ -181,6 +182,15 @@ void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?voi
181
182
  };
182
183
 
183
184
  WSClient.prototype.add = function(object, target, data) {
185
+ var key, ref, val;
186
+ if (data.style) {
187
+ ref = data.style;
188
+ for (key in ref) {
189
+ if (!hasProp.call(ref, key)) continue;
190
+ val = ref[key];
191
+ object.css(key, val);
192
+ }
193
+ }
184
194
  if (data.replace) {
185
195
  return target.html(object);
186
196
  } else {
@@ -6679,7 +6679,8 @@ if (typeof module !== 'undefined') {
6679
6679
 
6680
6680
  }).call(this);
6681
6681
  (function() {
6682
- var WSClient;
6682
+ var WSClient,
6683
+ hasProp = {}.hasOwnProperty;
6683
6684
 
6684
6685
  WSClient = (function() {
6685
6686
  function WSClient() {
@@ -6802,6 +6803,15 @@ if (typeof module !== 'undefined') {
6802
6803
  };
6803
6804
 
6804
6805
  WSClient.prototype.add = function(object, target, data) {
6806
+ var key, ref, val;
6807
+ if (data.style) {
6808
+ ref = data.style;
6809
+ for (key in ref) {
6810
+ if (!hasProp.call(ref, key)) continue;
6811
+ val = ref[key];
6812
+ object.css(key, val);
6813
+ }
6814
+ }
6805
6815
  if (data.replace) {
6806
6816
  return target.html(object);
6807
6817
  } else {
@@ -7273,7 +7283,7 @@ if (typeof module !== 'undefined') {
7273
7283
 
7274
7284
  Plot = (function() {
7275
7285
  Plot.prototype.default_options = {
7276
- color: "#fff",
7286
+ color: $(document.body).css("color"),
7277
7287
  replace: true,
7278
7288
  size: 1.0,
7279
7289
  orientation: 'vertical',
@@ -58,7 +58,8 @@ void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?voi
58
58
 
59
59
  }).call(this);
60
60
  (function() {
61
- var WSClient;
61
+ var WSClient,
62
+ hasProp = {}.hasOwnProperty;
62
63
 
63
64
  WSClient = (function() {
64
65
  function WSClient() {
@@ -181,6 +182,15 @@ void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?voi
181
182
  };
182
183
 
183
184
  WSClient.prototype.add = function(object, target, data) {
185
+ var key, ref, val;
186
+ if (data.style) {
187
+ ref = data.style;
188
+ for (key in ref) {
189
+ if (!hasProp.call(ref, key)) continue;
190
+ val = ref[key];
191
+ object.css(key, val);
192
+ }
193
+ }
184
194
  if (data.replace) {
185
195
  return target.html(object);
186
196
  } else {
@@ -58,7 +58,8 @@ void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?voi
58
58
 
59
59
  }).call(this);
60
60
  (function() {
61
- var WSClient;
61
+ var WSClient,
62
+ hasProp = {}.hasOwnProperty;
62
63
 
63
64
  WSClient = (function() {
64
65
  function WSClient() {
@@ -181,6 +182,15 @@ void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?voi
181
182
  };
182
183
 
183
184
  WSClient.prototype.add = function(object, target, data) {
185
+ var key, ref, val;
186
+ if (data.style) {
187
+ ref = data.style;
188
+ for (key in ref) {
189
+ if (!hasProp.call(ref, key)) continue;
190
+ val = ref[key];
191
+ object.css(key, val);
192
+ }
193
+ }
184
194
  if (data.replace) {
185
195
  return target.html(object);
186
196
  } else {
@@ -25,7 +25,7 @@
25
25
 
26
26
  Plot = (function() {
27
27
  Plot.prototype.default_options = {
28
- color: "#fff",
28
+ color: $(document.body).css("color"),
29
29
  replace: true,
30
30
  size: 1.0,
31
31
  orientation: 'vertical',
@@ -58,7 +58,8 @@ void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?voi
58
58
 
59
59
  }).call(this);
60
60
  (function() {
61
- var WSClient;
61
+ var WSClient,
62
+ hasProp = {}.hasOwnProperty;
62
63
 
63
64
  WSClient = (function() {
64
65
  function WSClient() {
@@ -181,6 +182,15 @@ void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=n.find.attr(a,b),null==e?voi
181
182
  };
182
183
 
183
184
  WSClient.prototype.add = function(object, target, data) {
185
+ var key, ref, val;
186
+ if (data.style) {
187
+ ref = data.style;
188
+ for (key in ref) {
189
+ if (!hasProp.call(ref, key)) continue;
190
+ val = ref[key];
191
+ object.css(key, val);
192
+ }
193
+ }
184
194
  if (data.replace) {
185
195
  return target.html(object);
186
196
  } else {
@@ -13,7 +13,7 @@ $.extend WSClient.prototype.actions,
13
13
 
14
14
  class Plot
15
15
  default_options:
16
- color: "#fff"
16
+ color: $(document.body).css("color")
17
17
  replace: true
18
18
  size: 1.0
19
19
  orientation: 'vertical'
@@ -75,6 +75,8 @@ class WSClient
75
75
  return text
76
76
 
77
77
  add: (object, target, data) ->
78
+ if data.style
79
+ object.css(key, val) for own key, val of data.style
78
80
  if data.replace
79
81
  target.html(object)
80
82
  else
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flammarion
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.0.14
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -284,6 +284,7 @@ files:
284
284
  - lib/html/Gemfile
285
285
  - lib/flammarion/about.rb
286
286
  - lib/flammarion/server.rb
287
+ - lib/flammarion/engraving.rb
287
288
  - lib/flammarion/pane.rb
288
289
  - lib/flammarion/version.rb
289
290
  - lib/flammarion/revelator.rb