2du 5 лет назад
Родитель
Сommit
a8dcd946f8

+ 107 - 96
emergency_tool.py

@@ -2,117 +2,127 @@
 import time
 from route.tool.func import *
 
-# DB
 while 1:
-    try:
-        set_data = json.loads(open('data/set.json', encoding = 'utf8').read())
-        if not 'db_type' in set_data:
-            try:
-                os.remove('data/set.json')
-            except:
-                print('Please delete set.json')
-                print('----')
-                raise
-        else:
-            print('DB name : ' + set_data['db'])
-            print('DB type : ' + set_data['db_type'])
+    print('Load DB (Y) [Y, N] : ', end = '')
+    data_db_load = input()
+    if data_db_load in ['Y', 'N']:
+        break
+
+if data_db_load == 'Y':
+    # DB
+    while 1:
+        try:
+            set_data = json.loads(open('data/set.json', encoding = 'utf8').read())
+            if not 'db_type' in set_data:
+                try:
+                    os.remove('data/set.json')
+                except:
+                    print('Please delete set.json')
+                    print('----')
+                    raise
+            else:
+                print('DB name : ' + set_data['db'])
+                print('DB type : ' + set_data['db_type'])
 
-            break
-    except:
-        if os.getenv('NAMU_DB') != None or os.getenv('NAMU_DB_TYPE') != None:
-            set_data = {
-                "db" : os.getenv('NAMU_DB') if os.getenv('NAMU_DB') else 'data',
-                "db_type" : os.getenv('NAMU_DB_TYPE') if os.getenv('NAMU_DB_TYPE') else 'sqlite'
-            }
+                break
+        except:
+            if os.getenv('NAMU_DB') != None or os.getenv('NAMU_DB_TYPE') != None:
+                set_data = {
+                    "db" : os.getenv('NAMU_DB') if os.getenv('NAMU_DB') else 'data',
+                    "db_type" : os.getenv('NAMU_DB_TYPE') if os.getenv('NAMU_DB_TYPE') else 'sqlite'
+                }
 
-            print('DB name : ' + set_data['db'])
-            print('DB type : ' + set_data['db_type'])
+                print('DB name : ' + set_data['db'])
+                print('DB type : ' + set_data['db_type'])
 
-            break
-        else:
-            new_json = ['', '']
-            normal_db_type = ['sqlite', 'mysql']
-
-            print('DB type (sqlite) [sqlite, mysql] : ', end = '')
-            new_json[0] = str(input())
-            if new_json[0] == '' or not new_json[0] in normal_db_type:
-                new_json[0] = 'sqlite'
-
-            all_src = []
-            for i_data in os.listdir("."):
-                f_src = re.search(r"(.+)\.db$", i_data)
-                if f_src:
-                    all_src += [f_src.group(1)]
-
-            if all_src != [] and new_json[0] != 'mysql':
-                print('DB name (data) [' + ', '.join(all_src) + '] : ', end = '')
+                break
             else:
-                print('DB name (data) : ', end = '')
+                new_json = ['', '']
+                normal_db_type = ['sqlite', 'mysql']
 
-            new_json[1] = str(input())
-            if new_json[1] == '':
-                new_json[1] = 'data'
+                print('DB type (sqlite) [sqlite, mysql] : ', end = '')
+                new_json[0] = str(input())
+                if new_json[0] == '' or not new_json[0] in normal_db_type:
+                    new_json[0] = 'sqlite'
 
-            with open('data/set.json', 'w', encoding = 'utf8') as f:
-                f.write('{ "db" : "' + new_json[1] + '", "db_type" : "' + new_json[0] + '" }')
+                all_src = []
+                for i_data in os.listdir("."):
+                    f_src = re.search(r"(.+)\.db$", i_data)
+                    if f_src:
+                        all_src += [f_src.group(1)]
 
-            set_data = json.loads(open('data/set.json', encoding = 'utf8').read())
+                if all_src != [] and new_json[0] != 'mysql':
+                    print('DB name (data) [' + ', '.join(all_src) + '] : ', end = '')
+                else:
+                    print('DB name (data) : ', end = '')
 
-            break
+                new_json[1] = str(input())
+                if new_json[1] == '':
+                    new_json[1] = 'data'
 
-db_data_get(set_data['db_type'])
+                with open('data/set.json', 'w', encoding = 'utf8') as f:
+                    f.write('{ "db" : "' + new_json[1] + '", "db_type" : "' + new_json[0] + '" }')
 
-if set_data['db_type'] == 'mysql':
-    try:
-        set_data_mysql = json.loads(open('data/mysql.json', encoding = 'utf8').read())
-    except:
-        new_json = {}
+                set_data = json.loads(open('data/set.json', encoding = 'utf8').read())
 
-        while 1:
-            print('DB user ID : ', end = '')
-            new_json['user'] = str(input())
-            if new_json['user'] != '':
                 break
 
-        while 1:
-            print('DB password : ', end = '')
-            new_json['password'] = str(input())
-            if new_json['password'] != '':
-                break
-                
-        print('DB host (localhost) : ', end = '')
-        new_json['host'] = str(input())
-        new_json['host'] = 'localhost' if new_json['host'] == '' else new_json['host']
-
-        print('DB port (3306) : ', end = '')
-        new_json['port'] = str(input())
-        new_json['port'] = '3306' if new_json['port'] == '' else new_json['port']
-
-        with open('data/mysql.json', 'w', encoding = 'utf8') as f:
-            f.write(json.dumps(new_json))
-
-        set_data_mysql = new_json
-
-    conn = pymysql.connect(
-        host = set_data_mysql['host'] if 'host' in set_data_mysql else 'localhost',
-        user = set_data_mysql['user'],
-        password = set_data_mysql['password'],
-        charset = 'utf8mb4',
-        port = int(set_data_mysql['port']) if 'port' in set_data_mysql else 3306
-    )
-    curs = conn.cursor()
-
-    try:
-        curs.execute(db_change('create database ? default character set utf8mb4;')%pymysql.escape_string(set_data['db']))
-    except:
-        pass
+    db_data_get(set_data['db_type'])
+
+    if set_data['db_type'] == 'mysql':
+        try:
+            set_data_mysql = json.loads(open('data/mysql.json', encoding = 'utf8').read())
+        except:
+            new_json = {}
+
+            while 1:
+                print('DB user ID : ', end = '')
+                new_json['user'] = str(input())
+                if new_json['user'] != '':
+                    break
+
+            while 1:
+                print('DB password : ', end = '')
+                new_json['password'] = str(input())
+                if new_json['password'] != '':
+                    break
+
+            print('DB host (localhost) : ', end = '')
+            new_json['host'] = str(input())
+            new_json['host'] = 'localhost' if new_json['host'] == '' else new_json['host']
+
+            print('DB port (3306) : ', end = '')
+            new_json['port'] = str(input())
+            new_json['port'] = '3306' if new_json['port'] == '' else new_json['port']
+
+            with open('data/mysql.json', 'w', encoding = 'utf8') as f:
+                f.write(json.dumps(new_json))
+
+            set_data_mysql = new_json
+
+        conn = pymysql.connect(
+            host = set_data_mysql['host'] if 'host' in set_data_mysql else 'localhost',
+            user = set_data_mysql['user'],
+            password = set_data_mysql['password'],
+            charset = 'utf8mb4',
+            port = int(set_data_mysql['port']) if 'port' in set_data_mysql else 3306
+        )
+        curs = conn.cursor()
+
+        try:
+            curs.execute(db_change('create database ' + set_data['db'] + ' default character set utf8mb4;'))
+        except:
+            pass
+
+        conn.select_db(set_data['db'])
+    else:
+        conn = sqlite3.connect(set_data['db'] + '.db')
+        curs = conn.cursor()
 
-    curs.execute(db_change('use ?')%pymysql.escape_string(set_data['db']))
+    load_conn(conn)
 else:
-    conn = sqlite3.connect(set_data['db'] + '.db')
-    curs = conn.cursor()
-
-load_conn(conn)
+    print('----')
+    print('You can use [9, 11]')
 
 # Main
 print('----')
@@ -297,7 +307,8 @@ else:
     if curs.fetchall():
         curs.execute(db_change("update user_set set data = '' where name = '2fa' and id = ?"), [user_name])
 
-conn.commit()
+if data_db_load == 'Y':
+    conn.commit()
 
 print('----')
 print('OK')

+ 429 - 0
lang/en-US.json

