1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-08-02 15:57:31 +00:00

[file view/edit]rewrite with codemirror

This commit is contained in:
llj 2012-09-13 16:36:23 +08:00
parent 38eed0ca61
commit 51aa529071
11 changed files with 314 additions and 131 deletions

View File

@ -0,0 +1,172 @@
.CodeMirror {
font-size:14px;
line-height: 1.5em;
font-family: monospace;
/* Necessary so the scrollbar can be absolutely positioned within the wrapper on Lion. */
position: relative;
/* This prevents unwanted scrollbars from showing up on the body and wrapper in IE. */
overflow: hidden;
}
.CodeMirror-scroll {
min-height:300px;
/* This is needed to prevent an IE[67] bug where the scrolled content
is visible outside of the scrolling box. */
position: relative;
outline: none;
overflow-x:auto;
overflow-y:hidden;
}
/* Vertical scrollbar */
.CodeMirror-scrollbar {
position: absolute;
right: 0; top: 0;
overflow-x: hidden;
overflow-y: scroll;
z-index: 5;
}
.CodeMirror-scrollbar-inner {
/* This needs to have a nonzero width in order for the scrollbar to appear
in Firefox and IE9. */
width: 1px;
}
.CodeMirror-scrollbar.cm-sb-overlap {
/* Ensure that the scrollbar appears in Lion, and that it overlaps the content
rather than sitting to the right of it. */
position: absolute;
z-index: 1;
float: none;
right: 0;
min-width: 12px;
}
.CodeMirror-scrollbar.cm-sb-nonoverlap {
min-width: 12px;
}
.CodeMirror-scrollbar.cm-sb-ie7 {
min-width: 18px;
}
.CodeMirror-gutter {
position: absolute; left: 0; top: 0;
z-index: 10;
background-color: #ebebeb;
border-right: 1px solid #eee;
min-width: 2em;
height: 100%;
}
.CodeMirror-gutter-text {
color: #666;
text-align: right;
padding: .4em .7em;
white-space: pre !important;
cursor: default;
}
.CodeMirror-lines {
padding: .4em;
white-space: pre;
cursor: text;
}
.CodeMirror pre {
-moz-border-radius: 0;
-webkit-border-radius: 0;
-o-border-radius: 0;
border-radius: 0;
border-width: 0; margin: 0; padding: 0; background: transparent;
font-family: inherit;
font-size: inherit;
padding: 0; margin: 0;
white-space: pre;
word-wrap: normal;
line-height: inherit;
color: inherit;
}
.CodeMirror-wrap pre {
word-wrap: break-word;
white-space: pre-wrap;
word-break: normal;
}
.CodeMirror-wrap .CodeMirror-scroll {
overflow-x: hidden;
}
.CodeMirror textarea {
outline: none !important;
}
.CodeMirror pre.CodeMirror-cursor {
z-index: 10;
position: absolute;
visibility: hidden;
border-left: 1px solid black;
border-right: none;
width: 0;
}
.cm-keymap-fat-cursor pre.CodeMirror-cursor {
width: auto;
border: 0;
background: transparent;
background: rgba(0, 200, 0, .4);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6600c800, endColorstr=#4c00c800);
}
/* Kludge to turn off filter in ie9+, which also accepts rgba */
.cm-keymap-fat-cursor pre.CodeMirror-cursor:not(#nonsense_id) {
filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
}
.CodeMirror pre.CodeMirror-cursor.CodeMirror-overwrite {}
.CodeMirror-focused pre.CodeMirror-cursor {
visibility: hidden;
}
div.CodeMirror-selected { background: #d9d9d9; }
.CodeMirror-focused div.CodeMirror-selected { background: #d7d4f0; }
.CodeMirror-searching {
background: #ffa;
background: rgba(255, 255, 0, .4);
}
/* Default theme */
.cm-s-default span.cm-keyword {color: #708;}
.cm-s-default span.cm-atom {color: #219;}
.cm-s-default span.cm-number {color: #164;}
.cm-s-default span.cm-def {color: #00f;}
.cm-s-default span.cm-variable {color: black;}
.cm-s-default span.cm-variable-2 {color: #05a;}
.cm-s-default span.cm-variable-3 {color: #085;}
.cm-s-default span.cm-property {color: black;}
.cm-s-default span.cm-operator {color: black;}
.cm-s-default span.cm-comment {color: #a50;}
.cm-s-default span.cm-string {color: #a11;}
.cm-s-default span.cm-string-2 {color: #f50;}
.cm-s-default span.cm-meta {color: #555;}
.cm-s-default span.cm-error {color: #f00;}
.cm-s-default span.cm-qualifier {color: #555;}
.cm-s-default span.cm-builtin {color: #30a;}
.cm-s-default span.cm-bracket {color: #cc7;}
.cm-s-default span.cm-tag {color: #170;}
.cm-s-default span.cm-attribute {color: #00c;}
.cm-s-default span.cm-header {color: blue;}
.cm-s-default span.cm-quote {color: #090;}
.cm-s-default span.cm-hr {color: #999;}
.cm-s-default span.cm-link {color: #00c;}
span.cm-header, span.cm-strong {font-weight: bold;}
span.cm-em {font-style: italic;}
span.cm-emstrong {font-style: italic; font-weight: bold;}
span.cm-link {text-decoration: underline;}
span.cm-invalidchar {color: #f00;}
div.CodeMirror span.CodeMirror-matchingbracket {color: #0f0;}
div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #f22;}
@media print {
/* Hide the cursor when printing */
.CodeMirror pre.CodeMirror-cursor {
visibility: hidden;
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,28 @@
/* Based on Sublime Text's Monokai theme */
.cm-s-monokai {background: #272822; color: #f8f8f2;}
.cm-s-monokai div.CodeMirror-selected {background: #49483E !important;}
.cm-s-monokai .CodeMirror-gutter {background: #333; border-right: 0px;}
.cm-s-monokai .CodeMirror-gutter-text {color: #d0d0d0;}
.cm-s-monokai .CodeMirror-cursor {border-left: 1px solid #f8f8f0 !important;}
.cm-s-monokai span.cm-comment {color: #75715e;}
.cm-s-monokai span.cm-atom {color: #ae81ff;}
.cm-s-monokai span.cm-number {color: #ae81ff;}
.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute {color: #a6e22e;}
.cm-s-monokai span.cm-keyword {color: #f92672;}
.cm-s-monokai span.cm-string {color: #e6db74;}
.cm-s-monokai span.cm-variable {color: #a6e22e;}
.cm-s-monokai span.cm-variable-2 {color: #9effff;}
.cm-s-monokai span.cm-def {color: #fd971f;}
.cm-s-monokai span.cm-error {background: #f92672; color: #f8f8f0;}
.cm-s-monokai span.cm-bracket {color: #f8f8f2;}
.cm-s-monokai span.cm-tag {color: #f92672;}
.cm-s-monokai span.cm-link {color: #ae81ff;}
.cm-s-monokai .CodeMirror-matchingbracket {
text-decoration: underline;
color: white !important;
}

View File

@ -1,6 +1,16 @@
{% extends base_template %}
{% load seahub_tags %}
{% block extra_style %}
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}codemirror/codemirror.css" />
<style type="text/css">
.CodeMirror-focused pre.CodeMirror-cursor {
visibility: visible;
}
</style>
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}codemirror/monokai.css" />
{% endblock %}
{% block main_panel %}
<h2>编辑 {{ u_filename }}</h2>
<p class="path">
@ -14,18 +24,19 @@
{% endfor %}
</p>
<div id="file">
<p id="file-fetching-tip">文件内容读取中...</p>
<div id="docu-view" class="hide"></div>
{% if fileext == 'markdown' or fileext == 'md' %}
{% ifnotequal file_content None %}
<textarea id="docu-view" class="hide">{{ file_content|escape }}</textarea>
{% endifnotequal %}
{% if filetype == 'Markdown' %}
<div id="md-view" class="article hide"></div>
{% endif %}
</div>
<div id="op-after-edit" class="w100 ovhd hide">
{% if fileext == 'markdown' or fileext == 'md' %}
{% if filetype == 'Markdown' %}
<div class="fleft">
<button id="file-edit-submit">提交</button>
<button id="source-code" class="hide">原文件</button>
<button id="preview">预览</button>
<button id="source-code-btn" class="hide">原文件</button>
<button id="preview-btn">预览</button>
</div>
{% else %}
<button id="file-edit-submit" class="fleft">提交</button>
@ -35,50 +46,43 @@
{% endblock %}
{% block extra_script %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/ace.js"></script>
<script type="text/javascript" src="{{ MEDIA_URL }}ace/theme-twilight.js"></script>
{% include "snippets/file_view_js.html" %}
{% if fileext == 'markdown' or fileext == 'md' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/mode-markdown.js"></script>
<script type="text/javascript" src="{{MEDIA_URL}}codemirror/codemirror.js"></script>
{% if filetype == 'Markdown' %}
<script type="text/javascript" src="{{MEDIA_URL}}js/showdown.js"></script>
{% endif %}
<script type="text/javascript">
{% ifnotequal file_content None %}
if ($.browser.msie) {
$('#file').before('<p class="error">下面的编辑器在 IE 下对中文输入的支持不是很好。如果您需要输入中文,请使用 chrome 或 firefox .</p>');
}
var editor = ace.edit("docu-view");
editor.setShowPrintMargin(false); // rm the vertical line in the center
editor.renderer.scrollBar.element.style.display = "none"; // hide right scrollbar
editor.renderer.scrollBar.width = 0; // enlarge ace_content width
editor.setTheme("ace/theme/twilight");
{% include "snippets/editor_set_mode.html" %}
editor.session.getDocument().setValue('{{ file_content|escapejs }}');
editor.session.getDocument().setNewLineMode('{{ newline_mode }}');
$('#docu-view').css({'position': 'relative', 'height': (editor.session.getScreenLength() + 1) * parseInt($('#docu-view').css('line-height')), 'min-height': '400px'}); // '+ 1': offer space for bottom scrollbar
editor.session.setScrollLeft(0); // make bottom scrollbar start from the left-most
editor.resize(); // fix some problem for showing some file in ie8
$('#file-fetching-tip').addClass('hide');
$('#docu-view, #op-after-edit').removeClass('hide');
{% if fileext == 'markdown' or fileext == 'md' %}
$('#file-edit-submit').css('margin-right', '8px');
$('#source-code').click(function() {
$('#md-view, #source-code').addClass('hide');
$('#docu-view, #preview').removeClass('hide');
var editor = CodeMirror.fromTextArea($('#docu-view')[0], {
{% include "snippets/editor_set_mode.html" %}
{% if filetype == 'Markdown' %}
mode: 'markdown',
{% endif %}
theme: 'monokai',
indentUnit: 4,
lineNumbers: true,
autofocus: true
});
$('#preview').click(function() {
var content = editor.session.getValue();
editor.setSize(null, (editor.lineCount() + 1) * parseFloat($('.CodeMirror').css('line-height')));
$('#op-after-edit').removeClass('hide');
{% if filetype == 'Markdown' %}
$('#file-edit-submit').css('margin-right', '8px');
$('#source-code-btn').click(function() {
$('#md-view, #source-code-btn').addClass('hide');
$('.CodeMirror, #preview-btn').removeClass('hide');
editor.focus();
});
$('#preview-btn').click(function() {
var content = editor.getValue();
var converter = new Showdown.converter();
$('#docu-view, #preview').addClass('hide');
$('.CodeMirror, #preview-btn').addClass('hide');
$('#md-view').html(converter.makeHtml(content)).removeClass('hide');
$('#md-view').children(':first').css('margin-top', '0');
$('#source-code').removeClass('hide');
$('#source-code-btn').removeClass('hide');
});
{% endif %}
$('#file-edit-submit').click(function () {
var content = editor.session.getValue();
$.ajax({
type: "POST",
url: '{{ SITE_ROOT }}repo/{{repo.id}}/file/edit/?p={{path|urlencode}}',
@ -86,7 +90,7 @@ $('#file-edit-submit').click(function () {
cache: false,
contentType: 'application/json; charset=utf-8',
beforeSend: prepareCSRFToken,
data: {content: content, encoding: '{{ encoding }}'},
data: {content: editor.getValue(), encoding: '{{ encoding }}'},
success: function(data) {
location.href = $('#file-edit-cancel').attr('data');
},

View File

@ -2,6 +2,10 @@
{% load seahub_tags avatar_tags%}
{% load url from future %}
{% block extra_style %}
<link rel="stylesheet" type="text/css" href="{{ MEDIA_URL }}codemirror/codemirror.css" />
{% endblock %}
{% block main_panel %}
{% if messages %}
{% autoescape off %}
@ -60,7 +64,13 @@
{% endif %}
</div>
<div id="file-view">
{% if filetype == 'Text' %}
{% ifnotequal file_content None %}
<textarea id="docu-view" class="vh">{{ file_content|escape }}</textarea>
{% endifnotequal %}
{% else %}
<p>文件内容读取中...</p>
{% endif %}
</div>
</div>

View File

@ -1,36 +1,42 @@
{% if fileext = 'html' or fileext == 'xhtml' or fileext == 'htm' %}
editor.session.setMode('ace/mode/html');
{% endif %}
{% if fileext = 'css' %}
editor.session.setMode('ace/mode/css');
{% endif %}
{% if fileext = 'java' %}
editor.session.setMode('ace/mode/java');
{% endif %}
{% if fileext = 'js' %}
editor.session.setMode('ace/mode/javascript');
{% endif %}
{% if fileext = 'c' or fileext == 'cpp' or fileext == 'cc' %}
editor.session.setMode('ace/mode/c_cpp');
{% endif %}
{% if fileext = 'tex' %}
editor.session.setMode('ace/mode/latex');
{% endif %}
{% if fileext = 'pl' %}
editor.session.setMode('ace/mode/perl');
{% endif %}
{% if fileext = 'php' %}
editor.session.setMode('ace/mode/php');
{% endif %}
{% if fileext = 'py' %}
editor.session.setMode('ace/mode/python');
{% endif %}
{% if fileext = 'rb' %}
editor.session.setMode('ace/mode/ruby');
{% endif %}
{% if fileext = 'sh' %}
editor.session.setMode('ace/mode/sh');
{% endif %}
{% if fileext = 'xml' %}
editor.session.setMode('ace/mode/xml');
{% endif %}
{% if fileext == 'c' %}
mode: 'text/x-csrc',
{% endif %}
{% if fileext == 'cpp' or fileext == 'cc' %}
mode: 'text/x-c++src',
{% endif %}
{% if fileext == 'cs' %}
mode: 'text/x-csharp',
{% endif %}
{% if fileext == 'java' %}
mode: 'text/x-java',
{% endif %}
{% if fileext == 'css' %}
mode: 'CSS',
{% endif %}
{% if fileext == 'html' or fileext == 'xhtml' or fileext == 'htm' %}
mode: 'htmlmixed',
{% endif %}
{% if fileext == 'js' %}
mode: 'javascript',
{% endif %}
{% if fileext == 'pl' %}
mode: 'perl',
{% endif %}
{% if fileext == 'php' %}
mode: 'php',
{% endif %}
{% if fileext == 'py' %}
mode: 'python',
{% endif %}
{% if fileext == 'rb' %}
mode: 'ruby',
{% endif %}
{% if fileext == 'sh' %}
mode: 'shell',
{% endif %}
{% if fileext == 'txt' or fileext == 'text' %}
mode: null,
{% endif %}
{% if fileext == 'xml' %}
mode: 'xml',
{% endif %}

View File

@ -1,44 +1,5 @@
{% if filetype == 'Text' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/ace.js"></script>
<script type="text/javascript" src="{{MEDIA_URL}}ace/theme-chrome.js"></script>
{% if fileext == 'html' or fileext == 'xhtml' or fileext == 'htm' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/mode-html.js"></script>
{% endif %}
{% if fileext == 'css' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/mode-css.js"></script>
<script type="text/javascript" src="{{MEDIA_URL}}ace/worker-css.js"></script>
{% endif %}
{% if fileext == 'java' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/mode-java.js"></script>
{% endif %}
{% if fileext == 'js' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/mode-javascript.js"></script>
<script type="text/javascript" src="{{MEDIA_URL}}ace/worker-javascript.js"></script>
{% endif %}
{% if fileext == 'c' or fileext == 'cpp' or fileext == 'cc' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/mode-c_cpp.js"></script>
{% endif %}
{% if fileext == 'tex' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/mode-latex.js"></script>
{% endif %}
{% if fileext == 'pl' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/mode-perl.js"></script>
{% endif %}
{% if fileext == 'php' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/mode-php.js"></script>
{% endif %}
{% if fileext == 'py' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/mode-python.js"></script>
{% endif %}
{% if fileext == 'rb' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/mode-ruby.js"></script>
{% endif %}
{% if fileext == 'sh' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/mode-sh.js"></script>
{% endif %}
{% if fileext == 'xml' %}
<script type="text/javascript" src="{{MEDIA_URL}}ace/mode-xml.js"></script>
{% endif %}
<script type="text/javascript" src="{{MEDIA_URL}}codemirror/codemirror.js"></script>
{% endif %}
{% if filetype == 'PDF' %}
<script type="text/javascript" src="{{MEDIA_URL}}js/pdf.js"></script>

View File

@ -1,20 +1,14 @@
{% if filetype == 'Text' %}
{% ifnotequal file_content None %}
$('#file-view').html('<div id="docu-view" class="vh">' + '</div>');
var editor = ace.edit("docu-view");
$('#docu-view').removeClass('vh');
editor.setReadOnly(true);
editor.setHighlightActiveLine(false);
$('#docu-view .ace_cursor-layer').hide(); // rm cursor
editor.setShowPrintMargin(false); // rm the vertical line in the center
editor.renderer.scrollBar.element.style.display = "none"; // hide right scrollbar
editor.renderer.scrollBar.width = 0; // enlarge ace_content width
editor.setTheme("ace/theme/chrome");
{% include "snippets/editor_set_mode.html" %}
editor.session.getDocument().setValue('{{ file_content|escapejs }}');
$('#docu-view').css({'position': 'relative', 'height': (editor.session.getScreenLength() + 1) * parseInt($('#docu-view').css('line-height'))}); // '+ 1': offer space for bottom scrollbar
editor.session.setScrollLeft(0); // make bottom scrollbar start from the left-most
editor.resize(); // fix some problem for showing some file in ie8
$('#file-view').css('background', '#fff');
var editor = CodeMirror.fromTextArea($('#docu-view')[0], {
{% include 'snippets/editor_set_mode.html' %}
theme: 'default',
indentUnit: 4,
lineNumbers: true,
readOnly: true
});
editor.setSize(null, (editor.lineCount() + 1) * parseFloat($('.CodeMirror').css('line-height')));
{% endifnotequal %}
{% if err %}

View File

@ -10,7 +10,13 @@
<button data="{{ SITE_ROOT }}repo/{{ repo.id }}/{{ obj_id }}/?file_name={{ file_name }}&op=download&t={{ shared_token }}" id="download">下载</button>
</div>
<div id="file-view">
{% if filetype == 'Text' %}
{% ifnotequal file_content None %}
<textarea id="docu-view" class="vh">{{ file_content|escape }}</textarea>
{% endifnotequal %}
{% else %}
<p>文件内容读取中...</p>
{% endif %}
</div>
</div>
{% endblock %}

View File

@ -29,7 +29,7 @@ EMPTY_SHA1 = '0000000000000000000000000000000000000000'
MAX_INT = 2147483647
PREVIEW_FILEEXT = {
'Text': ('ac', 'am', 'bat', 'c', 'cc', 'cmake', 'cpp', 'css', 'diff', 'el', 'h', 'html', 'htm', 'java', 'js', 'json', 'less', 'make', 'org', 'php', 'pl', 'properties', 'py', 'rb', 'scala', 'script', 'sh', 'sql', 'txt', 'text', 'tex', 'vi', 'vim', 'xhtml', 'xml'),
'Text': ('ac', 'am', 'bat', 'c', 'cc', 'cmake', 'cpp', 'cs', 'css', 'diff', 'el', 'h', 'html', 'htm', 'java', 'js', 'json', 'less', 'make', 'org', 'php', 'pl', 'properties', 'py', 'rb', 'scala', 'script', 'sh', 'sql', 'txt', 'text', 'tex', 'vi', 'vim', 'xhtml', 'xml'),
'Image': ('gif', 'jpeg', 'jpg', 'png'),
'Document': ('doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx'),
'SVG': ('svg',),

View File

@ -1097,6 +1097,7 @@ def repo_file_edit(request, repo_id):
'u_filename':u_filename,
'path':path,
'zipped':zipped,
'filetype':filetype,
'fileext':fileext,
'err':err,
'file_content':file_content,