Explorar el Código

Merge pull request #644 from 2du/master

버그 수정
잉여강화기 (SPUP) hace 7 años
padre
commit
4f8941a180
Se han modificado 100 ficheros con 866 adiciones y 1405 borrados
  1. 7 4
      .github/ISSUE_TEMPLATE.md
  2. 57 16
      app.py
  3. 0 1
      emergency_tool.py
  4. 15 2
      language/en-US.json
  5. 21 8
      language/ko-KR.json
  6. 7 7
      readme-ko.md
  7. 2 1
      requirements.txt
  8. 16 6
      route/acl.py
  9. 9 5
      route/acl_list.py
  10. 16 16
      route/admin_plus.py
  11. 15 0
      route/api_skin_info.py
  12. 25 0
      route/api_version.py
  13. 11 6
      route/api_w.py
  14. 10 9
      route/change_password.py
  15. 14 12
      route/check_key.py
  16. 1 1
      route/close_topic_list.py
  17. 10 0
      route/easter_egg.py
  18. 24 26
      route/edit.py
  19. 6 0
      route/error_404.py
  20. 2 4
      route/login.py
  21. 9 0
      route/logout.py
  22. 9 0
      route/main_file.py
  23. 1 1
      route/manager.py
  24. 9 4
      route/need_email.py
  25. 7 5
      route/now_update.py
  26. 38 36
      route/other.py
  27. 0 41
      route/preview.py
  28. 89 45
      route/recent_changes.py
  29. 6 0
      route/search.py
  30. 43 24
      route/setting.py
  31. 240 120
      route/tool/func.py
  32. 0 0
      route/tool/set_mark/markdown.py
  33. 11 14
      route/tool/set_mark/namu.py
  34. 1 1
      route/tool/set_mark/tool.py
  35. 49 46
      route/topic.py
  36. 1 1
      route/topic_admin.py
  37. 21 0
      route/topic_block.py
  38. 0 179
      version-ko.md
  39. 3 0
      views/easter_egg.html
  40. 2 2
      views/main_css/css/main.css
  41. 0 0
      views/main_css/css/oauth.css
  42. 19 0
      views/main_css/js/do_preview.js
  43. 1 3
      views/main_css/js/folding.js
  44. 17 0
      views/main_css/js/insert_data.js
  45. 16 0
      views/main_css/js/load_ver.js
  46. 3 1
      views/main_css/js/open_foot.js
  47. 3 6
      views/main_css/js/topic_load.js
  48. 0 90
      views/main_css/katex/README.md
  49. 0 321
      views/main_css/katex/contrib/auto-render.js
  50. 0 0
      views/main_css/katex/contrib/auto-render.min.js
  51. 0 14
      views/main_css/katex/contrib/copy-tex.css
  52. 0 191
      views/main_css/katex/contrib/copy-tex.js
  53. 0 1
      views/main_css/katex/contrib/copy-tex.min.css
  54. 0 0
      views/main_css/katex/contrib/copy-tex.min.js
  55. 0 134
      views/main_css/katex/contrib/mathtex-script-type.js
  56. 0 1
      views/main_css/katex/contrib/mathtex-script-type.min.js
  57. BIN
      views/main_css/katex/fonts/KaTeX_AMS-Regular.ttf
  58. BIN
      views/main_css/katex/fonts/KaTeX_AMS-Regular.woff
  59. BIN
      views/main_css/katex/fonts/KaTeX_AMS-Regular.woff2
  60. BIN
      views/main_css/katex/fonts/KaTeX_Caligraphic-Bold.ttf
  61. BIN
      views/main_css/katex/fonts/KaTeX_Caligraphic-Bold.woff
  62. BIN
      views/main_css/katex/fonts/KaTeX_Caligraphic-Bold.woff2
  63. BIN
      views/main_css/katex/fonts/KaTeX_Caligraphic-Regular.ttf
  64. BIN
      views/main_css/katex/fonts/KaTeX_Caligraphic-Regular.woff
  65. BIN
      views/main_css/katex/fonts/KaTeX_Caligraphic-Regular.woff2
  66. BIN
      views/main_css/katex/fonts/KaTeX_Fraktur-Bold.ttf
  67. BIN
      views/main_css/katex/fonts/KaTeX_Fraktur-Bold.woff
  68. BIN
      views/main_css/katex/fonts/KaTeX_Fraktur-Bold.woff2
  69. BIN
      views/main_css/katex/fonts/KaTeX_Fraktur-Regular.ttf
  70. BIN
      views/main_css/katex/fonts/KaTeX_Fraktur-Regular.woff
  71. BIN
      views/main_css/katex/fonts/KaTeX_Fraktur-Regular.woff2
  72. BIN
      views/main_css/katex/fonts/KaTeX_Main-Bold.ttf
  73. BIN
      views/main_css/katex/fonts/KaTeX_Main-Bold.woff
  74. BIN
      views/main_css/katex/fonts/KaTeX_Main-Bold.woff2
  75. BIN
      views/main_css/katex/fonts/KaTeX_Main-BoldItalic.ttf
  76. BIN
      views/main_css/katex/fonts/KaTeX_Main-BoldItalic.woff
  77. BIN
      views/main_css/katex/fonts/KaTeX_Main-BoldItalic.woff2
  78. BIN
      views/main_css/katex/fonts/KaTeX_Main-Italic.ttf
  79. BIN
      views/main_css/katex/fonts/KaTeX_Main-Italic.woff
  80. BIN
      views/main_css/katex/fonts/KaTeX_Main-Italic.woff2
  81. BIN
      views/main_css/katex/fonts/KaTeX_Main-Regular.ttf
  82. BIN
      views/main_css/katex/fonts/KaTeX_Main-Regular.woff
  83. BIN
      views/main_css/katex/fonts/KaTeX_Main-Regular.woff2
  84. BIN
      views/main_css/katex/fonts/KaTeX_Math-BoldItalic.ttf
  85. BIN
      views/main_css/katex/fonts/KaTeX_Math-BoldItalic.woff
  86. BIN
      views/main_css/katex/fonts/KaTeX_Math-BoldItalic.woff2
  87. BIN
      views/main_css/katex/fonts/KaTeX_Math-Italic.ttf
  88. BIN
      views/main_css/katex/fonts/KaTeX_Math-Italic.woff
  89. BIN
      views/main_css/katex/fonts/KaTeX_Math-Italic.woff2
  90. BIN
      views/main_css/katex/fonts/KaTeX_SansSerif-Bold.ttf
  91. BIN
      views/main_css/katex/fonts/KaTeX_SansSerif-Bold.woff
  92. BIN
      views/main_css/katex/fonts/KaTeX_SansSerif-Bold.woff2
  93. BIN
      views/main_css/katex/fonts/KaTeX_SansSerif-Italic.ttf
  94. BIN
      views/main_css/katex/fonts/KaTeX_SansSerif-Italic.woff
  95. BIN
      views/main_css/katex/fonts/KaTeX_SansSerif-Italic.woff2
  96. BIN
      views/main_css/katex/fonts/KaTeX_SansSerif-Regular.ttf
  97. BIN
      views/main_css/katex/fonts/KaTeX_SansSerif-Regular.woff
  98. BIN
      views/main_css/katex/fonts/KaTeX_SansSerif-Regular.woff2
  99. BIN
      views/main_css/katex/fonts/KaTeX_Script-Regular.ttf
  100. BIN
      views/main_css/katex/fonts/KaTeX_Script-Regular.woff

+ 7 - 4
.github/ISSUE_TEMPLATE.md

@@ -1,7 +1,10 @@
-## Explanation (설명)
-
-## Desired results (원하는 결과)
+## Environment (환경)
+OS :
+Python version :
+openNAMU version :
+Skin : 
+Skin version : 
 
-## Current Results (현재 결과)
+## Explanation (설명)
 
 ## Screenshot (스크린샷)

+ 57 - 16
app.py

@@ -8,13 +8,15 @@ for i_data in os.listdir("route"):
 
         exec("from route." + f_src + " import *")
 
-r_ver = 'v3.0.9-stable-07'
-c_ver = '400000'
+r_ver = 'v3.1.0-master-06'
+c_ver = '400001'
+s_ver = '2'
 
 print('Version : ' + r_ver)
 
 app_var = json.loads(open('data/app_variables.json', encoding='utf-8').read())
 
+# DB
 all_src = []
 for i_data in os.listdir("."):
     f_src = re.search("(.+)\.db$", i_data)
@@ -68,6 +70,7 @@ class EverythingConverter(werkzeug.routing.PathConverter):
 
 app.jinja_env.filters['md5_replace'] = md5_replace
 app.jinja_env.filters['load_lang'] = load_lang
+app.jinja_env.filters['cut_100'] = cut_100
 
 app.url_map.converters['everything'] = EverythingConverter
 
@@ -145,7 +148,7 @@ if setup_tool != 0:
     create_data['rb'] = ['block', 'end', 'today', 'blocker', 'why', 'band']
     create_data['back'] = ['title', 'link', 'type']
     create_data['custom'] = ['user', 'css']
-    create_data['other'] = ['name', 'data']
+    create_data['other'] = ['name', 'data', 'coverage']
     create_data['alist'] = ['name', 'acl']
     create_data['re_admin'] = ['who', 'what', 'time']
     create_data['alarm'] = ['name', 'data', 'date']
@@ -166,6 +169,7 @@ if setup_tool != 0:
 
     update()
 
+# Init
 curs.execute('select name from alist where acl = "owner"')
 if not curs.fetchall():
     curs.execute('delete from alist where name = "owner"')
@@ -263,6 +267,20 @@ else:
 
 conn.commit()
 
+curs.execute('select data from other where name = "s_ver"')
+ver_set_data = curs.fetchall()
+if not ver_set_data:
+    curs.execute('insert into other (name, data) values ("s_ver", ?)', [s_ver])
+
+    print('Skin update required')
+else:
+    if int(ver_set_data[0][0]) < int(s_ver):
+        curs.execute('delete from other where name = "s_ver"')
+        curs.execute('insert into other (name, data) values ("s_ver", ?)', [s_ver])
+
+        print('Skin update required')
+
+## Func
 @app.route('/del_alarm')
 def del_alarm():
     return del_alarm_2(conn)
@@ -303,7 +321,7 @@ def acl_list():
 
 @app.route('/admin_plus/<name>', methods=['POST', 'GET'])
 def admin_plus(name = None):
-    return admin_plus_2(conn)
+    return admin_plus_2(conn, name)
         
 @app.route('/admin_list')
 def admin_list():
@@ -364,7 +382,7 @@ def block_log(name = None, tool = None):
             
 @app.route('/search', methods=['POST'])
 def search():
-    return redirect('/search/' + url_pas(flask.request.form.get('search', 'test')))
+    return search_2(conn)
 
 @app.route('/goto', methods=['POST'])
 def goto():
@@ -471,10 +489,7 @@ def check_key(tool = 'check_pass_key'):
            
 @app.route('/logout')
 def logout():
-    flask.session['state'] = 0
-    flask.session.pop('id', None)
-
-    return redirect('/user')
+    return logout_2(conn)
     
 @app.route('/ban/<name>', methods=['POST', 'GET'])
 def user_ban(name = None):
@@ -541,9 +556,24 @@ def title_random():
 
 @app.route('/skin_set')
 def skin_set():
-    return re_error('/error/5')
+    data = flask.make_response(re_error('/error/5'))
+
+    curs.execute("select data from other where name = 'language'")
+    main_data = curs.fetchall()
+
+    data.set_cookie('language', main_data[0][0])
+
+    curs.execute('select data from user_set where name = "lang" and id = ?', [ip_check()])
+    user_data = curs.fetchall()
+    if user_data:
+        data.set_cookie('user_language', user_data[0][0])
+    else:
+        data.set_cookie('user_language', main_data[0][0])
+
+    return data
     
-@app.route('/api/w/<everything:name>')
+# API
+@app.route('/api/w/<everything:name>', methods=['POST', 'GET'])
 def api_w(name = ''):
     return api_w_2(conn, name)
     
@@ -551,24 +581,35 @@ def api_w(name = ''):
 def api_raw(name = ''):
     return api_raw_2(conn, name)
 
+@app.route('/api/version')
+def api_version():
+    return api_version_2(conn, r_ver, c_ver)
+
+@app.route('/api/skin_info')
+def api_skin_info():
+    return api_skin_info_2(conn)
+
 @app.route('/api/topic/<everything:name>/sub/<sub>')
 def api_topic_sub(name = '', sub = '', time = ''):
     return api_topic_sub_2(conn, name, sub, time)
     
+## File
+@app.route('/views/easter_egg.html')
+def easter_egg():
+    return easter_egg_2(conn)
+
 @app.route('/views/<everything:name>')
 def views(name = None):
     return views_2(conn, name)
 
 @app.route('/<data>')
 def main_file(data = None):
-    if re.search('\.txt$', data):
-        return flask.send_from_directory('./', data)
-    else:
-        return redirect('/w/' + url_pas(wiki_set(2)))
+    return main_file_2(conn, data)
 
+## End
 @app.errorhandler(404)
 def error_404(e):
-    return redirect('/w/' + url_pas(wiki_set(2)))
+    return error_404_2(conn)
 
 if __name__=="__main__":
     app.secret_key = rep_key

+ 0 - 1
emergency_tool.py

@@ -1,5 +1,4 @@
 import os
-import json
 import sqlite3
 import hashlib
 import threading

+ 15 - 2
language/en-US.json

@@ -79,6 +79,9 @@
         "previous" : "Previous",
         "authority" : "Authority",
         "connect" : "Connect",
+        "explanation" : "Explanation",
+        "default" : "Default",
+        "lastest" : "Lastest",
         "_comment_1.1_" : "Time",
             "second" : "Second(s)",
             "hour" : "Hour(s)",
@@ -144,6 +147,13 @@
         "user_document" : "User[s] document",
         "user_head" : "User[s] <head>",
         "user_document_acl" : "User[s] document ACL",
+        "admin_acl" : "Admin only",
+        "member_acl" : "Member only",
+        "50_edit_acl" : "Only members with 50 or more all document edits",
+        "all_acl" : "All Users",
+        "encryption_method" : "Encryption method",
+        "check_key" : "Check Authentication Key",
+        "reset_user_ok" : "Check Success",
         "_comment_2.1_" : "Filter",
             "_comment_2.1.1_" : "List",
                 "interwiki_list" : "Interwiki(s) list",
@@ -224,6 +234,7 @@
         "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[s] <head> will deleted if you close the browser or sign-in",
         "no_login_warring" : "Non-login status. IP is logged when working with non-login.",
+        "user_reset_sign" : "Your account information has changed like this.",
         "_comment_3.1_" : "Error",
             "update_error" : "Auto update is not support.",
             "inter_error" : "Internal error.",
@@ -237,7 +248,7 @@
             "id_char_error" : "Only hangul, alphabet and space are allowed for ID.",
             "file_exist_error" : "File does not exist.",
             "password_error" : "The password is different.",
-            "recaptcha_error" : "Go through the recaptcha.",
+            "recaptcha_error" : "Go through the reCAPTCHA.",
             "file_extension_error" : "Only jpg, gif, jpeg, png, webp is possible.",
             "edit_record_error" : "Edit reason can not be more than 500 characters.",
             "same_file_error" : "A file with the same name exists.",
@@ -245,5 +256,7 @@
             "decument_exist_error" : "The document already exists where you want to move it.",
             "password_diffrent_error" : "Reconfirm password and input password are different.",
             "edit_filter_error" : "Censored by edit filter.",
-            "file_name_error" : "Only alphabet, hangul, space, underscore, and minus signs are allowed for file names."
+            "file_name_error" : "Only alphabet, hangul, space, underscore, and minus signs are allowed for file names.",
+            "topic_long_error" : "The discussion name must not exceed 256 characters.",
+            "email_error" : "No one has this email."
 }

+ 21 - 8
language/ko-KR.json

@@ -79,6 +79,9 @@
         "previous" : "이전",
         "authority" : "권한",
         "connect" : "연결",
+        "explanation" : "설명",
+        "default" : "기본값",
+        "lastest" : "최신",
         "_comment_1.1_" : "시간",
             "second" : "초",
             "hour" : "시간",
@@ -103,7 +106,7 @@
         "close_discussion" : "닫힌 토론",
         "open_discussion" : "열린 토론",
         "recent_discussion" : "최근 토론",
-        "recent_change" : "최근 수정",
+        "recent_change" : "최근 편집",
         "edit_filter" : "편집 필터",
         "recent_ban" : "최근 차단",
         "load" : "다른 문서 불러오기",
@@ -113,7 +116,7 @@
         "admin_tool" : "관리 도구",
         "check_user" : "사용자 검사",
         "compare_target" : "비교 대상 이름",
-        "authorize" : "인증",
+        "authorize" : "권한 부여",
         "indexing" : "DB 인덱싱",
         "hide_release" : "표시",
         "notice_release" : "릴리즈 노트",
@@ -144,6 +147,13 @@
         "user_document" : "사용자 문서",
         "user_head" : "사용자 <head>",
         "user_document_acl" : "사용자 문서 ACL",
+        "admin_acl" : "관리자만",
+        "member_acl" : "가입자만",
+        "50_edit_acl" : "기여 횟수 총합 50회 이상 가입자만",
+        "all_acl" : "모든 사용자",
+        "encryption_method" : "암호화 방식",
+        "check_key" : "인증키 검사",
+        "reset_user_ok" : "검사 성공",
         "_comment_2.1_" : "필터",
             "_comment_2.1.1_" : "목록",
                 "interwiki_list" : "인터위키 목록",
@@ -169,7 +179,7 @@
                 "main_body" : "전역 <body>",
             "_comment_2.2.2_" : "메인",
                 "wiki_name" : "위키 이름",
-                "wiki_logo" : "위키 목록",
+                "wiki_logo" : "위키 로고",
                 "main_page" : "대문",
                 "bottom_text" : "하단 텍스트",
                 "max_file_size" : "파일 최대 파일 크기",
@@ -191,14 +201,14 @@
             "_comment_2.2.4_" : "Google",
                 "recaptcha" : "reCAPTCHA",
                 "google_imap" : "Google IMAP",
-                "google_email" : "Google 이일",
+                "google_email" : "Google 이일",
                 "google_app_password" : "Google 앱 비밀번호",
         "_comment_2.3_" : "목록",
             "open_discussion_list" : "열린 토론 목록",
             "discussion_list" : "토론 목록",
             "admin_list" : "관리자 목록",
             "member_list" : "사용자 목록",
