diff --git a/app.rb b/app.rb
index 86f25003..b13d47c0 100644
--- a/app.rb
+++ b/app.rb
@@ -148,6 +148,30 @@ post '/site_files/delete' do
redirect '/dashboard'
end
+get '/site_files/text_editor/:filename' do |filename|
+ @file_url = "http://#{current_site.username}.neocities.org/#{filename}"
+
+ slim :'site_files/text_editor'
+end
+
+post '/site_files/save/:filename' do |filename|
+ tmpfile = Tempfile.new 'neocities_saving_file'
+
+ if (tmpfile.size + current_site.total_space) > Site::MAX_SPACE
+ halt 'File is too large, it has NOT been saved. Please make a local copy and then try to reduce the size.'
+ end
+
+ tmpfile.write request.body.read
+ tmpfile.close
+
+ sanitized_filename = filename.gsub(/[^a-zA-Z_\-.]/, '')
+ dest_path = File.join site_base_path(current_site.username), sanitized_filename
+
+ FileUtils.mv tmpfile.path, dest_path
+ File.chmod(0640, dest_path) if self.class.production?
+ 'ok'
+end
+
get '/terms' do
slim :'terms'
end
diff --git a/public/css/styles.css b/public/css/styles.css
index 66648d07..b896ff3f 100644
--- a/public/css/styles.css
+++ b/public/css/styles.css
@@ -17,4 +17,8 @@ textarea, input[type="text"], input[type="password"], input[type="datetime"], in
#file_criteria li {
padding-bottom: 20px;
+}
+
+select, textarea, input[type="text"], input[type="password"], input[type="datetime"], input[type="datetime-local"], input[type="date"], input[type="month"], input[type="time"], input[type="week"], input[type="number"], input[type="email"], input[type="url"], input[type="search"], input[type="tel"], input[type="color"], .uneditable-input {
+ color: #000000;
}
\ No newline at end of file
diff --git a/views/dashboard.slim b/views/dashboard.slim
index f91d056c..29101621 100644
--- a/views/dashboard.slim
+++ b/views/dashboard.slim
@@ -34,7 +34,7 @@ javascript:
a href="#" Edit with visual editor not implemented yet.. ETA one week
span
i class="icon-edit"
- a href="#" Edit with text editor not implemented yet.. ETA one day
+ a href="/site_files/text_editor/#{file.filename}" Edit with text editor not implemented yet.. ETA one day
span
i class="icon-trash"
a href="#" onclick="confirmFileDelete('#{file.filename}')" Delete
diff --git a/views/layout.slim b/views/layout.slim
index 651ec080..50c3d700 100644
--- a/views/layout.slim
+++ b/views/layout.slim
@@ -9,6 +9,7 @@ html
link href="/css/styles.css" rel="stylesheet"
meta property="og:title" content="NeoCities"
meta property="og:description" content="NeoCities is the new Geocities. Create your own free home page, and do whatever you want with it."
+ script src="/js/jquery.min.js"
body
a id="top"
@@ -33,5 +34,4 @@ html
container
== yield
- script src="/js/jquery.min.js"
script src="/js/bootstrap.min.js"
diff --git a/views/site_files/text_editor.slim b/views/site_files/text_editor.slim
new file mode 100644
index 00000000..f7657e2b
--- /dev/null
+++ b/views/site_files/text_editor.slim
@@ -0,0 +1,115 @@
+css:
+ #editor {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ }
+
+.row
+ .span6.offset3
+ div id="editorUpdates" class="alert alert-success hidden"
+ button type="button" class="close" onclick="$('#editorUpdates').addClass('hidden');" ×
+ span
+.row
+ .span6
+ font style="font-size: 27pt" Editing #{params[:filename]}
+ .span6
+ span.pull-right
+ | Theme:
+ select id="theme" size="1" onchange="setTheme();" onkeyup="setTheme();"
+ optgroup label="Bright"
+ option value="ace/theme/chrome" Chrome
+ option value="ace/theme/clouds" Clouds
+ option value="ace/theme/crimson_editor" Crimson Editor
+ option value="ace/theme/dawn" Dawn
+ option value="ace/theme/dreamweaver" Dreamweaver
+ option value="ace/theme/eclipse" Eclipse
+ option value="ace/theme/github" GitHub
+ option value="ace/theme/solarized_light" Solarized Light
+ option value="ace/theme/textmate" TextMate
+ option value="ace/theme/tomorrow" Tomorrow
+ option value="ace/theme/xcode" XCode
+ optgroup label="Dark"
+ option value="ace/theme/ambiance" Ambiance
+ option value="ace/theme/chaos" Chaos
+ option value="ace/theme/clouds_midnight" Clouds Midnight
+ option value="ace/theme/cobalt" Cobalt
+ option value="ace/theme/idle_fingers" idleFingers
+ option value="ace/theme/kr_theme" krTheme
+ option value="ace/theme/merbivore" Merbivore
+ option value="ace/theme/merbivore_soft" Merbivore Soft
+ option value="ace/theme/mono_industrial" Mono Industrial
+ option value="ace/theme/monokai" Monokai
+ option value="ace/theme/pastel_on_dark" Pastel on dark
+ option value="ace/theme/solarized_dark" selected="selected" Solarized Dark
+ option value="ace/theme/terminal" Terminal
+ option value="ace/theme/tomorrow_night" Tomorrow Night
+ option value="ace/theme/tomorrow_night_blue" Tomorrow Night Blue
+ option value="ace/theme/tomorrow_night_bright" Tomorrow Night Bright
+ option value="ace/theme/tomorrow_night_eighties" Tomorrow Night 80s
+ option value="ace/theme/twilight" Twilight
+ option value="ace/theme/vibrant_ink" Vibrant Ink
+
+.row
+ .span12
+ div id="editor" style="width: 100%; height: 1000px; position: relative;"
+ p Loading, please wait..
+
+.row.text-center style="margin-top: 10px"
+ .span4
+ a.btn.btn-large.btn-warning href="" Finish Without Saving
+ .span4
+ a.btn.btn-large.btn-success href="#" onclick="saveTextFile()" Save Changes
+ .span4
+ a.btn.btn-large.btn-info href="" Save and Finish
+
+
+script src="http://rawgithub.com/ajaxorg/ace-builds/master/src-noconflict/ace.js" type="text/javascript" charset="utf-8"
+javascript:
+
+ function setTheme(name) {
+ editor.setTheme($('#theme').val());
+ }
+
+ function saveTextFile() {
+ /*
+ $.post('/site_files/save/#{params[:filename]}', editor.getValue(), function(resp) {
+ if(resp == 'ok') {
+ $('#editorUpdates span').text('Your file has been saved.');
+ $('#editorUpdates').removeClass('hidden');
+ }
+ });
+ */
+
+ $.ajax({
+ url: '/site_files/save/#{params[:filename]}',
+ data: editor.getValue(),
+ processData: false,
+ contentType: false,
+ type: 'POST',
+ success: function(response){
+ if(response == 'ok') {
+ $('#editorUpdates span').text('Your file has been saved.');
+ } else {
+ $('#editorUpdates span').text(response);
+ }
+ $('#editorUpdates').removeClass('hidden');
+ }
+ });
+ }
+
+ var editor = {};
+
+ $(document).ready(function() {
+ $.get("#{@file_url}", function (response) {
+ $("#editor").text(response);
+
+ editor = ace.edit("editor");
+ setTheme();
+ editor.getSession().setMode("ace/mode/html");
+ editor.setFontSize(14);
+ editor.setShowPrintMargin(false);
+ });
+ });