@@ -0,0 +1,429 @@
+{
+    "_comment_1_" : "Common",
+        "server" : "Server",
+        "filter" : "Filter",
+        "delete" : "Delete",
+        "notice" : "Notice",
+        "add" : "Add",
+        "license" : "License",
+        "etc" : "Etc",
+        "name" : "Name",
+        "regex" : "Regex",
+        "id" : "ID",
+        "list" : "List",
+        "main" : "Main",
+        "return" : "Return",
+        "skin" : "Skin",
+        "save" : "Save",
+        "secret_key" : "Secret key",
+        "public_key" : "Public key",
+        "host" : "Host",
+        "port" : "Port",
+        "restart" : "Restart",
+        "document_name" : "Document[s] name",
+        "discussion_name" : "Discussion[s] topic",
+        "user_name" : "Username",
+        "go" : "Go",
+        "document" : "Document",
+        "discussion" : "Discussion",
+        "backlink" : "Backlink",
+        "link" : "Link",
+        "closed" : "Closed",
+        "reload" : "Reload",
+        "send" : "Send",
+        "ongoing" : "Ongoing",
+        "normal" : "Normal",
+        "range" : "Range",
+        "search" : "Search",
+        "raw" : "Raw",
+        "history" : "History",
+        "user_discussion" : "User discussion",
+        "record" : "Record",
+        "state" : "State",
+        "revert" : "Revert",
+        "why" : "Reason",
+        "edit" : "Edit",
+        "preview" : "Preview",
+        "move" : "Move",
+        "upload" : "Upload",
+        "version" : "Version",
+        "stop" : "Stop",
+        "close" : "Closed",
+        "open" : "Open",
+        "agreement" : "Agreement",
+        "template" : "Template",
+        "category" : "Category",
+        "file" : "File",
+        "writer" : "Writer",
+        "editor" : "Editor",
+        "hide" : "Hide",
+        "check" : "Check",
+        "destruction" : "Destruction",
+        "tool" : "Tool",
+        "recent" : "Recently",
+        "password" : "Password",
+        "login" : "Sign in",
+        "logout" : "Sign out",
+        "register" : "Sign up",
+        "language" : "Language",
+        "compare" : "Compare",
+        "email" : "Email",
+        "key" : "Key",
+        "all" : "All",
+        "sub" : "Sub",
+        "create" : "Create",
+        "acl" : "ACL",
+        "upper" : "Parent",
+        "other" : "Other",
+        "random" : "Random",
+        "error" : "Error",
+        "next" : "Next",
+        "previous" : "Previous",
+        "authority" : "Authority",
+        "connect" : "Connect",
+        "explanation" : "Explanation",
+        "default" : "Default",
+        "lastest" : "Lastest",
+        "type" : "Type",
+        "in_progress" : "In progress",
+        "start" : "Start",
+        "pass" : "Passing",
+        "file_name" : "File name",
+        "pinned" : "Pinned",
+        "markup" : "Markup",
+        "title" : "Title",
+        "reference" : "Reference",
+        "icon" : "Icon",
+        "view" : "View",
+        "content" : "Content",
+        "on" : "On",
+        "off" : "Off",
+        "unset" : "Unset",
+        "extension" : "Extension",
+        "empty" : "Empty",
+        "domain" : "Domain",
+        "result" : "Result",
+        "_comment_1.1_" : "Time",
+            "second" : "Second(s)",
+            "hour" : "Hour(s)",
+            "limitless" : "Limitless",
+            "time" : "Time",
+            "period" : "Period",
+            "end" : "End",
+        "_comment_1.2_" : "User",
+            "user" : "User",
+            "admin" : "Administrator",
+            "owner" : "Owner",
+            "ip" : "IP",
+            "member" : "Member",
+        "_comment_1.3_" : "Ban",
+            "ban" : "Block",
+            "blocked" : "Blocked",
+            "release" : "Unblock",
+    "_comment_2_" : "Func",
+        "wiki_restart" : "Restart wiki engine",
+        "update" : "Update",
+        "need_document" : "Required Document(s)",
+        "close_discussion" : "Closed discussion(s)",
+        "open_discussion" : "Open discussion(s)",
+        "recent_discussion" : "Recently discussion(s)",
+        "recent_change" : "Recently edit(s)",
+        "edit_filter" : "Contents filter",
+        "recent_ban" : "Block(s) record",
+        "load" : "Load another document",
+        "edit_filter_rule" : "Contents filter rule",
+        "move_history" : "History of moveing",
+        "other_tool" : "Other tools",
+        "admin_tool" : "Administrator[s] tools",
+        "check_user" : "Check user[s] login history",
+        "compare_target" : "Comparison target name",
+        "authorize" : "Authorize",
+        "indexing" : "Database Indexing",
+        "hide_release" : "Unhide",
+        "pinned_release" : "Unpinned",
+        "discussion_tool" : "Discussion tools",
+        "discussion_raw" : "Discussion raw",
+        "oauth_signin_facebook" : "Sign-in with Facebook",
+        "oauth_signin_naver" : "Sign-in with NAVER",
+        "oauth_signin_discord" : "Sign-in with Discord",
+        "oauth_signin_kakao" : "Sign-in with Kakao",
+        "connection" : "Connection",
+        "new_connection" : "Connect...",
+        "user_setting" : "User settings",
+        "now_password" : "Current password",
+        "new_password" : "New password",
+        "password_confirm" : "Confirm password",
+        "oauth_connection" : "OAuth Connection",
+        "password_search" : "Password finder",
+        "login_able" : "Loginable",
+        "band_ban" : "Range block",
+        "band_blocked" : "Range blocked",
+        "under_category" : "Sub-category",
+        "count" : "Number of Contributions",
+        "alarm" : "Notifications(s)",
+        "user_document" : "User document",
+        "user_head" : "Custom <HEAD>",
+        "encryption_method" : "Encryption method",
+        "check_key" : "Check authentication key",
+        "reset_user_ok" : "Check Success",
+        "name_or_ip_or_regex" : "Username or IP or Regex",
+        "ban_period" : "Period to block",
+        "not_sure" : "Not sure",
+        "use_push_alarm" : "Enable Push Notification",
+        "edit_button_paragraph" : "Paragraph",
+        "password_change" : "Change password",
+        "email_change" : "Change email",
+        "acl_change" : "Change document[s] ACL",
+        "user_tool" : "User[s] tools",
+        "skin_info" : "Skin information",
+        "closed_discussion" : "Closed discussions",
+        "agreed_discussion" : "Agreed discussions",
+        "history_delete" : "Delete history",
+        "direct_input" : "Direct input",
+        "acl_record" : "ACL record",
+        "last_edit_time" : "Last edited time",
+        "admin_group" : "Administrator groups",
+        "topic_setting" : "Discussion settings",
+        "old_page" : "Document(s) modified a long time ago",
+        "skin_set" : "Skin setting(s)",
+        "many_delete" : "Document bulk delete",
+        "edit_req" : "Edit request",
+        "edit_req_check" : "Check edit request",
+        "accept_edit_request" : "Accept edit request",
+        "history_add" : "Add history",
+        "all_register_num" : "The number of application forms",
+        "replace_move" : "Swaping documents",
+        "merge_move" : "Merging documents",
+        "add_admin_group" : "Add administrator groups",
+        "add_watchlist" : "Add watchlist",
+        "blocked_user" : "Blocked user",
+        "blocked_admin" : "Blocked administrator",
+        "category_title" : "Documents under this category",
+        "topic_name_change" : "Change discussion name",
+        "topic_acl_setting" : "Discussion ACL setting",
+        "topic_acl" : "Discussion ACL",
+        "delete_admin_group": "Delete admin group",
+        "main_skin_set" : "Main skin setting(s)",
+        "reset_backlink" : "Reset backlink",
+        "link_in_this" : "Links in this document",
+        "star_doc" : "Document(s) of interest",
+        "add_star_doc" : "Add document(s) of interest",
+        "get_sitemap" : "Create or renewal sitemap.xml",
+        "simple_check" : "Simple check",
+        "add_user" : "Add user",
+        "2fa" : "2FA",
+        "2fa_password" : "2FA password",
+        "2fa_password_change" : "Change 2FA password",
+        "_comment_2.1_" : "Filter",
+            "_comment_2.1.1_" : "List",
+                "interwiki_list" : "Interwiki(s) list",
+                "email_filter_list" : "Email filter(s) list",
+                "id_filter_list" : "Username filter(s) list",
+                "edit_filter_list" : "Contents filter(s) list",
+                "file_filter_list" : "File name filter(s) list",
+                "edit_tool_list" : "Edit tool(s) list",
+                "image_license_list" : "Image license(s) list",
+                "extension_filter_list" : "Extension filter(s) list",
+            "_comment_2.1.2_" : "Add",
+                "interwiki_add" : "Add Interwiki",
+                "edit_filter_add" : "Add contents filter",
+                "id_filter_add" : "Add username filter",
+                "email_filter_add" : "Add email filter",
+                "file_filter_add" : "Add file name filter",
+                "edit_tool_add" : "Add edit tool",
+                "image_license_add" : "Add image license",
+                "extension_filter_add" : "Add extension filter",
+        "_comment_2.2_" : "Setting",
+            "setting" : "Setting",
+            "restart_required" : "Restart required",
+            "oauth_setting" : "OAuth settings",
+            "adsense_setting" : "Adsense settings",
+            "adsense_enable" : "Adsense enable",
+            "skin_setting" : "Skin settings",
+            "main_acl_setting" : "Default ACL settings",
+            "_comment_2.2.1_" : "List",
+                "main_setting" : "Main settings",
+                "text_setting" : "Text settings",
+                "main_head" : "Global <HEAD>",
+                "main_body" : "Top of body",
+                "main_bottom_body" : "Bottom of body",
+            "_comment_2.2.2_" : "Main",
+                "wiki_name" : "Wiki[s] name",
+                "wiki_logo" : "Wiki[s] logo",
+                "main_page" : "Main page",
+                "bottom_text" : "Bottom text",
+                "max_file_size" : "Max file size",
+                "backup_interval" : "Backup Cycles",
+                "wiki_skin" : "Wiki[s] default Skin",
+                "no_register" : "Disallow signing up",
+                "hide_ip" : "Hide IP address",
+                "wiki_host" : "Wiki host address",
+                "wiki_port" : "Wiki port number",
+                "wiki_secret_key" : "Wiki secret key",
+                "email_required" : "Email required",
+                "smtp_setting_required" : "Email SMTP setting required",
+                "update_branch" : "Branch to import updates",
+                "slow_edit" : "Continuous edit limit",
+                "requires_approval" : "Requires approval for register",
+                "approval_question": "Registeration questions",
+                "backup_where" : "Backup location",
+                "ua_get_off" : "Turn off members information collection",
+            "_comment_2.2.3_" : "Text",
+                "register_text" : "Terms of sign-up",
+                "non_login_alert" : "Non-login alert",
+                "edit_bottom_text" : "Editing textarea bottom notice",
+                "copyright_checkbox_text" : "Copyright Agreenment text as checkbox",
+                "check_key_text" : "Check authentication key notice",
+                "email_title" : "Email subject",
+                "email_text" : "Email content",
+                "email_insert_text" : "Email input box text",
+                "password_search_text" : "Password finder text",
+                "reset_user_text" : "Password reset complete text",
+                "error_401" : "ACL view limited document notice",
+                "error_404" : "Missing document notice",
+                "edit_help" : "Editing textarea phrase",
+                "upload_help" : "File upload phrase",
+                "upload_default" : "File upload other Default",
+            "_comment_2.2.4_" : "Google",
+                "recaptcha" : "reCAPTCHA",
+                "smtp_setting" : "Email SMTP setting",
+                "smtp_server" : "SMTP Server address",
+                "smtp_security": "SMTP Connection security",
+                "smtp_port" : "SMTP Server port",
+                "smtp_username" : "SMTP Username",
+                "smtp_password" : "SMTP Password",
+        "_comment_2.3_" : "List",
+            "open_discussion_list" : "Open discussion(s) list",
+            "discussion_list" : "Discussion(s) list",
+            "admin_list" : "Administrator(s) list",
+            "member_list" : "Member(s) list",
+            "authority_use_list" : "Authority use list",
+            "admin_group_list" : "Administrator group(s) list",
+            "all_document_list" : "All document(s) list",
+            "watchlist" : "Watchlist",
+            "image_file_list" : "Image file(s) list",
+            "short_page" : "Short page(s) list",
+            "long_page" : "Long page(s) list",
+            "_comment_2.3.1_" : "ACL document list",
+                "acl_document_list" : "ACL document(s) list",
+                "acl_required" : "Required ACL",
+            "_comment_2.3.2_" : "ACL List",
+                "ban_authority" : "Block authority",
+                "discussion_authority" : "Discussion manage authority",
+                "user_check_authority" : "User check authority",
+                "document_acl_authority" : "Document ACL manage authority",
+                "history_hide_authority" : "History hide authority",
+                "authorization_authority" : "Authorization authority",
+                "owner_authority" : "Owner authority",
+            "_comment_2.3.3_" : "Record",
+                "edit_record" : "Edit record",
+                "discussion_record" : "Discussion record",
+        "_comment_2.4_" : "Topic tool",
+            "topic_tool" : "Discussion management tools",
+            "topic_state" : "Discussion status",
+            "topic_delete" : "Delete this thread",
+        "_comment_2.5_" : "Period",
+            "1_day" : "1 day",
+            "5_day" : "5 days",
+            "30_day" : "30 days",
+            "180_day" : "180 days",
+            "360_day" : "360 days",
+        "_comment_2.6_" : "ACL",
+            "admin_acl" : "Administrators only",
+            "member_acl" : "Members only",
+            "50_edit_acl" : "Only members with 50 or more document edits",
+            "all_acl" : "All users",
+            "email_acl" : "Only users with email",
+            "owner_acl" : "Owner only",
+            "before_acl" : "Only those who have edited this document before",
+            "ban_acl" : "Include blocked users",
+            "ban_admin_acl" : "Blocked users and administrators",
+            "30_day_acl" : "Only members 30 days after sign up",
+            "_comment_2.6_1_" : "Set",
+                "document_acl" : "Document ACL",
+                "discussion_acl" : "Discussion(s) ACL",
+                "view_acl" : "Reading ACL",
+                "user_document_acl" : "User document ACL",
+                "upload_acl" : "Upload ACL",
+                "edit_req_acl" : "Edit request ACL",
+                "many_upload_acl" : "Upload multiple files ACL",
+                "vote_acl" : "Vote ACL",
+        "_comment_2.7_" : "Application list",
+            "application_list": "Application list",
+            "application_time": "Application time",
+            "answer": "Answer",
+            "approve": "Approve",
+            "decline": "Decline",
+            "approve_or_decline": "Approve or reject",
+            "no_applications_now" : "There are no applications.",
+            "approval_requirement_disabled": "Approval requirement is disabled now. You can enable this feature on settings",
+        "_comment_2.8_" : "Vote",
+            "vote_list" : "Vote list(s)",
+            "add_vote" : "Add vote",
+            "open_vote" : "Public vote",
+            "not_open_vote" : "Private vote",
+            "close_vote_list" : "Closed vote list(s)",
+            "open_vote_list" : "Open vote list(s)",
+            "vote" : "Vote",
+            "result_vote" : "Result of a vote",
+            "1_line_1_q" : "1 option per line.",
+            "close_vote" : "Close vote",
+            "re_open_vote" : "Reopen vote",
+    "_comment_3_" : "Long",
+        "application_submitted": "Applicatied successfully for registration",
+        "waiting_for_approval": "Application for registration has been made successfully. Please wait for approval by administrators.",
+        "ie_no_data_required" : "Operation cannot continue because all required data has not been collected.",
+        "oauth_settings_not_found" : "The administrator has not provided any data about using this feature.",
+        "oauth_disabled" : "The administrator has disabled this feature.",
+        "http_warring" : "Warning: If you are not on HTTPS connection, Your information can be leaked. We won't response to that.",
+        "user_head_warring" : "User data will be deleted if you close the browser or when you sign in.",
+        "no_login_warring" : "You are not logged in. The IP address will be logged when editing or discussing with non-login.",
+        "user_reset_sign" : "Your account information has changed like this.",
+        "update_warring" : "Manual updates are recommended if your version is 0.2 or lower than the latest version. For Windows, the contents of the route folder disappear.",
+        "default_edit_help" : "Describe it here",
+        "markup_enabled" : "Markup enabled",
+        "many_delete_help" : "Please write down the document[s] name one by one on the line.",
+        "sqlite_only" : "SQLite only",
+        "approval_question_visible_only_when_approval_on" : "Approval questions are visible only when approval requirement is on",
+        "oauth_explain" : "To use the OAuth login feature, you must set the 'publish_url' value to a domain address that includes the HTTPS protocol, and actually support HTTPS connections.",
+        "msg_whatchlist_lmt": "You can add as many as",
+        "enter_html" : "Please enter HTML",
+        "exp_edit_conflict" : "Editing conflict occurred",
+        "same_ip_exist" : "Same IP exists",
+        "_comment_3.1_" : "Error",
+            "update_error" : "Auto update is not supported.",
+            "inter_error" : "Internal error.",
+            "authority_error" : "Insufficient privileges.",
+            "no_login_error" : "Non-login status.",
+            "no_exist_user_error" : "The account does not exist.",
+            "no_admin_block_error" : "You cannot block or check administrators.",
+            "skin_error" : "This skin is not support settings.",
+            "same_id_exist_error" : "There are users with the same username.",
+            "long_id_error" : "Username must be shorter than 20 characters.",
+            "id_char_error" : "Only Korean letters, alphabets are allowed for Username.",
+            "file_exist_error" : "The file does not exist.",
+            "password_error" : "The password is different.",
+            "recaptcha_error" : "Go through the reCAPTCHA.",
+            "file_extension_error" : "Only files with the specified extension can be uploaded.",
+            "edit_record_error" : "Edit reason can not be more than 500 characters.",
+            "same_file_error" : "A file with the same name exists.",
+            "file_capacity_error" : "Maximum file capacity (MB): ",
+            "decument_exist_error" : "The document with that title already exists.",
+            "password_diffrent_error" : "Reconfirm password and input password are different.",
+            "edit_filter_error" : "Censored by edit filter.",
+            "file_name_error" : "Only English alphabets, Korean alphabets, spaces, underscore, and hyphens are allowed for the file name.",
+            "topic_long_error" : "The discussion[s] topic must not exceed 256 characters.",
+            "email_error" : "No one has this email.",
+            "regex_error" : "There is an error in the regular expression.",
+            "decument_404_error" : "This document does not exist.",
+            "fast_edit_error" : "You can edit another document after this period (Second(s)) : ",
+            "too_many_dec_error" : "This feature is not supported because there are too many documents.",
+            "application_not_found" : "Application not found",
+            "invalid_password_error" : "The Password or ID is invalid.",
+            "watchlist_overflow_error": "You cannot add more than ten documents.",
+            "copyright_disagreed" : "You have to agree copyright noticement to contribute",
+            "email_send_error" : "Email transfer failed.",
+            "restart_fail_error" : "Restart failed. Please use manual restart.",
+            "same_email_error" : "There are users using the same email.",
+            "input_email_error" : "There is a problem with the input value."
+}