-            "authority_use_list" : "권한 목록",
+            "authority_use_list" : "권한 사용 목록",
             "admin_group_list" : "관리자 그룹 목록",
             "all_document_list" : "모든 문서 목록",
             "watchlist" : "주시 목록",
@@ -212,7 +222,7 @@
                 "user_check_authority" : "사용자 검사 권한",
                 "document_acl_authority" : "문서 ACL 관리 권한",
                 "history_hide_authority" : "역사 숨김 권한",
-                "authorization_authority" : "인증 권한",
+                "authorization_authority" : "권한 부여 권한",
                 "owner_authority" : "소유자 권한",
             "_comment_2.3.3_" : "기록",
                 "edit_record" : "편집 기록",
@@ -224,6 +234,7 @@
         "http_warring" : "경고: HTTPS 연결을 사용하지 않는다면 개인정보가 유출될 수 있습니다. 이 사항에 의해 입는 피해는 사용자에게 책임이 있음을 알려드립니다.",
         "user_head_warring" : "비로그인시 브라우저를 닫거나 로그인시 사용자의 <head>는 삭제됩니다.",
         "no_login_warring" : "비로그인 상태입니다. 편집시 지금 접속한 IP 명의로 기록됩니다.",
+        "user_reset_sign" : "사용자의 계정 정보가 다음과 같이 변경 되었습니다.",
         "_comment_3.1_" : "오류",
             "update_error" : "자동 업데이트가 지원되지 않습니다.",
             "inter_error" : "내부 오류.",
@@ -237,7 +248,7 @@
             "id_char_error" : "오직 한글과 알파벳, 공백만 사용 가능합니다.",
             "file_exist_error" : "파일이 존재하지 않습니다.",
             "password_error" : "비밀번호가 다릅니다.",
-            "recaptcha_error" : "'나는 로봇이 아닙니다'를 통해 reCaptcha를 수행하세요.",
+            "recaptcha_error" : "'나는 로봇이 아닙니다'를 통해 reCAPTCHA를 수행하세요.",
             "file_extension_error" : "오직 jpg, gif, jpeg, png, webp 만 업로드할 수 있습니다.",
             "edit_record_error" : "수정 요약은 500자를 넘길 수 없습니다.",
             "same_file_error" : "똑같은 이름의 파일이 존재합니다.",
@@ -245,5 +256,7 @@
             "decument_exist_error" : "이동하려는 이름에 이미 문서가 존재합니다.",
             "password_diffrent_error" : "입력한 비밀번호와 비밀번호 확인이 서로 다릅니다.",
             "edit_filter_error" : "편집 필터에 의해 금지된 단어가 사용되었습니다.",
-            "file_name_error" : "파일 이름에는 알파벳, 한글, 공백, 밑줄 과 빼기 기호만 사용할 수 있습니다."
+            "file_name_error" : "파일 이름에는 알파벳, 한글, 공백, 밑줄 과 빼기 기호만 사용할 수 있습니다.",
+            "topic_long_error" : "토론 이름이 256자를 넘지 않아야 합니다.",
+            "email_error" : "이런 이메일을 가진 사용자가 없습니다."
 }

+ 7 - 7
readme-ko.md

