Kaynağa Gözat

Merge pull request #1560 from openNAMU/dev

Dev
잉여개발기 (SPDV) 3 yıl önce
ebeveyn
işleme
18db480408

+ 7 - 3
app.py

@@ -423,6 +423,7 @@ app.route('/history_hidden/<int(signed = True):rev>/<everything:name>')(recent_h
 app.route('/history_send/<int(signed = True):rev>/<everything:name>', methods = ['POST', 'GET'])(recent_history_send)
 app.route('/history_reset/<everything:name>', methods = ['POST', 'GET'])(recent_history_reset)
 app.route('/history_add/<everything:name>', methods = ['POST', 'GET'])(recent_history_add)
+app.route('/history_add_preview/<everything:name>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(recent_history_add)
 
 # Func-view
 app.route('/xref/<everything:name>')(view_xref)
@@ -445,8 +446,10 @@ app.route('/random')(view_random)
 
 # Func-edit
 app.route('/edit/<everything:name>', methods = ['POST', 'GET'])(edit)
-app.route('/edit_from/<everything:name>', methods = ['POST', 'GET'], defaults = { 'do_type' : 'load' })(edit)
+app.route('/edit_preview/<everything:name>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(edit)
+app.route('/edit_from/<everything:name>', defaults = { 'do_type' : 'load' })(edit)
 app.route('/edit_section/<int:section>/<everything:name>', methods = ['POST', 'GET'])(edit)
+app.route('/edit_section_preview/<int:section>/<everything:name>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(edit)
 
 app.route('/upload', methods = ['POST', 'GET'])(edit_upload)
 
@@ -468,6 +471,7 @@ app.route('/recent_discuss/open', defaults = { 'tool' : 'open' })(recent_discuss
 app.route('/recent_discuss/delete')(recent_discuss_delete)
 
 app.route('/thread/<int:topic_num>', methods = ['POST', 'GET'])(topic)
+app.route('/thread_preview/<int:topic_num>', defaults = { 'do_type' : 'preview' }, methods = ['POST'])(topic)
 app.route('/topic/<everything:name>', methods = ['POST', 'GET'])(topic_list)
 
 app.route('/thread/<int:topic_num>/tool')(topic_tool)
@@ -642,9 +646,9 @@ app.route('/setting/phrase', methods = ['POST', 'GET'])(main_func_setting_phrase
 app.route('/setting/head', defaults = { 'num' : 3 }, methods = ['POST', 'GET'])(main_func_setting_head)
 app.route('/setting/head/<skin_name>', defaults = { 'num' : 3 }, methods = ['POST', 'GET'])(main_func_setting_head)
 app.route('/setting/body/top', defaults = { 'num' : 4 }, methods = ['POST', 'GET'])(main_func_setting_head)
-app.route('/setting/body/top/<skin_name>', defaults = { 'num' : 4 }, methods = ['POST', 'GET'])(main_func_setting_head)
+app.route('/setting_preview/body/top', defaults = { 'num' : 4, 'set_preview' : 1 }, methods = ['POST'])(main_func_setting_head)
 app.route('/setting/body/bottom', defaults = { 'num' : 7 }, methods = ['POST', 'GET'])(main_func_setting_head)
-app.route('/setting/body/bottom/<skin_name>', defaults = { 'num' : 7 }, methods = ['POST', 'GET'])(main_func_setting_head)
+app.route('/setting_preview/body/bottom', defaults = { 'num' : 7, 'set_preview' : 1 }, methods = ['POST'])(main_func_setting_head)
 app.route('/setting/robot', methods = ['POST', 'GET'])(main_func_setting_robot)
 app.route('/setting/external', methods = ['POST', 'GET'])(main_func_setting_external)
 app.route('/setting/acl', methods = ['POST', 'GET'])(main_func_setting_acl)

+ 85 - 37
route/edit.py

@@ -19,6 +19,7 @@ def edit(name = 'Test', section = 0, do_type = ''):
         post_ver = flask.request.form.get('ver', '')
         if flask.request.method == 'POST':
             edit_repeat = 'error' if post_ver != doc_ver else 'post'
+            edit_repeat = 'error' if do_type == 'preview' else 'post'
         else:
             edit_repeat = 'get'
         
@@ -113,6 +114,7 @@ def edit(name = 'Test', section = 0, do_type = ''):
             doc_section_edit_apply = 'X'
             data_section = ''
             data_section_where = ''
+            data_preview = ''
 
             if edit_repeat == 'get':
                 if do_type == 'load':
@@ -156,7 +158,7 @@ def edit(name = 'Test', section = 0, do_type = ''):
 
                             if section == count:
                                 data_section_sub = data_section
-                                data_section_sub = re.sub(data_match_re, '.' * len(data_match.group(0)), data_section_sub, 1)
+                                data_section_sub = re.sub(data_match_re, ('.' * (len(data_match.group(0)) - 1)) + '\n', data_section_sub, 1)
 
                                 data_match_plus = re.search(data_match_re, data_section_sub)
                                 if data_match_plus:
@@ -170,27 +172,48 @@ def edit(name = 'Test', section = 0, do_type = ''):
 
                                 break
                             else:
-                                data_section = re.sub(data_match_re, '.' * len(data_match.group(0)), data_section, 1)
+                                data_section = re.sub(data_match_re, ('.' * (len(data_match.group(0)) - 1)) + '\n', data_section, 1)
 
                             count += 1
             else:
                 data = flask.request.form.get('content', '')
-                warning_edit = load_lang('exp_edit_conflict') + ' '
-    
-                if flask.request.form.get('ver', '0') == '0':
-                    warning_edit += '<a href="/raw/' + url_pas(name) + '">(r' + doc_ver + ')</a>'
+                data = data.replace('\r\n', '\n')
+                
+                data_section_where = flask.request.form.get('doc_section_data_where', '')
+                doc_section_edit_apply = flask.request.form.get('doc_section_edit_apply', '')
+
+                doc_ver = flask.request.form.get('ver', '')
+
+                if do_type != 'preview':
+                    warning_edit = load_lang('exp_edit_conflict') + ' '
+        
+                    if flask.request.form.get('ver', '0') == '0':
+                        warning_edit += '<a href="/raw/' + url_pas(name) + '">(r' + doc_ver + ')</a>'
+                    else:
+                        warning_edit += '' + \
+                            '<a href="/diff/' + flask.request.form.get('ver', '1') + '/' + doc_ver + '/' + url_pas(name) + '">' + \
+                                '(r' + doc_ver + ')' + \
+                            '</a>' + \
+                        ''
+        
+                    warning_edit += '<hr class="main_hr">'
+                    editor_top_text = warning_edit + editor_top_text
                 else:
-                    warning_edit += '' + \
-                        '<a href="/diff/' + flask.request.form.get('ver', '1') + '/' + doc_ver + '/' + url_pas(name) + '">' + \
-                            '(r' + doc_ver + ')' + \
-                        '</a>' + \
-                    ''
-    
-                warning_edit += '<hr class="main_hr">'
-                editor_top_text = warning_edit + editor_top_text
+                    data_preview = render_set(
+                        doc_name = name, 
+                        doc_data = data,
+                        data_in = ''
+                    )
 
             if data_section == '':
                 data_section = data
+
+            if section == '':
+                form_action = 'formaction="/edit/' + url_pas(name) + '"'
+                form_action_preview = 'formaction="/edit_preview/' + url_pas(name) + '"'
+            else:
+                form_action = 'formaction="/edit_section/' + str(section) + '/' + url_pas(name) + '"'
+                form_action_preview = 'formaction="/edit_section_preview/' + str(section) + '/' + url_pas(name) + '"'
     
             editor_top_text += '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>'
     
@@ -205,17 +228,8 @@ def edit(name = 'Test', section = 0, do_type = ''):
                 add_get_file = '''
                     <link   rel="stylesheet"
                             data-name="vs/editor/editor.main" 
-                            href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/editor/editor.main.min.css">
-                    <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs/loader.min.js"></script>
-                    <script>
-                        function opennamu_edit_turn_off_monaco() {
-                            do_monaco_to_textarea();
-
-                            document.getElementById('opennamu_js_edit_textarea_view').style.display = 'block';
-                            document.getElementById('opennamu_monaco_editor').style.display = 'none';
-                            document.getElementById('opennamu_monaco_editor').remove();
-                        }
-                    </script>
+                            href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.1/min/vs/editor/editor.main.min.css">
+                    <script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.1/min/vs/loader.min.js"></script>
                 '''
 
                 editor_top_text += ' <a href="javascript:opennamu_edit_turn_off_monaco();">(' + load_lang('turn_off_monaco') + ')</a>'
@@ -226,14 +240,15 @@ def edit(name = 'Test', section = 0, do_type = ''):
                     monaco_thema = ''
                 
                 add_script = '''
-                    require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.20.0/min/vs' }});
+                    require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.1/min/vs' }});
+                    require.config({ 'vs/nls': { availableLanguages: { '*': 'ko' } }});
                     require(["vs/editor/editor.main"], function () {
                         window.editor = monaco.editor.create(document.getElementById('opennamu_monaco_editor'), {
-                            value: document.getElementById('opennamu_js_edit_textarea_view').value,
+                            value: document.getElementById('opennamu_edit_textarea').value,
                             language: 'plaintext',
+                            automaticLayout: true,
                             wordWrap: true,
-                            theme: \'''' + monaco_thema + '''\',
-                            minimap: { enabled: false }
+                            theme: \'''' + monaco_thema + '''\'
                         });
                     });
                 '''
@@ -251,18 +266,34 @@ def edit(name = 'Test', section = 0, do_type = ''):
             return easy_minify(flask.render_template(skin_check(), 
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('edit') + ')' + sub_menu, 0])],
                 data =  editor_top_text + add_get_file + '''
+                    <script>
+                        function opennamu_edit_turn_off_monaco() {
+                            do_monaco_to_textarea();
+                            
+                            document.getElementById('opennamu_edit_textarea').style.display = 'block';
+                            document.getElementById('opennamu_monaco_editor').style.display = 'none';
+                            document.getElementById('opennamu_monaco_editor').remove();
+                        }
+
+                        function do_monaco_to_textarea() {
+                            if(document.getElementById('opennamu_monaco_editor')) {
+                                try {
+                                    document.getElementById('opennamu_edit_textarea').value = window.editor.getValue();
+                                } catch(e) {}
+                            }
+                        }
+                    </script>
                     <form method="post">
-                        <textarea style="display: none;" id="opennamu_js_edit_origin" name="doc_data_org">''' + html.escape(data_section) + '''</textarea>
+                        <textarea style="display: none;" id="opennamu_edit_origin" name="doc_data_org">''' + html.escape(data_section) + '''</textarea>
                         <textarea style="display: none;" name="doc_section_data_where">''' + data_section_where + '''</textarea>
                         <input style="display: none;" name="doc_section_edit_apply" value="''' + doc_section_edit_apply + '''">
 
-                        <textarea style="display: none;" id="opennamu_js_edit_textarea" name="content"></textarea>
                         <input style="display: none;" name="ver" value="''' + doc_ver + '''">
                         
-                        <div>''' + edit_button(monaco_on) + '''</div>
+                        <div>''' + edit_button('opennamu_edit_textarea', 'opennamu_monaco_editor') + '''</div>
                         
                         <div id="opennamu_monaco_editor" class="content" ''' + monaco_display + '''></div>
-                        <textarea id="opennamu_js_edit_textarea_view" ''' + editor_display + ''' class="content" placeholder="''' + p_text + '''">''' + html.escape(data_section) + '''</textarea>
+                        <textarea id="opennamu_edit_textarea" ''' + editor_display + ''' class="content" name="content" placeholder="''' + p_text + '''">''' + html.escape(data_section) + '''</textarea>
                         <hr class="main_hr">
                         
                         <input placeholder="''' + load_lang('why') + '''" name="send">
@@ -270,18 +301,35 @@ def edit(name = 'Test', section = 0, do_type = ''):
                         
                         ''' + captcha_get() + ip_warning() + get_edit_text_bottom_check_box() + get_edit_text_bottom() + '''
                         
-                        <button id="opennamu_js_save" type="submit">''' + load_lang('save') + '''</button>
-                        <button id="opennamu_js_preview" type="button">''' + load_lang('preview') + '''</button>
+                        <button id="opennamu_save_button" type="submit" ''' + form_action + ''' onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_preview_button" type="submit" ''' + form_action_preview + ''' onclick="do_monaco_to_textarea(); do_stop_exit_release();">''' + load_lang('preview') + '''</button>
                     </form>
                     
                     <hr class="main_hr">
-                    <div id="opennamu_js_preview_area"></div>
+                    <div id="opennamu_preview_area">''' + data_preview + '''</div>
                     
                     <script>
+                        function do_stop_exit() {
+                            window.onbeforeunload = function() {
+                                do_monaco_to_textarea();
+
+                                let data = document.getElementById('opennamu_edit_textarea').value;
+                                let origin = document.getElementById('opennamu_edit_origin').value;
+                                if(data !== origin) {
+                                    return '';
+                                }
+                            }
+                        }
+
+                        function do_stop_exit_release() {
+                            window.onbeforeunload = function () {}
+                        }
+
+                        do_stop_exit();
                         do_paste_image();
+
                         ''' + add_script + '''
                     </script>
-                    <!-- JS : edit.js -->
                 ''',
                 menu = [
                     ['w/' + url_pas(name), load_lang('return')],

+ 1 - 1
route/edit_upload.py

@@ -152,7 +152,7 @@ def edit_upload():
                         <textarea rows="10" placeholder="''' + load_lang('other') + '''" name="f_lice">''' + upload_default + '''</textarea>
                         <hr class="main_hr">
                         ''' + captcha_get() + '''
-                        <button id="opennamu_js_save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 ''',
                 menu = [['other', load_lang('return')]]

+ 1 - 1
route/filter_inter_wiki.py

@@ -63,7 +63,7 @@ def filter_inter_wiki(tool):
             div += '</td>'
 
             if tool == 'inter_wiki':
-                div += '<td><a class="opennamuLinkOut" href="' + html.escape(data[1]) + '">' + html.escape(data[1]) + '</a></td>'
+                div += '<td><a class="opennamu_link_out" href="' + html.escape(data[1]) + '">' + html.escape(data[1]) + '</a></td>'
             else:
                 div += '<td>' + html.escape(data[1]) + '</td>'
 

+ 1 - 1
route/main_func_setting_acl.py

@@ -97,7 +97,7 @@ def main_func_setting_acl():
                         <select ''' + disable + ''' name="vote_acl">''' + acl_div[5] + '''</select>
                         <hr class="main_hr">
                         
-                        <button id="opennamu_js_save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 ''',
                 menu = [['setting', load_lang('return')]]

+ 1 - 1
route/main_func_setting_external.py

@@ -137,7 +137,7 @@ def main_func_setting_external():
                         <hr class="main_hr">
 
                         <hr class="main_hr">
-                        <button id="opennamu_js_save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                     <!-- JS : opennamu_do_render_simple -->
                 ''',

+ 19 - 11
route/main_func_setting_head.py

@@ -1,13 +1,13 @@
 from .tool.func import *
 
-def main_func_setting_head(num, skin_name = ''):
+def main_func_setting_head(num, skin_name = '', set_preview = 0):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
         if admin_check() != 1:
             return re_error('/ban')
         
-        if flask.request.method == 'POST':
+        if flask.request.method == 'POST' and set_preview == 0:
             if num == 4:
                 info_d = 'body'
                 end_r = 'body/top'
@@ -47,19 +47,23 @@ def main_func_setting_head(num, skin_name = ''):
                 curs.execute(db_change("select data from other where name = 'body'"))
                 title = '_body'
                 start = ''
+                form_action = 'formaction="/setting/body/top"'
+                data_preview = flask.request.form.get('content', '') if set_preview == 1 else ''
                 plus = '''
-                    <button id="opennamu_js_preview" type="button" onclick="load_raw_preview(\'content\', \'opennamu_js_preview_area\')">''' + load_lang('preview') + '''</button>
+                    <button id="opennamu_preview_button" type="submit" formaction="/setting_preview/body/top">''' + load_lang('preview') + '''</button>
                     <hr class="main_hr">
-                    <div id="opennamu_js_preview_area"></div>
+                    <div id="opennamu_preview_area">''' + data_preview + '''</div>
                 '''
             elif num == 7:
                 curs.execute(db_change("select data from other where name = 'bottom_body'"))
                 title = '_bottom_body'
                 start = ''
+                data_preview = flask.request.form.get('content', '') if set_preview == 1 else ''
+                form_action = 'formaction="/setting/body/bottom"'
                 plus = '''
-                    <button id="opennamu_js_preview" type="button" onclick="load_raw_preview(\'content\', \'opennamu_js_preview_area\')">''' + load_lang('preview') + '''</button>
+                    <button id="opennamu_preview_button" type="submit" formaction="/setting_preview/body/bottom">''' + load_lang('preview') + '''</button>
                     <hr class="main_hr">
-                    <div id="opennamu_js_preview_area"></div>
+                    <div id="opennamu_preview_area">''' + data_preview + '''</div>
                 '''
             else:
                 curs.execute(db_change("select data from other where name = 'head' and coverage = ?"), [skin_name])
@@ -75,13 +79,17 @@ def main_func_setting_head(num, skin_name = ''):
                     </span>
                     <hr class="main_hr">
                 '''
+                form_action = ''
                 plus = ''
 
-            head = curs.fetchall()
-            if head:
-                data = head[0][0]
+            if set_preview == 1:
+                data = data_preview
             else:
-                data = ''
+                head = curs.fetchall()
+                if head:
+                    data = head[0][0]
+                else:
+                    data = ''
 
             if skin_name != '':
                 sub_plus = ' (' + skin_name + ')'
@@ -96,7 +104,7 @@ def main_func_setting_head(num, skin_name = ''):
                         <textarea rows="25" placeholder="''' + load_lang('enter_html') + '''" name="content" id="content">''' + html.escape(data) + '''</textarea>
                         <hr class="main_hr">
                         ''' + (load_lang('main_css_warning') + '<hr class="main_hr">' if title == '_head' else '') + '''
-                        <button id="opennamu_js_save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit" ''' + form_action + '''>''' + load_lang('save') + '''</button>
                         ''' + plus + '''
                     </form>
                 ''',

+ 1 - 1
route/main_func_setting_main.py

@@ -258,7 +258,7 @@ def main_func_setting_main(db_set):
                         <input type="checkbox" name="history_recording_off" ''' + check_box_div[9] + '''> ''' + load_lang('set_history_recording_off') + ''' (''' + load_lang('beta') + ''')
                         <hr class="main_hr">
 
-                        <button id="opennamu_js_save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                     <!-- JS : opennamu_do_render_simple -->
                 ''',

+ 1 - 1
route/main_func_setting_main_logo.py

@@ -53,7 +53,7 @@ def main_func_setting_main_logo():
                 data = '''
                     <form method="post">
                         ''' + end_data + '''
-                        <button id="opennamu_js_save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 ''',
                 menu = [['setting/main', load_lang('return')]]

+ 1 - 1
route/main_func_setting_phrase.py

@@ -127,7 +127,7 @@ def main_func_setting_phrase():
                         <textarea rows="3" name="''' + i_list[20] + '''">''' + html.escape(d_list[20]) + '''</textarea>
 
                         <hr class="main_hr">
-                        <button id="opennamu_js_save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                     <ul id="footnote_data">
                         <li>

+ 1 - 1
route/main_func_setting_robot.py

@@ -48,7 +48,7 @@ def main_func_setting_robot():
                         <hr class="main_hr">
                         <input type="checkbox" name="default" ''' + default_data + '''> ''' + load_lang('default') + '''
                         <hr class="main_hr">
-                        <button id="opennamu_js_save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 ''',
                 menu = [['setting', load_lang('return')]]

+ 1 - 1
route/main_func_setting_sitemap.py

@@ -109,7 +109,7 @@ def main_func_setting_sitemap():
                         <input type="checkbox" name="exclude_category_page"> ''' + load_lang('stiemap_exclude_category_page') + '''
                         <hr class="main_hr">
 
-                        <button id="opennamu_js_save" type="submit">''' + load_lang('create') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('create') + '''</button>
                     </form>
                 ''',
                 menu = [['setting', load_lang('return')]]

+ 1 - 1
route/recent_app_submit.py

@@ -69,7 +69,7 @@ def recent_app_submit_2():
                             <tr>
                                 <td colspan="3">
                                     <button type="submit" 
-                                            id="opennamu_js_save"
+                                            id="opennamu_save_button"
                                             name="approve" 
                                             value="''' + application['id'] + '''">
                                         ''' + load_lang('approve') + '''

+ 27 - 13
route/recent_history_add.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def recent_history_add(name = 'Test'):
+def recent_history_add(name = 'Test', do_type = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
@@ -8,7 +8,7 @@ def recent_history_add(name = 'Test'):
         if admin_check() != 1:
             return re_error('/ban')
 
-        if flask.request.method == 'POST':
+        if flask.request.method == 'POST' and do_type == '':
             admin_check(None, 'history_add (' + name + ')')
 
             today = get_time()
@@ -33,31 +33,45 @@ def recent_history_add(name = 'Test'):
             curs.execute(db_change('select data from other where name = "edit_help"'))
             sql_d = curs.fetchall()
             p_text = html.escape(sql_d[0][0]) if sql_d and sql_d[0][0] != '' else load_lang('default_edit_help')
+
+            send = ''
+            get_ip = ''
+            data = ''
+            data_preview = ''
+            if do_type == 'preview':
+                data = flask.request.form.get('content', '')
+                data = data.replace('\r\n', '\n')
+
+                send = flask.request.form.get('send', '')
+                get_ip = flask.request.form.get('get_ip', '')
+
+                data_preview = render_set(
+                    doc_name = name, 
+                    doc_data = data,
+                    data_in = ''
+                )
             
             return easy_minify(flask.render_template(skin_check(),
                 imp = [load_lang('history_add'), wiki_set(), wiki_custom(), wiki_css(['(' + name + ')', 0])],
                 data = '''
-                    <form method="post">
-                        <textarea style="display: none;" id="opennamu_js_edit_origin"></textarea>
-                        <textarea style="display: none;" id="opennamu_js_edit_textarea" name="content"></textarea>
-                        
-                        <div>''' + edit_button() + '''</div>
+                    <form method="post">                        
+                        <div>''' + edit_button('opennamu_edit_textarea') + '''</div>
                         
-                        <textarea id="opennamu_js_edit_textarea_view" class="content" placeholder="''' + p_text + '''"></textarea>
+                        <textarea id="opennamu_edit_textarea" class="content" name="content" placeholder="''' + p_text + '''">''' + html.escape(data) + '''</textarea>
                         <hr class="main_hr">
                         
-                        <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
+                        <input placeholder="''' + load_lang('why') + '''" name="send" value="''' + html.escape(send) + '''">
                         <hr class="main_hr">
                         
-                        <input placeholder="''' + load_lang('name') + '''" name="get_ip" type="text">
+                        <input placeholder="''' + load_lang('name') + '''" name="get_ip" value="''' + html.escape(get_ip) + '''">
                         <hr class="main_hr">
                         
-                        <button id="opennamu_js_save" type="submit">''' + load_lang('save') + '''</button>
-                        <button id="opennamu_js_preview" type="button">''' + load_lang('preview') + '''</button>
+                        <button id="opennamu_save_button" formaction="/history_add/''' + url_pas(name) + '''" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_preview_button" formaction="/history_add_preview/''' + url_pas(name) + '''" type="submit">''' + load_lang('preview') + '''</button>
                     </form>
                     
                     <hr class="main_hr">
-                    <div id="opennamu_js_preview_area"></div>
+                    <div id="opennamu_preview_area">''' + data_preview + '''</div>
                 ''',
                 menu = [['history/' + url_pas(name), load_lang('return')]]
             ))

+ 2 - 2
route/recent_history_tool.py

@@ -12,9 +12,9 @@ def recent_history_tool(name = 'Test', rev = 1):
                 '<li><a href="/raw_rev/' + num + '/' + url_pas(name) + '">' + load_lang('raw') + '</a></li>' + \
         ''
 
-        data += '<li><a href="/revert/' + num + '/' + url_pas(name) + '">' + load_lang('revert') + ' | r' + num + '</a></li>'
+        data += '<li><a href="/revert/' + num + '/' + url_pas(name) + '">' + load_lang('revert') + ' (r' + num + ')</a></li>'
         if rev - 1 > 0:
-            data += '<li><a href="/revert/' + str(rev - 1) + '/' + url_pas(name) + '">' + load_lang('revert') + ' | r' + str(rev - 1) + '</a></li>'
+            data += '<li><a href="/revert/' + str(rev - 1) + '/' + url_pas(name) + '">' + load_lang('revert') + ' (r' + str(rev - 1) + ')</a></li>'
 
         if rev - 1 > 0:
             data += '<li><a href="/diff/' + str(rev - 1) + '/' + num + '/' + url_pas(name) + '">' + load_lang('compare') + '</a></li>'

+ 5 - 8
route/tool/func.py

@@ -613,6 +613,8 @@ def update(ver_num, set_data):
                 'User-agent: *\n' + \
                 'Disallow: /\n' + \
                 'Allow: /$\n' + \
+                'Allow: /image/\n' + \
+                'Allow: /views/\n' + \
                 'Allow: /w/' + \
             ''
             if db_data[0][0] == robot_default:
@@ -847,7 +849,7 @@ def load_domain(data_type = 'normal'):
 
     return domain
 
-def edit_button(editor_display = '0'):
+def edit_button(ob_name = 'opennamu_edit_textarea', monaco_ob_name = 'opennamu_monaco_editor'):
     curs = conn.cursor()
 
     insert_list = []
@@ -859,11 +861,7 @@ def edit_button(editor_display = '0'):
 
     data = ''
     for insert_data in insert_list:
-        data += '' + \
-            '<a href="' + \
-                'javascript:do_insert_data(\'opennamu_js_edit_textarea_view\', \'' + insert_data[0] + '\', ' + editor_display + ')' + \
-            '">(' + insert_data[1] + ')</a> ' + \
-        ''
+        data += '<a href="javascript:do_insert_data(\'' + ob_name + '\', \'' + insert_data[0] + '\', \'' + monaco_ob_name + '\');">(' + insert_data[1] + ')</a> '
 
     data += (' ' if data != '' else '') + '<a href="/edit_top">(' + load_lang('add') + ')</a>'
     data += '<hr class="main_hr">'
@@ -1043,7 +1041,7 @@ def wiki_css(data):
     data += ['' for _ in range(0, 3 - len(data))]
     
     data_css = ''
-    data_css_ver = '155'
+    data_css_ver = '156'
     
     # Func JS + Defer
     data_css += '<script src="/views/main_css/js/func/func.js?ver=' + data_css_ver + '"></script>'
@@ -1064,7 +1062,6 @@ def wiki_css(data):
     data_css += '<script src="/views/main_css/js/render/wiki.js?ver=' + data_css_ver + '"></script>'
     
     # Route JS + Defer
-    data_css += '<script defer src="/views/main_css/js/route/edit.js?ver=' + data_css_ver + '"></script>'
     data_css += '<script defer src="/views/main_css/js/route/thread.js?ver=' + data_css_ver + '"></script>'
     
     # 레거시 일반 JS

+ 163 - 41
route/tool/func_render_namumark.py

@@ -35,9 +35,9 @@ class class_do_render_namumark:
             return name + ' (RENDER LANG)'
 
     def get_tool_js_safe(self, data):
-        data = re.sub(r'\\', '\\\\\\\\', data)
-        data = re.sub(r'"', '\\"', data)
-        data = re.sub(r'\n', '\\n', data)
+        data = data.replace('\n', '\\\\n')
+        data = data.replace('\\', '\\\\')
+        data = data.replace('"', '\\"')
 
         return data
 
@@ -85,7 +85,7 @@ class class_do_render_namumark:
     def get_tool_data_revert(self, data, do_type = 'all'):
         storage_count = self.data_temp_storage_count * 3
         if do_type == 'all':
-            storage_regex = r'(?:<((slash)_(?:[0-9]+))>|<((render)_(?:[0-9]+))>(?:(?:(?!<(?:\/?render_(?:[0-9]+))>).)*)<\/render_(?:[0-9]+)>)'
+            storage_regex = r'(?:<((slash)_(?:[0-9]+))>|<((render)_(?:[0-9]+))>(?:(?:(?!<(?:\/?render_(?:[0-9]+))>).|\n)*)<\/render_(?:[0-9]+)>)'
         elif do_type == 'render':
             storage_regex = r'<((render)_(?:[0-9]+))>(?:(?:(?!<(?:\/?render_(?:[0-9]+))>).)*)<\/render_(?:[0-9]+)>'
         else:
@@ -113,12 +113,9 @@ class class_do_render_namumark:
                         else:
                             data_revert = ''
                     else:
-                        if self.data_temp_storage[match[0]] == '\\':
-                            data_revert = '\\\\\\\\'
-                        else:
-                            data_revert = '\\' + self.data_temp_storage[match[0]]
+                        data_revert = '\\' + self.data_temp_storage[match[0]]
 
-                data = re.sub(storage_regex, data_revert, data, 1)
+                data = re.sub(storage_regex, lambda x : data_revert, data, 1)
 
             storage_count -= 1
 
@@ -380,7 +377,7 @@ class class_do_render_namumark:
             toc_data += '</div>'
 
         # toc replace
-        self.render_data = re.sub(r'\[(목차|toc|tableofcontents)\]', toc_data, self.render_data)
+        self.render_data = re.sub(r'\[(목차|toc|tableofcontents)\]', lambda x : toc_data, self.render_data)
 
     def do_render_macro(self):
         # double macro function
@@ -561,12 +558,16 @@ class class_do_render_namumark:
 
     def do_render_math(self):
         def do_render_math_sub(match):
-            data = self.get_tool_data_restore(match.group(1), do_type = 'slash')
+            data = match.group(1)
+
+            data = re.sub(r'\n', '', data)
+            data = self.get_tool_data_revert(data)
+
+            data_html = self.get_tool_js_safe(data)
+
             data = html.unescape(data)
             data = self.get_tool_js_safe(data)
 
-            data_html = self.get_tool_js_safe(match.group(1))
-
             name_ob = 'opennamu_math_' + str(self.data_math_count)
 
             data_name = self.get_tool_data_storage('<span id="' + name_ob + '">', '</span>', match.group(0))
@@ -575,7 +576,9 @@ class class_do_render_namumark:
                 'try {\n' + \
                     'katex.render("' + data + '", document.getElementById(\"' + name_ob + '\"));\n' + \
                 '} catch {\n' + \
-                    'document.getElementById(\"' + name_ob + '\").innerHTML = "<span style=\'color: red;\'>' + data_html + '</span>";\n' + \
+                    'if(document.getElementById(\"' + name_ob + '\")) {\n' + \
+                        'document.getElementById(\"' + name_ob + '\").innerHTML = "<span style=\'color: red;\'>' + data_html + '</span>";\n' + \
+                    '}\n' + \
                 '}\n' + \
             ''
 
@@ -583,13 +586,9 @@ class class_do_render_namumark:
 
             return '<' + data_name + '></' + data_name + '>'
 
-        self.render_data = re.sub(r'\[math\(((?:(?!\)\]).)+)\)\]', do_render_math_sub, self.render_data)
+        self.render_data = re.sub(r'\[math\(((?:(?!\[math\(|\)\]).|\n)+)\)\]', do_render_math_sub, self.render_data)
 
     def do_render_link(self):
-        # todo list
-        # add link exist check
-        # add file exist check
-
         link_regex = r'\[\[((?:(?!\[\[|\]\]|\||<|>).|<slash_[0-9]+>)+)(?:\|((?:(?!\[\[|\]\]|\|).)+))?\]\]'
         link_count_all = len(re.findall(link_regex, self.render_data)) * 4
         while 1:
@@ -683,7 +682,7 @@ class class_do_render_namumark:
                     if link_exist != '':
                         data_name = self.get_tool_data_storage('<a class="' + link_exist + '" href="/upload?name=' + url_pas(link_main_org) + '">', '</a>', link_data_full)
 
-                        self.render_data = re.sub(link_regex, '<' + data_name + '>' + link_sub + '</' + data_name + '>', self.render_data, 1)
+                        self.render_data = re.sub(link_regex, lambda x : ('<' + data_name + '>' + link_sub + '</' + data_name + '>'), self.render_data, 1)
                     else:
                         data_name = self.get_tool_data_storage(file_end, '', link_data_full)
 
@@ -724,6 +723,49 @@ class class_do_render_namumark:
 
                     self.render_data = re.sub(link_regex, '', self.render_data, 1)
                 # out link
+                elif re.search(r'^(?:inter|인터):([^:]+):', link_main):
+                    link_inter_name = re.search(r'^(?:inter|인터):([^:]+):', link_main)
+                    link_inter_name = link_inter_name.group(1)
+
+                    link_main = re.sub(r'^(?:inter|인터):([^:]+):', '', link_main)
+
+                    # sharp
+                    link_data_sharp_regex = r'#([^#]+)$'
+                    link_data_sharp = re.search(link_data_sharp_regex, link_main)
+                    if link_data_sharp:
+                        link_data_sharp = link_data_sharp.group(1)
+                        link_data_sharp = html.unescape(link_data_sharp)
+                        link_data_sharp = '#' + url_pas(link_data_sharp)
+
+                        link_main = re.sub(link_data_sharp_regex, '', link_main)
+                    else:
+                        link_data_sharp = ''
+
+                    link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
+                    link_main = html.unescape(link_main)
+                    link_main = url_pas(link_main)
+
+                    self.curs.execute(db_change("select plus, plus_t from html_filter where kind = 'inter_wiki' and html = ?"), [link_inter_name])
+                    db_data = self.curs.fetchall()
+                    if db_data:
+                        link_main = db_data[0][0] + link_main
+
+                        # sub not exist -> sub = main
+                        if link_data[1]:
+                            link_sub = link_data[1]
+                            link_sub_storage = ''
+                        else:
+                            link_sub = ''
+                            link_sub_storage = link_main_org
+
+                        if db_data[0][1] != '':
+                            link_sub_storage = db_data[0][1] + link_sub_storage
+
+                        data_name = self.get_tool_data_storage('<a class="opennamu_link_inter" href="' + link_main + link_data_sharp + '">' + link_sub_storage, '</a>', link_data_full)
+                    
+                        self.render_data = re.sub(link_regex, lambda x : ('<' + data_name + '>' + link_sub + '</' + data_name + '>'), self.render_data, 1)
+                    else:
+                        self.render_data = re.sub(link_regex, '', self.render_data, 1)
                 elif re.search(r'^https?:\/\/', link_main):
                     link_main = self.get_tool_data_restore(link_main, do_type = 'slash')
                     link_main = html.unescape(link_main)
@@ -739,7 +781,7 @@ class class_do_render_namumark:
 
                     data_name = self.get_tool_data_storage('<a class="opennamu_link_out" href="' + link_main + '">' + link_sub_storage, '</a>', link_data_full)
 
-                    self.render_data = re.sub(link_regex, '<' + data_name + '>' + link_sub + '</' + data_name + '>', self.render_data, 1)
+                    self.render_data = re.sub(link_regex, lambda x : ('<' + data_name + '>' + link_sub + '</' + data_name + '>'), self.render_data, 1)
                 # in link
                 else:
                     # sharp
@@ -759,7 +801,7 @@ class class_do_render_namumark:
                         link_main = self.doc_name
                         link_main = re.sub(r'(\/[^/]+)$', '', link_main)
                     elif re.search(r'^\/', link_main):
-                        link_main = re.sub(r'^\/', self.doc_name + '/', link_main)
+                        link_main = re.sub(r'^\/', lambda x : (self.doc_name + '/'), link_main)
                     elif re.search(r'^:(분류|category):', link_main):
                         link_main = re.sub(r'^:(분류|category):', 'category:', link_main)
                     elif re.search(r'^:(파일|file):', link_main):
@@ -797,7 +839,7 @@ class class_do_render_namumark:
 
                     data_name = self.get_tool_data_storage('<a class="' + link_exist + ' ' + link_same + '" href="' + link_main + link_data_sharp + '">' + link_sub_storage, '</a>', link_data_full)
 
-                    self.render_data = re.sub(link_regex, '<' + data_name + '>' + link_sub + '</' + data_name + '>', self.render_data, 1)
+                    self.render_data = re.sub(link_regex, lambda x : ('<' + data_name + '>' + link_sub + '</' + data_name + '>'), self.render_data, 1)
 
             link_count_all -= 1
 
@@ -955,7 +997,7 @@ class class_do_render_namumark:
                 footnote_data_org = footnote_data.group(0)
                 footnote_data = footnote_data.groups()
                 if footnote_data[2]:
-                    self.render_data = re.sub(footnote_regex, self.get_tool_footnote_make(), self.render_data, 1)
+                    self.render_data = re.sub(footnote_regex, lambda x : self.get_tool_footnote_make(), self.render_data, 1)
                 else:
                     if not footnote_data[0]:
                         footnote_name = str(footnote_num)
@@ -1013,7 +1055,7 @@ class class_do_render_namumark:
                 link_main = self.doc_name
                 link_main = re.sub(r'(\/[^/]+)$', '', link_main)
             elif re.search(r'^\/', link_main):
-                link_main = re.sub(r'^\/', self.doc_name + '/', link_main)
+                link_main = re.sub(r'^\/', lambda x : (self.doc_name + '/'), link_main)
             elif re.search(r'^분류:', link_main):
                 link_main = re.sub(r'^분류:', 'category:', link_main)
             elif re.search(r'^사용자:', link_main):
@@ -1039,6 +1081,8 @@ class class_do_render_namumark:
         # get_tool_dark_mode_split
         # get_tool_px_add_check
         # get_tool_css_safe
+        # todo : after text render text not use to make table
+        # todo : table caption
         def do_render_table_parameter(cell_count, parameter, data, option = {}):
             table_parameter_all = { "div" : "", "table" : "", "tr" : "", "td" : "", "col" : "", "colspan" : "", "rowspan" : "", "data" : "" }
             
@@ -1131,7 +1175,7 @@ class class_do_render_namumark:
 
             return table_parameter_all
 
-        table_regex = r'\n *((?:(?:(?:(?:\|\|)+)(?:(?:(?:(?:(?:(?!\|\|).)+)\n*)+)|(?:(?:(?!\|\|).)*)))+(?:(?:\|\|+)\n))+)'
+        table_regex = re.compile('\n((?:(?:(?:(?:\|\|)+)|(?:\|[^|]+\|(?:\|\|)*))\n?(?:(?:(?!\|\|).)+))(?:(?:\|\||\|\|\n|(?:\|\|)+(?!\n)(?:(?:(?!\|\|).)+)\n*)*)\|\|)\n', re.DOTALL)
         table_sub_regex = r'(\n?)((?:\|\|)+)((?:&lt;(?:(?:(?!&lt;|&gt;).)+)&gt;)*)((?:\n*(?:(?:(?:(?!\|\|).)+)\n*)+)|(?:(?:(?!\|\|).)*))'
         table_count_all = len(re.findall(table_regex, self.render_data)) * 2
         while 1:
@@ -1145,18 +1189,24 @@ class class_do_render_namumark:
             else:
                 table_data_org = table_data.group(0)
                 table_data = table_data.group(1)
-                print(table_data)
 
                 table_parameter = { "div" : "", "table" : "", "col" : {} }
                 table_data_end = ''
                 table_col_num = 0
                 table_tr_change = 0
                 for table_sub in re.findall(table_sub_regex, table_data):
+                    table_data_in = table_sub[3]
+                    table_data_in = re.sub(r'^\n+', '', table_data_in)
+
+                    table_sub_parameter = do_render_table_parameter(table_sub[1], table_sub[2], table_data_in)
+
+                    if table_data_end == '':
+                        table_data_end += '<tr style="' + table_sub_parameter['tr'] + '">'
+
                     if table_sub[0] != '' and table_tr_change == 1:
                         table_col_num = 0
                         table_data_end += '</tr><tr style="' + table_sub_parameter['tr'] + '">'
 
-                    table_sub_parameter = do_render_table_parameter(table_sub[1], table_sub[2], table_sub[3])
                     if not table_col_num in table_parameter['col']:
                         table_parameter['col'][table_col_num] = ''
 
@@ -1173,17 +1223,20 @@ class class_do_render_namumark:
                     
                     table_col_num += 1
 
+                table_data_end += '</tr>'
                 table_data_end = '<table style="' + table_parameter['table'] + '">' + table_data_end + '</table>'
                 if table_parameter['div'] != '':
                     table_data_end = '<div style="' + table_parameter['div'] + '">' + table_data_end + '</div>'
 
-                self.render_data = re.sub(table_regex, '\n<front_br>' + table_data_end + '<back_br>\n', self.render_data, 1)
+                self.render_data = re.sub(table_regex, lambda x : ('\n<front_br>' + table_data_end + '<back_br>\n'), self.render_data, 1)
 
             table_count_all -= 1
     
     def do_render_middle(self):
         middle_regex = r'{{{([^{](?:(?!{{{|}}}).|\n)*)?(?:}|<(\/?(?:slash)_(?:[0-9]+))>)}}'
         wiki_count = 0
+        syntax_count = 0
+        folding_count = 0
         middle_count_all = len(re.findall(middle_regex, self.render_data)) * 10
         while 1:
             middle_data = re.search(middle_regex, self.render_data)
@@ -1197,7 +1250,7 @@ class class_do_render_namumark:
                 if middle_slash:
                     if self.data_temp_storage[middle_slash] != '}':
                         middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
-                        self.render_data = re.sub(middle_regex, middle_data_org, self.render_data, 1)
+                        self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
                         continue
 
                 middle_data = middle_data.group(1)
@@ -1211,7 +1264,7 @@ class class_do_render_namumark:
                     if middle_name == '#!wiki':
                         if middle_slash:
                             middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
-                            self.render_data = re.sub(middle_regex, middle_data_org, self.render_data, 1)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
                             continue
 
                         wiki_regex = r'^#!wiki(?:(?: style=(&quot;(?:(?:(?!&quot;).)*)&quot;|&#x27;(?:(?:(?!&#x27;).)*)&#x27;))| [^\n]*)?\n'
@@ -1239,28 +1292,64 @@ class class_do_render_namumark:
                     elif middle_name == '#!html':
                         if middle_slash:
                             middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
-                            self.render_data = re.sub(middle_regex, middle_data_org, self.render_data, 1)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
                             continue
 
                         data_name = self.get_tool_data_storage('', '', middle_data_org)
                     elif middle_name == '#!folding':
                         if middle_slash:
                             middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
-                            self.render_data = re.sub(middle_regex, middle_data_org, self.render_data, 1)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
                             continue
 
-                        data_name = self.get_tool_data_storage('', '', middle_data_org)
+                        wiki_regex = r'^#!folding(?: ([^\n]*))?\n'
+                        wiki_data_folding = re.search(wiki_regex, middle_data)
+                        wiki_data = re.sub(wiki_regex, '', middle_data)
+                        if wiki_data_folding:
+                            wiki_data_folding = wiki_data_folding.group(1)
+                            if not wiki_data_folding:
+                                wiki_data_folding = 'test'
+                        else:
+                            wiki_data_folding = 'test'
+
+                        wiki_data = self.get_tool_data_revert(wiki_data)
+                        wiki_data = html.unescape(wiki_data)
+                        wiki_data = re.sub('\n$', '', wiki_data)
+
+                        self.data_include += [[self.doc_include + 'opennamu_folding_' + str(folding_count), self.doc_name, wiki_data]]
+
+                        middle_data_pass = wiki_data_folding
+                        data_name = self.get_tool_data_storage(
+                            '<details><summary>',
+                            '</summary><div id="' + self.doc_include + 'opennamu_folding_' + str(folding_count) + '"></div></details>', 
+                            middle_data_org
+                        )
+                        folding_count += 1
                     elif middle_name == '#!syntax':
                         if middle_slash:
                             middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
-                            self.render_data = re.sub(middle_regex, middle_data_org, self.render_data, 1)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
                             continue
 
-                        data_name = self.get_tool_data_storage('', '', middle_data_org)
+                        wiki_regex = r'^#!syntax(?: ([^\n]*))?\n'
+                        wiki_data_syntax = re.search(wiki_regex, middle_data)
+                        wiki_data = re.sub(wiki_regex, '', middle_data)
+                        if wiki_data_syntax:
+                            wiki_data_syntax = wiki_data_syntax.group(1)
+                            if not wiki_data_syntax:
+                                wiki_data_syntax = 'python'
+                        else:
+                            wiki_data_syntax = 'python'
+
+                        if syntax_count == 0:
+                            self.render_data_js += 'hljs.highlightAll();\n'
+
+                        data_name = self.get_tool_data_storage('<pre id="syntax"><code class="' + wiki_data_syntax + '">' + wiki_data, '</code></pre>', middle_data_org)
+                        syntax_count += 1
                     elif middle_name in ('+5', '+4', '+3', '+2', '+1'):
                         if middle_slash:
                             middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
-                            self.render_data = re.sub(middle_regex, middle_data_org, self.render_data, 1)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
                             continue
 
                         wiki_data = re.sub(r'^\+[1-5] ', '', middle_data)
@@ -1280,7 +1369,7 @@ class class_do_render_namumark:
                     elif middle_name in ('-5', '-4', '-3', '-2', '-1'):
                         if middle_slash:
                             middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
-                            self.render_data = re.sub(middle_regex, middle_data_org, self.render_data, 1)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
                             continue
 
                         wiki_data = re.sub(r'^\-[1-5] ', '', middle_data)
@@ -1297,10 +1386,38 @@ class class_do_render_namumark:
 
                         middle_data_pass = wiki_data
                         data_name = self.get_tool_data_storage('<span style="font-size:' + wiki_size + '%">', '</span>', middle_data_org)
+                    elif re.search(r'^@(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+))', middle_name):
+                        if middle_slash:
+                            middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
+                            continue
+
+                        wiki_color = re.search(r'^@(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+))(?:,@(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+)))?', middle_name)
+                        if wiki_color:
+                            wiki_color = wiki_color.groups()
+                            if wiki_color[0]:
+                                wiki_color = '#' + wiki_color[0]
+                            else:
+                                wiki_color = wiki_color[1]
+
+                            if wiki_color[2]:
+                                wiki_color += ',#' + wiki_color[0]
+                            elif wiki_color[3]:
+                                wiki_color = ',' + wiki_color[1]
+                        else:
+                            wiki_color = 'red'
+
+                        wiki_color = self.get_tool_css_safe(wiki_color)
+                        wiki_color = self.get_tool_dark_mode_split(wiki_color)
+
+                        wiki_data = re.sub(r'^@(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+))(?:,@(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+)))? ?', '', middle_data)
+
+                        middle_data_pass = wiki_data
+                        data_name = self.get_tool_data_storage('<span style="background-color:' + wiki_color + '">', '</span>', middle_data_org)
                     elif re.search(r'^#(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+))', middle_name):
                         if middle_slash:
                             middle_data_org = re.sub(r'<(\/?(?:slash)_(?:[0-9]+))>', '<temp_' + middle_slash + '>', middle_data_org)
-                            self.render_data = re.sub(middle_regex, middle_data_org, self.render_data, 1)
+                            self.render_data = re.sub(middle_regex, lambda x : middle_data_org, self.render_data, 1)
                             continue
 
                         wiki_color = re.search(r'^#(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+))(?:,#(?:((?:[0-9a-f-A-F]{3}){1,2})|(\w+)))?', middle_name)
@@ -1330,6 +1447,8 @@ class class_do_render_namumark:
                             middle_data += '\\'
 
                         data_revert = self.get_tool_data_revert(middle_data)
+                        data_revert = re.sub('^\n', '', data_revert)
+                        data_revert = re.sub('\n$', '', data_revert)
 
                         data_name = self.get_tool_data_storage(data_revert, '', middle_data_org)
                 else:
@@ -1337,10 +1456,12 @@ class class_do_render_namumark:
                         middle_data += '\\'
 
                     data_revert = self.get_tool_data_revert(middle_data)
+                    data_revert = re.sub('^\n', '', data_revert)
+                    data_revert = re.sub('\n$', '', data_revert)
 
                     data_name = self.get_tool_data_storage(data_revert, '', middle_data_org)
 
-                self.render_data = re.sub(middle_regex, '<' + data_name + '>' + middle_data_pass + '</' + data_name + '>', self.render_data, 1)
+                self.render_data = re.sub(middle_regex, lambda x : ('<' + data_name + '>' + middle_data_pass + '</' + data_name + '>'), self.render_data, 1)
 
             middle_count_all -= 1
 
@@ -1382,9 +1503,10 @@ class class_do_render_namumark:
         self.do_render_slash()
         self.do_render_redirect()
         self.do_render_include()
-        self.do_render_math()
         self.do_render_middle()
+        self.do_render_math()
         # self.do_render_list()
+        # todo : fix slash
         self.do_render_table()
         self.do_render_link()
         self.do_render_macro()

+ 66 - 39
route/topic.py

@@ -1,11 +1,16 @@
 from .tool.func import *
 
-def topic(topic_num = 0):
+def topic(topic_num = 0, do_type = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
         topic_num = str(topic_num)
 
-        if flask.request.method == 'POST':
+        topic_acl = acl_check('', 'topic', topic_num)
+        topic_view_acl = acl_check('', 'topic_view', topic_num)
+        if topic_view_acl == 1:
+            return re_error('/ban')
+
+        if flask.request.method == 'POST' and do_type == '':
             name = flask.request.form.get('topic', 'Test')
             sub = flask.request.form.get('title', 'Test')
             
@@ -19,25 +24,7 @@ def topic(topic_num = 0):
                 curs.execute(db_change("select code from topic order by code + 0 desc limit 1"))
                 t_data = curs.fetchall()
                 topic_num = str(int(t_data[0][0]) + 1) if t_data else '1'
-        else:
-            if topic_num == '0':
-                name = load_lang('make_new_topic')
-                sub = load_lang('make_new_topic')
-            else:
-                curs.execute(db_change("select title, sub from rd where code = ?"), [topic_num])
-                name = curs.fetchall()
-                if name:
-                    sub = name[0][1]
-                    name = name[0][0]
-                else:
-                    return redirect('/')
-
-        topic_acl = acl_check('', 'topic', topic_num)
-        topic_view_acl = acl_check('', 'topic_view', topic_num)
-        if topic_view_acl == 1:
-            return re_error('/ban')
-
-        if flask.request.method == 'POST':
+            
             if flask.request.form.get('content', 'Test') == '':
                 return redirect('/thread/' + topic_num)
 
@@ -143,15 +130,43 @@ def topic(topic_num = 0):
 
             return redirect('/thread/' + topic_num + '#' + num)
         else:
-            display = 'display: none;' if topic_acl == 1 else ''
-            data_input_topic_name = ''
+            thread_data = ''
+            thread_data_preview = ''
+
             if topic_num == '0':
-                data_input_topic_name = '' + \
-                    '<input placeholder="' + load_lang('discussion_name') + '" name="title">' + \
-                    '<hr class="main_hr">' + \
-                    '<input placeholder="' + load_lang('document_name') + '" name="topic">' + \
-                    '<hr class="main_hr">' + \
-                ''
+                name = load_lang('make_new_topic')
+                sub = load_lang('make_new_topic')
+
+                if do_type == 'preview':
+                    name_value = flask.request.form.get('topic', '')
+                    sub_value = flask.request.form.get('title', '')
+                else:
+                    name_value = ''
+                    sub_value = ''
+            else:
+                curs.execute(db_change("select title, sub from rd where code = ?"), [topic_num])
+                name = curs.fetchall()
+                if name:
+                    sub = name[0][1]
+                    name = name[0][0]
+
+                    name_value = name
+                    sub_value = sub
+                else:
+                    return redirect('/')
+
+            if do_type == 'preview':
+                thread_data = flask.request.form.get('content', 'Test')
+                thread_data = thread_data.replace('\r', '')
+
+                thread_data_preview = render_set(
+                    doc_name = '', 
+                    doc_data = thread_data,
+                    data_in = ''
+                )
+
+            acl_display = 'display: none;' if topic_acl == 1 else ''
+            name_display = 'display: none;' if topic_num != '0' else ''
                 
             curs.execute(db_change('select data from other where name = "topic_text"'))
             sql_d = curs.fetchall()
@@ -161,25 +176,37 @@ def topic(topic_num = 0):
                 imp = [name, wiki_set(), wiki_custom(), wiki_css(['(' + load_lang('discussion') + ')', 0])],
                 data = '''
                     <h2 id="topic_top_title">''' + html.escape(sub) + '''</h2>
+                    
                     <div id="top_topic"></div>
                     <div id="main_topic"></div>
                     <div id="plus_topic"></div>
+                    
                     <a href="/thread/''' + topic_num + '/tool">(' + load_lang('topic_tool') + ''')</a>
                     <hr class="main_hr">
-                    <form style="''' + display + '''" method="post">
-                        ''' + data_input_topic_name + '''
-                        <textarea id="opennamu_js_edit_textarea" class="opennamu_comment_textarea" placeholder="''' + topic_text + '''" name="content"></textarea>
+                    
+                    <form style="''' + acl_display + '''" method="post">
+                        <div style="''' + name_display + '''">
+                            <input placeholder="''' + load_lang('document_name') + '''" name="topic" value="''' + html.escape(name_value) + '''">
+                            <hr class="main_hr">
+                            <input placeholder="''' + load_lang('discussion_name') + '''" name="title" value="''' + html.escape(sub_value) + '''">
+                            <hr class="main_hr">
+                        </div>
+                        
+                        <div>''' + edit_button('opennamu_edit_textarea') + '''</div>
+
+                        <textarea id="opennamu_edit_textarea" class="opennamu_comment_textarea" placeholder="''' + topic_text + '''" name="content">''' + html.escape(thread_data) + '''</textarea>
                         <hr class="main_hr">
-                        ''' + captcha_get() + (ip_warning() if display == '' else '') + '''
-                        <input style="display: none;" name="topic" value="''' + name + '''">
-                        <input style="display: none;" name="title" value="''' + sub + '''">
-                        <button id="opennamu_js_save" type="submit">''' + load_lang('send') + '''</button>
-                        <button id="opennamu_js_preview" type="button">''' + load_lang('preview') + '''</button>
+                        
+                        ''' + captcha_get() + ip_warning() + '''
+                        
+                        <button id="opennamu_save_button" formaction="/thread/''' + topic_num + '''" type="submit">''' + load_lang('send') + '''</button>
+                        <button id="opennamu_preview_button" formaction="/thread_preview/''' + topic_num + '''#opennamu_edit_textarea" type="submit">''' + load_lang('preview') + '''</button>
                     </form>
                     <hr class="main_hr">
-                    <div id="opennamu_js_preview_area"></div>
+                    
+                    <div id="opennamu_preview_area">''' + thread_data_preview + '''</div>
+                    
                     <!-- JS : opennamu_do_thread_make -->
-                    <!-- JS : edit.js -->
                 ''',
                 menu = [['topic/' + url_pas(name), load_lang('list')]]
             ))

+ 1 - 1
route/user_setting_head.py

@@ -70,7 +70,7 @@ def user_setting_head(skin_name = ''):
                         <hr class="main_hr">
                         ''' + load_lang('user_css_warning') + ''' : <a href="/change/head_reset">/change/head_reset</a>
                         <hr class="main_hr">
-                        <button id="opennamu_js_save" type="submit">''' + load_lang('save') + '''</button>
+                        <button id="opennamu_save_button" type="submit">''' + load_lang('save') + '''</button>
                     </form>
                 ''',
                 menu = [['user', load_lang('return')]]

+ 4 - 4
route/view_read.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def view_read(name = 'Test', doc_rev = 0, doc_from = '', do_type = ''):
+def view_read(name = 'Test', doc_rev = '', doc_from = '', do_type = ''):
     with get_db_connect() as conn:
         curs = conn.cursor()
 
@@ -131,7 +131,7 @@ def view_read(name = 'Test', doc_rev = 0, doc_from = '', do_type = ''):
         else:
             name_view = name
 
-        if num != '0':
+        if num != '':
             curs.execute(db_change("select title from history where title = ? and id = ? and hide = 'O'"), [name, num])
             if curs.fetchall() and admin_check(6) != 1:
                 return redirect('/history/' + url_pas(name))
@@ -187,7 +187,7 @@ def view_read(name = 'Test', doc_rev = 0, doc_from = '', do_type = ''):
         else:
             response_data = 200
 
-        if num != '0':
+        if num != '':
             menu += [['history/' + url_pas(name), load_lang('history')]]
             sub = ' (r' + str(num) + ')'
             acl = 0
@@ -234,7 +234,7 @@ def view_read(name = 'Test', doc_rev = 0, doc_from = '', do_type = ''):
 
         div = file_data + user_doc + end_data + category_doc
 
-        if num != '0':
+        if num != '':
             curs.execute(db_change('select data from other where name = "phrase_old_page_warring"'))
             db_data = curs.fetchall()
             if db_data and db_data[0][0] != '':

+ 1 - 1
version.json

@@ -1,6 +1,6 @@
 {
     "beta" : {
-        "r_ver" : "v3.4.5 (stable2) (beta4) (dev66)",
+        "r_ver" : "v3.4.5-unstable (stable2) (beta5-68)",
         "c_ver" : "3500354",
         "s_ver" : "3500110"
     }

+ 1 - 1
views/main_css/css/main.css

@@ -103,7 +103,7 @@ a {
     font-weight: bold;
 }
 
-#inside, #out_link, .opennamu_link_out {
+#inside, #out_link, .opennamu_link_out, .opennamu_link_inter {
     color: green;
 }
 

+ 2 - 6
views/main_css/js/load_editor.js

@@ -1,5 +1,5 @@
-function do_insert_data(name, data, monaco = 0) {
-    if(monaco === 0) {
+function do_insert_data(name, data, monaco_name) {
+    if(!document.getElementById(monaco_name)) {
         // https://stackoverflow.com/questions/11076975/insert-text-into-textarea-at-cursor-position-javascript
         if(document.selection) {
             document.getElementById(name).focus();
@@ -103,8 +103,4 @@ function pasteListener(e) {
             alert("업로드 실패");
         });
     }
-}
-
-function load_raw_preview(name_1, name_2) {
-    document.getElementById(name_2).innerHTML = document.getElementById(name_1).value;
 }

+ 0 - 71
views/main_css/js/route/edit.js

@@ -1,71 +0,0 @@
-// "use strict";
-
-function do_stop_exit() {
-    window.onbeforeunload = function() {
-        do_insert_edit_data();
-
-        let data = document.getElementById('opennamu_js_edit_textarea').value;
-        let origin = document.getElementById('opennamu_js_edit_origin').value;
-        if(data !== origin) {
-            return '';
-        }
-    }
-}
-
-function do_insert_edit_data() {
-    if(document.getElementById('opennamu_monaco_editor')) {
-        do_monaco_to_textarea();
-    }
-    
-    let get_data = document.getElementById('opennamu_js_edit_textarea_view').value;
-    
-    document.getElementById('opennamu_js_edit_textarea').value = get_data;
-}
-
-function do_stop_exit_release() {
-    window.onbeforeunload = function () {}
-}
-
-function do_monaco_to_textarea() {
-    try {
-        document.getElementById('opennamu_js_edit_textarea_view').value = window.editor.getValue();
-    } catch(e) {}
-}
-
-function do_insert_preview() {
-    let s_data = new FormData();
-    s_data.append('data', document.getElementById('opennamu_js_edit_textarea').value);
-
-    let xhr = new XMLHttpRequest();
-    xhr.open("POST", "/api/w/Test");
-    xhr.send(s_data);
-    
-    xhr.onreadystatechange = function() {
-        if(xhr.readyState === 4 && xhr.status === 200) {
-            let o_p_data = JSON.parse(xhr.responseText);
-            
-            document.getElementById('opennamu_js_preview_area').innerHTML = o_p_data['data'];
-            eval(o_p_data['js_data'])
-        }
-    }
-}
-
-
-if(window.location.pathname.match(/^\/(edit|edit_from|edit_section)\//)) {
-    do_stop_exit();
-    
-    document.getElementById('opennamu_js_save').onclick = function() {
-        do_insert_edit_data();
-        do_stop_exit_release();
-    };
-    document.getElementById('opennamu_js_preview').onclick = function() {
-        do_insert_edit_data();
-        do_insert_preview();
-    };
-}
-
-if(window.location.pathname.match(/^\/(thread)\//)) {
-    document.getElementById('opennamu_js_preview').onclick = function() {
-        do_insert_preview();
-    };
-}

+ 2 - 2
views/main_css/js/route/thread.js

@@ -161,8 +161,8 @@ function opennamu_do_open_comment(key) {
     }
 }
 
-if(window.location.pathname.match(/^\/thread\//)) {
-    let thread_num = window.location.pathname.match(/^\/thread\/([0-9]+)/)[1];
+if(window.location.pathname.match(/^\/(thread|thread_preview)\//)) {
+    let thread_num = window.location.pathname.match(/^\/(?:thread|thread_preview)\/([0-9]+)/)[1];
 
     opennamu_do_thread_make(thread_num);
 } else if(window.location.pathname.match(/^\/topic\//)) {

+ 1 - 1
views/ringo/css/main.css

@@ -315,7 +315,7 @@ footer.only_mobile {
     margin-top: 0px;
 }
 
-#main_data input, #main_data textarea, #main_data button, #main_data select {
+input, textarea, button, select {
     border: 1px solid #aaa;
     
     padding: 10px;

+ 1 - 1
views/ringo/index.html

@@ -10,7 +10,7 @@
         {{imp[3][3]|safe}}
         <script src="https://code.iconify.design/1/1.0.3/iconify.min.js"></script>
         <script src="/views/ringo/js/main.js?ver=1"></script>
-        <link rel="stylesheet" href="/views/ringo/css/main.css?ver=1">
+        <link rel="stylesheet" href="/views/ringo/css/main.css?ver=2">
         <link rel="shortcut icon" href="/views/main_css/file/favicon.ico?ver=1">
         {{imp[1][5]|safe}}
         {{imp[2][3]|safe}}

+ 1 - 1
views/tenshi/css/dark.css

@@ -44,6 +44,6 @@ html, #main {
     color: white;
 }
 
-button#opennamu_js_save {
+button#opennamu_save_button {
     background: #083808;
 }

+ 3 - 3
views/tenshi/css/main.css

@@ -288,7 +288,7 @@ pre, #toc, #cate, #redirect {
 }
 */
 
-#redirect, #cate, #toc, blockquote, button#opennamu_js_save, button#opennamu_js_preview {
+#redirect, #cate, #toc, blockquote, button#opennamu_save_button, button#opennamu_preview_button {
     border: 0;
     
     padding: 10px;
@@ -296,11 +296,11 @@ pre, #toc, #cate, #redirect {
     box-shadow: 0 2px 4px 0 rgba(0,0,0,0.16), 0 2px 10px 0 rgba(0,0,0,0.12);
 }
 
-button#opennamu_js_save {
+button#opennamu_save_button {
     background: #92f7f4;
 }
 
-button#opennamu_js_preview {
+button#opennamu_preview_button {
     margin-left: 5px;
 }