+ 30 - 0
lang/help_tool.py

@@ -0,0 +1,30 @@
+import re
+import json
+
+o_json = json.loads(open('en-US.json', encoding='utf8').read())
+
+print('n_name : ', end = '')
+n_name = input()
+n_json = json.loads(open(n_name + '.json', encoding='utf8').read())
+
+print()
+for i in list(n_json):
+    if not i in o_json:
+        del n_json[i]
+
+for i in list(o_json):
+    if not re.search(r'^_', i[0]):
+        if not i in n_json:
+            print('o_title : ' + i)
+            print('o_text : ' + o_json[i])
+
+            print('n_text : ', end = '')
+            n_text = input()
+
+            n_json = {**n_json, **{i : n_text}}
+
+n_data = json.dumps(n_json, indent = 4, ensure_ascii = False)
+
+f = open(n_name + '.json', "w", encoding='utf8')
+f.write(n_data)
+f.close()

+ 404 - 0
lang/ko-KR.json

@@ -0,0 +1,404 @@
+{
+    "delete_admin_group": "관리자 그룹 삭제",
+    "document_name": "문서명",
+    "non_login_alert": "비로그인 알림",
+    "hide": "숨김",
+    "discussion_acl": "토론들 ACL",
+    "ongoing": "진행 중",
+    "user_tool": "사용자 도구",
+    "compare_target": "비교 대상 이름",
+    "email_title": "이메일 제목",
+    "acl_required": "ACL 필요",
+    "blocked": "차단자",
+    "authorization_authority": "권한 부여 권한",
+    "open_discussion": "열린 토론",
+    "move_history": "이동 기록",
+    "register": "회원가입",
+    "reset_user_text": "암호 초기화 완료 문구",
+    "no_register": "가입 불가능",
+    "view_acl": "읽기 ACL",
+    "notice": "알림",
+    "login": "로그인",
+    "smtp_setting": "이메일 SMTP 설정",
+    "smtp_server": "SMTP 서버 주소",
+    "smtp_security": "SMTP 보안 프로토콜",
+    "smtp_port": "SMTP 서버 포트",
+    "close": "닫기",
+    "closed": "닫힘",
+    "start": "시작",
+    "encryption_method": "비밀번호 암호화 방식",
+    "why": "사유",
+    "user_check_authority": "사용자 검사 권한",
+    "second": "초",
+    "load": "불러오기",
+    "user_discussion": "사용자 토론",
+    "upper": "상위",
+    "email": "이메일",
+    "closed_discussion": "닫힌 토론",
+    "acl": "ACL",
+    "history_hide_authority": "역사 숨김 권한",
+    "go": "이동",
+    "document_acl": "문서 ACL",
+    "secret_key": "비밀 키",
+    "raw": "원본",
+    "file": "파일",
+    "state": "상태",
+    "authorize": "권한 부여",
+    "check_user": "사용자 검사",
+    "email_acl": "이메일 인증을 받은 사용자만",
+    "email_error": "해당 이메일을 가진 사용자가 존재하지 않습니다.",
+    "version": "버전",
+    "open": "열기",
+    "update_branch": "업데이트를 가져올 브랜치",
+    "edit_filter_error": "편집 필터에 의해 금지된 단어가 사용되었습니다.",
+    "ip": "IP",
+    "pinned_release": "고정 해제",
+    "next": "다음",
+    "password_change": "비밀번호 변경",
+    "hour": "시간",
+    "connect": "연결",
+    "edit_record": "편집 기록",
+    "preview": "미리보기",
+    "view": "보기",
+    "no_login_error": "비로그인 상태입니다.",
+    "upload": "파일 올리기",
+    "user_name": "사용자 이름",
+    "member_acl": "가입자만",
+    "search": "검색",
+    "etc": "기타",
+    "edit_filter": "편집 필터",
+    "no_exist_user_error": "계정이 존재하지 않습니다.",
+    "compare": "비교",
+    "password_error": "비밀번호가 올바르지 않습니다.",
+    "default": "기본값",
+    "wiki_name": "위키 이름",
+    "acl_document_list": "ACL 문서 목록",
+    "connection": "연결",
+    "oauth_disabled": "관리자가 이 기능을 비활성화시켰습니다.",
+    "random": "무작위",
+    "filter": "필터",
+    "band_blocked": "대역 차단됨",
+    "password_diffrent_error": "입력한 비밀번호와 비밀번호 확인이 서로 다릅니다.",
+    "180_day": "180일",
+    "markup_enabled": "문법 사용 가능",
+    "all_acl": "모든 사용자",
+    "send": "전송",
+    "not_sure": "확실하지 않음",
+    "file_name_error": "파일명에는 알파벳, 한글, 공백, 밑줄 및 빼기 기호만 사용할 수 있습니다.",
+    "pass": "넘기기",
+    "recaptcha_error": "'로봇이 아닙니다'를 통해 reCAPTCHA를 통과하세요.",
+    "file_capacity_error": "최대 파일 크기 (MB): ",
+    "setting": "설정",
+    "end": "끝",
+    "error": "오류",
+    "oauth_signin_discord": "디스코드 아이디로 로그인",
+    "ban": "차단",
+    "email_insert_text": "이메일 입력란 문구",
+    "check_key_text": "인증키 검사 문구",
+    "other_tool": "기타 도구",
+    "recent_discussion": "최근 토론",
+    "oauth_signin_naver": "네이버 아이디로 로그인",
+    "record": "기록",
+    "owner_authority": "소유자 권한",
+    "wiki_port": "위키 포트",
+    "limitless": "무기한",
+    "normal": "일반",
+    "reset_user_ok": "검사 성공",
+    "in_progress": "진행 중",
+    "under_category": "하위 분류",
+    "range": "대역",
+    "edit_filter_rule": "편집 필터 규칙",
+    "oauth_connection": "Oauth 연결",
+    "hide_ip": "IP 주소 숨기기",
+    "topic_tool": "토론 관리 도구",
+    "user_document": "사용자 문서",
+    "id": "아이디",
+    "no_login_warring": "비로그인 상태입니다. 편집 시 지금 접속한 IP가 기록됩니다.",
+    "decument_404_error": "이 문서는 존재하지 않습니다.",
+    "key": "키",
+    "lastest": "최신",
+    "now_password": "현재 비밀번호",
+    "same_file_error": "동일한 이름의 파일이 존재합니다.",
+    "same_id_exist_error": "이미 동일한 이름의 계정이 존재합니다.",
+    "max_file_size": "최대 파일 크기",
+    "new_password": "새 비밀번호",
+    "authority_use_list": "권한 사용 목록",
+    "alarm": "알림",
+    "main_body": "본문 상단",
+    "all_document_list": "모든 문서 목록",
+    "update": "업데이트",
+    "login_able": "로그인 허용",
+    "discussion_tool": "토론 도구",
+    "regex": "정규표현식",
+    "file_filter_add": "파일명 필터 추가",
+    "wiki_restart": "위키 엔진 재시작",
+    "oauth_settings_not_found": "관리자가 해당 기능을 수행하기 위해 필요한 데이터를 제공하지 않았습니다.",
+    "discussion_raw": "토론 댓글 원본",
+    "main_setting": "메인 설정",
+    "password": "비밀번호",
+    "update_error": "자동 업데이트가 지원되지 않습니다.",
+    "need_document": "필요한 문서들",
+    "sub": "하위",
+    "template": "틀",
+    "user_document_acl": "사용자 문서 ACL",
+    "password_confirm": "비밀번호 확인",
+    "pinned": "고정",
+    "edit_filter_add": "편집 필터 추가",
+    "ban_authority": "차단 권한",
+    "file_extension_error": "지정된 확장자의 파일만 올릴 수 있습니다.",
+    "host": "호스트",
+    "email_text": "이메일 내용",
+    "recent": "최근",
+    "admin_acl": "관리자만",
+    "wiki_host": "위키 호스트",
+    "error_404": "존재하지 않는 문서 문구",
+    "member_list": "사용자 목록",
+    "register_text": "회원가입 정책",
+    "interwiki_list": "인터위키 목록",
+    "email_change": "이메일 변경",
+    "edit_button_paragraph": "문단",
+    "check": "검사",
+    "admin": "관리자",
+    "edit_filter_list": "편집 필터 목록",
+    "wiki_skin": "위키 스킨",
+    "admin_group": "관리자 그룹",
+    "all": "전체",
+    "skin_error": "사용 중인 스킨은 스킨 설정 기능을 지원하지 않습니다.",
+    "member": "가입자",
+    "backlink": "역링크",
+    "no_admin_block_error": "관리자를 검사하거나 차단할 수 없습니다.",
+    "recaptcha": "reCAPTCHA",
+    "create": "생성",
+    "restart": "재시작",
+    "oauth_setting": "OAuth 설정",
+    "edit_bottom_text": "편집창 하단 문구",
+    "copyright_checkbox_text": "저작권 동의 문구(체크박스 형태)",
+    "authority": "권한",
+    "document": "문서",
+    "decument_exist_error": "이동하려는 문서에 이미 문서가 존재합니다.",
+    "skin_setting": "스킨 설정",
+    "discussion_list": "토론 목록",
+    "restart_required": "재시작 필요",
+    "save": "저장",
+    "delete": "삭제",
+    "file_exist_error": "파일이 존재하지 않습니다.",
+    "text_setting": "문구 설정",
+    "document_acl_authority": "문서 ACL 관리 권한",
+    "wiki_logo": "위키 로고",
+    "smtp_setting_required": "이메일 SMTP 설정 필요",
+    "adsense_setting": "애드센스 설정",
+    "smtp_username": "SMTP 아이디",
+    "previous": "이전",
+    "name_or_ip_or_regex": "사용자 이름 혹은 IP 주소 혹은 정규표현식",
+    "editor": "편집자",
+    "wiki_secret_key": "위키 비밀 키",
+    "band_ban": "대역 차단",
+    "http_warring": "경고: HTTPS 연결을 사용하지 않는다면 개인정보가 유출될 수 있습니다. 이 사항에 의해 입는 피해는 사용자에게 책임이 있음을 알려드립니다.",
+    "update_warring": "최신 버전보다 0.2 버전 이상 낮은 경우 수동 업데이트를 권장합니다. 윈도우의 경우 route 폴더의 내용이 사라집니다.",
+    "discussion_name": "토론 제목",
+    "discussion": "토론",
+    "main": "메인",
+    "server": "서버",
+    "admin_tool": "관리 도구",
+    "interwiki_add": "인터위키 추가",
+    "return": "돌아가기",
+    "logout": "로그아웃",
+    "bottom_text": "하단 내용",
+    "30_day": "30일",
+    "topic_long_error": "토론 제목은 256자를 넘을 수 없습니다.",
+    "error_401": "ACL 읽기 제한 문서 문구",
+    "history": "역사",
+    "admin_group_list": "관리자 그룹 목록",
+    "time": "시간",
+    "password_search_text": "비밀번호 찾기 문구",
+    "agreed_discussion": "합의된 토론",
+    "explanation": "설명",
+    "name": "이름",
+    "period": "기간",
+    "writer": "작성자",
+    "oauth_signin_facebook": "페이스북 아이디로 로그인",
+    "long_id_error": "ID는 20자보다 짧아야 합니다.",
+    "edit_record_error": "사유는 500자를 넘을 수 없습니다.",
+    "revert": "복원",
+    "discussion_authority": "토론 관리 권한",
+    "user_setting": "사용자 설정",
+    "admin_list": "관리자 목록",
+    "add": "추가",
+    "check_key": "인증 키 확인",
+    "file_filter_list": "파일명 필터 목록",
+    "5_day": "5일",
+    "email_filter_list": "이메일 필터 목록",
+    "user_reset_sign": "사용자의 계정 정보가 다음과 같이 변경되었습니다.",
+    "ban_period": "차단 기간",
+    "use_push_alarm": "푸쉬 알림 사용",
+    "email_filter_add": "이메일 필터 추가",
+    "oauth_signin_kakao": "카카오톡 아이디로 로그인",
+    "authority_error": "권한이 없습니다.",
+    "type": "유형",
+    "acl_change": "문서 ACL 변경",
+    "owner": "소유자",
+    "password_search": "비밀번호 찾기",
+    "file_name": "파일명",
+    "close_discussion": "닫힌 토론",
+    "language": "언어",
+    "id_char_error": "오직 한글과 알파벳만 사용 가능합니다.",
+    "id_filter_add": "ID 필터 추가",
+    "skin": "스킨",
+    "user_head": "사용자 <HEAD>",
+    "agreement": "동의",
+    "stop": "중지",
+    "application_submitted": "회원가입 신청 완료",
+    "waiting_for_approval": "회원가입 신청이 정상적으로 접수됐습니다. 관리자의 승인을 기다려주세요.",
+    "ie_no_data_required": "이 기능을 수행하기 위해 필요한 데이터가 제공되지 않았습니다.",
+    "port": "포트",
+    "reload": "갱신",
+    "indexing": "DB 인덱싱",
+    "topic_state": "토론 상태",
+    "watchlist": "주시 목록",
+    "main_page": "대문",
+    "user": "사용자",
+    "skin_info": "스킨 정보",
+    "new_connection": "연결...",
+    "discussion_record": "토론 참여 기록",
+    "move": "이동",
+    "recent_change": "최근 편집",
+    "destruction": "취소",
+    "count": "기여 횟수",
+    "main_head": "메인 <HEAD>",
+    "recent_ban": "차단 기록",
+    "smtp_password": "SMTP 비밀번호",
+    "id_filter_list": "ID 필터 목록",
+    "other": "기타",
+    "edit": "편집",
+    "open_discussion_list": "열린 토론 목록",
+    "user_head_warring": "비로그인시 브라우저를 닫거나 로그인시 사용자가 지정한 정보는 삭제됩니다.",
+    "email_required": "이메일 필요",
+    "1_day": "1일",
+    "regex_error": "정규표현식에 오류가 있습니다.",
+    "backup_interval": "백업 주기",
+    "license": "라이선스",
+    "hide_release": "숨김 해제",
+    "360_day": "360일",
+    "inter_error": "내부 오류.",
+    "50_edit_acl": "기여 횟수가 50회 이상인 가입자만",
+    "tool": "도구",
+    "adsense_enable": "애드센스 사용",
+    "list": "목록",
+    "release": "차단 해제",
+    "category": "분류",
+    "history_delete": "역사 삭제",
+    "markup": "문법",
+    "title": "제목",
+    "edit_tool_list": "편집 도구 목록",
+    "edit_tool_add": "편집 도구 추가",
+    "image_license_list": "이미지 라이선스 목록",
+    "image_license_add": "이미지 라이선스 추가",
+    "direct_input": "직접 입력",
+    "acl_record": "ACL 기록",
+    "main_bottom_body": "본문 하단",
+    "reference": "참고",
+    "owner_acl": "소유자만",
+    "last_edit_time": "최근 수정 시각",
+    "link": "링크",
+    "icon": "아이콘",
+    "topic_setting": "토론 설정",
+    "old_page": "편집된 지 오래된 문서",
+    "skin_set": "스킨 설정",
+    "edit_help": "편집 창 문구",
+    "default_edit_help": "이곳에 내용을 입력해주세요.",
+    "many_delete": "문서 대량 삭제",
+    "many_delete_help": "한 줄에 문서명을 한 개씩 적어주세요.",
+    "content": "내용",
+    "upload_acl": "파일 올리기 ACL",
+    "topic_delete": "토론 삭제",
+    "edit_req": "편집 요청",
+    "edit_req_check": "편집 요청 검사",
+    "sqlite_only": "SQLite만",
+    "off": "끄기",
+    "slow_edit": "편집 속도 제한 시간",
+    "requires_approval": "가입시 승인 필요",
+    "approval_question": "회원가입 질문",
+    "public_key": "공개 키",
+    "fast_edit_error": "편집 속도가 너무 빠릅니다. 제한 (초): ",
+    "main_acl_setting": "기본 ACL 설정",
+    "edit_req_acl": "편집 요청 ACL",
+    "application_list": "가입신청 목록",
+    "application_time": "가입신청 일시",
+    "answer": "답변",
+    "approve": "승인",
+    "decline": "거절",
+    "approve_or_decline": "승인 및 거절",
+    "history_add": "역사 추가",
+    "too_many_dec_error": "문서 수가 너무 많아서 지원하지 않는 기능입니다.",
+    "approval_question_visible_only_when_approval_on": "회원가입 질문은 가입시 승인필요 설정이 활성화됐을때만 보여집니다. 이 설정은 메인 설정에서 활성하실 수 있습니다.",
+    "no_applications_now": "회원가입 신청이 없습니다.",
+    "application_not_found": "존재하지 않는 회원가입 신청입니다.",
+    "approval_requirement_disabled": "현재 가입시 승인필요 설정이 비활성화되어있습니다. 필요시 설정에서 활성화할 수 있습니다.",
+    "all_register_num": "모든 가입 신청자의 수",
+    "replace_move": "문서 바꾸기",
+    "merge_move": "문서 병합",
+    "oauth_explain": "OAuth 로그인 기능을 사용하려면 'publish_url' 값을 HTTPS 프로토콜을 포함한 도메인 주소로 설정하고, 실제로 HTTPS 연결을 지원해야 합니다.",
+    "add_admin_group": "관리자 그룹 추가",
+    "add_watchlist": "주시 문서 추가",
+    "blocked_user": "차단된 사용자",
+    "blocked_admin": "차단한 관리자",
+    "invalid_password_error": "비밀번호 또는 아이디가 없습니다.",
+    "accept_edit_request": "편집 요청 승인",
+    "msg_whatchlist_lmt": "최대 추가 가능 갯수",
+    "watchlist_overflow_error": "추가 한도를 초과했으므로 더 이상 추가할 수 없습니다. 필요없는 항목을 삭제하십시오.",
+    "unset": "미설정",
+    "copyright_disagreed": "저작권 동의문구에 동의하여야 합니다.",
+    "category_title": "이 분류 아래 문서들",
+    "extension_filter_list": "확장자 필터 목록",
+    "extension_filter_add": "확장자 필터 추가",
+    "extension": "확장자",
+    "ban_acl": "차단된 사용자 포함",
+    "ban_admin_acl": "차단된 사용자 및 관리자",
+    "topic_name_change": "토론 제목 변경",
+    "topic_acl_setting": "토론 ACL 설정",
+    "topic_acl": "토론 ACL",
+    "main_skin_set": "기본 스킨 설정",
+    "image_file_list": "이미지 파일 목록",
+    "many_upload_acl": "다중 파일 올리기 ACL",
+    "reset_backlink": "역링크 초기화",
+    "link_in_this": "이 문서의 링크",
+    "star_doc": "관심 문서",
+    "add_star_doc": "관심 문서 추가",
+    "enter_html": "HTML을 입력하세요.",
+    "exp_edit_conflict": "편집 충돌 발생",
+    "backup_where": "백업 위치",
+    "empty": "빈칸",
+    "email_send_error": "이메일 전송이 실패했습니다.",
+    "get_sitemap": "sitemap.xml 만들거나 갱신하기",
+    "same_ip_exist": "동일한 아이피가 존재합니다.",
+    "restart_fail_error": "재시작이 실패했습니다. 수동 재시작을 이용해주세요.",
+    "domain": "도메인",
+    "before_acl": "이 문서를 이전에 편집한 적 있는 사람만",
+    "30_day_acl": "가입 후 30일이 지난 가입자만",
+    "simple_check": "간편 검사",
+    "add_user": "계정 추가",
+    "result": "결과",
+    "vote_list": "투표 목록",
+    "add_vote": "투표 추가",
+    "open_vote": "공개 투표",
+    "not_open_vote": "비밀 투표",
+    "close_vote_list": "닫힌 투표 목록",
+    "vote": "투표",
+    "result_vote": "투표 결과",
+    "1_line_1_q": "1줄당 1개의 선택지를 쓰세요.",
+    "open_vote_list" : "열린 투표 목록",
+    "close_vote" : "투표 닫기",
+    "re_open_vote" : "투표 다시 열기",
+    "on" : "켜기",
+    "2fa" : "2차 인증",
+    "2fa_password" : "2차 비밀번호",
+    "2fa_password_change" : "2차 비밀번호 변경",
+    "vote_acl" : "투표 ACL",
+    "upload_help" : "파일 올리기 문구",
+    "upload_default" : "파일 기타란 기본값",
+    "same_email_error" : "동일한 이메일을 사용하는 사용자가 있습니다.",
+    "input_email_error" : "입력 값에 문제가 있습니다.",
+    "short_page" : "짧은 문서 목록",
+    "long_page" : "긴 문서 목록",
+    "ua_get_off" : "가입자 정보 수집 끄기"
+}