@@ -5,20 +5,20 @@ openNAMU
 
 ![](https://raw.githubusercontent.com/2du/openNAMU/master/.github/logo.png)
 
-오픈나무는 파이썬 기반의 위키 엔진입니다. 파이썬과 그 의존성 모듈만 설치하면 사용할 수 있으며, 코드를 직접 수정하여 좀 더 주제에 특화된 위키를 만들 수 있습니다.
+openNAMU는 파이썬 기반의 위키 엔진입니다. 파이썬과 그 의존성 모듈만 설치하면 사용할 수 있으며, 코드를 직접 수정하여 좀 더 주제에 특화된 위키를 만들 수 있습니다.
 
 ### 목차
 [클론](#클론) | [기여](#기여) | [라이선스](#라이선스) | [기여자 목록](#기여자-목록) | [기타](#기타)
 
 ## 시작하기
-오픈나무는 파이썬 환경에서 동작하는 파이썬 애플리케이션으로, 파이썬 환경을 필요로 합니다.
+openNAMU는 파이썬 환경에서 동작하는 파이썬 애플리케이션으로, 파이썬 환경을 필요로 합니다.
 
-쉬운 오픈나무 설치를 위해 오픈나무 가이드를 따로 생성해두었으며, [이곳](https://github.com/Make-openNAMU/guide)에서 확인하실 수 있습니다.
+쉬운 openNAMU 설치를 위해 openNAMU 가이드를 따로 생성해두었으며, [이곳](https://github.com/Make-openNAMU/guide)에서 확인하실 수 있습니다.
 
 ### 가이드 목록
  * [파이썬 설치](https://github.com/Make-openNAMU/guide/blob/master/articles/ko-kr/install-python.md)
- * [오픈나무 시작](https://github.com/Make-openNAMU/guide/blob/master/articles/ko-kr/start-opennamu.md)
-   * [오픈나무 도커 시작(실험적 기능)](https://github.com/Make-openNAMU/guide/blob/master/articles/ko-kr/docker-install.md)
+ * [openNAMU 시작](https://github.com/Make-openNAMU/guide/blob/master/articles/ko-kr/start-opennamu.md)
+   * [openNAMU 도커 시작(실험적 기능)](https://github.com/Make-openNAMU/guide/blob/master/articles/ko-kr/docker-install.md)
 
 ## 클론
 아래 명령을 터미널(명령 프롬프트)에 입력하여 본 리포지토리를 클론할 수 있습니다.
@@ -29,10 +29,10 @@ openNAMU
  * `git clone -b master https://github.com/2du/openNAMU.git`
 
 ## 기여
-오픈나무에는 검증되지 않은 몇가지 버그가 존재할 수 있습니다. 당신의 오픈나무 사용과 버그 발견은 오픈나무의 발전을 돕습니다.
+openNAMU에는 검증되지 않은 몇가지 버그가 존재할 수 있습니다. 당신의 openNAMU 사용과 버그 발견은 openNAMU의 발전을 돕습니다.
 [이슈 생성하기](https://github.com/2du/openNAMU/issues/new)
 
-오픈나무는 완전한 오픈소스 프로젝트입니다. 새로운 기능을 추가하고 Pull Request를 생성해보세요.
+openNAMU는 완전한 오픈소스 프로젝트입니다. 새로운 기능을 추가하고 Pull Request를 생성해보세요.
 [Pull Request 생성하기](https://github.com/2du/openNAMU/compare)
 
 ## 라이선스

+ 2 - 1
requirements.txt

@@ -5,4 +5,5 @@ flask-Reggie
 flask-compress
 pysha3; python_version < "3.6"
 css-html-js-minify==2.2.2; python_version < "3.6"
-css-html-js-minify; python_version >= "3.6"
+css-html-js-minify; python_version >= "3.6"
+request

+ 16 - 6
route/acl.py

@@ -63,12 +63,12 @@ def acl_2(conn, name):
             
         return redirect('/acl/' + url_pas(name))            
     else:
-        data = '' + load_lang('document_acl') + '<br><br><select name="dec" ' + check_ok + '>'
+        data = '<h2>' + load_lang('document_acl') + '</h2><hr class=\"main_hr\"><select name="dec" ' + check_ok + '>'
     
         if re.search('^user:', name):
-            acl_list = [['', load_lang('normal')], ['user', load_lang('member')], ['all', load_lang('all')]]
+            acl_list = [['', 'normal'], ['user', 'member'], ['all', 'all']]
         else:
-            acl_list = [['', load_lang('normal')], ['user', load_lang('member')], ['admin', load_lang('admin')]]
+            acl_list = [['', 'normal'], ['user', 'member'], ['admin', 'admin'], ['50_edit', '50 edit']]
         
         curs.execute("select dec from acl where title = ?", [name])
         acl_data = curs.fetchall()
@@ -83,7 +83,7 @@ def acl_2(conn, name):
         data += '</select>'
         
         if not re.search('^user:', name):
-            data += '<hr class=\"main_hr\">' + load_lang('discussion_acl') + '<br><br><select name="dis" ' + check_ok + '>'
+            data += '<hr class=\"main_hr\"><h2>' + load_lang('discussion_acl') + '</h2><hr class=\"main_hr\"><select name="dis" ' + check_ok + '>'
         
             curs.execute("select dis, why, view from acl where title = ?", [name])
             acl_data = curs.fetchall()
@@ -97,7 +97,7 @@ def acl_2(conn, name):
                 
             data += '</select>'
 
-            data += '<hr class=\"main_hr\">' + load_lang('view_acl') + '<br><br><select name="view" ' + check_ok + '>'
+            data += '<hr class=\"main_hr\"><h2>' + load_lang('view_acl') + '</h2><hr class=\"main_hr\"><select name="view" ' + check_ok + '>'
             for data_list in acl_list:
                 if acl_data and acl_data[0][2] == data_list[0]:
                     check = 'selected="selected"'
@@ -106,7 +106,17 @@ def acl_2(conn, name):
                     
                 data += '<option value="' + data_list[0] + '" ' + check + '>' + data_list[1] + '</option>'
                 
-            data += '</select>'
+            data += '''
+                </select>
+                <h2>''' + load_lang('explanation') + '''</h2>
+                <ul>
+                    <li>normal : ''' + load_lang('default') + '''</li>
+                    <li>admin : ''' + load_lang('admin_acl') + '''</li>
+                    <li>member : ''' + load_lang('member_acl') + '''</li>
+                    <li>50 edit : ''' + load_lang('50_edit_acl') + '''</li>
+                    <li>all : ''' + load_lang('all_acl') + '''</li>
+                </ul>
+            '''
                 
             if check_ok == '':
                 if acl_data:

+ 9 - 5
route/acl_list.py

@@ -8,12 +8,12 @@ def acl_list_2(conn):
             <tbody>
                 <tr>
                     <td id="main_table_width_quarter">''' + load_lang('document_name') + '''</td>
-                    <td id="main_table_width_quarter">''' + load_lang('document') + ''' acl</td>
-                    <td id="main_table_width_quarter">''' + load_lang('discussion') + ''' acl</td>
-                    <td id="main_table_width_quarter">''' + load_lang('acl_required') + '''</td>
+                    <td id="main_table_width_quarter">''' + load_lang('document_acl') + '''</td>
+                    <td id="main_table_width_quarter">''' + load_lang('discussion_acl') + '''</td>
+                    <td id="main_table_width_quarter">''' + load_lang('view_acl') + '''</td>
     '''
     
-    curs.execute("select title, dec, dis, view, why from acl where dec = 'admin' or dec = 'user' or dis = 'admin' or dis = 'user' or view = 'admin' or view = 'user' order by title desc")
+    curs.execute("select title, dec, dis, view, why from acl where dec != '' or dis != '' or view != '' order by title desc")
     list_data = curs.fetchall()
     for data in list_data:
         if not re.search('^user:', data[0]) and not re.search('^file:', data[0]):
@@ -21,8 +21,12 @@ def acl_list_2(conn):
             for i in range(1, 4):
                 if data[i] == 'admin':
                     acl += [load_lang('admin')]
-                else:
+                elif data[i] == 'user':
                     acl += [load_lang('member')]
+                elif data[i] == '':
+                    acl += [load_lang('normal')]
+                else:
+                    acl += [data[i]]
 
             div +=  '''
                 <tr>

+ 16 - 16
route/admin_plus.py

@@ -1,6 +1,6 @@
 from .tool.func import *
 
-def admin_plus_2(conn):
+def admin_plus_2(conn, name):
     curs = conn.cursor()
     
     if flask.request.method == 'POST':
@@ -62,24 +62,24 @@ def admin_plus_2(conn):
             state = ''
 
         data += '''
-                    <li><input type="checkbox" ''' + state +  ' name="ban" ' + exist_list[0] + '> ' + load_lang('ban_authority') + '''</li>
-                    <li><input type="checkbox" ''' + state +  ' name="toron" ' + exist_list[2] + '> ' + load_lang('discussion_authority') + '''</li>
-                    <li><input type="checkbox" ''' + state +  ' name="check" ' + exist_list[3] + '> ' + load_lang('user_check_authority') + '''</li>
-                    <li><input type="checkbox" ''' + state +  ' name="acl" ' + exist_list[4] + '> ' + load_lang('document_acl_authority') + '''</li>
-                    <li><input type="checkbox" ''' + state +  ' name="hidel" ' + exist_list[5] + '> ' + load_lang('history_hide_authority') + '''</li>
-                    <li><input type="checkbox" ''' + state +  ' name="give" ' + exist_list[6] + '> ' + load_lang('authorization_authority') + '''</li>
-                    <li><input type="checkbox" ''' + state +  ' name="owner" ' + exist_list[7] + '> ' + load_lang('owner_authority') + '''</li>
-                </ul>
-                '''
+                <li><input type="checkbox" ''' + state +  ' name="ban" ' + exist_list[0] + '> ' + load_lang('ban_authority') + '''</li>
+                <li><input type="checkbox" ''' + state +  ' name="toron" ' + exist_list[2] + '> ' + load_lang('discussion_authority') + '''</li>
+                <li><input type="checkbox" ''' + state +  ' name="check" ' + exist_list[3] + '> ' + load_lang('user_check_authority') + '''</li>
+                <li><input type="checkbox" ''' + state +  ' name="acl" ' + exist_list[4] + '> ' + load_lang('document_acl_authority') + '''</li>
+                <li><input type="checkbox" ''' + state +  ' name="hidel" ' + exist_list[5] + '> ' + load_lang('history_hide_authority') + '''</li>
+                <li><input type="checkbox" ''' + state +  ' name="give" ' + exist_list[6] + '> ' + load_lang('authorization_authority') + '''</li>
+                <li><input type="checkbox" ''' + state +  ' name="owner" ' + exist_list[7] + '> ' + load_lang('owner_authority') + '''</li>
+            </ul>
+        '''
 
         return easy_minify(flask.render_template(skin_check(), 
             imp = [load_lang('admin_group_add'), wiki_set(), custom(), other2([0, 0])],
             data =  '''
-                    <form method="post">
-                        ''' + data + '''
-                        <hr class=\"main_hr\">
-                        <button id="save" ''' + state +  ''' type="submit">''' + load_lang('save') + '''</button>
-                    </form>
-                    ''',
+                <form method="post">
+                    ''' + data + '''
+                    <hr class=\"main_hr\">
+                    <button id="save" ''' + state +  ''' type="submit">''' + load_lang('save') + '''</button>
+                </form>
+            ''',
             menu = [['manager', load_lang('return')]]
         ))     

+ 15 - 0
route/api_skin_info.py

@@ -0,0 +1,15 @@
+from .tool.func import *
+
+def api_skin_info_2(conn):
+    curs = conn.cursor()
+
+    json_address = re.sub("(((?!\.|\/).)+)\.html$", "info.json", skin_check())
+    try:
+        json_data = json.loads(open(json_address).read())
+    except:
+        json_data = None
+
+    if json_data:    
+        return flask.jsonify(json_data)
+    else:
+        return flask.jsonify({})

+ 25 - 0
route/api_version.py

@@ -0,0 +1,25 @@
+from .tool.func import *
+
+def api_version_2(conn, r_ver, c_ver):
+    curs = conn.cursor()
+
+    n_ver = ''
+    data = None
+
+    try:
+        if flask.request.host != 'namu.ml':
+            data = urllib.request.urlopen('https://namu.ml/api/version')
+    except:
+        pass
+
+    if data and data.getcode() == 200:
+        try:
+            json_data = json.loads(data.read().decode())
+            if 'version' in json_data:
+                n_ver = json_data['version']
+        except:
+            pass
+        
+    json_data = { "version" : r_ver, "db_version" : c_ver, "lastest_version" : n_ver  }
+
+    return flask.jsonify(json_data)

+ 11 - 6
route/api_w.py

@@ -3,11 +3,16 @@ from .tool.func import *
 def api_w_2(conn, name):
     curs = conn.cursor()
 
-    curs.execute("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]) }
-    
+    if flask.request.method == 'POST':
+        json_data = { "title" : name, "data" : render_set(title = name, data = flask.request.form.get('data', '')) }
+        
         return flask.jsonify(json_data)
     else:
-        return flask.jsonify({})
+        curs.execute("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]) }
+        
+            return flask.jsonify(json_data)
+        else:
+            return flask.jsonify({})

+ 10 - 9
route/change_password.py

@@ -59,20 +59,21 @@ def change_password_2(conn, server_init):
                 email = ''
 
             div2 = load_skin()
-            
             div3 = ''
-            var_div3 = ''
 
             curs.execute('select data from user_set where name = "lang" and id = ?', [flask.session['id']])
             data = curs.fetchall()
+            if not data:
+                curs.execute('select data from other where name = "language"')
+                data = curs.fetchall()
+                if not data:
+                    data = [['en-US']]
 
             for lang_data in support_language:
                 if data and data[0][0] == lang_data:
-                    div3 = '<option value="' + lang_data + '">' + lang_data + '</option>'
+                    div3 = '<option value="' + lang_data + '">' + lang_data + '</option>' + div3
                 else:
-                    var_div3 += '<option value="' + lang_data + '">' + lang_data + '</option>'
-
-            div3 += var_div3
+                    div3 += '<option value="' + lang_data + '">' + lang_data + '</option>'
 
             oauth_provider = load_oauth('_README')['support']
             oauth_content = '<ul>'
@@ -80,9 +81,9 @@ def change_password_2(conn, server_init):
                 curs.execute('select name, picture from oauth_conn where wiki_id = ? and provider = ?', [flask.session['id'], oauth_provider[i]])
                 oauth_data = curs.fetchall()
                 if len(oauth_data) == 1:
-                    oauth_content += '<li>{} - {}</li>'.format(oauth_provider[i], load_lang('connection') + ' : <img src="{}" width="17px" height="17px">{}'.format(oauth_data[0][1], oauth_data[0][0]))
+                    oauth_content += '<li>{} - {}</li>'.format(oauth_provider[i].capitalize(), load_lang('connection') + ' : <img src="{}" width="17px" height="17px">{}'.format(oauth_data[0][1], oauth_data[0][0]))
                 else:
-                    oauth_content += '<li>{} - {}</li>'.format(oauth_provider[i], load_lang('connection') + ' : <a href="/oauth/{}/init">{}</a>'.format(oauth_provider[i], load_lang('connect')))
+                    oauth_content += '<li>{} - {}</li>'.format(oauth_provider[i].capitalize(), load_lang('connection') + ' : <a href="/oauth/{}/init">{}</a>'.format(oauth_provider[i], load_lang('connect')))
             
             oauth_content += '</ul>'
 
@@ -92,7 +93,7 @@ def change_password_2(conn, server_init):
                 imp = [load_lang('user_setting'), wiki_set(), custom(), other2([0, 0])],
                 data =  '''
                         <form method="post">
-                            <span>id : ''' + ip + '''</span>
+                            <span>''' + load_lang('id') + ''' : ''' + ip + '''</span>
                             <hr class=\"main_hr\">
                             <input placeholder="''' + load_lang('now_password') + '''" name="pw4" type="password">
                             <hr class=\"main_hr\">

+ 14 - 12
route/check_key.py

@@ -59,25 +59,27 @@ def check_key_2(conn, tool):
                 flask.session.pop('c_key', None)
 
                 return easy_minify(flask.render_template(skin_check(),    
-                    imp = ['check', wiki_set(), custom(), other2([0, 0])],
+                    imp = [load_lang('reset_user_ok'), wiki_set(), custom(), other2([0, 0])],
                     data =  '''
-                            ''' + load_lang('id') + ' : ' + d_id + '''
-                            <br>
-                            ''' + load_lang('password') + ' : ' + pw + '''
-                            ''',
+                        ''' + load_lang('id') + '''
+                        <hr class=\"main_hr\">
+                        ''' + load_lang('id') + ' : ' + d_id + '''
+                        <br>
+                        ''' + load_lang('password') + ' : ' + pw + '''
+                    ''',
                     menu = [['user', load_lang('return')]]
                 ))
             else:
                 return redirect('/pass_find')
     else:
         return easy_minify(flask.render_template(skin_check(),    
-            imp = ['check', wiki_set(), custom(), other2([0, 0])],
+            imp = [load_lang('key_check'), wiki_set(), custom(), other2([0, 0])],
             data =  '''
-                    <form method="post">
-                        <input placeholder="''' + load_lang('key') + '''" name="key" type="text">
-                        <hr class=\"main_hr\">
-                        <button type="submit">''' + load_lang('save') + '''</button>
-                    </form>
-                    ''',
+                <form method="post">
+                    <input placeholder="''' + load_lang('key') + '''" name="key" type="text">
+                    <hr class=\"main_hr\">
+                    <button type="submit">''' + load_lang('save') + '''</button>
+                </form>
+            ''',
             menu = [['user', load_lang('return')]]
         ))

+ 1 - 1
route/close_topic_list.py

@@ -18,7 +18,7 @@ def close_topic_list_2(conn, name, tool):
             else:
                 break
 
-        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(flask.request.form.get('topic', None) + t_num))
+        return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(flask.request.form.get('topic', 'test') + t_num))
     else:
         plus = ''
         menu = [['topic/' + url_pas(name), load_lang('return')]]

+ 10 - 0
route/easter_egg.py

@@ -0,0 +1,10 @@
+from .tool.func import *
+
+def easter_egg_2(conn):
+    curs = conn.cursor()
+
+    return easy_minify(flask.render_template(skin_check(), 
+        imp = ['easter_egg.html', wiki_set(), custom(), other2([0, 0])],
+        data = open('./views/easter_egg.html', 'r').read(),
+        menu = 0
+    ))

+ 24 - 26
route/edit.py

@@ -13,22 +13,22 @@ def edit_2(conn, name):
         else:
             captcha_post('', 0)
 
-        if flask.request.form.get('otent', None) == flask.request.form.get('content', None):
+        if flask.request.form.get('otent', '') == flask.request.form.get('content', ''):
             return redirect('/w/' + url_pas(name))
             
         if edit_filter_do(flask.request.form.get('content', '')) == 1:
             return re_error('/error/21')
 
         today = get_time()
-        content = savemark(flask.request.form.get('content', None))
+        content = savemark(flask.request.form.get('content', ''))
         
         curs.execute("select data from data where title = ?", [name])
         old = curs.fetchall()
         if old:
-            leng = leng_check(len(flask.request.form.get('otent', None)), len(content))
+            leng = leng_check(len(flask.request.form.get('otent', '')), len(content))
             
             if flask.request.args.get('section', None):
-                content = old[0][0].replace(flask.request.form.get('otent', None), content)
+                content = old[0][0].replace(flask.request.form.get('otent', ''), content)
                 
             curs.execute("update data set data = ? where title = ?", [content, name])
         else:
@@ -69,7 +69,7 @@ def edit_2(conn, name):
                 test_data = '\n' + re.sub('\r\n', '\n', new[0][0]) + '\n'   
                 
                 section_data = re.findall('((?:={1,6}) ?(?:(?:(?!={1,6}\n).)+) ?={1,6}\n(?:(?:(?!(?:={1,6}) ?(?:(?:(?!={1,6}\n).)+) ?={1,6}\n).)*\n*)*)', test_data)
-                data = section_data[int(flask.request.args.get('section', None)) - 1]
+                data = section_data[int(flask.request.args.get('section', '1')) - 1]
             else:
                 data = new[0][0]
         else:
@@ -79,37 +79,35 @@ def edit_2(conn, name):
         
         if not flask.request.args.get('section', None):
             get_name =  '''
-                        <a href="/manager/15?plus=''' + url_pas(name) + '">(' + load_lang('load') + ')</a> <a href="/edit_filter">(' + load_lang('edit_filter_rule') + ''')</a>
-                        <hr class=\"main_hr\">
-                        '''
-            action = ''
+                <a href="/manager/15?plus=''' + url_pas(name) + '">(' + load_lang('load') + ')</a> <a href="/edit_filter">(' + load_lang('edit_filter_rule') + ''')</a>
+                <hr class=\"main_hr\">
+            '''
         else:
             get_name = ''
-            action = '?section=' + flask.request.args.get('section', None)
             
         if flask.request.args.get('plus', None):
-            curs.execute("select data from data where title = ?", [flask.request.args.get('plus', None)])
+            curs.execute("select data from data where title = ?", [flask.request.args.get('plus', 'test')])
             get_data = curs.fetchall()
             if get_data:
                 data = get_data[0][0]
                 get_name = ''
 
-        js_data = edit_help_button()
-
         return easy_minify(flask.render_template(skin_check(), 
             imp = [name, wiki_set(), custom(), other2([' (' + load_lang('edit') + ')', 0])],
-            data =  get_name + js_data[0] + '''
-                    <form method="post" action="/edit/''' + url_pas(name) + action + '''">
-                        ''' + js_data[1] + '''
-                        <textarea id="content" rows="25" name="content">''' + html.escape(re.sub('\n$', '', data)) + '''</textarea>
-                        <textarea style="display: none;" name="otent">''' + html.escape(re.sub('\n$', '', data_old)) + '''</textarea>
-                        <hr class=\"main_hr\">
-                        <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
-                        <hr class=\"main_hr\">
-                        ''' + captcha_get() + ip_warring() + '''
-                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                        <button id="preview" type="submit" formaction="/preview/''' + url_pas(name) + action + '">' + load_lang('preview') + '''</button>
-                    </form>
-                    ''',
+            data =  get_name + '''
+                <form method="post">
+                    ''' + edit_button() + '''
+                    <textarea id="content" rows="25" id="content" name="content">''' + html.escape(re.sub('\n$', '', data)) + '''</textarea>
+                    <textarea style="display: none;" name="otent">''' + html.escape(re.sub('\n$', '', data_old)) + '''</textarea>
+                    <hr class=\"main_hr\">
+                    <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
+                    <hr class=\"main_hr\">
+                    ''' + captcha_get() + ip_warring() + '''
+                    <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                    <button id="preview" type="button" onclick="do_preview(\'''' + name + '\')">' + load_lang('preview') + '''</button>
+                </form>
+                <hr class=\"main_hr\">
+                <div id="see_preview"></div>
+            ''',
             menu = [['w/' + url_pas(name), load_lang('return')], ['delete/' + url_pas(name), load_lang('delete')], ['move/' + url_pas(name), load_lang('move')]]
         ))

+ 6 - 0
route/error_404.py

@@ -0,0 +1,6 @@
+from .tool.func import *
+
+def error_404_2(conn):
+    curs = conn.cursor()
+
+    return redirect('/w/' + url_pas(wiki_set(2)))

+ 2 - 4
route/login.py

@@ -1,5 +1,4 @@
 from .tool.func import *
-from flask import request
 
 def login_2(conn):
     curs = conn.cursor()
@@ -15,8 +14,7 @@ def login_2(conn):
             return re_error('/error/13')
         else:
             captcha_post('', 0)
-
-        ip = ip_check()
+            
         agent = flask.request.headers.get('User-Agent')
 
         curs.execute("select pw, encode from user where id = ?", [flask.request.form.get('id', None)])
@@ -50,7 +48,7 @@ def login_2(conn):
         return redirect('/user')  
     else:
         oauth_check = 0
-        oauth_content = '<link rel="stylesheet" href="/views/main_css/oauth.css"><hr class=\"main_hr\"><div class="oauth-wrapper"><ul class="oauth-list">'
+        oauth_content = '<hr class=\"main_hr\"><div class="oauth-wrapper"><ul class="oauth-list">'
         oauth_supported = load_oauth('_README')['support']
         for i in range(len(oauth_supported)):
             oauth_data = load_oauth(oauth_supported[i])

+ 9 - 0
route/logout.py

@@ -0,0 +1,9 @@
+from .tool.func import *
+
+def logout_2(conn):
+    curs = conn.cursor()
+
+    flask.session.pop('state', None)
+    flask.session.pop('id', None)
+
+    return redirect('/user')

+ 9 - 0
route/main_file.py

@@ -0,0 +1,9 @@
+from .tool.func import *
+
+def main_file_2(conn, data):
+    curs = conn.cursor()
+
+    if re.search('\.txt$', data):
+        return flask.send_from_directory('./', data)
+    else:
+        return redirect('/w/' + url_pas(wiki_set(2)))

+ 1 - 1
route/manager.py

@@ -26,11 +26,11 @@ def manager_2(conn, num):
             data =  '''
                     <h2>''' + load_lang('admin') + '''</h2>
                     <ul>
-                        <li><a href="/manager/2">''' + load_lang('acl_document_list') + '''</a></li>
                         <li><a href="/manager/3">''' + load_lang('check_user') + '''</a></li>
                         <li><a href="/manager/4">''' + load_lang('ban') + '''</a></li>
                         <li><a href="/manager/5">''' + load_lang('authorize') + '''</a></li>
                         <li><a href="/edit_filter">''' + load_lang('edit_filter_list') + '''</a></li>
+                        <li><a href="/give_log">''' + load_lang('admin_group_list') + '''</a></li>
                     </ul>
                     <br>
                     <h2>''' + load_lang('owner') + '''</h2>

+ 9 - 4
route/need_email.py

@@ -21,21 +21,26 @@ def need_email_2(conn, tool):
 
                             return redirect('/register')
                         else:
-                            send_email(flask.request.form.get('email', ''), wiki_set()[0] + ' key', 'key : ' + flask.session['c_key'])
+                            send_email(flask.request.form.get('email', ''), wiki_set()[0] + '\'s Key', 'Key : ' + flask.session['c_key'])
                             flask.session['c_email'] = flask.request.form.get('email', '')
 
                             return redirect('/check_key')
 
             return redirect('/register')
         else:
-            curs.execute("select id from user where id = ? and email = ?", [flask.request.form.get('id', ''), flask.request.form.get('email', '')])
+            curs.execute("select id from user_set where id = ? and name = 'email' and data = ?", [
+                flask.request.form.get('id', ''),
+                flask.request.form.get('email', '')
+            ])
             if curs.fetchall():
                 flask.session['c_key'] = ''.join(random.choice("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") for i in range(16))
                 flask.session['c_id'] = flask.request.form.get('id', '')
 
-                send_email(flask.request.form.get('email', ''), wiki_set()[0] + ' ' + load_lang('password_search') + ' key', 'key : ' + flask.session['c_key'])
+                send_email(flask.request.form.get('email', ''), wiki_set()[0] + '\'s key', 'Key : ' + flask.session['c_key'])
 
                 return redirect('/check_pass_key')
+            else:
+                return re_error('/error/12')
     else:
         if tool == 'need_email':
             return easy_minify(flask.render_template(skin_check(),    
@@ -58,7 +63,7 @@ def need_email_2(conn, tool):
                         <form method="post">
                             <input placeholder="''' + load_lang('id') + '''" name="id" type="text">
                             <hr class=\"main_hr\">
-                            <input placeholder="email" name="email" type="text">
+                            <input placeholder="''' + load_lang('email') + '''" name="email" type="text">
                             <hr class=\"main_hr\">
                             <button type="submit">''' + load_lang('save') + '''</button>
                         </form>

+ 7 - 5
route/now_update.py

@@ -19,11 +19,13 @@ def now_update_2(conn):
         if platform.system() == 'Linux':
             print('Update')
 
-            os.system('git remote rm origin')
-            os.system('git remote add origin https://github.com/2DU/opennamu.git')
-            ok = os.system('git fetch origin ' + up_data)
-            ok = os.system('git reset --hard origin/' + up_data)
-            if ok == 0:
+            ok = []
+
+            ok += [os.system('git remote rm origin')]
+            ok += [os.system('git remote add origin https://github.com/2DU/opennamu.git')]
+            ok += [os.system('git fetch origin ' + up_data)]
+            ok += [os.system('git reset --hard origin/' + up_data)]
+            if (ok[0] and ok[1] and ok[2] and ok[3]) == 0:
                 return redirect('/restart')
         else:
             if platform.system() == 'Windows':

+ 38 - 36
route/other.py

@@ -5,41 +5,43 @@ def other_2(conn, r_ver):
     
     return easy_minify(flask.render_template(skin_check(), 
         imp = [load_lang('other_tool'), wiki_set(), custom(), other2([0, 0])],
-        data =  '''
-                <h2>''' + load_lang('record') + '''</h2>
-                <ul>
-                    <li><a href="/manager/6">''' + load_lang('edit_record') + '''</a></li>
-                    <li><a href="/manager/7">''' + load_lang('discussion_record') + '''</a></li>
-                </ul>
-                <br>
-                <h2>''' + load_lang('list') + '''</h2>
-                <ul>
-                    <li><a href="/admin_list">''' + load_lang('admin_list') + '''</a></li>
-                    <li><a href="/give_log">''' + load_lang('admin_group_list') + '''</a></li>
-                    <li><a href="/not_close_topic">''' + load_lang('open_discussion_list') + '''</a></li>
-                    <li><a href="/title_index">''' + load_lang('all_document_list') + '''</a></li>
-                    <li><a href="/acl_list">''' + load_lang('acl_document_list') + '''</a></li>
-                    <li><a href="/please">''' + load_lang('need_document') + '''</a></li>
-                    <li><a href="/block_log">''' + load_lang('recent_ban') + '''</a></li>
-                    <li><a href="/user_log">''' + load_lang('member_list') + '''</a></li>
-                    <li><a href="/admin_log">''' + load_lang('authority_use_list') + '''</a></li>
-                </ul>
-                <br>
-                <h2>''' + load_lang('other') + '''</h2>
-                <ul>
-                    <li><a href="/upload">''' + load_lang('upload') + '''</a></li>
-                    <li><a href="/manager/10">''' + load_lang('search') + '''</a></li>
-                </ul>
-                <br>
-                <h2>''' + load_lang('admin') + '''</h2>
-                <ul>
-                    <li><a href="/manager/1">''' + load_lang('admin_tool') + '''</a></li>
-                </ul>
-                <br>
-                <h2>''' + load_lang('version') + '''</h2>
-                <ul>
-                    <li>''' + load_lang('version') + ' : <a id="out_link" href="https://github.com/2DU/opennamu/blob/master/version.md">' + r_ver + '''</a></li>
-                </ul>
-                ''',
+        data = '''
+            <h2>''' + load_lang('record') + '''</h2>
+            <ul>
+                <li><a href="/manager/6">''' + load_lang('edit_record') + '''</a></li>
+                <li><a href="/manager/7">''' + load_lang('discussion_record') + '''</a></li>
+            </ul>
+            <br>
+            <h2>''' + load_lang('list') + '''</h2>
+            <ul>
+                <li><a href="/manager/2">''' + load_lang('acl_document_list') + '''</a></li>
+                <li><a href="/admin_list">''' + load_lang('admin_list') + '''</a></li>
+                <li><a href="/not_close_topic">''' + load_lang('open_discussion_list') + '''</a></li>
+                <li><a href="/title_index">''' + load_lang('all_document_list') + '''</a></li>
+                <li><a href="/acl_list">''' + load_lang('acl_document_list') + '''</a></li>
+                <li><a href="/please">''' + load_lang('need_document') + '''</a></li>
+                <li><a href="/block_log">''' + load_lang('recent_ban') + '''</a></li>
+                <li><a href="/user_log">''' + load_lang('member_list') + '''</a></li>
+                <li><a href="/admin_log">''' + load_lang('authority_use_list') + '''</a></li>
+            </ul>
+            <br>
+            <h2>''' + load_lang('other') + '''</h2>
+            <ul>
+                <li><a href="/upload">''' + load_lang('upload') + '''</a></li>
+                <li><a href="/manager/10">''' + load_lang('search') + '''</a></li>
+            </ul>
+            <br>
+            <h2>''' + load_lang('admin') + '''</h2>
+            <ul>
+                <li><a href="/manager/1">''' + load_lang('admin_tool') + '''</a></li>
+            </ul>
+            <br>
+            <h2>''' + load_lang('version') + '''</h2>
+            <ul>
+                <li>''' + load_lang('version') + ' : ' + r_ver + '''</li>
+                <li id="ver_send" style="display: none;">''' + load_lang('lastest') + ''' : </li>
+            </ul>
+            <script>load_ver();</script>
+        ''',
         menu = 0
     ))

+ 0 - 41
route/preview.py

@@ -1,41 +0,0 @@
-from .tool.func import *
-
-def preview_2(conn, name):
-    curs = conn.cursor()
-
-    if acl_check(name) == 1:
-        return re_error('/ban')
-         
-    new_data = re.sub('^\r\n', '', flask.request.form.get('content', None))
-    new_data = re.sub('\r\n$', '', new_data)
-    
-    end_data = render_set(
-        title = name,
-        data = new_data
-    )
-    
-    if flask.request.args.get('section', None):
-        action = '?section=' + flask.request.args.get('section', None)
-    else:
-        action = ''
-
-    js_data = edit_help_button()
-    
-    return easy_minify(flask.render_template(skin_check(), 
-        imp = [name, wiki_set(), custom(), other2([' (' + load_lang('preview') + ')', 0])],
-        data =  '<a href="/edit_filter">(' + load_lang('edit_filter_rule') + ')</a>' + js_data[0] + '''
-                <form method="post" action="/edit/''' + url_pas(name) + action + '''">
-                    ''' + js_data[1] + '''
-                    <textarea id="content" rows="25" name="content">''' + html.escape(flask.request.form.get('content', None)) + '''</textarea>
-                    <textarea style="display: none;" name="otent">''' + html.escape(flask.request.form.get('otent', None)) + '''</textarea>
-                    <hr class=\"main_hr\">
-                    <input placeholder="''' + load_lang('why') + '''" name="send" type="text">
-                    <hr class=\"main_hr\">
-                    ''' + captcha_get() + '''
-                    <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                    <button id="preview" type="submit" formaction="/preview/''' + url_pas(name) + action + '">' + load_lang('preview') + '''</button>
-                </form>
-                <hr class=\"main_hr\">
-                ''' + end_data,
-        menu = [['w/' + url_pas(name), load_lang('return')]]
-    ))

+ 89 - 45
route/recent_changes.py

@@ -4,7 +4,11 @@ def recent_changes_2(conn, name, tool):
     curs = conn.cursor()
 
     if flask.request.method == 'POST':
-        return redirect('/diff/' + url_pas(name) + '?first=' + flask.request.form.get('b', None) + '&second=' + flask.request.form.get('a', None))
+        return redirect(
+            '/diff/' + url_pas(name) +
+            '?first=' + flask.request.form.get('b', '1') +
+            '&second=' + flask.request.form.get('a', '1')
+        )
     else:
         one_admin = admin_check(1)
         six_admin = admin_check(6)
@@ -13,10 +17,10 @@ def recent_changes_2(conn, name, tool):
         select = ''
 
         div =   '''
-                <table id="main_table_set">
-                    <tbody>
-                        <tr>
-                '''
+            <table id="main_table_set">
+                <tbody>
+                    <tr>
+        '''
         
         if name:
             num = int(number_check(flask.request.args.get('num', '1')))
@@ -27,19 +31,42 @@ def recent_changes_2(conn, name, tool):
 
             if tool == 'history':
                 div +=  '''
-                        <td id="main_table_width">''' + load_lang('version') + '''</td>
-                        <td id="main_table_width">''' + load_lang('editor') + '''</td>
-                        <td id="main_table_width">''' + load_lang('time') + '''</td></tr>
-                        '''
+                    <td id="main_table_width">''' + load_lang('version') + '''</td>
+                    <td id="main_table_width">''' + load_lang('editor') + '''</td>
+                    <td id="main_table_width">''' + load_lang('time') + '''</td></tr>
+                '''
                 
-                curs.execute("select id, title, date, ip, send, leng from history where title = ? order by id + 0 desc limit ?, '50'", [name, str(sql_num)])
+                # 기본적인 move만 구현
+                tool_select = flask.request.args.get('tool', None)
+                if tool_select:
+                    if tool_select == 'move':
+                        curs.execute('''
+                            select id, title, date, ip, send, leng from history
+                            where send like ? or send like ?
+                            order by id + 0 desc
+                            limit ?, '50'
+                        ''', ['%(<a>' + name +'</a>%', '%<a>' + name + '</a> move)', str(sql_num)])
+                    else:
+                        curs.execute('''
+                            select id, title, date, ip, send, leng from history
+                            where title = ?
+                            order by id + 0 desc
+                            limit ?, '50'
+                        ''', [name, str(sql_num)])
+                else:
+                    curs.execute('''
+                        select id, title, date, ip, send, leng from history
+                        where title = ?
+                        order by id + 0 desc
+                        limit ?, '50'
+                    ''', [name, str(sql_num)])
             else:
                 div +=  '''
-                            <td id="main_table_width">''' + load_lang('document_name') + '''</td>
-                            <td id="main_table_width">''' + load_lang('editor') + '''</td>
-                            <td id="main_table_width">''' + load_lang('time') + '''</td>
-                        </tr>
-                        '''
+                        <td id="main_table_width">''' + load_lang('document_name') + '''</td>
+                        <td id="main_table_width">''' + load_lang('editor') + '''</td>
+                        <td id="main_table_width">''' + load_lang('time') + '''</td>
+                    </tr>
+                '''
 
                 div = '<a href="/topic_record/' + url_pas(name) + '">(' + load_lang('discussion') + ')</a><hr class=\"main_hr\">' + div
                 
@@ -52,13 +79,18 @@ def recent_changes_2(conn, name, tool):
                 sql_num = 0            
             
             div +=  '''
-                        <td id="main_table_width">''' + load_lang('document_name') + '''</td>
-                        <td id="main_table_width">''' + load_lang('editor') + '''</td>
-                        <td id="main_table_width">''' + load_lang('time') + '''</td>
-                    </tr>
-                    '''
+                    <td id="main_table_width">''' + load_lang('document_name') + '''</td>
+                    <td id="main_table_width">''' + load_lang('editor') + '''</td>
+                    <td id="main_table_width">''' + load_lang('time') + '''</td>
+                </tr>
+            '''
             
-            curs.execute("select id, title, date, ip, send, leng from history where not title like 'user:%' order by date desc limit ?, 50", [str(sql_num)])
+            curs.execute('''
+                select id, title, date, ip, send, leng from history 
+                where not title like 'user:%' 
+                order by date desc 
+                limit ?, 50
+            ''', [str(sql_num)])
 
         data_list = curs.fetchall()
         for data in data_list:    
@@ -80,12 +112,16 @@ def recent_changes_2(conn, name, tool):
             if int(data[0]) - 1 == 0:
                 revert = ''
             else:
-                revert = '<a href="/diff/' + url_pas(data[1]) + '?first=' + str(int(data[0]) - 1) + '&second=' + data[0] + '">(' + load_lang('compare') + ')</a> <a href="/revert/' + url_pas(data[1]) + '?num=' + str(int(data[0]) - 1) + '">(' + load_lang('revert') + ')</a>'
+                revert = '<a href="/diff/' + url_pas(data[1]) + '?first=' + str(int(data[0]) - 1) + '&second=' + data[0] + '">(' + load_lang('compare') + ')</a>'
+                revert += ' <a href="/revert/' + url_pas(data[1]) + '?num=' + str(int(data[0]) - 1) + '">(' + load_lang('revert') + ')</a>'
             
             style = ['', '']
             date = data[2]
 
-            curs.execute("select title from history where title = ? and id = ? and hide = 'O'", [data[1], data[0]])
+            curs.execute('''
+                select title from history
+                where title = ? and id = ? and hide = 'O'
+            ''', [data[1], data[0]])
             hide = curs.fetchall()
             
             if six_admin == 1:
@@ -115,41 +151,49 @@ def recent_changes_2(conn, name, tool):
                 style[1] = 'id="toron_color_grey"'
 
             if tool == 'history':
-                title = '<a href="/w/' + url_pas(name) + '?num=' + data[0] + '">r' + data[0] + '</a> <a href="/raw/' + url_pas(name) + '?num=' + data[0] + '">(' + load_lang('raw') + ')</a> '
+                title = '<a href="/w/' + url_pas(name) + '?num=' + data[0] + '">r' + data[0] + '</a> '
+                title += '<a href="/raw/' + url_pas(name) + '?num=' + data[0] + '">(' + load_lang('raw') + ')</a> '
             else:
-                title = '<a href="/w/' + url_pas(data[1]) + '">' + html.escape(data[1]) + '</a> <a href="/history/' + url_pas(data[1]) + '">(r' + data[0] + ')</a> '
-                    
+                title = '<a href="/w/' + url_pas(data[1]) + '">' + html.escape(data[1]) + '</a> '
+                title += '<a href="/history/' + url_pas(data[1]) + '">(r' + data[0] + ')</a> '
+
             div +=  '''
-                    <tr ''' + style[0] + '''>
-                        <td>''' + title + revert + ' ' + leng + '''</td>
-                        <td>''' + ip + ban + hidden + '''</td>
-                        <td>''' + date + '''</td>
-                    </tr>
-                    <tr ''' + style[1] + '''>
-                        <td colspan="3">''' + send_parser(send) + '''</td>
-                    </tr>
-                    '''
+                <tr ''' + style[0] + '''>
+                    <td>''' + title + revert + ' ' + leng + '''</td>
+                    <td>''' + ip + ban + hidden + '''</td>
+                    <td>''' + date + '''</td>
+                </tr>
+                <tr ''' + style[1] + '''>
+                    <td colspan="3">''' + send_parser(send) + '''</td>
+                </tr>
+            '''
 
         div +=  '''
-                    </tbody>
-                </table>
-                '''
+                </tbody>
+            </table>
+        '''
         sub = ''
 
         if name:
             if tool == 'history':
-                div =   '''
-                        <form method="post">
-                            <select name="a">''' + select + '''</select> <select name="b">''' + select + '''</select>
-                            <button type="submit">''' + load_lang('compare') + '''</button>
-                        </form>
+                if not tool_select:
+                    div = '''
+                        <a href="?tool=move">(''' + load_lang('move') + ''')</a>
                         <hr class=\"main_hr\">
-                        ''' + div
+                    ''' + div
+                    
+                div = '''
+                    <form method="post">
+                        <select name="a">''' + select + '''</select> <select name="b">''' + select + '''</select>
+                        <button type="submit">''' + load_lang('compare') + '''</button>
+                    </form>
+                    <hr class=\"main_hr\">
+                ''' + div
                 title = name
                 
                 sub += ' (' + load_lang('history') + ')'
                 
-                menu = [['w/' + url_pas(name), load_lang('document')], ['raw/' + url_pas(name), 'raw']]
+                menu = [['w/' + url_pas(name), load_lang('document')], ['raw/' + url_pas(name), load_lang('raw')]]
                 
                 div += next_fix('/history/' + url_pas(name) + '?num=', num, data_list)
             else:

+ 6 - 0
route/search.py

@@ -0,0 +1,6 @@
+from .tool.func import *
+
+def search_2(conn):
+    curs = conn.cursor()
+
+    return redirect('/search/' + url_pas(flask.request.form.get('search', 'test')))

+ 43 - 24
route/setting.py

@@ -184,7 +184,7 @@ def setting_2(conn, num):
                             <br>
                             <select name="update">''' + div3 + '''</select>
                             <hr class=\"main_hr\">
-                            <span>encryption method</span>
+                            <span>''' + load_lang('encryption_method') + '''</span>
                             <br>
                             <br>
                             <select name="encode">''' + div5 + '''</select>
@@ -196,8 +196,8 @@ def setting_2(conn, num):
             ))
     elif num == 2:
         if flask.request.method == 'POST':
-            curs.execute("update other set data = ? where name = ?", [flask.request.form.get('contract', None), 'contract'])
-            curs.execute("update other set data = ? where name = ?", [flask.request.form.get('no_login_warring', None), 'no_login_warring'])
+            curs.execute("update other set data = ? where name = ?", [flask.request.form.get('contract', ''), 'contract'])
+            curs.execute("update other set data = ? where name = ?", [flask.request.form.get('no_login_warring', ''), 'no_login_warring'])
             conn.commit()
             
             admin_check(None, 'edit_set')
@@ -248,30 +248,44 @@ def setting_2(conn, num):
             if num == 4:
                 info_d = 'body'
                 end_r = '4'
+                coverage = ''
             else:
                 info_d = 'head'
                 end_r = '3'
-            
-            curs.execute("select name from other where name = ?", [info_d])
+                if flask.request.args.get('skin', '') == '':
+                    coverage = ''
+                else:
+                    coverage = flask.request.args.get('skin', '')
+                
+            curs.execute("select name from other where name = ? and coverage = ?", [info_d, coverage])
             if curs.fetchall():
-                curs.execute("update other set data = ? where name = ?", [flask.request.form.get('content', ''), info_d])
+                curs.execute("update other set data = ? where name = ? and coverage = ?", [
+                    flask.request.form.get('content', ''),
+                    info_d,
+                    coverage
+                ])
             else:
-                curs.execute("insert into other (name, data) values (?, ?)", [info_d, flask.request.form.get('content', '')])
+                curs.execute("insert into other (name, data, coverage) values (?, ?, ?)", [info_d, flask.request.form.get('content', ''), coverage])
             
             conn.commit()
 
             admin_check(None, 'edit_set')
 
-            return redirect('/setting/' + end_r)
+            return redirect('/setting/' + end_r + '?skin=' + flask.request.args.get('skin', ''))
         else:
             if num == 4:
                 curs.execute("select data from other where name = 'body'")
                 title = '_body'
                 start = ''
             else:
-                curs.execute("select data from other where name = 'head'")
+                curs.execute("select data from other where name = 'head' and coverage = ?", [flask.request.args.get('skin', '')])
                 title = '_head'
-                start = '<span>&lt;style&gt;CSS&lt;/style&gt;<br>&lt;script&gt;JS&lt;/script&gt;</span><hr class=\"main_hr\">'
+                start = '<a href="?">(' + load_lang('all') + ')</a> ' + \
+                        ' '.join(['<a href="?skin=' + i + '">(' + i + ')</a>' for i in load_skin('', 1)]) + \
+                        '''
+                            <hr class=\"main_hr\">
+                            <span>&lt;style&gt;CSS&lt;/style&gt;<br>&lt;script&gt;JS&lt;/script&gt;</span><hr class=\"main_hr\">
+                        '''
                 
             head = curs.fetchall()
             if head:
@@ -281,28 +295,28 @@ def setting_2(conn, num):
 
             return easy_minify(flask.render_template(skin_check(), 
                 imp = [load_lang(data = 'main' + title, safe = 1), wiki_set(), custom(), other2([0, 0])],
-                data =  '''
-                        <form method="post">
-                            ''' + start + '''
-                            <textarea rows="25" name="content">''' + html.escape(data) + '''</textarea>
-                            <hr class=\"main_hr\">
-                            <button id="save" type="submit">''' + load_lang('save') + '''</button>
-                        </form>
-                        ''',
+                data = '''
+                    <form method="post">
+                        ''' + start + '''
+                        <textarea rows="25" name="content">''' + html.escape(data) + '''</textarea>
+                        <hr class=\"main_hr\">
+                        <button id="save" type="submit">''' + load_lang('save') + '''</button>
+                    </form>
+                ''',
                 menu = [['setting', load_lang('return')]]
             ))
     elif num == 5:
         if flask.request.method == 'POST':
             curs.execute("select name from other where name = 'robot'")
             if curs.fetchall():
-                curs.execute("update other set data = ? where name = 'robot'", [flask.request.form.get('content', None)])
+                curs.execute("update other set data = ? where name = 'robot'", [flask.request.form.get('content', '')])
             else:
-                curs.execute("insert into other (name, data) values ('robot', ?)", [flask.request.form.get('content', None)])
+                curs.execute("insert into other (name, data) values ('robot', ?)", [flask.request.form.get('content', '')])
             
             conn.commit()
             
             fw = open('./robots.txt', 'w')
-            fw.write(re.sub('\r\n', '\n', flask.request.form.get('content', None)))
+            fw.write(re.sub('\r\n', '\n', flask.request.form.get('content', '')))
             fw.close()
             
             admin_check(None, 'edit_set')
@@ -341,13 +355,18 @@ def setting_2(conn, num):
 
         if flask.request.method == 'POST':
             for data in i_list:
-                curs.execute("update other set data = ? where name = ?", [flask.request.form.get(data, ''), data])
+                if data == 'g_email':
+                    into_data = re.sub('@.*$', '', flask.request.form.get(data, ''))
+                else:
+                    into_data = flask.request.form.get(data, '')
+
+                curs.execute("update other set data = ? where name = ?", [into_data, data])
 
             conn.commit()
             
             admin_check(None, 'edit_set')
 
-            return redirect('/setting/5')
+            return redirect('/setting/6')
         else:
             n_list = ['', '', '', '']
             d_list = []
@@ -369,7 +388,7 @@ def setting_2(conn, num):
             conn.commit()
 
             return easy_minify(flask.render_template(skin_check(), 
-                imp = ['google', wiki_set(), custom(), other2([0, 0])],
+                imp = ['Google', wiki_set(), custom(), other2([0, 0])],
                 data =  '''
                         <form method="post">
                             <h2><a href="https://www.google.com/recaptcha/admin">recaptcha</a></h2>

+ 240 - 120
route/tool/func.py

@@ -1,39 +1,63 @@
-import werkzeug.routing
-import flask_compress
-import flask_reggie
-import tornado.ioloop
-import tornado.httpserver
-import tornado.wsgi
-import urllib.request
-import email.mime.text
-import sqlite3
-import hashlib
-import smtplib
-import bcrypt
-import platform
-import zipfile
-import difflib
-import shutil
-import threading
-import logging
-import random
-import flask
-import json
-import html
-import sys
-import re
 import os
+import sys
+import platform
 
-try:
-    import css_html_js_minify
-except:
-    pass
-
-if sys.version_info < (3, 6):
-    import sha3
+for i in range(0, 2):
+    try:
+        import werkzeug.routing
+        import flask_compress
+        import flask_reggie
+        import tornado.ioloop
+        import tornado.httpserver
+        import tornado.wsgi
+        import urllib.request
+        import email.mime.text
+        import sqlite3
+        import hashlib
+        import smtplib
+        import bcrypt
+        import zipfile
+        import difflib
+        import shutil
+        import request
+        import threading
+        import logging
+        import random
+        import flask
+        import json
+        import html
+        import re
+
+        try:
+            import css_html_js_minify
+        except:
+            pass
 
-from .set_mark.tool import *
-from .mark import *
+        if sys.version_info < (3, 6):
+            import sha3
+
+        from .set_mark.tool import *
+        from .mark import *
+    except ImportError as e:
+        if i == 0:
+            if platform.system() == 'Linux':
+                ok = os.system('python3 -m pip install -r requirements.txt')
+                if ok == 0:
+                    os.execl(sys.executable, sys.executable, *sys.argv)
+                else:
+                    raise
+            elif platform.system() == 'Windows':
+                ok = os.system('python -m pip install -r requirements.txt')
+                if ok == 0:
+                    os.execl(sys.executable, sys.executable, *sys.argv)
+                else:
+                    raise
+            else:
+                print(e)
+                raise
+        else:
+            print(e)
+            raise
 
 app_var = json.loads(open('data/app_variables.json', encoding='utf-8').read())
 
@@ -72,7 +96,7 @@ def send_email(who, title, data):
         print('Error : Email login error')
 
 def last_change(data):
-    json_address = re.sub("\.html$", ".json", skin_check())
+    json_address = re.sub("(((?!\.|\/).)+)\.html$", "set.json", skin_check())
     try:
         json_data = json.loads(open(json_address).read())
     except:
@@ -101,7 +125,7 @@ def last_change(data):
                             data = re_data_3.sub("<" + i_data[0] + " class=\"" + json_data[j_data]["class"] + "\">", data)        
                 else:
                     re_data = re.compile("<(?P<in>" + j_data + "(?: (?:(?!>).)*)?)>")
-                    data = re_data.sub("<\g<in> class=\"" + json_data[j_data]["class"] + "\">", data)        
+                    data = re_data.sub("<\g<in> class=\"" + json_data[j_data]["class"] + "\">", data)
 
     return data
 
@@ -167,7 +191,7 @@ def update():
     except:
         pass
 
-    # Start Data Migration Code
+    # Start : Data Migration Code
     app_var = json.loads(open(os.path.abspath('./data/app_variables.json'), encoding='utf-8').read())
 
     if os.path.exists('image'):
@@ -191,7 +215,7 @@ def update():
         with open(app_var['path_oauth_setting'], 'w') as f:
             f.write(json.dumps(old_oauth_data, sort_keys = True, indent = 4))
 
-    # -> End Data Migration Code
+    # End
 
 def pw_encode(data, data2 = '', type_d = ''):
     if type_d == '':
@@ -258,16 +282,19 @@ def captcha_post(re_data, num = 1):
             curs.execute('select data from other where name = "sec_re"')
             sec_re = curs.fetchall()
             if sec_re and sec_re[0][0] != '':
-                data = urllib.request.urlopen('https://www.google.com/recaptcha/api/siteverify?secret=' + sec_re[0][0] + '&response=' + re_data)
-                if not data:
-                    return 0
-                else:
-                    json_data = data.read().decode(data.headers.get_content_charset())
-                    json_data = json.loads(json_data)
-                    if data.getcode() == 200 and json_data['success'] == True:
+                try:
+                    data = urllib.request.urlopen('https://www.google.com/recaptcha/api/siteverify?secret=' + sec_re[0][0] + '&response=' + re_data)
+                except:
+                    pass
+                    
+                if data and data.getcode() == 200:
+                    json_data = json.loads(data.read().decode(data.headers.get_content_charset()))
+                    if json_data['success'] == True:
                         return 0
                     else:
                         return 1
+                else:
+                    return 0
             else:
                 return 0
         else:
@@ -330,35 +357,14 @@ def ip_or_user(data):
     else:
         return 0
 
-def edit_help_button():
-    # https://stackoverflow.com/questions/11076975/insert-text-into-textarea-at-cursor-position-javascript
-    js_data = '''
-        <script>
-            function insert_data(name, data) {
-                if(document.selection) { 
-                    document.getElementById(name).focus();
-
-                    sel = document.selection.createRange();
-                    sel.text = data; 
-                } else if(document.getElementById(name).selectionStart || document.getElementById(name).selectionStart == '0') {
-                    var startPos = document.getElementById(name).selectionStart;
-                    var endPos = document.getElementById(name).selectionEnd;
-
-                    document.getElementById(name).value = document.getElementById(name).value.substring(0, startPos) + data + document.getElementById(name).value.substring(endPos, document.getElementById(name).value.length); 
-                } else {
-                    document.getElementById(name).value += data;
-                }
-            }
-        </script>
-    '''
-
+def edit_button():
     insert_list = [['[[|]]', '[[|]]'], ['[*()]', '[*()]'], ['{{{#!}}}', '{{{#!}}}'], ['||<>||', '||<>||'], ["\\'\\'\\'", "\'\'\'"]]
 
     data = ''
     for insert_data in insert_list:
         data += '<a href="javascript:void(0);" onclick="insert_data(\'content\', \'' + insert_data[0] + '\');">(' + insert_data[1] + ')</a> '
 
-    return [js_data, data + '<hr class=\"main_hr\">']
+    return data + '<hr class=\"main_hr\">'
 
 def ip_warring():
     if custom()[2] == 0:    
@@ -373,22 +379,25 @@ def ip_warring():
 
     return text_data
 
-def skin_check():
-    skin = './views/neo_yousoro/'
+def skin_check(set_n = 0):
+    skin = 'neo_yousoro'
 
     curs.execute('select data from other where name = "skin"')
     skin_exist = curs.fetchall()
     if skin_exist and skin_exist[0][0] != '':
         if os.path.exists(os.path.abspath('./views/' + skin_exist[0][0] + '/index.html')) == 1:
-            skin = './views/' + skin_exist[0][0] + '/'
+            skin = skin_exist[0][0]
     
     curs.execute('select data from user_set where name = "skin" and id = ?', [ip_check()])
     skin_exist = curs.fetchall()
     if skin_exist and skin_exist[0][0] != '':
         if os.path.exists(os.path.abspath('./views/' + skin_exist[0][0] + '/index.html')) == 1:
-            skin = './views/' + skin_exist[0][0] + '/'
+            skin = skin_exist[0][0]
 
-    return skin + 'index.html'
+    if set_n == 0:
+        return './views/' + skin + '/index.html'
+    else:
+        return skin
 
 def next_fix(link, num, page, end = 50):
     list_data = ''
@@ -404,7 +413,30 @@ def next_fix(link, num, page, end = 50):
     return list_data
 
 def other2(data):
-    return data + ['']
+    data += ['', '''
+        <link rel="stylesheet" href="/views/main_css/css/main.css">
+        <link rel="stylesheet" href="/views/main_css/css/oauth.css">
+        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css">
+        <link   rel="stylesheet"
+                href="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/katex.min.css"
+                integrity="sha384-dbVIfZGuN1Yq7/1Ocstc1lUEm+AT+/rCkibIcC/OmWo5f0EA48Vf8CytHzGrSwbQ"
+                crossorigin="anonymous">
+        <script src="/views/main_css/js/open_foot.js"></script>
+        <script src="/views/main_css/js/folding.js"></script>
+        <script src="/views/main_css/js/topic_load.js"></script>
+        <script src="/views/main_css/js/do_preview.js"></script>
+        <script src="/views/main_css/js/load_ver.js"></script>
+        <script src="/views/main_css/js/insert_data.js"></script>
+        <script src="https://cdn.jsdelivr.net/npm/katex@0.10.1/dist/katex.min.js"
+                integrity="sha384-2BKqo+exmr9su6dir+qCw08N2ZKRucY4PrGQPPWU1A7FtlCGjmEGFqXCv5nyM5Ij"
+                crossorigin="anonymous"></script>
+        <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
+    ''']
+
+    return data
+
+def cut_100(data):
+    return re.sub('<(((?!>).)*)>', '', data)[0:100] + '...'
 
 def wiki_set(num = 1):
     if num == 1:
@@ -433,12 +465,18 @@ def wiki_set(num = 1):
         else:
             data_list += [data_list[0]]
             
-        curs.execute("select data from other where name = 'head'")
+        curs.execute("select data from other where name = 'head' and coverage = ?", [skin_check(1)])
         db_data = curs.fetchall()
         if db_data and db_data[0][0] != '':
             data_list += [db_data[0][0]]
         else:
-            data_list += ['']
+            curs.execute("select data from other where name = 'head' and coverage = ''")
+            db_data = curs.fetchall()
+            if db_data and db_data[0][0] != '':
+                data_list += [db_data[0][0]]
+            else:
+                data_list += ['']
+
         return data_list
 
     if num == 2:
@@ -605,8 +643,9 @@ def custom():
 
     return ['', '', user_icon, user_head, email, user_name]
 
-def load_skin(data = ''):
+def load_skin(data = '', set_n = 0):
     div2 = ''
+    div3 = []
     system_file = ['main_css', 'easter_egg.html']
 
     if data == '':
@@ -614,26 +653,44 @@ def load_skin(data = ''):
 
         curs.execute('select data from user_set where name = "skin" and id = ?', [ip])
         data = curs.fetchall()
-        for skin_data in os.listdir(os.path.abspath('views')):
-            if not skin_data in system_file:
-                if not data:
-                    curs.execute('select data from other where name = "skin"')
-                    sql_data = curs.fetchall()
-                    if sql_data and sql_data[0][0] == skin_data:
+
+        if not data:
+            curs.execute('select data from other where name = "skin"')
+            data = curs.fetchall()
+            if not data:
+                data = [['neo_yousoro']]
+
+        if set_n == 0:
+            for skin_data in os.listdir(os.path.abspath('views')):
+                if not skin_data in system_file:
+                    if data[0][0] == skin_data:
                         div2 = '<option value="' + skin_data + '">' + skin_data + '</option>' + div2
                     else:
                         div2 += '<option value="' + skin_data + '">' + skin_data + '</option>'
-                elif data[0][0] == skin_data:
-                    div2 = '<option value="' + skin_data + '">' + skin_data + '</option>' + div2
-                else:
-                    div2 += '<option value="' + skin_data + '">' + skin_data + '</option>'
+        else:
+            div2 = []
+            for skin_data in os.listdir(os.path.abspath('views')):
+                if not skin_data in system_file:
+                    if data[0][0] == skin_data:
+                        div2 = [skin_data] + div2
+                    else:
+                        div2 += [skin_data]
     else:
-        for skin_data in os.listdir(os.path.abspath('views')):
-            if not skin_data in system_file:
-                if data == skin_data:
-                    div2 = '<option value="' + skin_data + '">' + skin_data + '</option>' + div2
-                else:
-                    div2 += '<option value="' + skin_data + '">' + skin_data + '</option>'
+        if set_n == 0:
+            for skin_data in os.listdir(os.path.abspath('views')):
+                if not skin_data in system_file:
+                    if data == skin_data:
+                        div2 = '<option value="' + skin_data + '">' + skin_data + '</option>' + div2
+                    else:
+                        div2 += '<option value="' + skin_data + '">' + skin_data + '</option>'
+        else:
+            div2 = []
+            for skin_data in os.listdir(os.path.abspath('views')):
+                if not skin_data in system_file:
+                    if data == skin_data:
+                        div2 = [skin_data] + div2
+                    else:
+                        div2 += [skin_data]
 
     return div2
 
@@ -645,11 +702,26 @@ def acl_check(name, tool = ''):
         acl_data = curs.fetchall()
         if acl_data:
             if acl_data[0][0] == 'user':
-                if ip_or_user(ip):
+                if ip_or_user(ip) == 1:
+                    return 1
+
+            if acl_data[0][0] == '50_edit':
+                if ip_or_user(ip) == 1:
                     return 1
+                
+                if admin_check(5, 'view (' + name + ')') != 1:
+                    curs.execute("select count(title) from history where ip = ?", [ip])
+                    count = curs.fetchall()
+                    if count:
+                        count = count[0][0]
+                    else:
+                        count = 0
+
+                    if count < 50:
+                        return 1
 
             if acl_data[0][0] == 'admin':
-                if ip_or_user(ip):
+                if ip_or_user(ip) == 1:
                     return 1
 
                 if admin_check(5, 'view (' + name + ')') != 1:
@@ -687,36 +759,63 @@ def acl_check(name, tool = ''):
         if re.search("^file:", name) and admin_check(None, 'file edit (' + name + ')') != 1:
             return 1
 
-        curs.execute("select acl from user where id = ?", [ip])
-        user_data = curs.fetchall()
-
         curs.execute("select dec from acl where title = ?", [name])
         acl_data = curs.fetchall()
         if acl_data:
             if acl_data[0][0] == 'user':
-                if not user_data:
+                if ip_or_user(ip) == 1:
                     return 1
 
             if acl_data[0][0] == 'admin':
-                if not user_data:
+                if ip_or_user(ip) == 1:
+                    return 1
+
+                if admin_check(5, 'topic send (' + name + ')') != 1:
                     return 1
 
-                if not admin_check(5, 'edit (' + name + ')') == 1:
+            if acl_data[0][0] == '50_edit':
+                if ip_or_user(ip) == 1:
                     return 1
+                
+                if admin_check(5, 'topic send (' + name + ')') != 1:
+                    curs.execute("select count(title) from history where ip = ?", [ip])
+                    count = curs.fetchall()
+                    if count:
+                        count = count[0][0]
+                    else:
+                        count = 0
+
+                    if count < 50:
+                        return 1
 
         curs.execute('select data from other where name = "edit"')
         set_data = curs.fetchall()
         if set_data:
             if set_data[0][0] == 'login':
-                if not user_data:
+                if ip_or_user(ip) == 1:
                     return 1
 
             if set_data[0][0] == 'admin':
-                if not user_data:
+                if ip_or_user(ip) == 1:
+                    return 1
+
+                if admin_check(5, 'edit (' + name + ')') != 1:
                     return 1
 
-                if not admin_check(5) == 1:
+            if set_data[0][0] == '50_edit':
+                if ip_or_user(ip) == 1:
                     return 1
+                
+                if admin_check(5, 'edit (' + name + ')') != 1:
+                    curs.execute("select count(title) from history where ip = ?", [ip])
+                    count = curs.fetchall()
+                    if count:
+                        count = count[0][0]
+                    else:
+                        count = 0
+
+                    if count < 50:
+                        return 1
 
         return 0
 
@@ -751,41 +850,53 @@ def topic_check(name, sub):
 
     if ban_check() == 1:
         return 1
-        
-    curs.execute("select acl from user where id = ?", [ip])
-    user_data = curs.fetchall()
 
     curs.execute('select data from other where name = "discussion"')
     acl_data = curs.fetchall()
     if acl_data:
         if acl_data[0][0] == 'login':
-            if not user_data:
+            if ip_or_user(ip) == 1:
                 return 1
 
         if acl_data[0][0] == 'admin':
-            if not user_data:
+            if ip_or_user(ip) == 1:
                 return 1
 
-            if not admin_check(3, 'topic (' + name + ')') == 1:
+            if admin_check(3, 'topic (' + name + ')') != 1:
                 return 1
 
     curs.execute("select dis from acl where title = ?", [name])
     acl_data = curs.fetchall()
     if acl_data:
         if acl_data[0][0] == 'user':
-            if not user_data:
+            if ip_or_user(ip) == 1:
+                return 1
+
+        if acl_data[0][0] == '50_edit':
+            if ip_or_user(ip) == 1:
                 return 1
+            
+            if admin_check(3, 'topic (' + name + ')') != 1:
+                curs.execute("select count(title) from history where ip = ?", [ip])
+                count = curs.fetchall()
+                if count:
+                    count = count[0][0]
+                else:
+                    count = 0
+
+                if count < 50:
+                    return 1
 
         if acl_data[0][0] == 'admin':
-            if not user_data:
+            if ip_or_user(ip) == 1:
                 return 1
 
-            if not admin_check(3, 'topic (' + name + ')') == 1:
+            if admin_check(3, 'topic (' + name + ')') != 1:
                 return 1
         
     curs.execute("select title from rd where title = ? and sub = ? and not stop = ''", [name, sub])
     if curs.fetchall():
-        if not admin_check(3, 'topic (' + name + ')') == 1:
+        if admin_check(3, 'topic (' + name + ')') != 1:
             return 1
 
     return 0
@@ -800,7 +911,14 @@ def ban_insert(name, end, why, login, blocker):
 
     curs.execute("select block from ban where block = ?", [name])
     if curs.fetchall():
-        curs.execute("insert into rb (block, end, today, blocker, why, band) values (?, ?, ?, ?, ?, ?)", [name, load_lang('release', 1), now_time, blocker, '', band])
+        curs.execute("insert into rb (block, end, today, blocker, why, band) values (?, ?, ?, ?, ?, ?)", [
+            name, 
+            load_lang('release', 1),
+            now_time, 
+            blocker, 
+            '', 
+            band
+        ])
         curs.execute("delete from ban where block = ?", [name])
     else:
         if login != '':
@@ -931,8 +1049,8 @@ def re_error(data):
                     end += '<li>' + load_lang('why') + ' : ' + end_data[0][1] + '</li>'
 
         return easy_minify(flask.render_template(skin_check(), 
-            imp = ['error', wiki_set(1), custom(), other2([0, 0])],
-            data = '<h2>error</h2><ul>' + end + '</ul>',
+            imp = [load_lang('error'), wiki_set(1), custom(), other2([0, 0])],
+            data = '<h2>' + load_lang('error') + '</h2><ul>' + end + '</ul>',
             menu = 0
         ))
     else:
@@ -947,8 +1065,6 @@ def re_error(data):
                 data = load_lang('authority_error')
             elif num == 4:
                 data = load_lang('no_admin_block_error')
-            elif num == 5:
-                data = load_lang('skin_error')
             elif num == 6:
                 data = load_lang('same_id_exist_error')
             elif num == 7:
@@ -959,6 +1075,10 @@ def re_error(data):
                 data = load_lang('file_exist_error')
             elif num == 10:
                 data = load_lang('password_error')
+            elif num == 11:
+                data = load_lang('topic_long_error')
+            elif num == 12:
+                data = load_lang('email_error')
             elif num == 13:
                 data = load_lang('recaptcha_error')
             elif num == 14:
@@ -981,8 +1101,8 @@ def re_error(data):
                 data = '???'
 
             return easy_minify(flask.render_template(skin_check(), 
-                imp = ['error', wiki_set(1), custom(), other2([0, 0])],
-                data = '<h2>error</h2><ul><li>' + data + '</li></ul>',
+                imp = [load_lang('error'), wiki_set(1), custom(), other2([0, 0])],
+                data = '<h2>' + load_lang('error') + '</h2><ul><li>' + data + '</li></ul>',
                 menu = 0
             ))
         else:

+ 0 - 0
route/tool/set_mark/markdown.py


+ 11 - 14
route/tool/set_mark/namu.py

@@ -238,10 +238,7 @@ def middle_parser(data, fol_num, syntax_num, folding_num):
                                                         middle_data_2 = ['python']
 
                                                     if syntax_num == 0:
-                                                        plus_data +=    '''
-                                                                        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/default.min.css">
-                                                                        <script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/highlight.min.js"></script>
-                                                                        '''
+                                                        plus_data += '<script>hljs.initHighlightingOnLoad();</script>'
 
                                                         syntax_num = 1
 
@@ -260,8 +257,6 @@ def middle_parser(data, fol_num, syntax_num, folding_num):
                                                             folding_data = ['Test']
 
                                                         if folding_num == 0:
-                                                            plus_data += '<script src="/views/main_css/parser.js"></script>'
-
                                                             folding_num = 1
                                                         
                                                         data = re.sub('{{{#!folding ?((?:(?!\n).)*)\n?', '<div>' + str(folding_data[0]) + ' <div style="display: inline-block;"><a href="javascript:void(0);" onclick="folding(' + str(fol_num) + ');">[do]</a></div_end><div id="folding_' + str(fol_num) + '" style="display: none;"><div id="wiki_div" style="">', data, 1)
@@ -385,6 +380,7 @@ def namu(conn, data, title, main_num):
     backlink = []
     end_data = []
     
+    data = re.sub('<math>(?P<in>(?:(?!<\/math>).)+)<\/math>', '[math(\g<in>)]', data)
     data = html.escape(data)
 
     data = re.sub('\r\n', '\n', data)
@@ -481,19 +477,20 @@ def namu(conn, data, title, main_num):
     while 1:
         math = math_re.search(data)
         if math:
-            if first == 0:
-                plus_data += '''
-                    <link rel="stylesheet" href="/views/main_css/katex/katex.min.css">
-                    <script src="/views/main_css/katex/katex.min.js"></script>
-                '''
-
             math = math.groups()[0]
             
             first += 1
             
             data = math_re.sub('<span id="math_' + str(first) + '"></span>', data, 1)
 
-            plus_data += '<script>katex.render("' + math.replace('\\', '\\\\').replace('&lt;', '<').replace('&gt;', '>') +'", document.getElementById("math_' + str(first) + '"));</script>'
+            plus_data += '''
+                <script>
+                    katex.render(
+                        "''' + math.replace('\\', '\\\\').replace('&lt;', '<').replace('&gt;', '>') + '''",
+                        document.getElementById("math_''' + str(first) + '''")
+                    );
+            </script>
+            '''
         else:
             break
             
@@ -943,7 +940,7 @@ def namu(conn, data, title, main_num):
 
                         footnote_all += [[float(footshort), footshort, 0]]
 
-                        data = re_footnote.sub('<sup><a href="javascript:open_foot(\'fn-' + footshort + '\')" id="rfn-' + footshort + '">(' + footshort + ')</a></sup><span class="foot_plus" id="cfn-' + footshort + '"></span>', data, 1)
+                        data = re_footnote.sub('<sup><a href="javascript:open_foot(\'fn-' + footshort + '\')" id="rfn-' + footshort + '">(' + footnote_name + ')</a></sup><span class="foot_plus" id="cfn-' + footshort + '"></span>', data, 1)
                     else:
                         data = re_footnote.sub('<sup><a href="#">(' + footnote_name + ')</a></sup>', data, 1)
                 else:

+ 1 - 1
route/tool/set_mark/tool.py

@@ -9,7 +9,7 @@ def get_time():
     
 def ip_check(d_type = 0):
     if d_type == 0:
-        if flask.session and ('state' and 'id') in flask.session and flask.session['state'] == 1:
+        if flask.session and ('state' and 'id') in flask.session:
             ip = flask.session['id']
         else:
             try:

+ 49 - 46
route/topic.py

@@ -5,6 +5,11 @@ def topic_2(conn, name, sub):
     
     ban = topic_check(name, sub)
     admin = admin_check(3)
+
+    curs.execute("select id from topic where title = ? and sub = ? limit 1", [name, sub])
+    topic_exist = curs.fetchall()
+    if not topic_exist and len(sub) > 256:
+        return re_error('/error/11')
     
     if flask.request.method == 'POST':
         if captcha_post(flask.request.form.get('g-recaptcha-response', '')) == 1:
@@ -29,7 +34,9 @@ def topic_2(conn, name, sub):
         if match:
             curs.execute('insert into alarm (name, data, date) values (?, ?, ?)', [match.groups()[0], ip + ' - <a href="/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '">' + load_lang('user_discussion', 1) + '</a>', today])
         
-        data = re.sub('\[\[((?:분류|category):(?:(?:(?!\]\]).)*))\]\]', '[br]', flask.request.form.get('content', None))
+        cate_re = re.compile('\[\[((?:분류|category):(?:(?:(?!\]\]).)*))\]\]', re.I)
+        data = cate_re.sub('[br]', flask.request.form.get('content', 'Test'))
+        
         for rd_data in re.findall("(?:#([0-9]+))", data):
             curs.execute("select ip from topic where title = ? and sub = ? and id = ?", [name, sub, rd_data])
             ip_data = curs.fetchall()
@@ -53,9 +60,6 @@ def topic_2(conn, name, sub):
         curs.execute("select title from rd where title = ? and sub = ? and stop = 'S'", [name, sub])
         stop_data = curs.fetchall()
         
-        curs.execute("select id from topic where title = ? and sub = ? limit 1", [name, sub])
-        topic_exist = curs.fetchall()
-        
         display = ''
         all_data = ''
         data = ''
@@ -96,22 +100,22 @@ def topic_2(conn, name, sub):
                 who_plus += ' <span style="margin-right: 5px;">@' + topic_data_top[0][0] + ' </span>'
                                 
             all_data += '''
-                        <table id="toron">
-                            <tbody>
-                                <tr>
-                                    <td id="toron_color_red">
-                                        <a href="#''' + topic_data[1] + '''">
-                                            #''' + topic_data[1] + '''
-                                        </a> ''' + ip_pas(topic_data[3]) + who_plus + ''' <span style="float: right;">''' + topic_data[2] + '''</span>
-                                    </td>
-                                </tr>
-                                <tr>
-                                    <td>''' + render_set(data = topic_data[0]) + '''</td>
-                                </tr>
-                            </tbody>
-                        </table>
-                        <br>
-                        '''    
+                <table id="toron">
+                    <tbody>
+                        <tr>
+                            <td id="toron_color_red">
+                                <a href="#''' + topic_data[1] + '''">
+                                    #''' + topic_data[1] + '''
+                                </a> ''' + ip_pas(topic_data[3]) + who_plus + ''' <span style="float: right;">''' + topic_data[2] + '''</span>
+                            </td>
+                        </tr>
+                        <tr>
+                            <td>''' + render_set(data = topic_data[0]) + '''</td>
+                        </tr>
+                    </tbody>
+                </table>
+                <br>
+            '''    
 
         for topic_data in topic:
             user_write = topic_data[0]
@@ -158,41 +162,40 @@ def topic_2(conn, name, sub):
                 user_write = '<br>'
                          
             all_data += '''
-                        <table id="toron">
-                            <tbody>
-                                <tr>
-                                    <td id="toron_color''' + color + '''">
-                                        <a href="javascript:void(0);" id="''' + str(number) + '">#' + str(number) + '</a> ' + ip + '''</span>
-                                    </td>
-                                </tr>
-                                <tr ''' + blind_data + '''>
-                                    <td>''' + user_write + '''</td>
-                                </tr>
-                            </tbody>
-                        </table>
-                        <br>
-                        '''
+                <table id="toron">
+                    <tbody>
+                        <tr>
+                            <td id="toron_color''' + color + '''">
+                                <a href="javascript:void(0);" id="''' + str(number) + '">#' + str(number) + '</a> ' + ip + '''</span>
+                            </td>
+                        </tr>
+                        <tr ''' + blind_data + '''>
+                            <td>''' + user_write + '''</td>
+                        </tr>
+                    </tbody>
+                </table>
+                <br>
+            '''
             number += 1
 
         if ban != 1 or admin == 1:
             data += '''
-                    <div id="plus"></div>
-                    <script type="text/javascript" src="/views/main_css/topic_reload.js"></script>
-                    <script>topic_load("''' + name + '''", "''' + sub + '''");</script>
-                    <a id="reload" href="javascript:void(0);" onclick="location.href.endsWith(\'#reload\')? location.reload(true):location.href=\'#reload\'">(''' + load_lang('reload') + ''')</a>
-                    <form style="''' + display + '''" method="post">
-                    <br>
-                    <textarea style="height: 100px;" name="content"></textarea>
-                    <hr class=\"main_hr\">
-                    ''' + captcha_get()
+                <div id="plus"></div>
+                <script>topic_load("''' + name + '''", "''' + sub + '''");</script>
+                <a id="reload" href="javascript:void(0);" onclick="location.href.endsWith(\'#reload\')? location.reload(true):location.href=\'#reload\'">(''' + load_lang('reload') + ''')</a>
+                <form style="''' + display + '''" method="post">
+                <br>
+                <textarea style="height: 100px;" name="content"></textarea>
+                <hr class=\"main_hr\">
+            ''' + captcha_get()
             
             if display == '':
                 data += ip_warring()
 
             data += '''
-                        <button type="submit">''' + load_lang('send') + '''</button>
-                    </form>
-                    '''
+                    <button type="submit">''' + load_lang('send') + '''</button>
+                </form>
+            '''
 
         return easy_minify(flask.render_template(skin_check(), 
             imp = [name, wiki_set(), custom(), other2([' (' + load_lang('discussion') + ')', 0])],

+ 1 - 1
route/topic_admin.py

@@ -54,7 +54,7 @@ def topic_admin_2(conn, name, sub, num):
             <h2>''' + load_lang('other_tool') + '''</h2>
             <ul>
                 <li>
-                    <a href="/topic/''' + url_pas(name) + '/sub/' + url_pas(sub) + '/raw/' + str(num) + '''">raw</a>
+                    <a href="/topic/''' + url_pas(name) + '/sub/' + url_pas(sub) + '/raw/' + str(num) + '''">''' + load_lang('raw') + '''</a>
                 </li>
             '''
     ban = '<li>' + load_lang('time') + ' : ' + data[0][2] + '</li>' + ban

+ 21 - 0
route/topic_block.py

@@ -0,0 +1,21 @@
+from .tool.func import *
+
+def topic_block_2(conn, name, sub, num):
+    curs = conn.cursor()
+
+    if admin_check(3, 'blind (' + name + ' - ' + sub + '#' + str(num) + ')') != 1:
+        return re_error('/error/3')
+
+    curs.execute("select block from topic where title = ? and sub = ? and id = ?", [name, sub, str(num)])
+    block = curs.fetchall()
+    if block:
+        if block[0][0] == 'O':
+            curs.execute("update topic set block = '' where title = ? and sub = ? and id = ?", [name, sub, str(num)])
+        else:
+            curs.execute("update topic set block = 'O' where title = ? and sub = ? and id = ?", [name, sub, str(num)])
+        
+        rd_plus(name, sub, get_time())
+        
+        conn.commit()
+        
+    return redirect('/topic/' + url_pas(name) + '/sub/' + url_pas(sub) + '#' + str(num))

+ 0 - 179
version-ko.md

@@ -1,179 +0,0 @@
-## 0.1 (알파)
- * 문서 보기와 편집
- * 기타 문서
- * 랜덤 구현
-
-## 0.2 ~ 0.9 (베타)
- * 그 외 엄청나게 많은 기능 구현 (기존 [오픈나무](https://github.com/2DU/Discard-opennamu-Legacy) 기능에서 로그인 필요한 기능 빼고 구현)
-
-## 1.0
- * 로그인 구현
-
-## 1.1
- * 차단 구현
- * 토론 닫기, 정지
- * 블라인드 구현
- * ACL 기능 구현
- * 어드민 부여 구현
-
-## 1.2
- * 미리보기 구현
- * 대역 차단 구현
- * 문서 비교 구현
- * 파일 업로드 개선
- * 파일 업로드 구현
- * 기본적인 다중 검사 기능
-
-## 1.3
- * 토론 목록 보강
- * 토론에 문법 지원
- * 비 효율적으로 돌아가던거 수정
- * 하위 문서 지원
- * 관리자 기능의 접근성 향상
- * 대규모도 편하게 접근되게
-
-## 1.4
- * 사용자 문서
- * 사문 접근성
- * 검색 기능 수정
- * 상위 문서 바로가기
- * 유저 기록 보기
-
-## 1.5 (정식)
- * 디자인 변경
- * 관리자 기능 접근성
- * 파일 문서 생성
- * 유저 가입 목록
- * 최근 차단을 유저 차단 기록으로
-
-## 1.6
- * 역링크 기능 완성 
- * 분류 완성 
- * 셋업 변경
- * 문단 편집 
- * 비밀번호 변경 
- * 몇몇 알고리즘 변경과 토론 있으면 불 나오게
- 
-## 1.7
- * 404 반환
- * 역사 가리기
- * 사용자 문서 역링크 방지
- * 사용자 목록 개선
- * 설계 변경
- * 디자인 패치
- * 비밀번호 잘못 입력 방지 시스템
- 
-## 1.8
- * 디자인 변경 
- * 서명 문법 
- * 차단 당한 유저 사문에는 차단 표기 되게 
- * 토론 공지 
- * 합의된 토론 
- * 기타 등등 
-
-## 1.9
- * 코드 분리 및 정리
- * 역 링크 재 생성 메뉴
- * 기타 등등등
- * 검색 강화
- * 커스텀 CSS
- * 파일명 제한 없애기
- 
-## 2.0 (bottle)
- * Bottle로 이전
- * 업로드 다시 완성
- * 사용자 토론 기록 보기
- * 많은 문서 삭제
- * 디자인 분리
- * 디자인 기능 분리
- * 나머지
- * 코드 많이 수정
- 
-## 2.1
- * 타임아웃 문제 해결
- * 하위 문서 바로가기
- * app.py 부분 while을 for로 수정
- * 역링크 구조 개선
-
-## 2.2 (SQLite)
- * SQLite로 DB 변경
- * set.json 대부분 위키 내부로 이전
- * 파서 수정
- * 문법 추가
- * 기타 기능 수정
- * 커스텀 JS
- * 비 로그인도 CSS, JS 기능 사용 가능하게
-
-## 2.3
- * 기본 스킨 Acme로 변경
- * diff 수정
- * 관리자 사용 기록
- * 파일 올리기 완성
- * 스킨 선택
- * UA 보여주기
- * 사문 ACL
- * 다른 문서 불러오기
- * 아이피 비공개
- * 백업 기능
-
-## 2.4
- * 로그인 가능 차단
- * 리캡차 기능
- * robot.txt 설정 가능
- * 모든 문서 보기 비활성화
- * 편집 필터
- * 차단 기록 세분화
-
-## 2.5
- * 주기 문서 기능
- * 현재 차단 목록
- * ACL 개편
- * 기타 구조 개편
- * 파일 시스템 개선
- * 잡 패치
-
-## 2.6 (Flask)
- * 기반 구조 개편
- * 분류 구조 개편
- * 디자인 수정
- * 문법 추가, 수정
- * 재 인덱싱 추가
- * 디자인 수정
-
-## 3.0 (진행)
- * 파서 다시 작성
- * 사소한 기능 변경
- * 내 정보 수정 완성
- * 사용자 스킨 기능
- * 차단 관련 조정
- * 스킨 JinJa로 변경
- * 파서 완성
- * 이메일 인증 추가
-
-
-## 자세한 내용
- * [참조](https://github.com/2DU/opennamu/commits/master)
-
-----
-## 라이선스
-### 오픈나무
- * [BSD 3-Clause License](https://github.com/2DU/opennamu/blob/master/license.md)
-
-### 외부 파일
- * 인용문 아이콘 [Dave Gandy](http://www.flaticon.com/free-icon/quote-left_25672) CC 3.0 BY
- * 구문 강조 [highlightjs](https://highlightjs.org/)
- * 수식 [KaTeX](https://github.com/Khan/KaTeX)
- 
-## 기여자들
- * [참조](https://github.com/2DU/opennamu/graphs/contributors)
-
-## 도움 준 사람들
- * [Team Croatia](https://github.com/TeamCroatia)
- * Basix
- * Efrit
- * 기타 채팅방 사람들
-
-----
-## 개발 이념
- * 최대한 간단하게
- * 개발하기 편하게

+ 3 - 0
views/easter_egg.html

@@ -0,0 +1,3 @@
+<iframe style="width: 100%; height: 500px;" src="https://jcw87.github.io/c2-sans-fight/"></iframe>
+<br>
+<a id="out_link" href="https://jcw87.github.io/c2-sans-fight/">https://jcw87.github.io/c2-sans-fight/</a>

+ 2 - 2
views/main_css/main.css → views/main_css/css/main.css

@@ -1,5 +1,5 @@
 textarea { width: 100%; }
-input { width: 100%; }
+input { width: 100%; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; }
 #last { margin-top: 30px; }
 #toc { border: 1px solid; padding: 20px; width: fit-content; width: -moz-fit-content; margin-top: 10px; }
 #toc-name { font-size: 18px; }
@@ -31,7 +31,7 @@ s:hover, strike:hover, del:hover { color: gray; background-color: gainsboro; tex
 #main_table_width_half { width: 50%; }
 #main_table_width_quarter { width: 25%; }
 #redirect { border: 1px solid; padding: 10px; }
-body { word-break: break-all; overflow: scroll; }
+body { word-break: break-all; overflow: auto; }
 hr.main_hr { border: none; }
 #include_link { display: none; }
 .foot_plus { background: gainsboro; }

+ 0 - 0
views/main_css/oauth.css → views/main_css/css/oauth.css


+ 19 - 0
views/main_css/js/do_preview.js

@@ -0,0 +1,19 @@
+function do_preview(name) {
+    var o_data = document.getElementById('content');
+    var p_data = document.getElementById('see_preview');
+
+    var s_data = new FormData();
+    s_data.append('data', o_data.value);
+
+    var url = "/api/w/" + name;
+    
+    var xhr = new XMLHttpRequest();
+    xhr.open("POST", url, true);
+    xhr.send(s_data);
+
+    xhr.onreadystatechange = function() {
+        if(this.readyState === 4 && this.status === 200) {
+            p_data.innerHTML = JSON.parse(this.responseText)['data'];
+        }
+    }
+}

+ 1 - 3
views/main_css/parser.js → views/main_css/js/folding.js

@@ -1,8 +1,6 @@
-hljs.initHighlightingOnLoad(); 
-
 function folding(num) { 
     var fol = document.getElementById('folding_' + num); 
-    if(fol.style.display == 'inline-block' || fol.style.display == 'block') { 
+    if(fol.style.display === 'inline-block' || fol.style.display === 'block') { 
         fol.style.display = 'none';
     } else {
         fol.style.display = 'block'; 

+ 17 - 0
views/main_css/js/insert_data.js

@@ -0,0 +1,17 @@
+// https://stackoverflow.com/questions/11076975/insert-text-into-textarea-at-cursor-position-javascript
+
+function insert_data(name, data) {
+    if(document.selection) { 
+        document.getElementById(name).focus();
+
+        sel = document.selection.createRange();
+        sel.text = data; 
+    } else if(document.getElementById(name).selectionStart || document.getElementById(name).selectionStart == '0') {
+        var startPos = document.getElementById(name).selectionStart;
+        var endPos = document.getElementById(name).selectionEnd;
+
+        document.getElementById(name).value = document.getElementById(name).value.substring(0, startPos) + data + document.getElementById(name).value.substring(endPos, document.getElementById(name).value.length); 
+    } else {
+        document.getElementById(name).value += data;
+    }
+}

+ 16 - 0
views/main_css/js/load_ver.js

@@ -0,0 +1,16 @@
+function load_ver() {
+    var n_ver = document.getElementById('ver_send');
+
+    var url = "/api/version";
+    
+    var xhr = new XMLHttpRequest();
+    xhr.open("GET", url, true);
+    xhr.send(null);
+
+    xhr.onreadystatechange = function() {
+        if(this.readyState === 4 && this.status === 200) {
+            n_ver.innerHTML += JSON.parse(this.responseText)['lastest_version'];
+            n_ver.style.display = "list-item";
+        }
+    }
+}

+ 3 - 1
views/main_css/main.js → views/main_css/js/open_foot.js

@@ -1,6 +1,8 @@
 function open_foot(name) {
-    var g_data = document.getElementById(name);
     var o_data = document.getElementById('c' + name);
+    
+    name = name.replace(/\.([0-9]+)$/, '');
+    var g_data = document.getElementById(name);
 
     if(o_data.innerHTML === '') {
         o_data.innerHTML += '<sup><a onclick="open_foot(\'' + name + '\')" href="#' + name + '">(Go)</a></sup> ' + g_data.innerHTML;

+ 3 - 6
views/main_css/topic_reload.js → views/main_css/js/topic_load.js

@@ -19,19 +19,16 @@ function topic_load(name, sub) {
             var xhr = new XMLHttpRequest();
             var doc_data = document.getElementById("plus");
 
-            xhr.open("GET", url);
+            xhr.open("GET", url, true);
             xhr.send(null);
 
             xhr.onreadystatechange = function() {
-                if(this.readyState == XMLHttpRequest.DONE && xhr.status == 200 && xhr.responseText != "{}\n") {
-                    console.log(xhr.responseText);
-                    console.log(url);
-
+                if(this.readyState === 4 && this.status === 200 && this.responseText !== "{}\n") {
                     doc_data.innerText += '(New)\n\n';
 
                     clearInterval(test);
                 }
             }
-        }, 3000)
+        }, 1000)
     }, 4000);
 }

+ 0 - 90
views/main_css/katex/README.md

@@ -1,90 +0,0 @@
-# [<img src="https://cdn.rawgit.com/Khan/KaTeX/84189cd3adae24d92e766d14eb80d6e54f3c7dca/katex-logo.svg" width="130" alt="KaTeX">](https://khan.github.io/KaTeX/)
-[![npm](https://img.shields.io/npm/v/katex.svg)](https://www.npmjs.com/package/katex)
-[![CircleCI](https://circleci.com/gh/Khan/KaTeX.svg?style=shield)](https://circleci.com/gh/Khan/KaTeX)
-[![codecov](https://codecov.io/gh/Khan/KaTeX/branch/master/graph/badge.svg)](https://codecov.io/gh/Khan/KaTeX)
-[![Join the chat at https://gitter.im/Khan/KaTeX](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Khan/KaTeX?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Greenkeeper badge](https://badges.greenkeeper.io/Khan/KaTeX.svg)](https://greenkeeper.io/)
-[![jsDelivr](https://data.jsdelivr.com/v1/package/npm/katex/badge?style=rounded)](https://www.jsdelivr.com/package/npm/katex)
-![](https://img.badgesize.io/Khan/KaTeX/v0.10.0-rc.1/dist/katex.min.js?compression=gzip)
-
-KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web.
-
- * **Fast:** KaTeX renders its math synchronously and doesn't need to reflow the page. See how it compares to a competitor in [this speed test](http://www.intmath.com/cg5/katex-mathjax-comparison.php).
- * **Print quality:** KaTeX’s layout is based on Donald Knuth’s TeX, the gold standard for math typesetting.
- * **Self contained:** KaTeX has no dependencies and can easily be bundled with your website resources.
- * **Server side rendering:** KaTeX produces the same output regardless of browser or environment, so you can pre-render expressions using Node.js and send them as plain HTML.
-
-KaTeX is compatible with all major browsers, including Chrome, Safari, Firefox, Opera, Edge, and IE 9–11.
-
-KaTeX supports much (but not all) of LaTeX and many LaTeX packages. See the [list of supported functions](https://khan.github.io/KaTeX/docs/supported.html).
-
-Try out KaTeX [on the demo page](https://khan.github.io/KaTeX/#demo)!
-
-## Getting started
-
-### Starter template
-
-```html
-<!DOCTYPE html>
-<!-- KaTeX requires the use of the HTML5 doctype. Without it, KaTeX may not render properly -->
-<html>
-  <head>
-    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.10.0-rc.1/dist/katex.min.css" integrity="sha384-D+9gmBxUQogRLqvARvNLmA9hS2x//eK1FhVb9PiU86gmcrBrJAQT8okdJ4LMp2uv" crossorigin="anonymous">
-
-    <!-- The loading of KaTeX is deferred to speed up page rendering -->
-    <script defer src="https://cdn.jsdelivr.net/npm/katex@0.10.0-rc.1/dist/katex.min.js" integrity="sha384-483A6DwYfKeDa0Q52fJmxFXkcPCFfnXMoXblOkJ4JcA8zATN6Tm78UNL72AKk+0O" crossorigin="anonymous"></script>
-
-    <!-- To automatically render math in text elements, include the auto-render extension: -->
-    <script defer src="https://cdn.jsdelivr.net/npm/katex@0.10.0-rc.1/dist/contrib/auto-render.min.js" integrity="sha384-yACMu8JWxKzSp/C1YV86pzGiQ/l1YUfE8oPuahJQxzehAjEt2GiQuy/BIvl9KyeF" crossorigin="anonymous"
-        onload="renderMathInElement(document.body);"></script>
-  </head>
-  ...
-</html>
-```
-
-You can also [download KaTeX](https://github.com/khan/katex/releases) and host it yourself.
-
-For details on how to configure auto-render extension, refer to [the documentation](https://khan.github.io/KaTeX/docs/autorender.html).
-
-### API
-
-Call `katex.render` to render a TeX expression directly into a DOM element.
-For example:
-
-```js
-katex.render("c = \\pm\\sqrt{a^2 + b^2}", element, {
-    throwOnError: false
-});
-```
-
-Call `katex.renderToString` to generate an HTML string of the rendered math,
-e.g., for server-side rendering.  For example:
-
-```js
-var html = katex.renderToString("c = \\pm\\sqrt{a^2 + b^2}", {
-    throwOnError: false
-});
-// '<span class="katex">...</span>'
-```
-
-Make sure to include the CSS and font files in both cases.
-If you are doing all rendering on the server, there is no need to include the
-JavaScript on the client.
-
-The examples above use the `throwOnError: false` option, which renders invalid
-inputs as the TeX source code in red (by default), with the error message as
-hover text.  For other available options, see the
-[API documentation](https://khan.github.io/KaTeX/docs/api.html),
-[options documentation](https://khan.github.io/KaTeX/docs/options.html), and
-[handling errors documentation](https://khan.github.io/KaTeX/docs/error.html).
-
-## Demo and Documentation
-
-Learn more about using KaTeX [on the website](https://khan.github.io/KaTeX)!
-
-## Contributing
-
-See [CONTRIBUTING.md](CONTRIBUTING.md)
-
-## License
-
-KaTeX is licensed under the [MIT License](http://opensource.org/licenses/MIT).

+ 0 - 321
views/main_css/katex/contrib/auto-render.js

@@ -1,321 +0,0 @@
-(function webpackUniversalModuleDefinition(root, factory) {
-	if(typeof exports === 'object' && typeof module === 'object')
-		module.exports = factory(require("katex"));
-	else if(typeof define === 'function' && define.amd)
-		define(["katex"], factory);
-	else if(typeof exports === 'object')
-		exports["renderMathInElement"] = factory(require("katex"));
-	else
-		root["renderMathInElement"] = factory(root["katex"]);
-})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__0__) {
-return /******/ (function(modules) { // webpackBootstrap
-/******/ 	// The module cache
-/******/ 	var installedModules = {};
-/******/
-/******/ 	// The require function
-/******/ 	function __webpack_require__(moduleId) {
-/******/
-/******/ 		// Check if module is in cache
-/******/ 		if(installedModules[moduleId]) {
-/******/ 			return installedModules[moduleId].exports;
-/******/ 		}
-/******/ 		// Create a new module (and put it into the cache)
-/******/ 		var module = installedModules[moduleId] = {
-/******/ 			i: moduleId,
-/******/ 			l: false,
-/******/ 			exports: {}
-/******/ 		};
-/******/
-/******/ 		// Execute the module function
-/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
-/******/
-/******/ 		// Flag the module as loaded
-/******/ 		module.l = true;
-/******/
-/******/ 		// Return the exports of the module
-/******/ 		return module.exports;
-/******/ 	}
-/******/
-/******/
-/******/ 	// expose the modules object (__webpack_modules__)
-/******/ 	__webpack_require__.m = modules;
-/******/
-/******/ 	// expose the module cache
-/******/ 	__webpack_require__.c = installedModules;
-/******/
-/******/ 	// define getter function for harmony exports
-/******/ 	__webpack_require__.d = function(exports, name, getter) {
-/******/ 		if(!__webpack_require__.o(exports, name)) {
-/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
-/******/ 		}
-/******/ 	};
-/******/
-/******/ 	// define __esModule on exports
-/******/ 	__webpack_require__.r = function(exports) {
-/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
-/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
-/******/ 		}
-/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
-/******/ 	};
-/******/
-/******/ 	// create a fake namespace object
-/******/ 	// mode & 1: value is a module id, require it
-/******/ 	// mode & 2: merge all properties of value into the ns
-/******/ 	// mode & 4: return value when already ns object
-/******/ 	// mode & 8|1: behave like require
-/******/ 	__webpack_require__.t = function(value, mode) {
-/******/ 		if(mode & 1) value = __webpack_require__(value);
-/******/ 		if(mode & 8) return value;
-/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
-/******/ 		var ns = Object.create(null);
-/******/ 		__webpack_require__.r(ns);
-/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
-/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
-/******/ 		return ns;
-/******/ 	};
-/******/
-/******/ 	// getDefaultExport function for compatibility with non-harmony modules
-/******/ 	__webpack_require__.n = function(module) {
-/******/ 		var getter = module && module.__esModule ?
-/******/ 			function getDefault() { return module['default']; } :
-/******/ 			function getModuleExports() { return module; };
-/******/ 		__webpack_require__.d(getter, 'a', getter);
-/******/ 		return getter;
-/******/ 	};
-/******/
-/******/ 	// Object.prototype.hasOwnProperty.call
-/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
-/******/
-/******/ 	// __webpack_public_path__
-/******/ 	__webpack_require__.p = "";
-/******/
-/******/
-/******/ 	// Load entry module and return exports
-/******/ 	return __webpack_require__(__webpack_require__.s = 1);
-/******/ })
-/************************************************************************/
-/******/ ([
-/* 0 */
-/***/ (function(module, exports) {
-
-module.exports = __WEBPACK_EXTERNAL_MODULE__0__;
-
-/***/ }),
-/* 1 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-
-// EXTERNAL MODULE: external "katex"
-var external_katex_ = __webpack_require__(0);
-var external_katex_default = /*#__PURE__*/__webpack_require__.n(external_katex_);
-
-// CONCATENATED MODULE: ./contrib/auto-render/splitAtDelimiters.js
-/* eslint no-constant-condition:0 */
-var findEndOfMath = function findEndOfMath(delimiter, text, startIndex) {
-    // Adapted from
-    // https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
-    var index = startIndex;
-    var braceLevel = 0;
-
-    var delimLength = delimiter.length;
-
-    while (index < text.length) {
-        var character = text[index];
-
-        if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) {
-            return index;
-        } else if (character === "\\") {
-            index++;
-        } else if (character === "{") {
-            braceLevel++;
-        } else if (character === "}") {
-            braceLevel--;
-        }
-
-        index++;
-    }
-
-    return -1;
-};
-
-var splitAtDelimiters = function splitAtDelimiters(startData, leftDelim, rightDelim, display) {
-    var finalData = [];
-
-    for (var i = 0; i < startData.length; i++) {
-        if (startData[i].type === "text") {
-            var text = startData[i].data;
-
-            var lookingForLeft = true;
-            var currIndex = 0;
-            var nextIndex = void 0;
-
-            nextIndex = text.indexOf(leftDelim);
-            if (nextIndex !== -1) {
-                currIndex = nextIndex;
-                finalData.push({
-                    type: "text",
-                    data: text.slice(0, currIndex)
-                });
-                lookingForLeft = false;
-            }
-
-            while (true) {
-                if (lookingForLeft) {
-                    nextIndex = text.indexOf(leftDelim, currIndex);
-                    if (nextIndex === -1) {
-                        break;
-                    }
-
-                    finalData.push({
-                        type: "text",
-                        data: text.slice(currIndex, nextIndex)
-                    });
-
-                    currIndex = nextIndex;
-                } else {
-                    nextIndex = findEndOfMath(rightDelim, text, currIndex + leftDelim.length);
-                    if (nextIndex === -1) {
-                        break;
-                    }
-
-                    finalData.push({
-                        type: "math",
-                        data: text.slice(currIndex + leftDelim.length, nextIndex),
-                        rawData: text.slice(currIndex, nextIndex + rightDelim.length),
-                        display: display
-                    });
-
-                    currIndex = nextIndex + rightDelim.length;
-                }
-
-                lookingForLeft = !lookingForLeft;
-            }
-
-            finalData.push({
-                type: "text",
-                data: text.slice(currIndex)
-            });
-        } else {
-            finalData.push(startData[i]);
-        }
-    }
-
-    return finalData;
-};
-
-/* harmony default export */ var auto_render_splitAtDelimiters = (splitAtDelimiters);
-// CONCATENATED MODULE: ./contrib/auto-render/auto-render.js
-/* eslint no-console:0 */
-
-
-
-
-var auto_render_splitWithDelimiters = function splitWithDelimiters(text, delimiters) {
-    var data = [{ type: "text", data: text }];
-    for (var i = 0; i < delimiters.length; i++) {
-        var delimiter = delimiters[i];
-        data = auto_render_splitAtDelimiters(data, delimiter.left, delimiter.right, delimiter.display || false);
-    }
-    return data;
-};
-
-/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
- * API, we should copy it before mutating.
- */
-var auto_render_renderMathInText = function renderMathInText(text, optionsCopy) {
-    var data = auto_render_splitWithDelimiters(text, optionsCopy.delimiters);
-    var fragment = document.createDocumentFragment();
-
-    for (var i = 0; i < data.length; i++) {
-        if (data[i].type === "text") {
-            fragment.appendChild(document.createTextNode(data[i].data));
-        } else {
-            var span = document.createElement("span");
-            var math = data[i].data;
-            // Override any display mode defined in the settings with that
-            // defined by the text itself
-            optionsCopy.displayMode = data[i].display;
-            try {
-                external_katex_default.a.render(math, span, optionsCopy);
-            } catch (e) {
-                if (!(e instanceof external_katex_default.a.ParseError)) {
-                    throw e;
-                }
-                optionsCopy.errorCallback("KaTeX auto-render: Failed to parse `" + data[i].data + "` with ", e);
-                fragment.appendChild(document.createTextNode(data[i].rawData));
-                continue;
-            }
-            fragment.appendChild(span);
-        }
-    }
-
-    return fragment;
-};
-
-var renderElem = function renderElem(elem, optionsCopy) {
-    for (var i = 0; i < elem.childNodes.length; i++) {
-        var childNode = elem.childNodes[i];
-        if (childNode.nodeType === 3) {
-            // Text node
-            var frag = auto_render_renderMathInText(childNode.textContent, optionsCopy);
-            i += frag.childNodes.length - 1;
-            elem.replaceChild(frag, childNode);
-        } else if (childNode.nodeType === 1) {
-            (function () {
-                // Element node
-                var className = ' ' + childNode.className + ' ';
-                var shouldRender = optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && optionsCopy.ignoredClasses.every(function (x) {
-                    return className.indexOf(' ' + x + ' ') === -1;
-                });
-
-                if (shouldRender) {
-                    renderElem(childNode, optionsCopy);
-                }
-            })();
-        }
-        // Otherwise, it's something else, and ignore it.
-    }
-};
-
-var renderMathInElement = function renderMathInElement(elem, options) {
-    if (!elem) {
-        throw new Error("No element provided to render");
-    }
-
-    var optionsCopy = {};
-
-    // Object.assign(optionsCopy, option)
-    for (var option in options) {
-        if (options.hasOwnProperty(option)) {
-            optionsCopy[option] = options[option];
-        }
-    }
-
-    // default options
-    optionsCopy.delimiters = optionsCopy.delimiters || [{ left: "$$", right: "$$", display: true }, { left: "\\(", right: "\\)", display: false },
-    // LaTeX uses $…$, but it ruins the display of normal `$` in text:
-    // {left: "$", right: "$", display: false},
-
-    //  \[…\] must come last in this array. Otherwise, renderMathInElement
-    //  will search for \[ before it searches for $$ or  \(
-    // That makes it susceptible to finding a \\[0.3em] row delimiter and
-    // treating it as if it were the start of a KaTeX math zone.
-    { left: "\\[", right: "\\]", display: true }];
-    optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code"];
-    optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
-    optionsCopy.errorCallback = optionsCopy.errorCallback || console.error;
-
-    // Enable sharing of global macros defined via `\gdef` between different
-    // math elements within a single call to `renderMathInElement`.
-    optionsCopy.macros = optionsCopy.macros || {};
-
-    renderElem(elem, optionsCopy);
-};
-
-/* harmony default export */ var auto_render = __webpack_exports__["default"] = (renderMathInElement);
-
-/***/ })
-/******/ ])["default"];
-});

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
views/main_css/katex/contrib/auto-render.min.js


+ 0 - 14
views/main_css/katex/contrib/copy-tex.css

@@ -1,14 +0,0 @@
-/* Force selection of entire .katex/.katex-display blocks, so that we can
- * copy/paste the entire source code.  If you omit this CSS, partial
- * selections of a formula will work, but will copy the ugly HTML
- * representation instead of the LaTeX source code.  (Full selections will
- * still produce the LaTeX source code.)
- */
-.katex,
-.katex-display {
-    user-select: all;
-    -moz-user-select: all;
-    -webkit-user-select: all;
-    -ms-user-select: all;
-}
-

+ 0 - 191
views/main_css/katex/contrib/copy-tex.js

@@ -1,191 +0,0 @@
-(function webpackUniversalModuleDefinition(root, factory) {
-	if(typeof exports === 'object' && typeof module === 'object')
-		module.exports = factory();
-	else if(typeof define === 'function' && define.amd)
-		define([], factory);
-	else {
-		var a = factory();
-		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
-	}
-})((typeof self !== 'undefined' ? self : this), function() {
-return /******/ (function(modules) { // webpackBootstrap
-/******/ 	// The module cache
-/******/ 	var installedModules = {};
-/******/
-/******/ 	// The require function
-/******/ 	function __webpack_require__(moduleId) {
-/******/
-/******/ 		// Check if module is in cache
-/******/ 		if(installedModules[moduleId]) {
-/******/ 			return installedModules[moduleId].exports;
-/******/ 		}
-/******/ 		// Create a new module (and put it into the cache)
-/******/ 		var module = installedModules[moduleId] = {
-/******/ 			i: moduleId,
-/******/ 			l: false,
-/******/ 			exports: {}
-/******/ 		};
-/******/
-/******/ 		// Execute the module function
-/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
-/******/
-/******/ 		// Flag the module as loaded
-/******/ 		module.l = true;
-/******/
-/******/ 		// Return the exports of the module
-/******/ 		return module.exports;
-/******/ 	}
-/******/
-/******/
-/******/ 	// expose the modules object (__webpack_modules__)
-/******/ 	__webpack_require__.m = modules;
-/******/
-/******/ 	// expose the module cache
-/******/ 	__webpack_require__.c = installedModules;
-/******/
-/******/ 	// define getter function for harmony exports
-/******/ 	__webpack_require__.d = function(exports, name, getter) {
-/******/ 		if(!__webpack_require__.o(exports, name)) {
-/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
-/******/ 		}
-/******/ 	};
-/******/
-/******/ 	// define __esModule on exports
-/******/ 	__webpack_require__.r = function(exports) {
-/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
-/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
-/******/ 		}
-/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
-/******/ 	};
-/******/
-/******/ 	// create a fake namespace object
-/******/ 	// mode & 1: value is a module id, require it
-/******/ 	// mode & 2: merge all properties of value into the ns
-/******/ 	// mode & 4: return value when already ns object
-/******/ 	// mode & 8|1: behave like require
-/******/ 	__webpack_require__.t = function(value, mode) {
-/******/ 		if(mode & 1) value = __webpack_require__(value);
-/******/ 		if(mode & 8) return value;
-/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
-/******/ 		var ns = Object.create(null);
-/******/ 		__webpack_require__.r(ns);
-/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
-/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
-/******/ 		return ns;
-/******/ 	};
-/******/
-/******/ 	// getDefaultExport function for compatibility with non-harmony modules
-/******/ 	__webpack_require__.n = function(module) {
-/******/ 		var getter = module && module.__esModule ?
-/******/ 			function getDefault() { return module['default']; } :
-/******/ 			function getModuleExports() { return module; };
-/******/ 		__webpack_require__.d(getter, 'a', getter);
-/******/ 		return getter;
-/******/ 	};
-/******/
-/******/ 	// Object.prototype.hasOwnProperty.call
-/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
-/******/
-/******/ 	// __webpack_public_path__
-/******/ 	__webpack_require__.p = "";
-/******/
-/******/
-/******/ 	// Load entry module and return exports
-/******/ 	return __webpack_require__(__webpack_require__.s = 2);
-/******/ })
-/************************************************************************/
-/******/ ([
-/* 0 */
-/***/ (function(module, exports, __webpack_require__) {
-
-// extracted by mini-css-extract-plugin
-
-/***/ }),
-/* 1 */,
-/* 2 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-
-// EXTERNAL MODULE: ./contrib/copy-tex/copy-tex.css
-var copy_tex = __webpack_require__(0);
-
-// CONCATENATED MODULE: ./contrib/copy-tex/katex2tex.js
-// Set these to how you want inline and display math to be delimited.
-var defaultCopyDelimiters = {
-    inline: ['$', '$'], // alternative: ['\(', '\)']
-    display: ['$$', '$$'] // alternative: ['\[', '\]']
-};
-
-// Replace .katex elements with their TeX source (<annotation> element).
-// Modifies fragment in-place.  Useful for writing your own 'copy' handler,
-// as in copy-tex.js.
-var katexReplaceWithTex = function katexReplaceWithTex(fragment) {
-    var copyDelimiters = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : defaultCopyDelimiters;
-
-    // Remove .katex-html blocks that are preceded by .katex-mathml blocks
-    // (which will get replaced below).
-    var katexHtml = fragment.querySelectorAll('.katex-mathml + .katex-html');
-    for (var i = 0; i < katexHtml.length; i++) {
-        var element = katexHtml[i];
-        if (element.remove) {
-            element.remove(null);
-        } else {
-            element.parentNode.removeChild(element);
-        }
-    }
-    // Replace .katex-mathml elements with their annotation (TeX source)
-    // descendant, with inline delimiters.
-    var katexMathml = fragment.querySelectorAll('.katex-mathml');
-    for (var _i = 0; _i < katexMathml.length; _i++) {
-        var _element = katexMathml[_i];
-        var texSource = _element.querySelector('annotation');
-        if (texSource) {
-            if (_element.replaceWith) {
-                _element.replaceWith(texSource);
-            } else {
-                _element.parentNode.replaceChild(texSource, _element);
-            }
-            texSource.innerHTML = copyDelimiters.inline[0] + texSource.innerHTML + copyDelimiters.inline[1];
-        }
-    }
-    // Switch display math to display delimiters.
-    var displays = fragment.querySelectorAll('.katex-display annotation');
-    for (var _i2 = 0; _i2 < displays.length; _i2++) {
-        var _element2 = displays[_i2];
-        _element2.innerHTML = copyDelimiters.display[0] + _element2.innerHTML.substr(copyDelimiters.inline[0].length, _element2.innerHTML.length - copyDelimiters.inline[0].length - copyDelimiters.inline[1].length) + copyDelimiters.display[1];
-    }
-    return fragment;
-};
-
-/* harmony default export */ var katex2tex = (katexReplaceWithTex);
-// CONCATENATED MODULE: ./contrib/copy-tex/copy-tex.js
-
-
-
-// Global copy handler to modify behavior on .katex elements.
-document.addEventListener('copy', function (event) {
-    var selection = window.getSelection();
-    if (selection.isCollapsed) {
-        return; // default action OK if selection is empty
-    }
-    var fragment = selection.getRangeAt(0).cloneContents();
-    if (!fragment.querySelector('.katex-mathml')) {
-        return; // default action OK if no .katex-mathml elements
-    }
-    // Preserve usual HTML copy/paste behavior.
-    var html = [];
-    for (var i = 0; i < fragment.childNodes.length; i++) {
-        html.push(fragment.childNodes[i].outerHTML);
-    }
-    event.clipboardData.setData('text/html', html.join(''));
-    // Rewrite plain-text version.
-    event.clipboardData.setData('text/plain', katex2tex(fragment).textContent);
-    // Prevent normal copy handling.
-    event.preventDefault();
-});
-
-/***/ })
-/******/ ])["default"];
-});

+ 0 - 1
views/main_css/katex/contrib/copy-tex.min.css

@@ -1 +0,0 @@
-.katex,.katex-display{-moz-user-select:all;-ms-user-select:all;-webkit-user-select:all;user-select:all}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
views/main_css/katex/contrib/copy-tex.min.js


+ 0 - 134
views/main_css/katex/contrib/mathtex-script-type.js

@@ -1,134 +0,0 @@
-(function webpackUniversalModuleDefinition(root, factory) {
-	if(typeof exports === 'object' && typeof module === 'object')
-		module.exports = factory(require("katex"));
-	else if(typeof define === 'function' && define.amd)
-		define(["katex"], factory);
-	else {
-		var a = typeof exports === 'object' ? factory(require("katex")) : factory(root["katex"]);
-		for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
-	}
-})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__0__) {
-return /******/ (function(modules) { // webpackBootstrap
-/******/ 	// The module cache
-/******/ 	var installedModules = {};
-/******/
-/******/ 	// The require function
-/******/ 	function __webpack_require__(moduleId) {
-/******/
-/******/ 		// Check if module is in cache
-/******/ 		if(installedModules[moduleId]) {
-/******/ 			return installedModules[moduleId].exports;
-/******/ 		}
-/******/ 		// Create a new module (and put it into the cache)
-/******/ 		var module = installedModules[moduleId] = {
-/******/ 			i: moduleId,
-/******/ 			l: false,
-/******/ 			exports: {}
-/******/ 		};
-/******/
-/******/ 		// Execute the module function
-/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
-/******/
-/******/ 		// Flag the module as loaded
-/******/ 		module.l = true;
-/******/
-/******/ 		// Return the exports of the module
-/******/ 		return module.exports;
-/******/ 	}
-/******/
-/******/
-/******/ 	// expose the modules object (__webpack_modules__)
-/******/ 	__webpack_require__.m = modules;
-/******/
-/******/ 	// expose the module cache
-/******/ 	__webpack_require__.c = installedModules;
-/******/
-/******/ 	// define getter function for harmony exports
-/******/ 	__webpack_require__.d = function(exports, name, getter) {
-/******/ 		if(!__webpack_require__.o(exports, name)) {
-/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
-/******/ 		}
-/******/ 	};
-/******/
-/******/ 	// define __esModule on exports
-/******/ 	__webpack_require__.r = function(exports) {
-/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
-/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
-/******/ 		}
-/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
-/******/ 	};
-/******/
-/******/ 	// create a fake namespace object
-/******/ 	// mode & 1: value is a module id, require it
-/******/ 	// mode & 2: merge all properties of value into the ns
-/******/ 	// mode & 4: return value when already ns object
-/******/ 	// mode & 8|1: behave like require
-/******/ 	__webpack_require__.t = function(value, mode) {
-/******/ 		if(mode & 1) value = __webpack_require__(value);
-/******/ 		if(mode & 8) return value;
-/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
-/******/ 		var ns = Object.create(null);
-/******/ 		__webpack_require__.r(ns);
-/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
-/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
-/******/ 		return ns;
-/******/ 	};
-/******/
-/******/ 	// getDefaultExport function for compatibility with non-harmony modules
-/******/ 	__webpack_require__.n = function(module) {
-/******/ 		var getter = module && module.__esModule ?
-/******/ 			function getDefault() { return module['default']; } :
-/******/ 			function getModuleExports() { return module; };
-/******/ 		__webpack_require__.d(getter, 'a', getter);
-/******/ 		return getter;
-/******/ 	};
-/******/
-/******/ 	// Object.prototype.hasOwnProperty.call
-/******/ 	__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
-/******/
-/******/ 	// __webpack_public_path__
-/******/ 	__webpack_require__.p = "";
-/******/
-/******/
-/******/ 	// Load entry module and return exports
-/******/ 	return __webpack_require__(__webpack_require__.s = 1);
-/******/ })
-/************************************************************************/
-/******/ ([
-/* 0 */
-/***/ (function(module, exports) {
-
-module.exports = __WEBPACK_EXTERNAL_MODULE__0__;
-
-/***/ }),
-/* 1 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(0);
-/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(katex__WEBPACK_IMPORTED_MODULE_0__);
-
-
-var scripts = document.body.getElementsByTagName("script");
-scripts = Array.prototype.slice.call(scripts);
-scripts.forEach(function (script) {
-    if (!script.type || !script.type.match(/math\/tex/i)) {
-        return -1;
-    }
-    var display = script.type.match(/mode\s*=\s*display(;|\s|\n|$)/) != null;
-
-    var katexElement = document.createElement(display ? "div" : "span");
-    katexElement.setAttribute("class", display ? "equation" : "inline-equation");
-    try {
-        katex__WEBPACK_IMPORTED_MODULE_0___default.a.render(script.text, katexElement, { displayMode: display });
-    } catch (err) {
-        //console.error(err); linter doesn't like this
-        katexElement.textContent = script.text;
-    }
-    script.parentNode.replaceChild(katexElement, script);
-});
-
-/***/ })
-/******/ ])["default"];
-});

+ 0 - 1
views/main_css/katex/contrib/mathtex-script-type.min.js

@@ -1 +0,0 @@
-!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("katex"));else if("function"==typeof define&&define.amd)define(["katex"],t);else{var r="object"==typeof exports?t(require("katex")):t(e.katex);for(var n in r)("object"==typeof exports?exports:e)[n]=r[n]}}("undefined"!=typeof self?self:this,function(e){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=1)}([function(t,r){t.exports=e},function(e,t,r){"use strict";r.r(t);var n=r(0),o=r.n(n),u=document.body.getElementsByTagName("script");(u=Array.prototype.slice.call(u)).forEach(function(e){if(!e.type||!e.type.match(/math\/tex/i))return-1;var t=null!=e.type.match(/mode\s*=\s*display(;|\s|\n|$)/),r=document.createElement(t?"div":"span");r.setAttribute("class",t?"equation":"inline-equation");try{o.a.render(e.text,r,{displayMode:t})}catch(t){r.textContent=e.text}e.parentNode.replaceChild(r,e)})}]).default});

BIN
views/main_css/katex/fonts/KaTeX_AMS-Regular.ttf


BIN
views/main_css/katex/fonts/KaTeX_AMS-Regular.woff


BIN
views/main_css/katex/fonts/KaTeX_AMS-Regular.woff2


BIN
views/main_css/katex/fonts/KaTeX_Caligraphic-Bold.ttf


BIN
views/main_css/katex/fonts/KaTeX_Caligraphic-Bold.woff


BIN
views/main_css/katex/fonts/KaTeX_Caligraphic-Bold.woff2


BIN
views/main_css/katex/fonts/KaTeX_Caligraphic-Regular.ttf


BIN
views/main_css/katex/fonts/KaTeX_Caligraphic-Regular.woff


BIN
views/main_css/katex/fonts/KaTeX_Caligraphic-Regular.woff2


BIN
views/main_css/katex/fonts/KaTeX_Fraktur-Bold.ttf


BIN
views/main_css/katex/fonts/KaTeX_Fraktur-Bold.woff


BIN
views/main_css/katex/fonts/KaTeX_Fraktur-Bold.woff2


BIN
views/main_css/katex/fonts/KaTeX_Fraktur-Regular.ttf


BIN
views/main_css/katex/fonts/KaTeX_Fraktur-Regular.woff


BIN
views/main_css/katex/fonts/KaTeX_Fraktur-Regular.woff2


BIN
views/main_css/katex/fonts/KaTeX_Main-Bold.ttf


BIN
views/main_css/katex/fonts/KaTeX_Main-Bold.woff


BIN
views/main_css/katex/fonts/KaTeX_Main-Bold.woff2


BIN
views/main_css/katex/fonts/KaTeX_Main-BoldItalic.ttf


BIN
views/main_css/katex/fonts/KaTeX_Main-BoldItalic.woff


BIN
views/main_css/katex/fonts/KaTeX_Main-BoldItalic.woff2


BIN
views/main_css/katex/fonts/KaTeX_Main-Italic.ttf


BIN
views/main_css/katex/fonts/KaTeX_Main-Italic.woff


BIN
views/main_css/katex/fonts/KaTeX_Main-Italic.woff2


BIN
views/main_css/katex/fonts/KaTeX_Main-Regular.ttf


BIN
views/main_css/katex/fonts/KaTeX_Main-Regular.woff


BIN
views/main_css/katex/fonts/KaTeX_Main-Regular.woff2


BIN
views/main_css/katex/fonts/KaTeX_Math-BoldItalic.ttf


BIN
views/main_css/katex/fonts/KaTeX_Math-BoldItalic.woff


BIN
views/main_css/katex/fonts/KaTeX_Math-BoldItalic.woff2


BIN
views/main_css/katex/fonts/KaTeX_Math-Italic.ttf


BIN
views/main_css/katex/fonts/KaTeX_Math-Italic.woff


BIN
views/main_css/katex/fonts/KaTeX_Math-Italic.woff2


BIN
views/main_css/katex/fonts/KaTeX_SansSerif-Bold.ttf


BIN
views/main_css/katex/fonts/KaTeX_SansSerif-Bold.woff


BIN
views/main_css/katex/fonts/KaTeX_SansSerif-Bold.woff2


BIN
views/main_css/katex/fonts/KaTeX_SansSerif-Italic.ttf


BIN
views/main_css/katex/fonts/KaTeX_SansSerif-Italic.woff


BIN
views/main_css/katex/fonts/KaTeX_SansSerif-Italic.woff2


BIN
views/main_css/katex/fonts/KaTeX_SansSerif-Regular.ttf


BIN
views/main_css/katex/fonts/KaTeX_SansSerif-Regular.woff


BIN
views/main_css/katex/fonts/KaTeX_SansSerif-Regular.woff2


BIN
views/main_css/katex/fonts/KaTeX_Script-Regular.ttf


BIN
views/main_css/katex/fonts/KaTeX_Script-Regular.woff


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio