smalruby-editor 0.0.5 → 0.0.6
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.
Potentially problematic release.
This version of smalruby-editor might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rspec +2 -1
- data/.rubocop.yml +18 -0
- data/.travis.yml +24 -23
- data/LEGAL +13 -0
- data/README.rdoc +1 -0
- data/Rakefile +3 -0
- data/app/assets/javascripts/application.js +1 -1
- data/app/assets/javascripts/editor.js.coffee +60 -15
- data/app/assets/stylesheets/application.css +1 -2
- data/app/assets/stylesheets/flatstrap-custom.css.scss +2 -0
- data/app/controllers/editor_controller.rb +0 -24
- data/app/controllers/source_codes_controller.rb +67 -0
- data/app/models/source_code.rb +42 -0
- data/app/views/editor/index.html.erb +5 -3
- data/bin/smalruby-editor +11 -0
- data/config/application.rb +8 -20
- data/config/boot.rb +3 -0
- data/config/environments/development.rb +2 -1
- data/config/environments/production.rb +12 -6
- data/config/environments/standalone.rb +3 -2
- data/config/environments/test.rb +14 -4
- data/config/initializers/backtrace_silencers.rb +4 -2
- data/config/initializers/session_store.rb +2 -1
- data/config/initializers/wrap_parameters.rb +2 -1
- data/config/routes.rb +10 -6
- data/config/unicorn.rb +7 -6
- data/db/migrate/20131216121603_create_source_codes.rb +9 -0
- data/db/migrate/20131219045113_add_filename_to_source_code.rb +5 -0
- data/db/schema.rb +8 -1
- data/lib/smalruby_editor.rb +29 -15
- data/lib/smalruby_editor/version.rb +1 -1
- data/lib/tasks/rspec.rake +2 -2
- data/lib/tasks/rubocop.rake +3 -0
- data/public/fonts/FontAwesome.otf +0 -0
- data/public/fonts/fontawesome-webfont.eot +0 -0
- data/public/fonts/fontawesome-webfont.ttf +0 -0
- data/public/fonts/fontawesome-webfont.woff +0 -0
- data/smalruby-editor.gemspec +3 -3
- data/spec/acceptance/readme.md +3 -0
- data/spec/acceptance/text_editor/base.feature +24 -0
- data/spec/acceptance/text_editor/check.feature +20 -0
- data/spec/acceptance/text_editor/load.feature +74 -0
- data/spec/acceptance/text_editor/save.feature +31 -0
- data/spec/controllers/editor_controller_spec.rb +2 -63
- data/spec/controllers/source_codes_controller_spec.rb +296 -0
- data/spec/models/source_code_spec.rb +44 -0
- data/spec/spec_helper.rb +123 -65
- data/spec/steps/ace_steps.rb +60 -0
- data/spec/steps/global_variable.rb +39 -0
- data/spec/steps/text_editor_steps.rb +160 -0
- data/spec/support/capybara.rb +17 -0
- metadata +49 -19
- data/spec/acceptance/editor.feature +0 -68
- data/spec/steps/editor_steps.rb +0 -123
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d71a9e4754ddc023b99130576187b13e97cca3ce
|
4
|
+
data.tar.gz: 4ed1b62b217727d2a96bfa9c337049a8850e2684
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb60b2b55e43a4403b29441647b3eae78b6ae563be42d2b84c5c6f4971eccd10875fe131bac0013042d641a0aa5165b564472cf1cc3db5039fadb54ac688e9f5
|
7
|
+
data.tar.gz: 77272e287ef54a97a9c8fdf70e9da1c02a7a62eee9cf5e05df6413b0ae4285b6686616aa35020ebe64735e1ead930cb80e1d00840f193c4a24250bc49661f237
|
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
AllCops:
|
2
|
+
Excludes:
|
3
|
+
- db/seeds.rb
|
4
|
+
|
5
|
+
AsciiComments:
|
6
|
+
Enabled: false
|
7
|
+
|
8
|
+
# メソッドの戻り値としてブロックの値を使う場合にもエラーになるため無効
|
9
|
+
# にしている
|
10
|
+
Blocks:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Documentation:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
# WindowsだとEndOfLine copが動作しないため無効にしている
|
17
|
+
EndOfLine:
|
18
|
+
Enabled: false
|
data/.travis.yml
CHANGED
@@ -1,23 +1,24 @@
|
|
1
|
-
language: ruby
|
2
|
-
|
3
|
-
rvm:
|
4
|
-
- 2.0.0
|
5
|
-
|
6
|
-
before_script:
|
7
|
-
- cp config/database.yml.travis config/database.yml
|
8
|
-
- mysql -e 'create database myapp_test;'
|
9
|
-
|
10
|
-
script:
|
11
|
-
- export SECRET_KEY_BASE='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
|
12
|
-
- export COVERALLS='1'
|
13
|
-
- RAILS_ENV=test bundle exec rake db:migrate --trace
|
14
|
-
- bundle exec rake db:test:prepare
|
15
|
-
- bundle exec rake
|
16
|
-
|
17
|
-
deploy:
|
18
|
-
provider: heroku
|
19
|
-
api_key:
|
20
|
-
secure: HqZ7FylThjaB3XguCZJbccu7dB8CvWIWFlZpWLLfJwfUkjvoEC1F6VPFakFbwjLXLsvaKlYLakzL+bhaLnxu+HyeNmCrvpIRR2j8EuHmSkxdWrlxAZRV2ojHuDpZuVNaEzd7YtcBCoPiTvqnxWzhAfzZWbPrZfCdA1f+5t5/So0=
|
21
|
-
app: smalruby
|
22
|
-
on:
|
23
|
-
repo: smalruby/smalruby-editor
|
1
|
+
language: ruby
|
2
|
+
|
3
|
+
rvm:
|
4
|
+
- 2.0.0
|
5
|
+
|
6
|
+
before_script:
|
7
|
+
- cp config/database.yml.travis config/database.yml
|
8
|
+
- mysql -e 'create database myapp_test;'
|
9
|
+
|
10
|
+
script:
|
11
|
+
- export SECRET_KEY_BASE='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
|
12
|
+
- export COVERALLS='1'
|
13
|
+
- RAILS_ENV=test bundle exec rake db:migrate --trace
|
14
|
+
- bundle exec rake db:test:prepare
|
15
|
+
- bundle exec rake
|
16
|
+
|
17
|
+
deploy:
|
18
|
+
provider: heroku
|
19
|
+
api_key:
|
20
|
+
secure: HqZ7FylThjaB3XguCZJbccu7dB8CvWIWFlZpWLLfJwfUkjvoEC1F6VPFakFbwjLXLsvaKlYLakzL+bhaLnxu+HyeNmCrvpIRR2j8EuHmSkxdWrlxAZRV2ojHuDpZuVNaEzd7YtcBCoPiTvqnxWzhAfzZWbPrZfCdA1f+5t5/So0=
|
21
|
+
app: smalruby
|
22
|
+
on:
|
23
|
+
repo: smalruby/smalruby-editor
|
24
|
+
run: "rake db:migrate"
|
data/LEGAL
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
LEGAL NOTICE INFORMATION
|
2
|
+
------------------------
|
3
|
+
|
4
|
+
All the files in this distribution are covered under either the
|
5
|
+
smalruby-editor's license (see the file LICENSE) except some files
|
6
|
+
mentioned below.
|
7
|
+
|
8
|
+
public/fonts/FontAwesome.otf, public/fonts/fontawesome-webfont.eot,
|
9
|
+
public/fonts/fontawesome-webfont.ttf,
|
10
|
+
public/fonts/fontawesome-webfont.woff:
|
11
|
+
|
12
|
+
These's license is SIL Open Font License (OFL) 1.1:
|
13
|
+
http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL .
|
data/README.rdoc
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
== smalruby-editor
|
2
2
|
|
3
|
+
{<img src="https://badge.fury.io/rb/smalruby-editor.png" alt="Gem Version" />}[http://badge.fury.io/rb/smalruby-editor]
|
3
4
|
{<img src="https://travis-ci.org/smalruby/smalruby-editor.png?branch=master" alt="Build Status" />}[https://travis-ci.org/smalruby/smalruby-editor]
|
4
5
|
{<img src="https://coveralls.io/repos/smalruby/smalruby-editor/badge.png?branch=master" alt="Coverage Status" />}[https://coveralls.io/r/smalruby/smalruby-editor?branch=master]
|
5
6
|
{<img src="https://codeclimate.com/github/smalruby/smalruby-editor.png" />}[https://codeclimate.com/github/smalruby/smalruby-editor]
|
data/Rakefile
CHANGED
@@ -2,11 +2,22 @@
|
|
2
2
|
# All this logic will automatically be available in application.js.
|
3
3
|
# You can use CoffeeScript in this file: http://coffeescript.org/
|
4
4
|
|
5
|
+
changed = false
|
6
|
+
|
5
7
|
$ ->
|
8
|
+
saving = false
|
9
|
+
|
6
10
|
textEditor = ace.edit('text-editor')
|
7
|
-
textEditor.setTheme('ace/theme/
|
11
|
+
textEditor.setTheme('ace/theme/github')
|
8
12
|
textEditor.setShowInvisibles(true)
|
9
13
|
|
14
|
+
textEditor.focus()
|
15
|
+
textEditor.gotoLine(0, 0)
|
16
|
+
|
17
|
+
textEditor.on('change', (e) ->
|
18
|
+
changed = true
|
19
|
+
)
|
20
|
+
|
10
21
|
session = textEditor.getSession()
|
11
22
|
session.setMode('ace/mode/ruby')
|
12
23
|
session.setTabSize(2)
|
@@ -20,18 +31,40 @@ $ ->
|
|
20
31
|
e.preventDefault()
|
21
32
|
false
|
22
33
|
|
23
|
-
$('#
|
34
|
+
$('#check-button').click (e) ->
|
35
|
+
e.preventDefault()
|
36
|
+
data =
|
37
|
+
source_code:
|
38
|
+
data: session.getDocument().getValue()
|
39
|
+
success = (data, textStatus, jqXHR) ->
|
40
|
+
for errorInfo in data
|
41
|
+
do (errorInfo) ->
|
42
|
+
msg = $('<div class="alert alert-error" style="display: none">')
|
43
|
+
.append('<button type="button" class="close" data-dismiss="alert">×</button>')
|
44
|
+
.append('<h4><i class="icon-exclamation-sign"></i>エラー</h4>')
|
45
|
+
.append("#{errorInfo.row}行")
|
46
|
+
if errorInfo.column > 0
|
47
|
+
msg.append("、#{errorInfo.column}文字")
|
48
|
+
msg.append(": #{errorInfo.message}")
|
49
|
+
$('#messages').append(msg)
|
50
|
+
msg.fadeIn('slow')
|
51
|
+
$.post('/source_codes/check', data, success, 'json')
|
52
|
+
|
53
|
+
$('#save-button').click (e) ->
|
54
|
+
e.preventDefault()
|
24
55
|
filename = $.trim($('#filename').val())
|
25
56
|
if filename.length <= 0
|
26
57
|
$('#filename').focus()
|
27
58
|
else
|
28
59
|
data =
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
60
|
+
source_code:
|
61
|
+
filename: filename
|
62
|
+
data: session.getDocument().getValue()
|
63
|
+
success = (data, textStatus, jqXHR) ->
|
64
|
+
saving = true
|
65
|
+
changed = false
|
66
|
+
$('#download-link').click()
|
67
|
+
$.post('/source_codes/', data, success, 'json')
|
35
68
|
|
36
69
|
$('#filename').keypress (e) ->
|
37
70
|
e = window.event if !e
|
@@ -41,20 +74,32 @@ $ ->
|
|
41
74
|
else
|
42
75
|
true
|
43
76
|
|
77
|
+
$('#load-button').click (e) ->
|
78
|
+
e.preventDefault()
|
79
|
+
if changed
|
80
|
+
return unless confirm('まだセーブしていないのでロードするとプログラムが消えてしまうよ!それでもロードしますか?')
|
81
|
+
$(@).parent().find('input[name="source_code[file]"]').click()
|
82
|
+
|
44
83
|
$('#file-form').fileupload(
|
45
84
|
dataType: 'json'
|
46
|
-
add: (e, data) ->
|
47
|
-
data.submit()
|
48
85
|
done: (e, data) ->
|
49
|
-
|
50
|
-
if
|
86
|
+
info = data.result.source_code
|
87
|
+
if info.error
|
51
88
|
msg = $('<div class="alert alert-error" style="display: none">')
|
52
89
|
.append('<button type="button" class="close" data-dismiss="alert">×</button>')
|
53
90
|
.append('<h4><i class="icon-exclamation-sign"></i>エラー</h4>')
|
54
|
-
.append(
|
91
|
+
.append(info.filename + 'は' + info.error)
|
55
92
|
$('#messages').append(msg)
|
56
93
|
msg.fadeIn('slow').delay(5000).fadeOut('slow')
|
57
94
|
else
|
58
|
-
$('#filename').val(
|
59
|
-
session.getDocument().setValue(
|
95
|
+
$('#filename').val(info.filename)
|
96
|
+
session.getDocument().setValue(info.data)
|
97
|
+
changed = false
|
60
98
|
)
|
99
|
+
|
100
|
+
window.onbeforeunload = (event) ->
|
101
|
+
if !saving && session.getDocument().getValue().length > 0
|
102
|
+
return '作成中のプログラムが消えてしまいます。'
|
103
|
+
else
|
104
|
+
saving = false
|
105
|
+
return
|
@@ -8,8 +8,7 @@
|
|
8
8
|
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
9
|
* compiled file, but it's generally better to create a new file per style scope.
|
10
10
|
*
|
11
|
-
*= require flatstrap
|
12
|
-
*= require font-awesome
|
11
|
+
*= require flatstrap-custom
|
13
12
|
*= require_self
|
14
13
|
*= require_tree .
|
15
14
|
*/
|
@@ -1,29 +1,5 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
|
-
require 'nkf'
|
3
|
-
|
4
2
|
class EditorController < ApplicationController
|
5
3
|
def index
|
6
4
|
end
|
7
|
-
|
8
|
-
def save_file
|
9
|
-
send_data(params[:source], filename: params[:filename],
|
10
|
-
disposition: 'attachment', type: 'text/plain; charset=utf-8')
|
11
|
-
end
|
12
|
-
|
13
|
-
def load_file
|
14
|
-
f = params['load_file']
|
15
|
-
mime_type = MIME.check(f.path)
|
16
|
-
content_type = mime_type.try(:content_type) || f.content_type
|
17
|
-
res = {
|
18
|
-
name: f.original_filename,
|
19
|
-
type: content_type,
|
20
|
-
size: f.size,
|
21
|
-
}
|
22
|
-
if /\Atext\/plain/ =~ content_type
|
23
|
-
res[:source] = NKF.nkf('-w', f.read)
|
24
|
-
else
|
25
|
-
res[:error] = 'Rubyのプログラムではありません'
|
26
|
-
end
|
27
|
-
render json: res, content_type: request.format
|
28
|
-
end
|
29
5
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'nkf'
|
3
|
+
|
4
|
+
class SourceCodesController < ApplicationController
|
5
|
+
def check
|
6
|
+
render json: SourceCode.new(source_code_params).check_syntax
|
7
|
+
end
|
8
|
+
|
9
|
+
def create
|
10
|
+
source_code = SourceCode.create!(source_code_params)
|
11
|
+
session[:source_code] = {
|
12
|
+
id: source_code.id,
|
13
|
+
digest: source_code.digest,
|
14
|
+
}
|
15
|
+
render json: { source_code: { id: source_code.id } }
|
16
|
+
end
|
17
|
+
|
18
|
+
def download
|
19
|
+
source_code = SourceCode.find(session[:source_code][:id])
|
20
|
+
unless source_code.digest == session[:source_code][:digest]
|
21
|
+
fail ActiveRecord::RecordNotFound
|
22
|
+
end
|
23
|
+
|
24
|
+
send_data(source_code.data,
|
25
|
+
filename: encode_filename(source_code.filename),
|
26
|
+
disposition: 'attachment',
|
27
|
+
type: 'text/plain; charset=utf-8')
|
28
|
+
|
29
|
+
source_code.destroy
|
30
|
+
|
31
|
+
session[:source_code] = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def load
|
35
|
+
f = params[:source_code][:file]
|
36
|
+
info = get_file_info(f)
|
37
|
+
if /\Atext\/plain/ =~ info[:type]
|
38
|
+
info[:data] = NKF.nkf('-w', f.read)
|
39
|
+
else
|
40
|
+
info[:error] = 'Rubyのプログラムではありません'
|
41
|
+
end
|
42
|
+
|
43
|
+
render json: { source_code: info }, content_type: request.format
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def source_code_params
|
49
|
+
params.require(:source_code).permit(:data, :filename)
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_file_info(file)
|
53
|
+
{
|
54
|
+
filename: file.original_filename,
|
55
|
+
type: MIME.check(file.path).try(:content_type) || file.content_type,
|
56
|
+
size: file.size,
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
def encode_filename(filename)
|
61
|
+
if request.env['HTTP_USER_AGENT'] =~ /MSIE|Trident/
|
62
|
+
return ERB::Util.url_encode(filename)
|
63
|
+
else
|
64
|
+
filename
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'tempfile'
|
4
|
+
require 'open3'
|
5
|
+
require 'digest/sha2'
|
6
|
+
|
7
|
+
# ソースコードを表現するモデル
|
8
|
+
class SourceCode < ActiveRecord::Base
|
9
|
+
validates :filename, presence: true
|
10
|
+
validates :data, presence: true, allow_blank: true
|
11
|
+
|
12
|
+
# シンタックスをチェックする
|
13
|
+
def check_syntax
|
14
|
+
_, stderr_str, status = *open3_capture3_ruby_c
|
15
|
+
return [] if status.success?
|
16
|
+
|
17
|
+
stderr_str.lines.each.with_object([]) { |line, res|
|
18
|
+
if (md = /^.*:(\d+): (.*)$/.match(line))
|
19
|
+
res << { row: md[1].to_i, column: 0, message: md[2] }
|
20
|
+
elsif (md = /( +)\^$/.match(line))
|
21
|
+
res[-1][:column] = md[1].length
|
22
|
+
end
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
# ハッシュ値を計算する
|
27
|
+
def digest
|
28
|
+
Digest::SHA256.hexdigest(data)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def open3_capture3_ruby_c
|
34
|
+
tempfile = Tempfile.new('smalruby-editor')
|
35
|
+
tempfile.write(data)
|
36
|
+
path = tempfile.path
|
37
|
+
tempfile.close
|
38
|
+
ruby_cmd = File.join(RbConfig::CONFIG['bindir'],
|
39
|
+
RbConfig::CONFIG['RUBY_INSTALL_NAME'])
|
40
|
+
Open3.capture3("#{ruby_cmd} -c #{path}")
|
41
|
+
end
|
42
|
+
end
|
@@ -4,11 +4,13 @@
|
|
4
4
|
<li class="active"><a id="ruby-tab" href="#">Ruby</a></li>
|
5
5
|
</ul>
|
6
6
|
|
7
|
-
<%= form_tag(
|
7
|
+
<%= form_tag(source_codes_load_path, id: "file-form", class: "navbar-form pull-right", method: "post", multipart: true) do %>
|
8
|
+
<button id="check-button" type="button" class="btn btn-primary">チェック</button>
|
8
9
|
<input id="filename" type="text" class="span4" placeholder="プログラムの名前を入れてね(例:01.rb)">
|
9
10
|
<button id="save-button" type="button" class="btn btn-primary">セーブ</button>
|
10
|
-
|
11
|
-
<
|
11
|
+
<%= link_to '', source_codes_download_path, id: 'download-link', style: 'display: none', 'data-method' => 'delete' %>
|
12
|
+
<button id="load-button" class="btn btn-primary">ロード</button>
|
13
|
+
<input id="load-file" type="file" name="source_code[file]" style="display: none">
|
12
14
|
<% end %>
|
13
15
|
</div>
|
14
16
|
</div>
|
data/bin/smalruby-editor
CHANGED
@@ -17,6 +17,7 @@ require 'smalruby_editor'
|
|
17
17
|
Dir.chdir(File.expand_path('../../', APP_PATH))
|
18
18
|
require 'rails/commands/server'
|
19
19
|
|
20
|
+
# rubocop:disable all
|
20
21
|
module Rails
|
21
22
|
class Server < ::Rack::Server
|
22
23
|
def start
|
@@ -35,6 +36,15 @@ module Rails
|
|
35
36
|
console.level = Rails.logger.level
|
36
37
|
|
37
38
|
Rails.logger.extend(ActiveSupport::Logger.broadcast(console))
|
39
|
+
|
40
|
+
if ActiveRecord::Migrator.needs_migration?
|
41
|
+
ActiveRecord::Migration.verbose = true
|
42
|
+
begin
|
43
|
+
ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths)
|
44
|
+
ensure
|
45
|
+
ActiveRecord::Migration.verbose = false
|
46
|
+
end
|
47
|
+
end
|
38
48
|
end
|
39
49
|
|
40
50
|
uri = "http://localhost:#{options[:Port]}"
|
@@ -71,3 +81,4 @@ Rails::Server.new.tap do |server|
|
|
71
81
|
Dir.chdir(Rails.application.root)
|
72
82
|
server.start
|
73
83
|
end
|
84
|
+
# rubocop:enable all
|