+ 8 - 1
route/api_raw.py

@@ -11,7 +11,14 @@ def api_raw_2(conn, name):
             curs.execute(db_change("select data from data where title = ?"), [name])
         data = curs.fetchall()
         if data:
-            json_data = { "title" : name, "data" : render_set(title = name, data = data[0][0], s_data = 1) }
+            json_data = {
+                "title" : name, 
+                "data" : render_set(
+                    doc_name = name, 
+                    doc_data = data[0][0],
+                    data_type = 'raw'
+                )
+            }
 
             return flask.jsonify(json_data)
         

+ 6 - 2
route/api_topic_sub.py

@@ -4,7 +4,6 @@ def api_topic_sub_2(conn, topic_num):
     curs = conn.cursor()
 
     topic_num = str(topic_num)
-    get_acl = acl_check('', 'render')
 
     if flask.request.args.get('num', None):
         curs.execute(db_change("select id, data, date, ip, block, top from topic where code = ? and id + 0 = ? + 0 order by id + 0 asc"), [
@@ -40,7 +39,12 @@ def api_topic_sub_2(conn, topic_num):
                 "blind" : i[4],
                 
                 "ip_pas" : ip_a[i[3]],
-                "data_pas" : render_set(data = data_v, num = 2, include = 'topic_' + i[0], acl = get_acl)
+                "data_pas" : render_set(
+                    doc_data = data_v, 
+                    data_type = 'api_view',
+                    data_in = i[0],
+                    doc_acl = 0
+                )
             }
 
         return flask.jsonify(data_a)

+ 7 - 7
route/api_w.py

@@ -13,9 +13,9 @@ def api_w_2(conn, name):
             if flask.request.method == 'POST':
                 data_org = flask.request.form.get('data', '')
                 data_pas = render_set(
-                    title = name, 
-                    data = data_org, 
-                    num = 2
+                    doc_name = name, 
+                    doc_data = data_org, 
+                    data_type = 'api_view'
                 )
 
                 return flask.jsonify({
@@ -58,10 +58,10 @@ def api_w_2(conn, name):
                             )
                         
                     data_pas = render_set(
-                        title = name_org, 
-                        data = json_data, 
-                        num = 2, 
-                        include = include_data
+                        doc_name = name_org, 
+                        doc_data = json_data, 
+                        data_type = 'api_view',
+                        data_in = include_data
                     )
 
                     return flask.jsonify({

+ 3 - 3
route/edit.py

@@ -103,9 +103,9 @@ def edit_2(conn, name):
         curs.execute(db_change("delete from back where title = ? and type = 'no'"), [name])
         
         render_set(
-            title = name,
-            data = content,
-            num = 1
+            doc_name = name,
+            doc_data = content,
+            data_type = 'backlink'
         )
         
         conn.commit()

+ 3 - 3
route/edit_backlink_reset.py

@@ -10,9 +10,9 @@ def edit_backlink_reset_2(conn, name):
         curs.execute(db_change("delete from back where title = ? and type = 'no'"), [name])
         
         render_set(
-            title = name,
-            data = old[0][0],
-            num = 1
+            doc_name = name,
+            doc_data = old[0][0],
+            data_type = 'backlink'
         )
 
     return redirect('/xref/' + url_pas(name))

+ 3 - 3
route/edit_revert.py

@@ -52,9 +52,9 @@ def edit_revert_2(conn, name):
             )
 
             render_set(
-                title = name,
-                data = data[0][0],
-                num = 1
+                doc_name = name,
+                doc_data = data[0][0],
+                data_type = 'backlink'
             )
 
             conn.commit()

+ 3 - 3
route/func_upload.py

@@ -95,9 +95,9 @@ def func_upload_2(conn, app_var):
             curs.execute(db_change("insert into acl (title, data, type) values (?, 'admin', 'decu')"), ['file:' + name])
 
             render_set(
-                title = 'file:' + name,
-                data = file_d,
-                num = 1
+                doc_name = 'file:' + name,
+                doc_data = file_d,
+                data_type = 'backlink'
             )
 
             history_plus(

+ 12 - 12
route/tool/func.py

@@ -195,21 +195,21 @@ def last_change(data):
 def easy_minify(data, tool = None):
     return last_change(data)
 
-def render_set(title = '', data = '', num = 0, s_data = 0, include = None, acl = None):
-    if not acl:
-        acl = acl_check(title, 'render')
-
-    if acl == 1:
+def render_set(doc_name = '', doc_data = '', data_type = 'view', data_in = '', doc_acl = ''):
+    # data_type in ['view', 'raw', 'api_view', 'backlink']
+    doc_acl = acl_check(doc_name, 'render') if doc_acl == '' else doc_acl
+    doc_data = 0 if not doc_data else doc_data
+        
+    if doc_acl == 1:
         return 'HTTP Request 401.3'
-    elif s_data == 1:
-        return data
     else:
-        if data != None:
-            darkmode = flask.request.cookies.get('main_css_darkmode', '0')
-            
-            return render_do(title, data, num, include)
+        if data_type == 'raw':
+            return doc_data
         else:
-            return 'HTTP Request 404'
+            if doc_data != 0:
+                return render_do(doc_name, doc_data, data_type, data_in)
+            else:
+                return 'HTTP Request 404'
 
 def update(ver_num, set_data):
     print('----')

+ 40 - 29
route/tool/mark.py

@@ -15,8 +15,12 @@ curs = ''
 if os.path.exists('route/tool/custom.py'):
     from .custom import custom_mark
 else:
-    def custom_mark(conn, data, title, num, include):
-        return [data, '', []]
+    def custom_mark(conn, doc_data, doc_name, data_in):
+        return [
+            doc_data, 
+            '', 
+            []
+        ]
 
 def load_conn2(data):
     global conn
@@ -39,44 +43,51 @@ def send_parser(data):
 
     return data
 
-def render_do(title, data, num, include):
-    # num == 1 -> commit O | html
-    # num == 2 -> commit X | list
-    # num == 3 -> commit X 
+def render_do(doc_name, doc_data, data_type, data_in):
+    data_in = None if data_in == '' else data_in
     curs.execute(db_change('select data from other where name = "markup"'))
     rep_data = curs.fetchall()
-    if rep_data[0][0] == 'namumark':
-        data = namumark(conn, data, title, include)
-    elif rep_data[0][0] == 'custom':
-        data = custom_mark(conn, data, title, include)
-    elif rep_data[0][0] == 'js_onmark':
-        include = (include + '_') if include else ''
-        data = [
-            '<div id="' + include + 'render_content">' + html.escape(data) + '</div>', 
+    if rep_data[0][0] in ('namumark', 'js_onmark'):
+        data_in = (data_in + '_') if data_in else ''
+        data_end = [
+            '<div class="render_content" id="' + data_in + 'render_content">' + html.escape(doc_data) + '</div>', 
             '''
                 do_onmark_render(
                     test_mode = 0, 
-                    name_id = "''' + include + '''render_content",
-                    name_include = "''' + include + '''",
-                    name_doc = "''' + title.replace('"', '//"') + '''",
+                    name_id = "''' + data_in + '''render_content",
+                    name_include = "''' + data_in + '''",
+                    name_doc = "''' + doc_name.replace('"', '//"') + '''",
                 );
             ''',
             []
         ]
+    elif rep_data[0][0] == 'custom':
+        data_end = custom_mark(
+            conn, 
+            doc_data, 
+            doc_name, 
+            data_in
+        )
     else:
-        data = [data, '', []]
+        data_end = [
+            doc_data, 
+            '', 
+            []
+        ]
 
-    if num in [1, 3]:
-        if data[2] == []:
-            curs.execute(db_change("insert into back (title, link, type) values ('test', ?, 'nothing')"), [title])
+    if data_type == 'backlink':
+        if data_end[2] == []:
+            curs.execute(db_change("insert into back (title, link, type) values ('test', ?, 'nothing')"), [doc_name])
         else:
-            curs.executemany(db_change("insert into back (link, title, type) values (?, ?, ?)"), data[2])
-            curs.execute(db_change("delete from back where title = ? and type = 'no'"), [title])
+            curs.executemany(db_change("insert into back (link, title, type) values (?, ?, ?)"), data_end[2])
+            curs.execute(db_change("delete from back where title = ? and type = 'no'"), [doc_name])
 
-        if num != 3:
-            conn.commit()
-
-    if num == 2:
-        return [data[0], data[1]]
+        conn.commit()
     else:
-        return data[0] + '<script>' + data[1] + '</script>'
+        if data_type == 'api_view':
+            return [
+                data_end[0], 
+                data_end[1]
+            ]
+        else:
+            return data_end[0] + '<script>' + data_end[1] + '</script>'

+ 2 - 2
route/view_read.py

@@ -81,8 +81,8 @@ def view_read_2(conn, name):
             else_data = re.sub(r'\r\n$', '', else_data)
 
         end_data = render_set(
-            title = name,
-            data = else_data
+            doc_name = name,
+            doc_data = else_data
         )
 
         if not num and acl_check(name, 'render') != 1:

+ 4 - 0
views/main_css/css/main.css

@@ -246,4 +246,8 @@ blockquote {
 
 hr {
     border-top: 1px solid lightgray;
+}
+
+.render_content {
+    white-space: pre-wrap;
 }

+ 99 - 48
views/main_css/js/render_onmark.js

@@ -3,7 +3,13 @@ function do_url_change(data) {
     return encodeURIComponent(data);
 }
 
-function do_link_change(data, data_nowiki, no_change = 0) {
+function do_nowiki_change(data, data_nowiki) {
+    return data.replace(/<span id="((?:.*)(?:nowiki_(?:[^"]+)))"><\/span>/, function(x, x_1) {
+        return data_nowiki[x_1];
+    });
+}
+
+function do_link_change(data, data_nowiki, no_change, data_nowiki) {
     data = data.replace(/^:/, '');
     
     if(no_change === 0) {
@@ -16,6 +22,8 @@ function do_link_change(data, data_nowiki, no_change = 0) {
     var link_main = data.replace(/#(.*)$/, '');
     var link_sub = data_var.length !== 1 ? ('#' + data_var[data_var.length - 1]) : '';
     
+    link_main = do_nowiki_change(link_main, data_nowiki);
+    
     return [link_main, link_sub];
 }
 
@@ -188,7 +196,7 @@ function do_onmark_link_render(data, data_js, name_doc, name_include, data_nowik
             var i = 0;
             while(i < 2) {
                 if(i === 0) {
-                    var link_data_var = do_link_change(link_real, data_nowiki);
+                    var link_data_var = do_link_change(link_real, data_nowiki, 0, data_nowiki);
                     var link_main = link_data_var[0];
                     var link_sub = link_data_var[1];
                     
@@ -196,7 +204,7 @@ function do_onmark_link_render(data, data_js, name_doc, name_include, data_nowik
                     var var_link_data = '/w/' + do_url_change(link_main) + link_sub;
                 } else {
                     var var_link_type = 'title';
-                    var var_link_data = do_js_safe_change(link_real);
+                    var var_link_data = do_js_safe_change(link_main) + link_sub;
                 }
                 
                 data_js += '' +
@@ -341,9 +349,9 @@ function do_onmark_macro_render(data) {
     return data;
 }
 
-function do_onmark_middle_render(data, data_js, name_include) {
+function do_onmark_middle_render(data, data_js, name_include, data_nowiki) {
     var middle_stack = [];
-    var middle_re = /(?:{{{([^{} ]+)|(}}}))/;
+    var middle_re = /(?:{{{([^{} ]*)|(}}}))/;
     
     var syntax_on = 0;
     
@@ -363,40 +371,46 @@ function do_onmark_middle_render(data, data_js, name_include) {
                 middle_stack.pop();
             }
         } else {
-            if(middle_data[1].match(/^(?:(#(?:[0-9a-f-A-F]{3}){1,2})|#([a-zA-Z]+))/)) {
-                var color = middle_data[1].match(/^(?:(#(?:[0-9a-f-A-F]{3}){1,2})|#([a-zA-Z]+))/);
-                color = color[1] ? color[1] : color[2];
-                
-                data = data.replace(middle_re, '<span style="color: ' + color + ';">');
-                middle_stack.push('</span>');
-            } else if(middle_data[1].match(/^(\+|-)([1-5])/)) {
-                var font = middle_data[1].match(/^(\+|-)([1-5])/);
-                if(font[1] === '+') {
-                    var font_size = String(100 + (20 * Number(font[2]))) + '%';
+            if(middle_stack.includes('</code>')) {
+                data = data.replace(middle_re, '<middle_start>' + middle_data[1]);
+                middle_stack.push('<middle_end>');
+            } else {
+                if(middle_data[1].match(/^(?:(#(?:[0-9a-f-A-F]{3}){1,2})|#([a-zA-Z]+))/)) {
+                    var color = middle_data[1].match(/^(?:(#(?:[0-9a-f-A-F]{3}){1,2})|#([a-zA-Z]+))/);
+                    color = color[1] ? color[1] : color[2];
+
+                    data = data.replace(middle_re, '<span style="color: ' + color + ';">');
+                    middle_stack.push('</span>');
+                } else if(middle_data[1].match(/^(\+|-)([1-5])/)) {
+                    var font = middle_data[1].match(/^(\+|-)([1-5])/);
+                    if(font[1] === '+') {
+                        var font_size = String(100 + (20 * Number(font[2]))) + '%';
+                    } else {
+                        var font_size = String(100 - (10 * Number(font[2]))) + '%';
+                    }
+
+                    data = data.replace(middle_re, '<span style="font-size: ' + font_size + ';">');
+                    middle_stack.push('</span>');
+                } else if(middle_data[1] === '#!wiki') {
+                    var wiki_re = /{{{#!wiki(?: style=["']([^"']*)["']\n)?/;
+
+                    var wiki = data.match(wiki_re);
+                    var wiki_style = wiki[1] ? wiki[1] : '';
+
+                    data = data.replace(wiki_re, '<div_wiki_start style="' + wiki_style + '">');  
+                    middle_stack.push('<div_wiki_end>');
+                } else if(middle_data[1] === '#!html') {
+                    html_n += 1;
+
+                    data = data.replace(middle_re, '<span id="' + name_include + 'render_contect_' + String(html_n) + '">');
+                    middle_stack.push('</span>');
+                } else if(middle_data[1] === '#!folding') {
+                    data = data.replace(middle_re, '<div>');
+                    middle_stack.push('</div>');
                 } else {
-                    var font_size = String(100 - (10 * Number(font[2]))) + '%';
+                    data = data.replace(middle_re, '<code>' + middle_data[1]);
+                    middle_stack.push('</code>');
                 }
-                
-                data = data.replace(middle_re, '<span style="font-size: ' + font_size + ';">');
-                middle_stack.push('</span>');
-            } else if(middle_data[1] === '#!wiki') {
-                var wiki_re = /{{{#!wiki(?: style=["']([^"']*)["']\n)?/;
-                
-                var wiki = data.match(wiki_re);
-                var wiki_style = wiki[1] ? wiki[1] : '';
-                
-                data = data.replace(wiki_re, '<div_wiki_start style="' + wiki_style + '">');  
-                middle_stack.push('<div_wiki_end>');
-            } else if(middle_data[1] === '#!html') {
-                html_n += 1;
-                
-                data = data.replace(middle_re, '<span id="' + name_include + 'render_contect_' + String(html_n) + '">');
-                middle_stack.push('</span>');
-            } else if(middle_data[1] === '#!folding') {
-                data = data.replace(middle_re, '<div>');
-                middle_stack.push('</div>');
-            } else {
-                data = data.replace(middle_re, '<middle_start>' + middle_data[1]);   
             }
         }
     }
@@ -411,7 +425,23 @@ function do_onmark_middle_render(data, data_js, name_include) {
     data = data.replace(/<middle_start>/g, '{{{');
     data = data.replace(/<middle_end>/g, '}}}');
     
-    return [data, data_js];
+    var code_re = /<code>(\n*(?:(?:(?!<\/code>).)+\n*)+)<\/code>/;
+    var code_n = 0;
+    while(1) {
+        code_n += 1;
+        
+        var code_data = data.match(code_re);
+        if(!code_data) {
+            break;
+        }
+        
+        data_nowiki[name_include + 'nowiki_mid_' + String(code_n)] = code_data[1];
+        data_js += do_data_try_insert(name_include + 'nowiki_mid_' + String(code_n), do_js_safe_change(code_data[1]));
+        data = data.replace(code_re, '<span id="' + name_include + 'nowiki_mid_' + String(code_n) + '"></span>');
+    }
+    
+    console.log(data_js);
+    return [data, data_js, data_nowiki];
 }
 
 function do_onmark_last_render(data) {
@@ -433,7 +463,7 @@ function do_onmark_last_render(data) {
     return data;
 }
 
-function do_onmark_include_render(data, data_js, name_include) {
+function do_onmark_include_render(data, data_js, name_include, data_nowiki) {
     var include_re = /\[include\(((?:(?!\)\]).)+)\)\]/;
     var i = 0;
     while(1) {
@@ -444,23 +474,44 @@ function do_onmark_include_render(data, data_js, name_include) {
             break;
         }
         
+        var include_name = do_nowiki_change(
+            include_data[1].match(/^([^,]+)/)[1],
+            data_nowiki
+        );
+        var include_add_re = /, *([^=]+)=((?:(?:(?!\)]|,).)+)+)/;
+        var include_add_data = []
+        var include_data = include_data[1];
+        while(1) {
+            var include_add = include_data.match(include_add_re);
+            if(!include_add) {
+                break;
+            }
+            
+            include_add_data.push([
+                include_add[1], 
+                do_nowiki_change(include_add[2], data_nowiki)
+            ]);
+            include_data = include_data.replace(include_add_re, '');
+        }
+        
         data = data.replace(include_re,
-            '<a id="' + name_include + 'include_link" class="include_' + String(i) + '" href="">(' + include_data[1] + ')</a>' +
+            '<a id="' + name_include + 'include_link" class="include_' + String(i) + '" href="">(' + include_name + ')</a>' +
             '<div id="' + name_include + 'include_' + String(i) + '"></div>'
         );
         
-        data_js += 'load_include("' + do_js_safe_change(include_data[1]) + '", "' + name_include + 'include_' + String(i) + '", []);\n'
+        data_js += 'load_include("' + do_js_safe_change(include_name) + '", "' + name_include + 'include_' + String(i) + '", ' + JSON.stringify(include_add_data) + ');\n'
     }
     
     return [data, data_js];
 }
 
-function do_onmark_nowiki_before_render(data, data_js, name_include, data_nowiki, num_nowiki = 0) {
+function do_onmark_nowiki_before_render(data, data_js, name_include, data_nowiki) {
+    var num_nowiki = 0;
     data = data.replace(/\\(.)/g, function(x, x_1) {
         num_nowiki += 1;
-        data_nowiki[name_include + 'nowiki_' + String(num_nowiki)] = x_1;
-        data_js += do_data_try_insert(name_include + 'nowiki_' + String(num_nowiki), do_js_safe_change(x_1));
-        return '<span id="' + name_include + 'nowiki_' + String(num_nowiki) + '"></span>';
+        data_nowiki[name_include + 'nowiki_one_' + String(num_nowiki)] = x_1;
+        data_js += do_data_try_insert(name_include + 'nowiki_one_' + String(num_nowiki), do_js_safe_change(x_1));
+        return '<span id="' + name_include + 'nowiki_one_' + String(num_nowiki) + '"></span>';
     });
     
     return [data, data_js, data_nowiki, num_nowiki];
@@ -524,15 +575,15 @@ function do_onmark_render(test_mode = 1, name_id = '', name_include = '', name_d
     data = data_var[0];
     data_js = data_var[1];
     data_nowiki = data_var[2];
-    var num_nowiki = data_var[3];
     
-    data_var = do_onmark_include_render(data, data_js, name_include);
+    data_var = do_onmark_include_render(data, data_js, name_include, data_nowiki);
     data = data_var[0];
     data_js = data_var[1];
     
-    data_var = do_onmark_middle_render(data, data_js, name_include);
+    data_var = do_onmark_middle_render(data, data_js, name_include, data_nowiki);
     data = data_var[0];
     data_js = data_var[1];
+    data_nowiki = data_var[2];
     
     data = do_onmark_text_render(data);
     data = do_onmark_heading_render(data);