From 62f53c083193985d7e576cb6af8a231e5dd7a952 Mon Sep 17 00:00:00 2001 From: wangweimin Date: Mon, 25 Jan 2021 11:44:44 +0800 Subject: [PATCH 001/445] doc: add note to `put_file()` doc --- docs/FAQ.rst | 4 ++++ pywebio/output.py | 6 ++++++ pywebio/session/__init__.py | 9 ++++++++- 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/FAQ.rst b/docs/FAQ.rst index b9f8b8ee..6f7143d6 100644 --- a/docs/FAQ.rst +++ b/docs/FAQ.rst @@ -19,3 +19,7 @@ PyWebIO 的设计就是输入表单在成功提交后就销毁,因为 PyWebIO ---------------------------------------------------------- 一般情况下,在Server模式下,任务函数一旦返回(或在Script模式下,脚本运行结束),会话就结束了,此时事件回调也将不起作用,可以在任务函数(或脚本)末尾处使用 `pywebio.session.hold()` 函数来将会话保持,这样在用户关闭浏览器页面前,事件回调将一直可用。 参见 :ref:`Server模式与Script模式 ` + +为什么 ``put_file()`` 无法下载文件 +---------------------------------------------------------- +原因同上。 ``put_file()`` 的文件链接被点击后,也是需要和服务端通信获取文件数据的,所以会话关闭后下载链接会不可用。可以在任务函数末尾处使用 `pywebio.session.hold()` 函数来将会话保持。 \ No newline at end of file diff --git a/pywebio/output.py b/pywebio/output.py index 3a975bb5..3a9b5e60 100644 --- a/pywebio/output.py +++ b/pywebio/output.py @@ -668,6 +668,12 @@ def put_file(name, content, label=None, scope=Scope.Current, position=OutputPosi :param content: 文件内容. 类型为 bytes-like object :param str label: 下载链接的显示文本,默认和文件名相同 :param int scope, position: 与 `put_text` 函数的同名参数含义一致 + + .. attention:: + + 在PyWebIO会话(关于会话的概念见 :ref:`Server与script模式 ` )结束后,使用 ``put_file()`` + 输出的文件也将无法下载,可以在任务函数末尾处使用 `pywebio.session.hold()` 函数来将会话保持,这样在用户关闭浏览器页面前, + 文件下载将一直可用。 """ if label is None: label = name diff --git a/pywebio/session/__init__.py b/pywebio/session/__init__.py index 41f03ff7..dffdd0a9 100644 --- a/pywebio/session/__init__.py +++ b/pywebio/session/__init__.py @@ -132,7 +132,14 @@ def next_client_event(): @chose_impl def hold(): - """保持会话,直到用户关闭浏览器 + """保持会话,直到用户关闭浏览器。 + + .. note:: + + 在PyWebIO会话结束后,页面和服务端的连接便会断开, + 页面上需要和服务端通信才可实现的功能(比如:下载通过 `put_file() ` 输出的文件, + `put_buttons() ` 按钮回调)便无法使用。 + 可以在任务函数末尾处调用 ``hold()`` 函数来将会话保持,这样在用户关闭浏览器页面前,会话将一直保持连接。 注意⚠️:在 :ref:`基于协程 ` 的会话上下文中,需要使用 ``await hold()`` 语法来进行调用。 """ From e42dfab4cc43ad023b5be21a6d2eb5400d749f5c Mon Sep 17 00:00:00 2001 From: wangweimin Date: Wed, 27 Jan 2021 14:15:28 +0800 Subject: [PATCH 002/445] fix: copy to clipboard in doc demo missing line break and add `hold()` to clipboard when necessary --- demos/doc_demo.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/demos/doc_demo.py b/demos/doc_demo.py index 9ddf9e73..f5b1f38e 100644 --- a/demos/doc_demo.py +++ b/demos/doc_demo.py @@ -37,6 +37,9 @@ def run_code(code, scope, locals): def copytoclipboard(code): + code = IMPORT_CODE + code + if 'put_buttons(' in code or 'put_file(' in code: + code += '\n\nhold() # keep session alive' run_js("writeText(text)", text=code) toast('已复制') @@ -44,7 +47,7 @@ def copytoclipboard(code): def handle_code(code, title): run_js(""" window.writeText = function(text) { - const input = document.createElement('INPUT'); + const input = document.createElement('textarea'); input.style.opacity = 0; input.style.position = 'absolute'; input.style.left = '-100000px'; @@ -68,7 +71,7 @@ def handle_code(code, title): put_buttons(['运行', '复制代码'], onclick=[ partial(run_code, code=p, scope=scope, locals=locals), - partial(copytoclipboard, code=IMPORT_CODE + p) + partial(copytoclipboard, code=p) ]) put_markdown('----') From 12420e677bb123d4a156d06eb36b6b3ebd00b6c7 Mon Sep 17 00:00:00 2001 From: wangweimin Date: Thu, 28 Jan 2021 18:52:57 +0800 Subject: [PATCH 003/445] fix: missing toastify css and js file in `package_data` --- setup.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index 5ffeb30d..94ddac61 100644 --- a/setup.py +++ b/setup.py @@ -46,19 +46,18 @@ "html/codemirror/python.js", "html/css/bootstrap.min.css", "html/css/mditor.min.css", - "html/css/jquery.toast.min.css", + "html/css/toastify.min.css", "html/css/app.css", "html/css/codemirror.min.css", "html/js/FileSaver.min.js", "html/js/mditor.min.js", - "html/js/codemirror.js", "html/js/pywebio.min.js", "html/js/mustache.min.js", "html/js/jquery.min.js", "html/js/bootstrap.min.js", "html/js/bs-custom-file-input.min.js", "html/js/popper.min.js", - "html/js/jquery.toast.min.js", + "html/js/toastify.min.js", "html/js/require.min.js", "html/js/codemirror.min.js", "html/image/favicon_open_16.png", From 28770ff81f61895710b35adeb12adf856a368752 Mon Sep 17 00:00:00 2001 From: wangweimin Date: Thu, 28 Jan 2021 18:56:05 +0800 Subject: [PATCH 004/445] doc: fix typo --- docs/guide.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/guide.rst b/docs/guide.rst index 38711a5a..24830201 100644 --- a/docs/guide.rst +++ b/docs/guide.rst @@ -692,7 +692,7 @@ Server模式下多线程的使用示例:: .. tab:: Tornado 需要在Tornado应用中引入两个 ``RequestHandler`` , - 一个 ``RequestHandler`` 用来提供静态的前端文件,另一个 ``RequestHandler`` 用来和浏览器进行WebSocket通讯:: + 一个 ``RequestHandler`` 用来提供前端静态文件,另一个 ``RequestHandler`` 用来和浏览器进行WebSocket通讯:: import tornado.ioloop import tornado.web @@ -724,7 +724,7 @@ Server模式下多线程的使用示例:: .. tab:: Flask - 需要添加两个PyWebIO相关的路由:一个用来提供静态的前端文件,另一个用来和浏览器进行Http通讯:: + 需要添加两个PyWebIO相关的路由:一个用来提供前端静态文件,另一个用来和浏览器进行Http通讯:: from pywebio.platform.flask import webio_view from pywebio import STATIC_PATH @@ -775,17 +775,17 @@ Server模式下多线程的使用示例:: .. tab:: aiohttp - 添加两个PyWebIO相关的路由:一个用来提供静态的前端文件,另一个用来和浏览器进行WebSocket通讯:: + 添加两个PyWebIO相关的路由:一个用来提供前端静态文件,另一个用来和浏览器进行WebSocket通讯:: from aiohttp import web from pywebio.platform.aiohttp import static_routes, webio_handler app = web.Application() # task_func 为使用PyWebIO编写的任务函数 - app.add_routes([web.get('/io', webio_handler(task_func))]) # http通信接口 + app.add_routes([web.get('/io', webio_handler(task_func))]) # websocket通信接口 app.add_routes(static_routes('/')) # 前端静态文件托管 - web.run_app(app, host='localhost', port=8080) + web.run_app(app, host='localhost', port=80) 启动aiohttp应用后,访问 ``http://localhost/`` 即可打开PyWebIO应用 @@ -973,7 +973,7 @@ PyWebIO的会话实现默认是基于线程的,用户每打开一个和服务 # 事件循环线程 threading.Thread(target=run_event_loop, daemon=True).start() - app.run(host='localhost', port='80') + app.run(host='localhost', port=80) 最后,使用PyWebIO编写的协程函数不支持Script模式,总是需要使用 ``start_server`` 来启动一个服务或者集成进Web框架来调用。 From 77c02aece34e8c29cafb90d59b813448032620ac Mon Sep 17 00:00:00 2001 From: wangweimin Date: Thu, 28 Jan 2021 19:07:13 +0800 Subject: [PATCH 005/445] workflow: make test workflow more strict --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 78ae873b..efc97659 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,7 +23,7 @@ jobs: - name: Install Test JS deps run: npm install -D @percy/agent - name: Install package - run: pip3 install -e ".[all]" + run: pip3 install ".[all]" - name: Install dev dependencies run: | python -m pip install --upgrade pip From f4f28c2754d0a8e126351c75890d171fd9626c0c Mon Sep 17 00:00:00 2001 From: wangweimin Date: Thu, 28 Jan 2021 19:26:14 +0800 Subject: [PATCH 006/445] release v1.0.3 - fix toastify css and js file missing --- pywebio/__version__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pywebio/__version__.py b/pywebio/__version__.py index 8248f4a3..22d1a4d6 100644 --- a/pywebio/__version__.py +++ b/pywebio/__version__.py @@ -1,8 +1,8 @@ __package__ = 'pywebio' __description__ = 'Write interactive web app in script way.' __url__ = 'https://pywebio.readthedocs.io' -__version__ = "1.0.2" -__version_info__ = (1, 0, 2, 0) +__version__ = "1.0.3" +__version_info__ = (1, 0, 3, 0) __author__ = 'WangWeimin' __author_email__ = 'wang0.618@qq.com' __license__ = 'MIT' \ No newline at end of file From 68239b6fd00d96de7fc2046c71a066e0b9531d23 Mon Sep 17 00:00:00 2001 From: wangweimin Date: Sun, 31 Jan 2021 21:21:20 +0800 Subject: [PATCH 007/445] fix: missing escape in `put_code()` --- pywebio/output.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pywebio/output.py b/pywebio/output.py index 3a9b5e60..e529e3c2 100644 --- a/pywebio/output.py +++ b/pywebio/output.py @@ -337,7 +337,15 @@ def put_code(content, language='', scope=Scope.Current, position=OutputPosition. :param str language: 代码语言 :param int scope, position: 与 `put_text` 函数的同名参数含义一致 """ - code = "```%s\n%s\n```" % (language, content) + if not isinstance(content, str): + content = str(content) + + # For fenced code blocks, escaping the backtick need to use more backticks + backticks = '```' + while backticks in content: + backticks += '`' + + code = "%s%s\n%s\n%s" % (backticks, language, content, backticks) return put_markdown(code, scope=scope, position=position) From a08c47684a84caf117538ff196c1db337f4af9dd Mon Sep 17 00:00:00 2001 From: wangweimin Date: Sun, 31 Jan 2021 22:43:58 +0800 Subject: [PATCH 008/445] remove `disable_asyncio` parameter in `start_server` of django and flask when enable `disable_asyncio`, the coroutine-based session raise error --- pywebio/platform/django.py | 10 +--------- pywebio/platform/flask.py | 9 +-------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/pywebio/platform/django.py b/pywebio/platform/django.py index 19d24f39..37b35f76 100644 --- a/pywebio/platform/django.py +++ b/pywebio/platform/django.py @@ -108,7 +108,6 @@ def view_func(request): def start_server(applications, port=8080, host='localhost', allowed_origins=None, check_origin=None, - disable_asyncio=False, session_cleanup_interval=None, session_expire_seconds=None, debug=False, **django_options): @@ -129,12 +128,6 @@ def start_server(applications, port=8080, host='localhost', 比如 ``https://*.example.com`` 、 ``*://*.example.com`` :param callable check_origin: 请求来源检查函数。接收请求来源(包含协议、域名和端口部分)字符串, 返回 ``True/False`` 。若设置了 ``check_origin`` , ``allowed_origins`` 参数将被忽略 - :param bool disable_asyncio: 禁用 asyncio 函数。仅在任务函数为协程函数时有效。 - - .. note:: 实现说明: - 当使用Django backend时,若要在PyWebIO的会话中使用 ``asyncio`` 标准库里的协程函数,PyWebIO需要单独开启一个线程来运行 ``asyncio`` 事件循环, - 若程序中没有使用到 ``asyncio`` 中的异步函数,可以开启此选项来避免不必要的资源浪费 - :param int session_expire_seconds: 会话过期时间。若 session_expire_seconds 秒内没有收到客户端的请求,则认为会话过期。 :param int session_cleanup_interval: 会话清理间隔。 :param bool debug: 开启 Django debug mode 和一般访问日志的记录 @@ -148,7 +141,6 @@ def start_server(applications, port=8080, host='localhost', from django.urls import path from django.utils.crypto import get_random_string from django.views.static import serve - from django.core.management import call_command if port == 0: port = get_free_port() @@ -203,7 +195,7 @@ def start_server(applications, port=8080, host='localhost', has_coro_target = any(iscoroutinefunction(target) or isgeneratorfunction(target) for target in make_applications(applications).values()) - if not disable_asyncio and has_coro_target: + if has_coro_target: threading.Thread(target=run_event_loop, daemon=True).start() # call_command('runserver', '%s:%d' % (host, port)) diff --git a/pywebio/platform/flask.py b/pywebio/platform/flask.py index 5d19a45e..012ac99a 100644 --- a/pywebio/platform/flask.py +++ b/pywebio/platform/flask.py @@ -109,7 +109,6 @@ def view_func(): def start_server(applications, port=8080, host='localhost', allowed_origins=None, check_origin=None, - disable_asyncio=False, session_cleanup_interval=None, session_expire_seconds=None, debug=False, **flask_options): @@ -130,12 +129,6 @@ def start_server(applications, port=8080, host='localhost', 比如 ``https://*.example.com`` 、 ``*://*.example.com`` :param callable check_origin: 请求来源检查函数。接收请求来源(包含协议、域名和端口部分)字符串, 返回 ``True/False`` 。若设置了 ``check_origin`` , ``allowed_origins`` 参数将被忽略 - :param bool disable_asyncio: 禁用 asyncio 函数。仅在任务函数为协程函数时有效。 - - .. note:: 实现说明: - 当使用Flask backend时,若要在PyWebIO的会话中使用 ``asyncio`` 标准库里的协程函数,PyWebIO需要单独开启一个线程来运行 ``asyncio`` 事件循环, - 若程序中没有使用到 ``asyncio`` 中的异步函数,可以开启此选项来避免不必要的资源浪费 - :param int session_expire_seconds: 会话过期时间。若 session_expire_seconds 秒内没有收到客户端的请求,则认为会话过期。 :param int session_cleanup_interval: 会话清理间隔。 :param bool debug: Flask debug mode @@ -164,7 +157,7 @@ def serve_static_file(static_file='index.html'): has_coro_target = any(iscoroutinefunction(target) or isgeneratorfunction(target) for target in make_applications(applications).values()) - if not disable_asyncio and has_coro_target: + if has_coro_target: threading.Thread(target=run_event_loop, daemon=True).start() if not debug: From 3c9b7e3fca4e41e5ac89323e9027507636392ba8 Mon Sep 17 00:00:00 2001 From: wangweimin Date: Mon, 1 Feb 2021 21:34:00 +0800 Subject: [PATCH 009/445] fix: `max_size` and `max_total_size` parse error in `file_upload` --- pywebio/input.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pywebio/input.py b/pywebio/input.py index 780d0066..ad048400 100644 --- a/pywebio/input.py +++ b/pywebio/input.py @@ -486,9 +486,10 @@ def _parse_file_size(size): return int(size) assert isinstance(size, str), '`size` must be int/float/str, got %s' % type(size) + size = size.lower() for idx, i in enumerate(['k', 'm', 'g'], 1): if i in size: - s = size.lower().replace(i, '') + s = size.replace(i, '') base = 2 ** (idx * 10) return int(float(s) * base) From 7a90b906125f82fe84b7f7efb6cace4e3af67992 Mon Sep 17 00:00:00 2001 From: wangweimin Date: Fri, 29 Jan 2021 13:38:17 +0800 Subject: [PATCH 010/445] doc: fix mistakes and add content --- docs/arch.rst | 162 ++++++++++++++++++++++++++++- docs/assets/architecture.png | Bin 0 -> 62433 bytes docs/guide.rst | 20 +++- docs/misc.rst | 5 +- docs/spec.rst | 10 +- pywebio/input.py | 50 ++++----- pywebio/output.py | 163 +++++++++++++++++++++--------- pywebio/platform/aiohttp.py | 4 +- pywebio/platform/django.py | 4 +- pywebio/platform/flask.py | 6 +- pywebio/platform/tornado.py | 16 +-- pywebio/session/__init__.py | 97 ++++++++++++++++-- pywebio/session/coroutinebased.py | 5 +- 13 files changed, 432 insertions(+), 110 deletions(-) create mode 100644 docs/assets/architecture.png diff --git a/docs/arch.rst b/docs/arch.rst index e4697766..81794437 100644 --- a/docs/arch.rst +++ b/docs/arch.rst @@ -4,5 +4,165 @@ Architecture 概念 ------------ -`Session` 表示浏览器与程序交互产生的一次会话。PyWebIO在会话中运行 ``Task`` ,任务是 +``Session`` 表示浏览器与程序交互产生的一次会话。PyWebIO在会话中运行 ``Task`` ,任务是 + +会话中除了起始的执行单元,也可以并发启动新的执行单元,在新的执行单元中也可以进行输入输出。 + +在用户端,相同会话中的不同的执行单元的输入是独立的,共享输出空间,但输出域的栈结构各自独立。 + +若用户正在填写一个执行单元的表单,会话中的其他执行单元也开始向用户请求输入,此时用户正在填写的表单将会隐藏, +新的输入表单将会显示给用户,当用户填写完新表单并提交后,旧表单重新显示,之前在旧表单上的输入也会保留。 + +在基于线程的会话中,会话中的每个执行单元都是一个线程 + +在基于协程的会话中,会话中的每个执行单元都是一个协程 + +除了并发执行的执行单元,会话中还有事件回调函数,目前就只有按钮控件可以绑定点击事件的回调函数。 + +架构 +------------ + +会话内的每个执行单元使用唯一的task_id进行标识,由于会话内的输入需要区分执行单元,所以每个表单提交时, +除了表单的内容以外,还会携带表单所在的执行单元的task_id,这样,后台会话才可以知道该将表单数据传递给哪个执行单元。 + + +.. image:: /assets/architecture.png + +PyWebIO会话是由事件驱动的,这些事件来自用户在页面上的操作,比如提交表单,点击按钮,这些事件会通过http请求或websocket连接发送到后端框架。 + +后端框架维护有当前在线的Session实例,后端框架在收到用户提交的事件后,回调用相关Session实例的 ``send_client_event()`` 方法将事件发送至会话; + +一个会话内会拥有至少一个执行单元,执行单元在调用PyWebIO的输入函数后会临时挂起,当会话收到用户的输入提交后,会话便将执行单元恢复执行,并提供用户输入的值。 +执行单元内,任何输入输出的调用都会转换成一些命令序列发送给会话. + +当后端框架通过HTTP与用户浏览器通信时,用户浏览器是以轮训的方式获取指令,会话会保存由执行单元生成的、还未发送到浏览器的命令序列,等待下次轮训时由后端框架取走。 + +当后端框架通过WebSocket与用户建立连接时,任何由执行单元发送到会话的命令都会立即发送到后端,并由后端通过WebSocket连接通知用户浏览器。 + +实现 +------------ + +后端与Session的交互 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +后端框架负责从Session会话中获取来自PyWebIO的指令,并发送给用户浏览器;同时后端框架接收用户提交的数据,并发送给相应的会话实例。 + +Session暴露给后端框架的方法仅有 `Session.send_client_event ` 、 `Session.get_task_commands ` 和 `Session.close ` 。 + + +基于HTTP通信的后端的实现逻辑 +""""""""""""""""""""""""""""""""" + +**基于HTTP的前后端通信约定** + +前端按照固定间隔使用GET请求轮训后端接口,在请求中使用 ``webio-session-id`` HTTP头来传递会话ID。 + +会话一开始时,会话ID由后端生成并通过响应中的 ``webio-session-id`` HTTP头返回给前端,后续前端的请求都会在请求头中使用 ``webio-session-id`` 字段传递会话ID。 + +前端产生的事件使用POST请求发送给后端。对于前端的每次轮训和事件提交请求,后端都会返回当前未执行的指令序列作为响应,前端收到响应后会依次执行指令。 + +**代码实现** + +以Flask后端为例,Flask后端与Session的交互都在Flask视图函数中实现,视图函数通过调用 `pywebio.platform.flask.webio_view <./_modules/pywebio/platform/flask.html#webio_view>`_ 获取, +在 `webio_view` 中,先是实例化了一个 `pywebio.platform.httpbased.HttpHandler` ,然后声明了一个内部函数,这个内部函数就是Flask视图函数, +在视图函数内,先是实例化了一个 `pywebio.platform.flask.FlaskHttpContext` 对象,然后通过调用 ``HttpHandler.handle_request(FlaskHttpContext)`` 就获得了视图的响应。 + +这其中,FlaskHttpContext 的基类为 HttpContext ,HttpContext 接口各异的后端框架定义了一个统一的操作接口,用于从当前请求中获取请求相关的数据并设置请求的相应。 FlaskHttpContext 为HttpContext接口的Flask实现。 + +而 HttpHandle 负责维护Session实例并实现HTTP请求与Session之间的交互,HttpHandle 与后端框架相关的交互全都通过 HttpContext 操作。 + +HttpContext的生命周期为一次HTTP请求,HttpHandle的生命周期和整个后端框架的生命周期一致。 + +HttpHandler.handle_request 负责处理前端发送给后端的每一次请求,HttpHandler.handle_request 的处理流程如下: + +1. 检测当前HTTP请求是否满足跨域设置 +2. 根绝当前请求的 webio-session-id 头信息找到相应的Session实例,若不存在 webio-session-id 头则创建新会话并分配webio-session-id +3. 若当前请求为POST事件提交请求,则将提交的数据通过 Session.send_client_event 发送给Session +4. 通过调用 Session.get_task_commands 获取待执行的指令序列,并通过 HttpContext 向后端设置响应数据 + +此外,基于HTTP的会话,用户主动关闭会话时(比如关闭浏览器),后端无法立即感知,所以在HttpHandler.handle_request 中, +还会周期性地检测会话的最后活跃时间,将一段时间内不活跃的会话视为过期,所以在HttpHandler清理过期会话并调用 Session.close 释放会话内的资源。 + + +基于WebSocket通信的后端的实现逻辑 +"""""""""""""""""""""""""""""""""""" +**基于WebSocket的前后端通信约定:** + +浏览器与后端使用一个WebSocket连接来保持一个会话,后端的指令通过JSON序列化之后的消息实时发送给前端,前端用户触发的事件数据也通过JSON序列化之后发送给后端。 + +**代码实现** + +以Tornado后端为例 + +webio_handler用于获取Tornado与前端进行通信的WebSocketHandler子类,其逻辑实现在 _webio_handler 中,由于WebSocket的有状态性, +WebSocketHandler子类的实现比基于HTTP通信的HttpHandler要简单许多,关键部分如下: + +* 在WebSocket连接创建的时候初始化Session实例,并向Session对象注册了 on_task_command和on_session_close 回调,分别在新指令产生时和会话由执行单元关闭时由Session调用, + 用于实现WebSocketHandler向前端实时发送指令 +* 在收到前端浏览器发送来的消息后,WebSocketHandler将收到的数据通过 Session.send_client_event 发送给Session +* 在WebSocket连接关闭时,调用 Session.close 释放会话内的资源。 + +session与执行单元(输入/输出)的交互 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +会话提供给执行单元的关键接口有: + +* get_current_session : 静态方法,获取当前执行单元所属的会话实例 +* get_current_task_id : 静态方法,获取当前执行单元所属的id +* send_task_command : 向会话发送指令 +* next_client_event : 读取来自浏览器的属于当前执行单元的下一个事件 +* register_callback : 向会话注册一个回调 + +同时,会话根据实现方式不同,还分别提供了 register_thread 和 run_async 用于启动新的执行单元。 + + +**回调机制** + +在会话中,为了能够响应用户在界面上的某些事件(比如点击了输出内容中的某个按钮),于是设计了回调机制,可以在执行单元中使用register_callback向当前会话注册回调,然后执行单元会得到一个回调ID, +执行单元再通过相关指令让浏览器输出一些可以触发的控件,并向控件绑定回调ID,当用户触发控件后,前端将带有回调ID的 :ref:`回调事件 ` 发回会话,会话会在专门的执行单元中或启动新执行单元中运行回调。 + +基于线程的会话实现 +"""""""""""""""""""""""""""""""""""" + +在基于线程的会话中,每个执行单元都是一个线程,每个执行单元通过一条消息队列从会话接收来自用户的事件消息,当执行单元所需要的事件用户还没有提交时,执行单元便会挂起。 + +基于线程的会话使用线程ID作为执行单元的ID,在全局使用一个以线程id为key的字典来映射执行单元所属的会话实例,会话内不同执行单元的用户事件消息队列也通过执行单元ID进行索引。 + +使用 register_thread 启动新的执行单元时,也需要为新执行单元注册用户事件消息队列。 + +基于协程的会话实现 +"""""""""""""""""""""""""""""""""""" +在基于协程的会话中,每个执行单元都是一个由协程包装成的任务对象(Task),当会话接收来自用户的事件消息后,便激活相应的任务对象,使得协程恢复运行。 + +由于基于协程的会话是单线程的,所以会话在激活任务对象前是通过将上下文信息保存在全局变量中来实现 get_current_session 和 get_current_task_id 方法,全局的上下文信息包含当前将要执行的会话的实例和执行单元的ID。 + + +Script mode的实现 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Script mode 也是基于线程的,但由于全局仅存在一个会话,所有执行单元必定全部属于这个会话,所以也无需主动调用register_thread(thread)注册线程。 + +当PyWebIO检测到用户代码在后端Server还未启动的情况下就调用了PyWebIO交互函数时,便会启动Script mode: + +1. 在新线程中启动后端Server +2. 启动浏览器打开后端Server运行的地址 +3. 在第一次与用户建立连接时初始化会话 + +script mode的会话类继承了基于线程的会话类,并修改了部分方法: + +* 构造函数 : 仅允许script mode会话类被初始化一次 +* get_current_session : 直接返回全局的会话对象 +* get_current_task_id : 除了返回当前线程id,还会自动将当前线程使用 register_thread 注册到会话中 + +相关对象的文档 +------------------------ + +.. autoclass:: pywebio.platform.httpbased.HttpHandler + :members: + +.. autoclass:: pywebio.platform.flask.FlaskHttpContext + :members: + +.. autoclass:: pywebio.session.base.Session + :members: + diff --git a/docs/assets/architecture.png b/docs/assets/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..b9faee43e34eb50845d97eb66c98ce570ad6f1ed GIT binary patch literal 62433 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 To^%dV4qg`KRtF0A9Siv{edE}@ literal 0 HcmV?d00001 diff --git a/docs/guide.rst b/docs/guide.rst index 24830201..952797a9 100644 --- a/docs/guide.rst +++ b/docs/guide.rst @@ -602,7 +602,23 @@ Server模式与Script模式 在Server模式下,PyWebIO会启动一个Web服务来持续性地提供服务。需要提供一个任务函数(类似于Web开发中的视图函数),当用户访问服务地址时,PyWebIO会开启一个新会话并运行任务函数。 使用 `start_server() ` 来启动PyWebIO的Server模式, `start_server() ` 除了接收一个函数作为任务函数外, -还支持传入函数列表或字典,从而使一个PyWebIO Server下可以有多个不同功能的服务,服务之间可以通过 `go_app() ` 进行跳转,详细内容见函数文档。 +还支持传入函数列表或字典,从而使一个PyWebIO Server下可以有多个不同功能的服务,服务之间可以通过 `go_app() ` 或 `put_link() ` 进行跳转:: + + def task_1(): + put_text('task_1') + put_buttons(['Go task 2'], [lambda: go_app('task_2')]) + hold() + + def task_2(): + put_text('task_2') + put_buttons(['Go task 1'], [lambda: go_app('task_1')]) + hold() + + def index(): + put_link('Go task 1', app='task_1') # 使用app参数指定任务名 + put_link('Go task 2', app='task_2') + + start_server([index, task_1, task_2]) # 或 start_server({'index': index, 'task_1': task_1, 'task_2': task_2}) .. attention:: @@ -900,6 +916,8 @@ PyWebIO的会话实现默认是基于线程的,用户每打开一个和服务 await asyncio.gather(asyncio.sleep(1), pywebio.session.eval_js('1+1')) task = asyncio.create_task(pywebio.input()) +.. _coroutine_based_concurrency: + 协程会话的并发 ^^^^^^^^^^^^^^^^ diff --git a/docs/misc.rst b/docs/misc.rst index 79d139ae..ccfcfa2f 100644 --- a/docs/misc.rst +++ b/docs/misc.rst @@ -13,6 +13,7 @@ * ``tabSize`` (int): 制表符宽度 * ``lineWrapping`` (bool): 是否换行以显示长行 +完整的Codemirror选项请见 https://codemirror.net/doc/manual.html#config .. _nginx_ws_config: @@ -44,10 +45,6 @@ Nginx WebSocket配置示例 以上配置文件将PyWebIO的静态文件托管到 ``/tool/`` 目录下, 并将 ``/tool/io`` 反向代理到 ``localhost:5000`` -.. note:: - 使用以上配置文件后,您还需要在 ``webio_handler`` 或 ``start_server`` 函数中将nginx绑定的域名添加到 ``allowed_origins`` 参数指定的列表中 - - PyWebIO的静态文件的路径可使用命令 ``python3 -c "import pywebio; print(pywebio.STATIC_PATH)"`` 获得,你也可以将静态文件复制到其他目录下:: cp -r `python3 -c "import pywebio; print(pywebio.STATIC_PATH)"` ~/web diff --git a/docs/spec.rst b/docs/spec.rst index b731d477..8597ef72 100644 --- a/docs/spec.rst +++ b/docs/spec.rst @@ -13,7 +13,7 @@ PyWebIO采用服务器-客户端架构,服务端运行任务代码,通过网 **Http 通信:** -* 客户端通过Http GET请求向后端轮训,后端返回json序列化之后的PyWebIO消息列表 +* 客户端通过Http GET请求向后端轮询,后端返回json序列化之后的PyWebIO消息列表 * 当用户提交表单或者点击页面按钮后,客户端通过Http POST请求向后端提交数据 @@ -135,8 +135,7 @@ input_group * actions - * buttons: 选项列表。``{label:选项标签, value:选项值, [type: 按钮类型 'submit'/'reset'/'cancel'/'callback'], [disabled:是否禁止选择]}`` . - 当 type 为 'callback' 时,value 字段表示回调函数的callback_id + * buttons: 选项列表。``{label:选项标签, value:选项值, [type: 按钮类型 'submit'/'reset'/'cancel'], [disabled:是否禁止选择]}`` . * file: @@ -160,8 +159,7 @@ update_input * placeholder: * invalid_feedback * valid_feedback - * action_result 仅在 actions 输入项中可用,表示设置输入项显示的文本 - * 输入项其他spec字段 // 不支持更新 on_focus on_blur inline label 字段 + * 输入项其他spec字段 // 不支持更新 inline 和 label 字段 close_session @@ -223,7 +221,7 @@ popup 命令 spec 字段: * title: 弹窗标题 -* content: 数组,元素为字符串/对象,字符串表示html +* content: 数组,元素为字符串/对象 * size: 弹窗窗口大小,可选值: ``large`` 、 ``normal`` 、 ``small`` * implicit_close: 是否可以通过点击弹窗外的内容或按下 `Esc` 键来关闭弹窗 * closable: 是否可由用户关闭弹窗. 默认情况下,用户可以通过点击弹窗右上角的关闭按钮来关闭弹窗, diff --git a/pywebio/input.py b/pywebio/input.py index ad048400..b0b89bba 100644 --- a/pywebio/input.py +++ b/pywebio/input.py @@ -112,7 +112,7 @@ def input(label='', type=TEXT, *, validate=None, name=None, value=None, action=N :param str type: 输入类型. 可使用的常量:`TEXT` , `NUMBER` , `FLOAT` , `PASSWORD` , `URL` , `DATE` , `TIME` 其中 `DATE` , `TIME` 类型在某些浏览器上不被支持,详情见 https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Browser_compatibility - :param Callable validate: 输入值校验函数. 如果提供,当用户输入完毕或提交表单后校验函数将被调用. + :param callable validate: 输入值校验函数. 如果提供,当用户输入完毕或提交表单后校验函数将被调用. ``validate`` 接收输入值作为参数,当输入值有效时,返回 ``None`` ,当输入值无效时,返回错误提示字符串. 比如: .. exportable-codeblock:: @@ -126,7 +126,7 @@ def check_age(age): return 'Too young' input('Input your age', type=NUMBER, validate=check_age) - :param name: 输入框的名字. 与 `input_group` 配合使用,用于在输入组的结果中标识不同输入项. **在单个输入中,不可以设置该参数!** + :param str name: 输入框的名字. 与 `input_group` 配合使用,用于在输入组的结果中标识不同输入项. **在单个输入中,不可以设置该参数!** :param str value: 输入框的初始值 :type action: tuple(label:str, callback:callable) :param action: 在输入框右侧显示一个按钮,可通过点击按钮为输入框设置值。 @@ -229,9 +229,9 @@ def textarea(label='', *, rows=6, code=None, maxlength=None, minlength=None, val placeholder=None, required=None, readonly=None, help_text=None, **other_html_attrs): r"""文本输入域(多行文本输入) - :param int rows: 输入文本的行数(显示的高度)。输入的文本超出设定值时会显示滚动条 - :param int maxlength: 允许用户输入的最大字符长度 (Unicode) 。未指定表示无限长度 - :param int minlength: 允许用户输入的最小字符长度(Unicode) + :param int rows: 输入框的最多可显示的文本的行数,内容超出时会显示滚动条 + :param int maxlength: 最大允许用户输入的字符长度 (Unicode) 。未指定表示无限长度 + :param int minlength: 最少需要用户输入的字符长度(Unicode) :param dict code: 通过提供 `Codemirror `_ 参数让文本输入域具有代码编辑器样式: .. exportable-codeblock:: @@ -244,7 +244,7 @@ def textarea(label='', *, rows=6, code=None, maxlength=None, minlength=None, val }) put_code(res, language='python') # ..demo-only - 更多配置可以参考 https://codemirror.net/doc/manual.html#config + :ref:`这里 ` 列举了一些常用的Codemirror选项 :param - label, validate, name, value, placeholder, required, readonly, help_text, other_html_attrs: 与 `input` 输入函数的同名参数含义一致 :return: 用户输入的文本 """ @@ -289,7 +289,7 @@ def select(label='', options=None, *, multiple=None, validate=None, name=None, v help_text=None, **other_html_attrs): r"""下拉选择框。 - 默认单选,设置 ``multiple`` 参数后,可以多选。但都至少要选择一个选项。 + 默认单选,可以通过设置 ``multiple`` 参数来允许多选 :param list options: 可选项列表。列表项的可用形式有: @@ -299,7 +299,7 @@ def select(label='', options=None, *, multiple=None, validate=None, name=None, v 注意: - 1. ``options`` 中的 ``value`` 可以为任意可Json序列化对象 + 1. ``options`` 中的 ``value`` 可以为任意可JSON序列化对象 2. 若 ``multiple`` 选项不为 ``True`` 则可选项列表最多仅能有一项的 ``selected`` 为 ``True``。 :param bool multiple: 是否可以多选. 默认单选 @@ -307,9 +307,9 @@ def select(label='', options=None, *, multiple=None, validate=None, name=None, v 你也可以通过设置 ``options`` 列表项中的 ``selected`` 字段来设置默认选中选项。 最终选中项为 ``value`` 参数和 ``options`` 中设置的并集。 :type value: list or str - :param bool required: 是否至少选择一项 + :param bool required: 是否至少选择一项,仅在 ``multiple=True`` 时可用 :param - label, validate, name, help_text, other_html_attrs: 与 `input` 输入函数的同名参数含义一致 - :return: 如果 ``multiple=True`` 时,返回用户选中的 ``options`` 中的值的列表;不设置 ``multiple`` 时,返回用户选中的 ``options`` 中的值 + :return: 如果 ``multiple=True`` 时,返回用户选中的 ``options`` 中的值的列表;否则,返回用户选中的 ``options`` 中的值 """ assert options is not None, 'Required `options` parameter in select()' @@ -326,7 +326,7 @@ def checkbox(label='', options=None, *, inline=None, validate=None, name=None, v **other_html_attrs): r"""勾选选项。可以多选,也可以不选。 - :param list options: 可选项列表。格式与 `select` 函数的 ``options`` 参数含义一致 + :param list options: 可选项列表。格式与同 `select()` 函数的 ``options`` 参数 :param bool inline: 是否将选项显示在一行上。默认每个选项单独占一行 :param list value: 勾选选项初始选中项。为选项值的列表。 你也可以通过设置 ``options`` 列表项中的 ``selected`` 字段来设置默认选中选项。 @@ -349,13 +349,13 @@ def radio(label='', options=None, *, inline=None, validate=None, name=None, valu help_text=None, **other_html_attrs): r"""单选选项 - :param list options: 可选项列表。格式与 `select` 函数的 ``options`` 参数含义一致 + :param list options: 可选项列表。格式与同 `select()` 函数的 ``options`` 参数 :param bool inline: 是否将选项显示在一行上。默认每个选项单独占一行 :param str value: 单选选项初始选中项的值。 你也可以通过设置 ``options`` 列表项中的 ``selected`` 字段来设置默认选中选项。 - :param bool required: 是否至少选择一项 + :param bool required: 是否一定要选择一项(默认条件下用户可以不选择任何选项) :param - label, validate, name, help_text, other_html_attrs: 与 `input` 输入函数的同名参数含义一致 - :return: 用户选中的选项的值 + :return: 用户选中的选项的值, 如果用户没有选任何值,返回 ``None`` """ assert options is not None, 'Required `options` parameter in radio()' @@ -409,16 +409,14 @@ def actions(label='', buttons=None, name=None, help_text=None): 在表单上显示为一组按钮,用户点击按钮后依据按钮类型的不同有不同的表现。 - 当 ``actions()`` 作为 `input_group()` 的 ``inputs`` 中最后一个输入项,并且输入项中含有 ``type=submit`` 的按钮时,表单默认的提交按钮会被当前 ``actions()`` 替换 + :param list buttons: 按钮列表。列表项的可用形式有: - :param list buttons: 选项列表。列表项的可用形式有: - - * dict: ``{label:选项标签, value:选项值, [type: 按钮类型], [disabled:是否禁止选择]}`` . + * dict: ``{label:按钮标签, value:按钮值, [type: 按钮类型], [disabled:是否禁止选择]}`` . 若 ``type='reset'/'cancel'`` 或 ``disabled=True`` 可省略 ``value`` * tuple or list: ``(label, value, [type], [disabled])`` * 单值: 此时label和value使用相同的值 - 其中, ``value`` 可以为任意可json序列化的对象。 ``type`` 可选值为: + 其中, ``value`` 可以为任意可JSON序列化的对象。 ``type`` 可选值为: * ``'submit'`` : 点击按钮后,立即将整个表单提交,最终表单中本项的值为被点击按钮的 ``value`` 值。 ``'submit'`` 为 ``type`` 的默认值 * ``'cancel'`` : 取消输入。点击按钮后,立即将整个表单提交,表单值返回 ``None`` @@ -426,9 +424,11 @@ def actions(label='', buttons=None, name=None, help_text=None): 注意:点击 ``type=reset`` 的按钮后,并不会提交表单, ``actions()`` 调用也不会返回 :param - label, name, help_text: 与 `input` 输入函数的同名参数含义一致 - :return: 若用户点击点击 ``type=submit`` 按钮进行表单提交,返回用户点击的按钮的值;若用户点击点击 ``type=callback`` 按钮,返回值通过回调函数设置; + :return: 若用户点击点击 ``type=submit`` 按钮进行表单提交,返回用户点击的按钮的值; 若用户点击 ``type=cancel`` 按钮或通过其它方式提交表单,则返回 ``None`` + 当 ``actions()`` 作为 `input_group()` 中的最后一个输入项、并且含有 ``type='submit'`` 的按钮时,`input_group()` 表单默认的提交按钮会被当前 ``actions()`` 替换 + **actions使用场景** .. _custom_form_ctrl_btn: @@ -500,12 +500,12 @@ def file_upload(label='', accept=None, name=None, placeholder='Choose file', mul max_total_size=0, required=None, help_text=None, **other_html_attrs): r"""文件上传。 - :param accept: 单值或列表, 表示可接受的文件类型。单值或列表项支持的形式有: + :param accept: 单值或列表, 表示可接受的文件类型。文件类型的可用形式有: * 以 ``.`` 字符开始的文件扩展名(例如:``.jpg, .png, .doc``)。 - 注意:截止本文档编写之时,微信内置浏览器还不支持这种语法 + 注意:截至本文档编写之时,微信内置浏览器还不支持这种语法 * 一个有效的 MIME 类型。 - 例如: ``application/pdf`` 、 ``audio/*`` 表示音频文件、``video/*`` 表示视频文件、``image/*`` 表示图片文件 + 例如: ``application/pdf`` 、 ``audio/*`` 表示音频文件、``video/*`` 表示视频文件、``image/*`` 表示图片文件。 参考 https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types :type accept: str or list @@ -513,7 +513,7 @@ def file_upload(label='', accept=None, name=None, placeholder='Choose file', mul :param bool multiple: 是否允许多文件上传 :param int/str max_size: 单个文件的最大大小,超过限制将会禁止上传。默认为0,表示不限制上传文件的大小。 - 可以为数字表示的字节数,或以 `K` / `M` / `G` 结尾的表示的字符串(分别表示 千字节、兆字节、吉字节,大小写不敏感)。例如: + ``max_size`` 值可以为数字表示的字节数,或以 `K` / `M` / `G` 结尾表示的字符串(分别表示 千字节、兆字节、吉字节,大小写不敏感)。例如: ``max_size=500`` , ``max_size='40K'`` , ``max_size='3M'`` :param int/str max_total_size: 所有文件的最大大小,超过限制将会禁止上传。仅在 ``multiple=True`` 时可用,默认不限制上传文件的大小。 格式同 ``max_size`` 参数 @@ -563,7 +563,7 @@ def input_group(label='', inputs=None, validate=None, cancelable=False): :param str label: 输入组标签 :param list inputs: 输入项列表。列表的内容为对单项输入函数的调用,并在单项输入函数中传入 ``name`` 参数。 - :param Callable validate: 输入组校验函数。 + :param callable validate: 输入组校验函数。 函数签名:``callback(data) -> (name, error_msg)`` ``validate`` 接收整个表单的值为参数,当校验表单值有效时,返回 ``None`` ,当某项输入值无效时,返回出错输入项的 ``name`` 值和错误提示. 比如: diff --git a/pywebio/output.py b/pywebio/output.py index e529e3c2..8a82d6e9 100644 --- a/pywebio/output.py +++ b/pywebio/output.py @@ -196,9 +196,10 @@ def set_scope(name, container_scope=Scope.Current, position=OutputPosition.BOTTO """创建一个新的scope. :param str name: scope名 - :param int/str container_scope: 此scope的父scope. 可以直接指定父scope名或使用 `Scope` 常量. scope不存在时,不进行任何操作. + :param int/str container_scope: 指定此scope的父scope. 可以直接指定父scope名或使用int索引运行时scope栈(参见 :ref:`输出函数的scope相关参数 `). scope不存在时,不进行任何操作. :param int position: 在父scope中创建此scope的位置. - `OutputPosition.TOP` : 在父scope的顶部创建, `OutputPosition.BOTTOM` : 在父scope的尾部创建 + 可选值: `OutputPosition.TOP` : 在父scope的顶部创建, `OutputPosition.BOTTOM`: 在父scope的底部创建。 + 也可以直接使用int来索引位置(参见 :ref:`输出函数的scope相关参数 `) :param str if_exist: 已经存在 ``name`` scope 时如何操作: - `None` 表示不进行任何操作 @@ -206,6 +207,7 @@ def set_scope(name, container_scope=Scope.Current, position=OutputPosition.BOTTO - `'clear'` 表示将旧scope的内容清除,不创建新scope 默认为 `None` + """ if isinstance(container_scope, int): container_scope = get_current_session().get_scope_name(container_scope) @@ -233,7 +235,7 @@ def get_scope(stack_idx=Scope.Current): def clear(scope=Scope.Current): """清空scope内容 - :param int/str scope: 可以直接指定scope名或使用 `Scope` 常量 + :param int/str scope: 可以直接指定scope名或使用int索引运行时scope栈(参见 :ref:`输出函数的scope相关参数 `) """ if isinstance(scope, int): scope = get_current_session().get_scope_name(scope) @@ -241,7 +243,10 @@ def clear(scope=Scope.Current): def remove(scope=Scope.Current): - """移除Scope""" + """移除Scope + + :param int/str scope: 可以直接指定scope名或使用int索引运行时scope栈(参见 :ref:`输出函数的scope相关参数 `) + """ if isinstance(scope, int): scope = get_current_session().get_scope_name(scope) assert scope != 'ROOT', "Can not remove `ROOT` scope." @@ -249,16 +254,15 @@ def remove(scope=Scope.Current): def scroll_to(scope=Scope.Current, position=Position.TOP): - """scroll_to(scope, position=Position.TOP) - + """ 将页面滚动到 ``scope`` Scope处 - :param str/int scope: Scope名 + :param str/int scope: 可以直接指定scope名或使用int索引运行时scope栈(参见 :ref:`输出函数的scope相关参数 `) :param str position: 将Scope置于屏幕可视区域的位置。可用值: - * ``Position.TOP`` : 滚动页面,让Scope位于屏幕可视区域顶部 - * ``Position.MIDDLE`` : 滚动页面,让Scope位于屏幕可视区域中间 - * ``Position.BOTTOM`` : 滚动页面,让Scope位于屏幕可视区域底部 + * ``'top'`` : 滚动页面,让Scope位于屏幕可视区域顶部 + * ``'middle'`` : 滚动页面,让Scope位于屏幕可视区域中间 + * ``'bottom'`` : 滚动页面,让Scope位于屏幕可视区域底部 """ if isinstance(scope, int): scope = get_current_session().get_scope_name(scope) @@ -298,7 +302,7 @@ def put_text(*texts, sep=' ', inline=False, scope=Scope.Current, position=Output :param texts: 要输出的内容。类型可以为任意对象,对非字符串对象会应用 `str()` 函数作为输出值。 :param str sep: 输出分隔符 - :param bool inline: 文本行末不换行。默认换行 + :param bool inline: 将文本作为行内元素(文本行末不换行)。默认换行 :param int/str scope: 内容输出的目标scope,若scope不存在,则不进行任何输出操作。 可以直接指定目标Scope名,或者使用int通过索引Scope栈来确定Scope:0表示最顶层也就是ROOT Scope,-1表示当前Scope,-2表示进入当前Scope的前一个Scope,... @@ -319,7 +323,7 @@ def put_html(html, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Outpu 与支持通过Html输出内容到 `Jupyter Notebook `_ 的库兼容。 - :param html: html字符串或实现了 `IPython.display.HTML` 接口的类的实例 + :param html: html字符串或实现了 `IPython.display.HTML` 接口的实例 :param int scope, position: 与 `put_text` 函数的同名参数含义一致 """ if hasattr(html, '__html__'): @@ -403,7 +407,7 @@ def __init__(self, content, row=1, col=1): def span(content, row=1, col=1): """用于在 :func:`put_table()` 和 :func:`put_grid()` 中设置内容跨单元格 - :param content: 单元格内容 + :param content: 单元格内容。可以为字符串或 ``put_xxx()`` 调用。 :param int row: 竖直方向跨度, 即:跨行的数目 :param int col: 水平方向跨度, 即:跨列的数目 @@ -570,7 +574,7 @@ def put_buttons(buttons, onclick, small=None, link_style=False, scope=Scope.Curr for i in ['primary' , 'secondary' , 'success' , 'danger' , 'warning' , 'info' , 'light' , 'dark'] # ..demo-only ], onclick=put_text) # ..demo-only - :type onclick: Callable / list + :type onclick: callable / list :param onclick: 按钮点击回调函数. ``onclick`` 可以是函数或者函数组成的列表. ``onclick`` 为函数时, 签名为 ``onclick(btn_value)``. ``btn_value`` 为被点击的按钮的 ``value`` 值 @@ -580,7 +584,7 @@ def put_buttons(buttons, onclick, small=None, link_style=False, scope=Scope.Curr Tip: 可以使用 ``functools.partial`` 来在 ``onclick`` 中保存更多上下文信息. Note: 当使用 :ref:`基于协程的会话实现 ` 时,回调函数可以为协程函数. - :param bool small: 是否显示小号按钮,默认为False + :param bool small: 是否使用小号按钮,默认为False :param bool link_style: 是否将按钮显示为链接样式,默认为False :param int scope, position: 与 `put_text` 函数的同名参数含义一致 :param callback_options: 回调函数的其他参数。根据选用的 session 实现有不同参数 @@ -590,8 +594,7 @@ def put_buttons(buttons, onclick, small=None, link_style=False, scope=Scope.Curr ThreadBasedSession 实现 * serial_mode: 串行模式模式。默认为 ``False`` ,此时每次触发回调,回调函数会在新线程中立即执行。 - 对于开启了serial_mode的回调,都会在会话内的一个固定线程内执行,当会话运行此回调时,其他所有新的点击事件的回调(包括 ``serial_mode=False`` 的回调)都将排队等待当前点击事件运行完成。 - 如果回调函数运行时间很短,可以开启 ``serial_mode`` 来提高性能。 + 开启serial_mode后,该按钮的回调会在会话内的一个固定线程内串行执行,且其他所有新的点击事件的回调(包括 ``serial_mode=False`` 的回调)都将排队等待当前点击事件运行完成。如果回调函数运行时间很短,可以开启 ``serial_mode`` 来提高性能。 使用示例: @@ -643,12 +646,26 @@ def put_image(src, format=None, title='', width=None, height=None, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output: """输出图片。 - :param src: 图片内容. 类型可以为字符串类型的URL或者是 bytes-like object 或者为 ``PIL.Image.Image`` 实例 + :param src: 图片内容. 可以为: 字符串类型的URL, bytes-like object 表示的图片二进制内容, ``PIL.Image.Image`` 实例 :param str title: 图片描述 :param str width: 图像的宽度,可以是CSS像素(数字px)或者百分比(数字%)。 :param str height: 图像的高度,可以是CSS像素(数字px)或者百分比(数字%)。可以只指定 width 和 height 中的一个值,浏览器会根据原始图像进行缩放。 - :param str format: 图片格式。如 ``png`` , ``jpeg`` , ``gif`` 等, 仅在 `src` 为非URL时有效 + :param str format: 图片格式,非必须。如 ``png`` , ``jpeg`` , ``gif`` 等, 仅在 `src` 为非URL时有效 :param int scope, position: 与 `put_text` 函数的同名参数含义一致 + + 使用示例: + + .. exportable-codeblock:: + :name: put_image + :summary: 使用`put_image()`输出图片 + + from pywebio import STATIC_PATH # ..demo-only + img = open(STATIC_PATH + '/image/favicon_open_32.png', 'rb').read() # ..demo-only + img = open('/path/to/some/image.png', 'rb').read() # ..doc-only + put_image(img, width='50px') + + ## ---- + put_image('https://www.python.org/static/img/python-logo.png') """ if isinstance(src, PILImage): format = src.format @@ -682,6 +699,14 @@ def put_file(name, content, label=None, scope=Scope.Current, position=OutputPosi 在PyWebIO会话(关于会话的概念见 :ref:`Server与script模式 ` )结束后,使用 ``put_file()`` 输出的文件也将无法下载,可以在任务函数末尾处使用 `pywebio.session.hold()` 函数来将会话保持,这样在用户关闭浏览器页面前, 文件下载将一直可用。 + + 使用示例: + + .. exportable-codeblock:: + :name: put_file + :summary: `put_file()`的使用 + + put_file('hello-world.txt', b'hello world!', 'download me') """ if label is None: label = name @@ -693,11 +718,11 @@ def put_file(name, content, label=None, scope=Scope.Current, position=OutputPosi def put_link(name, url=None, app=None, new_window=False, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output: - """输出链接到其他页面或PyWebIO App的超链接 + """输出链接到其他网页或PyWebIO App的超链接 :param str name: 链接名称 :param str url: 链接到的页面地址 - :param str app: 链接到的PyWebIO应用名 + :param str app: 链接到的PyWebIO应用名。参见 :ref:`Server模式 ` :param bool new_window: 是否在新窗口打开链接 :param int scope, position: 与 `put_text` 函数的同名参数含义一致 @@ -720,6 +745,19 @@ def put_processbar(name, init=0, label=None, auto_close=False, scope=Scope.Curre :param str label: 进度条显示的标签. 默认为当前进度的百分比 :param bool auto_close: 是否在进度完成后关闭进度条 :param int scope, position: 与 `put_text` 函数的同名参数含义一致 + + 使用示例: + + .. exportable-codeblock:: + :name: put_processbar + :summary: `put_processbar()` usage + + import time + + put_processbar('bar'); + for i in range(1, 11): + set_processbar('bar', i / 10) + time.sleep(0.1) """ processbar_id = 'webio-processbar-%s' % name percentage = init * 100 @@ -740,6 +778,8 @@ def set_processbar(name, value, label=None): :param str name: 进度条名称 :param float value: 进度条的值. 范围在 0 ~ 1 之间 :param str label: 进度条显示的标签. 默认为当前进度的百分比 + + 参见 `put_processbar()` """ from pywebio.session import run_js @@ -768,15 +808,20 @@ def put_loading(shape='border', color='dark', scope=Scope.Current, position=Outp `'warning'` 、`'info'` 、`'light'` 、 `'dark'` (默认) :param int scope, position: 与 `put_text` 函数的同名参数含义一致 - .. note:: - 可以通过 :func:`style()` 设置加载提示的尺寸: + 使用示例: - .. exportable-codeblock:: - :name: put_loading-size - :summary: `put_loading()`自定义加载提示尺寸 + .. exportable-codeblock:: + :name: put_loading + :summary: `put_loading()` 使用示例 + + for shape in ('border', 'grow'): + for color in ('primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'): + put_text(shape, color) + put_loading(shape=shape, color=color) - put_loading() # ..demo-only - style(put_loading(), 'width:4rem; height:4rem') + ## ---- + # 可以通过 style() 设置加载提示的尺寸 + style(put_loading(), 'width:4rem; height:4rem') """ assert shape in ('border', 'grow'), "shape must in ('border', 'grow')" assert color in {'primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'} @@ -796,6 +841,24 @@ def put_collapse(title, content, open=False, scope=Scope.Current, position=Outpu :param content: 内容可以为字符串或 ``put_xxx`` 类输出函数的返回值,或者由它们组成的列表。 :param bool open: 是否默认展开折叠内容。默认不展开内容 :param int scope, position: 与 `put_text` 函数的同名参数含义一致 + + 使用示例: + + .. exportable-codeblock:: + :name: put_collapse + :summary: `put_collapse()` 使用示例 + + put_collapse('Collapse title', [ + 'text', + put_markdown('~~Strikethrough~~'), + put_table([ + ['Commodity', 'Price'], + ['Apple', '5.5'], + ]) + ], open=True) + + ## ---- + put_collapse('Large text', 'Awesome PyWebIO! '*30) """ if not isinstance(content, (list, tuple, OutputList)): content = [content] @@ -828,7 +891,7 @@ def put_scrollable(content, max_height=400, horizon_scroll=False, border=True, s content = [content] for item in content: - assert isinstance(item, (str, Output)), "put_collapse() content must be list of str/put_xxx()" + assert isinstance(item, (str, Output)), "put_scrollable() content must be list of str/put_xxx()" tpl = """
` 中的 ``put_xxx()`` 子项进行动态修改(见下方代码示例) - :param contents: 要输出的初始内容. 元素为 ``put_xxx()`` 形式的调用或字符串,字符串会被看成HTML. + :param contents: 要输出的初始内容. 元素为 ``put_xxx()`` 形式的调用或字符串. :return: OutputHandler 实例, 实例支持的方法如下: * ``reset(*contents)`` : 重置内容为 ``contents`` @@ -1181,8 +1244,7 @@ def style(outputs, css_style) -> Union[Output, OutputList]: @safely_destruct_output_when_exp('content') def popup(title, content=None, size=PopupSize.NORMAL, implicit_close=True, closable=True): - """popup(title, content, size=PopupSize.NORMAL, implicit_close=True, closable=True) - + """ 显示弹窗 ⚠️: PyWebIO不允许同时显示多个弹窗,在显示新弹窗前,会自动关闭页面上存在的弹窗。可以使用 `close_popup()` 主动关闭弹窗 @@ -1192,15 +1254,15 @@ def popup(title, content=None, size=PopupSize.NORMAL, implicit_close=True, closa :param content: 弹窗内容. 可以为字符串或 ``put_xxx`` 类输出函数的返回值,或者为它们组成的列表。 :param str size: 弹窗窗口大小,可选值: - * ``LARGE`` : 大尺寸 - * ``NORMAL`` : 普通尺寸 - * ``SMALL`` : 小尺寸 + * ``'large'`` : 大尺寸 + * ``'normal'`` : 普通尺寸 + * ``'small'`` : 小尺寸 :param bool implicit_close: 是否可以通过点击弹窗外的内容或按下 ``Esc`` 键来关闭弹窗 - :param bool closable: 是否可由用户关闭弹窗. 默认情况下,用户可以通过点击弹窗右上角的关闭按钮来关闭弹窗, - 设置为 ``False`` 时弹窗仅能通过 :func:`popup_close()` 关闭, ``implicit_close`` 参数被忽略. + :param bool closable: 是否可由用户关闭弹窗. 默认情况下,用户可以通过点击弹窗右上角的关闭按钮来关闭弹窗。 + 设置为 ``False`` 时弹窗仅能通过 :func:`popup_close()` 关闭,此时 ``implicit_close`` 参数将被忽略. - 支持直接传入内容、上下文管理器、装饰器三种形式的调用 + ``popup()`` 支持直接传入内容、上下文管理器、装饰器三种形式的调用 * 直接传入内容: @@ -1227,13 +1289,13 @@ def popup(title, content=None, size=PopupSize.NORMAL, implicit_close=True, closa with popup('Popup title') as s: put_html('

Popup Content

') put_text('html:
') - put_buttons(['clear()'], onclick=lambda _: clear(scope=s)) + put_buttons([('clear()', s)], onclick=clear) put_text('Also work!', scope=s) - 上下文管理器会开启一个新的输出域并返回Scope名,上下文管理器中的输出调用会显示到弹窗上。 - 上下文管理器退出后,弹窗并不会关闭,依然可以使用 ``scope`` 参数输出内容到弹窗。 + 上下文管理器会开启一个新的输出域并返回Scope名,在上下文管理器中的输出默认会显示到弹窗上。 + 上下文管理器退出后,弹窗并不会关闭,依然可以在输出函数中指定 ``scope`` 参数来输出内容到弹窗。 * 作为装饰器使用: @@ -1269,7 +1331,10 @@ def show_popup(): def close_popup(): - """关闭当前页面上正在显示的弹窗""" + """关闭当前页面上正在显示的弹窗 + + 参见: `popup()` + """ send_msg(cmd='close_popup') @@ -1291,7 +1356,7 @@ def toast(content, duration=2, position='center', color='info', onclick=None): :summary: 使用`toast()`显示通知 def show_msg(): - put_text("Some messages...") + put_text("You clicked the notification.") toast('New messages', position='right', color='#2188ff', duration=0, onclick=show_msg) @@ -1318,10 +1383,10 @@ def use_scope(name=None, clear=False, create_scope=True, **scope_params): 参见 :ref:`用户手册-use_scope() ` - :param name: scope名. 若为None则生成一个全局唯一的scope名.(以上下文管理器形式的调用时,上下文管理器会返回scope名) + :param str name: scope名. 若为None则生成一个全局唯一的scope名.(以上下文管理器形式的调用时,上下文管理器会返回scope名) :param bool clear: 在进入scope前是否要清除scope里的内容 :param bool create_scope: scope不存在时是否创建scope - :param scope_params: 创建scope时传入set_scope()的参数. 仅在 `create_scope=True` 时有效. + :param scope_params: 创建scope时传入 `set_scope()` 的额外的参数. 仅在 `create_scope=True` 时有效. :Usage: diff --git a/pywebio/platform/aiohttp.py b/pywebio/platform/aiohttp.py index 8fcf45dd..aa7ad0b2 100644 --- a/pywebio/platform/aiohttp.py +++ b/pywebio/platform/aiohttp.py @@ -102,8 +102,8 @@ def close_from_session(): def webio_handler(applications, allowed_origins=None, check_origin=None, websocket_settings=None): - """获取在aiohttp中运行PyWebIO任务函数的 `Request Handle `_ 协程。 - Request Handle基于WebSocket协议与浏览器进行通讯。 + """获取在aiohttp中运行PyWebIO任务函数的 `Request Handler `_ 协程。 + Request Handler基于WebSocket协议与浏览器进行通讯。 :param list/dict/callable applications: PyWebIO应用。 :param list allowed_origins: 除当前域名外,服务器还允许的请求的来源列表。 diff --git a/pywebio/platform/django.py b/pywebio/platform/django.py index 37b35f76..8e14addd 100644 --- a/pywebio/platform/django.py +++ b/pywebio/platform/django.py @@ -108,8 +108,8 @@ def view_func(request): def start_server(applications, port=8080, host='localhost', allowed_origins=None, check_origin=None, - session_cleanup_interval=None, session_expire_seconds=None, + session_cleanup_interval=None, debug=False, **django_options): """启动一个 Django server 将PyWebIO应用作为Web服务提供。 @@ -129,7 +129,7 @@ def start_server(applications, port=8080, host='localhost', :param callable check_origin: 请求来源检查函数。接收请求来源(包含协议、域名和端口部分)字符串, 返回 ``True/False`` 。若设置了 ``check_origin`` , ``allowed_origins`` 参数将被忽略 :param int session_expire_seconds: 会话过期时间。若 session_expire_seconds 秒内没有收到客户端的请求,则认为会话过期。 - :param int session_cleanup_interval: 会话清理间隔。 + :param int session_cleanup_interval: 会话清理间隔(秒)。服务端会周期性清理过期的会话,释放会话占用的资源。 :param bool debug: 开启 Django debug mode 和一般访问日志的记录 :param django_options: django应用的其他设置,见 https://docs.djangoproject.com/en/3.0/ref/settings/ . 其中 ``DEBUG`` 、 ``ALLOWED_HOSTS`` 、 ``ROOT_URLCONF`` 、 ``SECRET_KEY`` 被PyWebIO设置,无法在 ``django_options`` 中指定 diff --git a/pywebio/platform/flask.py b/pywebio/platform/flask.py index 012ac99a..fe089346 100644 --- a/pywebio/platform/flask.py +++ b/pywebio/platform/flask.py @@ -109,8 +109,8 @@ def view_func(): def start_server(applications, port=8080, host='localhost', allowed_origins=None, check_origin=None, - session_cleanup_interval=None, session_expire_seconds=None, + session_cleanup_interval=None, debug=False, **flask_options): """启动一个 Flask server 将PyWebIO应用作为Web服务提供。 @@ -130,8 +130,8 @@ def start_server(applications, port=8080, host='localhost', :param callable check_origin: 请求来源检查函数。接收请求来源(包含协议、域名和端口部分)字符串, 返回 ``True/False`` 。若设置了 ``check_origin`` , ``allowed_origins`` 参数将被忽略 :param int session_expire_seconds: 会话过期时间。若 session_expire_seconds 秒内没有收到客户端的请求,则认为会话过期。 - :param int session_cleanup_interval: 会话清理间隔。 - :param bool debug: Flask debug mode + :param int session_cleanup_interval: 会话清理间隔(秒)。服务端会周期性清理过期的会话,释放会话占用的资源。 + :param bool debug: 是否开启Flask Server的debug模式,开启后,代码发生修改后服务器会自动重启。 :param flask_options: 传递给 ``flask.Flask.run`` 函数的额外的关键字参数 可设置项参考: https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.run """ diff --git a/pywebio/platform/tornado.py b/pywebio/platform/tornado.py index 1ff06729..9dd0da98 100644 --- a/pywebio/platform/tornado.py +++ b/pywebio/platform/tornado.py @@ -53,11 +53,11 @@ def _is_same_site(origin, handler: WebSocketHandler): def _webio_handler(applications, check_origin_func=_is_same_site): - """获取用于Tornado进行整合的RequestHandle类 + """获取用于Tornado进行整合的RequestHandler类 :param dict applications: 任务名->任务函数 的字典 :param callable check_origin_func: check_origin_func(origin, handler) -> bool - :return: Tornado RequestHandle类 + :return: Tornado RequestHandler类 """ class WSHandler(WebSocketHandler): @@ -114,7 +114,7 @@ def on_close(self): def webio_handler(applications, allowed_origins=None, check_origin=None): - """获取在Tornado中运行PyWebIO应用的RequestHandle类。RequestHandle类基于WebSocket协议与浏览器进行通讯。 + """获取在Tornado中运行PyWebIO应用的RequestHandler类。RequestHandler类基于WebSocket协议与浏览器进行通讯。 :param callable/list/dict applications: PyWebIO应用。 :param list allowed_origins: 除当前域名外,服务器还允许的请求的来源列表。 @@ -122,7 +122,7 @@ def webio_handler(applications, allowed_origins=None, check_origin=None): 关于各参数的详细说明见 :func:`pywebio.platform.tornado.start_server` 的同名参数。 - :return: Tornado RequestHandle类 + :return: Tornado RequestHandler类 """ applications = make_applications(applications) for target in applications.values(): @@ -175,12 +175,14 @@ def start_server(applications, port=0, host='', debug=False, 可以通过 ``app`` URL参数选择要运行的任务(例如访问 ``http://host:port/?app=foo`` 来运行 ``foo`` 任务), 默认使用运行 ``index`` 任务函数,当 ``index`` 任务不存在时,PyWebIO会提供一个默认的索引页作为主页。 + 参见 :ref:`Server模式 ` 任务函数为协程函数时,使用 :ref:`基于协程的会话实现 ` ;任务函数为普通函数时,使用基于线程的会话实现。 :param int port: 服务监听的端口。设置为 ``0`` 时,表示自动选择可用端口。 :param str host: 服务绑定的地址。 ``host`` 可以是IP地址或者为hostname。如果为hostname,服务会监听所有与该hostname关联的IP地址。 通过设置 ``host`` 为空字符串或 ``None`` 来将服务绑定到所有可用的地址上。 - :param bool debug: Tornado Server是否开启debug模式 + :param bool debug: 是否开启Tornado Server的debug模式,开启后,代码发生修改后服务器会自动重启。 + 详情请参阅 `tornado 文档 `_ :param list allowed_origins: 除当前域名外,服务器还允许的请求的来源列表。 来源包含协议、域名和端口部分,允许使用 Unix shell 风格的匹配模式(全部规则参见 `Python文档 `_ ): @@ -190,8 +192,8 @@ def start_server(applications, port=0, host='', debug=False, - ``[!seq]`` 匹配任何不在seq中的字符 比如 ``https://*.example.com`` 、 ``*://*.example.com`` - :param callable check_origin: 请求来源检查函数。接收请求来源(包含协议、域名和端口部分)字符串, - 返回 ``True/False`` 。若设置了 ``check_origin`` , ``allowed_origins`` 参数将被忽略 + :param callable check_origin: 请求来源检查函数。接收请求来源(包含协议、域名和端口部分)字符串作为参数, + 返回 ``True/False`` 指示服务器接受/拒绝该请求。若设置了 ``check_origin`` , ``allowed_origins`` 参数将被忽略 :param bool auto_open_webbrowser: 当服务启动后,是否自动打开浏览器来访问服务。(该操作需要操作系统支持) :param int websocket_max_message_size: Tornado Server最大可接受的WebSockets消息大小。单位为字节,默认为10MiB。 :param int websocket_ping_interval: 当被设置后,服务器会以 ``websocket_ping_interval`` 秒周期性地向每个WebSockets连接发送‘ping‘消息。 diff --git a/pywebio/session/__init__.py b/pywebio/session/__init__.py index dffdd0a9..1133cc30 100644 --- a/pywebio/session/__init__.py +++ b/pywebio/session/__init__.py @@ -155,6 +155,14 @@ def download(name, content): :param str name: 下载保存为的文件名 :param content: 文件内容. 类型为 bytes-like object + + 使用示例: + + .. exportable-codeblock:: + :name: download + :summary: `download()` 使用示例 + + put_buttons(['Click to download'], [lambda: download('hello-world.txt', b'hello world!')]) """ from ..io_ctrl import send_msg content = b64encode(content).decode('ascii') @@ -162,7 +170,7 @@ def download(name, content): def run_js(code_, **args): - """运行js代码. + """在用户浏览器中运行JavaScript代码. 代码运行在浏览器的JS全局作用域中 @@ -180,23 +188,32 @@ def run_js(code_, **args): @chose_impl def eval_js(expression_, **args): - """执行js表达式,并获取表达式的值 + """在用户浏览器中执行JavaScript表达式,并获取表达式的值 :param str expression_: js表达式. 表达式的值需要能JSON序列化 - :return: js表达式的值 :param args: 传递给js代码的局部变量。变量值需要可以被json序列化 + :return: js表达式的值 注意⚠️:在 :ref:`基于协程 ` 的会话上下文中,需要使用 ``await eval_js(expression)`` 语法来进行调用。 - Example:: + + 使用示例: + + .. exportable-codeblock:: + :name: eval_js + :summary: `eval_js()`使用示例 current_url = eval_js("window.location.href") + put_text(current_url) # ..demo-only + ## ---- function_res = eval_js('''(function(){ var a = 1; a += b; return a; })()''', b=100) + put_text(function_res) # ..demo-only + """ script = r""" (function(WebIO){ @@ -226,6 +243,8 @@ def run_async(coro_obj): :param coro_obj: 协程对象 :return: `TaskHandle ` 实例。 通过 TaskHandle 可以查询协程运行状态和关闭协程。 + + 参见::ref:`协程会话的并发 ` """ return get_current_session().run_async(coro_obj) @@ -283,7 +302,51 @@ def cleanup(): def data(): - """获取当前会话的数据对象,用于在对象上保存一些会话相关的数据。访问数据对象不存在的属性时会返回None而不是抛出异常。 + """获取当前会话的数据对象(session-local object)。 + + 访问数据对象不存在的属性时会返回None而不是抛出异常。 + + 当需要在多个函数中保存一些会话独立的数据时,使用session-local对象保存状态会比通过函数参数传递更方便。 + 以下是一个会话独立的计数器的实现示例:: + + def add(): + data().cnt = (data().cnt or 0) + 1 + + def show(): + put_text(data().cnt or 0) + + def main(): # 会话独立的计数器 + put_buttons(['Add counter', 'Show counter'], [add, show]) + hold() + + 而通过函数参数传递状态的实现方式为:: + + from functools import partial + def add(cnt): + cnt[0] += 1 + + def show(cnt): + put_text(cnt[0]) + + def main(): # 会话独立的计数器 + cnt = [0] # 将计数器保存在数组中才可以实现引用传参 + put_buttons(['Add counter', 'Show counter'], [partial(add, cnt), partial(show, cnt)]) + hold() + + 当然,还可以通过函数闭包来实现相同的功能:: + + def main(): # 会话独立的计数器 + cnt = 0 + + def add(): + nonlocal cnt + cnt += 1 + + def show(): + put_text(cnt) + + put_buttons(['Add counter', 'Show counter'], [add, show]) + hold() """ return get_current_session().save @@ -296,7 +359,7 @@ def set_env(**env_info): * ``title`` (str): 当前页面的标题 * ``output_animation`` (bool): 是否启用输出动画(在输出内容时,使用过渡动画),默认启用 * ``auto_scroll_bottom`` (bool): 是否在内容输出时将页面自动滚动到底部,默认关闭。注意,开启后,只有输出到ROOT Scope才可以触发自动滚动。 - * ``http_pull_interval`` (int): HTTP轮询后端消息的周期(单位为毫秒,默认1000ms),仅在基于HTTP连接的会话中可用() + * ``http_pull_interval`` (int): HTTP轮询后端消息的周期(单位为毫秒,默认1000ms),仅在基于HTTP连接的会话(使用Flask或Django后端)中可用 调用示例:: @@ -309,10 +372,12 @@ def set_env(**env_info): def go_app(name, new_window=True): - """跳转PyWebIO任务,仅在PyWebIO Server模式下可用 + """在同一PyWebIO应用的不同服务之间跳转。仅在PyWebIO Server模式下可用 - :param str name: PyWebIO任务名 + :param str name: 目标 PyWebIO 任务名 :param bool new_window: 是否在新窗口打开,默认为 `True` + + 参见: :ref:`Server 模式 ` """ run_js('javascript:WebIO.openApp(app, new_window)', app=name, new_window=new_window) @@ -346,7 +411,7 @@ def get_info(): * ``origin`` (str): 当前用户的页面地址. 包含 协议、主机、端口 部分. 比如 ``'http://localhost:8080'`` . 可能为空,但保证当用户的页面地址不在当前服务器下(即 主机、端口部分和 ``server_host`` 不一致)时有值. * ``user_ip`` (str): 用户的ip地址. - * ``backend`` (str): PyWebIO使用的Web框架名. 目前可用值有 ``'tornado'`` , ``'flask'`` , ``'django'`` , ``'aiohttp'`` . + * ``backend`` (str): 当前PyWebIO使用的后端Server实现. 可能出现的值有 ``'tornado'`` , ``'flask'`` , ``'django'`` , ``'aiohttp'``. * ``request`` (object): 创建当前会话时的Web请求对象. 根据PyWebIO使用的后端Server不同,``request`` 的类型也不同: * 使用Tornado后端时, ``request`` 为 @@ -356,5 +421,19 @@ def get_info(): * 使用aiohttp后端时, ``request`` 为 `aiohttp.web.BaseRequest `_ 实例 会话信息对象的 ``user_agent`` 属性是通过 user-agents 库进行解析生成的。参见 https://github.com/selwin/python-user-agents#usage + + 使用示例: + + .. exportable-codeblock:: + :name: get_info + :summary: `get_info()` 的使用 + + import json + + info = get_info() + put_code(json.dumps({ + k: str(v) + for k,v in info.items() + }, indent=4), 'json') """ return get_current_session().info diff --git a/pywebio/session/coroutinebased.py b/pywebio/session/coroutinebased.py index 2ea8e750..f6214d0c 100644 --- a/pywebio/session/coroutinebased.py +++ b/pywebio/session/coroutinebased.py @@ -226,7 +226,10 @@ async def run_asyncio_coroutine(self, coro_obj): class TaskHandle: - """协程任务句柄""" + """协程任务句柄 + + 参见:`run_async() ` + """ def __init__(self, close, closed): self._close = close From bd214c6ca487f7addf71651e4ccf85d2f208f7ad Mon Sep 17 00:00:00 2001 From: wangweimin Date: Tue, 2 Feb 2021 19:13:48 +0800 Subject: [PATCH 011/445] maint: increase the waiting time for server to start --- pywebio/platform/tornado.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pywebio/platform/tornado.py b/pywebio/platform/tornado.py index 9dd0da98..969e3bca 100644 --- a/pywebio/platform/tornado.py +++ b/pywebio/platform/tornado.py @@ -138,7 +138,7 @@ def webio_handler(applications, allowed_origins=None, check_origin=None): async def open_webbrowser_on_server_started(host, port): url = 'http://%s:%s' % (host, port) - is_open = await wait_host_port(host, port, duration=5, delay=0.5) + is_open = await wait_host_port(host, port, duration=30, delay=0.5) if is_open: logger.info('Try open %s in web browser' % url) webbrowser.open(url) From 682ae6639b3b8a361da5e972b8ef4da88798a797 Mon Sep 17 00:00:00 2001 From: wangweimin Date: Tue, 2 Feb 2021 19:15:41 +0800 Subject: [PATCH 012/445] feat: frontend i18n support --- webiojs/src/handlers/input.ts | 9 ++--- webiojs/src/i18n.ts | 60 ++++++++++++++++++++++++++++++++ webiojs/src/models/input/file.ts | 5 +-- webiojs/src/session.ts | 7 ++-- 4 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 webiojs/src/i18n.ts diff --git a/webiojs/src/handlers/input.ts b/webiojs/src/handlers/input.ts index 67a9214f..ab442463 100644 --- a/webiojs/src/handlers/input.ts +++ b/webiojs/src/handlers/input.ts @@ -5,6 +5,7 @@ import {state} from '../state' import {all_input_items} from "../models/input" import {CommandHandler} from "./base" import {close_input, show_input} from "../ui"; +import {t} from "../i18n"; /* * 整个输入区域的控制类 @@ -158,9 +159,9 @@ class FormController {
- - - {{#cancelable}}{{/cancelable}} + + + {{#cancelable}}{{/cancelable}}
@@ -208,7 +209,7 @@ class FormController { for (let name in that.name2input) if (!that.name2input[name].check_valid()) - return error_alert('输入项存在错误,请消除错误后再提交'); + return error_alert(t("error_in_input")); let data: { [i: string]: any } = {}; $.each(that.name2input, (name, ctrl) => { diff --git a/webiojs/src/i18n.ts b/webiojs/src/i18n.ts new file mode 100644 index 00000000..08d3efa5 --- /dev/null +++ b/webiojs/src/i18n.ts @@ -0,0 +1,60 @@ +// @ts-ignore +const userLangCode: string = (navigator.language || navigator.userLanguage || 'en').toLowerCase(); + +const userLang: string = userLangCode.split('-')[0]; + + +const translations: { [lang: string]: { [msgid: string]: string } } = { + "en": { + "disconnected_with_server": "Disconnected from the server, please refresh the page", + "connect_fail": "Failed to connect to server!", + "error_in_input": "There is an error with the input, please fix the error first", + "file_size_exceed": 'File "%1" size exceeds limit: the size of a single file must not exceed %2', + "file_total_size_exceed": "The total file size exceeds the limit: the total file size must not exceed %1", + "submit": "Submit", + "reset": "Reset", + "cancel": "Cancel", + }, + "zh": { + "disconnected_with_server": "与服务器连接已断开,请刷新页面重新操作", + "connect_fail": "连接服务器失败!", + "error_in_input": "输入项存在错误,请消除错误后再提交", + "file_size_exceed": '文件"%1"大小超过限制: 单个文件大小不超过%2', + "file_total_size_exceed": "文件总大小超过限制: 文件总大小不超过%1", + "submit": "提交", + "reset": "重置", + "cancel": "取消", + }, +}; + + +// sprintf equivalent, takes a string and some arguments to make a computed string +// eg: strfmt("%1 dogs are in %2", 7, "the kitchen"); => "7 dogs are in the kitchen" +// eg: strfmt("I like %1, bananas and %1", "apples"); => "I like apples, bananas and apples" +function strfmt(fmt: string) { + let args = arguments; + + return fmt + // put space after double % to prevent placeholder replacement of such matches + .replace(/%%/g, '%% ') + // replace placeholders + .replace(/%(\d+)/g, function (str, p1) { + return args[p1]; + }) + // replace double % and space with single % + .replace(/%% /g, '%') +} + +export function t(msgid: string, ...args:string[]): string { + let fmt = null; + for (let lang of [userLangCode, userLang, 'en']) { + if (translations[lang] && translations[lang][msgid]){ + fmt = translations[lang][msgid]; + break; + } + } + if (fmt === null) + throw Error(`No translation for "${msgid}" in "${userLangCode}"`); + + return strfmt.apply(null, [fmt, ...args]); +} \ No newline at end of file diff --git a/webiojs/src/models/input/file.ts b/webiojs/src/models/input/file.ts index 39cfa37c..6a33993d 100644 --- a/webiojs/src/models/input/file.ts +++ b/webiojs/src/models/input/file.ts @@ -1,6 +1,7 @@ import {Session} from "../../session"; import {InputItem} from "./base"; import {deep_copy} from "../../utils" +import {t} from "../../i18n"; const file_input_tpl = `
""".strip() % style + """.strip() % html.escape(style, quote=True) return put_widget(template=tpl, data=dict(contents=content), scope=scope, position=position) @@ -1104,7 +1108,7 @@ def put_grid(content, cell_width='auto', cell_height='auto', cell_widths=None, c {{& pywebio_output_parse}} {{/.}} {{/contents}} - """.strip() % css + """.strip() % html.escape(css, quote=True) return put_widget(template=tpl, data=dict(contents=content), scope=scope, position=position) From 60219d6cd710decf4a80a15d6e7330a1c4aca58e Mon Sep 17 00:00:00 2001 From: wangweimin Date: Wed, 3 Feb 2021 20:34:05 +0800 Subject: [PATCH 020/445] WIP: doc translate --- docs/FAQ.rst | 30 +- docs/demos.rst | 14 +- docs/guide.rst | 556 +++++++++++++++------- docs/index.rst | 55 ++- docs/input.rst | 2 +- docs/libraries_support.rst | 57 ++- docs/misc.rst | 36 +- docs/output.rst | 2 +- docs/platform.rst | 2 +- docs/session.rst | 2 +- docs/spec.rst | 251 +++++----- pywebio/exceptions.py | 6 +- pywebio/input.py | 360 +++++++------- pywebio/output.py | 751 +++++++++++++++--------------- pywebio/platform/__init__.py | 22 +- pywebio/platform/aiohttp.py | 54 +-- pywebio/platform/django.py | 60 ++- pywebio/platform/flask.py | 58 ++- pywebio/platform/tornado.py | 101 ++-- pywebio/session/__init__.py | 193 ++++---- pywebio/session/coroutinebased.py | 2 +- 21 files changed, 1470 insertions(+), 1144 deletions(-) diff --git a/docs/FAQ.rst b/docs/FAQ.rst index 6f7143d6..010b27be 100644 --- a/docs/FAQ.rst +++ b/docs/FAQ.rst @@ -1,25 +1,43 @@ -常见问题 +FAQ ========================== .. contents:: :local: +How to make the input form not disappear after submission, and can continue to receive input? +---------------------------------------------------------------------------------------------- 如何让输入框在提交后不消失,并可以持续性地输入 ----------------------------------------------------------- + PyWebIO 的设计就是输入表单在成功提交后就销毁,因为 PyWebIO 的输入是阻塞式的,一旦提交表单,输入函数就返回了,此时表单还留在界面上是没有意义的。如果想实现持续性的输入,可以将接收输入以及后续操作放到一个 ``while`` 循环中。 +The design of PyWebIO is that the input form is destroyed after successful submission. The input function of PyWebIO is blocking. Once the form is submitted, the input function returns. So it is meaningless to leave the form on the page after submission of form. If you want to make continuous input, you can put input and subsequent operations into a ``while`` loop. -如何输出一个诸如搜索栏的输入框 + +How to output an input widget such as a search bar? ---------------------------------------------------------- +如何输出一个诸如搜索栏的输入框 + 很遗憾,PyWebIO并不支持将输入框作为一般性的内容输出到页面。因为这样就相当于又回到了基于回调获取输入的方式了,会导致应用开发的复杂性提高,PyWebIO不太推荐过多依赖回调机制,所以对此仅提供了非常少的支持。 不过也可以使用另一种方式实现近似的效果:只需要在需要显示输入框的地方放置一个button( `put_buttons() ` ),然后在button的回调函数中调用输入函数来获取输入并进行后续操作。 +Unfortunately, PyWebIO does not support outputting input widget to the page as general output widget. +Because this will make the input asynchronous, which is exactly what PyWebIO strives to avoid. Callbacks will increase the complexity of application development. PyWebIO does not recommend relying too much on the callback mechanism, so it only provides very little support. +However, there is a compromise way to achieve similar behavior: just put a button (`put_buttons() `) where the input widget needs to be displayed, and in the button's callback function, you can call the input function to get input and perform subsequent operations. -为什么 ``put_buttons()`` 的回调不起作用 + +Why the callback of ``put_buttons()`` does not work? ---------------------------------------------------------- +为什么 ``put_buttons()`` 的回调不起作用 + 一般情况下,在Server模式下,任务函数一旦返回(或在Script模式下,脚本运行结束),会话就结束了,此时事件回调也将不起作用,可以在任务函数(或脚本)末尾处使用 `pywebio.session.hold()` 函数来将会话保持,这样在用户关闭浏览器页面前,事件回调将一直可用。 参见 :ref:`Server模式与Script模式 ` +In general, in Server mode, once the task function returns (or in Script mode, the script exits), the session closes. After this, the event callback will not work. You can call the `pywebio.session.hold()` function at the end of the task function (or script) to hold the session, so that the event callback will always be available before the browser page is closed by user. -为什么 ``put_file()`` 无法下载文件 + +Why I cannot download the file using ``put_file()``? ---------------------------------------------------------- -原因同上。 ``put_file()`` 的文件链接被点击后,也是需要和服务端通信获取文件数据的,所以会话关闭后下载链接会不可用。可以在任务函数末尾处使用 `pywebio.session.hold()` 函数来将会话保持。 \ No newline at end of file +为什么 ``put_file()`` 无法下载文件 + +原因同上。 ``put_file()`` 的文件链接被点击后,也是需要和服务端通信获取文件数据的,所以会话关闭后下载链接会不可用。可以在任务函数末尾处使用 `pywebio.session.hold()` 函数来将会话保持。 + +The reason is the same as above. The page needs to request server for data when the download button is clicked, so the download link will be unavailable after the session is closed. You can use the `pywebio.session.hold()` function at the end of the task function to hold the session. \ No newline at end of file diff --git a/docs/demos.rst b/docs/demos.rst index dbff9423..4bc8f7a5 100644 --- a/docs/demos.rst +++ b/docs/demos.rst @@ -1,12 +1,14 @@ -示例Demos +Demos ========== -基本demo +Basic demos ------------ -使用PyWebIO编写的示例应用 +Sample application written with PyWebIO .. automodule:: demos -数据可视化demo ------------------ -PyWebIO支持使用第三方库进行数据可视化,详情见 :ref:`使用PyWebIO进行数据可视化 ` \ No newline at end of file +Data visualization demos +-------------------------- +PyWebIO支持使用第三方库进行数据可视化,详情见 :ref:`使用PyWebIO进行数据可视化 ` + +PyWebIO supports data visualization by using of third-party libraries. For details, see :ref:`Use PyWebIO for data visualization ` \ No newline at end of file diff --git a/docs/guide.rst b/docs/guide.rst index 952797a9..d7f19f76 100644 --- a/docs/guide.rst +++ b/docs/guide.rst @@ -3,96 +3,113 @@ User's guide 如果你接触过Web开发,你可能对接下来描述的PyWebIO的用法感到不太习惯,不同于传统Web开发的后端实现接口、前端进行展示交互的模式,在PyWebIO中,所有的逻辑都通过编写Python代码实现。 -你可以按照编写控制台程序的逻辑编写PyWebIO应用,只不过这里的终端变成了浏览器。通过PyWebIO提供的命令式API, +事实上,PyWebIO应用的编写逻辑更像控制台程序,只不过这里的终端变成了浏览器。通过PyWebIO提供的命令式API, 你可以简单地调用 ``put_text`` 、 ``put_image`` 、 ``put_table`` 等函数输出文本、图片、表格等内容到浏览器,也可以调用 ``input`` 、 ``select`` 、 ``file_upload`` 等函数在浏览器上显示不同表单来接收用户的输入。此外PyWebIO中还提供了点击事件、布局等支持,让你可以使用最少的代码完成与用户的交互, 并尽可能提供良好的用户体验。 本篇使用指南从几个方面对PyWebIO的使用进行介绍,覆盖了PyWebIO的绝大部分特性。本文档中大部分示例代码的右上方都有一个Demo链接,点击后可以在线预览代码的运行效果。 -输入 +If you are familiar with web development, you may not be accustomed to the usage of PyWebIO described next, which is different from the traditional web development mode that backend implement api and frontend display content. In PyWebIO, you only need write code in Python. + +In fact, the way of writing PyWebIO applications is more like writing a console program, except that the terminal here becomes a browser. Using the imperative API provided by PyWebIO, +you can simply call ``put_text``, ``put_image``, ``put_table`` and other functions to output text, pictures, tables and other content to the browser, or you can call some functions such as ``input``, ``select``, ``file_upload`` to display different forms on the browser to get user input. In addition, PyWebIO also provides support for click events, layout, etc. PyWebIO aims to allow you to use the least code to complete the interaction with the user and provide a good user experience as much as possible. + +This user guide introduces you the most of the features of PyWebIO. There is a demo link at the top right of the most of the example codes in this document, where you can preview the running effect of the code online. + +Input ------------ 输入函数都定义在 :doc:`pywebio.input ` 模块中,可以使用 ``from pywebio.input import *`` 引入。 调用输入函数会在浏览器上弹出一个输入表单来获取输入。PyWebIO的输入函数是阻塞式的(和Python内置的 `input` 一样),在表单被成功提交之前,输入函数不会返回。 -基本输入 -^^^^^^^^^^^ +The input functions are defined in the :doc:`pywebio.input ` module and can be imported using ``from pywebio.input import *``. -首先是一些基本类型的输入 +Calling the input function will pop up an input form on the browser. PyWebIO's input functions is blocking (same as Python's built-in ``input()`` function) and will not return until the form is successfully submitted. -文本输入: +Basic input +^^^^^^^^^^^^^ + +Here are some basic types of input. + +Text input: .. exportable-codeblock:: :name: text-input - :summary: 文本输入 + :summary: Text input age = input("How old are you?", type=NUMBER) put_text('age = %r' % age) # ..demo-only -这样一行代码的效果为:浏览器会弹出一个文本输入框来获取输入,在用户完成输入将表单提交后,函数返回用户输入的值。 +After running the above code, the browser will pop up a text input box to get the input. After the user completes the input and submits the form, the function returns the value entered by the user. -下面是一些其他类型的输入函数: +Here are some other types of input functions: .. exportable-codeblock:: :name: basic-input - :summary: 基本输入 + :summary: Basic input - # 密码输入 + # Password input password = input("Input password", type=PASSWORD) put_text('password = %r' % password) # ..demo-only ## ---- - # 下拉选择框 + # Drop-down selection gift = select('Which gift you want?', ['keyboard', 'ipad']) put_text('gift = %r' % gift) # ..demo-only ## ---- - # 勾选选项 - agree = checkbox("用户协议", options=['I agree to terms and conditions']) + # Checkbox + agree = checkbox("User Term", options=['I agree to terms and conditions']) put_text('agree = %r' % agree) # ..demo-only ## ---- - # 单选选项 + # Single choice answer = radio("Choose one", options=['A', 'B', 'C', 'D']) put_text('answer = %r' % answer) # ..demo-only ## ---- - # 多行文本输入 + # Multi-line text input text = textarea('Text Area', rows=3, placeholder='Some text') put_text('text = %r' % text) # ..demo-only ## ---- - # 文件上传 + # File Upload img = file_upload("Select a image:", accept="image/*") if img: # ..demo-only put_image(img['content'], title=img['filename']) # ..demo-only -输入选项 -^^^^^^^^^^^ +Parameter of input functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 输入函数可指定的参数非常丰富(全部参数及含义请见 :doc:`函数文档 ` ): +There are many parameters that can be passed to the input function(for complete parameters, please refer to the :doc:`function document `): + .. exportable-codeblock:: :name: input-args - :summary: 输入参数 + :summary: Parameter of input functions input('This is label', type=TEXT, placeholder='This is placeholder', help_text='This is help text', required=True) 以上代码将在浏览器上显示如下: +The results of the above example are as follows: + .. image:: /assets/input_1.png 我们可以为输入指定校验函数,校验函数应在校验通过时返回None,否则返回错误消息: +You can specify a validation function for the input by using ``validate`` parameter. The validation function should return ``None`` when the check passes, otherwise an error message will be returned: + .. exportable-codeblock:: :name: input-valid-func - :summary: 输入指定校验函数 + :summary: Input validate function for - def check_age(p): # 检验函数校验通过时返回None,否则返回错误消息 + def check_age(p): # return None when the check passes, otherwise an error message will be returned if p < 10: return 'Too young!!' if p > 60: @@ -103,37 +120,50 @@ User's guide 当用户输入了不合法的值时,页面上的显示如下: +When the user input an illegal value, the display on the page is as follows: + .. image:: /assets/input_2.png :func:`pywebio.input.textarea` 还支持使用 `Codemirror `_ 实现代码风格的编辑区,只需使用 ``code`` 参数传入Codemirror支持的选项即可(最简单的情况是直接传入 ``code={}`` 或 ``code=True``): +:func:`pywebio.input.textarea` supports for code editing by using `Codemirror `_ , just use the ``code`` parameter to pass in the options supported by Codemirror (the simplest case is to pass in ``code={}`` or ``code=True`` directly): + +You can use ``code`` parameter in :func:`pywebio.input.textarea` to make a code editing textarea. This feature uses `Codemirror `_ as underlying implementation. The ``code`` parameter accept the Codemirror options as a dict. + .. exportable-codeblock:: :name: codemirror - :summary: textarea代码编辑 + :summary: Code editing by using textarea code = textarea('Code Edit', code={ - 'mode': "python", # 编辑区代码语言 - 'theme': 'darcula', # 编辑区darcula主题, Visit https://codemirror.net/demo/theme.html#cobalt to get more themes + 'mode': "python", # code language + 'theme': 'darcula', # Codemirror theme. Visit https://codemirror.net/demo/theme.html#cobalt to get more themes }, value='import something\n# Write your python code') put_code(code, language='python') # ..demo-only 文本框的显示效果为: +The results of the above example are as follows: + .. image:: /assets/codemirror_textarea.png :ref:`这里 ` 列举了一些常用的Codemirror选项,完整的Codemirror选项请见:https://codemirror.net/doc/manual.html#config -输入组 -^^^^^^^ +:ref:`Here ` are some commonly used Codemirror options. For complete Codemirror options, please visit: https://codemirror.net/doc/manual.html#config + +Input Group +^^^^^^^^^^^^^ PyWebIO支持输入组, 返回结果为一个字典。`pywebio.input.input_group()` 接受单项输入组成的列表作为参数, 返回以单项输入函数中的 ``name`` 作为键、以输入数据为值的字典: +PyWebIO uses input group to get multiple inputs in single form. `pywebio.input.input_group()` accepts a list of single input function call as parameter, and returns a dictionary with the ``name`` from the single input function as the key and the input data as the value: + + .. exportable-codeblock:: :name: input-group - :summary: 输入组 + :summary: Input Group - def check_age(p): # 检验函数校验通过时返回None,否则返回错误消息 # ..demo-only + def check_age(p): # ..demo-only if p < 10: # ..demo-only return 'Too young!!' # ..demo-only if p > 60: # ..demo-only @@ -147,21 +177,23 @@ PyWebIO支持输入组, 返回结果为一个字典。`pywebio.input.input_group 输入组中同样支持使用 ``validate`` 参数设置校验函数,其接受整个表单数据作为参数: +The input group also supports using ``validate`` parameter to set the validation function, which accepts the entire form data as parameter: + .. exportable-codeblock:: :name: input-group :summary: 输入组 - def check_age(p): # 检验函数校验通过时返回None,否则返回错误消息 # ..demo-only + def check_age(p): # single input item validation # ..demo-only if p < 10: # ..demo-only return 'Too young!!' # ..demo-only if p > 60: # ..demo-only return 'Too old!!' # ..demo-only # ..demo-only - def check_form(data): # 检验函数校验通过时返回None,否则返回 (input name,错误消息) + def check_form(data): # input group validation: return (input name, error msg) when validation error if len(data['name']) > 6: - return ('name', '名字太长!') + return ('name', 'Name too long!') if data['age'] <= 0: - return ('age', '年龄不能为负数!') + return ('age', 'Age can not be negative!') data = input_group("Basic info",[ # ..demo-only input('Input your name', name='name'), # ..demo-only @@ -173,59 +205,71 @@ PyWebIO支持输入组, 返回结果为一个字典。`pywebio.input.input_group PyWebIO 根据是否在输入函数中传入 ``name`` 参数来判断输入函数是在 `input_group` 中还是被单独调用。 所以当单独调用一个输入函数时, **不要** 设置 ``name`` 参数;而在 `input_group` 中调用输入函数时,需 **务必提供** ``name`` 参数 -输出 + PyWebIO determine whether the input function is in `input_group` or is called alone according to whether the ``name`` parameter is passed. So when calling an input function alone, **do not** set the ``name`` parameter; when calling the input function in `input_group`, you **must** provide the ``name`` parameter. + +Output ------------ 输出函数都定义在 :doc:`pywebio.output ` 模块中,可以使用 ``from pywebio.output import *`` 引入。 -调用输出函数后,内容会实时输出到浏览器,在应用的生命周期内,可以在任意时刻调用输出函数。 +The output functions are all defined in the :doc:`pywebio.output ` module and can be imported using ``from pywebio.output import *``. -基本输出 +When output functions is called, the content will be output to the browser in real time. The output functions can be called at any time during the application life cycle. + +Basic Output ^^^^^^^^^^^^^^ PyWebIO提供了一系列函数来输出表格、链接等格式: +PyWebIO provides a series of functions to output text, tables, links, etc: + .. exportable-codeblock:: :name: basic-output - :summary: 基本输出 + :summary: Basic Output - # 文本输出 + # Text Output put_text("Hello world!") ## ---- - # 表格输出 + # Table Output put_table([ - ['商品', '价格'], - ['苹果', '5.5'], - ['香蕉', '7'], + ['Commodity', 'Price'], + ['Apple', '5.5'], + ['Banana', '7'], ]) ## ---- - # Markdown输出 - put_markdown('~~删除线~~') + # Markdown Output + put_markdown('~~Strikethrough~~') ## ---- - # 文件输出 + # File Output put_file('hello_word.txt', b'hello word!') ## ---- - # 显示一个弹窗 + # PopUp Output popup('popup title', 'popup text content') PyWebIO提供的全部输出函数见 :doc:`pywebio.output ` 模块。另外,PyWebIO还支持一些第三方库来进行数据可视化,参见 :doc:`第三方库生态 ` 。 +For all output functions provided by PyWebIO, please refer to the :doc:`pywebio.output ` module. In addition, PyWebIO also supports data visualization with some third-party libraries, see :doc:`Third-party library ecology `. + .. _combine_output: -组合输出 -^^^^^^^^^^^^^^ +Combined Output(组合输出) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 函数名以 ``put_`` 开始的输出函数,可以与一些输出函数组合使用,作为最终输出的一部分: +The output function whose function name starts with ``put_`` can be combined with some output functions as part of the final output: + `put_table() ` 支持以 ``put_xxx()`` 调用作为单元格内容: +You can pass ``put_xxx()`` calls to `put_table() ` as cell content: + .. exportable-codeblock:: :name: putxxx - :summary: 组合输出 + :summary: Combined output put_table([ ['Type', 'Content'], @@ -240,17 +284,21 @@ PyWebIO提供的全部输出函数见 :doc:`pywebio.output ` 模块。 上例显示效果如下: +The results of the above example are as follows: + .. image:: /assets/put_table.png 类似地, `popup() ` 也可以将 ``put_xxx()`` 调用作为弹窗内容: +Similarly, you can pass ``put_xxx()`` calls to `popup() ` as the popup content: + .. exportable-codeblock:: :name: popup - :summary: 弹窗 + :summary: Popup popup('Popup title', [ put_html('

Popup Content

'), - 'plain html:
', # 等价于 put_text('plain html:
') + 'plain html:
', # Equivalent to: put_text('plain html:
') put_table([['A', 'B'], ['C', 'D']]), put_buttons(['close_popup()'], onclick=lambda _: close_popup()) ]) @@ -258,40 +306,48 @@ PyWebIO提供的全部输出函数见 :doc:`pywebio.output ` 模块。 其他接受 ``put_xxx()`` 调用作为参数的输出函数还有 `put_collapse() ` 、 `put_scrollable() ` 、`put_row() ` 等, 此外,还可以通过 `put_widget() ` 自定义可接收 ``put_xxx()`` 调用的输出组件,具体用法请参考函数文档。 +Other output functions that accept ``put_xxx()`` calls as parameters are `put_collapse() `, `put_scrollable() `, `put_row() `, etc. In addition, you can use `put_widget() ` to make your own output widgets that can accept ``put_xxx()`` calls. For more information, please refer to corresponding function documentation. + 使用组合输出时,如果想在内容输出后,对其中的 ``put_xxx()`` 子项进行动态修改,可以使用 `output() ` 函数, `output() ` 就像一个占位符,它可以像 ``put_xxx()`` 一样传入 `put_table` 、 `popup` 、 `put_widget` 等函数中作为输出的一部分, 并且,在输出后,还可以对其中的内容进行修改(比如重置或增加内容): +When using combined output, if you want to dynamically update the ``put_xxx()`` content after it has been output, you can use the `output() ` function. `output() ` is like a placeholder, it can be passed in anywhere that ``put_xxx()`` can passed in. And after being output, the content can also be modified: + .. exportable-codeblock:: :name: output - :summary: 内容占位符——`output()` + :summary: Output placeholder——`output()` hobby = output(put_text('Coding')) put_table([ ['Name', 'Hobbies'], - ['Wang', hobby] # hobby 初始为 Coding + ['Wang', hobby] # hobby is initialized to Coding ]) ## ---- - hobby.reset(put_text('Movie')) # hobby 被重置为 Movie + hobby.reset(put_text('Movie')) # hobby is reset to Movie ## ---- - hobby.append(put_text('Music'), put_text('Drama')) # 向 hobby 追加 Music, Drama + hobby.append(put_text('Music'), put_text('Drama')) # append Music, Drama to hobby ## ---- - hobby.insert(0, put_markdown('**Coding**')) # 将 Coding 插入 hobby 顶端 + hobby.insert(0, put_markdown('**Coding**')) # insert the Coding into the top of the hobby -事件回调 +Callback ^^^^^^^^^^^^^^ 从上面可以看出,PyWebIO把交互分成了输入和输出两部分:输入函数为阻塞式调用,会在用户浏览器上显示一个表单,在用户提交表单之前输入函数将不会返回;输出函数将内容实时输出至浏览器。这种交互方式和控制台程序是一致的,因此PyWebIO应用非常适合使用控制台程序的编写逻辑来进行开发。 +As we can see from the above, PyWebIO divides the interaction into two parts: input and output. The input function is blocking, a form will be displayed on the user's web browser when calling input function, the input function will not return util the user submits the form. The output function is used to output content to the browser in real time. This input and output behavior is consistent with the console program. That's why we say PyWebIO turning the browser into a "rich text terminal". So you can write PyWebIO applications in script programing way. + 此外,PyWebIO还支持事件回调:PyWebIO允许你输出一些控件,当控件被点击时执行提供的回调函数。 -下面是一个例子: +In addition, PyWebIO also supports event callbacks: PyWebIO allows you to output some buttons and the provided callback function will be executed when button is clicked. + +This is an example: .. exportable-codeblock:: :name: onclick-callback - :summary: 事件回调 + :summary: Event callback from functools import partial @@ -307,10 +363,14 @@ PyWebIO提供的全部输出函数见 :doc:`pywebio.output ` 模块。 `put_table() ` 的调用不会阻塞。当用户点击了某行中的按钮时,PyWebIO会自动调用相应的回调函数: +The call to `put_table() ` will not block. When user clicks a button, the corresponding callback function will be called: + .. image:: /assets/table_onclick.* 当然,PyWebIO还支持单独的按钮控件: +PyWebIO also supports output button alone: + .. exportable-codeblock:: :name: put-buttons :summary: 按钮控件 @@ -322,33 +382,45 @@ PyWebIO提供的全部输出函数见 :doc:`pywebio.output ` 模块。 .. note:: 在PyWebIO会话(关于会话的概念见下文 :ref:`Server与script模式 ` )结束后,事件回调也将不起作用,你可以在任务函数末尾处使用 :func:`pywebio.session.hold()` 函数来将会话保持,这样在用户关闭浏览器页面前,事件回调将一直可用。 -输出域Scope + After the PyWebIO session (see :ref:`Server and script mode ` for more information about session) closed, the event callback will not work. You can call the :func:`pywebio.session.hold()` function at the end of the task function to hold the session, so that the event callback will always be available before the browser page is closed by user. + +Output Scope ^^^^^^^^^^^^^^ PyWebIO使用Scope模型来对内容输出的位置进行灵活地控制,PyWebIO的内容输出区可以划分出不同的输出域,PyWebIO将输出域称作 `Scope` 。 +PyWebIO uses the scope model to give more control to the location of content output. The output area of PyWebIO can be divided into different output domains. The output domain is called Scope in PyWebIO. + 输出域为输出内容的容器,各个输出域之间上下排列,输出域也可以进行嵌套。 +The output domain is a container for output content, and each output domain is arranged vertically, and the output domains can also be nested. + 每个输出函数(函数名形如 `put_xxx()` )都会将内容输出到一个Scope,默认为"当前Scope","当前Scope"由运行时上下文确定,输出函数也可以手动指定输出到的Scope。Scope名在会话内唯一。 +Each output function (function name like ``put_xxx()``) will output the content to a scope, the default is "current scope". "current scope" is determined by the runtime context. The output function can also manually specify the scope to be output to. The scope name is unique within the session. + .. _use_scope: **use_scope()** 可以使用 `use_scope() ` 开启并进入一个新的输出域,或进入一个已经存在的输出域: +You can use `use_scope() ` to open and enter a new output scope, or enter an existing output scope: + .. exportable-codeblock:: :name: use-scope - :summary: 使用`use_scope()`创建或进入输出域 + :summary: use `use_scope()` to open or enter scope - with use_scope('scope1'): # 创建并进入scope 'scope1' + with use_scope('scope1'): # open and enter a new output: 'scope1' put_text('text1 in scope1') put_text('text in parent scope of scope1') - with use_scope('scope1'): # 进入之前创建的scope 'scope1' + with use_scope('scope1'): # enter an existing output scope: 'scope1' put_text('text2 in scope1') -以上代码将会输出:: +以上代码将会输出: + +The results of the above code are as follows:: text1 in scope1 text2 in scope1 @@ -356,9 +428,11 @@ PyWebIO使用Scope模型来对内容输出的位置进行灵活地控制,PyWeb `use_scope() ` 还可以使用 `clear` 参数将scope中原有的内容清空: +You can use ``clear`` parameter in `use_scope() ` to clear the previous content in the scope: + .. exportable-codeblock:: :name: use-scope - :summary: 使用`use_scope()`清空输出域内容 + :summary: `use_scope()`'s `clear` parameter with use_scope('scope2'): put_text('create scope2') @@ -366,19 +440,23 @@ PyWebIO使用Scope模型来对内容输出的位置进行灵活地控制,PyWeb put_text('text in parent scope of scope2') ## ---- - with use_scope('scope2', clear=True): # 进入之前创建的scope2,并清空原有内容 + with use_scope('scope2', clear=True): # enter an existing output scope and clear the original content put_text('text in scope2') -以上代码将会输出:: +以上代码将会输出: + +The results of the above code are as follows:: text in scope2 text in parent scope of scope2 `use_scope() ` 还可以作为装饰器来使用: +`use_scope() ` can also be used as a decorator: + .. exportable-codeblock:: :name: use-scope-decorator - :summary: `use_scope()`作为装饰器来使用 + :summary: `use_scope()` as decorator import time # ..demo-only from datetime import datetime @@ -393,14 +471,20 @@ PyWebIO使用Scope模型来对内容输出的位置进行灵活地控制,PyWeb 第一次调用 ``show_time`` 时,将会在当前位置创建 ``time`` 输出域并在其中输出当前时间,之后每次调用 ``show_time()`` ,时间都会输出到相同的区域。 +When calling ``show_time()`` for the first time, a ``time`` scope will be created at the current position and the current time will be output to it, and then every time the ``show_time()`` is called, the time will be output to the same area. + Scope是可嵌套的,初始条件下,PyWebIO应用只有一个最顶层的 ``ROOT`` Scope。每创建一个新Scope,Scope的嵌套层级便会多加一层,每退出当前Scope,Scope的嵌套层级便会减少一层。 PyWebIO使用Scope栈来保存运行时的Scope的嵌套层级。 +Scopes can be nested. At the beginning, PyWebIO applications have only one ``ROOT`` Scope. Each time a new scope is created, the nesting level of the scope will increase by one level, and each time the current scope is exited, the nesting level of the scope will be reduced by one. PyWebIO uses the Scope stack to save the nesting level of scope at runtime. + 例如,如下代码将会创建3个Scope: +For example, the following code will create 3 scopes: + .. exportable-codeblock:: :name: use-scope-nested - :summary: 嵌套Scope + :summary: Nested Scope with use_scope('A'): put_text('Text in scope A') @@ -420,7 +504,9 @@ PyWebIO使用Scope栈来保存运行时的Scope的嵌套层级。 put_buttons([('Put text to %s' % i, i) for i in ('A', 'B', 'C')], lambda s: put_text(s, scope=s)) # ..demo-only -以上代码将会产生如下Scope布局:: +以上代码将会产生如下Scope布局: + +The above code will make the following Scope layout:: ┌─ROOT────────────────────┐ │ │ @@ -438,23 +524,29 @@ PyWebIO使用Scope栈来保存运行时的Scope的嵌套层级。 .. _scope_param: -**输出函数的scope相关参数** +**Scope related parameters of output function** 输出函数(函数名形如 ``put_xxx()`` )在默认情况下,会将内容输出到"当前Scope",可以通过 ``use_scope()`` 设置运行时上下文的"当前Scope"。 +The output function (function name like ``put_xxx()``) will output the content to the "current scope" by default, and the "current scope" of the runtime context can be set by use_scope(). + 此外,也可以通过输出函数的 ``scope`` 参数指定输出的目的Scope: +In addition, you can use the ``scope`` parameter of the output function to specify the destination scope to output: + .. exportable-codeblock:: :name: put-xxx-scope - :summary: 输出函数的`scope`参数 + :summary: ``scope`` parameter of the output function with use_scope('scope3'): - put_text('text1 in scope3') # 输出到当前Scope:scope3 - put_text('text in ROOT scope', scope='ROOT') # 输出到ROOT Scope + put_text('text1 in scope3') # output to scope3 + put_text('text in ROOT scope', scope='ROOT') # output to ROOT Scope - put_text('text2 in scope3', scope='scope3') # 输出到scope3 + put_text('text2 in scope3', scope='scope3') # output to scope3 -以上将会输出:: +以上将会输出: + +The results of the above code are as follows:: text1 in scope3 text2 in scope3 @@ -462,77 +554,99 @@ PyWebIO使用Scope栈来保存运行时的Scope的嵌套层级。 ``scope`` 参数除了直接指定目标Scope名,还可以使用一个整形通过索引Scope栈来确定Scope:0表示最顶层也就是ROOT Scope,-1表示当前Scope,-2表示进入当前Scope前所使用的Scope,...... +In addition to directly specifying the target scope name, the ``scope`` parameter can also accept an integer to determine the scope by indexing the scope stack: 0 means the top level scope(the ROOT Scope), -1 means the current Scope, -2 means the scope used before entering the current scope, ... + 默认条件下,在同一Scope中的输出内容,会根据输出函数的调用顺序从上往下排列,最后调用的输出函数会输出内容到目标Scope的底部。通过输出函数的 ``position`` 参数可以将输出内容插入到目标Scope的其他位置。 +By default, the output content in the same scope will be arranged from top to bottom according to the calling order of the output function, and the output function called last will output the content to the bottom of the target scope. The output content can be inserted into other positions of the target scope by using the ``position`` parameter of the output function. + 一个Scope中各次输出的元素具有像数组一样的索引,最前面的编号为0,以此往后递增加一;同样可以使用负数对Scope中的元素进行索引,-1表示最后面的元素,-2表示次后面的元素...... +Each output element in a scope has an index like Python list, the first element's index is 0, and the next element's index is incremented by one. You can also use a negative number to index the elements in the scope, -1 means the last element, -2 means the element before the last... + ``position`` 参数类型为整形, ``position>=0`` 时表示输出内容到目标Scope的第position号元素的前面; ``position<0`` 时表示输出内容到目标Scope第position号元素之后: +The ``position`` parameter is integer. When ``position>=0``, it means to insert content before the element whose index equal ``position``; when ``position<0``, it means to insert content after the element whose index equal ``position``: + .. exportable-codeblock:: :name: put-xxx-position - :summary: 输出函数的`position`参数 + :summary: `position` parameter of the output function with use_scope('scope1'): - put_text('A') # 输出内容: A + put_text('A') ## ---- with use_scope('scope1'): # ..demo-only - put_text('B', position=0) # 输出内容: B A + put_text('B', position=0) # insert B before A -> B A ## ---- with use_scope('scope1'): # ..demo-only - put_text('C', position=-2) # 输出内容: B C A + put_text('C', position=-2) # insert C after B -> B C A ## ---- with use_scope('scope1'): # ..demo-only - put_text('D', position=1) # 输出内容: B D C A + put_text('D', position=1) # insert D before C B -> B D C A -**输出域控制函数** +**Scope control** 除了 `use_scope()` , PyWebIO同样提供了以下scope控制函数: -* `set_scope(name) ` : 在当前位置(或指定位置)创建scope -* `clear(scope) ` : 清除scope的内容 -* `remove(scope) ` : 移除scope -* `scroll_to(scope) ` : 将页面滚动到scope处 +In addition to `use_scope() `, PyWebIO also provides the following scope control functions: +* `set_scope(name) ` : Create scope at current location(or specified location) +* `clear(scope) ` : Clear the contents of the scope +* `remove(scope) ` : Remove scope +* `scroll_to(scope) ` : Scroll the page to the scope -页面环境设置 -^^^^^^^^^^^^^^ -**页面标题** +Page environment settings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -调用 `set_env(title=...) ` 可以设置页面标题。 +**Page Title** -**自动滚动** +You can call `set_env(title=...) ` to set the page title。 + +**Auto Scroll** 在进行一些持续性的输出时(比如日志输出),有时希望在有新输出后自动将页面滚动到最下方,这时可以调用 `set_env(auto_scroll_bottom=True) ` 来开启自动滚动。 注意,开启后,只有输出到ROOT Scope才可以触发自动滚动。 -**输出动画** +When performing some continuous output (such as log output), you may want to automatically scroll the page to the bottom when there is new output. You can call `set_env(auto_scroll_bottom=True) ` to enable automatic scrolling. Note that after enabled, only outputting to ROOT scope can trigger automatic scrolling. + +**Output Animation** PyWebIO在输出内容时默认会使用淡入的动画效果来显示内容,可使用 `set_env(output_animation=False) ` 来关闭动画。 +PyWebIO will use the fade-in animation effect to display the content by default. You can use `set_env(output_animation=False) ` to turn off the animation. + 有关不同环境配置的效果可查看 :demo_host:`set_env Demo ` -布局 +For the effects of different environment settings, please see :demo_host:`set_env Demo ` + +Layout ^^^^^^^^^^^^^^ 一般情况下,使用上文介绍的各种输出函数足以完成各种内容的展示,但直接调用输出函数产生的输出之间都是竖直排列的,如果想实现更复杂的布局(比如在页面左侧显示一个代码块,在右侧显示一个图像),就需要借助布局函数。 +In general, using the various output functions introduced above to output all kinds of content is enough, but these outputs are arranged vertically. If you want to make a more complex layout (such as displaying a code block on the left side of the page and an image on the right left), you need to use layout functions. + ``pywebio.output`` 模块提供了3个布局函数,通过对他们进行组合可以完成各种复杂的布局: -* `put_row() ` : 使用行布局输出内容. 内容在水平方向上排列 -* `put_column() ` : 使用列布局输出内容. 内容在竖直方向上排列 -* `put_grid() ` : 使用网格布局输出内容 +The ``pywebio.output`` module provides three layout functions, and you can make complex layouts by combining them: + +* `put_row() ` : 使用行布局输出内容. 内容在水平方向上排列 Use row layout to output content. The content is arranged horizontally +* `put_column() ` : 使用列布局输出内容. 内容在竖直方向上排列 Use column layout to output content. The content is arranged vertically +* `put_grid() ` : 使用网格布局输出内容 Output content using grid layout 通过组合 ``put_row()`` 和 ``put_column()`` 可以实现灵活布局: +Here is a layout example by combining ``put_row()`` and ``put_column()``: + .. exportable-codeblock:: :name: put-row-column - :summary: 布局函数 + :summary: Layout functions put_row([ put_column([ put_code('A'), put_row([ - put_code('B1'), None, # None 表示输出之间的空白 + put_code('B1'), None, # None represents the space between the output put_code('B2'), None, put_code('B3'), ]), @@ -544,24 +658,34 @@ PyWebIO在输出内容时默认会使用淡入的动画效果来显示内容, 显示效果如下: +The results of the above example are as follows: + .. image:: /assets/layout.png :align: center -布局函数还支持自定义各部分的尺寸:: +布局函数还支持自定义各部分的尺寸: + +The layout function also supports customizing the size of each part:: - put_row([put_image(...), put_image(...)], size='40% 60%') # 左右两图宽度比2:3 + put_row([put_image(...), put_image(...)], size='40% 60%') # The ratio of the width of two images is 2:3 更多布局函数的用法及代码示例请查阅 :ref:`布局函数文档 ` . -样式 +For more information, please refer to the :ref:`layout function documentation `. + +Style ^^^^^^^^^^^^^^ 如果你熟悉 `CSS样式 `_ ,你还可以使用 `style() ` 函数给输出设定自定义样式。 +If you are familiar with `CSS `_ styles, you can use the `style() ` function to set a custom style for the output. + 可以给单个的 ``put_xxx()`` 输出设定CSS样式,也可以配合组合输出使用: +You can set the CSS style for a single ``put_xxx()`` output: + .. exportable-codeblock:: :name: style - :summary: 输出样式 + :summary: style of output style(put_text('Red'), 'color: red') @@ -573,9 +697,11 @@ PyWebIO在输出内容时默认会使用淡入的动画效果来显示内容, ``style()`` 也接受列表作为输入,``style()`` 会为列表的每一项都设置CSS样式,返回值可以直接输出,可用于任何接受 ``put_xxx()`` 列表的地方: +`style() ` also accepts a list of output calls, `style() ` will set the CSS style for each item in the list: + .. exportable-codeblock:: :name: style-list - :summary: 批量设置输出样式 + :summary: style a list of output style([ put_text('Red'), @@ -591,18 +717,24 @@ PyWebIO在输出内容时默认会使用淡入的动画效果来显示内容, .. _server_and_script_mode: -Server模式与Script模式 +Server mode and Script mode ------------------------------------ 在 :ref:`Hello, world ` 一节中,已经知道,PyWebIO支持在普通的脚本中调用和使用 `start_server() ` 启动一个Web服务两种模式。 -**Server模式** +In the :ref:`Hello, world ` section, we already know that PyWebIO supports two modes of running as a script and using `start_server() ` to run as a web service. + +**Server mode** 在Server模式下,PyWebIO会启动一个Web服务来持续性地提供服务。需要提供一个任务函数(类似于Web开发中的视图函数),当用户访问服务地址时,PyWebIO会开启一个新会话并运行任务函数。 +In Server mode, PyWebIO will start a web server to continuously provide services. A task function (similar to the view function in Flask) needs to be provided. When the user accesses the service address, PyWebIO will open a new session and run the task function. + 使用 `start_server() ` 来启动PyWebIO的Server模式, `start_server() ` 除了接收一个函数作为任务函数外, -还支持传入函数列表或字典,从而使一个PyWebIO Server下可以有多个不同功能的服务,服务之间可以通过 `go_app() ` 或 `put_link() ` 进行跳转:: +还支持传入函数列表或字典,从而使一个PyWebIO Server下可以有多个不同功能的服务,服务之间可以通过 `go_app() ` 或 `put_link() ` 进行跳转 + +Use `start_server() ` to start a web service. In addition to accepting a function as task function, ``start_server()`` also accepts a list of task function or a dictionary of it, so that a PyWebIO Server can have multiple services with different functions. You can use `go_app() ` or `put_link() ` to jump between services:: def task_1(): put_text('task_1') @@ -615,46 +747,60 @@ Server模式与Script模式 hold() def index(): - put_link('Go task 1', app='task_1') # 使用app参数指定任务名 + put_link('Go task 1', app='task_1') # Use `app` parameter to specify the task name put_link('Go task 2', app='task_2') - start_server([index, task_1, task_2]) # 或 start_server({'index': index, 'task_1': task_1, 'task_2': task_2}) + start_server([index, task_1, task_2]) # or start_server({'index': index, 'task_1': task_1, 'task_2': task_2}) For more information, please refer to the function documentation. .. attention:: - 注意,在Server模式下,仅能在任务函数上下文中对PyWebIO的交互函数进行调用。比如如下调用是 **不被允许的** :: + 注意,在Server模式下,仅能在任务函数上下文中对PyWebIO的交互函数进行调用。比如如下调用是 **不被允许的** + + Note that in Server mode, PyWebIO's input and output functions can only be called in the context of task functions. For example, the following code is not allowed:: import pywebio from pywebio.input import input - port = input('Input port number:') # ❌ 在任务函数上下文之外调用了PyWebIO交互函数!! + port = input('Input port number:') # ❌ error pywebio.start_server(my_task_func, port=int(port)) -**Script模式** +**Script mode** Script模式下,在任何位置都可以调用PyWebIO的交互函数。 +In Script mode, PyWebIO input and output functions can be called anywhere. + 如果用户在会话结束之前关闭了浏览器,那么之后会话内对于PyWebIO交互函数的调用将会引发一个 `SessionException ` 异常。 +If the user closes the browser before the end of the session, then calls to PyWebIO input and output functions in the session will cause a `SessionException ` exception. + .. _thread_in_server_mode: -并发 +Concurrent ^^^^^^^^^^^^^^ PyWebIO 支持在多线程环境中使用。 -**Script模式** +PyWebIO can be used in a multi-threading environment. + +**Script mode** 在 Script模式下,你可以自由地启动线程,并在其中调用PyWebIO的交互函数。当所有非 `Daemon线程 `_ 运行结束后,脚本退出。 -**Server模式** +In Script mode, you can freely start new thread and call PyWebIO interactive functions in it. When all `non-daemonic `_ threads finish running, the script exits. + +**Server mode** Server模式下,如果需要在新创建的线程中使用PyWebIO的交互函数,需要手动调用 `register_thread(thread) ` 对新进程进行注册(这样PyWebIO才能知道新创建的线程属于哪个会话)。 如果新创建的线程中没有使用到PyWebIO的交互函数,则无需注册。没有使用 `register_thread(thread) ` 注册的线程不受会话管理,其调用PyWebIO的交互函数将会产生 `SessionNotFoundException ` 异常。 当会话的任务函数和会话内通过 `register_thread(thread) ` 注册的线程都结束运行时,会话关闭。 -Server模式下多线程的使用示例:: +In Server mode, if you need to use PyWebIO interactive functions in new thread, you need to use `register_thread(thread) ` to register the new thread (so that PyWebIO can know which session the thread belongs to). If the PyWebIO interactive function is not used in the new thread, no registration is required. Threads that are not registered with `register_thread(thread) ` calling PyWebIO's interactive functions will cause `SessionNotFoundException `. When both the task function of the session and the thread registered through `register_thread(thread) ` in the session have finished running, the session is closed. + +Server模式下多线程的使用示例: + +Example of using multi-threading in Server mode:: def show_time(): while True: @@ -666,9 +812,9 @@ Server模式下多线程的使用示例:: t = threading.Thread(target=show_time) register_thread(t) put_markdown('## Clock') - t.start() # 在后台运行show_time() + t.start() # run `show_time()` in background - # ❌ 没有使用register_thread注册的线程调用PyWebIO交互函数会产生异常 + # ❌ this thread will cause `SessionNotFoundException` threading.Thread(target=show_time).start() put_text('Background task started.') @@ -679,36 +825,48 @@ Server模式下多线程的使用示例:: .. _session_close: -会话的结束 -^^^^^^^^^^^^^^ +Close of session +^^^^^^^^^^^^^^^^^ 会话还会因为用户的关闭浏览器而结束,这时当前会话内还未返回的PyWebIO输入函数调用将抛出 `SessionClosedException ` 异常,之后对于PyWebIO交互函数的调用将会产生 `SessionNotFoundException ` 或 `SessionClosedException ` 异常。 +The session will also close because the user closes the browser page. After the browser page closed, PyWebIO input function calls that have not yet returned in the current session will cause `SessionClosedException `, and subsequent calls to PyWebIO interactive functions will cause `SessionNotFoundException ` or `SessionClosedException `. + 可以使用 `defer_call(func) ` 来设置会话结束时需要调用的函数。无论是因为用户主动关闭页面还是任务结束使得会话关闭,设置的函数都会被执行。 `defer_call(func) ` 可以用于资源清理等工作。在会话中可以多次调用 `defer_call() ` ,会话结束后将会顺序执行设置的函数。 +You can use `defer_call(func) ` to set the function to be called when the session closes. Whether it is because the user closes the page or the task finishes to cause session closed, the function set by `defer_call(func) ` will be executed. `defer_call(func) ` can be used for resource cleaning. You can call `defer_call(func) ` multiple times in the session, and the set functions will be executed sequentially after the session closes. -与Web框架集成 ---------------- +Integration with web framework +--------------------------------- .. _integration_web_framework: 可以将PyWebIO应用集成到现有的Python Web项目中,PyWebIO应用与Web项目共用一个Web框架。目前支持与Flask、Tornado、Django和aiohttp Web框架的集成。 +The PyWebIO application can be integrated into an existing Python Web project, and the PyWebIO application and the Web project share a web framework. PyWebIO currently supports integration with Flask, Tornado, Django and aiohttp web frameworks. + 与Web框架集成需要完成两部分配置:托管PyWebIO前端静态文件;暴露PyWebIO后端接口。这其中需要注意前端页面和后端接口的路径约定, 以及前端静态文件与后端接口分开部署时因为跨域而需要的特别设置。 -集成方法 -^^^^^^^^^^^ +Integration with the web framework basically requires two steps: hosting the PyWebIO frontend static files; exposing the PyWebIO backend API. + +Integration method +^^^^^^^^^^^^^^^^^^^^^ 不同Web框架的集成方法如下: +The integration methods of different web frameworks are as follows: + .. tabs:: .. tab:: Tornado 需要在Tornado应用中引入两个 ``RequestHandler`` , - 一个 ``RequestHandler`` 用来提供前端静态文件,另一个 ``RequestHandler`` 用来和浏览器进行WebSocket通讯:: + 一个 ``RequestHandler`` 用来提供前端静态文件,另一个 ``RequestHandler`` 用来和浏览器进行WebSocket通讯 + + Need to add two ``RequestHandler`` to Tornado application, + One ``RequestHandler`` is used to serve frontend static files, and the other ``RequestHandler`` is the backend API which is used to communicate with the browser through WebSocket:: import tornado.ioloop import tornado.web @@ -722,9 +880,9 @@ Server模式下多线程的使用示例:: if __name__ == "__main__": application = tornado.web.Application([ (r"/", MainHandler), - (r"/tool/io", webio_handler(task_func)), # task_func 为使用PyWebIO编写的任务函数 + (r"/tool/io", webio_handler(task_func)), # `task_func` is PyWebIO task function (r"/tool/(.*)", tornado.web.StaticFileHandler, - {"path": STATIC_PATH, 'default_filename': 'index.html'}) # 前端静态文件托管 + {"path": STATIC_PATH, 'default_filename': 'index.html'}) # static files serving ]) application.listen(port=80, address='localhost') tornado.ioloop.IOLoop.current().start() @@ -733,14 +891,20 @@ Server模式下多线程的使用示例:: 并将其绑定在 ``/tool/io`` 路径下;同时将PyWebIO的静态文件使用 `tornado.web.StaticFileHandler `_ 托管到 ``/tool/(.*)`` 路径下。 启动Tornado服务器后,访问 ``http://localhost/tool/`` 即可打开PyWebIO应用 + In above code, we use `webio_handler(task_func) ` to get the Tornado `WebSocketHandler `_ that communicates with the browser, and bind it to the ``/tool/io`` path. PyWebIO static files are hosted to ``/tool/(.*)`` by using `tornado.web.StaticFileHandler `_ . After starting the Tornado server, you can visit ``http://localhost/tool/`` to open the PyWebIO application. + .. attention:: 当使用Tornado后端时,PyWebIO使用WebSocket协议和浏览器进行通讯,如果你的Tornado应用处在反向代理(比如Nginx)之后, 可能需要特别配置反向代理来支持WebSocket协议,:ref:`这里 ` 有一个Nginx配置WebSocket的例子。 + PyWebIO uses the WebSocket protocol to communicate with the browser in Tornado. If your Tornado application is behind a reverse proxy (such as Nginx), you may need to configure the reverse proxy to support the WebSocket protocol. :ref:`Here ` is an example of Nginx WebSocket configuration. + .. tab:: Flask - 需要添加两个PyWebIO相关的路由:一个用来提供前端静态文件,另一个用来和浏览器进行Http通讯:: + 需要添加两个PyWebIO相关的路由:一个用来提供前端静态文件,另一个用来和浏览器进行Http通讯 + + Need to add two routes: one is used to host frontend static files, and the other is used to communicate with the browser through Http:: from pywebio.platform.flask import webio_view from pywebio import STATIC_PATH @@ -748,14 +912,14 @@ Server模式下多线程的使用示例:: app = Flask(__name__) - # task_func 为使用PyWebIO编写的任务函数 + # `task_func` is PyWebIO task function app.add_url_rule('/io', 'webio_view', webio_view(task_func), - methods=['GET', 'POST', 'OPTIONS']) # 接口需要能接收GET、POST和OPTIONS请求 + methods=['GET', 'POST', 'OPTIONS']) # need GET,POST and OPTIONS methods @app.route('/') @app.route('/') def serve_static_file(static_file='index.html'): - """前端静态文件托管""" + """host frontend static files""" return send_from_directory(STATIC_PATH, static_file) app.run(host='localhost', port=80) @@ -764,9 +928,13 @@ Server模式下多线程的使用示例:: 并调用 `Flask.add_url_rule `_ 将其绑定在 ``/io`` 路径下;同时编写视图函数 ``serve_static_file`` 将PyWebIO使用的静态文件托管到 ``/`` 路径下。 启动Flask应用后,访问 ``http://localhost/`` 即可打开PyWebIO应用 + In above code, we use `webio_view(task_func) ` to get the Flask view of the PyWebIO application, and use `Flask.add_url_rule `_ to bind it to ``/io`` path. The view function ``serve_static_file`` is used to host the static files used by PyWebIO and is bind to ``/`` path. After starting the Flask application, visit ``http://localhost/`` to open the PyWebIO application. + .. tab:: Django - 在django的路由配置文件 ``urls.py`` 中加入PyWebIO相关的路由即可:: + 在django的路由配置文件 ``urls.py`` 中加入PyWebIO相关的路由即可 + + Need to add two routes in ``urls.py``:: # urls.py @@ -776,93 +944,129 @@ Server模式下多线程的使用示例:: from pywebio import STATIC_PATH from pywebio.platform.django import webio_view - # task_func 为使用PyWebIO编写的任务函数 + # `task_func` is PyWebIO task function webio_view_func = webio_view(task_func) urlpatterns = [ - path(r"io", webio_view_func), # http通信接口 - path(r'', partial(serve, path='index.html'), {'document_root': STATIC_PATH}), # 前端index.html文件托管 - path(r'', serve, {'document_root': STATIC_PATH}), # 前端其他文件托管 + path(r"io", webio_view_func), # backend API + path(r'', partial(serve, path='index.html'), {'document_root': STATIC_PATH}), # host index.html file + path(r'', serve, {'document_root': STATIC_PATH}), # host other static files ] 需要添加3条路由规则,第一条路由规则将PyWebIO应用的视图函数绑定到 ``/io`` 路径下,第二条路由用于提供PyWebIO的前端index.html文件,最后一个路由用于提供PyWebIO的其他静态文件 + Three routing rules need to be added. The first routing rule binds the view function of the PyWebIO application to the ``/io`` path, the second route is used to host the frontend ``index.html`` file of PyWebIO, and the last route is used to host other PyWebIO static files. + 启动Django应用后,访问 ``http://localhost/`` 即可打开PyWebIO应用 + After starting the Django server, visit ``http://localhost/`` to open the PyWebIO application + .. tab:: aiohttp - 添加两个PyWebIO相关的路由:一个用来提供前端静态文件,另一个用来和浏览器进行WebSocket通讯:: + 添加两个PyWebIO相关的路由:一个用来提供前端静态文件,另一个用来和浏览器进行WebSocket通讯 + + Need to add two routes: one is used to host frontend static files, and the other is used to communicate with the browser through WebSocket::: from aiohttp import web from pywebio.platform.aiohttp import static_routes, webio_handler app = web.Application() - # task_func 为使用PyWebIO编写的任务函数 - app.add_routes([web.get('/io', webio_handler(task_func))]) # websocket通信接口 - app.add_routes(static_routes('/')) # 前端静态文件托管 + # `task_func` is PyWebIO task function + app.add_routes([web.get('/io', webio_handler(task_func))]) # backend API + app.add_routes(static_routes('/')) # host static files web.run_app(app, host='localhost', port=80) 启动aiohttp应用后,访问 ``http://localhost/`` 即可打开PyWebIO应用 + After starting the aiohttp server, visit ``http://localhost/`` to open the PyWebIO application + .. attention:: 当使用aiohttp后端时,PyWebIO使用WebSocket协议和浏览器进行通讯,如果你的aiohttp应用处在反向代理(比如Nginx)之后, 可能需要特别配置反向代理来支持WebSocket协议,:ref:`这里 ` 有一个Nginx配置WebSocket的例子。 + PyWebIO uses the WebSocket protocol to communicate with the browser in aiohttp. If your aiohttp server is behind a reverse proxy (such as Nginx), you may need to configure the reverse proxy to support the WebSocket protocol. :ref:`Here ` is an example of Nginx WebSocket configuration. + .. _integration_web_framework_note: -注意事项 +Notes ^^^^^^^^^^^ -**PyWebIO静态资源的托管** +**Static resources Hosting** 在开发阶段,使用后端框架提供的静态文件服务对于开发和调试都十分方便,上文的与Web框架集成的示例代码也都是使用了后端框架提供的静态文件服务。 但出于性能考虑,托管静态文件最好的方式是使用 `反向代理 `_ (比如 `nginx `_ ) 或者 `CDN `_ 服务。 -**前端页面和后端接口的路径约定** +Using the web framework to serve static files is very convenient for development and debugging (Just like the above code). But for performance reasons, the best way to host static files is to use a `reverse proxy `_ (such as `nginx `_) or `CDN `_ service. + +**前端页面和后端接口的路径约定 Path conventions for frontend pages and backend interfaces** PyWebIO默认通过当前页面的同级的 ``./io`` API与后端进行通讯。 +By default, PyWebIO uses ``./io`` API of the current page to communicates with the backend. + 例如你将PyWebIO静态文件托管到 ``/A/B/C/(.*)`` 路径下,那么你需要将PyWebIO API的路由绑定到 ``/A/B/C/io`` 处; 你也可以在PyWebIO应用的地址中添加 ``pywebio_api`` url参数来指定PyWebIO后端API地址, 例如 ``/A/B/C/?pywebio_api=/D/pywebio`` 将PyWebIO后端API地址设置到了 ``/D/pywebio`` 处。 +For example, if you host PyWebIO static files under the path ``/A/B/C/(.*)``, then you need to bind the route of the PyWebIO backend API to ``/A/B/C/io``. You can also use the ``pywebio_api`` url parameter in page to specify the PyWebIO backend API address, for example, ``/A/B/C/?pywebio_api=/D/pywebio`` sets the PyWebIO backend API address to ``/D/pywebio``. + ``pywebio_api`` 参数可以使用相对地址、绝对地址,也可以指定其他服务器。 +The ``pywebio_api`` parameter can use a relative address, absolute address or other host. + .. caution:: 需要注意 ``pywebio_api`` 参数的格式: + Pay attention to the format of the ``pywebio_api`` url parameter: + * 相对地址可以为 ``./xxx/xxx`` 或 ``xxx/xxx`` 的相对地址格式。 + The relative address can be in the format of ``./xxx/xxx`` or ``xxx/xxx``. * 绝对地址以 ``/`` 开头,比如 ``/aaa/bbb`` . + The absolute address starts with ``/``, such as ``/aaa/bbb``. * 指定其他服务器需要使用完整格式: ``http://example.com:5000/aaa/io`` 、 ``ws://example.com:8080/bbb/ws_io`` ,或者省略协议字段: ``//example.com:8080/aaa/io`` 。省略协议字段时,PyWebIO根据当前页面的协议确定要使用的协议: 若当前页面为http协议,则后端接口自动选择http或ws协议;若当前页面为https协议,则后端接口自动选择https或wss协议。 + Specifying other host needs to use the full format, such as ``http://example.com:5000/aaa/io``, ``ws://example.com:8080/bbb/ws_io``, or omit the protocol field: ``//example.com:8080/aaa/io``. + When the protocol field is omitted, PyWebIO determines the protocol to be used according to the protocol of the current page: if the current page is the http protocol, the protocol of backend API automatically will be http or ws; if the current page is the https protocol, the protocol of backend API automatically will be https or wss. 如果你不想自己托管静态文件,你可以使用PyWebIO的Github Page页面: ``https://wang0618.github.io/PyWebIO/pywebio/html/?pywebio_api=`` ,需要在页面上通过 ``pywebio_api`` 参数传入后端API地址,并且将 ``https://wang0618.github.io`` 加入 ``allowed_origins`` 列表中(见下文"跨域配置"说明)。 -**跨域配置** +If you don’t want to host static files by yourself, you can use PyWebIO's Github Page: ``https://wang0618.github.io/PyWebIO/pywebio/html/?pywebio_api=``, you need to pass in the backend API address to the ``pywebio_api`` parameter , And add ``https://wang0618.github.io`` to the ``allowed_origins`` list (see "CORS setting" section below). + +**CORS setting** 当后端API与前端页面不在同一host下时,需要在 `webio_handler() ` 或 `webio_view() ` 中使用 ``allowed_origins`` 或 ``check_origin`` 参数来使后端接口允许前端页面的请求。 +When the backend API and the frontend page are not in the same host, you need to use the ``allowed_origins`` or ``check_origin`` parameter in ``webio_handler()`` or ``webio_view()`` to make backend API allow the requests from the frontend page. + .. _coroutine_based_session: -基于协程的会话 ---------------- +Coroutine-based session +------------------------------- 此部分内容属于高级特性,您不必使用此部分也可以实现PyWebIO支持的全部功能。PyWebIO中所有仅用于协程会话的函数或方法都在文档中有特别说明。 +This section will introduce the advanced features of PyWebIO. In most cases, you don’t need it. All functions or methods in PyWebIO that are only used for coroutine sessions are specifically noted in the document. + PyWebIO的会话实现默认是基于线程的,用户每打开一个和服务端的会话连接,PyWebIO会启动一个线程来运行任务函数。 除了基于线程的会话,PyWebIO还提供了基于协程的会话。基于协程的会话接受协程函数作为任务函数。 +PyWebIO's session is based on thread by default. Each time a user opens a session connection with the server, PyWebIO will start a thread to run task functions. In addition to thread-based sessions, PyWebIO also provides coroutine-based sessions. Coroutine-based sessions accept coroutine functions as task functions. + 基于协程的会话为单线程模型,所有会话都运行在一个线程内。对于IO密集型的任务,协程比线程占用更少的资源同时又拥有媲美于线程的性能。 另外,协程的上下文切换具有可预测性,能够减少程序同步与加锁的需要,可以有效避免大多数临界区问题。 -使用协程会话 -^^^^^^^^^^^^^^^^ +The session based on the coroutine uses a single-threaded model, which means that all sessions run in a single thread. For IO-bound tasks, coroutines take up fewer resources than threads and have performance comparable to threads. In addition, the context switching of the coroutine is predictable, which can reduce the need for program synchronization and locking, and can effectively avoid most critical section problems. + +Using coroutine session +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 要使用基于协程的会话,需要使用 ``async`` 关键字将任务函数声明为协程函数,并使用 ``await`` 语法调用PyWebIO输入函数: +To use coroutine-based session, you need to use the ``async`` keyword to declare the task function as a coroutine function, and use the ``await`` syntax to call the PyWebIO input function: + .. code-block:: python :emphasize-lines: 5,6 @@ -878,6 +1082,8 @@ PyWebIO的会话实现默认是基于线程的,用户每打开一个和服务 在协程任务函数中,也可以使用 ``await`` 调用其他协程或标准库 `asyncio `_ 中的可等待对象( `awaitable objects `_ ): +In the coroutine task function, you can also use ``await`` to call other coroutines or ( `awaitable objects `_ ) in the standard library `asyncio `_: + .. code-block:: python :emphasize-lines: 6,10 @@ -900,8 +1106,12 @@ PyWebIO的会话实现默认是基于线程的,用户每打开一个和服务 在基于协程的会话中, :doc:`pywebio.input ` 模块中的定义输入函数都需要使用 ``await`` 语法来获取返回值, 忘记使用 ``await`` 将会是在使用基于协程的会话时常出现的错误。 + In coroutine-based session, all input functions defined in the :doc:`pywebio.input ` module need to use ``await`` syntax to get the return value. Forgetting to use ``await`` will be a common error when using coroutine-based session. + 其他在协程会话中也需要使用 ``await`` 语法来进行调用函数有: + Other functions that need to use ``await`` syntax in the coroutine session are: + * `pywebio.session.run_asyncio_coroutine(coro_obj) ` * `pywebio.session.eval_js(expression) ` * `pywebio.session.hold() ` @@ -910,7 +1120,11 @@ PyWebIO的会话实现默认是基于线程的,用户每打开一个和服务 虽然PyWebIO的协程会话兼容标准库 ``asyncio`` 中的 ``awaitable objects`` ,但 ``asyncio`` 库不兼容PyWebIO协程会话中的 ``awaitable objects`` . - 也就是说,无法将PyWebIO中的 ``awaitable objects`` 传入 ``asyncio`` 中的接受 ``awaitable objects`` 作为参数的函数中,比如如下调用是 **不被支持的** :: + Although the PyWebIO coroutine session is compatible with the ``awaitable objects`` in the standard library ``asyncio``, the ``asyncio`` library is not compatible with the ``awaitable objects`` in the PyWebIO coroutine session. + + 也就是说,无法将PyWebIO中的 ``awaitable objects`` 传入 ``asyncio`` 中的接受 ``awaitable objects`` 作为参数的函数中,比如如下调用是 **不被支持的** + + That is to say, you can't pass PyWebIO ``awaitable objects`` to the `asyncio`` function that accepts ``awaitable objects``. For example, the following calls are **unsupported** :: await asyncio.shield(pywebio.input()) await asyncio.gather(asyncio.sleep(1), pywebio.session.eval_js('1+1')) @@ -918,11 +1132,13 @@ PyWebIO的会话实现默认是基于线程的,用户每打开一个和服务 .. _coroutine_based_concurrency: -协程会话的并发 -^^^^^^^^^^^^^^^^ +Concurrency in coroutine-based sessions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 在基于协程的会话中,你可以启动线程,但是无法在其中调用PyWebIO交互函数( `register_thread() ` 在协程会话中不可用)。 -但你可以使用 `run_async(coro) ` 来异步执行一个协程对象,新协程内可以使用PyWebIO交互函数:: +但你可以使用 `run_async(coro) ` 来异步执行一个协程对象,新协程内可以使用PyWebIO交互函数 + +In coroutine-based session, you can start new thread, but you cannot call PyWebIO interactive functions in it (`register_thread() ` is not available in coroutine session). But you can use `run_async(coro) ` to execute a coroutine object asynchronously, and PyWebIO interactive functions can be used in the new coroutine:: from pywebio import start_server from pywebio.session import run_async @@ -941,28 +1157,46 @@ PyWebIO的会话实现默认是基于线程的,用户每打开一个和服务 `run_async(coro) ` 返回一个 `TaskHandle ` ,通过 `TaskHandle ` 可以查询协程运行状态和关闭协程。 -协程会话的关闭 -^^^^^^^^^^^^^^^^ +`run_async(coro) ` returns a `TaskHandle `, which can be used to query the running status of the coroutine or close the coroutine. + +Close of session +^^^^^^^^^^^^^^^^^^^ 与基于线程的会话类似,在基于协程的会话中,当任务函数和在会话内通过 `run_async() ` 运行的协程全部结束后,会话关闭。 +Similar to thread-based session, in coroutine-based session, when the task function and the coroutine running through `run_async() ` in the session are all finished, the session is closed. + 对于因为用户的关闭浏览器而造成的会话结束,处理逻辑和 :ref:`基于线程的会话 ` 一致: 此时当前会话内还未返回的PyWebIO输入函数调用将抛出 `SessionClosedException ` 异常,之后对于PyWebIO交互函数的调用将会产生 `SessionNotFoundException ` 或 `SessionClosedException ` 异常。 +If the close of the session is caused by the user closing the browser, the behavior of PyWebIO is the same as :ref:`Thread-based session `: After the browser page closed, PyWebIO input function calls that have not yet returned in the current session will cause `SessionClosedException `, and subsequent calls to PyWebIO interactive functions will cause `SessionNotFoundException ` or `SessionClosedException `. + 协程会话也同样支持使用 `defer_call(func) ` 来设置会话结束时需要调用的函数。 -协程会话与Web框架集成 -^^^^^^^^^^^^^^^^^^^^^^^^^ +`defer_call(func) ` also available in coroutine session. + +Integration with Web Framework +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 基于协程的会话同样可以与Web框架进行集成,只需要在原来传入任务函数的地方改为传入协程函数即可。 +The coroutine-based session can also be integrated with the web framework. + 但当前在使用基于协程的会话集成进Flask或Django时,存在一些限制: +However, there are some limitations when using coroutine-based sessions to integrate into Flask or Django: + 一是协程函数内还无法直接通过 ``await`` 直接等待asyncio库中的协程对象,目前需要使用 `run_asyncio_coroutine() ` 进行包装。 +First, when ``await`` the coroutine object in the ``asyncio`` module, you need use `run_asyncio_coroutine() ` to wrap the coroutine object. + 二是,在启动Flask/Django这类基于线程的服务器之前需要启动一个单独的线程来运行事件循环。 +Secondly, you need to start a new thread to run the event loop before starting a Flask/Django server. + 使用基于协程的会话集成进Flask的示例: +Example of coroutine-based session integration into Flask: + .. code-block:: python :emphasize-lines: 12,25 @@ -977,7 +1211,7 @@ PyWebIO的会话实现默认是基于线程的,用户每打开一个和服务 async def hello_word(): put_text('Hello ...') - await run_asyncio_coroutine(asyncio.sleep(1)) # 无法直接 await asyncio.sleep(1) + await run_asyncio_coroutine(asyncio.sleep(1)) # can't just "await asyncio.sleep(1)" put_text('... World!') app = Flask(__name__) @@ -989,20 +1223,26 @@ PyWebIO的会话实现默认是基于线程的,用户每打开一个和服务 def serve_static_file(static_file='index.html'): return send_from_directory(STATIC_PATH, static_file) - # 事件循环线程 + # thread to run event loop threading.Thread(target=run_event_loop, daemon=True).start() app.run(host='localhost', port=80) 最后,使用PyWebIO编写的协程函数不支持Script模式,总是需要使用 ``start_server`` 来启动一个服务或者集成进Web框架来调用。 +Finally, coroutine-based session is not available in the Script mode. Last but not least --------------------- 以上就是PyWebIO的全部功能了,你可以继续阅读接下来的文档,或者立即开始PyWebIO应用的编写了。 +This is all features of PyWebIO, you can continue to read the rest of the documents, or start writing your PyWebIO applications now. + 最后再提供一条建议,当你在使用PyWebIO遇到设计上的问题时,可以问一下自己:如果在是在终端程序中我会怎么做? 如果你已经有答案了,那么在PyWebIO中一样可以使用这样的方式完成。如果问题依然存在或者觉得解决方案不够好, 你可以考虑使用 `put_buttons() ` 提供的回调机制。 -好了,Have fun with PyWebIO! \ No newline at end of file +Finally, please allow me to provide one more suggestion. When you encounter design problems when using PyWebIO, you can ask yourself a question: What would I do if it is in a terminal program? +If you already have the answer, it can be done in the same way with PyWebIO. If the problem persists or the solution is not good enough, you can consider using the callback mechanism provided by `put_buttons() `. + +OK, Have fun with PyWebIO! \ No newline at end of file diff --git a/docs/index.rst b/docs/index.rst index 33cedc8b..a1784e38 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,80 +1,77 @@ PyWebIO ========== -PyWebIO提供了一系列命令式的交互函数来在浏览器上获取用户输入和进行输出,将浏览器变成了一个“富文本终端”,可以用于构建简单的Web应用或基于浏览器的GUI应用。 -使用PyWebIO,开发者能像编写终端脚本一样(基于input和print进行交互)来编写应用,无需具备HTML和JS的相关知识; -PyWebIO还可以方便地整合进现有的Web服务。非常适合快速构建对UI要求不高的应用。 +PyWebIO provides a series of imperative functions to obtain user input and output on the browser, turning the browser into a "rich text terminal", which can be used to build simple web applications or browser-based GUI applications. Using PyWebIO, developers can write applications just like writing terminal scripts (interaction based on input and print), without the need to have relevant knowledge of HTML and JS. PyWebIO can also be easily integrated into existing Web services. PyWebIO is very suitable for quickly building applications that do not require complex UI. - -特性 +Features ------------ -- 使用同步而不是基于回调的方式获取输入,代码编写逻辑更自然 -- 非声明式布局,布局方式简单高效 -- 代码侵入性小,旧脚本代码仅需修改输入输出逻辑便可改造为Web服务 -- 支持整合到现有的Web服务,目前支持与Flask、Django、Tornado、aiohttp框架集成 -- 同时支持基于线程的执行模型和基于协程的执行模型 -- 支持结合第三方库实现数据可视化 +- Use synchronization instead of callback-based method to get input, making programing logic more natural +- Non-declarative layout, simple and efficient +- Less intrusive: old script code can be transformed into a Web service only by modifying the input and output logic +- Support integration into existing web services, currently supports Flask, Django, Tornado, aiohttp framework +- Support for ``asyncio`` and coroutine +- Support data visualization with third-party libraries -Install ------------- +Installation +-------------- -稳定版安装:: +Stable version:: pip3 install -U pywebio -开发版安装:: +Development version:: pip3 install -U --force-reinstall https://code.aliyun.com/wang0618/pywebio/repository/archive.zip -**系统要求**: PyWebIO要求 Python 版本在 3.5.2 及以上 +**Prerequisites**: PyWebIO requires Python 3.5.2 or newer .. _hello_word: Hello, world -------------- -这是一个使用PyWebIO计算 `BMI指数 `_ 的脚本:: +Here is a simple PyWebIO script to calculate the `BMI `_ :: # A simple script to calculate BMI from pywebio.input import input, FLOAT from pywebio.output import put_text def bmi(): - height = input("请输入你的身高(cm):", type=FLOAT) - weight = input("请输入你的体重(kg):", type=FLOAT) + height = input("Input your height(cm):", type=FLOAT) + weight = input("Input your weight(kg):", type=FLOAT) BMI = weight / (height / 100) ** 2 - top_status = [(14.9, '极瘦'), (18.4, '偏瘦'), - (22.9, '正常'), (27.5, '过重'), - (40.0, '肥胖'), (float('inf'), '非常肥胖')] + top_status = [(16, 'Severely underweight'), (18.5, 'Underweight'), + (25, 'Normal'), (30, 'Overweight'), + (35, 'Moderately obese'), (float('inf'), 'Severely obese')] for top, status in top_status: if BMI <= top: - put_text('你的 BMI 值: %.1f,身体状态:%s' % (BMI, status)) + put_text('Your BMI: %.1f. Category: %s' % (BMI, status)) break if __name__ == '__main__': bmi() -如果没有使用PyWebIO,这只是一个非常简单的脚本,而通过使用PyWebIO提供的输入输出函数,你可以在浏览器中与代码进行交互: +This is just a very simple script if you ignore PyWebIO, but by using the input and output functions provided by PyWebIO, you can interact with the code in the browser: .. image:: /assets/demo.* :width: 450px :align: center -将上面代码最后一行对 ``bmi()`` 的直接调用改为使用 `pywebio.start_server(bmi, port=80) ` 便可以在80端口提供 ``bmi()`` 服务( :demo_host:`在线Demo ` )。 +In the last line of the above code, change the function call ``bmi()`` to `pywebio.start_server(bmi, port=80) ` to provide bmi service on port 80 ( :demo_host:`online Demo ` ). -将 ``bmi()`` 服务整合到现有的Web框架请参考 :ref:`与Web框架集成 ` +If you want to integrate the ``bmi()`` service into an existing web framework, you can visit :ref:`Integration with a web framework ` part of this document. Documentation ------------- -这个文档同时也提供 `PDF 和 Epub 格式 `_. +This documentation is also available in `PDF and Epub formats `_. .. toctree:: :maxdepth: 2 - :caption: 使用手册 + :caption: Manual guide input @@ -93,7 +90,7 @@ Documentation .. toctree:: :maxdepth: 2 - :caption: 实现文档 + :caption: Implement Doc spec diff --git a/docs/input.rst b/docs/input.rst index ef9f0501..f540e026 100644 --- a/docs/input.rst +++ b/docs/input.rst @@ -1,4 +1,4 @@ -``pywebio.input`` --- 输入模块 +``pywebio.input`` --- Get input from web browser ==================================================== .. automodule:: pywebio.input diff --git a/docs/libraries_support.rst b/docs/libraries_support.rst index 18f7139b..dcb7d27f 100644 --- a/docs/libraries_support.rst +++ b/docs/libraries_support.rst @@ -1,17 +1,21 @@ -第三方库生态 -============== +Libraries support +====================== .. _visualization: -数据可视化 -------------- -PyWebIO支持使用第三方库进行数据可视化 +Data visualization +-------------------- +PyWebIO supports for data visualization with the third-party libraries. Bokeh ^^^^^^^^^^^^^^^^^^^^^^ `Bokeh `_ 是一个支持创建实时交互的数据可视化库。 -在 PyWebIO 会话中调用 ``bokeh.io.output_notebook(notebook_type='pywebio')`` 来设置Bokeh输出到PyWebIO:: +`Bokeh `_ is an interactive visualization library for modern web browsers. It provides elegant, concise construction of versatile graphics, and affords high-performance interactivity over large or streaming datasets. + +在 PyWebIO 会话中调用 ``bokeh.io.output_notebook(notebook_type='pywebio')`` 来设置Bokeh输出到PyWebIO: + +You can use ``bokeh.io.output_notebook(notebook_type='pywebio')`` in the PyWebIO session to set Bokeh output to PyWebIO:: from bokeh.io import output_notebook from bokeh.io import show @@ -21,11 +25,15 @@ Bokeh ... show(fig) -相应demo见 :charts_demo_host:`bokeh demo ` +See related demo on :charts_demo_host:`bokeh demo ` + +除了创建普通图表,Bokeh还可以通过启动 `Bokeh server `_ 来显示Bokeh app,Bokeh app支持向图表的添加按钮、输入框等交互组件,并向组件注册Python回调,从而创建可以与Python代码交互的图表。 -除了创建普通图表,Bokeh还可以通过启动Bokeh server来显示Bokeh app,Bokeh app支持向图表的添加按钮、输入框等交互组件,并向组件注册Python回调,从而创建可以与Python代码交互的图表。 +In addition to creating ordinary charts, Bokeh can also build the Bokeh applications by starting the `Bokeh server `_. The purpose of the Bokeh server is to make it easy for Python users to create interactive web applications that can connect front-end UI events to real, running Python code. -在PyWebIO中,你也可以使用 ``bokeh.io.show()`` 来显示一个Bokeh App,代码示例见 `bokeh_app.py `_。 +在PyWebIO中,你也可以使用 ``bokeh.io.show()`` 来显示一个Bokeh App,代码示例见 `bokeh_app.py `_。 + +In PyWebIO, you can also use ``bokeh.io.show()`` to display a Bokeh App. For the example, see `bokeh_app.py `_. .. image:: https://cdn.jsdelivr.net/gh/wang0618/pywebio-chart-gallery@master/assets/bokeh.png @@ -33,12 +41,16 @@ pyecharts ^^^^^^^^^^^^^^^^^^^^^^ `pyecharts `_ 是一个使用Python创建 `Echarts `_ 可视化图表的库。 -在 PyWebIO 中使用 `put_html() ` 可以输出 pyecharts 库创建的图表:: +`pyecharts `_ is a python plotting library which uses `Echarts `_ as underlying implementation. + +在 PyWebIO 中使用 `put_html() ` 可以输出 pyecharts 库创建的图表: + +In PyWebIO, you can use the following code to output the pyecharts chart instance:: - # chart 为 pyecharts 的图表实例 + # `chart` is pyecharts chart instance pywebio.output.put_html(chart.render_notebook()) -相应demo见 :charts_demo_host:`pyecharts demo ` +See related demo on :charts_demo_host:`pyecharts demo ` .. only:: not latex @@ -48,13 +60,17 @@ plotly ^^^^^^^^^^^^^^^^^^^^^^ `plotly.py `_ 是一个非常流行的Python数据可视化库,可以生成高质量的交互式图表。 -PyWebIO 支持输出使用 plotly 库创建的图表。使用方式为在PyWebIO会话中调用:: +`plotly.py `_ is an interactive, open-source, and browser-based graphing library for Python. - # fig 为 plotly 的图表实例 +PyWebIO 支持输出使用 plotly 库创建的图表。使用方式为在PyWebIO会话中调用: + +In PyWebIO, you can use the following code to output the plotly chart instance:: + + # `fig` is plotly chart instance html = fig.to_html(include_plotlyjs="require", full_html=False) pywebio.output.put_html(html) -相应demo见 :charts_demo_host:`plotly demo ` +See related demo on :charts_demo_host:`plotly demo ` .. image:: https://cdn.jsdelivr.net/gh/wang0618/pywebio-chart-gallery@master/assets/plotly.png @@ -64,11 +80,16 @@ cutecharts.py `cutecharts.py `_ 是一个可以创建具有卡通风格的可视化图表的python库。 底层使用了 `chart.xkcd `_ Javascript库。 -在 PyWebIO 中使用 `put_html() ` 可以输出 cutecharts.py 库创建的图表:: +`cutecharts.py `_ is a hand drawing style charts library for Python which uses `chart.xkcd `_ as underlying implementation. + + +在 PyWebIO 中使用 `put_html() ` 可以输出 cutecharts.py 库创建的图表: + +In PyWebIO, you can use the following code to output the cutecharts.py chart instance:: - # chart 为 cutecharts 的图表实例 + # `chart` is cutecharts chart instance pywebio.output.put_html(chart.render_notebook()) -相应demo见 :charts_demo_host:`cutecharts demo ` +See related demo on :charts_demo_host:`cutecharts demo ` .. image:: https://cdn.jsdelivr.net/gh/wang0618/pywebio-chart-gallery@master/assets/cutecharts.png diff --git a/docs/misc.rst b/docs/misc.rst index ccfcfa2f..71488c48 100644 --- a/docs/misc.rst +++ b/docs/misc.rst @@ -1,26 +1,28 @@ -其他 -============ +Miscellaneous +=============== .. _codemirror_options: -常用的Codemirror选项 --------------------- +Commonly used Codemirror options +------------------------------------ -* ``mode`` (str): 代码语言。支持的语言有:https://codemirror.net/mode/index.html -* ``theme`` (str): 编辑器主题。可使用的主题:https://codemirror.net/demo/theme.html -* ``lineNumbers`` (bool): 是否显示行号 -* ``indentUnit`` (int): 缩进使用的空格数 -* ``tabSize`` (int): 制表符宽度 -* ``lineWrapping`` (bool): 是否换行以显示长行 +* ``mode`` (str): The language of code. For complete list, see https://codemirror.net/mode/index.html +* ``theme`` (str): The theme to style the editor with. For all available theme, see https://codemirror.net/demo/theme.html +* ``lineNumbers`` (bool): Whether to show line numbers to the left of the editor. +* ``indentUnit`` (int): How many spaces a block (whatever that means in the edited language) should be indented. The default is 2. +* ``tabSize`` (int): The width of a tab character. Defaults to 4. +* ``lineWrapping`` (bool): Whether CodeMirror should scroll or wrap for long lines. Defaults to false (scroll). -完整的Codemirror选项请见 https://codemirror.net/doc/manual.html#config +For complete Codemirror options, please visit: https://codemirror.net/doc/manual.html#config .. _nginx_ws_config: -Nginx WebSocket配置示例 ------------------------ +Nginx WebSocket Config Example +--------------------------------- -假设后端服务器运行在 ``localhost:5000`` 地址,并将PyWebIO的后端接口绑定到 ``/tool/io`` 路径上,则通过Nginx访问PyWebIO服务的配置如下:: +假设后端服务器运行在 ``localhost:5000`` 地址,并将PyWebIO的后端接口绑定到 ``/tool/io`` 路径上,则通过Nginx访问PyWebIO服务的配置如下 + +Assuming that the backend server is running at the ``localhost:5000`` address, and the backend API of PyWebIO is bind to the ``/tool/io`` path, the configuration of Nginx is as follows:: map $http_upgrade $connection_upgrade { default upgrade; @@ -45,6 +47,10 @@ Nginx WebSocket配置示例 以上配置文件将PyWebIO的静态文件托管到 ``/tool/`` 目录下, 并将 ``/tool/io`` 反向代理到 ``localhost:5000`` -PyWebIO的静态文件的路径可使用命令 ``python3 -c "import pywebio; print(pywebio.STATIC_PATH)"`` 获得,你也可以将静态文件复制到其他目录下:: +The above configuration file hosts the static files of PyWebIO on the ``/tool/`` path, and reverse proxy ``/tool/io`` to ``localhost:5000`` + +PyWebIO的静态文件的路径可使用命令 ``python3 -c "import pywebio; print(pywebio.STATIC_PATH)"`` 获得,你也可以将静态文件复制到其他目录下 + +The path of the static file of PyWebIO can be obtained with the command ``python3 -c "import pywebio; print(pywebio.STATIC_PATH)"``, you can also copy the static file to other directories:: cp -r `python3 -c "import pywebio; print(pywebio.STATIC_PATH)"` ~/web diff --git a/docs/output.rst b/docs/output.rst index 16bbbef6..6de3b838 100644 --- a/docs/output.rst +++ b/docs/output.rst @@ -1,4 +1,4 @@ -``pywebio.output`` --- 输出模块 +``pywebio.output`` --- Make output to web browser ==================================================== .. automodule:: pywebio.output diff --git a/docs/platform.rst b/docs/platform.rst index 965a4e70..01264708 100644 --- a/docs/platform.rst +++ b/docs/platform.rst @@ -1,4 +1,4 @@ -``pywebio.platform`` --- Web框架支持 +``pywebio.platform`` --- Support to Web framework =============================================================== .. automodule:: pywebio.platform diff --git a/docs/session.rst b/docs/session.rst index 64e369e8..07603307 100644 --- a/docs/session.rst +++ b/docs/session.rst @@ -1,4 +1,4 @@ -``pywebio.session`` --- 会话相关 +``pywebio.session`` --- More control to session ==================================================== .. automodule:: pywebio.session diff --git a/docs/spec.rst b/docs/spec.rst index 8cb7fa59..fbd8d1c3 100644 --- a/docs/spec.rst +++ b/docs/spec.rst @@ -1,30 +1,45 @@ -服务器-客户端通信协议 -========================== +Server-Client communication protocol +======================================== PyWebIO采用服务器-客户端架构,服务端运行任务代码,通过网络与客户端(也就是用户浏览器)交互 +PyWebIO uses a server-client architecture, the server executes task code, and interacts with the client (that is, the user browser) through the network. This section is the protocol specification for the communication between PyWebIO server and client. + 服务器与客户端有两种通信方式:WebSocket 和 Http 通信。 +There are two communication methods between server and client: WebSocket and Http. + 使用 Tornado或aiohttp 后端时,服务器与客户端通过 WebSocket 通信,使用 Flask或Django 后端时,服务器与客户端通过 Http 通信。 -**WebSocket 通信:** +When using Tornado or aiohttp backend, the server and client communicate through WebSocket, when using Flask or Django backend, the server and client communicate through Http. + +**WebSocket communication** 服务器与客户端通过WebSocket连接发送json序列化之后的PyWebIO消息 +The server and the client send the PyWebIO message which are json serialized through WebSocket connection -**Http 通信:** +**Http communication** * 客户端通过Http GET请求向后端轮询,后端返回json序列化之后的PyWebIO消息列表 +* The client polls the backend through Http GET requests, and the backend returns a list of PyWebIO messages serialized in json + * 当用户提交表单或者点击页面按钮后,客户端通过Http POST请求向后端提交数据 +* When the user submits the form or clicks the page button, the client submits data to the backend through Http POST request + 为方便区分,下文将由服务器向客户端发送的数据称作command,将客户端发向服务器的数据称作event +In the following, the data sent by the server to the client is called command, and the data sent by the client to the server is called event. + 以下介绍command和event的格式 +The following describes the format of command and event + Command ------------ -command由服务器->客户端,基本格式为:: +command is sent by the server to the client. The basic format of command is:: { "command": "" @@ -32,73 +47,72 @@ command由服务器->客户端,基本格式为:: "spec": {} } -各字段含义如下: +Each fields are described as follows: - * ``command`` 字段表示指令名 + * ``command`` : command name - * ``task_id`` 字段表示发送指令的Task id,客户端对于此命令的响应事件都会传递 task_id + * ``task_id`` : Id of the task that send the command - * ``spec`` 字段为指令的参数,不同指令参数不同 + * ``spec`` : the data of the command, which is different depending on the command name 需要注意,以下不同命令的参数和 PyWebIO 的对应函数的参数大部分含义一致,但是也有些许不同。 -以下分别对不同指令的 ``spec`` 字段进行说明: +The arguments shown above are merely the same with the parameters of corresponding PyWebIO functions. + +The following describes the ``spec`` fields of different commands: input_group ^^^^^^^^^^^^^^^ -显示一个输入表单 +Show a form in user's browser. -.. list-table:: ``spec`` 可用字段 +.. list-table:: fields of ``spec`` :header-rows: 1 - * - 字段 - - 是否必选 - - 类型 - - 字段说明 + * - Field + - Required + - Type + - Description * - label - False - str - - 表单标题 + - Title of the form * - inputs - True - list - - 输入项 + - Input items * - cancelable - False - bool - - | 表单是否可以取消。 - | 若 ``cancelable=True`` 则会在表单底部显示一个"取消"按钮, - | 用户点击取消按钮后,触发 ``from_cancel`` 事件 - - -``inputs`` 字段为输入项组成的列表,每一输入项为一个 ``dict``,字段如下: - -* label: 输入标签名。必选 -* type: 输入类型。必选 -* name: 输入项id。必选 -* auto_focus: 自动获取输入焦点. 输入项列表中最多只能由一项的auto_focus为真 -* help_text: 帮助文字 -* 输入对应的html属性 -* 不同输入类型的特有属性 - - - -输入类型目前有: - -* text: 文本输入 -* number: 数字输入 -* password: 密码输入 -* checkbox: 多选项 -* radio: 单选项 -* select: 下拉选择框(可单选/多选) -* textarea: 大段文本输入 -* file: 文件上传 -* actions: 如果表单最后一个输入元素为actions组件,则隐藏默认的"提交"/"重置"按钮 - -输入类型与html输入元素的对应关系: + - | Whether the form can be cancelled。 + | If cancelable=True, a “Cancel” button will be displayed at the bottom of the form. + | A ``from_cancel`` event is triggered after the user clicks the cancel button. + +The ``inputs`` field is a list of input items, each input item is a ``dict``, the fields of the item are as follows: + +* label: Label of input field, required. +* type: Input type, required. +* name: Identifier of the input field, required. +* auto_focus: Set focus automatically. At most one item of ``auto_focus`` can be true in the input item list +* help_text: Help text for the input +* Additional HTML attribute of the input element +* Other attributes of different input types + +Currently supported ``type`` are: + +* text: Plain text input +* number: Number input +* password: Password input +* checkbox: Checkbox +* radio: Radio +* select: Drop-down selection +* textarea: Multi-line text input +* file: File uploading +* actions: Actions selection. + +Correspondence between different input types and html input elements: * text: input[type=text] * number: input[type=number] @@ -110,167 +124,166 @@ input_group * file: input[type=file] * actions: button[type=submit] https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/button -不同输入类型的特有属性: +Unique attributes of different input types: * text,number,password: - * action: 在输入框一侧显示一个按钮。格式为 ``{label: 按钮标签, callback_id: 按钮回调id}`` + * action: Display a button on the right of the input field. + The format of ``action`` is ``{label: button label, callback_id: button click callback id}`` * textarea: - * code: Codemirror 参数, 见 :func:`pywebio.input.textarea` 的 ``code`` 参数 + * code: Codemirror options, same as ``code`` parameter of :func:`pywebio.input.textarea` * select: - * options: 选项列表 ``{label:选项标签, value: 选项值, [selected:是否默认选中,] [disabled:是否禁止选中]}`` + * options: ``{label:, value: , [selected:,] [disabled:]}`` * checkbox: - * options: 选项列表 ``{label:选项标签, value: 选项值, [selected:是否默认选中,] [disabled:是否禁止选中]}`` + * options: ``{label:, value: , [selected:,] [disabled:]}`` * inline * radio: - * options: 选项列表 ``{label:选项标签, value: 选项值, [selected:是否默认选中,] [disabled:是否禁止选中]}`` + * options: ``{label:, value: , [selected:,] [disabled:]}`` * inline * actions - * buttons: 选项列表。``{label:选项标签, value:选项值, [type: 按钮类型 'submit'/'reset'/'cancel'], [disabled:是否禁止选择]}`` . + * buttons: ``{label:, value:, [type: 'submit'/'reset'/'cancel'], [disabled:]}`` . + * file: - * multiple: 是否允许多文件上传 - * max_size: 单个文件的最大大小,超过限制将会禁止上传 - * max_total_size: 所有文件的最大大小,超过限制将会禁止上传 + * multiple: Whether to allow upload multiple files. + * max_size: The maximum size of a single file, in bytes. + * max_total_size: The maximum size of all files, in bytes. update_input ^^^^^^^^^^^^^^^ -更新输入项,用于对当前显示表单中输入项的 ``spec`` 进行更新 +Update the input item, you can update the ``spec`` of the input item of the currently displayed form -命令 ``spec`` 可用字段: +The ``spec`` fields of ``update_input`` commands: -* target_name: str 输入项的name值 -* target_value: str,可选。 用于在checkbox, radio, actions输入中过滤input(这些类型的输入项包含多个html input元素) -* attributes: dist 需要更新的内容 +* target_name: str The name of the target input item. +* target_value: str, optional. Used to filter options in checkbox, radio, actions type +* attributes: dist, fields need to be updated - * valid_status: 为bool时,表示设置输入值的有效性,通过/不通过; 为0时,表示清空valid_status标志 - * value: 输入项的值 - * placeholder: + * valid_status: When it is bool, it means setting the state of the input value, pass/fail; when it is 0, it means clear the valid_status flag + * value: Set the value of the item + * placeholder * invalid_feedback * valid_feedback - * 输入项其他spec字段 // 不支持更新 inline 和 label 字段 + * other fields of item's ``spec`` // not support to inline adn label fields close_session ^^^^^^^^^^^^^^^ -指示服务器端已经关闭连接。 ``spec`` 为空 +Indicates that the server has closed the connection. ``spec`` of the command is empty. destroy_form ^^^^^^^^^^^^^^^ -销毁当前表单。 ``spec`` 为空 +Destroy the current form. ``spec`` of the command is empty. -表单在页面上提交之后不会自动销毁,需要使用此命令显式销毁 +Note: The form will not be automatically destroyed after it is submitted, it needs to be explicitly destroyed using this command output ^^^^^^^^^^^^^^^ -输出内容 - -命令 ``spec`` 字段: +Output content -* type: 内容类型 -* style: str 自定义样式 -* scope: str 内容输出的域的css选择器。若CSS选择器匹配到页面上的多个容器,则内容会输出到每个匹配到的容器 -* position: int 在输出域中输出的位置, 见 :ref:`输出函数的scope相关参数 ` -* 不同type时的特有字段 +The ``spec`` fields of ``output`` commands: +* type: content type +* style: str, Additional css style +* scope: str, CSS selector of the output container. If multiple containers are matched, the content will be output to every matched container +* position: int, see :ref:`scope - User manual ` +* Other attributes of different types -``type`` 的可选值及特有字段: +Unique attributes of different types: * type: markdown * content: str - * options: dict, `marked.js `_ 选项 - * sanitize: bool, 是否使用 `DOMPurify `_ 对内容进行过滤来防止XSS攻击。 + * options: dict, `marked.js `_ options + * sanitize: bool, Whether to enable a XSS sanitizer for HTML * type: html - * content: str: - * sanitize: bool, 是否使用 `DOMPurify `_ 对内容进行过滤来防止XSS攻击。 - + * content: str + * sanitize: bool, Whether to enable a XSS sanitizer for HTML * type: text - * content: str 输出的文本 - * inline: True/False 文本是否末尾换行 + * content: str + * inline: bool, Use text as an inline element (no line break at the end of the text) * type: buttons * callback_id: * buttons:[ {value:, label:, [color:]},...] - * small: bool,是否显示为小按钮样式 - * link: bool,是否显示为链接样式 + * small: bool, Whether to enable small button + * link: bool, Whether to make button seem as link. * type: file - * name: 下载保存为的文件名 - * content: 文件base64编码的内容 + * name: File name when downloading + * content: File content with base64 encoded * type: table - * data: 二维数组,表示表格数据,第一行为表头 - * span: 跨行/跨列的单元格信息,格式: {"[行id],[列id]": {"row":跨行数, "col":跨列数 }} + * data: Table data, which is a two-dimensional list, the first row is table header. + * span: cell span info. Format: {"[row id],[col id]": {"row":row span, "col":col span }} popup ^^^^^^^^^^^^^^^ -显示弹窗 +Show popup -命令 spec 字段: +The ``spec`` fields of ``popup`` commands: -* title: 弹窗标题 -* content: 数组,元素为字符串/对象 -* size: 弹窗窗口大小,可选值: ``large`` 、 ``normal`` 、 ``small`` -* implicit_close: 是否可以通过点击弹窗外的内容或按下 `Esc` 键来关闭弹窗 -* closable: 是否可由用户关闭弹窗. 默认情况下,用户可以通过点击弹窗右上角的关闭按钮来关闭弹窗, - 设置为 ``false`` 时弹窗仅能通过 ``popup_close`` command 关闭, ``implicit_close`` 参数被忽略. -* dom_id: 弹窗内容区的dom id +* title +* content +* size: ``large``, ``normal``, ``small`` +* implicit_close +* closable +* dom_id: DOM id of popup container element toast ^^^^^^^^^^^^^^^ -显示通知消息 +Show a notification message -命令 spec 字段: +The ``spec`` fields of ``popup`` commands: -* content: 通知内容 -* duration: 通知显示持续的时间,单位为毫秒 -* position: 通知消息显示的位置,可以为 `'left'` / `'center'` / `'right'` -* color: 通知消息的背景颜色,格式为合法的css颜色值 -* callback_id: 点击通知消息时的回调函数callback_id, 没有回调时为 null +* content +* duration +* position: `'left'` / `'center'` / `'right'` +* color: hexadecimal color value starting with '#' +* callback_id close_popup ^^^^^^^^^^^^^^^ -关闭正在显示的弹窗 +Close the current popup window. -该命令字段 ``spec`` 为 ``null`` +``spec`` of the command is empty. set_env ^^^^^^^^^^^^^^^ -环境配置 +Config the environment of current session. -命令 spec 字段: +The ``spec`` fields of ``set_env`` commands: -* title (str): 设定标题 -* output_animation (bool): 是否在输出内容时,使用过渡动画 -* auto_scroll_bottom (bool): 是否在内容输出时将页面自动滚动到底部 -* http_pull_interval (int): HTTP轮训后端消息的周期(单位为毫秒,默认1000ms),仅在使用HTTP的连接中可用 +* title (str) +* output_animation (bool) +* auto_scroll_bottom (bool) +* http_pull_interval (int) output_ctl ^^^^^^^^^^^^^^^ -输入控制 +Output control -命令 spec 字段: +The ``spec`` fields of ``output_ctl`` commands: * set_scope: 要创建的scope的名字 @@ -286,7 +299,7 @@ output_ctl * clear_before * clear_after * clear_range:[,] -* scroll_to: +* scroll_to * position: top/middle/bottom 与scroll_to一起出现, 表示滚动页面,让scope位于屏幕可视区域顶部/中部/底部 * remove: 将给定的scope连同scope处的内容移除 diff --git a/pywebio/exceptions.py b/pywebio/exceptions.py index 2c9721db..4c85f5c7 100644 --- a/pywebio/exceptions.py +++ b/pywebio/exceptions.py @@ -7,13 +7,13 @@ class SessionException(Exception): - """PyWebIO会话相关异常的基类""" + """Base class for PyWebIO session related exceptions""" class SessionClosedException(SessionException): - """会话已经关闭异常""" + """The session has been closed abnormally""" class SessionNotFoundException(SessionException): - """会话未找到异常""" + """Session not found""" diff --git a/pywebio/input.py b/pywebio/input.py index b0b89bba..80b8999c 100644 --- a/pywebio/input.py +++ b/pywebio/input.py @@ -1,13 +1,19 @@ -"""从浏览器接收用户输入 +""" 本模块提供了一系列函数来从浏览器接收用户不同的形式的输入 -输入函数大致分为两类,一类是单项输入:: +This module provides a series of functions to get all kinds of input of user from the browser + +输入函数的使用有两种方式,一种是单独调用输入函数的单项输入: + +There are two ways to use the input function, one is to call the input function alone to get a single input:: name = input("What's your name") print("Your name is %s" % name) -另一类是使用 `input_group` 的输入组:: +另一种是使用 `input_group` 的输入组: + +The other is to use `input_group` to get multiple inputs at once:: info = input_group("User info",[ input('Input your name', name='name'), @@ -17,47 +23,51 @@ 输入组中需要在每一项输入函数中提供 ``name`` 参数来用于在结果中标识不同输入项. +When use `input_group`, you needs to provide the ``name`` parameter in each input function to identify the input items in the result. + .. note:: PyWebIO 根据是否在输入函数中传入 ``name`` 参数来判断输入函数是在 `input_group` 中还是被单独调用。 所以当你想要单独调用一个输入函数时,请不要设置 ``name`` 参数;而在 `input_group` 中调用输入函数时,**务必提供** ``name`` 参数 -输入默认可以忽略,如果需要用户必须提供值,则需要在输入函数中传入 ``required=True`` (部分输入函数不支持 ``required`` 参数) + PyWebIO determine whether the input function is in `input_group` or is called alone according to whether the ``name`` parameter is passed. So when calling an input function alone, **do not** set the ``name`` parameter; when calling the input function in input_group, you **must** provide the ``name`` parameter. + +输入默认可以忽略,如果需要用户必须提供输入值,则需要在输入函数中传入 ``required=True`` (部分输入函数不支持 ``required`` 参数) -函数清单 ------------- +Functions list +----------------- .. list-table:: - * - 函数 - - 简介 + * - Function name + - Description * - `input ` - - 文本输入 + - Text input * - `textarea ` - - 多行文本输入 + - Multi-line text input * - `select ` - - 下拉选择框 + - Drop-down selection * - `checkbox ` - - 勾选选项 + - Checkbox * - `radio ` - - 单选选项 + - Radio * - `actions ` - - 按钮选项 + - Actions selection * - `file_upload ` - - 文件上传 + - File uploading * - `input_group ` - - 输入组 + - Input group -函数文档 ------------- +Functions doc +-------------- """ import logging @@ -89,12 +99,12 @@ def _parse_args(kwargs, excludes=()): - """处理传给各类输入函数的原始参数 + """parse the raw parameters that pass to input functions - - excludes: 排除的参数 - - 对为None的参数忽略处理 + - excludes: the parameters that don't appear in returned spec + - remove the parameters whose value is None - :return:(spec参数,valid_func) + :return:(spec,valid_func) """ kwargs = {k: v for k, v in kwargs.items() if v is not None and k not in excludes} assert is_html_safe_value(kwargs.get('name', '')), '`name` can only contains a-z、A-Z、0-9、_、-' @@ -106,18 +116,19 @@ def _parse_args(kwargs, excludes=()): def input(label='', type=TEXT, *, validate=None, name=None, value=None, action=None, placeholder=None, required=None, readonly=None, datalist=None, help_text=None, **other_html_attrs): - r"""文本输入 + r"""Text input - :param str label: 输入框标签 - :param str type: 输入类型. 可使用的常量:`TEXT` , `NUMBER` , `FLOAT` , `PASSWORD` , `URL` , `DATE` , `TIME` + :param str label: Label of input field. + :param str type: Input type. Currently supported types are:`TEXT` , `NUMBER` , `FLOAT` , `PASSWORD` , `URL` , `DATE` , `TIME` - 其中 `DATE` , `TIME` 类型在某些浏览器上不被支持,详情见 https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Browser_compatibility - :param callable validate: 输入值校验函数. 如果提供,当用户输入完毕或提交表单后校验函数将被调用. - ``validate`` 接收输入值作为参数,当输入值有效时,返回 ``None`` ,当输入值无效时,返回错误提示字符串. 比如: + Note that `DATE` and `TIME` type are not supported on some browsers, for details see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#Browser_compatibility + :param callable validate: Input value validation function. If provided, the validation function will be called when the user completes input or submits the form. + + ``validate`` receives the input value as a parameter. When the input value is valid, it returns ``None``. When the input value is invalid, it returns an error message string. For example: .. exportable-codeblock:: :name: input-valid-func - :summary: `input()` 输入值校验 + :summary: `input()` validation def check_age(age): if age>30: @@ -126,31 +137,31 @@ def check_age(age): return 'Too young' input('Input your age', type=NUMBER, validate=check_age) - :param str name: 输入框的名字. 与 `input_group` 配合使用,用于在输入组的结果中标识不同输入项. **在单个输入中,不可以设置该参数!** - :param str value: 输入框的初始值 + :param str name: A string specifying a name for the input. Used with `input_group()` to identify different input items in the results of the input group. If call the input function alone, this parameter can **not** be set! + :param str value: The initial value of the input :type action: tuple(label:str, callback:callable) - :param action: 在输入框右侧显示一个按钮,可通过点击按钮为输入框设置值。 + :param action: Put a button on the right side of the input field, and you can click the button to set the value for the input. - ``label`` 为按钮的显示文本, ``callback`` 为按钮点击的回调函数。 + ``label`` is the label of the button, and ``callback`` is the callback function to set the input value when clicked. - 回调函数需要接收一个 ``set_value`` 位置参数, ``set_value`` 是一个可调用对象,接受单参数调用和双参数调用。 + The callback is invoked with one argument, the ``set_value``. ``set_value`` is a callable object, which is invoked with one or two arguments. You can use ``set_value`` to set the value for the input. - 单参数调用时,签名为 ``set_value(value:str)`` ,调用set_value即可将表单项的值设置为传入的 ``value`` 参数。 + ``set_value`` can be invoked with one argument: ``set_value(value:str)``. The ``value`` parameter is the value to be set for the input. - 双参数调用时,签名为 ``set_value(value:any, label:str)`` ,其中: + ``set_value`` can be invoked with two arguments: ``set_value(value:any, label:str)``. Each arguments are described as follows: - * ``value`` 参数为最终输入项的返回值,可以为任意Python对象,并不会传递给用户浏览器 - * ``label`` 参数用于显示在用户表单项上 + * ``value`` : The real value of the input, can be any object. it will not be passed to the user browser. + * ``label`` : The text displayed to the user - 使用双参数调用 ``set_value`` 后,用户表单项会变为只读状态。 + When calling ``set_value`` with two arguments, the input item in web page will become read-only. - 双参数调用的使用场景为:表单项的值通过回调动态生成,同时希望用户表单显示的和实际提交的数据不同(例如表单项上可以显示更人性化的内容,而表单项的值则可以保存更方便被处理的对象) + The usage scenario of ``set_value(value:any, label:str)`` is: You need to dynamically generate the value of the input in the callback, and hope that the result displayed to the user is different from the actual submitted data (for example, result displayed to the user can be some user-friendly texts, and the value of the input can be objects that are easier to process) - 使用示例: + Usage example: .. exportable-codeblock:: :name: input-action - :summary: `input()`使用action参数动态设置表单项的值 + :summary: `input()` action usage import time def set_now_ts(set_value): @@ -168,15 +179,15 @@ def select_date(set_value): d = input('Date', action=('Select', select_date), readonly=True) put_text(type(d), d) - Note: 当使用 :ref:`基于协程的会话实现 ` 时,回调函数 ``callback`` 可以为协程函数. + Note: When using :ref:`Coroutine-based session ` implementation, the ``callback`` function can be a coroutine function. - :param str placeholder: 输入框的提示内容。提示内容会在输入框未输入值时以浅色字体显示在输入框中 - :param bool required: 当前输入是否为必填项 - :param bool readonly: 输入框是否为只读 - :param list datalist: 输入建议内容列表,在页面上的显示效果为下拉候选列表,用户可以忽略建议内容列表而输入其他内容。仅当输入类型 ``type`` 为 `TEXT` 时可用 - :param str help_text: 输入框的帮助文本。帮助文本会以小号字体显示在输入框下方 - :param other_html_attrs: 在输入框上附加的额外html属性。参考: https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input#%E5%B1%9E%E6%80%A7 - :return: 用户输入的值 + :param str placeholder: A hint to the user of what can be entered in the input. It will appear in the input field when it has no value set. + :param bool required: Whether a value is required for the input to be submittable + :param bool readonly: Whether the value is readonly(not editable) + :param list datalist: A list of predefined values to suggest to the user for this input. Can only be used when ``type=TEXT`` + :param str help_text: Help text for the input. The text will be displayed below the input field in a small font + :param other_html_attrs: Additional html attributes added to the input element. reference: https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/input#%E5%B1%9E%E6%80%A7 + :return: The value that user input. """ item_spec, valid_func = _parse_args(locals(), excludes=('action',)) @@ -227,16 +238,16 @@ def preprocess_func(d): # 将用户提交的原始数据进行转换 def textarea(label='', *, rows=6, code=None, maxlength=None, minlength=None, validate=None, name=None, value=None, placeholder=None, required=None, readonly=None, help_text=None, **other_html_attrs): - r"""文本输入域(多行文本输入) + r"""Text input area (multi-line text input) - :param int rows: 输入框的最多可显示的文本的行数,内容超出时会显示滚动条 - :param int maxlength: 最大允许用户输入的字符长度 (Unicode) 。未指定表示无限长度 - :param int minlength: 最少需要用户输入的字符长度(Unicode) - :param dict code: 通过提供 `Codemirror `_ 参数让文本输入域具有代码编辑器样式: + :param int rows: The number of visible text lines for the input area. Scroll bar will be used when content exceeds. + :param int maxlength: The maximum number of characters (UTF-16 code units) that the user can enter. If this value isn't specified, the user can enter an unlimited number of characters. + :param int minlength: The minimum number of characters (UTF-16 code units) required that the user should enter. + :param dict code: Make the text input field have a code editor style by providing the `Codemirror `_ options: .. exportable-codeblock:: :name: textarea-code - :summary: `textarea()`代码编辑 + :summary: `textarea()` code editor style res = textarea('Text area', code={ 'mode': "python", @@ -244,9 +255,10 @@ def textarea(label='', *, rows=6, code=None, maxlength=None, minlength=None, val }) put_code(res, language='python') # ..demo-only - :ref:`这里 ` 列举了一些常用的Codemirror选项 - :param - label, validate, name, value, placeholder, required, readonly, help_text, other_html_attrs: 与 `input` 输入函数的同名参数含义一致 - :return: 用户输入的文本 + Some commonly used Codemirror options are listed :ref:`here `. + + :param - label, validate, name, value, placeholder, required, readonly, help_text, other_html_attrs: Those arguments have the same meaning as for `input()` + :return: The string value that user input. """ item_spec, valid_func = _parse_args(locals()) item_spec['type'] = TEXTAREA @@ -255,11 +267,11 @@ def textarea(label='', *, rows=6, code=None, maxlength=None, minlength=None, val def _parse_select_options(options): - # 转换 select、checkbox、radio函数中的 options 参数为统一的格式 - # option 可用形式: + # Convert the `options` parameter in the `select`, `checkbox`, and `radio` functions to a unified format + # Available forms of option: # {value:, label:, [selected:,] [disabled:]} # (value, label, [selected,] [disabled]) - # value 单值,label等于value + # value (label same as value) opts_res = [] for opt in options: if isinstance(opt, Mapping): @@ -276,7 +288,7 @@ def _parse_select_options(options): def _set_options_selected(options, value): - """使用value为options的项设置selected""" + """set `selected` attribute for `options`""" if not isinstance(value, (list, tuple)): value = [value] for opt in options: @@ -287,29 +299,36 @@ def _set_options_selected(options, value): def select(label='', options=None, *, multiple=None, validate=None, name=None, value=None, required=None, help_text=None, **other_html_attrs): - r"""下拉选择框。 + r"""Drop-down selection + + By default, only one option can be selected at a time, you can set ``multiple`` parameter to enable multiple selection. - 默认单选,可以通过设置 ``multiple`` 参数来允许多选 + :param list options: list of options. The available formats of the list items are: - :param list options: 可选项列表。列表项的可用形式有: + * dict:: + + { + "label":(str) option label, + "value":(object) option value, + "selected":(bool, optional) whether the option is initially selected, + "disabled":(bool, optional) whether the option is initially disabled + } - * dict: ``{label:选项标签, value: 选项值, [selected:是否默认选中,] [disabled:是否禁止选中]}`` * tuple or list: ``(label, value, [selected,] [disabled])`` - * 单值: 此时label和value使用相同的值 + * single value: label and value of option use the same value - 注意: + Attention: - 1. ``options`` 中的 ``value`` 可以为任意可JSON序列化对象 - 2. 若 ``multiple`` 选项不为 ``True`` 则可选项列表最多仅能有一项的 ``selected`` 为 ``True``。 + 1. The ``value`` of option can be any JSON serializable object + 2. If the ``multiple`` is not ``True``, the list of options can only have one ``selected`` item at most. - :param bool multiple: 是否可以多选. 默认单选 - :param value: 下拉选择框初始选中项的值。当 ``multiple=True`` 时, ``value`` 需为list,否则为单个选项的值。 - 你也可以通过设置 ``options`` 列表项中的 ``selected`` 字段来设置默认选中选项。 - 最终选中项为 ``value`` 参数和 ``options`` 中设置的并集。 + :param bool multiple: whether multiple options can be selected + :param value: The value of the initial selected item. When ``multiple=True``, ``value`` must be a list. + You can also set the initial selected option by setting the ``selected`` field in the ``options`` list item. :type value: list or str - :param bool required: 是否至少选择一项,仅在 ``multiple=True`` 时可用 - :param - label, validate, name, help_text, other_html_attrs: 与 `input` 输入函数的同名参数含义一致 - :return: 如果 ``multiple=True`` 时,返回用户选中的 ``options`` 中的值的列表;否则,返回用户选中的 ``options`` 中的值 + :param bool required: Whether to select at least one item, only available when ``multiple=True`` + :param - label, validate, name, help_text, other_html_attrs: Those arguments have the same meaning as for `input()` + :return: If ``multiple=True``, return a list of the values in the ``options`` selected by the user; otherwise, return the single value selected by the user. """ assert options is not None, 'Required `options` parameter in select()' @@ -324,14 +343,14 @@ def select(label='', options=None, *, multiple=None, validate=None, name=None, v def checkbox(label='', options=None, *, inline=None, validate=None, name=None, value=None, help_text=None, **other_html_attrs): - r"""勾选选项。可以多选,也可以不选。 - - :param list options: 可选项列表。格式与同 `select()` 函数的 ``options`` 参数 - :param bool inline: 是否将选项显示在一行上。默认每个选项单独占一行 - :param list value: 勾选选项初始选中项。为选项值的列表。 - 你也可以通过设置 ``options`` 列表项中的 ``selected`` 字段来设置默认选中选项。 - :param - label, validate, name, help_text, other_html_attrs: 与 `input` 输入函数的同名参数含义一致 - :return: 用户选中的 options 中的值的列表。当用户没有勾选任何选项时,返回空列表 + r"""A group of check box that allowing single values to be selected/deselected. + + :param list options: List of options. The format is the same as the ``options`` parameter of the `select()` function + :param bool inline: Whether to display the options on one line. Default is False + :param list value: The value list of the initial selected items. + You can also set the initial selected option by setting the ``selected`` field in the ``options`` list item. + :param - label, validate, name, help_text, other_html_attrs: Those arguments have the same meaning as for `input()` + :return: A list of the values in the ``options`` selected by the user """ assert options is not None, 'Required `options` parameter in checkbox()' @@ -347,15 +366,15 @@ def checkbox(label='', options=None, *, inline=None, validate=None, name=None, v def radio(label='', options=None, *, inline=None, validate=None, name=None, value=None, required=None, help_text=None, **other_html_attrs): - r"""单选选项 - - :param list options: 可选项列表。格式与同 `select()` 函数的 ``options`` 参数 - :param bool inline: 是否将选项显示在一行上。默认每个选项单独占一行 - :param str value: 单选选项初始选中项的值。 - 你也可以通过设置 ``options`` 列表项中的 ``selected`` 字段来设置默认选中选项。 - :param bool required: 是否一定要选择一项(默认条件下用户可以不选择任何选项) - :param - label, validate, name, help_text, other_html_attrs: 与 `input` 输入函数的同名参数含义一致 - :return: 用户选中的选项的值, 如果用户没有选任何值,返回 ``None`` + r"""A group of radio button. Only a single button can be selected. + + :param list options: List of options. The format is the same as the ``options`` parameter of the `select()` function + :param bool inline: Whether to display the options on one line. Default is False + :param str value: The value of the initial selected items. + You can also set the initial selected option by setting the ``selected`` field in the ``options`` list item. + :param bool required: whether to must select one option. (the user can select nothing option by default) + :param - label, validate, name, help_text, other_html_attrs: Those arguments have the same meaning as for `input()` + :return: The value of the option selected by the user, if the user does not select any value, return ``None`` """ assert options is not None, 'Required `options` parameter in radio()' @@ -375,8 +394,8 @@ def radio(label='', options=None, *, inline=None, validate=None, name=None, valu def _parse_action_buttons(buttons): """ :param label: - :param actions: action 列表 - action 可用形式: + :param actions: action list + action available format: * dict: ``{label:选项标签, value:选项值, [type: 按钮类型], [disabled:是否禁止选择]}`` * tuple or list: ``(label, value, [type], [disabled])`` @@ -405,52 +424,66 @@ def _parse_action_buttons(buttons): def actions(label='', buttons=None, name=None, help_text=None): - r"""按钮选项。 + r"""Actions selection 在表单上显示为一组按钮,用户点击按钮后依据按钮类型的不同有不同的表现。 + + It is displayed as a group of buttons on the page. After the user clicks the button of it, it will behave differently depending on the type of the button. + + :param list buttons: list of buttons. The available formats of the list items are: - :param list buttons: 按钮列表。列表项的可用形式有: + * dict:: - * dict: ``{label:按钮标签, value:按钮值, [type: 按钮类型], [disabled:是否禁止选择]}`` . - 若 ``type='reset'/'cancel'`` 或 ``disabled=True`` 可省略 ``value`` + { + "label":(str) button label, + "value":(object) button value, + "type":(str, optional) button type, + "disabled":(bool, optional) whether the button is disabled + } + + When ``type='reset'/'cancel'`` or ``disabled=True``, ``value`` can be omitted * tuple or list: ``(label, value, [type], [disabled])`` - * 单值: 此时label和value使用相同的值 + * single value: label and value of button use the same value - 其中, ``value`` 可以为任意可JSON序列化的对象。 ``type`` 可选值为: + The ``value`` of button can be any JSON serializable object. - * ``'submit'`` : 点击按钮后,立即将整个表单提交,最终表单中本项的值为被点击按钮的 ``value`` 值。 ``'submit'`` 为 ``type`` 的默认值 - * ``'cancel'`` : 取消输入。点击按钮后,立即将整个表单提交,表单值返回 ``None`` - * ``'reset'`` : 点击按钮后,将整个表单重置,输入项将变为初始状态。 - 注意:点击 ``type=reset`` 的按钮后,并不会提交表单, ``actions()`` 调用也不会返回 + ``type`` can be: - :param - label, name, help_text: 与 `input` 输入函数的同名参数含义一致 - :return: 若用户点击点击 ``type=submit`` 按钮进行表单提交,返回用户点击的按钮的值; - 若用户点击 ``type=cancel`` 按钮或通过其它方式提交表单,则返回 ``None`` + * ``'submit'`` : After clicking the button, the entire form is submitted immediately, and the value of this input item in the final form is the ``value`` of the button that was clicked. ``'submit'`` is the default value of ``type`` + * ``'cancel'`` : Cancel form. After clicking the button, the entire form will be submitted immediately, and the form value will return ``None`` + * ``'reset'`` : Reset form. After clicking the button, the entire form will be reset, and the input items will become the initial state. + Note: After clicking the ``type=reset`` button, the form will not be submitted, and the ``actions()`` call will not return + + :param - label, name, help_text: Those arguments have the same meaning as for `input()` + :return: If the user clicks the ``type=submit`` button to submit the form, return the value of the button clicked by the user. If the user clicks the ``type=cancel`` button or submits the form by other means, ``None`` is returned. 当 ``actions()`` 作为 `input_group()` 中的最后一个输入项、并且含有 ``type='submit'`` 的按钮时,`input_group()` 表单默认的提交按钮会被当前 ``actions()`` 替换 - **actions使用场景** + When ``actions()`` is used as the last input item in `input_group()` and contains a button with ``type='submit'``, the default submit button of the `input_group()` form will be replace with the current ``actions()`` + + **usage scenes of ``actions()``** .. _custom_form_ctrl_btn: - * 实现简单的选择操作: + * Perform simple selection operations: .. exportable-codeblock:: :name: actions-select - :summary: 使用`actions()`实现简单的选择操作 + :summary: Use `actions()` to perform simple selection - confirm = actions('确认删除文件?', ['确认', '取消'], help_text='文件删除后不可恢复') - if confirm=='确认': # ..doc-only + confirm = actions('Confirm to delete file?', ['confirm', 'cancel'], help_text='Unrecoverable after file deletion') + if confirm=='confirm': # ..doc-only ... # ..doc-only put_markdown('点击了`%s`按钮' % confirm) # ..demo-only 相比于其他输入项,使用 `actions()` 用户只需要点击一次就可完成提交。 + Compared with other input items, when using `actions()`, the user just needs to click once to complete the submission. - * 替换默认的提交按钮: + * Replace the default submit button: .. exportable-codeblock:: :name: actions-submit - :summary: 使用`actions()`替换默认的提交按钮 + :summary: Use `actions()` to replace the default submit button import json # ..demo-only # ..demo-only @@ -458,18 +491,18 @@ def actions(label='', buttons=None, name=None, help_text=None): input('username', type=TEXT, name='username', required=True), input('password', type=PASSWORD, name='password', required=True), actions('actions', [ - {'label': '保存', 'value': 'save'}, - {'label': '保存并添加下一个', 'value': 'save_and_continue'}, - {'label': '重置', 'type': 'reset'}, - {'label': '取消', 'type': 'cancel'}, + {'label': 'Save', 'value': 'save'}, + {'label': 'Save and add next', 'value': 'save_and_continue'}, + {'label': 'Reset', 'type': 'reset'}, + {'label': 'Cancel', 'type': 'cancel'}, ], name='action', help_text='actions'), ]) put_code('info = ' + json.dumps(info, indent=4)) if info is not None: save_user(info['username'], info['password']) # ..doc-only - if info['action'] == 'save_and_continue': # 选择了"保存并添加下一个" + if info['action'] == 'save_and_continue': add_next() # ..doc-only - put_text('选择了"保存并添加下一个"') # ..demo-only + put_text('Save and add next...') # ..demo-only """ assert buttons is not None, 'Required `buttons` parameter in actions()' @@ -487,6 +520,7 @@ def _parse_file_size(size): assert isinstance(size, str), '`size` must be int/float/str, got %s' % type(size) size = size.lower() + for idx, i in enumerate(['k', 'm', 'g'], 1): if i in size: s = size.replace(i, '') @@ -498,44 +532,42 @@ def _parse_file_size(size): def file_upload(label='', accept=None, name=None, placeholder='Choose file', multiple=False, max_size=0, max_total_size=0, required=None, help_text=None, **other_html_attrs): - r"""文件上传。 + r"""File uploading - :param accept: 单值或列表, 表示可接受的文件类型。文件类型的可用形式有: + :param accept: Single value or list, indicating acceptable file types. The available formats of file types are: - * 以 ``.`` 字符开始的文件扩展名(例如:``.jpg, .png, .doc``)。 - 注意:截至本文档编写之时,微信内置浏览器还不支持这种语法 - * 一个有效的 MIME 类型。 - 例如: ``application/pdf`` 、 ``audio/*`` 表示音频文件、``video/*`` 表示视频文件、``image/*`` 表示图片文件。 - 参考 https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types + * A valid case-insensitive filename extension, starting with a period (".") character. For example: ``.jpg``, ``.pdf``, or ``.doc``. + * A valid MIME type string, with no extensions. + For examples: ``application/pdf``, ``audio/*``, ``video/*``, ``image/*``. + For more information, please visit: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types :type accept: str or list - :param str placeholder: 未上传文件时,文件上传框内显示的文本 - :param bool multiple: 是否允许多文件上传 - :param int/str max_size: 单个文件的最大大小,超过限制将会禁止上传。默认为0,表示不限制上传文件的大小。 + :param str placeholder: A hint to the user of what to be uploaded. It will appear in the input field when there is no file selected. + :param bool multiple: Whether to allow upload multiple files. Default is ``False``. + :param int/str max_size: The maximum size of a single file, exceeding the limit will prohibit uploading. The default is 0, which means there is no limit to the size. - ``max_size`` 值可以为数字表示的字节数,或以 `K` / `M` / `G` 结尾表示的字符串(分别表示 千字节、兆字节、吉字节,大小写不敏感)。例如: - ``max_size=500`` , ``max_size='40K'`` , ``max_size='3M'`` + ``max_size`` can be a integer indicating the number of bytes, or a case-insensitive string ending with `K` / `M` / `G` (representing kilobytes, megabytes, and gigabytes, respectively). + E.g: ``max_size=500``, ``max_size='40K'``, ``max_size='3M'`` - :param int/str max_total_size: 所有文件的最大大小,超过限制将会禁止上传。仅在 ``multiple=True`` 时可用,默认不限制上传文件的大小。 格式同 ``max_size`` 参数 - :param bool required: 是否必须要上传文件。默认为 `False` - :param - label, name, help_text, other_html_attrs: 与 `input` 输入函数的同名参数含义一致 - :return: ``multiple=False`` 时(默认),返回dict:: + :param int/str max_total_size: The maximum size of all files. Only available when ``multiple=True``. The default is 0, which means there is no limit to the size. The format is the same as the ``max_size`` parameter + :param bool required: Indicates whether the user must specify a file for the input. Default is `False`. + :param - label, name, help_text, other_html_attrs: Those arguments have the same meaning as for `input()` + :return: When ``multiple=False``, a dict is returned:: { - 'filename': 文件名, - 'content':文件二进制数据(bytes object), - 'mime_type': 文件的MIME类型, - 'last_modified': 文件上次修改时间(时间戳) + 'filename': file name, + 'content':content of the file(bytes object), + 'mime_type': MIME type of the file, + 'last_modified': Last modified time(timestamp) of the file } - 若用户没有上传文件,返回 ``None`` 。 + If there is no file uploaded, return ``None``. - ``multiple=True`` 时,返回列表,列表项格式同上文 ``multiple=False`` 时的返回值;若用户没有上传文件,返回空列表。 + When ``multiple=True``, a list is returned. The format of the list item is the same as the return value when ``multiple=False`` above. If the user does not upload a file, an empty list is returned. .. note:: - 若上传大文件请留意Web框架的文件上传大小限制设置。在使用 :func:`start_server ` 启动PyWebIO应用时, - 可通过 `websocket_max_message_size` 参数设置允许上传的最大文件大小 + If uploading large files, please pay attention to the file upload size limit setting of the web framework. When using :func:`start_server ` to start the PyWebIO application, the maximum file size to be uploaded allowed by the web framework can be set through the `websocket_max_message_size` parameter """ item_spec, valid_func = _parse_args(locals()) @@ -559,23 +591,26 @@ def read_file(data): # data: None or [{'filename':, 'dataurl', 'mime_type', 'la def input_group(label='', inputs=None, validate=None, cancelable=False): - r"""输入组。向页面上展示一组输入 + r"""Input group. Request a set of inputs from the user at once. - :param str label: 输入组标签 - :param list inputs: 输入项列表。列表的内容为对单项输入函数的调用,并在单项输入函数中传入 ``name`` 参数。 - :param callable validate: 输入组校验函数。 - 函数签名:``callback(data) -> (name, error_msg)`` + :param str label: Label of input group. + :param list inputs: Input items. + The item of the list is the call to the single input function, and the ``name`` parameter need to be passed in the single input function. + :param callable validate: validation function for the group. If provided, the validation function will be called when the user submits the form. + + Function signature: ``callback(data) -> (name, error_msg)``. ``validate`` 接收整个表单的值为参数,当校验表单值有效时,返回 ``None`` ,当某项输入值无效时,返回出错输入项的 ``name`` 值和错误提示. 比如: + ``validate`` receives the value of the entire group as a parameter. When the form value is valid, it returns ``None``. When an input item's value is invalid, it returns the ``name`` value of the item and an error message. For example: .. exportable-codeblock:: :name: input_group-valid_func - :summary: `input_group()`输入组校验 + :summary: `input_group()` form validation def check_form(data): if len(data['name']) > 6: - return ('name', '名字太长!') + return ('name', 'Name to long!') if data['age'] <= 0: - return ('age', '年龄不能为负数!') + return ('age', 'Age cannot be negative!') data = input_group("Basic info",[ input('Input your name', name='name'), @@ -584,10 +619,11 @@ def check_form(data): put_text(data['name'], data['age']) - :param bool cancelable: 表单是否可以取消。若 ``cancelable=True`` 则会在表单底部显示一个"取消"按钮。 - 注意:若 ``inputs`` 中最后一项输入为 `actions()` ,则忽略 ``cancelable`` + :param bool cancelable: Whether the form can be cancelled. Default is False. If ``cancelable=True``, a "Cancel" button will be displayed at the bottom of the form. + + Note: If the last input item in the group is `actions()`, ``cancelable`` will be ignored. - :return: 若用户取消表单,返回 ``None`` ,否则返回一个 ``dict`` , 其键为输入项的 ``name`` 值,字典值为输入项的值 + :return: If the user cancels the form, return ``None``, otherwise a ``dict`` is returned, whose key is the ``name`` of the input item, and whose value is the value of the input item. """ assert inputs is not None, 'Required `inputs` parameter in input_group()' @@ -596,7 +632,9 @@ def check_form(data): item_valid_funcs = {} for single_input_return in inputs: try: - single_input_return.send(None) # 协程模式下,带有name参数的单项输入函数通过send(None)来获取协程参数 + # 协程模式下,单项输入为协程对象,可以通过send(None)来获取传入单项输入的参数字典 + # In the coroutine mode, the item of `inputs` is coroutine object. using `send(None)` to get the single input function's parameter dict. + single_input_return.send(None) except StopIteration as e: input_kwargs = e.args[0] except AttributeError: @@ -616,9 +654,9 @@ def check_form(data): item_valid_funcs[input_name] = input_kwargs['valid_func'] spec_inputs.append(input_kwargs['item_spec']) - if all('auto_focus' not in i for i in spec_inputs): # 每一个输入项都没有设置auto_focus参数 + if all('auto_focus' not in i for i in spec_inputs): # No `auto_focus` parameter is set for each input item for i in spec_inputs: - text_inputs = {TEXT, NUMBER, PASSWORD, SELECT, URL} # todo update + text_inputs = {TEXT, NUMBER, PASSWORD, SELECT, URL, FLOAT, DATE, TIME} if i.get('type') in text_inputs: i['auto_focus'] = True break diff --git a/pywebio/output.py b/pywebio/output.py index 5a7d968c..067a8a90 100644 --- a/pywebio/output.py +++ b/pywebio/output.py @@ -1,78 +1,78 @@ -r"""输出内容到用户浏览器 +r""" +This module provides a series of functions to output all kinds of content to the user's browser, and supply flexible output control. -本模块提供了一系列函数来输出不同形式的内容到用户浏览器,并支持灵活的输出控制。 - -函数清单 --------------- +Functions list +--------------- .. Use https://www.tablesgenerator.com/text_tables to generate/update below table -+-------------+------------------+---------------------------------------------------------+ -| | **函数** | **简介** | -+-------------+------------------+---------------------------------------------------------+ -| 输出域Scope | `set_scope` | 创建一个新的scope. | -| +------------------+---------------------------------------------------------+ -| | `get_scope` | 获取当前运行时scope栈中的scope名 | -| +------------------+---------------------------------------------------------+ -| | `clear` | 清空scope内容 | -| +------------------+---------------------------------------------------------+ -| | `remove` | 移除Scope | -| +------------------+---------------------------------------------------------+ -| | `scroll_to` | 将页面滚动到 scope Scope处 | -| +------------------+---------------------------------------------------------+ -| | `use_scope` | 开启/进入输出域 | -+-------------+------------------+---------------------------------------------------------+ -| 内容输出 | `put_text` | 输出文本 | -| +------------------+---------------------------------------------------------+ -| | `put_markdown` | 输出Markdown | -| +------------------+---------------------------------------------------------+ -| | `put_html` | 输出Html | -| +------------------+---------------------------------------------------------+ -| | `put_link` | 输出链接 | -| +------------------+---------------------------------------------------------+ -| | `put_processbar` | 输出进度条 | -| +------------------+---------------------------------------------------------+ -| | `set_processbar` | 设置进度条进度 | -| +------------------+---------------------------------------------------------+ -| | `put_loading` | 输出加载提示 | -| +------------------+---------------------------------------------------------+ -| | `put_code` | 输出代码块 | -| +------------------+---------------------------------------------------------+ -| | `put_table` | 输出表格 | -| +------------------+---------------------------------------------------------+ -| | `put_buttons` | 输出一组按钮,并绑定点击事件 | -| +------------------+---------------------------------------------------------+ -| | `put_image` | 输出图片 | -| +------------------+---------------------------------------------------------+ -| | `put_file` | 显示一个文件下载链接 | -| +------------------+---------------------------------------------------------+ -| | `put_collapse` | 输出可折叠的内容 | -| +------------------+---------------------------------------------------------+ -| | `put_scrollable` | 固定高度内容输出区域,内容超出则显示滚动条 | -| +------------------+---------------------------------------------------------+ -| | `put_widget` | 输出自定义的控件 | -+-------------+------------------+---------------------------------------------------------+ -| 其他交互 | `toast` | 显示一条通知消息 | -| +------------------+---------------------------------------------------------+ -| | `popup` | 显示弹窗 | -| +------------------+---------------------------------------------------------+ -| | `close_popup` | 关闭正在显示的弹窗 | -+-------------+------------------+---------------------------------------------------------+ -| 布局与样式 | `put_row` | 使用行布局输出内容 | -| +------------------+---------------------------------------------------------+ -| | `put_column` | 使用列布局输出内容 | -| +------------------+---------------------------------------------------------+ -| | `put_grid` | 使用网格布局输出内容 | -| +------------------+---------------------------------------------------------+ -| | `span` | 在 `put_table()` 和 `put_grid()` 中设置内容跨单元格 | -| +------------------+---------------------------------------------------------+ -| | `style` | 自定义输出内容的css样式 | -+-------------+------------------+---------------------------------------------------------+ -| 其他 | `output` | 内容占位符 | -+-------------+------------------+---------------------------------------------------------+ - - -输出域Scope ++--------------------+------------------+------------------------------------------------------------+ +| | **Name** | **Description** | ++--------------------+------------------+------------------------------------------------------------+ +| Output Scope | `set_scope` | Create a new scope | +| +------------------+------------------------------------------------------------+ +| | `get_scope` | Get the scope name in the runtime scope stack | +| +------------------+------------------------------------------------------------+ +| | `clear` | Clear the content of scope | +| +------------------+------------------------------------------------------------+ +| | `remove` | Remove the scope | +| +------------------+------------------------------------------------------------+ +| | `scroll_to` | Scroll the page to the scope | +| +------------------+------------------------------------------------------------+ +| | `use_scope` | Open or enter a scope | ++--------------------+------------------+------------------------------------------------------------+ +| Content Outputting | `put_text` | Output plain text | +| +------------------+------------------------------------------------------------+ +| | `put_markdown` | Output Markdown | +| +------------------+------------------------------------------------------------+ +| | `put_html` | Output html | +| +------------------+------------------------------------------------------------+ +| | `put_link` | Output link | +| +------------------+------------------------------------------------------------+ +| | `put_processbar` | Output a process bar | +| +------------------+------------------------------------------------------------+ +| | `set_processbar` | Set the progress of progress bar | +| +------------------+------------------------------------------------------------+ +| | `put_loading` | Output loading prompt | +| +------------------+------------------------------------------------------------+ +| | `put_code` | Output code block | +| +------------------+------------------------------------------------------------+ +| | `put_table` | Output table | +| +------------------+------------------------------------------------------------+ +| | `put_buttons` | Output a group of buttons and bind click event | +| +------------------+------------------------------------------------------------+ +| | `put_image` | Output image | +| +------------------+------------------------------------------------------------+ +| | `put_file` | Output a link to download a file | +| +------------------+------------------------------------------------------------+ +| | `put_collapse` | Output collapsible content | +| +------------------+------------------------------------------------------------+ +| | `put_scrollable` | | Output a fixed height content area, | +| | | | scroll bar is displayed when the content | +| | | | exceeds the limit | +| +------------------+------------------------------------------------------------+ +| | `put_widget` | Output your own widget | ++--------------------+------------------+------------------------------------------------------------+ +| Other Interactions | `toast` | Show a notification message | +| +------------------+------------------------------------------------------------+ +| | `popup` | Show popup | +| +------------------+------------------------------------------------------------+ +| | `close_popup` | Close the current popup window. | ++--------------------+------------------+------------------------------------------------------------+ +| Layout and Style | `put_row` | Use row layout to output content | +| +------------------+------------------------------------------------------------+ +| | `put_column` | Use column layout to output content | +| +------------------+------------------------------------------------------------+ +| | `put_grid` | Output content using grid layout | +| +------------------+------------------------------------------------------------+ +| | `span` | Cross-cell content | +| +------------------+------------------------------------------------------------+ +| | `style` | Customize the css style of output content | ++--------------------+------------------+------------------------------------------------------------+ +| Other | `output` | Placeholder of output | ++--------------------+------------------+------------------------------------------------------------+ + +Output Scope -------------- .. autofunction:: set_scope .. autofunction:: get_scope @@ -81,8 +81,8 @@ .. autofunction:: scroll_to .. autofunction:: use_scope -内容输出 --------------- +Content Outputting +----------------------- .. autofunction:: put_text .. autofunction:: put_markdown .. autofunction:: put_html @@ -100,22 +100,22 @@ .. autofunction:: put_scrollable .. autofunction:: put_widget -其他交互 --------------- +Other Interactions +-------------------- .. autofunction:: toast .. autofunction:: popup .. autofunction:: close_popup .. _style_and_layout: -布局与样式 --------------- +Layout and Style +------------------ .. autofunction:: put_row .. autofunction:: put_column .. autofunction:: put_grid .. autofunction:: style -其他 +Other -------------- .. autofunction:: output @@ -148,7 +148,7 @@ 'output', 'toast', 'get_scope'] -# popup尺寸 +# popup size class PopupSize: LARGE = 'large' NORMAL = 'normal' @@ -161,7 +161,7 @@ class Position: BOTTOM = 'bottom' -# put_xxx()中的position值 +# position value of `put_xxx()` class OutputPosition: TOP = 0 BOTTOM = -1 @@ -177,9 +177,10 @@ class Scope: def _parse_scope(name, no_css_selector=False): - """获取实际用于前端html页面中的CSS选择器/元素名 + """Get the CSS selector/element name actually used in the front-end html page - name 为str/tuple,为str时,视作Dom ID名; tuple格式为(css选择器符号, 元素名),仅供内部实现使用 + :param str/tuple name: When it is str, it is regarded as the Dom ID name; + when tuple, the format is (css selector, element name) """ selector = '#' if isinstance(name, tuple): @@ -194,21 +195,20 @@ def _parse_scope(name, no_css_selector=False): def set_scope(name, container_scope=Scope.Current, position=OutputPosition.BOTTOM, if_exist=None): - """创建一个新的scope. - - :param str name: scope名 - :param int/str container_scope: 指定此scope的父scope. 可以直接指定父scope名或使用int索引运行时scope栈(参见 :ref:`输出函数的scope相关参数 `). scope不存在时,不进行任何操作. - :param int position: 在父scope中创建此scope的位置. - 可选值: `OutputPosition.TOP` : 在父scope的顶部创建, `OutputPosition.BOTTOM`: 在父scope的底部创建。 - 也可以直接使用int来索引位置(参见 :ref:`输出函数的scope相关参数 `) - :param str if_exist: 已经存在 ``name`` scope 时如何操作: + """Create a new scope. - - `None` 表示不进行任何操作 - - `'remove'` 表示先移除旧scope再创建新scope - - `'clear'` 表示将旧scope的内容清除,不创建新scope + :param str name: scope name + :param int/str container_scope: Specify the parent scope of this scope. You can use the scope name or use a integer to index the runtime scope stack (see :ref:`User Guide `). When the scope does not exist, no operation is performed. + :param int position: The location where this scope is created in the parent scope. + Available values: `OutputPosition.TOP`: created at the top of the parent scope, `OutputPosition.BOTTOM`: created at the bottom of the parent scope. + You can also use a integer to index the position (see :ref:`User Guide `) + :param str if_exist: What to do when the specified scope already exists: - 默认为 `None` + - `None`: Do nothing + - `'remove'`: Remove the old scope first and then create a new one + - `'clear'`: Just clear the contents of the old scope, but don't create a new scope + Default is `None` """ if isinstance(container_scope, int): container_scope = get_current_session().get_scope_name(container_scope) @@ -220,12 +220,14 @@ def set_scope(name, container_scope=Scope.Current, position=OutputPosition.BOTTO def get_scope(stack_idx=Scope.Current): - """获取当前运行时scope栈中的scope名 + """Get the scope name of runtime scope stack - :param int stack_idx: 需要获取的scope在scope栈中的索引值。默认返回当前scope名 + :param int stack_idx: The index of the runtime scope stack. Default is -1. - -1表示当前scope,-2表示进入当前scope前的scope,依次类推;0表示 `ROOT` scope - :return: 返回Scope栈中对应索引的scope名,索引错误时返回None + 0 means the top level scope(the ROOT Scope), + -1 means the current Scope, + -2 means the scope used before entering the current scope, … + :return: Returns the scope name with the index, and returns ``None`` when occurs index error """ try: return get_current_session().get_scope_name(stack_idx) @@ -234,9 +236,9 @@ def get_scope(stack_idx=Scope.Current): def clear(scope=Scope.Current): - """清空scope内容 + """Clear the content of the specified scope - :param int/str scope: 可以直接指定scope名或使用int索引运行时scope栈(参见 :ref:`输出函数的scope相关参数 `) + :param int/str scope: Can specify the scope name or use a integer to index the runtime scope stack (see :ref:`User Guide `) """ if isinstance(scope, int): scope = get_current_session().get_scope_name(scope) @@ -244,9 +246,9 @@ def clear(scope=Scope.Current): def remove(scope=Scope.Current): - """移除Scope + """Remove the specified scope - :param int/str scope: 可以直接指定scope名或使用int索引运行时scope栈(参见 :ref:`输出函数的scope相关参数 `) + :param int/str scope: Can specify the scope name or use a integer to index the runtime scope stack (see :ref:`User Guide `) """ if isinstance(scope, int): scope = get_current_session().get_scope_name(scope) @@ -256,14 +258,14 @@ def remove(scope=Scope.Current): def scroll_to(scope=Scope.Current, position=Position.TOP): """ - 将页面滚动到 ``scope`` Scope处 + Scroll the page to the specified scope - :param str/int scope: 可以直接指定scope名或使用int索引运行时scope栈(参见 :ref:`输出函数的scope相关参数 `) - :param str position: 将Scope置于屏幕可视区域的位置。可用值: + :param str/int scope: Target scope. Can specify the scope name or use a integer to index the runtime scope stack (see :ref:`User Guide `) + :param str position: Where to place the scope in the visible area of the page. Available value: - * ``'top'`` : 滚动页面,让Scope位于屏幕可视区域顶部 - * ``'middle'`` : 滚动页面,让Scope位于屏幕可视区域中间 - * ``'bottom'`` : 滚动页面,让Scope位于屏幕可视区域底部 + * ``'top'`` : Keep the scope at the top of the visible area of the page + * ``'middle'`` : Keep the scope at the middle of the visible area of the page + * ``'bottom'`` : Keep the scope at the bottom of the visible area of the page """ if isinstance(scope, int): scope = get_current_session().get_scope_name(scope) @@ -272,18 +274,18 @@ def scroll_to(scope=Scope.Current, position=Position.TOP): def _get_output_spec(type, scope, position, **other_spec): """ - 获取输出类指令的spec字段 + get the spec dict of output functions - :param str type: 输出类型 - :param int/str scope: 输出到的scope - :param int position: 在scope输出的位置, `OutputPosition.TOP` : 输出到scope的顶部, `OutputPosition.BOTTOM` : 输出到scope的尾部 - :param other_spec: 额外的输出参数,值为None的参数不会包含到返回值中 + :param str type: output type + :param int/str scope: target scope + :param int position: + :param other_spec: Additional output parameters, the None value will not be included in the return value - :return dict: ``output`` 指令的spec字段 + :return dict: ``spec`` field of ``output`` command """ spec = dict(type=type) - # 将非None的参数加入SPEC中 + # add non-None arguments to spec spec.update({k: v for k, v in other_spec.items() if v is not None}) if isinstance(scope, int): @@ -299,19 +301,17 @@ def _get_output_spec(type, scope, position, **other_spec): def put_text(*texts, sep=' ', inline=False, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output: """ - 输出文本内容 - - :param texts: 要输出的内容。类型可以为任意对象,对非字符串对象会应用 `str()` 函数作为输出值。 - :param str sep: 输出分隔符 - :param bool inline: 将文本作为行内元素(文本行末不换行)。默认换行 - :param int/str scope: 内容输出的目标scope,若scope不存在,则不进行任何输出操作。 + Output plain text - 可以直接指定目标Scope名,或者使用int通过索引Scope栈来确定Scope:0表示最顶层也就是ROOT Scope,-1表示当前Scope,-2表示进入当前Scope的前一个Scope,... - :param int position: 在scope中输出的位置。 + :param texts: Texts need to output. The type can be any object, and the `str()` function will be used for non-string objects. + :param str sep: The separator between the texts + :param bool inline: Use text as an inline element (no line break at the end of the text). Default is ``False`` + :param int/str scope: The target scope to output. If the scope does not exist, no operation will be performed. - position>=0时表示输出到scope的第position个(从0计数)子元素的前面;position<0时表示输出到scope的倒数第position个(从-1计数)元素之后。 + Can specify the scope name or use a integer to index the runtime scope stack. + :param int position: The position where the content is output in target scope - 参数 `scope` 和 `position` 的更多使用说明参见 :ref:`用户手册 ` + For more information about ``scope`` and ``position`` parameter, please refer to :ref:`User Manual ` """ content = sep.join(str(i) for i in texts) spec = _get_output_spec('text', content=content, inline=inline, scope=scope, position=position) @@ -320,13 +320,11 @@ def put_text(*texts, sep=' ', inline=False, scope=Scope.Current, position=Output def put_html(html, sanitize=False, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output: """ - 输出Html内容。 + Output HTML content - 与支持通过Html输出内容到 `Jupyter Notebook `_ 的库兼容。 - - :param html: html字符串或实现了 `IPython.display.HTML` 接口的实例 - :param bool sanitize: 是否使用 `DOMPurify `_ 对内容进行过滤来防止XSS攻击。 - :param int scope, position: 与 `put_text` 函数的同名参数含义一致 + :param html: html string + :param bool sanitize: Whether to use `DOMPurify `_ to filter the content to prevent XSS attacks. + :param int scope, position: Those arguments have the same meaning as for `put_text()` """ if hasattr(html, '__html__'): html = html.__html__() @@ -337,53 +335,44 @@ def put_html(html, sanitize=False, scope=Scope.Current, position=OutputPosition. def put_code(content, language='', scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output: """ - 输出代码块 + Output code block - :param str content: 代码内容 - :param str language: 代码语言 - :param int scope, position: 与 `put_text` 函数的同名参数含义一致 + :param str content: code string + :param str language: language of code + :param int scope, position: Those arguments have the same meaning as for `put_text()` """ - if not isinstance(content, str): - content = str(content) - - # For fenced code blocks, escaping the backtick need to use more backticks - backticks = '```' - while backticks in content: - backticks += '`' - - code = "%s%s\n%s\n%s" % (backticks, language, content, backticks) + code = "```%s\n%s\n```" % (language, content) return put_markdown(code, scope=scope, position=position) def put_markdown(mdcontent, strip_indent=0, lstrip=False, options=None, sanitize=True, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output: """ - 输出Markdown内容。 + Output Markdown - :param str mdcontent: Markdown文本 - :param int strip_indent: 对于每一行,若前 ``strip_indent`` 个字符都为空格,则将其去除 - :param bool lstrip: 是否去除每一行开始的空白符 - :param dict options: 解析Markdown时的配置参数。 - PyWebIO使用 `marked `_ 解析Markdown, 可配置项参见: https://marked.js.org/using_advanced#options (仅支持配置string和boolean类型的项) - :param bool sanitize: 是否使用 `DOMPurify `_ 对内容进行过滤来防止XSS攻击。 - :param int scope, position: 与 `put_text` 函数的同名参数含义一致 + :param str mdcontent: Markdown string + :param int strip_indent: For each line of ``mdcontent``, if the first ``strip_indent`` characters are spaces, remove them + :param bool lstrip: Whether to remove the whitespace at the beginning of each line of ``mdcontent`` + :param dict options: Configuration when parsing Markdown. + PyWebIO uses `marked `_ library to parse Markdown, the parse options see: https://marked.js.org/using_advanced#options (Only supports members of string and boolean type) + :param bool sanitize: Whether to use `DOMPurify `_ to filter the content to prevent XSS attacks. + :param int scope, position: Those arguments have the same meaning as for `put_text()` - 当在函数中使用Python的三引号语法输出多行内容时,为了排版美观可能会对Markdown文本进行缩进, - 这时候,可以设置 ``strip_indent`` 或 ``lstrip`` 来防止Markdown错误解析(但不要同时使用 ``strip_indent`` 和 ``lstrip`` ):: + When using Python triple quotes syntax to output multi-line Markdown in a function, if you indent the Markdown text, you can use ``strip_indent`` or ``lstrip`` to prevent Markdown from parsing errors (But do not use ``strip_indent`` and ``lstrip`` at the same time):: - # 不使用strip_indent或lstrip + # It is ugly without strip_indent or lstrip def hello(): put_markdown(r\""" # H1 This is content. \""") - # 使用lstrip + # Using lstrip to get beautiful indent def hello(): put_markdown(r\""" # H1 This is content. \""", lstrip=True) - # 使用strip_indent + # Using strip_indent to get beautiful indent def hello(): put_markdown(r\""" # H1 This is content. @@ -411,26 +400,26 @@ def __init__(self, content, row=1, col=1): @safely_destruct_output_when_exp('content') def span(content, row=1, col=1): - """用于在 :func:`put_table()` 和 :func:`put_grid()` 中设置内容跨单元格 - - :param content: 单元格内容。可以为字符串或 ``put_xxx()`` 调用。 - :param int row: 竖直方向跨度, 即:跨行的数目 - :param int col: 水平方向跨度, 即:跨列的数目 + """Create cross-cell content in :func:`put_table()` and :func:`put_grid()` + + :param content: cell content. It can be a string or ``put_xxx()`` call. + :param int row: Vertical span, that is, the number of spanning rows + :param int col: Horizontal span, that is, the number of spanning columns :Example: .. exportable-codeblock:: :name: span - :summary: 使用`span()`合并单元格 + :summary: Create cross-cell content with `span()` put_table([ ['C'], - [span('E', col=2)], # 'E' 跨2列 - ], header=[span('A', row=2), 'B']) # 'A' 跨2行 + [span('E', col=2)], # 'E' across 2 columns + ], header=[span('A', row=2), 'B']) # 'A' across 2 rows put_grid([ [put_text('A'), put_text('B')], - [span(put_text('A'), col=2)], # 'A' 跨2列 + [span(put_text('A'), col=2)], # 'A' across 2 columns ]) """ @@ -440,25 +429,25 @@ def span(content, row=1, col=1): @safely_destruct_output_when_exp('tdata') def put_table(tdata, header=None, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output: """ - 输出表格 + Output table - :param list tdata: 表格数据。列表项可以为 ``list`` 或者 ``dict`` , 单元格的内容可以为字符串或 ``put_xxx`` 类型的输出函数。 - 数组项可以使用 :func:`span()` 函数来设定单元格跨度。 - :param list header: 设定表头。 - 当 ``tdata`` 的列表项为 ``list`` 类型时,若省略 ``header`` 参数,则使用 ``tdata`` 的第一项作为表头。表头项可以使用 :func:`span()` 函数来设定单元格跨度。 + :param list tdata: Table data, which can be a two-dimensional list or a list of dict. + The table cell can be a string or ``put_xxx()`` call. The cell can use the :func:`span()` to set the cell span. + :param list header: Table header. + When the item of ``tdata`` is of type ``list``, if the ``header`` parameter is omitted, the first item of ``tdata`` will be used as the header. The header item can also use the :func:`span()` function to set the cell span. - 当 ``tdata`` 为字典列表时,使用 ``header`` 指定表头顺序,不可省略。 - 此时, ``header`` 格式可以为 <字典键>列表 或者 ``(<显示文本>, <字典键>)`` 列表。 + When ``tdata`` is list of dict, ``header`` is used to specify the order of table headers, which cannot be omitted. + In this case, the ``header`` can be a list of dict key or a list of ``(
@@ -60,13 +61,13 @@ export class File extends InputItem { that.valid = false; that.update_input_helper(-1, { 'valid_status': false, - 'invalid_feedback': `文件"${f.name}"大小超过限制: 单个文件大小不超过${that._formate_size(that.spec.max_size)}` + 'invalid_feedback': t("file_size_exceed", f.name, that._formate_size(that.spec.max_size)), }); } else if (that.spec.max_total_size && total_size > that.spec.max_total_size) { that.valid = false; that.update_input_helper(-1, { 'valid_status': false, - 'invalid_feedback': `文件总大小超过限制: 文件总大小不超过${that._formate_size(that.spec.max_total_size)}` + 'invalid_feedback': t("file_total_size_exceed",that._formate_size(that.spec.max_total_size)) }); return; } diff --git a/webiojs/src/session.ts b/webiojs/src/session.ts index e9536804..879b8b0b 100644 --- a/webiojs/src/session.ts +++ b/webiojs/src/session.ts @@ -1,5 +1,6 @@ import {error_alert} from "./utils"; import {state} from "./state"; +import {t} from "./i18n"; export interface Command { command: string @@ -97,7 +98,7 @@ export class WebSocketSession implements Session { send_message(msg: ClientEvent, onprogress?: (loaded: number, total: number) => void): void { if (this.closed()) - return error_alert("与服务器连接已断开,请刷新页面重新操作"); + return error_alert(t("disconnected_with_server")); if (this.ws === null) return console.error('WebSocketWebIOSession.ws is null when invoke WebSocketWebIOSession.send_message. ' + @@ -193,7 +194,7 @@ export class HttpSession implements Session { send_message(msg: ClientEvent, onprogress?: (loaded: number, total: number) => void): void { if (this.closed()) - return error_alert("与服务器连接已断开,请刷新页面重新操作"); + return error_alert(t("disconnected_with_server")); if (this.debug) console.info('<<<', msg); $.ajax({ @@ -216,7 +217,7 @@ export class HttpSession implements Session { }, error: function () { // todo console.error('Http push event failed, event data: %s', msg); - error_alert("连接服务器失败!"); + error_alert(t("connect_fail")); } }); From 81a88db82c20539fd55d73efaf812ddefe544e99 Mon Sep 17 00:00:00 2001 From: wangweimin Date: Tue, 2 Feb 2021 19:59:20 +0800 Subject: [PATCH 013/445] fix a typo --- .github/workflows/sync_repo.yml | 4 ++-- demos/doc_demo.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/sync_repo.yml b/.github/workflows/sync_repo.yml index 722c835c..13b843ae 100644 --- a/.github/workflows/sync_repo.yml +++ b/.github/workflows/sync_repo.yml @@ -23,7 +23,7 @@ jobs: - name: Build doc demos run: | pip3 install -e ".[all]" - cd docs && CODE_EXPORT_PATH=../demos/doc_domes make clean text + cd docs && CODE_EXPORT_PATH=../demos/doc_demos make clean text - name: Push run: | git fetch --unshallow origin @@ -31,7 +31,7 @@ jobs: git config credential.helper '!f() { sleep 1; echo "username=${ALIYUN_GIT_USER}"; echo "password=${ALIYUN_GIT_PASSWORD}"; }; f' rm .gitignore git add pywebio/html/js - git add demos/doc_domes + git add demos/doc_demos git config user.email "${ALIYUN_GIT_USER}" git config user.name "${ALIYUN_GIT_USER}" git commit --amend --no-edit diff --git a/demos/doc_demo.py b/demos/doc_demo.py index f5b1f38e..7a898b9a 100644 --- a/demos/doc_demo.py +++ b/demos/doc_demo.py @@ -82,13 +82,13 @@ def handle_code(code, title): def get_app(): app = {} try: - demos = listdir(path.join(here_dir, 'doc_domes')) + demos = listdir(path.join(here_dir, 'doc_demos')) except Exception: demos = [] demo_infos = [] for name in demos: - code = open(path.join(here_dir, 'doc_domes', name)).read() + code = open(path.join(here_dir, 'doc_demos', name)).read() title, code = code.split('\n\n', 1) app[name] = partial(handle_code, code=code, title=title) demo_infos.append([name, title]) From 9aa75e71e3e578d7e3d85bfe79b6d9588d41fee4 Mon Sep 17 00:00:00 2001 From: wangweimin Date: Wed, 3 Feb 2021 10:35:18 +0800 Subject: [PATCH 014/445] fix: utils.wait_host_port() not compatible below py3.7 --- pywebio/platform/tornado.py | 2 +- pywebio/utils.py | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pywebio/platform/tornado.py b/pywebio/platform/tornado.py index 969e3bca..8e256f41 100644 --- a/pywebio/platform/tornado.py +++ b/pywebio/platform/tornado.py @@ -138,7 +138,7 @@ def webio_handler(applications, allowed_origins=None, check_origin=None): async def open_webbrowser_on_server_started(host, port): url = 'http://%s:%s' % (host, port) - is_open = await wait_host_port(host, port, duration=30, delay=0.5) + is_open = await wait_host_port(host, port, duration=20) if is_open: logger.info('Try open %s in web browser' % url) webbrowser.open(url) diff --git a/pywebio/utils.py b/pywebio/utils.py index 631639e6..de490896 100644 --- a/pywebio/utils.py +++ b/pywebio/utils.py @@ -133,9 +133,14 @@ async def wait_host_port(host, port, duration=10, delay=2): tmax = time.time() + duration while time.time() < tmax: try: - _reader, writer = await asyncio.wait_for(asyncio.open_connection(host, port), timeout=5) + _, writer = await asyncio.wait_for(asyncio.open_connection(host, port), timeout=5) writer.close() - await writer.wait_closed() + + # asyncio.StreamWriter.wait_closed is introduced in py 3.7 + # See https://docs.python.org/3/library/asyncio-stream.html#asyncio.StreamWriter.wait_closed + if hasattr(writer, 'wait_closed'): + await writer.wait_closed() + return True except Exception: if delay: From 6883086a5138dcad1f1c161ef86c8cb2ea92dc76 Mon Sep 17 00:00:00 2001 From: wangweimin Date: Wed, 3 Feb 2021 13:40:32 +0800 Subject: [PATCH 015/445] feat: add markdown parse option to `put_markdown()` --- pywebio/html/css/markdown.min.css | 12 + pywebio/html/css/mditor.min.css | 8 - pywebio/html/index.html | 4 +- pywebio/html/js/highlight.min.js | 1296 +++++++++++++++++++++++++++++ pywebio/html/js/mditor.min.js | 11 - pywebio/output.py | 8 +- setup.py | 4 +- webiojs/gulpfile.js | 2 +- webiojs/package-lock.json | 66 ++ webiojs/package.json | 4 + webiojs/src/models/output.ts | 24 +- webiojs/src/vendor.d.ts | 4 +- 12 files changed, 1411 insertions(+), 32 deletions(-) create mode 100644 pywebio/html/css/markdown.min.css delete mode 100755 pywebio/html/css/mditor.min.css create mode 100644 pywebio/html/js/highlight.min.js delete mode 100755 pywebio/html/js/mditor.min.js diff --git a/pywebio/html/css/markdown.min.css b/pywebio/html/css/markdown.min.css new file mode 100644 index 00000000..2c51f175 --- /dev/null +++ b/pywebio/html/css/markdown.min.css @@ -0,0 +1,12 @@ +/** + * github-markdown-css - The minimal amount of CSS to replicate the GitHub Markdown style + * Copyright (c) Sindre Sorhus. (MIT Licensed) + * https://github.com/sindresorhus/github-markdown-css + */ +.markdown-body .octicon{display:inline-block;fill:currentColor;vertical-align:text-bottom}.markdown-body .anchor{float:left;line-height:1;margin-left:-20px;padding-right:4px}.markdown-body .anchor:focus{outline:0}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#1b1f23;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1:hover .anchor .octicon-link:before,.markdown-body h2:hover .anchor .octicon-link:before,.markdown-body h3:hover .anchor .octicon-link:before,.markdown-body h4:hover .anchor .octicon-link:before,.markdown-body h5:hover .anchor .octicon-link:before,.markdown-body h6:hover .anchor .octicon-link:before{width:16px;height:16px;content:' ';display:inline-block;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' width='16' height='16' aria-hidden='true'%3E%3Cpath fill-rule='evenodd' d='M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z'%3E%3C/path%3E%3C/svg%3E")}.markdown-body{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;line-height:1.5;color:#24292e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;font-size:16px;line-height:1.5;word-wrap:break-word}.markdown-body details{display:block}.markdown-body summary{display:list-item}.markdown-body a{background-color:initial}.markdown-body a:active,.markdown-body a:hover{outline-width:0}.markdown-body strong{font-weight:inherit;font-weight:bolder}.markdown-body h1{font-size:2em;margin:.67em 0}.markdown-body img{border-style:none}.markdown-body code,.markdown-body kbd,.markdown-body pre{font-family:monospace,monospace;font-size:1em}.markdown-body hr{box-sizing:initial;height:0;overflow:visible}.markdown-body input{font:inherit;margin:0}.markdown-body input{overflow:visible}.markdown-body [type=checkbox]{box-sizing:border-box;padding:0}.markdown-body *{box-sizing:border-box}.markdown-body input{font-family:inherit;font-size:inherit;line-height:inherit}.markdown-body a{color:#0366d6;text-decoration:none}.markdown-body a:hover{text-decoration:underline}.markdown-body strong{font-weight:600}.markdown-body hr{height:0;margin:15px 0;overflow:hidden;background:0 0;border:0;border-bottom:1px solid #dfe2e5}.markdown-body hr:after,.markdown-body hr:before{display:table;content:""}.markdown-body hr:after{clear:both}.markdown-body table{border-spacing:0;border-collapse:collapse}.markdown-body td,.markdown-body th{padding:0}.markdown-body details summary{cursor:pointer}.markdown-body kbd{display:inline-block;padding:3px 5px;font:11px SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:1px solid #d1d5da;border-radius:3px;box-shadow:inset 0 -1px 0 #d1d5da}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:0;margin-bottom:0}.markdown-body h1{font-size:32px}.markdown-body h1,.markdown-body h2{font-weight:600}.markdown-body h2{font-size:24px}.markdown-body h3{font-size:20px}.markdown-body h3,.markdown-body h4{font-weight:600}.markdown-body h4{font-size:16px}.markdown-body h5{font-size:14px}.markdown-body h5,.markdown-body h6{font-weight:600}.markdown-body h6{font-size:12px}.markdown-body p{margin-top:0;margin-bottom:10px}.markdown-body blockquote{margin:0}.markdown-body ol,.markdown-body ul{padding-left:0;margin-top:0;margin-bottom:0}.markdown-body ol ol,.markdown-body ul ol{list-style-type:lower-roman}.markdown-body ol ol ol,.markdown-body ol ul ol,.markdown-body ul ol ol,.markdown-body ul ul ol{list-style-type:lower-alpha}.markdown-body dd{margin-left:0}.markdown-body code,.markdown-body pre{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:12px}.markdown-body pre{margin-top:0;margin-bottom:0}.markdown-body input::-webkit-inner-spin-button,.markdown-body input::-webkit-outer-spin-button{margin:0;-webkit-appearance:none;appearance:none}.markdown-body :checked+.radio-label{position:relative;z-index:1;border-color:#0366d6}.markdown-body .border{border:1px solid #e1e4e8!important}.markdown-body .border-0{border:0!important}.markdown-body .border-bottom{border-bottom:1px solid #e1e4e8!important}.markdown-body .rounded-1{border-radius:3px!important}.markdown-body .bg-white{background-color:#fff!important}.markdown-body .bg-gray-light{background-color:#fafbfc!important}.markdown-body .text-gray-light{color:#6a737d!important}.markdown-body .mb-0{margin-bottom:0!important}.markdown-body .my-2{margin-top:8px!important;margin-bottom:8px!important}.markdown-body .pl-0{padding-left:0!important}.markdown-body .py-0{padding-top:0!important;padding-bottom:0!important}.markdown-body .pl-1{padding-left:4px!important}.markdown-body .pl-2{padding-left:8px!important}.markdown-body .py-2{padding-top:8px!important;padding-bottom:8px!important}.markdown-body .pl-3,.markdown-body .px-3{padding-left:16px!important}.markdown-body .px-3{padding-right:16px!important}.markdown-body .pl-4{padding-left:24px!important}.markdown-body .pl-5{padding-left:32px!important}.markdown-body .pl-6{padding-left:40px!important}.markdown-body .f6{font-size:12px!important}.markdown-body .lh-condensed{line-height:1.25!important}.markdown-body .text-bold{font-weight:600!important}.markdown-body .pl-c{color:#6a737d}.markdown-body .pl-c1,.markdown-body .pl-s .pl-v{color:#005cc5}.markdown-body .pl-e,.markdown-body .pl-en{color:#6f42c1}.markdown-body .pl-s .pl-s1,.markdown-body .pl-smi{color:#24292e}.markdown-body .pl-ent{color:#22863a}.markdown-body .pl-k{color:#d73a49}.markdown-body .pl-pds,.markdown-body .pl-s,.markdown-body .pl-s .pl-pse .pl-s1,.markdown-body .pl-sr,.markdown-body .pl-sr .pl-cce,.markdown-body .pl-sr .pl-sra,.markdown-body .pl-sr .pl-sre{color:#032f62}.markdown-body .pl-smw,.markdown-body .pl-v{color:#e36209}.markdown-body .pl-bu{color:#b31d28}.markdown-body .pl-ii{color:#fafbfc;background-color:#b31d28}.markdown-body .pl-c2{color:#fafbfc;background-color:#d73a49}.markdown-body .pl-c2:before{content:"^M"}.markdown-body .pl-sr .pl-cce{font-weight:700;color:#22863a}.markdown-body .pl-ml{color:#735c0f}.markdown-body .pl-mh,.markdown-body .pl-mh .pl-en,.markdown-body .pl-ms{font-weight:700;color:#005cc5}.markdown-body .pl-mi{font-style:italic;color:#24292e}.markdown-body .pl-mb{font-weight:700;color:#24292e}.markdown-body .pl-md{color:#b31d28;background-color:#ffeef0}.markdown-body .pl-mi1{color:#22863a;background-color:#f0fff4}.markdown-body .pl-mc{color:#e36209;background-color:#ffebda}.markdown-body .pl-mi2{color:#f6f8fa;background-color:#005cc5}.markdown-body .pl-mdr{font-weight:700;color:#6f42c1}.markdown-body .pl-ba{color:#586069}.markdown-body .pl-sg{color:#959da5}.markdown-body .pl-corl{text-decoration:underline;color:#032f62}.markdown-body .mb-0{margin-bottom:0!important}.markdown-body .my-2{margin-bottom:8px!important}.markdown-body .my-2{margin-top:8px!important}.markdown-body .pl-0{padding-left:0!important}.markdown-body .py-0{padding-top:0!important;padding-bottom:0!important}.markdown-body .pl-1{padding-left:4px!important}.markdown-body .pl-2{padding-left:8px!important}.markdown-body .py-2{padding-top:8px!important;padding-bottom:8px!important}.markdown-body .pl-3{padding-left:16px!important}.markdown-body .pl-4{padding-left:24px!important}.markdown-body .pl-5{padding-left:32px!important}.markdown-body .pl-6{padding-left:40px!important}.markdown-body .pl-7{padding-left:48px!important}.markdown-body .pl-8{padding-left:64px!important}.markdown-body .pl-9{padding-left:80px!important}.markdown-body .pl-10{padding-left:96px!important}.markdown-body .pl-11{padding-left:112px!important}.markdown-body .pl-12{padding-left:128px!important}.markdown-body hr{border-bottom-color:#eee}.markdown-body kbd{display:inline-block;padding:3px 5px;font:11px SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:1px solid #d1d5da;border-radius:3px;box-shadow:inset 0 -1px 0 #d1d5da}.markdown-body:after,.markdown-body:before{display:table;content:""}.markdown-body:after{clear:both}.markdown-body>:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body blockquote,.markdown-body details,.markdown-body dl,.markdown-body ol,.markdown-body p,.markdown-body pre,.markdown-body table,.markdown-body ul{margin-top:0;margin-bottom:16px}.markdown-body hr{height:.25em;padding:0;margin:24px 0;background-color:#e1e4e8;border:0}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid #dfe2e5}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body h1{font-size:2em}.markdown-body h1,.markdown-body h2{padding-bottom:.3em;border-bottom:1px solid #eaecef}.markdown-body h2{font-size:1.5em}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{font-size:.85em;color:#6a737d}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:0;margin-bottom:0}.markdown-body li{word-wrap:break-all}.markdown-body li>p{margin-top:16px}.markdown-body li+li{margin-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body table{display:block;width:100%;overflow:auto}.markdown-body table th{font-weight:600}.markdown-body table td,.markdown-body table th{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body img{max-width:100%;box-sizing:initial;background-color:#fff}.markdown-body img[align=right]{padding-left:20px}.markdown-body img[align=left]{padding-right:20px}.markdown-body code{padding:.2em .4em;margin:0;font-size:85%;background-color:rgba(27,31,35,.05);border-radius:3px}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:0 0;border:0}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:3px}.markdown-body pre code{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:initial;border:0}.markdown-body .commit-tease-sha{display:inline-block;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:90%;color:#444d56}.markdown-body .full-commit .btn-outline:not(:disabled):hover{color:#005cc5;border-color:#005cc5}.markdown-body .blob-wrapper{overflow-x:auto;overflow-y:hidden}.markdown-body .blob-wrapper-embedded{max-height:240px;overflow-y:auto}.markdown-body .blob-num{width:1%;min-width:50px;padding-right:10px;padding-left:10px;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:12px;line-height:20px;color:rgba(27,31,35,.3);text-align:right;white-space:nowrap;vertical-align:top;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.markdown-body .blob-num:hover{color:rgba(27,31,35,.6)}.markdown-body .blob-num:before{content:attr(data-line-number)}.markdown-body .blob-code{position:relative;padding-right:10px;padding-left:10px;line-height:20px;vertical-align:top}.markdown-body .blob-code-inner{overflow:visible;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:12px;color:#24292e;word-wrap:normal;white-space:pre}.markdown-body .pl-token.active,.markdown-body .pl-token:hover{cursor:pointer;background:#ffea7f}.markdown-body .tab-size[data-tab-size="1"]{-moz-tab-size:1;tab-size:1}.markdown-body .tab-size[data-tab-size="2"]{-moz-tab-size:2;tab-size:2}.markdown-body .tab-size[data-tab-size="3"]{-moz-tab-size:3;tab-size:3}.markdown-body .tab-size[data-tab-size="4"]{-moz-tab-size:4;tab-size:4}.markdown-body .tab-size[data-tab-size="5"]{-moz-tab-size:5;tab-size:5}.markdown-body .tab-size[data-tab-size="6"]{-moz-tab-size:6;tab-size:6}.markdown-body .tab-size[data-tab-size="7"]{-moz-tab-size:7;tab-size:7}.markdown-body .tab-size[data-tab-size="8"]{-moz-tab-size:8;tab-size:8}.markdown-body .tab-size[data-tab-size="9"]{-moz-tab-size:9;tab-size:9}.markdown-body .tab-size[data-tab-size="10"]{-moz-tab-size:10;tab-size:10}.markdown-body .tab-size[data-tab-size="11"]{-moz-tab-size:11;tab-size:11}.markdown-body .tab-size[data-tab-size="12"]{-moz-tab-size:12;tab-size:12}.markdown-body .task-list-item{list-style-type:none}.markdown-body .task-list-item+.task-list-item{margin-top:3px}.markdown-body .task-list-item input{margin:0 .2em .25em -1.6em;vertical-align:middle} +/** + * highlight.js github theme + */ +code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal} +.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} +.hljs{display:block;background:#fff;padding:.5em;color:#333;overflow-x:auto}.hljs-comment,.hljs-meta{color:#969896}.hljs-emphasis,.hljs-quote,.hljs-strong,.hljs-template-variable,.hljs-variable{color:#df5000}.hljs-keyword,.hljs-selector-tag,.hljs-type{color:#d73a49}.hljs-attribute,.hljs-bullet,.hljs-literal,.hljs-symbol{color:#0086b3}.hljs-name,.hljs-section{color:#63a35c}.hljs-tag{color:#333}.hljs-attr,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-selector-pseudo,.hljs-title{color:#6f42c1}.hljs-addition{color:#55a532;background-color:#eaffea}.hljs-deletion{color:#bd2c00;background-color:#ffecec}.hljs-link{text-decoration:underline}.hljs-number{color:#005cc5}.hljs-string{color:#032f62} \ No newline at end of file diff --git a/pywebio/html/css/mditor.min.css b/pywebio/html/css/mditor.min.css deleted file mode 100755 index e28408a4..00000000 --- a/pywebio/html/css/mditor.min.css +++ /dev/null @@ -1,8 +0,0 @@ -/*! - * Mditor embed version 1.3.3 - * Homepage: http://mditor.com - */ -.mditor .toolbar{margin:0;padding:4px;height:100%;position:relative}.mditor .toolbar .item{transition:.3s;height:27px;width:27px;text-align:center;line-height:25px;font-size:14px;border:1px solid transparent;border-radius:3px;margin:1px;color:#888;transition:.2s;-webkit-transition:.2s;position:relative;vertical-align:middle}.mditor .toolbar .item:hover{color:#444;border:1px solid #ddd}.mditor .toolbar .item.active,.mditor .toolbar .item:active{border:1px solid #ddd;background-color:#ebebeb;box-shadow:inset 0 0 3px rgba(0,0,0,.1)}.mditor .toolbar .item.control{float:right}.mditor .editor{position:relative;display:inline-block;width:100%;height:100%;-webkit-text-size-adjust:none;transform:translateZ(0)}.mditor .editor .backdrop,.mditor .editor .textarea{position:absolute;border:none;outline:none;display:block;left:0;top:0;width:100%;height:100%;resize:none;background-color:transparent;margin:0;overflow-x:hidden;overflow-y:auto;transition:transform 1s;letter-spacing:1px}.mditor .editor .backdrop .inner,.mditor .editor .textarea{padding:8px 12px;white-space:pre-wrap;word-wrap:break-word}.mditor .editor .textarea{z-index:1;color:#444}.mditor .editor .backdrop{z-index:0;pointer-events:none;overflow:hidden;padding:0}.mditor .editor .backdrop .inner{color:transparent}.mditor .editor .backdrop .inner mark{border-radius:3px;color:transparent;background-color:rgba(255,245,75,.8)}.mditor .editor .backdrop .inner mark.active{background-color:rgba(145,225,255,.8)}.mditor .viewer{overflow:auto;position:relative;display:inline-block;border:none;outline:none;width:100%;height:100%;resize:none;background-color:transparent;margin:0;padding:10px 12px 40px;color:#333;word-break:break-all;word-wrap:break-word}.mditor .viewer .markdown-body{max-width:900px;margin:auto}.mditor .viewer .alert{color:#ddd;text-align:center;position:absolute;left:0;width:100%;top:50%;font-size:20px;margin-top:-15px}.mditor .body .finder{position:absolute;top:0;right:0;padding:8px;background-color:hsla(0,0%,94%,.9);box-shadow:-1px 1px 2px 0 rgba(0,0,0,.18);z-index:2;display:none}.mditor .body .finder input{outline:0;font-size:13px;padding:5px;height:25px;vertical-align:middle;border:1px solid #ddd;margin:2px;min-width:200px;-webkit-font-smoothing:antialiased}.mditor .body .finder i.fa{vertical-align:middle;font-size:12px;padding:5px;outline:0;color:#888}.mditor .body .finder i.fa:hover{color:#555}.mditor .body .finder.active{display:block}/*! - * Font Awesome 4.7.0 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:FontAwesome;src:url(../font/674f50d287a8c48dc19ba404d20fe713.eot);src:url(../font/674f50d287a8c48dc19ba404d20fe713.eot?#iefix&v=4.7.0) format("embedded-opentype"),url(../font/af7ae505a9eed503f8b8e6982036873e.woff2) format("woff2"),url(../font/fee66e712a8a08eef5805a46892932ad.woff) format("woff"),url(../font/b06871f281fee6b241d60582ae9369b9.ttf) format("truetype"),url(../font/912ec66d7572ff821749319396470bde.svg#fontawesomeregular) format("svg");font-weight:400;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:.08em solid #eee;border-radius:.1em}.fa-pull-left{float:left}.fa-pull-right{float:right}.fa.fa-pull-left{margin-right:.3em}.fa.fa-pull-right{margin-left:.3em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}.fa-pulse{-webkit-animation:fa-spin 1s infinite steps(8);animation:fa-spin 1s infinite steps(8)}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";-webkit-transform:scaleX(-1);-ms-transform:scaleX(-1);transform:scaleX(-1)}.fa-flip-vertical{-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";-webkit-transform:scaleY(-1);-ms-transform:scaleY(-1);transform:scaleY(-1)}:root .fa-flip-horizontal,:root .fa-flip-vertical,:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\F000"}.fa-music:before{content:"\F001"}.fa-search:before{content:"\F002"}.fa-envelope-o:before{content:"\F003"}.fa-heart:before{content:"\F004"}.fa-star:before{content:"\F005"}.fa-star-o:before{content:"\F006"}.fa-user:before{content:"\F007"}.fa-film:before{content:"\F008"}.fa-th-large:before{content:"\F009"}.fa-th:before{content:"\F00A"}.fa-th-list:before{content:"\F00B"}.fa-check:before{content:"\F00C"}.fa-close:before,.fa-remove:before,.fa-times:before{content:"\F00D"}.fa-search-plus:before{content:"\F00E"}.fa-search-minus:before{content:"\F010"}.fa-power-off:before{content:"\F011"}.fa-signal:before{content:"\F012"}.fa-cog:before,.fa-gear:before{content:"\F013"}.fa-trash-o:before{content:"\F014"}.fa-home:before{content:"\F015"}.fa-file-o:before{content:"\F016"}.fa-clock-o:before{content:"\F017"}.fa-road:before{content:"\F018"}.fa-download:before{content:"\F019"}.fa-arrow-circle-o-down:before{content:"\F01A"}.fa-arrow-circle-o-up:before{content:"\F01B"}.fa-inbox:before{content:"\F01C"}.fa-play-circle-o:before{content:"\F01D"}.fa-repeat:before,.fa-rotate-right:before{content:"\F01E"}.fa-refresh:before{content:"\F021"}.fa-list-alt:before{content:"\F022"}.fa-lock:before{content:"\F023"}.fa-flag:before{content:"\F024"}.fa-headphones:before{content:"\F025"}.fa-volume-off:before{content:"\F026"}.fa-volume-down:before{content:"\F027"}.fa-volume-up:before{content:"\F028"}.fa-qrcode:before{content:"\F029"}.fa-barcode:before{content:"\F02A"}.fa-tag:before{content:"\F02B"}.fa-tags:before{content:"\F02C"}.fa-book:before{content:"\F02D"}.fa-bookmark:before{content:"\F02E"}.fa-print:before{content:"\F02F"}.fa-camera:before{content:"\F030"}.fa-font:before{content:"\F031"}.fa-bold:before{content:"\F032"}.fa-italic:before{content:"\F033"}.fa-text-height:before{content:"\F034"}.fa-text-width:before{content:"\F035"}.fa-align-left:before{content:"\F036"}.fa-align-center:before{content:"\F037"}.fa-align-right:before{content:"\F038"}.fa-align-justify:before{content:"\F039"}.fa-list:before{content:"\F03A"}.fa-dedent:before,.fa-outdent:before{content:"\F03B"}.fa-indent:before{content:"\F03C"}.fa-video-camera:before{content:"\F03D"}.fa-image:before,.fa-photo:before,.fa-picture-o:before{content:"\F03E"}.fa-pencil:before{content:"\F040"}.fa-map-marker:before{content:"\F041"}.fa-adjust:before{content:"\F042"}.fa-tint:before{content:"\F043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\F044"}.fa-share-square-o:before{content:"\F045"}.fa-check-square-o:before{content:"\F046"}.fa-arrows:before{content:"\F047"}.fa-step-backward:before{content:"\F048"}.fa-fast-backward:before{content:"\F049"}.fa-backward:before{content:"\F04A"}.fa-play:before{content:"\F04B"}.fa-pause:before{content:"\F04C"}.fa-stop:before{content:"\F04D"}.fa-forward:before{content:"\F04E"}.fa-fast-forward:before{content:"\F050"}.fa-step-forward:before{content:"\F051"}.fa-eject:before{content:"\F052"}.fa-chevron-left:before{content:"\F053"}.fa-chevron-right:before{content:"\F054"}.fa-plus-circle:before{content:"\F055"}.fa-minus-circle:before{content:"\F056"}.fa-times-circle:before{content:"\F057"}.fa-check-circle:before{content:"\F058"}.fa-question-circle:before{content:"\F059"}.fa-info-circle:before{content:"\F05A"}.fa-crosshairs:before{content:"\F05B"}.fa-times-circle-o:before{content:"\F05C"}.fa-check-circle-o:before{content:"\F05D"}.fa-ban:before{content:"\F05E"}.fa-arrow-left:before{content:"\F060"}.fa-arrow-right:before{content:"\F061"}.fa-arrow-up:before{content:"\F062"}.fa-arrow-down:before{content:"\F063"}.fa-mail-forward:before,.fa-share:before{content:"\F064"}.fa-expand:before{content:"\F065"}.fa-compress:before{content:"\F066"}.fa-plus:before{content:"\F067"}.fa-minus:before{content:"\F068"}.fa-asterisk:before{content:"\F069"}.fa-exclamation-circle:before{content:"\F06A"}.fa-gift:before{content:"\F06B"}.fa-leaf:before{content:"\F06C"}.fa-fire:before{content:"\F06D"}.fa-eye:before{content:"\F06E"}.fa-eye-slash:before{content:"\F070"}.fa-exclamation-triangle:before,.fa-warning:before{content:"\F071"}.fa-plane:before{content:"\F072"}.fa-calendar:before{content:"\F073"}.fa-random:before{content:"\F074"}.fa-comment:before{content:"\F075"}.fa-magnet:before{content:"\F076"}.fa-chevron-up:before{content:"\F077"}.fa-chevron-down:before{content:"\F078"}.fa-retweet:before{content:"\F079"}.fa-shopping-cart:before{content:"\F07A"}.fa-folder:before{content:"\F07B"}.fa-folder-open:before{content:"\F07C"}.fa-arrows-v:before{content:"\F07D"}.fa-arrows-h:before{content:"\F07E"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\F080"}.fa-twitter-square:before{content:"\F081"}.fa-facebook-square:before{content:"\F082"}.fa-camera-retro:before{content:"\F083"}.fa-key:before{content:"\F084"}.fa-cogs:before,.fa-gears:before{content:"\F085"}.fa-comments:before{content:"\F086"}.fa-thumbs-o-up:before{content:"\F087"}.fa-thumbs-o-down:before{content:"\F088"}.fa-star-half:before{content:"\F089"}.fa-heart-o:before{content:"\F08A"}.fa-sign-out:before{content:"\F08B"}.fa-linkedin-square:before{content:"\F08C"}.fa-thumb-tack:before{content:"\F08D"}.fa-external-link:before{content:"\F08E"}.fa-sign-in:before{content:"\F090"}.fa-trophy:before{content:"\F091"}.fa-github-square:before{content:"\F092"}.fa-upload:before{content:"\F093"}.fa-lemon-o:before{content:"\F094"}.fa-phone:before{content:"\F095"}.fa-square-o:before{content:"\F096"}.fa-bookmark-o:before{content:"\F097"}.fa-phone-square:before{content:"\F098"}.fa-twitter:before{content:"\F099"}.fa-facebook-f:before,.fa-facebook:before{content:"\F09A"}.fa-github:before{content:"\F09B"}.fa-unlock:before{content:"\F09C"}.fa-credit-card:before{content:"\F09D"}.fa-feed:before,.fa-rss:before{content:"\F09E"}.fa-hdd-o:before{content:"\F0A0"}.fa-bullhorn:before{content:"\F0A1"}.fa-bell:before{content:"\F0F3"}.fa-certificate:before{content:"\F0A3"}.fa-hand-o-right:before{content:"\F0A4"}.fa-hand-o-left:before{content:"\F0A5"}.fa-hand-o-up:before{content:"\F0A6"}.fa-hand-o-down:before{content:"\F0A7"}.fa-arrow-circle-left:before{content:"\F0A8"}.fa-arrow-circle-right:before{content:"\F0A9"}.fa-arrow-circle-up:before{content:"\F0AA"}.fa-arrow-circle-down:before{content:"\F0AB"}.fa-globe:before{content:"\F0AC"}.fa-wrench:before{content:"\F0AD"}.fa-tasks:before{content:"\F0AE"}.fa-filter:before{content:"\F0B0"}.fa-briefcase:before{content:"\F0B1"}.fa-arrows-alt:before{content:"\F0B2"}.fa-group:before,.fa-users:before{content:"\F0C0"}.fa-chain:before,.fa-link:before{content:"\F0C1"}.fa-cloud:before{content:"\F0C2"}.fa-flask:before{content:"\F0C3"}.fa-cut:before,.fa-scissors:before{content:"\F0C4"}.fa-copy:before,.fa-files-o:before{content:"\F0C5"}.fa-paperclip:before{content:"\F0C6"}.fa-floppy-o:before,.fa-save:before{content:"\F0C7"}.fa-square:before{content:"\F0C8"}.fa-bars:before,.fa-navicon:before,.fa-reorder:before{content:"\F0C9"}.fa-list-ul:before{content:"\F0CA"}.fa-list-ol:before{content:"\F0CB"}.fa-strikethrough:before{content:"\F0CC"}.fa-underline:before{content:"\F0CD"}.fa-table:before{content:"\F0CE"}.fa-magic:before{content:"\F0D0"}.fa-truck:before{content:"\F0D1"}.fa-pinterest:before{content:"\F0D2"}.fa-pinterest-square:before{content:"\F0D3"}.fa-google-plus-square:before{content:"\F0D4"}.fa-google-plus:before{content:"\F0D5"}.fa-money:before{content:"\F0D6"}.fa-caret-down:before{content:"\F0D7"}.fa-caret-up:before{content:"\F0D8"}.fa-caret-left:before{content:"\F0D9"}.fa-caret-right:before{content:"\F0DA"}.fa-columns:before{content:"\F0DB"}.fa-sort:before,.fa-unsorted:before{content:"\F0DC"}.fa-sort-desc:before,.fa-sort-down:before{content:"\F0DD"}.fa-sort-asc:before,.fa-sort-up:before{content:"\F0DE"}.fa-envelope:before{content:"\F0E0"}.fa-linkedin:before{content:"\F0E1"}.fa-rotate-left:before,.fa-undo:before{content:"\F0E2"}.fa-gavel:before,.fa-legal:before{content:"\F0E3"}.fa-dashboard:before,.fa-tachometer:before{content:"\F0E4"}.fa-comment-o:before{content:"\F0E5"}.fa-comments-o:before{content:"\F0E6"}.fa-bolt:before,.fa-flash:before{content:"\F0E7"}.fa-sitemap:before{content:"\F0E8"}.fa-umbrella:before{content:"\F0E9"}.fa-clipboard:before,.fa-paste:before{content:"\F0EA"}.fa-lightbulb-o:before{content:"\F0EB"}.fa-exchange:before{content:"\F0EC"}.fa-cloud-download:before{content:"\F0ED"}.fa-cloud-upload:before{content:"\F0EE"}.fa-user-md:before{content:"\F0F0"}.fa-stethoscope:before{content:"\F0F1"}.fa-suitcase:before{content:"\F0F2"}.fa-bell-o:before{content:"\F0A2"}.fa-coffee:before{content:"\F0F4"}.fa-cutlery:before{content:"\F0F5"}.fa-file-text-o:before{content:"\F0F6"}.fa-building-o:before{content:"\F0F7"}.fa-hospital-o:before{content:"\F0F8"}.fa-ambulance:before{content:"\F0F9"}.fa-medkit:before{content:"\F0FA"}.fa-fighter-jet:before{content:"\F0FB"}.fa-beer:before{content:"\F0FC"}.fa-h-square:before{content:"\F0FD"}.fa-plus-square:before{content:"\F0FE"}.fa-angle-double-left:before{content:"\F100"}.fa-angle-double-right:before{content:"\F101"}.fa-angle-double-up:before{content:"\F102"}.fa-angle-double-down:before{content:"\F103"}.fa-angle-left:before{content:"\F104"}.fa-angle-right:before{content:"\F105"}.fa-angle-up:before{content:"\F106"}.fa-angle-down:before{content:"\F107"}.fa-desktop:before{content:"\F108"}.fa-laptop:before{content:"\F109"}.fa-tablet:before{content:"\F10A"}.fa-mobile-phone:before,.fa-mobile:before{content:"\F10B"}.fa-circle-o:before{content:"\F10C"}.fa-quote-left:before{content:"\F10D"}.fa-quote-right:before{content:"\F10E"}.fa-spinner:before{content:"\F110"}.fa-circle:before{content:"\F111"}.fa-mail-reply:before,.fa-reply:before{content:"\F112"}.fa-github-alt:before{content:"\F113"}.fa-folder-o:before{content:"\F114"}.fa-folder-open-o:before{content:"\F115"}.fa-smile-o:before{content:"\F118"}.fa-frown-o:before{content:"\F119"}.fa-meh-o:before{content:"\F11A"}.fa-gamepad:before{content:"\F11B"}.fa-keyboard-o:before{content:"\F11C"}.fa-flag-o:before{content:"\F11D"}.fa-flag-checkered:before{content:"\F11E"}.fa-terminal:before{content:"\F120"}.fa-code:before{content:"\F121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\F122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\F123"}.fa-location-arrow:before{content:"\F124"}.fa-crop:before{content:"\F125"}.fa-code-fork:before{content:"\F126"}.fa-chain-broken:before,.fa-unlink:before{content:"\F127"}.fa-question:before{content:"\F128"}.fa-info:before{content:"\F129"}.fa-exclamation:before{content:"\F12A"}.fa-superscript:before{content:"\F12B"}.fa-subscript:before{content:"\F12C"}.fa-eraser:before{content:"\F12D"}.fa-puzzle-piece:before{content:"\F12E"}.fa-microphone:before{content:"\F130"}.fa-microphone-slash:before{content:"\F131"}.fa-shield:before{content:"\F132"}.fa-calendar-o:before{content:"\F133"}.fa-fire-extinguisher:before{content:"\F134"}.fa-rocket:before{content:"\F135"}.fa-maxcdn:before{content:"\F136"}.fa-chevron-circle-left:before{content:"\F137"}.fa-chevron-circle-right:before{content:"\F138"}.fa-chevron-circle-up:before{content:"\F139"}.fa-chevron-circle-down:before{content:"\F13A"}.fa-html5:before{content:"\F13B"}.fa-css3:before{content:"\F13C"}.fa-anchor:before{content:"\F13D"}.fa-unlock-alt:before{content:"\F13E"}.fa-bullseye:before{content:"\F140"}.fa-ellipsis-h:before{content:"\F141"}.fa-ellipsis-v:before{content:"\F142"}.fa-rss-square:before{content:"\F143"}.fa-play-circle:before{content:"\F144"}.fa-ticket:before{content:"\F145"}.fa-minus-square:before{content:"\F146"}.fa-minus-square-o:before{content:"\F147"}.fa-level-up:before{content:"\F148"}.fa-level-down:before{content:"\F149"}.fa-check-square:before{content:"\F14A"}.fa-pencil-square:before{content:"\F14B"}.fa-external-link-square:before{content:"\F14C"}.fa-share-square:before{content:"\F14D"}.fa-compass:before{content:"\F14E"}.fa-caret-square-o-down:before,.fa-toggle-down:before{content:"\F150"}.fa-caret-square-o-up:before,.fa-toggle-up:before{content:"\F151"}.fa-caret-square-o-right:before,.fa-toggle-right:before{content:"\F152"}.fa-eur:before,.fa-euro:before{content:"\F153"}.fa-gbp:before{content:"\F154"}.fa-dollar:before,.fa-usd:before{content:"\F155"}.fa-inr:before,.fa-rupee:before{content:"\F156"}.fa-cny:before,.fa-jpy:before,.fa-rmb:before,.fa-yen:before{content:"\F157"}.fa-rouble:before,.fa-rub:before,.fa-ruble:before{content:"\F158"}.fa-krw:before,.fa-won:before{content:"\F159"}.fa-bitcoin:before,.fa-btc:before{content:"\F15A"}.fa-file:before{content:"\F15B"}.fa-file-text:before{content:"\F15C"}.fa-sort-alpha-asc:before{content:"\F15D"}.fa-sort-alpha-desc:before{content:"\F15E"}.fa-sort-amount-asc:before{content:"\F160"}.fa-sort-amount-desc:before{content:"\F161"}.fa-sort-numeric-asc:before{content:"\F162"}.fa-sort-numeric-desc:before{content:"\F163"}.fa-thumbs-up:before{content:"\F164"}.fa-thumbs-down:before{content:"\F165"}.fa-youtube-square:before{content:"\F166"}.fa-youtube:before{content:"\F167"}.fa-xing:before{content:"\F168"}.fa-xing-square:before{content:"\F169"}.fa-youtube-play:before{content:"\F16A"}.fa-dropbox:before{content:"\F16B"}.fa-stack-overflow:before{content:"\F16C"}.fa-instagram:before{content:"\F16D"}.fa-flickr:before{content:"\F16E"}.fa-adn:before{content:"\F170"}.fa-bitbucket:before{content:"\F171"}.fa-bitbucket-square:before{content:"\F172"}.fa-tumblr:before{content:"\F173"}.fa-tumblr-square:before{content:"\F174"}.fa-long-arrow-down:before{content:"\F175"}.fa-long-arrow-up:before{content:"\F176"}.fa-long-arrow-left:before{content:"\F177"}.fa-long-arrow-right:before{content:"\F178"}.fa-apple:before{content:"\F179"}.fa-windows:before{content:"\F17A"}.fa-android:before{content:"\F17B"}.fa-linux:before{content:"\F17C"}.fa-dribbble:before{content:"\F17D"}.fa-skype:before{content:"\F17E"}.fa-foursquare:before{content:"\F180"}.fa-trello:before{content:"\F181"}.fa-female:before{content:"\F182"}.fa-male:before{content:"\F183"}.fa-gittip:before,.fa-gratipay:before{content:"\F184"}.fa-sun-o:before{content:"\F185"}.fa-moon-o:before{content:"\F186"}.fa-archive:before{content:"\F187"}.fa-bug:before{content:"\F188"}.fa-vk:before{content:"\F189"}.fa-weibo:before{content:"\F18A"}.fa-renren:before{content:"\F18B"}.fa-pagelines:before{content:"\F18C"}.fa-stack-exchange:before{content:"\F18D"}.fa-arrow-circle-o-right:before{content:"\F18E"}.fa-arrow-circle-o-left:before{content:"\F190"}.fa-caret-square-o-left:before,.fa-toggle-left:before{content:"\F191"}.fa-dot-circle-o:before{content:"\F192"}.fa-wheelchair:before{content:"\F193"}.fa-vimeo-square:before{content:"\F194"}.fa-try:before,.fa-turkish-lira:before{content:"\F195"}.fa-plus-square-o:before{content:"\F196"}.fa-space-shuttle:before{content:"\F197"}.fa-slack:before{content:"\F198"}.fa-envelope-square:before{content:"\F199"}.fa-wordpress:before{content:"\F19A"}.fa-openid:before{content:"\F19B"}.fa-bank:before,.fa-institution:before,.fa-university:before{content:"\F19C"}.fa-graduation-cap:before,.fa-mortar-board:before{content:"\F19D"}.fa-yahoo:before{content:"\F19E"}.fa-google:before{content:"\F1A0"}.fa-reddit:before{content:"\F1A1"}.fa-reddit-square:before{content:"\F1A2"}.fa-stumbleupon-circle:before{content:"\F1A3"}.fa-stumbleupon:before{content:"\F1A4"}.fa-delicious:before{content:"\F1A5"}.fa-digg:before{content:"\F1A6"}.fa-pied-piper-pp:before{content:"\F1A7"}.fa-pied-piper-alt:before{content:"\F1A8"}.fa-drupal:before{content:"\F1A9"}.fa-joomla:before{content:"\F1AA"}.fa-language:before{content:"\F1AB"}.fa-fax:before{content:"\F1AC"}.fa-building:before{content:"\F1AD"}.fa-child:before{content:"\F1AE"}.fa-paw:before{content:"\F1B0"}.fa-spoon:before{content:"\F1B1"}.fa-cube:before{content:"\F1B2"}.fa-cubes:before{content:"\F1B3"}.fa-behance:before{content:"\F1B4"}.fa-behance-square:before{content:"\F1B5"}.fa-steam:before{content:"\F1B6"}.fa-steam-square:before{content:"\F1B7"}.fa-recycle:before{content:"\F1B8"}.fa-automobile:before,.fa-car:before{content:"\F1B9"}.fa-cab:before,.fa-taxi:before{content:"\F1BA"}.fa-tree:before{content:"\F1BB"}.fa-spotify:before{content:"\F1BC"}.fa-deviantart:before{content:"\F1BD"}.fa-soundcloud:before{content:"\F1BE"}.fa-database:before{content:"\F1C0"}.fa-file-pdf-o:before{content:"\F1C1"}.fa-file-word-o:before{content:"\F1C2"}.fa-file-excel-o:before{content:"\F1C3"}.fa-file-powerpoint-o:before{content:"\F1C4"}.fa-file-image-o:before,.fa-file-photo-o:before,.fa-file-picture-o:before{content:"\F1C5"}.fa-file-archive-o:before,.fa-file-zip-o:before{content:"\F1C6"}.fa-file-audio-o:before,.fa-file-sound-o:before{content:"\F1C7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\F1C8"}.fa-file-code-o:before{content:"\F1C9"}.fa-vine:before{content:"\F1CA"}.fa-codepen:before{content:"\F1CB"}.fa-jsfiddle:before{content:"\F1CC"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-ring:before,.fa-life-saver:before,.fa-support:before{content:"\F1CD"}.fa-circle-o-notch:before{content:"\F1CE"}.fa-ra:before,.fa-rebel:before,.fa-resistance:before{content:"\F1D0"}.fa-empire:before,.fa-ge:before{content:"\F1D1"}.fa-git-square:before{content:"\F1D2"}.fa-git:before{content:"\F1D3"}.fa-hacker-news:before,.fa-y-combinator-square:before,.fa-yc-square:before{content:"\F1D4"}.fa-tencent-weibo:before{content:"\F1D5"}.fa-qq:before{content:"\F1D6"}.fa-wechat:before,.fa-weixin:before{content:"\F1D7"}.fa-paper-plane:before,.fa-send:before{content:"\F1D8"}.fa-paper-plane-o:before,.fa-send-o:before{content:"\F1D9"}.fa-history:before{content:"\F1DA"}.fa-circle-thin:before{content:"\F1DB"}.fa-header:before{content:"\F1DC"}.fa-paragraph:before{content:"\F1DD"}.fa-sliders:before{content:"\F1DE"}.fa-share-alt:before{content:"\F1E0"}.fa-share-alt-square:before{content:"\F1E1"}.fa-bomb:before{content:"\F1E2"}.fa-futbol-o:before,.fa-soccer-ball-o:before{content:"\F1E3"}.fa-tty:before{content:"\F1E4"}.fa-binoculars:before{content:"\F1E5"}.fa-plug:before{content:"\F1E6"}.fa-slideshare:before{content:"\F1E7"}.fa-twitch:before{content:"\F1E8"}.fa-yelp:before{content:"\F1E9"}.fa-newspaper-o:before{content:"\F1EA"}.fa-wifi:before{content:"\F1EB"}.fa-calculator:before{content:"\F1EC"}.fa-paypal:before{content:"\F1ED"}.fa-google-wallet:before{content:"\F1EE"}.fa-cc-visa:before{content:"\F1F0"}.fa-cc-mastercard:before{content:"\F1F1"}.fa-cc-discover:before{content:"\F1F2"}.fa-cc-amex:before{content:"\F1F3"}.fa-cc-paypal:before{content:"\F1F4"}.fa-cc-stripe:before{content:"\F1F5"}.fa-bell-slash:before{content:"\F1F6"}.fa-bell-slash-o:before{content:"\F1F7"}.fa-trash:before{content:"\F1F8"}.fa-copyright:before{content:"\F1F9"}.fa-at:before{content:"\F1FA"}.fa-eyedropper:before{content:"\F1FB"}.fa-paint-brush:before{content:"\F1FC"}.fa-birthday-cake:before{content:"\F1FD"}.fa-area-chart:before{content:"\F1FE"}.fa-pie-chart:before{content:"\F200"}.fa-line-chart:before{content:"\F201"}.fa-lastfm:before{content:"\F202"}.fa-lastfm-square:before{content:"\F203"}.fa-toggle-off:before{content:"\F204"}.fa-toggle-on:before{content:"\F205"}.fa-bicycle:before{content:"\F206"}.fa-bus:before{content:"\F207"}.fa-ioxhost:before{content:"\F208"}.fa-angellist:before{content:"\F209"}.fa-cc:before{content:"\F20A"}.fa-ils:before,.fa-shekel:before,.fa-sheqel:before{content:"\F20B"}.fa-meanpath:before{content:"\F20C"}.fa-buysellads:before{content:"\F20D"}.fa-connectdevelop:before{content:"\F20E"}.fa-dashcube:before{content:"\F210"}.fa-forumbee:before{content:"\F211"}.fa-leanpub:before{content:"\F212"}.fa-sellsy:before{content:"\F213"}.fa-shirtsinbulk:before{content:"\F214"}.fa-simplybuilt:before{content:"\F215"}.fa-skyatlas:before{content:"\F216"}.fa-cart-plus:before{content:"\F217"}.fa-cart-arrow-down:before{content:"\F218"}.fa-diamond:before{content:"\F219"}.fa-ship:before{content:"\F21A"}.fa-user-secret:before{content:"\F21B"}.fa-motorcycle:before{content:"\F21C"}.fa-street-view:before{content:"\F21D"}.fa-heartbeat:before{content:"\F21E"}.fa-venus:before{content:"\F221"}.fa-mars:before{content:"\F222"}.fa-mercury:before{content:"\F223"}.fa-intersex:before,.fa-transgender:before{content:"\F224"}.fa-transgender-alt:before{content:"\F225"}.fa-venus-double:before{content:"\F226"}.fa-mars-double:before{content:"\F227"}.fa-venus-mars:before{content:"\F228"}.fa-mars-stroke:before{content:"\F229"}.fa-mars-stroke-v:before{content:"\F22A"}.fa-mars-stroke-h:before{content:"\F22B"}.fa-neuter:before{content:"\F22C"}.fa-genderless:before{content:"\F22D"}.fa-facebook-official:before{content:"\F230"}.fa-pinterest-p:before{content:"\F231"}.fa-whatsapp:before{content:"\F232"}.fa-server:before{content:"\F233"}.fa-user-plus:before{content:"\F234"}.fa-user-times:before{content:"\F235"}.fa-bed:before,.fa-hotel:before{content:"\F236"}.fa-viacoin:before{content:"\F237"}.fa-train:before{content:"\F238"}.fa-subway:before{content:"\F239"}.fa-medium:before{content:"\F23A"}.fa-y-combinator:before,.fa-yc:before{content:"\F23B"}.fa-optin-monster:before{content:"\F23C"}.fa-opencart:before{content:"\F23D"}.fa-expeditedssl:before{content:"\F23E"}.fa-battery-4:before,.fa-battery-full:before,.fa-battery:before{content:"\F240"}.fa-battery-3:before,.fa-battery-three-quarters:before{content:"\F241"}.fa-battery-2:before,.fa-battery-half:before{content:"\F242"}.fa-battery-1:before,.fa-battery-quarter:before{content:"\F243"}.fa-battery-0:before,.fa-battery-empty:before{content:"\F244"}.fa-mouse-pointer:before{content:"\F245"}.fa-i-cursor:before{content:"\F246"}.fa-object-group:before{content:"\F247"}.fa-object-ungroup:before{content:"\F248"}.fa-sticky-note:before{content:"\F249"}.fa-sticky-note-o:before{content:"\F24A"}.fa-cc-jcb:before{content:"\F24B"}.fa-cc-diners-club:before{content:"\F24C"}.fa-clone:before{content:"\F24D"}.fa-balance-scale:before{content:"\F24E"}.fa-hourglass-o:before{content:"\F250"}.fa-hourglass-1:before,.fa-hourglass-start:before{content:"\F251"}.fa-hourglass-2:before,.fa-hourglass-half:before{content:"\F252"}.fa-hourglass-3:before,.fa-hourglass-end:before{content:"\F253"}.fa-hourglass:before{content:"\F254"}.fa-hand-grab-o:before,.fa-hand-rock-o:before{content:"\F255"}.fa-hand-paper-o:before,.fa-hand-stop-o:before{content:"\F256"}.fa-hand-scissors-o:before{content:"\F257"}.fa-hand-lizard-o:before{content:"\F258"}.fa-hand-spock-o:before{content:"\F259"}.fa-hand-pointer-o:before{content:"\F25A"}.fa-hand-peace-o:before{content:"\F25B"}.fa-trademark:before{content:"\F25C"}.fa-registered:before{content:"\F25D"}.fa-creative-commons:before{content:"\F25E"}.fa-gg:before{content:"\F260"}.fa-gg-circle:before{content:"\F261"}.fa-tripadvisor:before{content:"\F262"}.fa-odnoklassniki:before{content:"\F263"}.fa-odnoklassniki-square:before{content:"\F264"}.fa-get-pocket:before{content:"\F265"}.fa-wikipedia-w:before{content:"\F266"}.fa-safari:before{content:"\F267"}.fa-chrome:before{content:"\F268"}.fa-firefox:before{content:"\F269"}.fa-opera:before{content:"\F26A"}.fa-internet-explorer:before{content:"\F26B"}.fa-television:before,.fa-tv:before{content:"\F26C"}.fa-contao:before{content:"\F26D"}.fa-500px:before{content:"\F26E"}.fa-amazon:before{content:"\F270"}.fa-calendar-plus-o:before{content:"\F271"}.fa-calendar-minus-o:before{content:"\F272"}.fa-calendar-times-o:before{content:"\F273"}.fa-calendar-check-o:before{content:"\F274"}.fa-industry:before{content:"\F275"}.fa-map-pin:before{content:"\F276"}.fa-map-signs:before{content:"\F277"}.fa-map-o:before{content:"\F278"}.fa-map:before{content:"\F279"}.fa-commenting:before{content:"\F27A"}.fa-commenting-o:before{content:"\F27B"}.fa-houzz:before{content:"\F27C"}.fa-vimeo:before{content:"\F27D"}.fa-black-tie:before{content:"\F27E"}.fa-fonticons:before{content:"\F280"}.fa-reddit-alien:before{content:"\F281"}.fa-edge:before{content:"\F282"}.fa-credit-card-alt:before{content:"\F283"}.fa-codiepie:before{content:"\F284"}.fa-modx:before{content:"\F285"}.fa-fort-awesome:before{content:"\F286"}.fa-usb:before{content:"\F287"}.fa-product-hunt:before{content:"\F288"}.fa-mixcloud:before{content:"\F289"}.fa-scribd:before{content:"\F28A"}.fa-pause-circle:before{content:"\F28B"}.fa-pause-circle-o:before{content:"\F28C"}.fa-stop-circle:before{content:"\F28D"}.fa-stop-circle-o:before{content:"\F28E"}.fa-shopping-bag:before{content:"\F290"}.fa-shopping-basket:before{content:"\F291"}.fa-hashtag:before{content:"\F292"}.fa-bluetooth:before{content:"\F293"}.fa-bluetooth-b:before{content:"\F294"}.fa-percent:before{content:"\F295"}.fa-gitlab:before{content:"\F296"}.fa-wpbeginner:before{content:"\F297"}.fa-wpforms:before{content:"\F298"}.fa-envira:before{content:"\F299"}.fa-universal-access:before{content:"\F29A"}.fa-wheelchair-alt:before{content:"\F29B"}.fa-question-circle-o:before{content:"\F29C"}.fa-blind:before{content:"\F29D"}.fa-audio-description:before{content:"\F29E"}.fa-volume-control-phone:before{content:"\F2A0"}.fa-braille:before{content:"\F2A1"}.fa-assistive-listening-systems:before{content:"\F2A2"}.fa-american-sign-language-interpreting:before,.fa-asl-interpreting:before{content:"\F2A3"}.fa-deaf:before,.fa-deafness:before,.fa-hard-of-hearing:before{content:"\F2A4"}.fa-glide:before{content:"\F2A5"}.fa-glide-g:before{content:"\F2A6"}.fa-sign-language:before,.fa-signing:before{content:"\F2A7"}.fa-low-vision:before{content:"\F2A8"}.fa-viadeo:before{content:"\F2A9"}.fa-viadeo-square:before{content:"\F2AA"}.fa-snapchat:before{content:"\F2AB"}.fa-snapchat-ghost:before{content:"\F2AC"}.fa-snapchat-square:before{content:"\F2AD"}.fa-pied-piper:before{content:"\F2AE"}.fa-first-order:before{content:"\F2B0"}.fa-yoast:before{content:"\F2B1"}.fa-themeisle:before{content:"\F2B2"}.fa-google-plus-circle:before,.fa-google-plus-official:before{content:"\F2B3"}.fa-fa:before,.fa-font-awesome:before{content:"\F2B4"}.fa-handshake-o:before{content:"\F2B5"}.fa-envelope-open:before{content:"\F2B6"}.fa-envelope-open-o:before{content:"\F2B7"}.fa-linode:before{content:"\F2B8"}.fa-address-book:before{content:"\F2B9"}.fa-address-book-o:before{content:"\F2BA"}.fa-address-card:before,.fa-vcard:before{content:"\F2BB"}.fa-address-card-o:before,.fa-vcard-o:before{content:"\F2BC"}.fa-user-circle:before{content:"\F2BD"}.fa-user-circle-o:before{content:"\F2BE"}.fa-user-o:before{content:"\F2C0"}.fa-id-badge:before{content:"\F2C1"}.fa-drivers-license:before,.fa-id-card:before{content:"\F2C2"}.fa-drivers-license-o:before,.fa-id-card-o:before{content:"\F2C3"}.fa-quora:before{content:"\F2C4"}.fa-free-code-camp:before{content:"\F2C5"}.fa-telegram:before{content:"\F2C6"}.fa-thermometer-4:before,.fa-thermometer-full:before,.fa-thermometer:before{content:"\F2C7"}.fa-thermometer-3:before,.fa-thermometer-three-quarters:before{content:"\F2C8"}.fa-thermometer-2:before,.fa-thermometer-half:before{content:"\F2C9"}.fa-thermometer-1:before,.fa-thermometer-quarter:before{content:"\F2CA"}.fa-thermometer-0:before,.fa-thermometer-empty:before{content:"\F2CB"}.fa-shower:before{content:"\F2CC"}.fa-bath:before,.fa-bathtub:before,.fa-s15:before{content:"\F2CD"}.fa-podcast:before{content:"\F2CE"}.fa-window-maximize:before{content:"\F2D0"}.fa-window-minimize:before{content:"\F2D1"}.fa-window-restore:before{content:"\F2D2"}.fa-times-rectangle:before,.fa-window-close:before{content:"\F2D3"}.fa-times-rectangle-o:before,.fa-window-close-o:before{content:"\F2D4"}.fa-bandcamp:before{content:"\F2D5"}.fa-grav:before{content:"\F2D6"}.fa-etsy:before{content:"\F2D7"}.fa-imdb:before{content:"\F2D8"}.fa-ravelry:before{content:"\F2D9"}.fa-eercast:before{content:"\F2DA"}.fa-microchip:before{content:"\F2DB"}.fa-snowflake-o:before{content:"\F2DC"}.fa-superpowers:before{content:"\F2DD"}.fa-wpexplorer:before{content:"\F2DE"}.fa-meetup:before{content:"\F2E0"}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0}.sr-only-focusable:active,.sr-only-focusable:focus{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto}@font-face{font-family:octicons-link;src:url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAAZwABAAAAAACFQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEU0lHAAAGaAAAAAgAAAAIAAAAAUdTVUIAAAZcAAAACgAAAAoAAQAAT1MvMgAAAyQAAABJAAAAYFYEU3RjbWFwAAADcAAAAEUAAACAAJThvmN2dCAAAATkAAAABAAAAAQAAAAAZnBnbQAAA7gAAACyAAABCUM+8IhnYXNwAAAGTAAAABAAAAAQABoAI2dseWYAAAFsAAABPAAAAZwcEq9taGVhZAAAAsgAAAA0AAAANgh4a91oaGVhAAADCAAAABoAAAAkCA8DRGhtdHgAAAL8AAAADAAAAAwGAACfbG9jYQAAAsAAAAAIAAAACABiATBtYXhwAAACqAAAABgAAAAgAA8ASm5hbWUAAAToAAABQgAAAlXu73sOcG9zdAAABiwAAAAeAAAAME3QpOBwcmVwAAAEbAAAAHYAAAB/aFGpk3jaTY6xa8JAGMW/O62BDi0tJLYQincXEypYIiGJjSgHniQ6umTsUEyLm5BV6NDBP8Tpts6F0v+k/0an2i+itHDw3v2+9+DBKTzsJNnWJNTgHEy4BgG3EMI9DCEDOGEXzDADU5hBKMIgNPZqoD3SilVaXZCER3/I7AtxEJLtzzuZfI+VVkprxTlXShWKb3TBecG11rwoNlmmn1P2WYcJczl32etSpKnziC7lQyWe1smVPy/Lt7Kc+0vWY/gAgIIEqAN9we0pwKXreiMasxvabDQMM4riO+qxM2ogwDGOZTXxwxDiycQIcoYFBLj5K3EIaSctAq2kTYiw+ymhce7vwM9jSqO8JyVd5RH9gyTt2+J/yUmYlIR0s04n6+7Vm1ozezUeLEaUjhaDSuXHwVRgvLJn1tQ7xiuVv/ocTRF42mNgZGBgYGbwZOBiAAFGJBIMAAizAFoAAABiAGIAznjaY2BkYGAA4in8zwXi+W2+MjCzMIDApSwvXzC97Z4Ig8N/BxYGZgcgl52BCSQKAA3jCV8CAABfAAAAAAQAAEB42mNgZGBg4f3vACQZQABIMjKgAmYAKEgBXgAAeNpjYGY6wTiBgZWBg2kmUxoDA4MPhGZMYzBi1AHygVLYQUCaawqDA4PChxhmh/8ODDEsvAwHgMKMIDnGL0x7gJQCAwMAJd4MFwAAAHjaY2BgYGaA4DAGRgYQkAHyGMF8NgYrIM3JIAGVYYDT+AEjAwuDFpBmA9KMDEwMCh9i/v8H8sH0/4dQc1iAmAkALaUKLgAAAHjaTY9LDsIgEIbtgqHUPpDi3gPoBVyRTmTddOmqTXThEXqrob2gQ1FjwpDvfwCBdmdXC5AVKFu3e5MfNFJ29KTQT48Ob9/lqYwOGZxeUelN2U2R6+cArgtCJpauW7UQBqnFkUsjAY/kOU1cP+DAgvxwn1chZDwUbd6CFimGXwzwF6tPbFIcjEl+vvmM/byA48e6tWrKArm4ZJlCbdsrxksL1AwWn/yBSJKpYbq8AXaaTb8AAHja28jAwOC00ZrBeQNDQOWO//sdBBgYGRiYWYAEELEwMTE4uzo5Zzo5b2BxdnFOcALxNjA6b2ByTswC8jYwg0VlNuoCTWAMqNzMzsoK1rEhNqByEyerg5PMJlYuVueETKcd/89uBpnpvIEVomeHLoMsAAe1Id4AAAAAAAB42oWQT07CQBTGv0JBhagk7HQzKxca2sJCE1hDt4QF+9JOS0nbaaYDCQfwCJ7Au3AHj+LO13FMmm6cl7785vven0kBjHCBhfpYuNa5Ph1c0e2Xu3jEvWG7UdPDLZ4N92nOm+EBXuAbHmIMSRMs+4aUEd4Nd3CHD8NdvOLTsA2GL8M9PODbcL+hD7C1xoaHeLJSEao0FEW14ckxC+TU8TxvsY6X0eLPmRhry2WVioLpkrbp84LLQPGI7c6sOiUzpWIWS5GzlSgUzzLBSikOPFTOXqly7rqx0Z1Q5BAIoZBSFihQYQOOBEdkCOgXTOHA07HAGjGWiIjaPZNW13/+lm6S9FT7rLHFJ6fQbkATOG1j2OFMucKJJsxIVfQORl+9Jyda6Sl1dUYhSCm1dyClfoeDve4qMYdLEbfqHf3O/AdDumsjAAB42mNgYoAAZQYjBmyAGYQZmdhL8zLdDEydARfoAqIAAAABAAMABwAKABMAB///AA8AAQAAAAAAAAAAAAAAAAABAAAAAA==) format("woff")}.markdown-body{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;color:#24292e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif;font-size:16px;line-height:1.5;word-wrap:break-word}.markdown-body .pl-c{color:#6a737d}.markdown-body .pl-c1,.markdown-body .pl-s .pl-v{color:#005cc5}.markdown-body .pl-e,.markdown-body .pl-en{color:#6f42c1}.markdown-body .pl-s .pl-s1,.markdown-body .pl-smi{color:#24292e}.markdown-body .pl-ent{color:#22863a}.markdown-body .pl-k{color:#d73a49}.markdown-body .pl-pds,.markdown-body .pl-s,.markdown-body .pl-s .pl-pse .pl-s1,.markdown-body .pl-sr,.markdown-body .pl-sr .pl-cce,.markdown-body .pl-sr .pl-sra,.markdown-body .pl-sr .pl-sre{color:#032f62}.markdown-body .pl-smw,.markdown-body .pl-v{color:#e36209}.markdown-body .pl-bu{color:#b31d28}.markdown-body .pl-ii{color:#fafbfc;background-color:#b31d28}.markdown-body .pl-c2{color:#fafbfc;background-color:#d73a49}.markdown-body .pl-c2:before{content:"^M"}.markdown-body .pl-sr .pl-cce{font-weight:700;color:#22863a}.markdown-body .pl-ml{color:#735c0f}.markdown-body .pl-mh,.markdown-body .pl-mh .pl-en,.markdown-body .pl-ms{font-weight:700;color:#005cc5}.markdown-body .pl-mi{font-style:italic;color:#24292e}.markdown-body .pl-mb{font-weight:700;color:#24292e}.markdown-body .pl-md{color:#b31d28;background-color:#ffeef0}.markdown-body .pl-mi1{color:#22863a;background-color:#f0fff4}.markdown-body .pl-mc{color:#e36209;background-color:#ffebda}.markdown-body .pl-mi2{color:#f6f8fa;background-color:#005cc5}.markdown-body .pl-mdr{font-weight:700;color:#6f42c1}.markdown-body .pl-ba{color:#586069}.markdown-body .pl-sg{color:#959da5}.markdown-body .pl-corl{text-decoration:underline;color:#032f62}.markdown-body .octicon{display:inline-block;vertical-align:text-top;fill:currentColor}.markdown-body a{background-color:transparent;-webkit-text-decoration-skip:objects}.markdown-body a:active,.markdown-body a:hover{outline-width:0}.markdown-body strong{font-weight:inherit;font-weight:bolder}.markdown-body h1{margin:.67em 0}.markdown-body img{border-style:none}.markdown-body svg:not(:root){overflow:hidden}.markdown-body code,.markdown-body kbd,.markdown-body pre{font-family:monospace,monospace;font-size:1em}.markdown-body hr{box-sizing:content-box;overflow:visible}.markdown-body input{font:inherit;margin:0;overflow:visible}.markdown-body [type=checkbox]{box-sizing:border-box;padding:0}.markdown-body *{box-sizing:border-box}.markdown-body input{font-family:inherit;font-size:inherit;line-height:inherit}.markdown-body a{color:#0366d6;text-decoration:none}.markdown-body a:hover{text-decoration:underline}.markdown-body strong{font-weight:600}.markdown-body hr{height:0;margin:15px 0;overflow:hidden;background:transparent;border-bottom:1px solid #dfe2e5}.markdown-body hr:after,.markdown-body hr:before{display:table;content:""}.markdown-body hr:after{clear:both}.markdown-body table{border-spacing:0;border-collapse:collapse}.markdown-body td,.markdown-body th{padding:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:0;margin-bottom:0}.markdown-body h1{font-size:32px;font-weight:600}.markdown-body h2{font-size:24px;font-weight:600}.markdown-body h3{font-size:20px;font-weight:600}.markdown-body h4{font-size:16px;font-weight:600}.markdown-body h5{font-size:14px;font-weight:600}.markdown-body h6{font-size:12px;font-weight:600}.markdown-body p{margin-top:0;margin-bottom:10px}.markdown-body blockquote{margin:0}.markdown-body ol,.markdown-body ul{padding-left:0;margin-top:0;margin-bottom:0}.markdown-body ol ol,.markdown-body ul ol{list-style-type:lower-roman}.markdown-body ol ol ol,.markdown-body ol ul ol,.markdown-body ul ol ol,.markdown-body ul ul ol{list-style-type:lower-alpha}.markdown-body dd{margin-left:0}.markdown-body code,.markdown-body pre{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;font-size:12px}.markdown-body pre{margin-top:0;margin-bottom:0}.markdown-body .octicon{vertical-align:text-bottom}.markdown-body .pl-0{padding-left:0!important}.markdown-body .pl-1{padding-left:4px!important}.markdown-body .pl-2{padding-left:8px!important}.markdown-body .pl-3{padding-left:16px!important}.markdown-body .pl-4{padding-left:24px!important}.markdown-body .pl-5{padding-left:32px!important}.markdown-body .pl-6{padding-left:40px!important}.markdown-body:after,.markdown-body:before{display:table;content:""}.markdown-body:after{clear:both}.markdown-body>:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .anchor{float:left;padding-right:4px;margin-left:-20px;line-height:1}.markdown-body .anchor:focus{outline:none}.markdown-body blockquote,.markdown-body dl,.markdown-body ol,.markdown-body p,.markdown-body pre,.markdown-body table,.markdown-body ul{margin-top:0;margin-bottom:16px}.markdown-body hr{height:.25em;padding:0;margin:24px 0;background-color:#e1e4e8;border:0}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid #dfe2e5}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body kbd{font-size:11px;border:1px solid #c6cbd1;border-bottom-color:#959da5;box-shadow:inset 0 -1px 0 #959da5}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#1b1f23;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1{font-size:2em}.markdown-body h1,.markdown-body h2{padding-bottom:.3em;border-bottom:1px solid #eaecef}.markdown-body h2{font-size:1.5em}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{font-size:.85em;color:#6a737d}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:0;margin-bottom:0}.markdown-body li>p{margin-top:16px}.markdown-body li+li{margin-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body table{display:block;width:100%;overflow:auto}.markdown-body table th{font-weight:600}.markdown-body table td,.markdown-body table th{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body img{max-width:100%;box-sizing:content-box;background-color:#fff}.markdown-body img[align=right]{padding-left:20px}.markdown-body img[align=left]{padding-right:20px}.markdown-body code{padding:0;padding-top:.2em;padding-bottom:.2em;margin:0;font-size:85%;background-color:rgba(27,31,35,.05);border-radius:3px}.markdown-body code:after,.markdown-body code:before{letter-spacing:-.2em;content:"\A0"}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:transparent;border:0}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:3px}.markdown-body pre code{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:transparent;border:0}.markdown-body pre code:after,.markdown-body pre code:before{content:normal}.markdown-body .full-commit .btn-outline:not(:disabled):hover{color:#005cc5;border-color:#005cc5}.markdown-body kbd{display:inline-block;padding:3px 5px;font:11px SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:1px solid #d1d5da;border-bottom-color:#c6cbd1;border-radius:3px;box-shadow:inset 0 -1px 0 #c6cbd1}.markdown-body :checked+.radio-label{position:relative;z-index:1;border-color:#0366d6}.markdown-body .task-list-item{list-style-type:none}.markdown-body .task-list-item+.task-list-item{margin-top:3px}.markdown-body .task-list-item input{margin:0 .2em .25em -1.6em;vertical-align:middle}.markdown-body hr{border-bottom-color:#eee}code[class*=language-],pre[class*=language-]{color:#000;background:none;text-shadow:0 1px #fff;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-]::-moz-selection,code[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-]::selection,code[class*=language-] ::selection,pre[class*=language-]::selection,pre[class*=language-] ::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#a67f59;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}@font-face{font-family:RobotoMono;font-style:normal;font-weight:400;src:url(../font/a48ac41620cd818c5020d0f4302489ff.ttf) format("truetype")}.mditor{transition:.05s;border-radius:3px;padding:38px 0 0;overflow:hidden;background-color:#fff;border:1px solid #ccc;position:relative;outline:0}.mditor,.mditor *{box-sizing:border-box;-webkit-tap-highlight-color:rgba(0,0,0,0)}.mditor .head{-webkit-touch-callout:none;user-select:none;cursor:default;outline:0;position:absolute;height:38px;left:0;top:0;width:100%;zoom:1;margin:0;padding:0;border-bottom:1px solid #ccc;border-radius:3px 3px 0 0;background:#f1f1f1;box-shadow:inset 0 1px 0 hsla(0,0%,100%,.4);background-color:#f3f3f3;background-image:-moz-linear-gradient(top,#f5f5f5,#efefef);background-image:-ms-linear-gradient(top,#f5f5f5,#efefef);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#efefef));background-image:-webkit-linear-gradient(top,#f5f5f5,#efefef);background-image:-o-linear-gradient(top,#f5f5f5,#efefef);background-image:linear-gradient(top,#f5f5f5,#efefef);background-repeat:repeat-x}.mditor .body{margin:0;padding:0;position:relative;line-height:0;font-size:0;border-radius:0 0 3px 3px;box-shadow:inset 0 0 4px 0 rgba(0,0,0,.1);height:100%}.mditor .body.active{border:1px solid #aaa}.mditor.split .editor,.mditor.split .viewer{width:50%;float:left}.mditor.split .editor{border-right:1px solid #ddd}.mditor.preview .viewer{width:100%}.mditor.preview .editor,.mditor.preview .toolbar .item{display:none}.mditor.preview .toolbar .item.control{display:inline-block}.mditor.fullscreen{position:fixed;margin:0!important;left:0!important;top:0!important;width:100%!important;height:100%!important;min-width:100%!important;min-height:100%!important;max-width:100%!important;max-height:100%!important;z-index:999999;border-radius:0;border:none}.mditor.toolbar-hidden .head{display:none}.mditor.toolbar-hidden .body{border-radius:3px}.mditor .backdrop,.mditor .textarea,.mditor .viewer{-webkit-font-smoothing:antialiased;font:16px/1.6 RobotoMono,PingFang SC,Lantinghei SC,Helvetica Neue,Helvetica,Arial,Microsoft YaHei,\\\5FAE\8F6F\96C5\9ED1,STHeitiSC-Light,simsun,\\\5B8B\4F53,WenQuanYi Zen Hei,WenQuanYi Micro Hei,sans-serif}.mditor-hidden{display:none}.markdown-body>ul{list-style-type:disc}.markdown-body>ol{list-style-type:decimal}.markdown-body table{display:table}.markdown-body hr{height:2px;padding:0;margin:24px 0;background-color:#eaecef;border:0}.markdown-body img{background-color:hsla(0,0%,100%,.1)} \ No newline at end of file diff --git a/pywebio/html/index.html b/pywebio/html/index.html index 34ac1ed7..8e047d1d 100644 --- a/pywebio/html/index.html +++ b/pywebio/html/index.html @@ -6,7 +6,7 @@ PyWebIO - + @@ -39,7 +39,7 @@ - + diff --git a/pywebio/html/js/highlight.min.js b/pywebio/html/js/highlight.min.js new file mode 100644 index 00000000..532ae2a2 --- /dev/null +++ b/pywebio/html/js/highlight.min.js @@ -0,0 +1,1296 @@ +/* + Highlight.js 10.5.0 (af20048d) + License: BSD-3-Clause + Copyright (c) 2006-2020, Ivan Sagalaev +*/ +var hljs=function(){"use strict";function e(t){ +return t instanceof Map?t.clear=t.delete=t.set=()=>{ +throw Error("map is read-only")}:t instanceof Set&&(t.add=t.clear=t.delete=()=>{ +throw Error("set is read-only") +}),Object.freeze(t),Object.getOwnPropertyNames(t).forEach((n=>{var s=t[n] +;"object"!=typeof s||Object.isFrozen(s)||e(s)})),t}var t=e,n=e;t.default=n +;class s{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data} +ignoreMatch(){this.ignore=!0}}function r(e){ +return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") +}function a(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] +;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const i=e=>!!e.kind +;class o{constructor(e,t){ +this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ +this.buffer+=r(e)}openNode(e){if(!i(e))return;let t=e.kind +;e.sublanguage||(t=`${this.classPrefix}${t}`),this.span(t)}closeNode(e){ +i(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ +this.buffer+=``}}class l{constructor(){this.rootNode={ +children:[]},this.stack=[this.rootNode]}get top(){ +return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ +this.top.children.push(e)}openNode(e){const t={kind:e,children:[]} +;this.add(t),this.stack.push(t)}closeNode(){ +if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ +for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} +walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ +return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), +t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ +"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ +l._collapse(e)})))}}class c extends l{constructor(e){super(),this.options=e} +addKeyword(e,t){""!==e&&(this.openNode(t),this.addText(e),this.closeNode())} +addText(e){""!==e&&this.add(e)}addSublanguage(e,t){const n=e.root +;n.kind=t,n.sublanguage=!0,this.add(n)}toHTML(){ +return new o(this,this.options).value()}finalize(){return!0}}function u(e){ +return e?"string"==typeof e?e:e.source:null} +const g="[a-zA-Z]\\w*",d="[a-zA-Z_]\\w*",h="\\b\\d+(\\.\\d+)?",f="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",p="\\b(0b[01]+)",m={ +begin:"\\\\[\\s\\S]",relevance:0},b={className:"string",begin:"'",end:"'", +illegal:"\\n",contains:[m]},x={className:"string",begin:'"',end:'"', +illegal:"\\n",contains:[m]},E={ +begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ +},v=(e,t,n={})=>{const s=a({className:"comment",begin:e,end:t,contains:[]},n) +;return s.contains.push(E),s.contains.push({className:"doctag", +begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),s +},N=v("//","$"),w=v("/\\*","\\*/"),R=v("#","$");var y=Object.freeze({ +__proto__:null,IDENT_RE:g,UNDERSCORE_IDENT_RE:d,NUMBER_RE:h,C_NUMBER_RE:f, +BINARY_NUMBER_RE:p, +RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", +SHEBANG:(e={})=>{const t=/^#![ ]*\// +;return e.binary&&(e.begin=((...e)=>e.map((e=>u(e))).join(""))(t,/.*\b/,e.binary,/\b.*/)), +a({className:"meta",begin:t,end:/$/,relevance:0,"on:begin":(e,t)=>{ +0!==e.index&&t.ignoreMatch()}},e)},BACKSLASH_ESCAPE:m,APOS_STRING_MODE:b, +QUOTE_STRING_MODE:x,PHRASAL_WORDS_MODE:E,COMMENT:v,C_LINE_COMMENT_MODE:N, +C_BLOCK_COMMENT_MODE:w,HASH_COMMENT_MODE:R,NUMBER_MODE:{className:"number", +begin:h,relevance:0},C_NUMBER_MODE:{className:"number",begin:f,relevance:0}, +BINARY_NUMBER_MODE:{className:"number",begin:p,relevance:0},CSS_NUMBER_MODE:{ +className:"number", +begin:h+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", +relevance:0},REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp", +begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[m,{begin:/\[/,end:/\]/, +relevance:0,contains:[m]}]}]},TITLE_MODE:{className:"title",begin:g,relevance:0 +},UNDERSCORE_TITLE_MODE:{className:"title",begin:d,relevance:0},METHOD_GUARD:{ +begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:e=>Object.assign(e,{ +"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{ +t.data._beginMatch!==e[1]&&t.ignoreMatch()}})});function _(e,t){ +"."===e.input[e.index-1]&&t.ignoreMatch()}function k(e,t){ +t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", +e.__beforeBegin=_,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords) +}function M(e,t){ +Array.isArray(e.illegal)&&(e.illegal=((...e)=>"("+e.map((e=>u(e))).join("|")+")")(...e.illegal)) +}function O(e,t){if(e.match){ +if(e.begin||e.end)throw Error("begin & end are not supported with match") +;e.begin=e.match,delete e.match}}function A(e,t){ +void 0===e.relevance&&(e.relevance=1)} +const L=["of","and","for","in","not","or","if","then","parent","list","value"] +;function B(e,t){return t?Number(t):(e=>L.includes(e.toLowerCase()))(e)?0:1} +function I(e,{plugins:t}){function n(t,n){ +return RegExp(u(t),"m"+(e.case_insensitive?"i":"")+(n?"g":""))}class s{ +constructor(){ +this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} +addRule(e,t){ +t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), +this.matchAt+=(e=>RegExp(e.toString()+"|").exec("").length-1)(e)+1}compile(){ +0===this.regexes.length&&(this.exec=()=>null) +;const e=this.regexes.map((e=>e[1]));this.matcherRe=n(((e,t="|")=>{ +const n=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;let s=0,r="" +;for(let a=0;a0&&(r+=t),r+="(";o.length>0;){const e=n.exec(o);if(null==e){r+=o;break} +r+=o.substring(0,e.index), +o=o.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?r+="\\"+(Number(e[1])+i):(r+=e[0], +"("===e[0]&&s++)}r+=")"}return r})(e),!0),this.lastIndex=0}exec(e){ +this.matcherRe.lastIndex=this.lastIndex;const t=this.matcherRe.exec(e) +;if(!t)return null +;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),s=this.matchIndexes[n] +;return t.splice(0,n),Object.assign(t,s)}}class r{constructor(){ +this.rules=[],this.multiRegexes=[], +this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ +if(this.multiRegexes[e])return this.multiRegexes[e];const t=new s +;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), +t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ +return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ +this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ +const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex +;let n=t.exec(e) +;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ +const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} +return n&&(this.regexIndex+=n.position+1, +this.regexIndex===this.count&&this.considerAll()),n}} +if(e.compilerExtensions||(e.compilerExtensions=[]), +e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") +;return e.classNameAliases=a(e.classNameAliases||{}),function t(s,i){const o=s +;if(s.compiled)return o +;[O].forEach((e=>e(s,i))),e.compilerExtensions.forEach((e=>e(s,i))), +s.__beforeBegin=null,[k,M,A].forEach((e=>e(s,i))),s.compiled=!0;let l=null +;if("object"==typeof s.keywords&&(l=s.keywords.$pattern, +delete s.keywords.$pattern),s.keywords&&(s.keywords=((e,t)=>{const n={} +;return"string"==typeof e?s("keyword",e):Object.keys(e).forEach((t=>{s(t,e[t]) +})),n;function s(e,s){t&&(s=s.toLowerCase()),s.split(" ").forEach((t=>{ +const s=t.split("|");n[s[0]]=[e,B(s[0],s[1])]}))} +})(s.keywords,e.case_insensitive)), +s.lexemes&&l)throw Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ") +;return l=l||s.lexemes||/\w+/, +o.keywordPatternRe=n(l,!0),i&&(s.begin||(s.begin=/\B|\b/), +o.beginRe=n(s.begin),s.endSameAsBegin&&(s.end=s.begin), +s.end||s.endsWithParent||(s.end=/\B|\b/), +s.end&&(o.endRe=n(s.end)),o.terminatorEnd=u(s.end)||"", +s.endsWithParent&&i.terminatorEnd&&(o.terminatorEnd+=(s.end?"|":"")+i.terminatorEnd)), +s.illegal&&(o.illegalRe=n(s.illegal)), +s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>a(e,{ +variants:null},t)))),e.cachedVariants?e.cachedVariants:T(e)?a(e,{ +starts:e.starts?a(e.starts):null +}):Object.isFrozen(e)?a(e):e))("self"===e?s:e)))),s.contains.forEach((e=>{t(e,o) +})),s.starts&&t(s.starts,i),o.matcher=(e=>{const t=new r +;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" +}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" +}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(o),o}(e)}function T(e){ +return!!e&&(e.endsWithParent||T(e.starts))}function j(e){const t={ +props:["language","code","autodetect"],data:()=>({detectedLanguage:"", +unknownLanguage:!1}),computed:{className(){ +return this.unknownLanguage?"":"hljs "+this.detectedLanguage},highlighted(){ +if(!this.autoDetect&&!e.getLanguage(this.language))return console.warn(`The language "${this.language}" you specified could not be found.`), +this.unknownLanguage=!0,r(this.code);let t={} +;return this.autoDetect?(t=e.highlightAuto(this.code), +this.detectedLanguage=t.language):(t=e.highlight(this.language,this.code,this.ignoreIllegals), +this.detectedLanguage=this.language),t.value},autoDetect(){ +return!(this.language&&(e=this.autodetect,!e&&""!==e));var e}, +ignoreIllegals:()=>!0},render(e){return e("pre",{},[e("code",{ +class:this.className,domProps:{innerHTML:this.highlighted}})])}};return{ +Component:t,VuePlugin:{install(e){e.component("highlightjs",t)}}}}const S={ +"after:highlightBlock":({block:e,result:t,text:n})=>{const s=D(e) +;if(!s.length)return;const a=document.createElement("div") +;a.innerHTML=t.value,t.value=((e,t,n)=>{let s=0,a="";const i=[];function o(){ +return e.length&&t.length?e[0].offset!==t[0].offset?e[0].offset"}function c(e){ +a+=""}function u(e){("start"===e.event?l:c)(e.node)} +for(;e.length||t.length;){let t=o() +;if(a+=r(n.substring(s,t[0].offset)),s=t[0].offset,t===e){i.reverse().forEach(c) +;do{u(t.splice(0,1)[0]),t=o()}while(t===e&&t.length&&t[0].offset===s) +;i.reverse().forEach(l) +}else"start"===t[0].event?i.push(t[0].node):i.pop(),u(t.splice(0,1)[0])} +return a+r(n.substr(s))})(s,D(a),n)}};function P(e){ +return e.nodeName.toLowerCase()}function D(e){const t=[];return function e(n,s){ +for(let r=n.firstChild;r;r=r.nextSibling)3===r.nodeType?s+=r.nodeValue.length:1===r.nodeType&&(t.push({ +event:"start",offset:s,node:r}),s=e(r,s),P(r).match(/br|hr|img|input/)||t.push({ +event:"stop",offset:s,node:r}));return s}(e,0),t}const C=e=>{console.error(e) +},H=(e,...t)=>{console.log("WARN: "+e,...t)},$=(e,t)=>{ +console.log(`Deprecated as of ${e}. ${t}`)},U=r,z=a,K=Symbol("nomatch") +;return(e=>{const n=Object.create(null),r=Object.create(null),a=[];let i=!0 +;const o=/(^(<[^>]+>|\t|)+|\n)/gm,l="Could not find the language '{}', did you forget to load/include a language module?",u={ +disableAutodetect:!0,name:"Plain text",contains:[]};let g={ +noHighlightRe:/^(no-?highlight)$/i, +languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", +tabReplace:null,useBR:!1,languages:null,__emitter:c};function d(e){ +return g.noHighlightRe.test(e)}function h(e,t,n,s){const r={code:t,language:e} +;_("before:highlight",r);const a=r.result?r.result:f(r.language,r.code,n,s) +;return a.code=r.code,_("after:highlight",a),a}function f(e,t,r,o){const c=t +;function u(e,t){const n=w.case_insensitive?t[0].toLowerCase():t[0] +;return Object.prototype.hasOwnProperty.call(e.keywords,n)&&e.keywords[n]} +function d(){null!=_.subLanguage?(()=>{if(""===O)return;let e=null +;if("string"==typeof _.subLanguage){ +if(!n[_.subLanguage])return void M.addText(O) +;e=f(_.subLanguage,O,!0,k[_.subLanguage]),k[_.subLanguage]=e.top +}else e=p(O,_.subLanguage.length?_.subLanguage:null) +;_.relevance>0&&(A+=e.relevance),M.addSublanguage(e.emitter,e.language) +})():(()=>{if(!_.keywords)return void M.addText(O);let e=0 +;_.keywordPatternRe.lastIndex=0;let t=_.keywordPatternRe.exec(O),n="";for(;t;){ +n+=O.substring(e,t.index);const s=u(_,t);if(s){const[e,r]=s +;M.addText(n),n="",A+=r;const a=w.classNameAliases[e]||e;M.addKeyword(t[0],a) +}else n+=t[0];e=_.keywordPatternRe.lastIndex,t=_.keywordPatternRe.exec(O)} +n+=O.substr(e),M.addText(n)})(),O=""}function h(e){ +return e.className&&M.openNode(w.classNameAliases[e.className]||e.className), +_=Object.create(e,{parent:{value:_}}),_}function m(e,t,n){let r=((e,t)=>{ +const n=e&&e.exec(t);return n&&0===n.index})(e.endRe,n);if(r){if(e["on:end"]){ +const n=new s(e);e["on:end"](t,n),n.ignore&&(r=!1)}if(r){ +for(;e.endsParent&&e.parent;)e=e.parent;return e}} +if(e.endsWithParent)return m(e.parent,t,n)}function b(e){ +return 0===_.matcher.regexIndex?(O+=e[0],1):(T=!0,0)}function x(e){ +const t=e[0],n=c.substr(e.index),s=m(_,e,n);if(!s)return K;const r=_ +;r.skip?O+=t:(r.returnEnd||r.excludeEnd||(O+=t),d(),r.excludeEnd&&(O=t));do{ +_.className&&M.closeNode(),_.skip||_.subLanguage||(A+=_.relevance),_=_.parent +}while(_!==s.parent) +;return s.starts&&(s.endSameAsBegin&&(s.starts.endRe=s.endRe), +h(s.starts)),r.returnEnd?0:t.length}let E={};function v(t,n){const a=n&&n[0] +;if(O+=t,null==a)return d(),0 +;if("begin"===E.type&&"end"===n.type&&E.index===n.index&&""===a){ +if(O+=c.slice(n.index,n.index+1),!i){const t=Error("0 width match regex") +;throw t.languageName=e,t.badRule=E.rule,t}return 1} +if(E=n,"begin"===n.type)return function(e){ +const t=e[0],n=e.rule,r=new s(n),a=[n.__beforeBegin,n["on:begin"]] +;for(const n of a)if(n&&(n(e,r),r.ignore))return b(t) +;return n&&n.endSameAsBegin&&(n.endRe=RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")), +n.skip?O+=t:(n.excludeBegin&&(O+=t), +d(),n.returnBegin||n.excludeBegin||(O=t)),h(n),n.returnBegin?0:t.length}(n) +;if("illegal"===n.type&&!r){ +const e=Error('Illegal lexeme "'+a+'" for mode "'+(_.className||"")+'"') +;throw e.mode=_,e}if("end"===n.type){const e=x(n);if(e!==K)return e} +if("illegal"===n.type&&""===a)return 1 +;if(B>1e5&&B>3*n.index)throw Error("potential infinite loop, way more iterations than matches") +;return O+=a,a.length}const w=N(e) +;if(!w)throw C(l.replace("{}",e)),Error('Unknown language: "'+e+'"') +;const R=I(w,{plugins:a});let y="",_=o||R;const k={},M=new g.__emitter(g);(()=>{ +const e=[];for(let t=_;t!==w;t=t.parent)t.className&&e.unshift(t.className) +;e.forEach((e=>M.openNode(e)))})();let O="",A=0,L=0,B=0,T=!1;try{ +for(_.matcher.considerAll();;){ +B++,T?T=!1:_.matcher.considerAll(),_.matcher.lastIndex=L +;const e=_.matcher.exec(c);if(!e)break;const t=v(c.substring(L,e.index),e) +;L=e.index+t}return v(c.substr(L)),M.closeAllNodes(),M.finalize(),y=M.toHTML(),{ +relevance:A,value:y,language:e,illegal:!1,emitter:M,top:_}}catch(t){ +if(t.message&&t.message.includes("Illegal"))return{illegal:!0,illegalBy:{ +msg:t.message,context:c.slice(L-100,L+100),mode:t.mode},sofar:y,relevance:0, +value:U(c),emitter:M};if(i)return{illegal:!1,relevance:0,value:U(c),emitter:M, +language:e,top:_,errorRaised:t};throw t}}function p(e,t){ +t=t||g.languages||Object.keys(n);const s=(e=>{const t={relevance:0, +emitter:new g.__emitter(g),value:U(e),illegal:!1,top:u} +;return t.emitter.addText(e),t})(e),r=t.filter(N).filter(R).map((t=>f(t,e,!1))) +;r.unshift(s);const a=r.sort(((e,t)=>{ +if(e.relevance!==t.relevance)return t.relevance-e.relevance +;if(e.language&&t.language){if(N(e.language).supersetOf===t.language)return 1 +;if(N(t.language).supersetOf===e.language)return-1}return 0})),[i,o]=a,l=i +;return l.second_best=o,l}const m={"before:highlightBlock":({block:e})=>{ +g.useBR&&(e.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")) +},"after:highlightBlock":({result:e})=>{ +g.useBR&&(e.value=e.value.replace(/\n/g,"
"))}},b=/^(<[^>]+>|\t)+/gm,x={ +"after:highlightBlock":({result:e})=>{ +g.tabReplace&&(e.value=e.value.replace(b,(e=>e.replace(/\t/g,g.tabReplace))))}} +;function E(e){let t=null;const n=(e=>{let t=e.className+" " +;t+=e.parentNode?e.parentNode.className:"";const n=g.languageDetectRe.exec(t) +;if(n){const t=N(n[1]) +;return t||(H(l.replace("{}",n[1])),H("Falling back to no-highlight mode for this block.",e)), +t?n[1]:"no-highlight"}return t.split(/\s+/).find((e=>d(e)||N(e)))})(e) +;if(d(n))return;_("before:highlightBlock",{block:e,language:n}),t=e +;const s=t.textContent,a=n?h(n,s,!0):p(s);_("after:highlightBlock",{block:e, +result:a,text:s}),e.innerHTML=a.value,((e,t,n)=>{const s=t?r[t]:n +;e.classList.add("hljs"),s&&e.classList.add(s)})(e,n,a.language),e.result={ +language:a.language,re:a.relevance,relavance:a.relevance +},a.second_best&&(e.second_best={language:a.second_best.language, +re:a.second_best.relevance,relavance:a.second_best.relevance})}const v=()=>{ +v.called||(v.called=!0,document.querySelectorAll("pre code").forEach(E))} +;function N(e){return e=(e||"").toLowerCase(),n[e]||n[r[e]]} +function w(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{r[e]=t +}))}function R(e){const t=N(e);return t&&!t.disableAutodetect}function _(e,t){ +const n=e;a.forEach((e=>{e[n]&&e[n](t)}))}Object.assign(e,{highlight:h, +highlightAuto:p,fixMarkup:e=>{ +return $("10.2.0","fixMarkup will be removed entirely in v11.0"), +$("10.2.0","Please see https://github.com/highlightjs/highlight.js/issues/2534"), +t=e, +g.tabReplace||g.useBR?t.replace(o,(e=>"\n"===e?g.useBR?"
":e:g.tabReplace?e.replace(/\t/g,g.tabReplace):e)):t +;var t},highlightBlock:E,configure:e=>{ +e.useBR&&($("10.3.0","'useBR' will be removed entirely in v11.0"), +$("10.3.0","Please see https://github.com/highlightjs/highlight.js/issues/2559")), +g=z(g,e)},initHighlighting:v,initHighlightingOnLoad:()=>{ +window.addEventListener("DOMContentLoaded",v,!1)},registerLanguage:(t,s)=>{ +let r=null;try{r=s(e)}catch(e){ +if(C("Language definition for '{}' could not be registered.".replace("{}",t)), +!i)throw e;C(e),r=u} +r.name||(r.name=t),n[t]=r,r.rawDefinition=s.bind(null,e),r.aliases&&w(r.aliases,{ +languageName:t})},listLanguages:()=>Object.keys(n),getLanguage:N, +registerAliases:w,requireLanguage:e=>{ +$("10.4.0","requireLanguage will be removed entirely in v11."), +$("10.4.0","Please see https://github.com/highlightjs/highlight.js/pull/2844") +;const t=N(e);if(t)return t +;throw Error("The '{}' language is required, but not loaded.".replace("{}",e))}, +autoDetection:R,inherit:z,addPlugin:e=>{a.push(e)},vuePlugin:j(e).VuePlugin +}),e.debugMode=()=>{i=!1},e.safeMode=()=>{i=!0},e.versionString="10.5.0" +;for(const e in y)"object"==typeof y[e]&&t(y[e]) +;return Object.assign(e,y),e.addPlugin(m),e.addPlugin(S),e.addPlugin(x),e})({}) +}();"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs); +hljs.registerLanguage("apache",(()=>{"use strict";return e=>{const n={ +className:"number",begin:/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(:\d{1,5})?/} +;return{name:"Apache config",aliases:["apacheconf"],case_insensitive:!0, +contains:[e.HASH_COMMENT_MODE,{className:"section",begin:/<\/?/,end:/>/, +contains:[n,{className:"number",begin:/:\d{1,5}/ +},e.inherit(e.QUOTE_STRING_MODE,{relevance:0})]},{className:"attribute", +begin:/\w+/,relevance:0,keywords:{ +nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername" +},starts:{end:/$/,relevance:0,keywords:{literal:"on off all deny allow"}, +contains:[{className:"meta",begin:/\s\[/,end:/\]$/},{className:"variable", +begin:/[\$%]\{/,end:/\}/,contains:["self",{className:"number",begin:/[$%]\d+/}] +},n,{className:"number",begin:/\d+/},e.QUOTE_STRING_MODE]}}],illegal:/\S/}} +})()); +hljs.registerLanguage("bash",(()=>{"use strict";function e(...e){ +return e.map((e=>{return(s=e)?"string"==typeof s?s:s.source:null;var s +})).join("")}return s=>{const n={},t={begin:/\$\{/,end:/\}/,contains:["self",{ +begin:/:-/,contains:[n]}]};Object.assign(n,{className:"variable",variants:[{ +begin:e(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},t]});const a={ +className:"subst",begin:/\$\(/,end:/\)/,contains:[s.BACKSLASH_ESCAPE]},i={ +begin:/<<-?\s*(?=\w+)/,starts:{contains:[s.END_SAME_AS_BEGIN({begin:/(\w+)/, +end:/(\w+)/,className:"string"})]}},c={className:"string",begin:/"/,end:/"/, +contains:[s.BACKSLASH_ESCAPE,n,a]};a.contains.push(c);const o={begin:/\$\(\(/, +end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},s.NUMBER_MODE,n] +},r=s.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10 +}),l={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0, +contains:[s.inherit(s.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{ +name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b[a-z._-]+\b/, +keyword:"if then else elif fi for while in do done case esac function", +literal:"true false", +built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp" +},contains:[r,s.SHEBANG(),l,o,s.HASH_COMMENT_MODE,i,c,{className:"",begin:/\\"/ +},{className:"string",begin:/'/,end:/'/},n]}}})()); +hljs.registerLanguage("c",(()=>{"use strict";function e(e){ +return((...e)=>e.map((e=>(e=>e?"string"==typeof e?e:e.source:null)(e))).join(""))("(",e,")?") +}return t=>{const n=(t=>{const n=t.COMMENT("//","$",{contains:[{begin:/\\\n/}] +}),r="[a-zA-Z_]\\w*::",a="(decltype\\(auto\\)|"+e(r)+"[a-zA-Z_]\\w*"+e("<[^<>]+>")+")",s={ +className:"keyword",begin:"\\b[a-z\\d_]*_t\\b"},i={className:"string", +variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n", +contains:[t.BACKSLASH_ESCAPE]},{ +begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", +end:"'",illegal:"."},t.END_SAME_AS_BEGIN({ +begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={ +className:"number",variants:[{begin:"\\b(0b[01']+)"},{ +begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" +},{ +begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" +}],relevance:0},c={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ +"meta-keyword":"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" +},contains:[{begin:/\\\n/,relevance:0},t.inherit(i,{className:"meta-string"}),{ +className:"meta-string",begin:/<.*?>/,end:/$/,illegal:"\\n" +},n,t.C_BLOCK_COMMENT_MODE]},l={className:"title",begin:e(r)+t.IDENT_RE, +relevance:0},d=e(r)+t.IDENT_RE+"\\s*\\(",u={ +keyword:"int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid wchar_t short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignas alignof constexpr consteval constinit decltype concept co_await co_return co_yield requires noexcept static_assert thread_local restrict final override atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq", +built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr _Bool complex _Complex imaginary _Imaginary", +literal:"true false nullptr NULL"},m=[c,s,n,t.C_BLOCK_COMMENT_MODE,o,i],p={ +variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{ +beginKeywords:"new throw return else",end:/;/}],keywords:u,contains:m.concat([{ +begin:/\(/,end:/\)/,keywords:u,contains:m.concat(["self"]),relevance:0}]), +relevance:0},_={className:"function",begin:"("+a+"[\\*&\\s]+)+"+d, +returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:u,illegal:/[^\w\s\*&:<>.]/, +contains:[{begin:"decltype\\(auto\\)",keywords:u,relevance:0},{begin:d, +returnBegin:!0,contains:[l],relevance:0},{className:"params",begin:/\(/, +end:/\)/,keywords:u,relevance:0,contains:[n,t.C_BLOCK_COMMENT_MODE,i,o,s,{ +begin:/\(/,end:/\)/,keywords:u,relevance:0, +contains:["self",n,t.C_BLOCK_COMMENT_MODE,i,o,s]}] +},s,n,t.C_BLOCK_COMMENT_MODE,c]};return{ +aliases:["c","cc","h","c++","h++","hpp","hh","hxx","cxx"],keywords:u, +disableAutodetect:!0,illegal:"",keywords:u,contains:["self",s]},{begin:t.IDENT_RE+"::",keywords:u},{ +className:"class",beginKeywords:"enum class struct union",end:/[{;:<>=]/, +contains:[{beginKeywords:"final class struct"},t.TITLE_MODE]}]),exports:{ +preprocessor:c,strings:i,keywords:u}}})(t) +;return n.name="C",n.aliases=["c","h"],n}})()); +hljs.registerLanguage("coffeescript",(()=>{"use strict" +;const e=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],n=["true","false","null","undefined","NaN","Infinity"],a=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]) +;return r=>{const t={ +keyword:e.concat(["then","unless","until","loop","by","when","and","or","is","isnt","not"]).filter((i=["var","const","let","function","static"], +e=>!i.includes(e))).join(" "), +literal:n.concat(["yes","no","on","off"]).join(" "), +built_in:a.concat(["npm","print"]).join(" ")};var i +;const s="[A-Za-z$_][0-9A-Za-z$_]*",o={className:"subst",begin:/#\{/,end:/\}/, +keywords:t},c=[r.BINARY_NUMBER_MODE,r.inherit(r.C_NUMBER_MODE,{starts:{ +end:"(\\s*/)?",relevance:0}}),{className:"string",variants:[{begin:/'''/, +end:/'''/,contains:[r.BACKSLASH_ESCAPE]},{begin:/'/,end:/'/, +contains:[r.BACKSLASH_ESCAPE]},{begin:/"""/,end:/"""/, +contains:[r.BACKSLASH_ESCAPE,o]},{begin:/"/,end:/"/, +contains:[r.BACKSLASH_ESCAPE,o]}]},{className:"regexp",variants:[{begin:"///", +end:"///",contains:[o,r.HASH_COMMENT_MODE]},{begin:"//[gim]{0,3}(?=\\W)", +relevance:0},{begin:/\/(?![ *]).*?(?![\\]).\/[gim]{0,3}(?=\W)/}]},{begin:"@"+s +},{subLanguage:"javascript",excludeBegin:!0,excludeEnd:!0,variants:[{ +begin:"```",end:"```"},{begin:"`",end:"`"}]}];o.contains=c +;const l=r.inherit(r.TITLE_MODE,{begin:s}),d="(\\(.*\\)\\s*)?\\B[-=]>",g={ +className:"params",begin:"\\([^\\(]",returnBegin:!0,contains:[{begin:/\(/, +end:/\)/,keywords:t,contains:["self"].concat(c)}]};return{name:"CoffeeScript", +aliases:["coffee","cson","iced"],keywords:t,illegal:/\/\*/, +contains:c.concat([r.COMMENT("###","###"),r.HASH_COMMENT_MODE,{ +className:"function",begin:"^\\s*"+s+"\\s*=\\s*"+d,end:"[-=]>",returnBegin:!0, +contains:[l,g]},{begin:/[:\(,=]\s*/,relevance:0,contains:[{className:"function", +begin:d,end:"[-=]>",returnBegin:!0,contains:[g]}]},{className:"class", +beginKeywords:"class",end:"$",illegal:/[:="\[\]]/,contains:[{ +beginKeywords:"extends",endsWithParent:!0,illegal:/[:="\[\]]/,contains:[l]},l] +},{begin:s+":",end:":",returnBegin:!0,returnEnd:!0,relevance:0}])}}})()); +hljs.registerLanguage("cpp",(()=>{"use strict";function e(e){ +return((...e)=>e.map((e=>(e=>e?"string"==typeof e?e:e.source:null)(e))).join(""))("(",e,")?") +}return t=>{const n=(t=>{const n=t.COMMENT("//","$",{contains:[{begin:/\\\n/}] +}),r="[a-zA-Z_]\\w*::",a="(decltype\\(auto\\)|"+e(r)+"[a-zA-Z_]\\w*"+e("<[^<>]+>")+")",s={ +className:"keyword",begin:"\\b[a-z\\d_]*_t\\b"},i={className:"string", +variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n", +contains:[t.BACKSLASH_ESCAPE]},{ +begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", +end:"'",illegal:"."},t.END_SAME_AS_BEGIN({ +begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},c={ +className:"number",variants:[{begin:"\\b(0b[01']+)"},{ +begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" +},{ +begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" +}],relevance:0},o={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ +"meta-keyword":"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" +},contains:[{begin:/\\\n/,relevance:0},t.inherit(i,{className:"meta-string"}),{ +className:"meta-string",begin:/<.*?>/,end:/$/,illegal:"\\n" +},n,t.C_BLOCK_COMMENT_MODE]},l={className:"title",begin:e(r)+t.IDENT_RE, +relevance:0},d=e(r)+t.IDENT_RE+"\\s*\\(",u={ +keyword:"int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid wchar_t short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignas alignof constexpr consteval constinit decltype concept co_await co_return co_yield requires noexcept static_assert thread_local restrict final override atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq", +built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr _Bool complex _Complex imaginary _Imaginary", +literal:"true false nullptr NULL"},p=[o,s,n,t.C_BLOCK_COMMENT_MODE,c,i],m={ +variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{ +beginKeywords:"new throw return else",end:/;/}],keywords:u,contains:p.concat([{ +begin:/\(/,end:/\)/,keywords:u,contains:p.concat(["self"]),relevance:0}]), +relevance:0},_={className:"function",begin:"("+a+"[\\*&\\s]+)+"+d, +returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:u,illegal:/[^\w\s\*&:<>.]/, +contains:[{begin:"decltype\\(auto\\)",keywords:u,relevance:0},{begin:d, +returnBegin:!0,contains:[l],relevance:0},{className:"params",begin:/\(/, +end:/\)/,keywords:u,relevance:0,contains:[n,t.C_BLOCK_COMMENT_MODE,i,c,s,{ +begin:/\(/,end:/\)/,keywords:u,relevance:0, +contains:["self",n,t.C_BLOCK_COMMENT_MODE,i,c,s]}] +},s,n,t.C_BLOCK_COMMENT_MODE,o]};return{ +aliases:["c","cc","h","c++","h++","hpp","hh","hxx","cxx"],keywords:u, +disableAutodetect:!0,illegal:"",keywords:u,contains:["self",s]},{begin:t.IDENT_RE+"::",keywords:u},{ +className:"class",beginKeywords:"enum class struct union",end:/[{;:<>=]/, +contains:[{beginKeywords:"final class struct"},t.TITLE_MODE]}]),exports:{ +preprocessor:o,strings:i,keywords:u}}})(t) +;return n.disableAutodetect=!1,n.name="C++", +n.aliases=["cc","c++","h++","hpp","hh","hxx","cxx"],n}})()); +hljs.registerLanguage("csharp",(()=>{"use strict";return e=>{var n={ +keyword:["abstract","as","base","break","case","class","const","continue","do","else","event","explicit","extern","finally","fixed","for","foreach","goto","if","implicit","in","interface","internal","is","lock","namespace","new","operator","out","override","params","private","protected","public","readonly","record","ref","return","sealed","sizeof","stackalloc","static","struct","switch","this","throw","try","typeof","unchecked","unsafe","using","virtual","void","volatile","while"].concat(["add","alias","and","ascending","async","await","by","descending","equals","from","get","global","group","init","into","join","let","nameof","not","notnull","on","or","orderby","partial","remove","select","set","unmanaged","value|0","var","when","where","with","yield"]).join(" "), +built_in:"bool byte char decimal delegate double dynamic enum float int long nint nuint object sbyte short string ulong unit ushort", +literal:"default false null true"},a=e.inherit(e.TITLE_MODE,{ +begin:"[a-zA-Z](\\.?\\w)*"}),i={className:"number",variants:[{ +begin:"\\b(0b[01']+)"},{ +begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{ +begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" +}],relevance:0},s={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}] +},t=e.inherit(s,{illegal:/\n/}),r={className:"subst",begin:/\{/,end:/\}/, +keywords:n},l=e.inherit(r,{illegal:/\n/}),c={className:"string",begin:/\$"/, +end:'"',illegal:/\n/,contains:[{begin:/\{\{/},{begin:/\}\}/ +},e.BACKSLASH_ESCAPE,l]},o={className:"string",begin:/\$@"/,end:'"',contains:[{ +begin:/\{\{/},{begin:/\}\}/},{begin:'""'},r]},d=e.inherit(o,{illegal:/\n/, +contains:[{begin:/\{\{/},{begin:/\}\}/},{begin:'""'},l]}) +;r.contains=[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,i,e.C_BLOCK_COMMENT_MODE], +l.contains=[d,c,t,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,i,e.inherit(e.C_BLOCK_COMMENT_MODE,{ +illegal:/\n/})];var g={variants:[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] +},E={begin:"<",end:">",contains:[{beginKeywords:"in out"},a] +},_=e.IDENT_RE+"(<"+e.IDENT_RE+"(\\s*,\\s*"+e.IDENT_RE+")*>)?(\\[\\])?",b={ +begin:"@"+e.IDENT_RE,relevance:0};return{name:"C#",aliases:["cs","c#"], +keywords:n,illegal:/::/,contains:[e.COMMENT("///","$",{returnBegin:!0, +contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{ +begin:"\x3c!--|--\x3e"},{begin:""}]}] +}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#", +end:"$",keywords:{ +"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum" +}},g,i,{beginKeywords:"class interface",relevance:0,end:/[{;=]/, +illegal:/[^\s:,]/,contains:[{beginKeywords:"where class" +},a,E,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace", +relevance:0,end:/[{;=]/,illegal:/[^\s:]/, +contains:[a,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{ +beginKeywords:"record",relevance:0,end:/[{;=]/,illegal:/[^\s:]/, +contains:[a,E,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"meta", +begin:"^\\s*\\[",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{ +className:"meta-string",begin:/"/,end:/"/}]},{ +beginKeywords:"new return throw await else",relevance:0},{className:"function", +begin:"("+_+"\\s+)+"+e.IDENT_RE+"\\s*(<.+>\\s*)?\\(",returnBegin:!0, +end:/\s*[{;=]/,excludeEnd:!0,keywords:n,contains:[{ +beginKeywords:"public private protected static internal protected abstract async extern override unsafe virtual new sealed partial", +relevance:0},{begin:e.IDENT_RE+"\\s*(<.+>\\s*)?\\(",returnBegin:!0, +contains:[e.TITLE_MODE,E],relevance:0},{className:"params",begin:/\(/,end:/\)/, +excludeBegin:!0,excludeEnd:!0,keywords:n,relevance:0, +contains:[g,i,e.C_BLOCK_COMMENT_MODE] +},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},b]}}})()); +hljs.registerLanguage("css",(()=>{"use strict";return e=>{ +var n="[a-zA-Z-][a-zA-Z0-9_-]*",a={ +begin:/([*]\s?)?(?:[A-Z_.\-\\]+|--[a-zA-Z0-9_-]+)\s*(\/\*\*\/)?:/, +returnBegin:!0,end:";",endsWithParent:!0,contains:[{className:"attribute", +begin:/\S/,end:":",excludeEnd:!0,starts:{endsWithParent:!0,excludeEnd:!0, +contains:[{begin:/[\w-]+\(/,returnBegin:!0,contains:[{className:"built_in", +begin:/[\w-]+/},{begin:/\(/,end:/\)/, +contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE]}] +},e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{ +className:"number",begin:"#[0-9A-Fa-f]+"},{className:"meta",begin:"!important"}] +}}]};return{name:"CSS",case_insensitive:!0,illegal:/[=|'\$]/, +contains:[e.C_BLOCK_COMMENT_MODE,{className:"selector-id", +begin:/#[A-Za-z0-9_-]+/},{className:"selector-class",begin:"\\."+n},{ +className:"selector-attr",begin:/\[/,end:/\]/,illegal:"$", +contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},{className:"selector-pseudo", +begin:/:(:)?[a-zA-Z0-9_+()"'.-]+/},{begin:"@(page|font-face)", +lexemes:"@[a-z-]+",keywords:"@page @font-face"},{begin:"@",end:"[{;]", +illegal:/:/,returnBegin:!0,contains:[{className:"keyword", +begin:/@-?\w[\w]*(-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0, +relevance:0,keywords:"and or not only",contains:[{begin:/[a-z-]+:/, +className:"attribute"},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE] +}]},{className:"selector-tag",begin:n,relevance:0},{begin:/\{/,end:/\}/, +illegal:/\S/,contains:[e.C_BLOCK_COMMENT_MODE,{begin:/;/},a]}]}}})()); +hljs.registerLanguage("diff",(()=>{"use strict";return e=>({name:"Diff", +aliases:["patch"],contains:[{className:"meta",relevance:10,variants:[{ +begin:/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/},{begin:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{ +begin:/^--- +\d+,\d+ +----$/}]},{className:"comment",variants:[{begin:/Index: /, +end:/$/},{begin:/^index/,end:/$/},{begin:/={3,}/,end:/$/},{begin:/^-{3}/,end:/$/ +},{begin:/^\*{3} /,end:/$/},{begin:/^\+{3}/,end:/$/},{begin:/^\*{15}$/},{ +begin:/^diff --git/,end:/$/}]},{className:"addition",begin:/^\+/,end:/$/},{ +className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/, +end:/$/}]})})()); +hljs.registerLanguage("go",(()=>{"use strict";return e=>{const n={ +keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune", +literal:"true false iota nil", +built_in:"append cap close complex copy imag len make new panic print println real recover delete" +};return{name:"Go",aliases:["golang"],keywords:n,illegal:"{"use strict";function e(...e){ +return e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null;var n +})).join("")}return n=>{const a="HTTP/(2|1\\.[01])",s=[{className:"attribute", +begin:e("^",/[A-Za-z][A-Za-z0-9-]*/,"(?=\\:\\s)"),starts:{contains:[{ +className:"punctuation",begin:/: /,relevance:0,starts:{end:"$",relevance:0}}]} +},{begin:"\\n\\n",starts:{subLanguage:[],endsWithParent:!0}}];return{ +name:"HTTP",aliases:["https"],illegal:/\S/,contains:[{begin:"^(?="+a+" \\d{3})", +end:/$/,contains:[{className:"meta",begin:a},{className:"number", +begin:"\\b\\d{3}\\b"}],starts:{end:/\b\B/,illegal:/\S/,contains:s}},{ +begin:"(?=^[A-Z]+ (.*?) "+a+"$)",end:/$/,contains:[{className:"string", +begin:" ",end:" ",excludeBegin:!0,excludeEnd:!0},{className:"meta",begin:a},{ +className:"keyword",begin:"[A-Z]+"}],starts:{end:/\b\B/,illegal:/\S/,contains:s} +}]}}})()); +hljs.registerLanguage("ini",(()=>{"use strict";function e(e){ +return e?"string"==typeof e?e:e.source:null}function n(...n){ +return n.map((n=>e(n))).join("")}return s=>{const a={className:"number", +relevance:0,variants:[{begin:/([+-]+)?[\d]+_[\d_]+/},{begin:s.NUMBER_RE}] +},i=s.COMMENT();i.variants=[{begin:/;/,end:/$/},{begin:/#/,end:/$/}];const t={ +className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{begin:/\$\{(.*?)\}/ +}]},r={className:"literal",begin:/\bon|off|true|false|yes|no\b/},l={ +className:"string",contains:[s.BACKSLASH_ESCAPE],variants:[{begin:"'''", +end:"'''",relevance:10},{begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"' +},{begin:"'",end:"'"}]},c={begin:/\[/,end:/\]/,contains:[i,r,t,l,a,"self"], +relevance:0 +},g="("+[/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/].map((n=>e(n))).join("|")+")" +;return{name:"TOML, also INI",aliases:["toml"],case_insensitive:!0,illegal:/\S/, +contains:[i,{className:"section",begin:/\[+/,end:/\]+/},{ +begin:n(g,"(\\s*\\.\\s*",g,")*",n("(?=",/\s*=\s*[^#\s]/,")")),className:"attr", +starts:{end:/$/,contains:[i,c,r,t,l,a]}}]}}})()); +hljs.registerLanguage("java",(()=>{"use strict" +;var e="\\.([0-9](_*[0-9])*)",n="[0-9a-fA-F](_*[0-9a-fA-F])*",a={ +className:"number",variants:[{ +begin:`(\\b([0-9](_*[0-9])*)((${e})|\\.)?|(${e}))[eE][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` +},{begin:`\\b([0-9](_*[0-9])*)((${e})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{ +begin:`(${e})[fFdD]?\\b`},{begin:"\\b([0-9](_*[0-9])*)[fFdD]\\b"},{ +begin:`\\b0[xX]((${n})\\.?|(${n})?\\.(${n}))[pP][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` +},{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${n})[lL]?\\b`},{ +begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}], +relevance:0};return e=>{ +var n="false synchronized int abstract float private char boolean var static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",s={ +className:"meta",begin:"@[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*", +contains:[{begin:/\(/,end:/\)/,contains:["self"]}]};const r=a;return{ +name:"Java",aliases:["jsp"],keywords:n,illegal:/<\/|#/, +contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/, +relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),{ +begin:/import java\.[a-z]+\./,keywords:"import",relevance:2 +},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{ +className:"class",beginKeywords:"class interface enum",end:/[{;=]/, +excludeEnd:!0,keywords:"class interface enum",illegal:/[:"\[\]]/,contains:[{ +beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{ +beginKeywords:"new throw return else",relevance:0},{className:"class", +begin:"record\\s+"+e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,excludeEnd:!0, +end:/[{;=]/,keywords:n,contains:[{beginKeywords:"record"},{ +begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0, +contains:[e.UNDERSCORE_TITLE_MODE]},{className:"params",begin:/\(/,end:/\)/, +keywords:n,relevance:0,contains:[e.C_BLOCK_COMMENT_MODE] +},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"function", +begin:"([\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*(<[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*(\\s*,\\s*[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*)*>)?\\s+)+"+e.UNDERSCORE_IDENT_RE+"\\s*\\(", +returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:n,contains:[{ +begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0, +contains:[e.UNDERSCORE_TITLE_MODE]},{className:"params",begin:/\(/,end:/\)/, +keywords:n,relevance:0, +contains:[s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,r,e.C_BLOCK_COMMENT_MODE] +},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},r,s]}}})()); +hljs.registerLanguage("javascript",(()=>{"use strict" +;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],s=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]) +;function r(e){return i("(?=",e,")")}function i(...e){return e.map((e=>{ +return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}return t=>{ +const c=e,o={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/, +isTrulyOpeningTag:(e,n)=>{const a=e[0].length+e.index,s=e.input[a] +;"<"!==s?">"===s&&(((e,{after:n})=>{const a="", +returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{ +begin:t.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0 +},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:l,contains:A}]}] +},{begin:/,/,relevance:0},{className:"",begin:/\s/,end:/\s*/,skip:!0},{ +variants:[{begin:"<>",end:""},{begin:o.begin,"on:begin":o.isTrulyOpeningTag, +end:o.end}],subLanguage:"xml",contains:[{begin:o.begin,end:o.end,skip:!0, +contains:["self"]}]}],relevance:0},{className:"function", +beginKeywords:"function",end:/[{;]/,excludeEnd:!0,keywords:l, +contains:["self",t.inherit(t.TITLE_MODE,{begin:c}),p],illegal:/%/},{ +beginKeywords:"while if switch catch for"},{className:"function", +begin:t.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", +returnBegin:!0,contains:[p,t.inherit(t.TITLE_MODE,{begin:c})]},{variants:[{ +begin:"\\."+c},{begin:"\\$"+c}],relevance:0},{className:"class", +beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"[\]]/,contains:[{ +beginKeywords:"extends"},t.UNDERSCORE_TITLE_MODE]},{begin:/\b(?=constructor)/, +end:/[{;]/,excludeEnd:!0,contains:[t.inherit(t.TITLE_MODE,{begin:c}),"self",p] +},{begin:"(get|set)\\s+(?="+c+"\\()",end:/\{/,keywords:"get set", +contains:[t.inherit(t.TITLE_MODE,{begin:c}),{begin:/\(\)/},p]},{begin:/\$[(.]/}] +}}})()); +hljs.registerLanguage("json",(()=>{"use strict";return n=>{const e={ +literal:"true false null" +},i=[n.C_LINE_COMMENT_MODE,n.C_BLOCK_COMMENT_MODE],a=[n.QUOTE_STRING_MODE,n.C_NUMBER_MODE],l={ +end:",",endsWithParent:!0,excludeEnd:!0,contains:a,keywords:e},t={begin:/\{/, +end:/\}/,contains:[{className:"attr",begin:/"/,end:/"/, +contains:[n.BACKSLASH_ESCAPE],illegal:"\\n"},n.inherit(l,{begin:/:/ +})].concat(i),illegal:"\\S"},s={begin:"\\[",end:"\\]",contains:[n.inherit(l)], +illegal:"\\S"};return a.push(t,s),i.forEach((n=>{a.push(n)})),{name:"JSON", +contains:a,keywords:e,illegal:"\\S"}}})()); +hljs.registerLanguage("kotlin",(()=>{"use strict" +;var e="\\.([0-9](_*[0-9])*)",n="[0-9a-fA-F](_*[0-9a-fA-F])*",a={ +className:"number",variants:[{ +begin:`(\\b([0-9](_*[0-9])*)((${e})|\\.)?|(${e}))[eE][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` +},{begin:`\\b([0-9](_*[0-9])*)((${e})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{ +begin:`(${e})[fFdD]?\\b`},{begin:"\\b([0-9](_*[0-9])*)[fFdD]\\b"},{ +begin:`\\b0[xX]((${n})\\.?|(${n})?\\.(${n}))[pP][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` +},{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${n})[lL]?\\b`},{ +begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}], +relevance:0};return e=>{const n={ +keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual", +built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing", +literal:"true false null"},i={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@" +},s={className:"subst",begin:/\$\{/,end:/\}/,contains:[e.C_NUMBER_MODE]},t={ +className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},r={className:"string", +variants:[{begin:'"""',end:'"""(?=[^"])',contains:[t,s]},{begin:"'",end:"'", +illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/, +contains:[e.BACKSLASH_ESCAPE,t,s]}]};s.contains.push(r);const l={ +className:"meta", +begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?" +},c={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/, +end:/\)/,contains:[e.inherit(r,{className:"meta-string"})]}] +},o=a,b=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),E={ +variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/, +contains:[]}]},d=E;return d.variants[1].contains=[E],E.variants[1].contains=[d], +{name:"Kotlin",aliases:["kt"],keywords:n,contains:[e.COMMENT("/\\*\\*","\\*/",{ +relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+"}] +}),e.C_LINE_COMMENT_MODE,b,{className:"keyword", +begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol", +begin:/@\w+/}]}},i,l,c,{className:"function",beginKeywords:"fun",end:"[(]|$", +returnBegin:!0,excludeEnd:!0,keywords:n,relevance:5,contains:[{ +begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0, +contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://, +keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/, +endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/, +endsWithParent:!0,contains:[E,e.C_LINE_COMMENT_MODE,b],relevance:0 +},e.C_LINE_COMMENT_MODE,b,l,c,r,e.C_NUMBER_MODE]},b]},{className:"class", +beginKeywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0, +illegal:"extends implements",contains:[{ +beginKeywords:"public protected internal private constructor" +},e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0, +excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,]|$/, +excludeBegin:!0,returnEnd:!0},l,c]},r,{className:"meta",begin:"^#!/usr/bin/env", +end:"$",illegal:"\n"},o]}}})()); +hljs.registerLanguage("less",(()=>{"use strict";return e=>{ +var n="([\\w-]+|@\\{[\\w-]+\\})",a=[],s=[],t=e=>({className:"string", +begin:"~?"+e+".*?"+e}),r=(e,n,a)=>({className:e,begin:n,relevance:a}),i={ +begin:"\\(",end:"\\)",contains:s,relevance:0} +;s.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,t("'"),t('"'),e.CSS_NUMBER_MODE,{ +begin:"(url|data-uri)\\(",starts:{className:"string",end:"[\\)\\n]", +excludeEnd:!0} +},r("number","#[0-9A-Fa-f]+\\b"),i,r("variable","@@?[\\w-]+",10),r("variable","@\\{[\\w-]+\\}"),r("built_in","~?`[^`]*?`"),{ +className:"attribute",begin:"[\\w-]+\\s*:",end:":",returnBegin:!0,excludeEnd:!0 +},{className:"meta",begin:"!important"});var c=s.concat({begin:/\{/,end:/\}/, +contains:a}),l={beginKeywords:"when",endsWithParent:!0,contains:[{ +beginKeywords:"and not"}].concat(s)},g={begin:n+"\\s*:",returnBegin:!0, +end:"[;}]",relevance:0,contains:[{className:"attribute",begin:n,end:":", +excludeEnd:!0,starts:{endsWithParent:!0,illegal:"[<=$]",relevance:0,contains:s} +}]},d={className:"keyword", +begin:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b", +starts:{end:"[;{}]",returnEnd:!0,contains:s,relevance:0}},o={ +className:"variable",variants:[{begin:"@[\\w-]+\\s*:",relevance:15},{ +begin:"@[\\w-]+"}],starts:{end:"[;}]",returnEnd:!0,contains:c}},b={variants:[{ +begin:"[\\.#:&\\[>]",end:"[;{}]"},{begin:n,end:/\{/}],returnBegin:!0, +returnEnd:!0,illegal:"[<='$\"]",relevance:0, +contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,l,r("keyword","all\\b"),r("variable","@\\{[\\w-]+\\}"),r("selector-tag",n+"%?",0),r("selector-id","#"+n),r("selector-class","\\."+n,0),r("selector-tag","&",0),{ +className:"selector-attr",begin:"\\[",end:"\\]"},{className:"selector-pseudo", +begin:/:(:)?[a-zA-Z0-9_\-+()"'.]+/},{begin:"\\(",end:"\\)",contains:c},{ +begin:"!important"}]} +;return a.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,d,o,g,b),{ +name:"Less",case_insensitive:!0,illegal:"[=>'/<($\"]",contains:a}}})()); +hljs.registerLanguage("lua",(()=>{"use strict";return e=>{ +const t="\\[=*\\[",a="\\]=*\\]",n={begin:t,end:a,contains:["self"] +},o=[e.COMMENT("--(?!\\[=*\\[)","$"),e.COMMENT("--\\[=*\\[",a,{contains:[n], +relevance:10})];return{name:"Lua",keywords:{$pattern:e.UNDERSCORE_IDENT_RE, +literal:"true false nil", +keyword:"and break do else elseif end for goto if in local not or repeat return then until while", +built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove" +},contains:o.concat([{className:"function",beginKeywords:"function",end:"\\)", +contains:[e.inherit(e.TITLE_MODE,{ +begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params", +begin:"\\(",endsWithParent:!0,contains:o}].concat(o) +},e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"string", +begin:t,end:a,contains:[n],relevance:5}])}}})()); +hljs.registerLanguage("makefile",(()=>{"use strict";return e=>{const i={ +className:"variable",variants:[{begin:"\\$\\("+e.UNDERSCORE_IDENT_RE+"\\)", +contains:[e.BACKSLASH_ESCAPE]},{begin:/\$[@%{"use strict";function e(e){ +return e?"string"==typeof e?e:e.source:null}function n(e){return a("(?=",e,")")} +function a(...n){return n.map((n=>e(n))).join("")}function s(...n){ +return"("+n.map((n=>e(n))).join("|")+")"}return e=>{ +const t=a(/[A-Z_]/,a("(",/[A-Z0-9_.-]+:/,")?"),/[A-Z0-9_.-]*/),i={ +className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},r={begin:/\s/, +contains:[{className:"meta-keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}] +},c=e.inherit(r,{begin:/\(/,end:/\)/}),l=e.inherit(e.APOS_STRING_MODE,{ +className:"meta-string"}),g=e.inherit(e.QUOTE_STRING_MODE,{ +className:"meta-string"}),m={endsWithParent:!0,illegal:/`]+/}]}] +}]};return{name:"HTML, XML", +aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"], +case_insensitive:!0,contains:[{className:"meta",begin://, +relevance:10,contains:[r,g,l,c,{begin:/\[/,end:/\]/,contains:[{className:"meta", +begin://,contains:[r,c,g,l]}]}]},e.COMMENT(//,{ +relevance:10}),{begin://,relevance:10},i,{ +className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"style"},contains:[m],starts:{ +end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag", +begin:/)/,end:/>/,keywords:{name:"script"},contains:[m],starts:{ +end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{ +className:"tag",begin:/<>|<\/>/},{className:"tag", +begin:a(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name", +begin:t,relevance:0,starts:m}]},{className:"tag",begin:a(/<\//,n(a(t,/>/))), +contains:[{className:"name",begin:t,relevance:0},{begin:/>/,relevance:0}]}]}} +})()); +hljs.registerLanguage("markdown",(()=>{"use strict";function n(...n){ +return n.map((n=>{return(e=n)?"string"==typeof e?e:e.source:null;var e +})).join("")}return e=>{const a={begin:/<\/?[A-Za-z_]/,end:">", +subLanguage:"xml",relevance:0},i={variants:[{begin:/\[.+?\]\[.*?\]/,relevance:0 +},{begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/, +relevance:2},{begin:n(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/), +relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{ +begin:/\[.+?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{ +className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0, +returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)", +excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[", +end:"\\]",excludeBegin:!0,excludeEnd:!0}]},s={className:"strong",contains:[], +variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},c={ +className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{ +begin:/_(?!_)/,end:/_/,relevance:0}]};s.contains.push(c),c.contains.push(s) +;let t=[a,i] +;return s.contains=s.contains.concat(t),c.contains=c.contains.concat(t), +t=t.concat(s,c),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{ +className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:t},{ +begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n", +contains:t}]}]},a,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)", +end:"\\s+",excludeEnd:!0},s,c,{className:"quote",begin:"^>\\s+",contains:t, +end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{ +begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{ +begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))", +contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{ +begin:"^[-\\*]{3,}",end:"$"},i,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{ +className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{ +className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}})()); +hljs.registerLanguage("nginx",(()=>{"use strict";return e=>{const n={ +className:"variable",variants:[{begin:/\$\d+/},{begin:/\$\{/,end:/\}/},{ +begin:/[$@]/+e.UNDERSCORE_IDENT_RE}]},a={endsWithParent:!0,keywords:{ +$pattern:"[a-z/_]+", +literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll" +},relevance:0,illegal:"=>",contains:[e.HASH_COMMENT_MODE,{className:"string", +contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/ +}]},{begin:"([a-z]+):/",end:"\\s",endsWithParent:!0,excludeEnd:!0,contains:[n] +},{className:"regexp",contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:"\\s\\^", +end:"\\s|\\{|;",returnEnd:!0},{begin:"~\\*?\\s+",end:"\\s|\\{|;",returnEnd:!0},{ +begin:"\\*(\\.[a-z\\-]+)+"},{begin:"([a-z\\-]+\\.)+\\*"}]},{className:"number", +begin:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{ +className:"number",begin:"\\b\\d+[kKmMgGdshdwy]*\\b",relevance:0},n]};return{ +name:"Nginx config",aliases:["nginxconf"],contains:[e.HASH_COMMENT_MODE,{ +begin:e.UNDERSCORE_IDENT_RE+"\\s+\\{",returnBegin:!0,end:/\{/,contains:[{ +className:"section",begin:e.UNDERSCORE_IDENT_RE}],relevance:0},{ +begin:e.UNDERSCORE_IDENT_RE+"\\s",end:";|\\{",returnBegin:!0,contains:[{ +className:"attribute",begin:e.UNDERSCORE_IDENT_RE,starts:a}],relevance:0}], +illegal:"[^\\s\\}]"}}})()); +hljs.registerLanguage("objectivec",(()=>{"use strict";return e=>{ +const n=/[a-zA-Z@][a-zA-Z0-9_]*/,_={$pattern:n, +keyword:"@interface @class @protocol @implementation"};return{ +name:"Objective-C",aliases:["mm","objc","obj-c","obj-c++","objective-c++"], +keywords:{$pattern:n, +keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN", +literal:"false true FALSE TRUE nil YES NO NULL", +built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once" +},illegal:"/,end:/$/, +illegal:"\\n"},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{ +className:"class",begin:"("+_.keyword.split(" ").join("|")+")\\b",end:/(\{|$)/, +excludeEnd:!0,keywords:_,contains:[e.UNDERSCORE_TITLE_MODE]},{ +begin:"\\."+e.UNDERSCORE_IDENT_RE,relevance:0}]}}})()); +hljs.registerLanguage("perl",(()=>{"use strict";function e(...e){ +return e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null;var n +})).join("")}return n=>{const t=/[dualxmsipn]{0,12}/,s={$pattern:/[\w.]+/, +keyword:"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qq fileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmget sub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedir ioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when" +},r={className:"subst",begin:"[$@]\\{",end:"\\}",keywords:s},i={begin:/->\{/, +end:/\}/},a={variants:[{begin:/\$\d/},{ +begin:e(/[$%@](\^\w\b|#\w+(::\w+)*|\{\w+\}|\w+(::\w*)*)/,"(?![A-Za-z])(?![@$%])") +},{begin:/[$%@][^\s\w{]/,relevance:0}] +},o=[n.BACKSLASH_ESCAPE,r,a],c=[a,n.HASH_COMMENT_MODE,n.COMMENT(/^=\w/,/=cut/,{ +endsWithParent:!0}),i,{className:"string",contains:o,variants:[{ +begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[", +end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{ +begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*<",end:">", +relevance:5},{begin:"qw\\s+q",end:"q",relevance:5},{begin:"'",end:"'", +contains:[n.BACKSLASH_ESCAPE]},{begin:'"',end:'"'},{begin:"`",end:"`", +contains:[n.BACKSLASH_ESCAPE]},{begin:/\{\w+\}/,contains:[],relevance:0},{ +begin:"-?\\w+\\s*=>",contains:[],relevance:0}]},{className:"number", +begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b", +relevance:0},{ +begin:"(\\/\\/|"+n.RE_STARTERS_RE+"|\\b(split|return|print|reverse|grep)\\b)\\s*", +keywords:"split return print reverse grep",relevance:0, +contains:[n.HASH_COMMENT_MODE,{className:"regexp", +begin:e(/(s|tr|y)/,/\//,/(\\.|[^\\\/])*/,/\//,/(\\.|[^\\\/])*/,/\//,t), +relevance:10},{className:"regexp",begin:/(m|qr)?\//,end:e(/\//,t), +contains:[n.BACKSLASH_ESCAPE],relevance:0}]},{className:"function", +beginKeywords:"sub",end:"(\\s*\\(.*?\\))?[;{]",excludeEnd:!0,relevance:5, +contains:[n.TITLE_MODE]},{begin:"-\\w\\b",relevance:0},{begin:"^__DATA__$", +end:"^__END__$",subLanguage:"mojolicious",contains:[{begin:"^@@.*",end:"$", +className:"comment"}]}];return r.contains=c,i.contains=c,{name:"Perl", +aliases:["pl","pm"],keywords:s,contains:c}}})()); +hljs.registerLanguage("php",(()=>{"use strict";return e=>{const r={ +className:"variable", +begin:"\\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?![A-Za-z0-9])(?![$])"},t={ +className:"meta",variants:[{begin:/<\?php/,relevance:10},{begin:/<\?[=]?/},{ +begin:/\?>/}]},a={className:"subst",variants:[{begin:/\$\w+/},{begin:/\{\$/, +end:/\}/}]},n=e.inherit(e.APOS_STRING_MODE,{illegal:null +}),i=e.inherit(e.QUOTE_STRING_MODE,{illegal:null, +contains:e.QUOTE_STRING_MODE.contains.concat(a)}),o=e.END_SAME_AS_BEGIN({ +begin:/<<<[ \t]*(\w+)\n/,end:/[ \t]*(\w+)\b/, +contains:e.QUOTE_STRING_MODE.contains.concat(a)}),l={className:"string", +contains:[e.BACKSLASH_ESCAPE,t],variants:[e.inherit(n,{begin:"b'",end:"'" +}),e.inherit(i,{begin:'b"',end:'"'}),i,n,o]},c={ +variants:[e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE]},s={ +keyword:"__CLASS__ __DIR__ __FILE__ __FUNCTION__ __LINE__ __METHOD__ __NAMESPACE__ __TRAIT__ die echo exit include include_once print require require_once array abstract and as binary bool boolean break callable case catch class clone const continue declare default do double else elseif empty enddeclare endfor endforeach endif endswitch endwhile eval extends final finally float for foreach from global goto if implements instanceof insteadof int integer interface isset iterable list match|0 new object or private protected public real return string switch throw trait try unset use var void while xor yield", +literal:"false null true", +built_in:"Error|0 AppendIterator ArgumentCountError ArithmeticError ArrayIterator ArrayObject AssertionError BadFunctionCallException BadMethodCallException CachingIterator CallbackFilterIterator CompileError Countable DirectoryIterator DivisionByZeroError DomainException EmptyIterator ErrorException Exception FilesystemIterator FilterIterator GlobIterator InfiniteIterator InvalidArgumentException IteratorIterator LengthException LimitIterator LogicException MultipleIterator NoRewindIterator OutOfBoundsException OutOfRangeException OuterIterator OverflowException ParentIterator ParseError RangeException RecursiveArrayIterator RecursiveCachingIterator RecursiveCallbackFilterIterator RecursiveDirectoryIterator RecursiveFilterIterator RecursiveIterator RecursiveIteratorIterator RecursiveRegexIterator RecursiveTreeIterator RegexIterator RuntimeException SeekableIterator SplDoublyLinkedList SplFileInfo SplFileObject SplFixedArray SplHeap SplMaxHeap SplMinHeap SplObjectStorage SplObserver SplObserver SplPriorityQueue SplQueue SplStack SplSubject SplSubject SplTempFileObject TypeError UnderflowException UnexpectedValueException ArrayAccess Closure Generator Iterator IteratorAggregate Serializable Throwable Traversable WeakReference Directory __PHP_Incomplete_Class parent php_user_filter self static stdClass" +};return{aliases:["php","php3","php4","php5","php6","php7","php8"], +case_insensitive:!0,keywords:s, +contains:[e.HASH_COMMENT_MODE,e.COMMENT("//","$",{contains:[t] +}),e.COMMENT("/\\*","\\*/",{contains:[{className:"doctag",begin:"@[A-Za-z]+"}] +}),e.COMMENT("__halt_compiler.+?;",!1,{endsWithParent:!0, +keywords:"__halt_compiler"}),t,{className:"keyword",begin:/\$this\b/},r,{ +begin:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{className:"function", +relevance:0,beginKeywords:"fn function",end:/[;{]/,excludeEnd:!0, +illegal:"[$%\\[]",contains:[e.UNDERSCORE_TITLE_MODE,{begin:"=>"},{ +className:"params",begin:"\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0, +keywords:s,contains:["self",r,e.C_BLOCK_COMMENT_MODE,l,c]}]},{className:"class", +beginKeywords:"class interface",relevance:0,end:/\{/,excludeEnd:!0, +illegal:/[:($"]/,contains:[{beginKeywords:"extends implements" +},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"namespace",relevance:0,end:";", +illegal:/[.']/,contains:[e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"use", +relevance:0,end:";",contains:[e.UNDERSCORE_TITLE_MODE]},l,c]}}})()); +hljs.registerLanguage("php-template",(()=>{"use strict";return n=>({ +name:"PHP template",subLanguage:"xml",contains:[{begin:/<\?(php|=)?/,end:/\?>/, +subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0},{begin:'b"', +end:'"',skip:!0},{begin:"b'",end:"'",skip:!0},n.inherit(n.APOS_STRING_MODE,{ +illegal:null,className:null,contains:null,skip:!0 +}),n.inherit(n.QUOTE_STRING_MODE,{illegal:null,className:null,contains:null, +skip:!0})]}]})})()); +hljs.registerLanguage("plaintext",(()=>{"use strict";return t=>({ +name:"Plain text",aliases:["text","txt"],disableAutodetect:!0})})()); +hljs.registerLanguage("properties",(()=>{"use strict";return e=>{ +var n="[ \\t\\f]*",a=n+"[:=]"+n,t="("+a+"|[ \\t\\f]+)",r="([^\\\\\\W:= \\t\\f\\n]|\\\\.)+",s="([^\\\\:= \\t\\f\\n]|\\\\.)+",i={ +end:t,relevance:0,starts:{className:"string",end:/$/,relevance:0,contains:[{ +begin:"\\\\\\\\"},{begin:"\\\\\\n"}]}};return{name:".properties", +case_insensitive:!0,illegal:/\S/,contains:[e.COMMENT("^\\s*[!#]","$"),{ +returnBegin:!0,variants:[{begin:r+a,relevance:1},{begin:r+"[ \\t\\f]+", +relevance:0}],contains:[{className:"attr",begin:r,endsParent:!0,relevance:0}], +starts:i},{begin:s+t,returnBegin:!0,relevance:0,contains:[{className:"meta", +begin:s,endsParent:!0,relevance:0}],starts:i},{className:"attr",relevance:0, +begin:s+n+"$"}]}}})()); +hljs.registerLanguage("python",(()=>{"use strict";return e=>{const n={ +keyword:"and as assert async await break class continue def del elif else except finally for from global if import in is lambda nonlocal|10 not or pass raise return try while with yield", +built_in:"__import__ abs all any ascii bin bool breakpoint bytearray bytes callable chr classmethod compile complex delattr dict dir divmod enumerate eval exec filter float format frozenset getattr globals hasattr hash help hex id input int isinstance issubclass iter len list locals map max memoryview min next object oct open ord pow print property range repr reversed round set setattr slice sorted staticmethod str sum super tuple type vars zip", +literal:"__debug__ Ellipsis False None NotImplemented True"},a={ +className:"meta",begin:/^(>>>|\.\.\.) /},s={className:"subst",begin:/\{/, +end:/\}/,keywords:n,illegal:/#/},i={begin:/\{\{/,relevance:0},r={ +className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{ +begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/, +contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{ +begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/, +contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{ +begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/, +contains:[e.BACKSLASH_ESCAPE,a,i,s]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/, +end:/"""/,contains:[e.BACKSLASH_ESCAPE,a,i,s]},{begin:/([uU]|[rR])'/,end:/'/, +relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{ +begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/, +end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/, +contains:[e.BACKSLASH_ESCAPE,i,s]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/, +contains:[e.BACKSLASH_ESCAPE,i,s]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] +},t="[0-9](_?[0-9])*",l=`(\\b(${t}))?\\.(${t})|\\b(${t})\\.`,b={ +className:"number",relevance:0,variants:[{ +begin:`(\\b(${t})|(${l}))[eE][+-]?(${t})[jJ]?\\b`},{begin:`(${l})[jJ]?`},{ +begin:"\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?\\b"},{ +begin:"\\b0[bB](_?[01])+[lL]?\\b"},{begin:"\\b0[oO](_?[0-7])+[lL]?\\b"},{ +begin:"\\b0[xX](_?[0-9a-fA-F])+[lL]?\\b"},{begin:`\\b(${t})[jJ]\\b`}]},o={ +className:"params",variants:[{begin:/\(\s*\)/,skip:!0,className:null},{ +begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n, +contains:["self",a,b,r,e.HASH_COMMENT_MODE]}]};return s.contains=[r,b,a],{ +name:"Python",aliases:["py","gyp","ipython"],keywords:n, +illegal:/(<\/|->|\?)|=>/,contains:[a,b,{begin:/\bself\b/},{beginKeywords:"if", +relevance:0},r,e.HASH_COMMENT_MODE,{variants:[{className:"function", +beginKeywords:"def"},{className:"class",beginKeywords:"class"}],end:/:/, +illegal:/[${=;\n,]/,contains:[e.UNDERSCORE_TITLE_MODE,o,{begin:/->/, +endsWithParent:!0,keywords:"None"}]},{className:"meta",begin:/^[\t ]*@/, +end:/(?=#)|$/,contains:[b,o,r]},{begin:/\b(print|exec)\(/}]}}})()); +hljs.registerLanguage("python-repl",(()=>{"use strict";return s=>({ +aliases:["pycon"],contains:[{className:"meta",starts:{end:/ |$/,starts:{end:"$", +subLanguage:"python"}},variants:[{begin:/^>>>(?=[ ]|$)/},{ +begin:/^\.\.\.(?=[ ]|$)/}]}]})})()); +hljs.registerLanguage("r",(()=>{"use strict";function e(...e){return e.map((e=>{ +return(a=e)?"string"==typeof a?a:a.source:null;var a})).join("")}return a=>{ +const n=/(?:(?:[a-zA-Z]|\.[._a-zA-Z])[._a-zA-Z0-9]*)|\.(?!\d)/;return{name:"R", +illegal:/->/,keywords:{$pattern:n, +keyword:"function if in break next repeat else for while", +literal:"NULL NA TRUE FALSE Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10", +built_in:"LETTERS letters month.abb month.name pi T F abs acos acosh all any anyNA Arg as.call as.character as.complex as.double as.environment as.integer as.logical as.null.default as.numeric as.raw asin asinh atan atanh attr attributes baseenv browser c call ceiling class Conj cos cosh cospi cummax cummin cumprod cumsum digamma dim dimnames emptyenv exp expression floor forceAndCall gamma gc.time globalenv Im interactive invisible is.array is.atomic is.call is.character is.complex is.double is.environment is.expression is.finite is.function is.infinite is.integer is.language is.list is.logical is.matrix is.na is.name is.nan is.null is.numeric is.object is.pairlist is.raw is.recursive is.single is.symbol lazyLoadDBfetch length lgamma list log max min missing Mod names nargs nzchar oldClass on.exit pos.to.env proc.time prod quote range Re rep retracemem return round seq_along seq_len seq.int sign signif sin sinh sinpi sqrt standardGeneric substitute sum switch tan tanh tanpi tracemem trigamma trunc unclass untracemem UseMethod xtfrm" +},compilerExtensions:[(a,n)=>{if(!a.beforeMatch)return +;if(a.starts)throw Error("beforeMatch cannot be used with starts") +;const i=Object.assign({},a);Object.keys(a).forEach((e=>{delete a[e] +})),a.begin=e(i.beforeMatch,e("(?=",i.begin,")")),a.starts={relevance:0, +contains:[Object.assign(i,{endsParent:!0})]},a.relevance=0,delete i.beforeMatch +}],contains:[a.COMMENT(/#'/,/$/,{contains:[{className:"doctag", +begin:"@examples",starts:{contains:[{begin:/\n/},{begin:/#'\s*(?=@[a-zA-Z]+)/, +endsParent:!0},{begin:/#'/,end:/$/,excludeBegin:!0}]}},{className:"doctag", +begin:"@param",end:/$/,contains:[{className:"variable",variants:[{begin:n},{ +begin:/`(?:\\.|[^`\\])+`/}],endsParent:!0}]},{className:"doctag", +begin:/@[a-zA-Z]+/},{className:"meta-keyword",begin:/\\[a-zA-Z]+/}] +}),a.HASH_COMMENT_MODE,{className:"string",contains:[a.BACKSLASH_ESCAPE], +variants:[a.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\(/,end:/\)(-*)"/ +}),a.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\{/,end:/\}(-*)"/ +}),a.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\[/,end:/\](-*)"/ +}),a.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\(/,end:/\)(-*)'/ +}),a.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\{/,end:/\}(-*)'/ +}),a.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\[/,end:/\](-*)'/}),{begin:'"',end:'"', +relevance:0},{begin:"'",end:"'",relevance:0}]},{className:"number",relevance:0, +beforeMatch:/([^a-zA-Z0-9._])/,variants:[{ +match:/0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?\d+i?/},{ +match:/0[xX][0-9a-fA-F]+([pP][+-]?\d+)?[Li]?/},{ +match:/(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?[Li]?/}]},{begin:"%",end:"%"},{ +begin:e(/[a-zA-Z][a-zA-Z_0-9]*/,"\\s+<-\\s+")},{begin:"`",end:"`",contains:[{ +begin:/\\./}]}]}}})()); +hljs.registerLanguage("ruby",(()=>{"use strict";function e(...e){ +return e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null;var n +})).join("")}return n=>{ +var a,i="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",s={ +keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor __FILE__", +built_in:"proc lambda",literal:"true false nil"},r={className:"doctag", +begin:"@[A-Za-z]+"},b={begin:"#<",end:">"},t=[n.COMMENT("#","$",{contains:[r] +}),n.COMMENT("^=begin","^=end",{contains:[r],relevance:10 +}),n.COMMENT("^__END__","\\n$")],c={className:"subst",begin:/#\{/,end:/\}/, +keywords:s},d={className:"string",contains:[n.BACKSLASH_ESCAPE,c],variants:[{ +begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:/%[qQwWx]?\(/, +end:/\)/},{begin:/%[qQwWx]?\[/,end:/\]/},{begin:/%[qQwWx]?\{/,end:/\}/},{ +begin:/%[qQwWx]?/},{begin:/%[qQwWx]?\//,end:/\//},{begin:/%[qQwWx]?%/, +end:/%/},{begin:/%[qQwWx]?-/,end:/-/},{begin:/%[qQwWx]?\|/,end:/\|/},{ +begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{ +begin:/<<[-~]?'?(\w+)\n(?:[^\n]*\n)*?\s*\1\b/,returnBegin:!0,contains:[{ +begin:/<<[-~]?'?/},n.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/, +contains:[n.BACKSLASH_ESCAPE,c]})]}]},g="[0-9](_?[0-9])*",l={className:"number", +relevance:0,variants:[{ +begin:`\\b([1-9](_?[0-9])*|0)(\\.(${g}))?([eE][+-]?(${g})|r)?i?\\b`},{ +begin:"\\b0[dD][0-9](_?[0-9])*r?i?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*r?i?\\b" +},{begin:"\\b0[oO][0-7](_?[0-7])*r?i?\\b"},{ +begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"},{ +begin:"\\b0(_?[0-7])+r?i?\\b"}]},o={className:"params",begin:"\\(",end:"\\)", +endsParent:!0,keywords:s},_=[d,{className:"class",beginKeywords:"class module", +end:"$|;",illegal:/=/,contains:[n.inherit(n.TITLE_MODE,{ +begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|!)?"}),{begin:"<\\s*",contains:[{ +begin:"("+n.IDENT_RE+"::)?"+n.IDENT_RE}]}].concat(t)},{className:"function", +begin:e(/def\s*/,(a=i+"\\s*(\\(|;|$)",e("(?=",a,")"))),keywords:"def",end:"$|;", +contains:[n.inherit(n.TITLE_MODE,{begin:i}),o].concat(t)},{begin:n.IDENT_RE+"::" +},{className:"symbol",begin:n.UNDERSCORE_IDENT_RE+"(!|\\?)?:",relevance:0},{ +className:"symbol",begin:":(?!\\s)",contains:[d,{begin:i}],relevance:0},l,{ +className:"variable", +begin:"(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])(?![A-Za-z])(?![@$?'])"},{ +className:"params",begin:/\|/,end:/\|/,relevance:0,keywords:s},{ +begin:"("+n.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[{ +className:"regexp",contains:[n.BACKSLASH_ESCAPE,c],illegal:/\n/,variants:[{ +begin:"/",end:"/[a-z]*"},{begin:/%r\{/,end:/\}[a-z]*/},{begin:"%r\\(", +end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}] +}].concat(b,t),relevance:0}].concat(b,t);c.contains=_,o.contains=_;var E=[{ +begin:/^\s*=>/,starts:{end:"$",contains:_}},{className:"meta", +begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>)(?=[ ])", +starts:{end:"$",contains:_}}];return t.unshift(b),{name:"Ruby", +aliases:["rb","gemspec","podspec","thor","irb"],keywords:s,illegal:/\/\*/, +contains:[n.SHEBANG({binary:"ruby"})].concat(E).concat(t).concat(_)}}})()); +hljs.registerLanguage("rust",(()=>{"use strict";return e=>{ +const n="([ui](8|16|32|64|128|size)|f(32|64))?",t="drop i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 str char bool Box Option Result String Vec Copy Send Sized Sync Drop Fn FnMut FnOnce ToOwned Clone Debug PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator SliceConcatExt ToString assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules! assert_ne! debug_assert_ne!" +;return{name:"Rust",aliases:["rs"],keywords:{$pattern:e.IDENT_RE+"!?", +keyword:"abstract as async await become box break const continue crate do dyn else enum extern false final fn for if impl in let loop macro match mod move mut override priv pub ref return self Self static struct super trait true try type typeof unsafe unsized use virtual where while yield", +literal:"true false Some None Ok Err",built_in:t},illegal:""}]}}})()); +hljs.registerLanguage("scss",(()=>{"use strict";return e=>{var t="@[a-z-]+",i={ +className:"variable",begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b"},r={ +className:"number",begin:"#[0-9A-Fa-f]+"} +;return e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE, +e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{name:"SCSS",case_insensitive:!0, +illegal:"[=/|']",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{ +className:"selector-id",begin:"#[A-Za-z0-9_-]+",relevance:0},{ +className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0},{ +className:"selector-attr",begin:"\\[",end:"\\]",illegal:"$"},{ +className:"selector-tag", +begin:"\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\b", +relevance:0},{className:"selector-pseudo", +begin:":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)" +},{className:"selector-pseudo", +begin:"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)" +},i,{className:"attribute", +begin:"\\b(src|z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background-blend-mode|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\b", +illegal:"[^\\s]"},{ +begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b" +},{begin:":",end:";", +contains:[i,r,e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,{ +className:"meta",begin:"!important"}]},{begin:"@(page|font-face)",lexemes:t, +keywords:"@page @font-face"},{begin:"@",end:"[{;]",returnBegin:!0, +keywords:"and or not only",contains:[{begin:t,className:"keyword" +},i,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,r,e.CSS_NUMBER_MODE]}]}}})()); +hljs.registerLanguage("shell",(()=>{"use strict";return s=>({ +name:"Shell Session",aliases:["console"],contains:[{className:"meta", +begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#]/,starts:{end:/[^\\](?=\s*$)/, +subLanguage:"bash"}}]})})()); +hljs.registerLanguage("sql",(()=>{"use strict";function e(e){ +return e?"string"==typeof e?e:e.source:null}function r(...r){ +return r.map((r=>e(r))).join("")}function t(...r){ +return"("+r.map((r=>e(r))).join("|")+")"}return e=>{ +const n=e.COMMENT("--","$"),a=["true","false","unknown"],i=["bigint","binary","blob","boolean","char","character","clob","date","dec","decfloat","decimal","float","int","integer","interval","nchar","nclob","national","numeric","real","row","smallint","time","timestamp","varchar","varying","varbinary"],s=["abs","acos","array_agg","asin","atan","avg","cast","ceil","ceiling","coalesce","corr","cos","cosh","count","covar_pop","covar_samp","cume_dist","dense_rank","deref","element","exp","extract","first_value","floor","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","last_value","lead","listagg","ln","log","log10","lower","max","min","mod","nth_value","ntile","nullif","percent_rank","percentile_cont","percentile_disc","position","position_regex","power","rank","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","row_number","sin","sinh","sqrt","stddev_pop","stddev_samp","substring","substring_regex","sum","tan","tanh","translate","translate_regex","treat","trim","trim_array","unnest","upper","value_of","var_pop","var_samp","width_bucket"],o=["create table","insert into","primary key","foreign key","not null","alter table","add constraint","grouping sets","on overflow","character set","respect nulls","ignore nulls","nulls first","nulls last","depth first","breadth first"],c=s,l=["abs","acos","all","allocate","alter","and","any","are","array","array_agg","array_max_cardinality","as","asensitive","asin","asymmetric","at","atan","atomic","authorization","avg","begin","begin_frame","begin_partition","between","bigint","binary","blob","boolean","both","by","call","called","cardinality","cascaded","case","cast","ceil","ceiling","char","char_length","character","character_length","check","classifier","clob","close","coalesce","collate","collect","column","commit","condition","connect","constraint","contains","convert","copy","corr","corresponding","cos","cosh","count","covar_pop","covar_samp","create","cross","cube","cume_dist","current","current_catalog","current_date","current_default_transform_group","current_path","current_role","current_row","current_schema","current_time","current_timestamp","current_path","current_role","current_transform_group_for_type","current_user","cursor","cycle","date","day","deallocate","dec","decimal","decfloat","declare","default","define","delete","dense_rank","deref","describe","deterministic","disconnect","distinct","double","drop","dynamic","each","element","else","empty","end","end_frame","end_partition","end-exec","equals","escape","every","except","exec","execute","exists","exp","external","extract","false","fetch","filter","first_value","float","floor","for","foreign","frame_row","free","from","full","function","fusion","get","global","grant","group","grouping","groups","having","hold","hour","identity","in","indicator","initial","inner","inout","insensitive","insert","int","integer","intersect","intersection","interval","into","is","join","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","language","large","last_value","lateral","lead","leading","left","like","like_regex","listagg","ln","local","localtime","localtimestamp","log","log10","lower","match","match_number","match_recognize","matches","max","member","merge","method","min","minute","mod","modifies","module","month","multiset","national","natural","nchar","nclob","new","no","none","normalize","not","nth_value","ntile","null","nullif","numeric","octet_length","occurrences_regex","of","offset","old","omit","on","one","only","open","or","order","out","outer","over","overlaps","overlay","parameter","partition","pattern","per","percent","percent_rank","percentile_cont","percentile_disc","period","portion","position","position_regex","power","precedes","precision","prepare","primary","procedure","ptf","range","rank","reads","real","recursive","ref","references","referencing","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","release","result","return","returns","revoke","right","rollback","rollup","row","row_number","rows","running","savepoint","scope","scroll","search","second","seek","select","sensitive","session_user","set","show","similar","sin","sinh","skip","smallint","some","specific","specifictype","sql","sqlexception","sqlstate","sqlwarning","sqrt","start","static","stddev_pop","stddev_samp","submultiset","subset","substring","substring_regex","succeeds","sum","symmetric","system","system_time","system_user","table","tablesample","tan","tanh","then","time","timestamp","timezone_hour","timezone_minute","to","trailing","translate","translate_regex","translation","treat","trigger","trim","trim_array","true","truncate","uescape","union","unique","unknown","unnest","update ","upper","user","using","value","values","value_of","var_pop","var_samp","varbinary","varchar","varying","versioning","when","whenever","where","width_bucket","window","with","within","without","year","add","asc","collation","desc","final","first","last","view"].filter((e=>!s.includes(e))),u={ +begin:r(/\b/,t(...c),/\s*\(/),keywords:{built_in:c.join(" ")}};return{ +name:"SQL",case_insensitive:!0,illegal:/[{}]|<\//,keywords:{ +$pattern:/\b[\w\.]+/,keyword:((e,{exceptions:r,when:t}={})=>{const n=t +;return r=r||[],e.map((e=>e.match(/\|\d+$/)||r.includes(e)?e:n(e)?e+"|0":e)) +})(l,{when:e=>e.length<3}).join(" "),literal:a.join(" "),type:i.join(" "), +built_in:"current_catalog current_date current_default_transform_group current_path current_role current_schema current_transform_group_for_type current_user session_user system_time system_user current_time localtime current_timestamp localtimestamp" +},contains:[{begin:t(...o),keywords:{$pattern:/[\w\.]+/, +keyword:l.concat(o).join(" "),literal:a.join(" "),type:i.join(" ")}},{ +className:"type", +begin:t("double precision","large object","with timezone","without timezone") +},u,{className:"variable",begin:/@[a-z0-9]+/},{className:"string",variants:[{ +begin:/'/,end:/'/,contains:[{begin:/''/}]}]},{begin:/"/,end:/"/,contains:[{ +begin:/""/}]},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,n,{className:"operator", +begin:/[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,relevance:0}]}}})()); +hljs.registerLanguage("swift",(()=>{"use strict";function e(e){ +return e?"string"==typeof e?e:e.source:null}function n(e){return i("(?=",e,")")} +function i(...n){return n.map((n=>e(n))).join("")}function a(...n){ +return"("+n.map((n=>e(n))).join("|")+")"} +const t=e=>i(/\b/,e,/\w$/.test(e)?/\b/:/\B/),u=["Protocol","Type"].map(t),s=["init","self"].map(t),r=["Any","Self"],o=["associatedtype",/as\?/,/as!/,"as","break","case","catch","class","continue","convenience","default","defer","deinit","didSet","do","dynamic","else","enum","extension","fallthrough","fileprivate(set)","fileprivate","final","for","func","get","guard","if","import","indirect","infix",/init\?/,/init!/,"inout","internal(set)","internal","in","is","lazy","let","mutating","nonmutating","open(set)","open","operator","optional","override","postfix","precedencegroup","prefix","private(set)","private","protocol","public(set)","public","repeat","required","rethrows","return","set","some","static","struct","subscript","super","switch","throws","throw",/try\?/,/try!/,"try","typealias","unowned(safe)","unowned(unsafe)","unowned","var","weak","where","while","willSet"],l=["false","nil","true"],c=["#colorLiteral","#column","#dsohandle","#else","#elseif","#endif","#error","#file","#fileID","#fileLiteral","#filePath","#function","#if","#imageLiteral","#keyPath","#line","#selector","#sourceLocation","#warn_unqualified_access","#warning"],b=["abs","all","any","assert","assertionFailure","debugPrint","dump","fatalError","getVaList","isKnownUniquelyReferenced","max","min","numericCast","pointwiseMax","pointwiseMin","precondition","preconditionFailure","print","readLine","repeatElement","sequence","stride","swap","swift_unboxFromSwiftValueWithType","transcode","type","unsafeBitCast","unsafeDowncast","withExtendedLifetime","withUnsafeMutablePointer","withUnsafePointer","withVaList","withoutActuallyEscaping","zip"],p=a(/[/=\-+!*%<>&|^~?]/,/[\u00A1-\u00A7]/,/[\u00A9\u00AB]/,/[\u00AC\u00AE]/,/[\u00B0\u00B1]/,/[\u00B6\u00BB\u00BF\u00D7\u00F7]/,/[\u2016-\u2017]/,/[\u2020-\u2027]/,/[\u2030-\u203E]/,/[\u2041-\u2053]/,/[\u2055-\u205E]/,/[\u2190-\u23FF]/,/[\u2500-\u2775]/,/[\u2794-\u2BFF]/,/[\u2E00-\u2E7F]/,/[\u3001-\u3003]/,/[\u3008-\u3020]/,/[\u3030]/),F=a(p,/[\u0300-\u036F]/,/[\u1DC0-\u1DFF]/,/[\u20D0-\u20FF]/,/[\uFE00-\uFE0F]/,/[\uFE20-\uFE2F]/),d=i(p,F,"*"),g=a(/[a-zA-Z_]/,/[\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-\u00BA]/,/[\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]/,/[\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]/,/[\u1E00-\u1FFF]/,/[\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]/,/[\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]/,/[\u2C00-\u2DFF\u2E80-\u2FFF]/,/[\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]/,/[\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-\uFE44]/,/[\uFE47-\uFFFD]/),f=a(g,/\d/,/[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/),m=i(g,f,"*"),w=i(/[A-Z]/,f,"*"),E=["autoclosure",i(/convention\(/,a("swift","block","c"),/\)/),"discardableResult","dynamicCallable","dynamicMemberLookup","escaping","frozen","GKInspectable","IBAction","IBDesignable","IBInspectable","IBOutlet","IBSegueAction","inlinable","main","nonobjc","NSApplicationMain","NSCopying","NSManaged",i(/objc\(/,m,/\)/),"objc","objcMembers","propertyWrapper","requires_stored_property_inits","testable","UIApplicationMain","unknown","usableFromInline"],y=["iOS","iOSApplicationExtension","macOS","macOSApplicationExtension","macCatalyst","macCatalystApplicationExtension","watchOS","watchOSApplicationExtension","tvOS","tvOSApplicationExtension","swift"] +;return e=>{const p=e.COMMENT("/\\*","\\*/",{contains:["self"]}),g={ +className:"keyword",begin:i(/\./,n(a(...u,...s))),end:a(...u,...s), +excludeBegin:!0},A={begin:i(/\./,a(...o)),relevance:0 +},C=o.filter((e=>"string"==typeof e)).concat(["_|0"]),v={variants:[{ +className:"keyword", +begin:a(...o.filter((e=>"string"!=typeof e)).concat(r).map(t),...s)}]},_={ +$pattern:a(/\b\w+(\(\w+\))?/,/#\w+/),keyword:C.concat(c).join(" "), +literal:l.join(" ")},N=[g,A,v],D=[{begin:i(/\./,a(...b)),relevance:0},{ +className:"built_in",begin:i(/\b/,a(...b),/(?=\()/)}],B={begin:/->/,relevance:0 +},M=[B,{className:"operator",relevance:0,variants:[{begin:d},{ +begin:`\\.(\\.|${F})+`}]}],h="([0-9a-fA-F]_*)+",S={className:"number", +relevance:0,variants:[{ +begin:"\\b(([0-9]_*)+)(\\.(([0-9]_*)+))?([eE][+-]?(([0-9]_*)+))?\\b"},{ +begin:`\\b0x(${h})(\\.(${h}))?([pP][+-]?(([0-9]_*)+))?\\b`},{ +begin:/\b0o([0-7]_*)+\b/},{begin:/\b0b([01]_*)+\b/}]},O=(e="")=>({ +className:"subst",variants:[{begin:i(/\\/,e,/[0\\tnr"']/)},{ +begin:i(/\\/,e,/u\{[0-9a-fA-F]{1,8}\}/)}]}),x=(e="")=>({className:"subst", +begin:i(/\\/,e,/[\t ]*(?:[\r\n]|\r\n)/)}),k=(e="")=>({className:"subst", +label:"interpol",begin:i(/\\/,e,/\(/),end:/\)/}),L=(e="")=>({begin:i(e,/"""/), +end:i(/"""/,e),contains:[O(e),x(e),k(e)]}),I=(e="")=>({begin:i(e,/"/), +end:i(/"/,e),contains:[O(e),k(e)]}),$={className:"string", +variants:[L(),L("#"),L("##"),L("###"),I(),I("#"),I("##"),I("###")]},T=[{ +begin:i(/`/,m,/`/)},{className:"variable",begin:/\$\d+/},{className:"variable", +begin:`\\$${f}+`}],j=[{begin:/(@|#)available\(/,end:/\)/,keywords:{ +$pattern:/[@#]?\w+/,keyword:y.concat(["@available","#available"]).join(" ")}, +contains:[...M,S,$]},{className:"keyword",begin:i(/@/,a(...E))},{ +className:"meta",begin:i(/@/,m)}],K={begin:n(/\b[A-Z]/),relevance:0,contains:[{ +className:"type", +begin:i(/(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)/,f,"+") +},{className:"type",begin:w,relevance:0},{begin:/[?!]+/,relevance:0},{ +begin:/\.\.\./,relevance:0},{begin:i(/\s+&\s+/,n(w)),relevance:0}]},P={ +begin://,keywords:_,contains:[...N,...j,B,K]};K.contains.push(P) +;for(const e of $.variants){const n=e.contains.find((e=>"interpol"===e.label)) +;n.keywords=_;const i=[...N,...D,...M,S,$,...T];n.contains=[...i,{begin:/\(/, +end:/\)/,contains:["self",...i]}]}return{name:"Swift",keywords:_, +contains:[e.C_LINE_COMMENT_MODE,p,{className:"function",beginKeywords:"func", +end:/\{/,excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{ +begin:/[A-Za-z$_][0-9A-Za-z$_]*/}),{begin://},{className:"params", +begin:/\(/,end:/\)/,endsParent:!0,keywords:_, +contains:["self",...N,S,$,e.C_BLOCK_COMMENT_MODE,{begin:":"}],illegal:/["']/}], +illegal:/\[|%/},{className:"class", +beginKeywords:"struct protocol class extension enum",end:"\\{",excludeEnd:!0, +keywords:_,contains:[e.inherit(e.TITLE_MODE,{ +begin:/[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/}),...N]},{beginKeywords:"import", +end:/$/,contains:[e.C_LINE_COMMENT_MODE,p],relevance:0 +},...N,...D,...M,S,$,...T,...j,K]}}})()); +hljs.registerLanguage("typescript",(()=>{"use strict" +;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],s=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]) +;function t(e){return i("(?=",e,")")}function i(...e){return e.map((e=>{ +return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}return r=>{ +const c={$pattern:e, +keyword:n.concat(["type","namespace","typedef","interface","public","private","protected","implements","declare","abstract","readonly"]).join(" "), +literal:a.join(" "), +built_in:s.concat(["any","void","number","boolean","string","object","never","enum"]).join(" ") +},o={className:"meta",begin:"@[A-Za-z$_][0-9A-Za-z$_]*"},l=(e,n,a)=>{ +const s=e.contains.findIndex((e=>e.label===n)) +;if(-1===s)throw Error("can not find mode to replace");e.contains.splice(s,1,a) +},b=(r=>{const c=e,o={begin:/<[A-Za-z0-9\\._:-]+/, +end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ +const a=e[0].length+e.index,s=e.input[a];"<"!==s?">"===s&&(((e,{after:n})=>{ +const a="", +returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{ +begin:r.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0 +},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:l,contains:f}]}] +},{begin:/,/,relevance:0},{className:"",begin:/\s/,end:/\s*/,skip:!0},{ +variants:[{begin:"<>",end:""},{begin:o.begin,"on:begin":o.isTrulyOpeningTag, +end:o.end}],subLanguage:"xml",contains:[{begin:o.begin,end:o.end,skip:!0, +contains:["self"]}]}],relevance:0},{className:"function", +beginKeywords:"function",end:/[{;]/,excludeEnd:!0,keywords:l, +contains:["self",r.inherit(r.TITLE_MODE,{begin:c}),A],illegal:/%/},{ +beginKeywords:"while if switch catch for"},{className:"function", +begin:r.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", +returnBegin:!0,contains:[A,r.inherit(r.TITLE_MODE,{begin:c})]},{variants:[{ +begin:"\\."+c},{begin:"\\$"+c}],relevance:0},{className:"class", +beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"[\]]/,contains:[{ +beginKeywords:"extends"},r.UNDERSCORE_TITLE_MODE]},{begin:/\b(?=constructor)/, +end:/[{;]/,excludeEnd:!0,contains:[r.inherit(r.TITLE_MODE,{begin:c}),"self",A] +},{begin:"(get|set)\\s+(?="+c+"\\()",end:/\{/,keywords:"get set", +contains:[r.inherit(r.TITLE_MODE,{begin:c}),{begin:/\(\)/},A]},{begin:/\$[(.]/}] +}})(r) +;return Object.assign(b.keywords,c),b.exports.PARAMS_CONTAINS.push(o),b.contains=b.contains.concat([o,{ +beginKeywords:"namespace",end:/\{/,excludeEnd:!0},{beginKeywords:"interface", +end:/\{/,excludeEnd:!0,keywords:"interface extends" +}]),l(b,"shebang",r.SHEBANG()),l(b,"use_strict",{className:"meta",relevance:10, +begin:/^\s*['"]use strict['"]/ +}),b.contains.find((e=>"function"===e.className)).relevance=0,Object.assign(b,{ +name:"TypeScript",aliases:["ts"]}),b}})()); +hljs.registerLanguage("vbnet",(()=>{"use strict";function e(e){ +return e?"string"==typeof e?e:e.source:null}function n(...n){ +return n.map((n=>e(n))).join("")}function t(...n){ +return"("+n.map((n=>e(n))).join("|")+")"}return e=>{ +const a=/\d{1,2}\/\d{1,2}\/\d{4}/,i=/\d{4}-\d{1,2}-\d{1,2}/,s=/(\d|1[012])(:\d+){0,2} *(AM|PM)/,r=/\d{1,2}(:\d{1,2}){1,2}/,o={ +className:"literal",variants:[{begin:n(/# */,t(i,a),/ *#/)},{ +begin:n(/# */,r,/ *#/)},{begin:n(/# */,s,/ *#/)},{ +begin:n(/# */,t(i,a),/ +/,t(s,r),/ *#/)}]},l=e.COMMENT(/'''/,/$/,{contains:[{ +className:"doctag",begin:/<\/?/,end:/>/}]}),c=e.COMMENT(null,/$/,{variants:[{ +begin:/'/},{begin:/([\t ]|^)REM(?=\s)/}]});return{name:"Visual Basic .NET", +aliases:["vb"],case_insensitive:!0,classNameAliases:{label:"symbol"},keywords:{ +keyword:"addhandler alias aggregate ansi as async assembly auto binary by byref byval call case catch class compare const continue custom declare default delegate dim distinct do each equals else elseif end enum erase error event exit explicit finally for friend from function get global goto group handles if implements imports in inherits interface into iterator join key let lib loop me mid module mustinherit mustoverride mybase myclass namespace narrowing new next notinheritable notoverridable of off on operator option optional order overloads overridable overrides paramarray partial preserve private property protected public raiseevent readonly redim removehandler resume return select set shadows shared skip static step stop structure strict sub synclock take text then throw to try unicode until using when where while widening with withevents writeonly yield", +built_in:"addressof and andalso await directcast gettype getxmlnamespace is isfalse isnot istrue like mod nameof new not or orelse trycast typeof xor cbool cbyte cchar cdate cdbl cdec cint clng cobj csbyte cshort csng cstr cuint culng cushort", +type:"boolean byte char date decimal double integer long object sbyte short single string uinteger ulong ushort", +literal:"true false nothing"}, +illegal:"//|\\{|\\}|endif|gosub|variant|wend|^\\$ ",contains:[{ +className:"string",begin:/"(""|[^/n])"C\b/},{className:"string",begin:/"/, +end:/"/,illegal:/\n/,contains:[{begin:/""/}]},o,{className:"number",relevance:0, +variants:[{begin:/\b\d[\d_]*((\.[\d_]+(E[+-]?[\d_]+)?)|(E[+-]?[\d_]+))[RFD@!#]?/ +},{begin:/\b\d[\d_]*((U?[SIL])|[%&])?/},{begin:/&H[\dA-F_]+((U?[SIL])|[%&])?/},{ +begin:/&O[0-7_]+((U?[SIL])|[%&])?/},{begin:/&B[01_]+((U?[SIL])|[%&])?/}]},{ +className:"label",begin:/^\w+:/},l,c,{className:"meta", +begin:/[\t ]*#(const|disable|else|elseif|enable|end|externalsource|if|region)\b/, +end:/$/,keywords:{ +"meta-keyword":"const disable else elseif enable end externalsource if region then" +},contains:[c]}]}}})()); +hljs.registerLanguage("yaml",(()=>{"use strict";return e=>{ +var n="true false yes no null",a="[\\w#;/?:@&=+$,.~*'()[\\]]+",s={ +className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/ +},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable", +variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},i=e.inherit(s,{ +variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),l={ +end:",",endsWithParent:!0,excludeEnd:!0,contains:[],keywords:n,relevance:0},t={ +begin:/\{/,end:/\}/,contains:[l],illegal:"\\n",relevance:0},g={begin:"\\[", +end:"\\]",contains:[l],illegal:"\\n",relevance:0},b=[{className:"attr", +variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{ +begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)" +}]},{className:"meta",begin:"^---\\s*$",relevance:10},{className:"string", +begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{ +begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0, +relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type", +begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a +},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta", +begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)", +relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{ +className:"number", +begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b" +},{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},t,g,s],r=[...b] +;return r.pop(),r.push(i),l.contains=r,{name:"YAML",case_insensitive:!0, +aliases:["yml","YAML"],contains:b}}})()); \ No newline at end of file diff --git a/pywebio/html/js/mditor.min.js b/pywebio/html/js/mditor.min.js deleted file mode 100755 index 287ec321..00000000 --- a/pywebio/html/js/mditor.min.js +++ /dev/null @@ -1,11 +0,0 @@ -/*! - * Mditor embed version 1.3.3 - * Homepage: http://mditor.com - */ -!function(e){function t(i){if(n[i])return n[i].exports;var r=n[i]={exports:{},id:i,loaded:!1};return e[i].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";var i=n(1),r=n(84),s=n(89),o=n(94),a=n(97),l=n(100),c=n(102);n(151),n(158),n(159),n(160);var u="mditor-hidden",p=new i.Component({template:n(162),onInit:function(){this.PLATFORM=navigator.platform.toLowerCase(),this.EOL="win32"==this.PLATFORM?"\r\n":"\n",this.CMD=this.PLATFORM.indexOf("mac")>-1?"command":"ctrl",this.INDENT=" ",this.shortcut=new l(this),this.Parser=c,this.parser=new c(this)},onReady:function(){var e=this;this.shortcut.bind("tab",this.editor.addIndent.bind(this.editor)),this.shortcut.bind("shift+tab",this.editor.removeIndent.bind(this.editor)),this.shortcut.bind("enter",function(t){e._ulAndQuoteAutoComplete(t),e._olAutoComplete(t),e._keepIndent(t)},!0),setTimeout(function(){e.$emit("ready")},0)},components:{Toolbar:r,Editor:s,Viewer:o,Finder:a},props:{height:"400px",width:"auto",preview:!1,split:!0,fullscreen:!1},data:function(){return{self:this,value:""}},find:function(e){this.finder.show(e)},syncScroll:function(){if(this.split&&!this.preview){var e=this.editor.textarea.offsetHeight,t=this.editor.textarea.scrollHeight,n=this.viewer.$element.scrollHeight,i=this.editor.textarea.scrollTop,r=i*(n-e)/(t-e);this.viewer.$element.scrollTop=r}},onChanged:function(e){this.$emit("changed",e),this.syncScroll()},onInput:function(e){this.$emit("input",e)},onPaste:function(e){this.$emit("paste",e),this.syncScroll()},onHeadDblClick:function(e){"I"!=e.target.tagName&&this.$emit("head-dblclick",e)},_keepIndent:function(e){var t=this.editor.getBeforeTextInLine(),n=t.split(this.INDENT);if(!(n.length<2)){for(var i=0,r=[this.EOL];""===n[i]&&i "!=n||(t.length>n.length?this.editor.insertBeforeText(this.EOL+n):(this.editor.selectBeforeText(n.length),this.editor.setSelectText("")),e.preventDefault())},_olAutoComplete:function(e){var t=/^\d+\./,n=this.editor.getBeforeTextInLine(),i=n.trim();if(t.test(i)){var r=i.split(".")[0];i.length>r.length+1?this.editor.insertBeforeText(this.EOL+(parseInt(r)+1)+". "):(this.editor.selectBeforeText(n.length),this.editor.setSelectText("")),e.preventDefault()}},focus:function(){this.preview?this.$element.focus():this.editor.focus()},blur:function(){this.editor.blur()},addCommand:function(e){e.name&&e.handler&&(this.commands=this.commands||{},this.commands[e.name]=e,e.key&&this.shortcut.bind(e.key,e.name,e.allowDefault,e.owner))},removeCommand:function(e){this.commands=this.commands||{};var t=this.commands[e];t&&(this.shortcut.unbind(t.key),this.commands[e]=null,delete this.commands[e])},execCommand:function(e,t){t=t||{},t.mditor=this,t.toolbar=this.toolbar,t.editor=this.editor,this.commands[e].handler.call(this,t)}});p.fromTextarea=function(e){e.classList.add(u);var t=new p;return t.value=e.value,t.$watch("value",function(){e.value=t.value}),t.$mount(e),t.switchTextarea=function(){e.classList.contains(u)?(e.value=t.value,t.$element.classList.add(u),e.classList.remove(u)):(t.value=e.value,e.classList.add(u),t.$element.classList.remove(u))},t},p.Parser=c,e.exports=window.Mditor=p},function(e,t,n){"use strict";var i=n(2),r=n(3),s=n(4),o=n(5),a=n(6),l=n(51),c=n(79),u=n(50);r.copy(l,c),c.version=i.version,c.Template=l,c.Watcher=o,c.Observer=a,c.EventEmitter=u,c.utils=r,c.Class=s,c.use=function(e){var t=e.install||e;if(!r.isFunction(t))throw new Error("Invalid Plugin");return t.call(e,this)},e.exports=c},function(e,t){e.exports={name:"mokit",version:"3.1.3"}},function(e,t,n){!function(e){e.noop=function(){},e.isNull=function(e){return null===e||"undefined"==typeof e},e.trim=function(e){return this.isNull(e)?e:e.trim?e.trim():e.replace(/(^[\\s]*)|([\\s]*$)/g,"")},e.replace=function(e,t,n){return this.isNull(e)?e:e.replace(new RegExp(t,"g"),n)},e.startWith=function(e,t){return!this.isNull(e)&&!this.isNull(t)&&0===e.indexOf(t)},e.contains=function(e,t){return!this.isNull(e)&&!this.isNull(t)&&e.indexOf(t)>-1},e.endWith=function(e,t){return!this.isNull(e)&&!this.isNull(t)&&e.indexOf(t)===e.length-t.length},e.has=e.hasProperty=function(e,t){return!this.isNull(e)&&!this.isNull(t)&&(t in e||e.hasOwnProperty(t))},e.isFunction=function(e){return!this.isNull(e)&&"function"==typeof e},e.isString=function(e){return!this.isNull(e)&&("string"==typeof e||e instanceof String)},e.isNumber=function(e){return!this.isNull(e)&&("number"==typeof e||e instanceof Number)},e.isBoolean=function(e){return!this.isNull(e)&&("boolean"==typeof e||e instanceof Boolean)},e.isElement=function(e){return!this.isNull(e)&&(window.Element?e instanceof Element:e.tagName&&e.nodeType&&e.nodeName&&e.attributes&&e.ownerDocument)},e.isText=function(e){return!this.isNull(e)&&e instanceof Text},e.isObject=function(e){return!this.isNull(e)&&"object"==typeof e},e.isArray=function(e){if(this.isNull(e))return!1;var t="[object Array]"===Object.prototype.toString.call(e),n=e instanceof Array,i=!this.isString(e)&&this.isNumber(e.length)&&this.isFunction(e.splice),r=!this.isString(e)&&this.isNumber(e.length)&&e[0];return t||n||i||r},e.isDate=function(e){return!this.isNull(e)&&e instanceof Date},e.isRegexp=function(e){return e instanceof RegExp},e.toArray=function(e){return this.isNull(e)?[]:Array.prototype.slice.call(e)},e.toDate=function(e){var t=this;return t.isNumber(e)?new Date(e):t.isString(e)?new Date(t.replace(t.replace(e,"-","/"),"T"," ")):t.isDate(e)?e:null},e.each=function(e,t,n){if(!this.isNull(e)&&!this.isNull(t))if(this.isArray(e))for(var i=e.length,r=0;r-1))if(delete t[i],Object.getOwnPropertyDescriptor)try{Object.defineProperty(t,i,Object.getOwnPropertyDescriptor(e,i))}catch(n){t[i]=e[i]}else t[i]=e[i]}),t},e.clone=function(e,t){if(this.isNull(e)||this.isString(e)||this.isNumber(e)||this.isBoolean(e)||this.isDate(e))return e;var n=e;try{n=new e.constructor}catch(e){}return this.each(e,function(e,i){n[e]==i||this.contains(t,e)||(this.isObject(i)?n[e]=this.clone(i,t):n[e]=i)},this),["toString","valueOf"].forEach(function(i){this.contains(t,i)||this.defineFreezeProp(n,i,e[i])},this),n},e.mix=function(t,n,i,r,s){if(r)switch(r){case 1:return e.mix(t.prototype,n.prototype,i,0);case 2:e.mix(t.prototype,n.prototype,i,0);break;case 3:return e.mix(t,n.prototype,i,0);case 4:return e.mix(t.prototype,n,i,0)}return n=n||{},t=t||(this.isArray(n)?[]:{}),this.keys(n).forEach(function(r){this.contains(i,r)||s&&this.isNull(n[r])||(!this.isObject(n[r])||n[r].constructor!=Object&&n[r].constructor!=Array&&null!=n[r].constructor?t[r]=n[r]:t[r]=e.mix(t[r],n[r],i,0,s))},this),t},e.defineFreezeProp=function(e,t,n){try{Object.defineProperty(e,t,{value:n,enumerable:!1,configurable:!0,writable:!1})}catch(i){e[t]=n}},e.keys=function(e){if(Object.keys)return Object.keys(e);var t=[];return this.each(e,function(e){t.push(e)}),t},e.create=function(e,t){if(Object.create)return Object.create(e,t);var n=function(){};n.prototype=e;var i=new n;return t&&this.copy(t,i),i},e.setPrototypeOf=function(e,t){return Object.setPrototypeOf?Object.setPrototypeOf(e,t||this.create(null)):("__proto__"in Object||this.copy(t,e),void(e.__proto__=t))},e.getPrototypeOf=function(e){return e.__proto__?e.__proto__:Object.getPrototypeOf?Object.getPrototypeOf(e):e.constructor?e.constructor.prototype:void 0},e.deepEqual=function(e,t){if(e===t)return!0;if(!this.isObject(e)||!this.isObject(t))return!1;var n=this.keys(e),i=this.keys(t);if(n.length!==i.length)return!1;var r=n.concat(i),s=this.create(null),o=!0;return this.each(r,function(n,i){s[i]||(this.deepEqual(e[i],t[i])||(o=!1),s[i]=!0)},this),o},e.fromTo=function(e,t,n,i){if(i||(i=[n,n=i][0]),n=Math.abs(n||1),e=t;r-=n)i(r)},e.newGuid=function(){var e=function(){return(65536*(1+Math.random())|0).toString(16).substring(1)};return e()+e()+"-"+e()+"-"+e()+"-"+e()+"-"+e()+e()+e()},e.map=function(e,t){var n=this.isArray(e)?[]:{};return this.each(e,function(e,i){n[e]=t(e,i)}),n},e.setByPath=function(e,t,n){this.isNull(e)||this.isNull(t)||""===t||(this.isArray(t)||(t=t.replace(/\[/,".").replace(/\]/,".").split(".")),this.each(t,function(i,r){this.isNull(r)||r.length<1||(i===t.length-1?e[r]=n:(e[r]=e[r]||{},e=e[r]))},this))},e.getByPath=function(e,t){return this.isNull(e)||this.isNull(t)||""===t?e:(this.isArray(t)||(t=t.replace(/\[/,".").replace(/\]/,".").split(".")),this.each(t,function(t,n){this.isNull(n)||n.length<1||this.isNull(e)||(e=e[n])},this),e)},e.unique=function(e){if(this.isNull(e))return e;var t=[];return this.each(e,function(e,n){t.indexOf(n)>-1||t.push(n)}),t},e.getFunctionArgumentNames=function(e){if(!e)return[];var t=e.toString(),n=t.split(")")[0].split("=>")[0].split("(");return(n[1]||n[0]).split(",").map(function(e){return e.trim()}).filter(function(e){return"function"!=e})},e.short=function(e,t){if(!e)return e;t=t||40;var n=e.length,i=t/2;return n>t?e.substr(0,i)+"..."+e.substr(n-i):e},e.firstUpper=function(e){if(!this.isNull(e))return e.substring(0,1).toUpperCase()+e.substring(1)},e.escapeRegExp=function(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")},e.parseDom=function(t){this._PDD_=this._PDD_||document.createElement("div"),this._PDD_.innerHTML=e.trim(t);var n=this._PDD_.childNodes[0];return n&&(n=n.cloneNode(!0)),this._PDD_.innerHTML="",n}}(t)},function(e,t,n){function i(e){e=e||r.create(null),e.$name=e.$name||"Class",e.$extends=e.$extends||i,e.$static=e.$static||r.create(null);var t=r.isFunction(e.$extends)?e.$extends.prototype:e.$extends,n=function(){if(!this.$super){r.defineFreezeProp(this,"$super",function(){if(this._super_called_)return this._super_ret_;if(this._super_called_=!0,r.isFunction(e.$extends)){if(this._super_ret_=e.$extends.apply(this,arguments),this._super_ret_){var t=r.getPrototypeOf(this);r.setPrototypeOf(t,this._super_ret_)}}else this._super_ret_=e.$extends;return this._super_ret_});for(var n in t){var i=t[n];r.isFunction(i)?this.$super[n]=i.bind(this):this.$super[n]=i}}return r.isFunction(e.constructor)&&e.constructor!==Object?e.constructor.apply(this,arguments):void this.$super.apply(this,arguments)};return n.prototype=r.create(t),r.copy(e,n.prototype),r.defineFreezeProp(n.prototype,"$class",n),r.copy(e.$static,n),r.isFunction(e.$extends)&&r.setPrototypeOf(n,e.$extends),e.$extends.$extend||r.copy(i,n),r.defineFreezeProp(n,"$super",e.$extends),n}const r=n(3);i.$extend=function(e){return e.$extends=this,new i(e)},i.Class=i,e.exports=i},function(e,t,n){"use strict";var i=n(4),r=n(3),s=new i({constructor:function(e,t,n){if(!r.isFunction(e)||!r.isFunction(t))throw new Error("Invalid parameters");this.calcor=e,this.handler=t,n&&this.calc(!0)},calc:function(e){var t=this.calcor();!e&&r.deepEqual(t,this.value)||this.handler(t,this.value),this.value=r.clone(t)}});e.exports=s},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}var r=n(7),s=i(r),o=n(42),a=i(o),l=n(47),c=i(l),u=n(4),p=n(3),d=n(50),h="_observer_",f="change",m=10,g=[/^\_(.*)\_$/i,/^\_\_/i],b=new u({$extends:d,constructor:function(e,t){if(p.isNull(e))throw new Error("Invalid target");t=t||{};var n=e[h];return n?(p.copy(t,n.options),n.apply(),n):(d.call(this),p.defineFreezeProp(this,"options",t),p.defineFreezeProp(this,"shadow",{}),p.defineFreezeProp(this,"target",e),p.defineFreezeProp(this,"parents",[]),p.defineFreezeProp(e,h,this),void this.apply())},set:function(e,t){p.isFunction(t)||b.isIgnore(e)||((0,c.default)(this.target,e,{get:function(){return this[h].shadow[e]},set:function(t){var n=this[h],i=n.shadow[e];if(i!==t){if(p.isObject(t)){var r=new b(t);n.addChild(r,e)}i&&i[h]&&n.removeChild(i[h],e),n.shadow[e]=t,n.emitChange({path:e,value:t})}},configurable:!0,enumerable:!0}),this.target[e]=t)},apply:function(){p.isArray(this.target)&&this._wrapArray(this.target);var e=this._getPropertyNames(this.target);e.forEach(function(e){var t=(0,a.default)(this.target,e);"value"in t&&this.set(e,this.target[e])},this)},clearReference:function(){p.each(this.target,function(e,t){if(!p.isNull(t)){var n=t[h];n&&this.removeChild(n)}},this)},dispatch:function(e,t){t._src_!==this&&(t._src_=t._src_||this,t._layer_=t._layer_||0,t._layer_++>=m||(this.emit(e,t),!this.parents||this.parents.length<1||this.parents.forEach(function(n){if(!(n.name in n.parent.target))return n.parent.removeChild(this);var i=p.copy(t);i.path=n.name+"."+t.path,n.parent.dispatch(e,i)},this)))},addChild:function(e,t){if(p.isNull(e)||p.isNull(t))throw new Error("Invalid paramaters");e.options.root||e.parents.push({parent:this,name:t})},removeChild:function(e,t){if(p.isNull(e))throw new Error("Invalid paramaters");var n=-1;e.parents.forEach(function(e,i){e.parent===this&&e.name===t&&(n=i)},this),n>-1&&e.parents.splice(n,1)},emitChange:function(e){this.dispatch(f,e)},_getPropertyNames:function(){var e=p.isArray(this.target)?this.target.map(function(e,t){return t}):(0,s.default)(this.target);return e.filter(function(e){return e!==h})},_wrapArray:function(e){p.defineFreezeProp(e,"push",function(){var t=[].slice.call(arguments);t.forEach(function(t){this[h].set(e.length,t)},this),this[h].emitChange({path:"length",value:this.length})}),p.defineFreezeProp(e,"pop",function(){var e=[].pop.apply(this,arguments);return this[h].emitChange({path:this.length,value:e}),this[h].emitChange({path:"length",value:this.length}),e}),p.defineFreezeProp(e,"unshift",function(){var e=[].slice.call(arguments);e.forEach(function(e){this[h].set(0,e)},this),this[h].emitChange({path:"length",value:this.length})}),p.defineFreezeProp(e,"shift",function(){var e=[].shift.apply(this,arguments);return this[h].emitChange({path:0,value:e}),this[h].emitChange({path:"length",value:this.length}),e}),p.defineFreezeProp(e,"splice",function(){for(var e=arguments[0],t=p.isNull(arguments[1])?e+arguments[1]:this.length-1,n=[].splice.apply(this,arguments),i=e;i<=t;i++)this[h].emitChange({path:i,value:n[i-e]});return this[h].emitChange({path:"length",value:this.length}),n}),p.defineFreezeProp(e,"set",function(e,t){e>=this.length&&this[h].emitChange({path:"length",value:this.length}),this[h].set(e,t)})}});b.observe=function(e){return new b(e)},b.isIgnore=function(e){return g.some(function(t){return t.test(e)})},e.exports=b},function(e,t,n){e.exports={default:n(8),__esModule:!0}},function(e,t,n){n(9),e.exports=n(29).Object.keys},function(e,t,n){var i=n(10),r=n(12);n(27)("keys",function(){return function(e){return r(i(e))}})},function(e,t,n){var i=n(11);e.exports=function(e){return Object(i(e))}},function(e,t){e.exports=function(e){if(void 0==e)throw TypeError("Can't call method on "+e);return e}},function(e,t,n){var i=n(13),r=n(26);e.exports=Object.keys||function(e){return i(e,r)}},function(e,t,n){var i=n(14),r=n(15),s=n(18)(!1),o=n(22)("IE_PROTO");e.exports=function(e,t){var n,a=r(e),l=0,c=[];for(n in a)n!=o&&i(a,n)&&c.push(n);for(;t.length>l;)i(a,n=t[l++])&&(~s(c,n)||c.push(n));return c}},function(e,t){var n={}.hasOwnProperty;e.exports=function(e,t){return n.call(e,t)}},function(e,t,n){var i=n(16),r=n(11);e.exports=function(e){return i(r(e))}},function(e,t,n){var i=n(17);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(e){return"String"==i(e)?e.split(""):Object(e)}},function(e,t){var n={}.toString;e.exports=function(e){return n.call(e).slice(8,-1)}},function(e,t,n){var i=n(15),r=n(19),s=n(21);e.exports=function(e){return function(t,n,o){var a,l=i(t),c=r(l.length),u=s(o,c);if(e&&n!=n){for(;c>u;)if(a=l[u++],a!=a)return!0}else for(;c>u;u++)if((e||u in l)&&l[u]===n)return e||u||0;return!e&&-1}}},function(e,t,n){var i=n(20),r=Math.min;e.exports=function(e){return e>0?r(i(e),9007199254740991):0}},function(e,t){var n=Math.ceil,i=Math.floor;e.exports=function(e){return isNaN(e=+e)?0:(e>0?i:n)(e)}},function(e,t,n){var i=n(20),r=Math.max,s=Math.min;e.exports=function(e,t){return e=i(e),e<0?r(e+t,0):s(e,t)}},function(e,t,n){var i=n(23)("keys"),r=n(25);e.exports=function(e){return i[e]||(i[e]=r(e))}},function(e,t,n){var i=n(24),r="__core-js_shared__",s=i[r]||(i[r]={});e.exports=function(e){return s[e]||(s[e]={})}},function(e,t){var n=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(e,t){var n=0,i=Math.random();e.exports=function(e){return"Symbol(".concat(void 0===e?"":e,")_",(++n+i).toString(36))}},function(e,t){e.exports="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(",")},function(e,t,n){var i=n(28),r=n(29),s=n(38);e.exports=function(e,t){var n=(r.Object||{})[e]||Object[e],o={};o[e]=t(n),i(i.S+i.F*s(function(){n(1)}),"Object",o)}},function(e,t,n){var i=n(24),r=n(29),s=n(30),o=n(32),a="prototype",l=function(e,t,n){var c,u,p,d=e&l.F,h=e&l.G,f=e&l.S,m=e&l.P,g=e&l.B,b=e&l.W,v=h?r:r[t]||(r[t]={}),_=v[a],y=h?i:f?i[t]:(i[t]||{})[a];h&&(n=t);for(c in n)u=!d&&y&&void 0!==y[c],u&&c in v||(p=u?y[c]:n[c],v[c]=h&&"function"!=typeof y[c]?n[c]:g&&u?s(p,i):b&&y[c]==p?function(e){var t=function(t,n,i){if(this instanceof e){switch(arguments.length){case 0:return new e;case 1:return new e(t);case 2:return new e(t,n)}return new e(t,n,i)}return e.apply(this,arguments)};return t[a]=e[a],t}(p):m&&"function"==typeof p?s(Function.call,p):p,m&&((v.virtual||(v.virtual={}))[c]=p,e&l.R&&_&&!_[c]&&o(_,c,p)))};l.F=1,l.G=2,l.S=4,l.P=8,l.B=16,l.W=32,l.U=64,l.R=128,e.exports=l},function(e,t){var n=e.exports={version:"2.5.1"};"number"==typeof __e&&(__e=n)},function(e,t,n){var i=n(31);e.exports=function(e,t,n){if(i(e),void 0===t)return e;switch(n){case 1:return function(n){return e.call(t,n)};case 2:return function(n,i){return e.call(t,n,i)};case 3:return function(n,i,r){return e.call(t,n,i,r)}}return function(){return e.apply(t,arguments)}}},function(e,t){e.exports=function(e){if("function"!=typeof e)throw TypeError(e+" is not a function!");return e}},function(e,t,n){var i=n(33),r=n(41);e.exports=n(37)?function(e,t,n){return i.f(e,t,r(1,n))}:function(e,t,n){return e[t]=n,e}},function(e,t,n){var i=n(34),r=n(36),s=n(40),o=Object.defineProperty;t.f=n(37)?Object.defineProperty:function(e,t,n){if(i(e),t=s(t,!0),i(n),r)try{return o(e,t,n)}catch(e){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(e[t]=n.value),e}},function(e,t,n){var i=n(35);e.exports=function(e){if(!i(e))throw TypeError(e+" is not an object!");return e}},function(e,t){e.exports=function(e){return"object"==typeof e?null!==e:"function"==typeof e}},function(e,t,n){e.exports=!n(37)&&!n(38)(function(){return 7!=Object.defineProperty(n(39)("div"),"a",{get:function(){return 7}}).a})},function(e,t,n){e.exports=!n(38)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(e,t){e.exports=function(e){try{return!!e()}catch(e){return!0}}},function(e,t,n){var i=n(35),r=n(24).document,s=i(r)&&i(r.createElement);e.exports=function(e){return s?r.createElement(e):{}}},function(e,t,n){var i=n(35);e.exports=function(e,t){if(!i(e))return e;var n,r;if(t&&"function"==typeof(n=e.toString)&&!i(r=n.call(e)))return r;if("function"==typeof(n=e.valueOf)&&!i(r=n.call(e)))return r;if(!t&&"function"==typeof(n=e.toString)&&!i(r=n.call(e)))return r;throw TypeError("Can't convert object to primitive value")}},function(e,t){e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},function(e,t,n){e.exports={default:n(43),__esModule:!0}},function(e,t,n){n(44);var i=n(29).Object;e.exports=function(e,t){return i.getOwnPropertyDescriptor(e,t)}},function(e,t,n){var i=n(15),r=n(45).f;n(27)("getOwnPropertyDescriptor",function(){return function(e,t){return r(i(e),t)}})},function(e,t,n){var i=n(46),r=n(41),s=n(15),o=n(40),a=n(14),l=n(36),c=Object.getOwnPropertyDescriptor;t.f=n(37)?c:function(e,t){if(e=s(e),t=o(t,!0),l)try{return c(e,t)}catch(e){}if(a(e,t))return r(!i.f.call(e,t),e[t])}},function(e,t){t.f={}.propertyIsEnumerable},function(e,t,n){e.exports={default:n(48),__esModule:!0}},function(e,t,n){n(49);var i=n(29).Object;e.exports=function(e,t,n){return i.defineProperty(e,t,n)}},function(e,t,n){var i=n(28);i(i.S+i.F*!n(37),"Object",{defineProperty:n(33).f})},function(e,t,n){"use strict";var i=n(3),r=n(4),s=new r({$extends:Function,constructor:function(e){e=e||this;var t=e._emitter_;return t?t:(i.defineFreezeProp(this,"_target_",e),i.defineFreezeProp(e,"_emitter_",this),this._isNative_=this._isNativeObject(this._target_),this._listeners_=this._listeners_||{},this.on=this.$on=this.$addListener=this.addListener,this.off=this.$off=this.$removeListener=this.removeListener,void(this.$emit=this.emit))},_isNativeObject:function(e){return e.addEventListener&&e.removeEventListener&&e.dispatchEvent},addListener:function(e,t,n){if(this._isNative_&&this._addNativeEventListener(e,t,n),this._listeners_[e]=this._listeners_[e]||[],this._listeners_[e].push(t),this._listeners_[e].length>s._maxListeners)throw new Error("The `"+e+"` event listener is not more than 10")},removeListener:function(e,t,n){if(e&&t){if(this._isNative_&&this._removeNativeEventListener(e,t,n),!this._listeners_[e])return;var r=this._listeners_[e].indexOf(t);this._listeners_[e].splice(r,1)}else e?(this._isNative_&&this._listeners_[e]&&this._listeners_[e].forEach(function(t){this.removeListener(e,t,n)},this),delete this._listeners_[e]):(i.each(this._listeners_,function(e){this.removeListener(e,null,n)},this),this._listeners_={})},emit:function(e,t,n,i){if(this._isNative_)return this._emitNativeEvent(e,t,n,i);if(this._listeners_[e]){var r=!1;return this._listeners_[e].forEach(function(e){var n=e.call(this._target_,t);n===!1&&(r=!0)},this),r}},_addNativeEventListener:function(e,t,n){this._target_.addEventListener(e,t,n);var i=s._events[e];i&&(i.addListener=i.addListener||i.on,i.addListener(this,e,t,n))},_removeNativeEventListener:function(e,t,n){this._target_.removeEventListener(e,t,n);var i=s._events[e];i&&(i.removeListener=i.removeListener||i.off,i.removeListener(this,e,t,n))},_emitNativeEvent:function(e,t,n,r){var s=document.createEvent("HTMLEvents");return s.initEvent(e,n,r),i.copy(t,s,["data"]),s.data=t,this._target_.dispatchEvent(s)}});s._maxListeners=10,s._events=[],s.register=function(e){var t=e.name;t&&(i.isArray(t)||(t=t.split(",")),t.forEach(function(t){this._events[t]=e},this))},e.exports=s},function(e,t,n){"use strict";var i=n(52),r=n(53),s=n(54),o=n(78),a=n(55);o.Template=o,o.Compiler=i,o.Directive=r,o.directives=a,o.Expression=s,e.exports=o},function(e,t,n){"use strict";var i=n(4),r=n(53),s=n(3),o=n(54),a=n(55),l="m",c=new i({constructor:function(e){e=e||{},this.prefix=e.prefix||l,this.elementDirectives={},this.attributeDirectives={},this.registerDirectives(a),this.registerDirectives(e.directives)},toCamelCase:function(e,t){return e&&(e=e.replace(/\-[a-z0-9]/g,function(e){return e.slice(1).toUpperCase()}),e=e.replace(/^[a-z]/i,function(e){return t?e.toUpperCase():e.toLowerCase()})),e},toSplitCase:function(e){return e&&(e=e.replace(/([A-Z])/g,"-$1"),"-"==e[0]&&(e=e.slice(1))),e},registerDirectives:function(e){s.each(e,function(e,t){e=this.toSplitCase(e);var n=t.options.prefix===!1?e:this.prefix+":"+e;t.options.type==r.TE?this.elementDirectives[n.toUpperCase()]=t:this.attributeDirectives[n.toLowerCase()]=t},this)},_parseAttrInfo:function(e){var t=this,n=e.toLowerCase().split(":"),i={};return n.length>1?(i.name=n[0]+":"+n[1],i.decorates=n.slice(2).map(function(e){return t.toCamelCase(e)})):(i.name=n[0],i.decorates=[]),i},_createDirectiveInstance:function(e,t){return t.compiler=this,t.prefix=this.prefix,new e(t)},_bindHandler:function(e){e.directives=e.directives.sort(function(e,t){return t.level-e.level});var t=[];s.each(e.directives,function(n,i){if(i.index=n,i.bind(),t.push(i),i.remove!==!1&&i.attribute&&i.node.removeAttribute(i.attribute.name),i.final)return e.final=!0},this),e.directives=t},_compileElement:function(e,t){var n=this.elementDirectives[t.nodeName.toUpperCase()];n&&e.directives.push(this._createDirectiveInstance(n,{handler:e,node:t}))},_compileAttributes:function(e,t){s.toArray(t.attributes).forEach(function(n){var i=this._parseAttrInfo(n.name),r=this.attributeDirectives[i.name]||this.attributeDirectives["*"];if(r){var s=r.options;e.directives.push(this._createDirectiveInstance(r,{handler:e,node:t,attribute:n,expression:s.literal?n.value:new o(n.value,s.mixed),decorates:i.decorates}))}},this)},_compileChildren:function(e,t){e.final||s.toArray(t.childNodes).forEach(function(t){if(!t._compiled_){var n=this.compile(t);n.parent=this,e.children.push(n)}},this)},compile:function(e,t){if(!e)throw new Error("Invalid node for compile");e._compiled_=!0,t=t||{};var n=function e(t){s.isNull(t)&&(t={}),e.directives.forEach(function(e){e.scope=t,e.execute(t)},this),e.children.forEach(function(e){e(t)},this)};return n.dispose=function(){n.directives.forEach(function(e){e.unbind()},this),n.children.forEach(function(e){e.dispose()},this)},n.node=e,n.directives=[],n.children=[],t.element!==!1&&this._compileElement(n,e),t.attribute!==!1&&this._compileAttributes(n,e),this._bindHandler(n),t.children!==!1&&this._compileChildren(n,e),n}});e.exports=c},function(e,t,n){"use strict";function i(e){e=e||{},e.type=e.type||i.TA,e.level=e.level||i.LG;var t=new r({$extends:e,constructor:function(e){s.copy(e,this)},options:e,bind:e.bind||s.noop,execute:e.execute||function(e){if(this.scope=e,this.options.type===i.TE)return this.update();var t=this.options.literal?this.attribute.value:this.expression.execute(e);s.deepEqual(this._value_,t)||(this.update(t,this._value_),this._value_=t)},update:e.update||s.noop,unbind:e.unbind||s.noop,utils:s,Expression:o});return t.options=e,s.setPrototypeOf(t,e),t}var r=n(4),s=n(3),o=n(54);i.TA="A",i.TE="E",i.LP=3e3,i.LS=2e3,i.LE=1e3,i.LG=0,i.LA=-1e3,i.LC=-2e3,e.exports=i},function(e,t,n){"use strict";var i=n(4),r=n(3),s=new i({constructor:function(e,t){this.func=t?this._compileMixedCode(e):this._compileCode(e)},_compileCode:function(e){return e=this._escapeEOL(this._wrapCode(e)),this._createFunction(e)},_compileMixedCode:function(e){var t=this._parseMixedCode(e);return e=this._escapeEOL(t.join("+")),this._createFunction(e)},_createFunction:function(e){var t=new Function("utils","scope","with(scope){return "+e+"}");return t.bind(null,r)},_parseMixedCode:function(e){for(var t=0,n=e.length,i="",s=!1,o=[];t<=n;){var a=e[t++],l=e[t];r.isNull(a)?(i.length>0&&o.push('"'+this._escapeCode(i)+'"'),i="",s=!1):s||a+l!="{{"?s&&a+l=="}}"?(i.length>0&&o.push(this._wrapCode(i)),i="",s=!1,t++):i+=a:(i.length>0&&o.push('"'+this._escapeCode(i)+'"'),i="",s=!0,t++)}return o},_escapeCode:function(e){return e.replace(/"/,'\\"').replace("\r\n","\\r\\n").replace("\n","\\n")},_escapeEOL:function(e){return e.replace(/\n/gm,"\\\n")},_wrapCode:function(e){return"((function(){try{return ("+e+")}catch(err){console.error(err);return err;}})())"},execute:function(e){return r.isNull(e)&&(e={}),this.func.call(e,e)}});e.exports=s},function(e,t,n){"use strict";e.exports={"#text":n(56),each:n(57),if:n(59),prop:n(60),attr:n(61),on:n(62),html:n(63),text:n(64),prevent:n(65),id:n(66),cloak:n(67),show:n(68),model:n(69),focus:n(76),"*":n(77)}},function(e,t,n){"use strict";var i=n(53),r=n(54);e.exports=new i({type:i.TE,prefix:!1,bind:function(){this.expr=new r(this.node.nodeValue,!0),this.node.nodeValue=""},execute:function(e){this.scope=e;var t=this.expr.execute(e);this.node.nodeValue!==t&&(this.node.nodeValue=t)}})},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}var r=n(47),s=i(r),o=n(53),a=n(3),l=n(58);e.exports=new o({level:o.LS+1,final:!0,literal:!0,bind:function(){this.mountNode=document.createTextNode(""),this.node.parentNode.insertBefore(this.mountNode,this.node),this.node.removeAttribute(this.attribute.name),this.node.parentNode.removeChild(this.node),this.parseExpr(),this.eachItems={}},parseExpr:function(){this.eachType=this.attribute.value.indexOf(" in ")>-1?"in":"of";var e=this.attribute.value.split(" "+this.eachType+" "),t="with(scope){utils.each("+e[1]+",fn.bind(this,"+e[1]+"))}";this.each=new Function("utils","scope","fn",t).bind(null,this.utils);var n=e[0].split(",").map(function(e){return e.trim()});"in"==this.eachType?(this.keyName=n[0],this.valueName=n[1]):(this.keyName=n[1],this.valueName=n[0])},execute:function(e){var t=this,n=[],i=document.createDocumentFragment(),r=this;this.each(e,function(e,t){var o=new l(this.scope);r.keyName&&(0,s.default)(o,r.keyName,{get:function(){return t}}),r.valueName&&(0,s.default)(o,r.valueName,{get:function(){return e[t]},set:function(n){e[t]=n}});var a=this.eachItems[t];if(a)a.handler(o);else{var c={};c.node=this.node.cloneNode(!0),i.appendChild(c.node),c.handler=this.compiler.compile(c.node),c.handler(o),this.eachItems[t]=c}n.push(t)}.bind(this)),a.each(this.eachItems,function(e,i){n.some(function(t){return t==e})||(i.node.parentNode&&i.node.parentNode.removeChild(i.node),delete t.eachItems[e])},this),i.childNodes.length>0&&this.mountNode.parentNode.insertBefore(i,this.mountNode)}})},function(e,t,n){"use strict";var i=n(3),r=function(e,t){var n=i.create(e);return i.copy(t,n),i.each(e,function(t,r){i.isFunction(r)&&(n[t]=r.bind(e))}),n};e.exports=r},function(e,t,n){"use strict";var i=n(53);e.exports=new i({level:i.LS,final:!0,bind:function(){this.mountNode=document.createTextNode(""),this.node.parentNode.insertBefore(this.mountNode,this.node),this.node.removeAttribute(this.attribute.name),this.node.parentNode.removeChild(this.node)},execute:function(e){var t=this.expression.execute(e);if(t){this._handler=this._handler||this.compiler.compile(this.node),this._handler(e);var n=this.node.$substitute||this.node;n.parentNode||this.mountNode.parentNode.insertBefore(n,this.mountNode)}else{var i=this.node.$substitute||this.node;i.parentNode&&i.parentNode.removeChild(i)}}})},function(e,t,n){"use strict";var i=n(53);e.exports=new i({update:function(e){var t=this.node.$target||this.node;t[this.decorates[0]]=e}})},function(e,t,n){"use strict";var i=n(53);e.exports=new i({update:function(e){var t=this.node.$target||this.node;t.setAttribute?t.setAttribute(this.decorates[0],e):t[this.decorates[0]]=e}})},function(e,t,n){"use strict";var i=n(53),r=n(50),s=n(58);e.exports=new i({literal:!0,bind:function(){var e=this.attribute.value||"";e.indexOf("(")<0&&e.indexOf(")")<0&&(e+="($event)"),this.expr=new this.Expression(e);var t=this.node.$target||this.node;this.emiter=new r(t),this.emiter.addListener(this.decorates[0],function(e){this.utils.isNull(this.scope)||this.expr.execute(new s(this.scope,{$event:e}))}.bind(this),!1)},unbind:function(){this.emiter.removeListener()},execute:function(e){this.scope=e}})},function(e,t,n){"use strict";var i=n(53);e.exports=new i({update:function(e){this.node.innerHTML=e}})},function(e,t,n){"use strict";var i=n(53);e.exports=new i({update:function(e){this.node.innerText=e}})},function(e,t,n){"use strict";var i=n(53);e.exports=new i({level:i.LP,final:!0})},function(e,t,n){"use strict";var i=n(53);e.exports=new i({literal:!0,update:function(e){if(e in this.scope)throw new Error("Conflicting component id `"+e+"`");this.scope[e]=this.node.$target||this.node; -}})},function(e,t,n){"use strict";var i=n(53);e.exports=new i({level:i.LC,literal:!0,prefix:!1,bind:function(){this.node.removeAttribute(this.attribute.name)}})},function(e,t,n){"use strict";var i=n(53);e.exports=new i({update:function(e){this.node.style.display=e?"":"none"}})},function(e,t,n){"use strict";var i=n(70),r=n(71),s=n(72),o=n(73),a=n(74),l=n(75),c=function(e){var t=e.node,n=t.tagName;if(e.decorates[0])return new l(e);if("INPUT"==n){var c=t.getAttribute("type");return"radio"==c?new o(e):"checkbox"==c?new a(e):new s(e)}if("TEXTAREA"==n)return new s(e);if("SELECT"==n)return new i(e);if(t.isContentEditable)return new r(e);throw new Error("Directive `model` cannot be used on `"+n+"`")};c.options={level:c.LA},e.exports=c},function(e,t,n){"use strict";var i=n(53),r=n(50),s=n(58);e.exports=new i({final:!0,bind:function(){this.backExpr=new this.Expression(this.attribute.value+"=_value_"),this.node.removeAttribute(this.attribute.name),this._handler=this.compiler.compile(this.node),this.emiter=new r(this.node),this.emiter.addListener("change",function(){if(!this.utils.isNull(this.scope)){var e=this.node.selectedOptions,t=this.node.multiple?[].slice.call(e).map(function(e){return e.value},this):e[0].value;this.backExpr.execute(new s(this.scope,{_value_:t}))}}.bind(this),!1)},unbind:function(){this.emiter.removeListener()},execute:function(e){this.scope=e,this._handler(e);var t=this.expression.execute(e);this.utils.isArray(t)||(t=[t]),[].slice.call(this.node.options).forEach(function(e){e.selected=t.indexOf(e.value)>-1},this)}})},function(e,t,n){"use strict";var i=n(53),r=n(50),s=n(58);e.exports=new i({bind:function(){this.backExpr=new this.Expression(this.attribute.value+"=_value_"),this.emiter=new r(this.node),this.emiter.addListener("input",function(){this.utils.isNull(this.scope)||this.backExpr.execute(new s(this.scope,{_value_:this.node.innerHTML}))}.bind(this),!1)},unbind:function(){this.emiter.removeListener()},execute:function(e){var t=this.expression.execute(e);this.node.innerHTML!==t&&(this.node.innerHTML=t)}})},function(e,t,n){"use strict";var i=n(53),r=n(50),s=n(58);e.exports=new i({bind:function(){this.backExpr=new this.Expression(this.attribute.value+"=_value_"),this.emiter=new r(this.node),this.emiter.addListener("input",function(){this.utils.isNull(this.scope)||this.backExpr.execute(new s(this.scope,{_value_:this.node.value}))}.bind(this),!1)},unbind:function(){this.emiter.removeListener()},execute:function(e){var t=this.expression.execute(e);this.node.value!==t&&(this.node.value=t)}})},function(e,t,n){"use strict";var i=n(53),r=n(50),s=n(58);e.exports=new i({bind:function(){this.backExpr=new this.Expression(this.attribute.value+"=_value_"),this.emiter=new r(this.node),this.emiter.addListener("change",function(){this.utils.isNull(this.scope)||this.backExpr.execute(new s(this.scope,{_value_:this.node.value}))}.bind(this),!1)},unbind:function(){this.emiter.removeListener()},execute:function(e){this.scope=e;var t=this.expression.execute(e);this.node.checked=t==this.node.value}})},function(e,t,n){"use strict";var i=n(53),r=n(50),s=n(58);e.exports=new i({bind:function(){this.backExpr=new this.Expression(this.attribute.value+"=_value_"),this.emiter=new r(this.node),this.emiter.addListener("change",function(){if(!this.utils.isNull(this.scope)){var e=this.expression.execute(this.scope);if(this.utils.isArray(e)&&this.node.checked)e.push(this.node.value);else if(this.utils.isArray(e)&&!this.node.checked){var t=e.indexOf(this.node.value);e.splice(t,1)}else this.backExpr.execute(new s(this.scope,{_value_:this.node.checked}))}}.bind(this),!1)},unbind:function(){this.emiter.removeListener()},execute:function(e){this.scope=e;var t=this.expression.execute(e);this.utils.isArray(t)?this.node.checked=t.indexOf(this.node.value)>-1:this.node.checked=t}})},function(e,t,n){"use strict";var i=n(53),r=n(58);e.exports=new i({bind:function(){var e=this;if(this.target=this.node.$target,this.backExpr=new this.Expression(this.attribute.value+"=_value_"),this.bindProp=this.decorates[0],!this.target)throw new Error("Directive `model:"+this.bindProp+"` cannot be used on `"+this.node.tagName+"`");this.watcher=this.target.$watch(this.bindProp,function(t){e.utils.isNull(e.scope)||e.backExpr.execute(new r(e.scope,{_value_:t}))})},unbind:function(){this.target.$unWatch(this.watcher)},update:function(e){this.target[this.bindProp]=e}})},function(e,t,n){"use strict";var i=n(53);e.exports=new i({execute:function(e){var t=this,n=this.expression.execute(e);setTimeout(function(){n?t.node.focus():t.node.blur()},0)}})},function(e,t,n){"use strict";var i=n(53);e.exports=new i({level:i.LA,prefix:!1,literal:!0,remove:!1,bind:function(){this.computedName=this.attribute.name,this.computedValue=this.attribute.value,this.nameExpr=new this.Expression(this.attribute.name,!0),this.valueExpr=new this.Expression(this.attribute.value,!0)},execute:function(e){var t=this.node.$target||this.node,n=this.nameExpr.execute(e);this.computedName!==n&&(t.removeAttribute&&t.removeAttribute(this.computedName),this.computedName=n,!this.utils.isNull(this.computedName)&&this.computedName.length>0&&t.setAttribute&&t.setAttribute(this.computedName,this.computedValue||""));var i=this.valueExpr.execute(e);this.computedValue!==i&&(this.computedValue=i,t.setAttribute?t.setAttribute(this.computedName,this.computedValue||""):t[this.computedName]=this.computedValue)}})},function(e,t,n){"use strict";var i=n(4),r=n(6),s=n(50),o=n(52),a=new i({$extends:s,constructor:function(e,t){t=t||{},s.call(this),this.options=t,this.element=e,this.compiler=t.compiler||new o(t),this.render=this.compiler.compile(this.element),this.update=this.update.bind(this),this._update=this._update.bind(this),this._updateTimer=0},update:function(){this._updateTimer&&(clearTimeout(this._updateTimer),this._updateTimer=null),this._updateTimer=setTimeout(this._update,0)},_update:function(){this._updateTimer&&this.observer&&(this.emit("update",this),this.render(this.observer.target),this._onBind())},_onBind:function(){this._bound||(this._bound=!0,this.emit("bind",this))},bind:function(e,t){e&&(this.unbind(),this.observer=new r(e,{root:this.options.root}),e.$self=e,this.observer.on("change",this.update),t?this._onBind():this.update())},unbind:function(){this.observer&&(this.observer.removeListener("change",this.update),this.observer.clearReference(),this.observer=null)},dispose:function(){this.unbind(),this.render.dispose()}});e.exports=a},function(e,t,n){"use strict";var i=n(80),r=n(82),s=n(51).directives;i.components=r,i.Component=i,i.component=function(e,t){return t?void(r[e]=t):r[e]},i.directive=function(e,t){return t?void(s[e]=t):s[e]},e.exports=i},function(e,t,n){"use strict";function i(e){return e&&e.__esModule?e:{default:e}}function r(e){e=e||{};var t=e.mixes;delete e.mixes,t=t&&!u.isArray(t)?[t]:[];var i=e.extend||r;delete e.extend,t.push(i),t.push(e);var s={};t.forEach(function(e){(e instanceof r||e==r)&&(e=e.$options||{}),u.mix(s,e)}),e=s;var f=new a({$extends:i,constructor:function(t){var i=this;return this==window?new this.$class(t):(p.call(this),t=t||{},u.each(t,function(e,t){e in i||(i[e]=t)}),this._onTemplateUpdate_=this._onTemplateUpdate_.bind(this),this._createdData_(e.data),this._createProperties_(e.properties||e.props),this._createWatches_(e.watches||e.watch),this.$directives=this.$directives||{},this._importDirectives_(e.directives),this.$components=this.$components||{},this._importComponents_(n(82)),this._importComponents_({self:f}),this._importComponents_(e.components),u.defineFreezeProp(this,"$children",[]),t.parent&&this.$setParent(t.parent),this.$callHook("init",[t]),d.observe(this),void(e.element?this.$mount():this.$compile()))},$setParent:function(e){this.$parent!==e&&(this.$parent&&this.$parent.$removeChild(this),e&&e.$addChild(this))},$addChild:function(e){e instanceof r&&(this.$children.push(e),u.defineFreezeProp(e,"$parent",this),u.defineFreezeProp(e,"$root",this.$root||this))},$removeChild:function(e){var t=this.$children.indexOf(e);this.$children.splice(t,1),u.defineFreezeProp(e,"$parent",null)},get $root(){return this.$parent?this.$parent.$root:this},_importComponents_:function(e){u.each(e,function(e,t){t&&(this.$components[e]=t,this.$directives[e]=new h({name:e,component:t,parent:this}))},this)},_importDirectives_:function(e){u.each(e,function(e,t){t&&(this.$directives[e]=t)},this)},$callHook:function(e,t){var n=this["on"+u.firstUpper(e)];u.isFunction(n)&&(n.apply(this,t||[]),this.$emit("$"+e,t))},_createdData_:function(e){u.isFunction(e)?this.$data=e.call(this):this.$data=e||{},u.each(this.$data,function(e){(0,o.default)(this,e,{configurable:!0,enumerable:!0,get:function(){if(this.$data)return this.$data[e]},set:function(t){this.$data&&(this.$data[e]=t)}})},this)},_createProperties_:function(e){this.$properties={},u.each(e,function(e,t){t=u.isFunction(t)?{get:t}:u.isObject(t)?u.copy(t):{value:t};var n=!!t.get||!!t.set;n||(t.get=function(){return t.value},t.set=function(e){t.value=e}),(0,o.default)(this,e,{configurable:!0,enumerable:!0,get:function(){if(!t.get)throw new Error("Property `"+e+"` cannot be read");return t.get.call(this)},set:function(n){if(!t.set)throw new Error("Property `"+e+"` cannot be written");if(t.test&&!t.test(n))throw new Error("Invalid value `"+n+"` for property `"+e+"`");t.set.call(this,n),this._observer_&&this._observer_.emitChange({path:e,value:n})}}),this.$properties[e]=t},this)},_createWatches_:function(e){this._watchers_=this._watchers_||[],u.each(e,function(e,t){this.$watch(e,t)},this)},_onTemplateUpdate_:function(){this._watchers_.forEach(function(e){e.calc()},this)},$watch:function(e,t){if(u.isFunction(t)){var n=e;u.isFunction(e)||(n=function(){return u.getByPath(this,e)});var i=new c(n.bind(this),t.bind(this));return this._watchers_.push(i),i}},$unWatch:function(e){var t=this._watchers_.findIndex(function(t){return t===e});this._watchers_.splice(t,1)},_createElement_:function(){if(!this._created_){if(this._created_=!0,this.$callHook("create"),u.defineFreezeProp(this,"$element",this.element||f.$template.cloneNode(!0)),!this.$element||"#text"===this.$element.nodeName)throw new Error("Invalid component template");this.$callHook("created")}},$compile:function(){this._compiled_||(this._compiled_=!0,this._createElement_(),u.defineFreezeProp(this,"_template_",new l(this.$element,{directives:this.$directives,root:!0})),this._template_.bind(this),this._template_.on("update",this._onTemplateUpdate_),this._template_.on("bind",function(){this.deferReady||this.$callHook("ready")}.bind(this)))},$mount:function(e,t){this._mounted_||(this.$compile(),this.$callHook("mount"),e&&(e.$substitute=this.$element,this.$element._mountNode=e,t?e.appendChild(this.$element):e.parentNode&&e.parentNode.insertBefore(this.$element,e)),this._mounted_=!0,this._removed_=!1,this.$callHook("mounted"))},$appendTo:function(e){this.$mount(e,!0)},$remove:function(){!this._removed_&&this._mounted_&&(this.$callHook("remove"),this.$element.parentNode&&this.$element.parentNode.removeChild(this.$element),this._removed_=!0,this._mounted_=!1,this.$callHook("removed"))},$dispatch:function(e,t){var n=this.$emit(e,t);!n&&this.$parent&&this.$parent.$dispatch(e,t)},$broadcast:function(e,t){var n=this.$emit(e,t);!n&&this.$children&&this.$children.length>0&&this.$children.forEach(function(n){n.$broadcast(e,t)},this)},$dispose:function(){if(this.$remove(),this._emitter_.off(),this.$children.forEach(function(e){e.$dispose()},this),this.$parent){var e=this.$parent.$children.indexOf(this);this.$parent.$children.splice(e,1)}this.$callHook("dispose"),this._compiled_&&this._template_.unbind(),this.$callHook("disposed");for(var t in this)delete this[t];["_observer_","$element","$children","$parent","_template_"].forEach(function(e){delete this[e]},this),u.setPrototypeOf(this,null)}});return f.$options=e,f.$template=u.parseDom(e.template),u.copy(e,f.prototype),u.copy(e.methods,f.prototype),u.setPrototypeOf(f,r.prototype),f}var s=n(47),o=i(s),a=n(4),l=n(51),c=n(5),u=n(3),p=n(50),d=n(6),h=n(81);r.prototype=u.create(p.prototype),r.extend=function(e){return new r(e)},r.prototype.extend=function(e){return e=e||{},e.extend=this,new r(e)},r.prototype.create=function(e){return new this(e)},r.prototype.start=function(e){if(!this.$options||!this.$options.element)throw new Error("Start method cannot be called");return this.create(e)},e.exports=r},function(e,t,n){"use strict";function i(e){return new s({type:s.TE,literal:!0,final:!0,level:s.LE,bind:function(){this.component=new e.component({deferReady:!0,parent:e.parent||this.scope}),this.handleAttrs(),this.node.$target=this.component,this.handler=this.compiler.compile(this.node,{element:!1,children:!1}),this.handleContents(),this.component.$mount(this.node),this.node.parentNode&&this.node.parentNode.removeChild(this.node)},handleAttrs:function(){this.attrs=[].slice.call(this.node.attributes);var e=new RegExp("^"+this.prefix+":","i");this.attrs.forEach(function(t){e.test(t.name)||t.name in this.component.$properties||(this.component.$element.setAttribute(t.name,t.value),this.node.removeAttribute(t.name))},this)},handleContents:function(){this.placeHandlers=[];var e=[].slice.call(this.component.$element.querySelectorAll("["+this.prefix+"\\:content]"));e.forEach(function(e){var t=null,n=e.getAttribute(this.prefix+":content");if(t=n?[].slice.call(this.node.querySelectorAll(n)):[].slice.call(this.node.childNodes),t&&!(t.length<1)){e.innerHTML="",t.forEach(function(t){e.appendChild(t.cloneNode(!0))},this);var i=this.compiler.compile(e);this.placeHandlers.push(i)}},this)},execute:function(e){this.handler(e),this._ready_||(this._ready_=!0,this.component.$callHook("ready")),this.placeHandlers.forEach(function(t){t(e)},this)}})}var r=n(51),s=r.Directive;e.exports=i},function(e,t,n){"use strict";e.exports={View:n(83)}},function(e,t,n){"use strict";var i=n(80),r=n(3),s=new i({template:"
",properties:{component:{test:function(e){return!!e&&(e instanceof i||r.isString(e))},set:function(e){if(!this._transitioning){if(this._transitioning=!0,r.isString(e))return void(this.$parent&&this.$parent.$components?this.component=this.$parent.$components[e]:this.component=null);var t=null,n=this.componentInstance;r.isFunction(e)?t=new e({parent:this}):(e.$setParent(this),t=e),this.transition.prep(t,n),t.$appendTo(this.$element),this.transition.go(t,n,function(){this.$emit("enter",t),this.$emit("leave",n),n&&n.$dispose(),this._transitioning=!1}.bind(this)),this.componentInstance=t}},get:function(){return this._Component}},transition:{get:function(){return this._transition||s.transition},set:function(e){if(!this._transitioning){if(!(!e||r.isFunction(e.prep)&&r.isFunction(e.go)))throw new Error("Invalid transition");this._transition&&r.isFunction(this._transition.clean)&&this._transition.clean(this),e&&r.isFunction(e.init)&&e.init(this),this._transition=e}}}},switchTo:function(e,t){t&&(this.transition=t),this.component=e}});s.transition={prep:function(e,t){t&&(t.$element.style.display="none")},go:function(e,t,n){n()}},e.exports=s},function(e,t,n){"use strict";var i=n(1),r=n(85);n(86);var s=new i.Component({template:n(88),props:{mditor:null},data:function(){return{items:r.slice(0)}},onReady:function(){this.bindCommands()},watch:{items:function(){this.bindCommands()}},bindCommands:function(){var e=this;this.mditor&&this.items.forEach(function(t){e.mditor.removeCommand(t.name),e.mditor.addCommand(t)})},isActive:function(e){return this.mditor&&e.state&&this.mditor[e.state]},exec:function(e,t){t.preventDefault(),this.mditor.execCommand(e,t)},getItem:function(e){return this.items.find(function(t){return t.name===e})},removeItem:function(e){var t=this.items.findIndex(function(t){return t.name===e});return this.items.splice(t,1)},addItem:function(e){this.items.push(e)},replaceItem:function(e,t){var n=this.items.findIndex(function(t){return t.name===e}),i=this.items.splice(n,1);return this.items.splice(n,0,t),i}});e.exports=s},function(e,t){"use strict";e.exports=[{name:"bold",title:"粗体",key:"shift+alt+b",handler:function(){this.editor.wrapSelectText("**","**")}},{name:"italic",title:"斜体",key:"shift+alt+i",handler:function(){this.editor.wrapSelectText("*","*")}},{name:"underline",title:"下划线",key:"shift+alt+e",handler:function(){this.editor.wrapSelectText("","")}},{name:"strikethrough",title:"删除线",key:"shift+alt+d",handler:function(){this.editor.wrapSelectText("~~","~~")}},{name:"header",title:"标题",key:"shift+alt+1",handler:function(){this.editor.wrapSelectText("# ")}},{name:"quote",icon:"quote-left",title:"引用",key:"shift+alt+q",handler:function(){var e=this.editor.getSelectText();if(e.length<1)return void this.editor.wrapSelectText("> ");var t=e.split(this.EOL),n=[];t.forEach(function(e){n.push("> "+e+" ")}),this.editor.setSelectText(n.join(this.EOL)+this.EOL)}},{name:"code",title:"代码",key:"shift+alt+c",handler:function(){var e="js"+this.EOL,t="```"+e,n="``` "+this.EOL,i=this.editor.getSelectText().trim();i.length>0&&(i+=this.EOL),this.editor.setSelectText(i),this.editor.wrapSelectText(t,n);var r=this.editor.getSelectRange(),s=r.start-e.length,o=r.start-this.EOL.length;this.editor.setSelectRange(s,o)}},{name:"list-ol",title:"有序列表",key:"shift+alt+o",handler:function(){var e=this.editor.getSelectText();if(e.length<1)return void this.editor.wrapSelectText("1. ");for(var t=e.split(this.EOL),n=[],i=0;i\n \n'},function(e,t,n){"use strict";var i=n(1),r=i.EventEmitter,s=n(3),o=n(90),a=n(91);n(92);var l=window.navigator.userAgent.toLowerCase(),c=!!l.match(/msie|trident\/7|edge/);e.exports=new i.Component({template:n(93),props:{mditor:null,value:null,markExp:null},onReady:function(){var e=this;this.stack=new o,setTimeout(function(){e.textareaEmitter=new r(e.textarea),e.stack.init({value:e.getValue()})},300),this._bindCommands()},_bindCommands:function(){var e=this;a.forEach(function(t){e.mditor.removeCommand(t.name),e.mditor.addCommand(t)})},onCompositionStart:function(){this._compositionLock=!0},onCompositionEnd:function(){var e=this;this._compositionLock=!1,setTimeout(function(){return e.onInput()},300)},onInput:function(){var e=this;this.$emit("input"),this._changedTimer&&(clearTimeout(this._changedTimer),this._changedTimer=null),this._compositionLock||(this._changedTimer=setTimeout(function(){e._changedTimer&&(e.stack.push({value:e.getValue(),range:e.getSelectRange()}),e.$emit("changed"))},300))},undo:function(){var e=this,t=this.stack.last(),n=this.stack.undo();if(!s.isNull(n)&&!s.isNull(n.value)){var i=t.value.length-n.value.length;this.value=n.value,t.range&&setTimeout(function(){var n=t.range.start-i,r=t.range.end-i;e.setSelectRange(n,r)})}},redo:function(){var e=this,t=this.stack.redo();s.isNull(t)||s.isNull(t.value)||(this.value=t.value,t.range&&setTimeout(function(){e.setSelectRange(t.range.start,t.range.end)}))},onPaste:function(e){this.$emit("paste",e)},onDragover:function(e){e.preventDefault(),this.$emit("dragover",e)},onDrop:function(e){e.preventDefault(),this.$emit("drop",e)},focus:function(){this.textarea.focus()},blur:function(){this.textarea.blur()},onScroll:function(e){this.syncScroll(),this.$emit("scroll",e)},syncScroll:function(e){var t=this;this.marks.scrollTop=this.textarea.scrollTop,this.marks.scrollLeft=this.textarea.scrollLeft,e||setTimeout(function(){t.syncScroll(!0)},0)},applyMarks:function(e){if(e&&this.markExp)return e=e.replace(/\n$/g,"\n\n").replace(this.markExp,"$&"),c&&(e=e.replace(/ /g," ")),e},activeMark:function e(t){var n=[].slice.call(this.marks.querySelectorAll("mark"));if(!(n.length<1)){this.activeMarkIndex=s.isNull(this.activeMarkIndex)?-1:this.activeMarkIndex,s.isNull(t)?this.activeMarkIndex++:this.activeMarkIndex=t,this.activeMarkIndex>=n.length&&(this.activeMarkIndex=0),n.forEach(function(e){e.classList.remove("active")});var e=n[this.activeMarkIndex];e.classList.add("active"),this.scrollToMark(e)}},scrollToMark:function(e){this.textarea.scrollTop=e.offsetTop-20},getValue:function(){return this.textarea.value},setValue:function(e){this.textarea.value=e},getActiveElement:function(){return this.textarea.focus(),document.activeElement},getSelectRange:function(){var e=this.getActiveElement();return{start:e.selectionStart,end:e.selectionEnd}},setSelectRange:function(e,t){var n=this.getActiveElement();n.setSelectionRange(e,t)},getSelectText:function(){var e=this.getActiveElement(),t=this.getSelectRange();return e.value.substring(t.start,t.end)},setSelectText:function(e){var t=this,n=this.getActiveElement(),i=this.getSelectRange();n.setRangeText(e),i.end==i.start&&this.setSelectRange(i.start,i.end+e.length),this.value=this.getValue(),this.onInput(),setTimeout(function(){t.blur(),t.focus()},0)},wrapSelectText:function(e,t){e=null!==e&&void 0!==e?e:"",t=null!==t&&void 0!==t?t:"";var n=this.getSelectRange(),i=this.getSelectText();this.setSelectText(e+i+t);var r=n.start+e.length,s=n.end+e.length;this.setSelectRange(r,s)},insertBeforeText:function(e){this.wrapSelectText(e)},insertAfterText:function(e){this.wrapSelectText("",e)},getBeforeText:function(e){var t=this.getSelectRange(),n=t.start,i=n-e,r=this.getValue();return r.substring(i,n)},getBeforeFirstCharIndex:function(e){var t=this.getSelectRange(),n=t.start,i=0,r=this.getValue();return r.substring(i,n).lastIndexOf(e)},getBeforeWord:function(){var e=this,t=[" ","\t",this.mditor.EOL],n=0;t.forEach(function(t){var i=e.getBeforeFirstCharIndex(t);i+t.length>n&&(n=i+t.length)});var i=this.getSelectRange(),r=this.getValue();return r.substring(n,i.end)},getBeforeTextInLine:function(){var e=this.getBeforeFirstCharIndex(this.mditor.EOL)+this.mditor.EOL.length,t=this.getSelectRange(),n=this.getValue();return n.substring(e,t.end)},selectBeforeText:function(e){var t=this.getSelectRange();this.setSelectRange(t.start-e,t.end)},selectAfterText:function(e){var t=this.getSelectRange();this.setSelectRange(t.start,t.end+e)},selectBeforeTextInLine:function(){var e=this.getBeforeFirstCharIndex(this.mditor.EOL)+this.mditor.EOL.length,t=this.getSelectRange();this.setSelectRange(e,t.end)},addIndent:function(){var e=this,t=this.getSelectText();if(t.length<1)return void this.insertBeforeText(this.mditor.INDENT);var n=t.split(this.mditor.EOL),i=[],r=n.length-1;n.forEach(function(t,n){t=""!==t.trim()?e.mditor.INDENT+t:t,(n0&&(event.clearSelected=!0,this.removeIndent()));var i=n.split(this.mditor.EOL),r=[];if(i.forEach(function(n){t.test(n)&&(n=n.replace(e.mditor.INDENT,"")),r.push(n)}),this.setSelectText(r.join(this.mditor.EOL)),event.clearSelected){var s=this.getSelectRange();this.setSelectRange(s.end,s.end)}}})},function(e,t,n){"use strict";var i=n(4).Class,r=n(3),s=new i({constructor:function(e){this.init(e)},init:function(e){this.undoList=[e||{value:null}],this.redoList=[]},push:function(e){this.last()!==e&&this.undoList.push(e)},last:function(){return this.undoList[this.undoList.length-1]},undo:function(){if(this.undoList.length>1){var e=this.undoList.pop();if(r.isNull(e)||r.isNull(e.value))return;this.redoList.push(e)}return this.last()},redo:function(){var e=this.redoList.pop();if(!r.isNull(e)&&!r.isNull(e.value))return this.undoList.push(e),e}});e.exports=s},function(e,t){"use strict";e.exports=[{name:"undo",key:"{cmd}+z",handler:function(){this.editor.undo()}},{name:"redo",key:"{cmd}+shift+z",handler:function(){this.editor.redo()}},{name:"h2",key:"shift+alt+2",handler:function(){this.editor.wrapSelectText("## ")}},{name:"h3",key:"shift+alt+3",handler:function(){this.editor.wrapSelectText("### ")}},{name:"h4",key:"shift+alt+4",handler:function(){this.editor.wrapSelectText("#### ")}},{name:"h5",key:"shift+alt+5",handler:function(){this.editor.wrapSelectText("##### ")}}]},function(e,t){},function(e,t){e.exports='
\n
\n
\n
\n \n
'},function(e,t,n){"use strict";var i=n(1);n(95);var r=new i.Component({template:n(96),data:function(){return{html:"",alert:"预览区域"}},props:{mditor:null,value:{get:function(){return this._value},set:function(e){var t=this;this._value=e;var n={value:this._value};this.$emit("beforeRender",n),this.mditor.parser.parse(n.value,function(e,n){var i={value:n||e};t.$emit("afterRender",i),t.html=i.value})}}},onClick:function(e){e.preventDefault();var t=e.target;if("A"==t.tagName){var n=t.getAttribute("href");n&&window.open(n,"_blank")}}});e.exports=r},function(e,t){},function(e,t){e.exports='
\n
\n
\n
'},function(e,t,n){"use strict";var i=n(1),r=n(3);n(98);var s=/^\/[\s\S]+\/(i|g|m)*$/,o=new i.Component({template:n(99),props:{mditor:null,active:!1,findWord:"",replaceWord:""},onReady:function(){this.mditor.removeCommand("find"),this.mditor.addCommand({name:"find",key:"{cmd}+f",owner:this.mditor.$element,handler:this.show.bind(this,null)}),this.mditor.removeCommand("cancel-find"),this.mditor.addCommand({name:"cancel-find",key:"esc",owner:this.mditor.$element,handler:this.hide.bind(this)})},hide:function(){this.findWord="",this.replaceWord="",this.mditor.editor.markExp=null,this.active=!1},show:function(e){var t=this;this.active=!0,this.findWord=e||this.mditor.editor.getSelectText(),this.active&&setTimeout(function(){t.findBox.focus()},200),this.mditor.editor.syncScroll()},watch:{findWord:function(){var e=this;this.mditor&&this.mditor.editor&&(this.findWord?this.mditor.editor.markExp=this.parseRegexp(this.findWord):this.mditor.editor.markExp=null,setTimeout(function(){e.mditor.editor.activeMark(0)},100))}},parseRegexp:function(e,t){if(t||!s.test(e))return new RegExp(r.escapeRegExp(e),"gm");try{return new Function("return "+e)()}catch(t){return this.parseRegexp(e,!0)}},find:function(){this.mditor.editor.activeMark()},replace:function(){this.mditor.value=this.mditor.value.replace(this.mditor.editor.markExp,this.replaceWord||"")},onFindEnter:function(e){13==e.keyCode&&(e.preventDefault(),this.find())},onReplaceEnter:function(e){13==e.keyCode&&(e.preventDefault(),this.replace())},onCompositionEnd:function(e){e.target.blur(),e.target.focus()}});e.exports=o},function(e,t){},function(e,t){e.exports='
\n
\n \n \n
\n
\n \n \n
\n
'},function(e,t,n){"use strict";var i=n(101),r=n(3);i.filter=function(e){return!!e.target};var s=e.exports=function(e){r.defineFreezeProp(this,"mditor",e)};s.prototype._inRegion=function(e,t){return!!e&&(t=t||this.mditor.editor.$element,r.isFunction(t)&&(t=t(this.mditor)),e===t||this._inRegion(e.parentNode,t))},s.prototype.bind=function(e,t,n,r){var s=this,o=this.mditor;e&&t&&(e=e.replace("{cmd}",o.CMD),i(e,function(e){s._inRegion(e.target,r)&&(n||e.preventDefault(),t instanceof Function?t.call(o,e):o.execCommand(t,e),setTimeout(function(){o.focus()},0))}))},s.prototype.unbind=function(e){i.unbind(e)}},function(e,t,n){!function(t){function n(e,t){for(var n=e.length;n--;)if(e[n]===t)return n;return-1}function i(e,t){if(e.length!=t.length)return!1;for(var n=0;n0;for(s in x)(!x[s]&&n(i.mods,+s)>-1||x[s]&&n(i.mods,+s)==-1)&&(a=!1);(0!=i.mods.length||x[16]||x[18]||x[17]||x[91])&&!a||i.method(e,i)===!1&&(e.preventDefault?e.preventDefault():e.returnValue=!1,e.stopPropagation&&e.stopPropagation(),e.cancelBubble&&(e.cancelBubble=!0))}}function o(e){var t,i=e.keyCode,r=n(N,i);if(r>=0&&N.splice(r,1),93!=i&&224!=i||(i=91),i in x){x[i]=!1;for(t in E)E[t]==i&&(l[t]=!1)}}function a(){for(y in x)x[y]=!1;for(y in E)l[y]=!1}function l(e,t,n){var i,r;i=g(e),void 0===n&&(n=t,t="all");for(var s=0;s1&&(r=b(e),e=[e[e.length-1]]),e=e[0],e=T(e),e in w||(w[e]=[]),w[e].push({shortcut:i[s],scope:t,method:n,key:i[s],mods:r})}function c(e,t){var n,r,s,o,a,l=[];for(n=g(e),o=0;o1&&(l=b(r),e=r[r.length-1]),e=T(e),void 0===t&&(t=f()),!w[e])return;for(s in w[e])a=w[e][s],a.scope===t&&i(a.mods,l)&&(w[e][s]={})}}function u(e){return"string"==typeof e&&(e=T(e)),n(N,e)!=-1}function p(){return N.slice(0)}function d(e){var t=(e.target||e.srcElement).tagName;return!("INPUT"==t||"SELECT"==t||"TEXTAREA"==t)}function h(e){k=e||"all"}function f(){return k||"all"}function m(e){var t,n,i; -for(t in w)for(n=w[t],i=0;i/g,">").replace(/"/g,""").replace(/'/g,"'")}function o(e){return e.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g,function(e,t){return t=t.toLowerCase(),"colon"===t?":":"#"===t.charAt(0)?"x"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):""})}function a(e,t){return e=e.source,t=t||"",function n(i,r){return i?(r=r.source||r,r=r.replace(/(^|[^\[])\^/g,"$1"),e=e.replace(i,r),n):new RegExp(e,t)}}function l(){}function c(e){for(var t,n,i=1;iAn error occured:

"+s(e.message+"",!0)+"
";throw e}}var p={newline:/^\n+/,code:/^( {4}[^\n]+\n*)+/,fences:l,hr:/^( *[-*_]){3,} *(?:\n+|$)/,heading:/^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,nptable:l,lheading:/^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,blockquote:/^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,list:/^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,html:/^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,def:/^ *\[([^\]]+)\]: *]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,table:l,paragraph:/^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,text:/^[^\n]+/};p.bullet=/(?:[*+-]|\d+\.)/,p.item=/^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/,p.item=a(p.item,"gm")(/bull/g,p.bullet)(),p.list=a(p.list)(/bull/g,p.bullet)("hr","\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))")("def","\\n+(?="+p.def.source+")")(),p.blockquote=a(p.blockquote)("def",p.def)(),p._tag="(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b",p.html=a(p.html)("comment",//)("closed",/<(tag)[\s\S]+?<\/\1>/)("closing",/])*?>/)(/tag/g,p._tag)(),p.paragraph=a(p.paragraph)("hr",p.hr)("heading",p.heading)("lheading",p.lheading)("blockquote",p.blockquote)("tag","<"+p._tag)("def",p.def)(),p.normal=c({},p),p.gfm=c({},p.normal,{fences:/^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,paragraph:/^/,heading:/^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/}),p.gfm.paragraph=a(p.paragraph)("(?!","(?!"+p.gfm.fences.source.replace("\\1","\\2")+"|"+p.list.source.replace("\\1","\\3")+"|")(),p.tables=c({},p.gfm,{nptable:/^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,table:/^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/}),t.rules=p,t.lex=function(e,n){var i=new t(n);return i.lex(e)},t.prototype.lex=function(e){return e=e.replace(/\r\n|\r/g,"\n").replace(/\t/g," ").replace(/\u00a0/g," ").replace(/\u2424/g,"\n"),this.token(e,!0)},t.prototype.token=function(e,t,n){for(var i,r,s,o,a,l,c,u,d,e=e.replace(/^ +$/gm,"");e;)if((s=this.rules.newline.exec(e))&&(e=e.substring(s[0].length),s[0].length>1&&this.tokens.push({type:"space"})),s=this.rules.code.exec(e))e=e.substring(s[0].length),s=s[0].replace(/^ {4}/gm,""),this.tokens.push({type:"code",text:this.options.pedantic?s:s.replace(/\n+$/,"")});else if(s=this.rules.fences.exec(e))e=e.substring(s[0].length),this.tokens.push({type:"code",lang:s[2],text:s[3]||""});else if(s=this.rules.heading.exec(e))e=e.substring(s[0].length),this.tokens.push({type:"heading",depth:s[1].length,text:s[2]});else if(t&&(s=this.rules.nptable.exec(e))){for(e=e.substring(s[0].length),l={type:"table",header:s[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:s[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:s[3].replace(/\n$/,"").split("\n")},u=0;u ?/gm,""),this.token(s,t,!0),this.tokens.push({type:"blockquote_end"});else if(s=this.rules.list.exec(e)){for(e=e.substring(s[0].length),o=s[2],this.tokens.push({type:"list_start",ordered:o.length>1}),s=s[0].match(this.rules.item),i=!1,d=s.length,u=0;u1&&a.length>1||(e=s.slice(u+1).join("\n")+e,u=d-1)),r=i||/\n\n(?!\s*$)/.test(l),u!==d-1&&(i="\n"===l.charAt(l.length-1),r||(r=i)),this.tokens.push({type:r?"loose_item_start":"list_item_start"}),this.token(l,!1,n),this.tokens.push({type:"list_item_end"});this.tokens.push({type:"list_end"})}else if(s=this.rules.html.exec(e))e=e.substring(s[0].length),this.tokens.push({type:this.options.sanitize?"paragraph":"html",pre:!this.options.sanitizer&&("pre"===s[1]||"script"===s[1]||"style"===s[1]),text:s[0]});else if(!n&&t&&(s=this.rules.def.exec(e)))e=e.substring(s[0].length),this.tokens.links[s[1].toLowerCase()]={href:s[2],title:s[3]};else if(t&&(s=this.rules.table.exec(e))){for(e=e.substring(s[0].length),l={type:"table",header:s[1].replace(/^ *| *\| *$/g,"").split(/ *\| */),align:s[2].replace(/^ *|\| *$/g,"").split(/ *\| */),cells:s[3].replace(/(?: *\| *)?\n$/,"").split("\n")},u=0;u])/,autolink:/^<([^ >]+(@|:\/)[^ >]+)>/,url:l,tag:/^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,link:/^!?\[(inside)\]\(href\)/,reflink:/^!?\[(inside)\]\s*\[([^\]]*)\]/,nolink:/^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,strong:/^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,em:/^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,code:/^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,br:/^ {2,}\n(?!\s*$)/,del:l,text:/^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/,d.link=a(d.link)("inside",d._inside)("href",d._href)(),d.reflink=a(d.reflink)("inside",d._inside)(),d.normal=c({},d),d.pedantic=c({},d.normal,{strong:/^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,em:/^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/}),d.gfm=c({},d.normal,{escape:a(d.escape)("])","~|])")(),url:/^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,del:/^~~(?=\S)([\s\S]*?\S)~~/,text:a(d.text)("]|","~]|")("|","|https?://|")()}),d.breaks=c({},d.gfm,{br:a(d.br)("{2,}","*")(),text:a(d.gfm.text)("{2,}","*")()}),n.rules=d,n.output=function(e,t,i){var r=new n(t,i);return r.output(e)},n.prototype.output=function(e){for(var t,n,i,r,o="";e;)if(r=this.rules.escape.exec(e))e=e.substring(r[0].length),o+=r[1];else if(r=this.rules.autolink.exec(e))e=e.substring(r[0].length),"@"===r[2]?(n=":"===r[1].charAt(6)?this.mangle(r[1].substring(7)):this.mangle(r[1]),i=this.mangle("mailto:")+n):(n=s(r[1]),i=n),o+=this.renderer.link(i,null,n);else if(this.inLink||!(r=this.rules.url.exec(e))){if(r=this.rules.tag.exec(e))!this.inLink&&/^
/i.test(r[0])&&(this.inLink=!1),e=e.substring(r[0].length),o+=this.options.sanitize?this.options.sanitizer?this.options.sanitizer(r[0]):s(r[0]):r[0];else if(r=this.rules.link.exec(e))e=e.substring(r[0].length),this.inLink=!0,o+=this.outputLink(r,{href:r[2],title:r[3]}),this.inLink=!1;else if((r=this.rules.reflink.exec(e))||(r=this.rules.nolink.exec(e))){if(e=e.substring(r[0].length),t=(r[2]||r[1]).replace(/\s+/g," "),t=this.links[t.toLowerCase()],!t||!t.href){o+=r[0].charAt(0),e=r[0].substring(1)+e;continue}this.inLink=!0,o+=this.outputLink(r,t),this.inLink=!1}else if(r=this.rules.strong.exec(e))e=e.substring(r[0].length),o+=this.renderer.strong(this.output(r[2]||r[1]));else if(r=this.rules.em.exec(e))e=e.substring(r[0].length),o+=this.renderer.em(this.output(r[2]||r[1]));else if(r=this.rules.code.exec(e))e=e.substring(r[0].length),o+=this.renderer.codespan(s(r[2],!0));else if(r=this.rules.br.exec(e))e=e.substring(r[0].length),o+=this.renderer.br();else if(r=this.rules.del.exec(e))e=e.substring(r[0].length),o+=this.renderer.del(this.output(r[1]));else if(r=this.rules.text.exec(e))e=e.substring(r[0].length),o+=this.renderer.text(s(this.smartypants(r[0])));else if(e)throw new Error("Infinite loop on byte: "+e.charCodeAt(0))}else e=e.substring(r[0].length),n=s(r[1]),i=n,o+=this.renderer.link(i,null,n);return o},n.prototype.outputLink=function(e,t){var n=s(t.href),i=t.title?s(t.title):null;return"!"!==e[0].charAt(0)?this.renderer.link(n,i,this.output(e[1])):this.renderer.image(n,i,s(e[1]))},n.prototype.smartypants=function(e){return this.options.smartypants?e.replace(/---/g,"—").replace(/--/g,"–").replace(/(^|[-\u2014\/(\[{"\s])'/g,"$1‘").replace(/'/g,"’").replace(/(^|[-\u2014\/(\[{\u2018\s])"/g,"$1“").replace(/"/g,"”").replace(/\.{3}/g,"…"):e},n.prototype.mangle=function(e){if(!this.options.mangle)return e;for(var t,n="",i=e.length,r=0;r.5&&(t="x"+t.toString(16)),n+="&#"+t+";";return n},i.prototype.code=function(e,t,n){if(this.options.highlight){var i=this.options.highlight(e,t);null!=i&&i!==e&&(n=!0,e=i)}return t?'
'+(n?e:s(e,!0))+"\n
\n":"
"+(n?e:s(e,!0))+"\n
"},i.prototype.blockquote=function(e){return"
\n"+e+"
\n"},i.prototype.html=function(e){return e},i.prototype.heading=function(e,t,n){return"'+e+"\n"},i.prototype.hr=function(){return this.options.xhtml?"
\n":"
\n"},i.prototype.list=function(e,t){var n=t?"ol":"ul";return"<"+n+">\n"+e+"\n"},i.prototype.listitem=function(e){return"
  • "+e+"
  • \n"},i.prototype.paragraph=function(e){return"

    "+e+"

    \n"},i.prototype.table=function(e,t){return"\n\n"+e+"\n\n"+t+"\n
    \n"},i.prototype.tablerow=function(e){return"\n"+e+"\n"},i.prototype.tablecell=function(e,t){var n=t.header?"th":"td",i=t.align?"<"+n+' style="text-align:'+t.align+'">':"<"+n+">";return i+e+"\n"},i.prototype.strong=function(e){return""+e+""},i.prototype.em=function(e){return""+e+""},i.prototype.codespan=function(e){return""+e+""},i.prototype.br=function(){return this.options.xhtml?"
    ":"
    "},i.prototype.del=function(e){return""+e+""},i.prototype.link=function(e,t,n){if(this.options.sanitize){try{var i=decodeURIComponent(o(e)).replace(/[^\w:]/g,"").toLowerCase()}catch(e){return""}if(0===i.indexOf("javascript:")||0===i.indexOf("vbscript:"))return""}var r='
    "},i.prototype.image=function(e,t,n){var i=''+n+'":">"},i.prototype.text=function(e){return e},r.parse=function(e,t,n){var i=new r(t,n);return i.parse(e)},r.prototype.parse=function(e){this.inline=new n(e.links,this.options,this.renderer),this.tokens=e.reverse();for(var t="";this.next();)t+=this.tok();return t},r.prototype.next=function(){return this.token=this.tokens.pop()},r.prototype.peek=function(){return this.tokens[this.tokens.length-1]||0},r.prototype.parseText=function(){for(var e=this.token.text;"text"===this.peek().type;)e+="\n"+this.next().text;return this.inline.output(e)},r.prototype.tok=function(){switch(this.token.type){case"space":return"";case"hr":return this.renderer.hr();case"heading":return this.renderer.heading(this.inline.output(this.token.text),this.token.depth,this.token.text);case"code":return this.renderer.code(this.token.text,this.token.lang,this.token.escaped);case"table":var e,t,n,i,r,s="",o="";for(n="",e=0;ee.length)return;if(!(w instanceof l)){d.lastIndex=0;var x=d.exec(w),k=1;if(!x&&m&&_!=t.length-1){if(d.lastIndex=y,x=d.exec(e),!x)break;for(var E=x.index+(f?x[1].length:0),S=x.index+x[0].length,T=_,N=y,P=t.length;T=N&&(++_,y=N);if(t[_]instanceof l||t[T-1].greedy)continue;k=T-_,w=e.slice(y,N),x.index-=y}if(x){f&&(g=x[1].length);var E=x.index+g,x=x[0].slice(g),S=E+x.length,A=w.slice(0,E),C=w.slice(S),I=[_,k];A&&(++_,y+=A.length,I.push(A));var L=new l(c,h?i.tokenize(x,h):x,b,x,m);if(I.push(L),C&&I.push(C),Array.prototype.splice.apply(t,I),1!=k&&i.matchGrammar(e,t,n,_,y,!0,c),o)break}else if(o)break}}}}},tokenize:function(e,t,n){var r=[e],s=t.rest;if(s){for(var o in s)t[o]=s[o];delete t.rest}return i.matchGrammar(e,r,t,0,0,!1),r},hooks:{all:{},add:function(e,t){var n=i.hooks.all;n[e]=n[e]||[],n[e].push(t)},run:function(e,t){var n=i.hooks.all[e];if(n&&n.length)for(var r,s=0;r=n[s++];)r(t)}}},r=i.Token=function(e,t,n,i,r){this.type=e,this.content=t,this.alias=n,this.length=0|(i||"").length,this.greedy=!!r};if(r.stringify=function(e,t,n){if("string"==typeof e)return e;if("Array"===i.util.type(e))return e.map(function(n){return r.stringify(n,t,e)}).join("");var s={type:e.type,content:r.stringify(e.content,t,n),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:n};if("comment"==s.type&&(s.attributes.spellcheck="true"),e.alias){var o="Array"===i.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(s.classes,o)}i.hooks.run("wrap",s);var a=Object.keys(s.attributes).map(function(e){return e+'="'+(s.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+s.tag+' class="'+s.classes.join(" ")+'"'+(a?" "+a:"")+">"+s.content+""},!n.document)return n.addEventListener?(n.addEventListener("message",function(e){var t=JSON.parse(e.data),r=t.language,s=t.code,o=t.immediateClose;n.postMessage(i.highlight(s,i.languages[r],r)),o&&n.close()},!1),n.Prism):n.Prism;var s=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return s&&(i.filename=s.src,i.manual||s.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(i.highlightAll):window.setTimeout(i.highlightAll,16):document.addEventListener("DOMContentLoaded",i.highlightAll))),n.Prism}();"undefined"!=typeof e&&e.exports&&(e.exports=i),"undefined"!=typeof t&&(t.Prism=i),i.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype://i,cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\s\S])*\1|[^\s'">=]+))?)*\s*\/?>/i,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:('|")[\s\S]*?(\1)|[^\s>]+)/i,inside:{punctuation:/[=>"']/}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},i.languages.markup.tag.inside["attr-value"].inside.entity=i.languages.markup.entity,i.hooks.add("wrap",function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))}),i.languages.xml=i.languages.markup,i.languages.html=i.languages.markup,i.languages.mathml=i.languages.markup,i.languages.svg=i.languages.markup,i.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^\{\}\s][^\{\};]*?(?=\s*\{)/,string:{pattern:/("|')(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/(\b|\B)[\w-]+(?=\s*:)/i,important:/\B!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},i.languages.css.atrule.inside.rest=i.util.clone(i.languages.css),i.languages.markup&&(i.languages.insertBefore("markup","tag",{style:{pattern:/()[\s\S]*?(?=<\/style>)/i,lookbehind:!0,inside:i.languages.css,alias:"language-css"}}),i.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|').*?\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:i.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:i.languages.css}},alias:"language-css"}},i.languages.markup.tag)),i.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:{pattern:/(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,lookbehind:!0,inside:{punctuation:/(\.|\\)/}},keyword:/\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(true|false)\b/,function:/[a-z0-9_]+(?=\()/i,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/},i.languages.javascript=i.languages.extend("clike",{keyword:/\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield)\b/,number:/\b-?(0[xX][\dA-Fa-f]+|0[bB][01]+|0[oO][0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,function:/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\s*\()/i,operator:/-[-=]?|\+[+=]?|!=?=?|<>?>?=?|=(?:==?|>)?|&[&=]?|\|[|=]?|\*\*?=?|\/=?|~|\^=?|%=?|\?|\.{3}/}),i.languages.insertBefore("javascript","keyword",{regex:{pattern:/(^|[^\/])\/(?!\/)(\[[^\]\r\n]+]|\\.|[^\/\\\[\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0},"function-variable":{pattern:/[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\s*=\s*(?:function\b|(?:\([^()]*\)|[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*)\s*=>))/i,alias:"function"}}),i.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\\\|\\?[^\\])*?`/,greedy:!0,inside:{interpolation:{pattern:/\$\{[^}]+\}/,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:i.languages.javascript}},string:/[\s\S]+/}}}),i.languages.markup&&i.languages.insertBefore("markup","tag",{script:{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:i.languages.javascript,alias:"language-javascript"}}),i.languages.js=i.languages.javascript,function(){"undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector&&(self.Prism.fileHighlight=function(){var e={js:"javascript",py:"python",rb:"ruby",ps1:"powershell",psm1:"powershell",sh:"bash",bat:"batch",h:"c",tex:"latex"};Array.prototype.slice.call(document.querySelectorAll("pre[data-src]")).forEach(function(t){for(var n,r=t.getAttribute("data-src"),s=t,o=/\blang(?:uage)?-(?!\*)(\w+)\b/i;s&&!o.test(s.className);)s=s.parentNode;if(s&&(n=(t.className.match(o)||[,""])[1]),!n){var a=(r.match(/\.(\w+)$/)||[,""])[1];n=e[a]||a}var l=document.createElement("code");l.className="language-"+n,t.textContent="",l.textContent="Loading…",t.appendChild(l);var c=new XMLHttpRequest;c.open("GET",r,!0),c.onreadystatechange=function(){4==c.readyState&&(c.status<400&&c.responseText?(l.textContent=c.responseText,i.highlightElement(l)):c.status>=400?l.textContent="✖ Error "+c.status+" while fetching file: "+c.statusText:l.textContent="✖ Error: File does not exist or is empty")},c.send(null)})},document.addEventListener("DOMContentLoaded",self.Prism.fileHighlight))}()}).call(t,function(){return this}())},function(e,t){Prism.languages.java=Prism.languages.extend("clike",{keyword:/\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/,number:/\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp\-]+\b|\b\d*\.?\d+(?:e[+-]?\d+)?[df]?\b/i,operator:{pattern:/(^|[^.])(?:\+[+=]?|-[-=]?|!=?|<>?>?=?|==?|&[&=]?|\|[|=]?|\*=?|\/=?|%=?|\^=?|[?:~])/m,lookbehind:!0}}),Prism.languages.insertBefore("java","function",{annotation:{alias:"punctuation",pattern:/(^|[^.])@\w+/,lookbehind:!0}})},function(e,t){Prism.languages.csharp=Prism.languages.extend("clike",{keyword:/\b(abstract|as|async|await|base|bool|break|byte|case|catch|char|checked|class|const|continue|decimal|default|delegate|do|double|else|enum|event|explicit|extern|false|finally|fixed|float|for|foreach|goto|if|implicit|in|int|interface|internal|is|lock|long|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch|this|throw|true|try|typeof|uint|ulong|unchecked|unsafe|ushort|using|virtual|void|volatile|while|add|alias|ascending|async|await|descending|dynamic|from|get|global|group|into|join|let|orderby|partial|remove|select|set|value|var|where|yield)\b/,string:[{pattern:/@("|')(\1\1|\\\1|\\?(?!\1)[\s\S])*\1/,greedy:!0},{pattern:/("|')(\\?.)*?\1/,greedy:!0}],number:/\b-?(0x[\da-f]+|\d*\.?\d+f?)\b/i}),Prism.languages.insertBefore("csharp","keyword",{"generic-method":{pattern:/[a-z0-9_]+\s*<[^>\r\n]+?>\s*(?=\()/i,alias:"function",inside:{keyword:Prism.languages.csharp.keyword,punctuation:/[<>(),.:]/}},preprocessor:{pattern:/(^\s*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(\s*#)\b(define|elif|else|endif|endregion|error|if|line|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}})},function(e,t){Prism.languages.php=Prism.languages.extend("clike",{keyword:/\b(and|or|xor|array|as|break|case|cfunction|class|const|continue|declare|default|die|do|else|elseif|enddeclare|endfor|endforeach|endif|endswitch|endwhile|extends|for|foreach|function|include|include_once|global|if|new|return|static|switch|use|require|require_once|var|while|abstract|interface|public|implements|private|protected|parent|throw|null|echo|print|trait|namespace|final|yield|goto|instanceof|finally|try|catch)\b/i, -constant:/\b[A-Z0-9_]{2,}\b/,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0}}),Prism.languages.insertBefore("php","class-name",{"shell-comment":{pattern:/(^|[^\\])#.*/,lookbehind:!0,alias:"comment"}}),Prism.languages.insertBefore("php","keyword",{delimiter:{pattern:/\?>|<\?(?:php|=)?/i,alias:"important"},variable:/\$\w+\b/i,package:{pattern:/(\\|namespace\s+|use\s+)[\w\\]+/,lookbehind:!0,inside:{punctuation:/\\/}}}),Prism.languages.insertBefore("php","operator",{property:{pattern:/(->)[\w]+/,lookbehind:!0}}),Prism.languages.markup&&(Prism.hooks.add("before-highlight",function(e){"php"===e.language&&/(?:<\?php|<\?)/gi.test(e.code)&&(e.tokenStack=[],e.backupCode=e.code,e.code=e.code.replace(/(?:<\?php|<\?)[\s\S]*?(?:\?>|$)/gi,function(t){for(var n=e.tokenStack.length;e.backupCode.indexOf("___PHP"+n+"___")!==-1;)++n;return e.tokenStack[n]=t,"___PHP"+n+"___"}),e.grammar=Prism.languages.markup)}),Prism.hooks.add("before-insert",function(e){"php"===e.language&&e.backupCode&&(e.code=e.backupCode,delete e.backupCode)}),Prism.hooks.add("after-highlight",function(e){if("php"===e.language&&e.tokenStack){e.grammar=Prism.languages.php;for(var t=0,n=Object.keys(e.tokenStack);t'+Prism.highlight(r,e.grammar,"php").replace(/\$/g,"$$$$")+"")}e.element.innerHTML=e.highlightedCode}}))},function(e,t){Prism.languages.python={"triple-quoted-string":{pattern:/"""[\s\S]+?"""|'''[\s\S]+?'''/,alias:"string"},comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},string:{pattern:/("|')(?:\\\\|\\?[^\\\r\n])*?\1/,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_][a-zA-Z0-9_]*(?=\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)[a-z0-9_]+/i,lookbehind:!0},keyword:/\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|pass|print|raise|return|try|while|with|yield)\b/,boolean:/\b(?:True|False)\b/,number:/\b-?(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*\.?\d*|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]|\b(?:or|and|not)\b/,punctuation:/[{}[\];(),.:]/}},function(e,t){Prism.languages.json={property:/"(?:\\.|[^\\"])*"(?=\s*:)/gi,string:/"(?!:)(?:\\.|[^\\"])*"(?!:)/g,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee][+-]?\d+)?)\b/g,punctuation:/[{}[\]);,]/g,operator:/:/g,boolean:/\b(true|false)\b/gi,null:/\bnull\b/gi},Prism.languages.jsonp=Prism.languages.json},function(e,t){Prism.languages.yaml={scalar:{pattern:/([\-:]\s*(![^\s]+)?[ \t]*[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)[^\r\n]+(?:\3[^\r\n]+)*)/,lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:/(\s*(?:^|[:\-,[{\r\n?])[ \t]*(![^\s]+)?[ \t]*)[^\r\n{[\]},#\s]+?(?=\s*:\s)/,lookbehind:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(\d{4}-\d\d?-\d\d?([tT]|[ \t]+)\d\d?:\d{2}:\d{2}(\.\d*)?[ \t]*(Z|[-+]\d\d?(:\d{2})?)?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(:\d{2}(\.\d*)?)?)(?=[ \t]*($|,|]|}))/m,lookbehind:!0,alias:"number"},boolean:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(true|false)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},null:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)(null|~)[ \t]*(?=$|,|]|})/im,lookbehind:!0,alias:"important"},string:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')(?=[ \t]*($|,|]|}))/m,lookbehind:!0,greedy:!0},number:{pattern:/([:\-,[{]\s*(![^\s]+)?[ \t]*)[+\-]?(0x[\da-f]+|0o[0-7]+|(\d+\.?\d*|\.?\d+)(e[\+\-]?\d+)?|\.inf|\.nan)[ \t]*(?=$|,|]|})/im,lookbehind:!0},tag:/![^\s]+/,important:/[&*][\w]+/,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./}},function(e,t){Prism.languages.perl={comment:[{pattern:/(^\s*)=\w+[\s\S]*?=cut.*/m,lookbehind:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0}],string:[{pattern:/\b(?:q|qq|qx|qw)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s+([a-zA-Z0-9])(?:[^\\]|\\[\s\S])*?\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\((?:[^()\\]|\\[\s\S])*\)/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\{(?:[^{}\\]|\\[\s\S])*\}/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\[(?:[^[\]\\]|\\[\s\S])*\]/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*<(?:[^<>\\]|\\[\s\S])*>/,greedy:!0},{pattern:/("|`)(?:[^\\]|\\[\s\S])*?\1/,greedy:!0},{pattern:/'(?:[^'\\\r\n]|\\.)*'/,greedy:!0}],regex:[{pattern:/\b(?:m|qr)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s+([a-zA-Z0-9])(?:[^\\]|\\.)*?\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngc]*/,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\2(?:[^\\]|\\[\s\S])*?\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s+([a-zA-Z0-9])(?:[^\\]|\\[\s\S])*?\2(?:[^\\]|\\[\s\S])*?\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\((?:[^()\\]|\\[\s\S])*\)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\{(?:[^{}\\]|\\[\s\S])*\}\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\[(?:[^[\]\\]|\\[\s\S])*\]\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*<(?:[^<>\\]|\\[\s\S])*>\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor|x)\b))/,greedy:!0}],variable:[/[&*$@%]\{\^[A-Z]+\}/,/[&*$@%]\^[A-Z_]/,/[&*$@%]#?(?=\{)/,/[&*$@%]#?((::)*'?(?!\d)[\w$]+)+(::)*/i,/[&*$@%]\d+/,/(?!%=)[$@%][!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/],filehandle:{pattern:/<(?![<=])\S*>|\b_\b/,alias:"symbol"},vstring:{pattern:/v\d+(\.\d+)*|\d+(\.\d+){2,}/,alias:"string"},function:{pattern:/sub [a-z0-9_]+/i,inside:{keyword:/sub/}},keyword:/\b(any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|say|state|sub|switch|undef|unless|until|use|when|while)\b/,number:/\b-?(0x[\dA-Fa-f](_?[\dA-Fa-f])*|0b[01](_?[01])*|(\d(_?\d)*)?\.?\d(_?\d)*([Ee][+-]?\d+)?)\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\b/,punctuation:/[{}[\];(),:]/}},function(e,t){Prism.languages.go=Prism.languages.extend("clike",{keyword:/\b(break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,builtin:/\b(bool|byte|complex(64|128)|error|float(32|64)|rune|string|u?int(8|16|32|64|)|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(ln)?|real|recover)\b/,boolean:/\b(_|iota|nil|true|false)\b/,operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,number:/\b(-?(0x[a-f\d]+|(\d+\.?\d*|\.\d+)(e[-+]?\d+)?)i?)\b/i,string:{pattern:/("|'|`)(\\?.|\r|\n)*?\1/,greedy:!0}}),delete Prism.languages.go["class-name"]},function(e,t){!function(e){var t={variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b-?(?:0x[\dA-Fa-f]+|\d*\.?\d+(?:[Ee]-?\d+)?)\b/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\([^)]+\)|`[^`]+`/,inside:{variable:/^\$\(|^`|\)$|`$/}},/\$(?:[a-z0-9_#\?\*!@]+|\{[^}]+\})/i]};e.languages.bash={shebang:{pattern:/^#!\s*\/bin\/bash|^#!\s*\/bin\/sh/,alias:"important"},comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},string:[{pattern:/((?:^|[^<])<<\s*)(?:"|')?(\w+?)(?:"|')?\s*\r?\n(?:[\s\S])*?\r?\n\2/g,lookbehind:!0,greedy:!0,inside:t},{pattern:/(["'])(?:\\\\|\\?[^\\])*?\1/g,greedy:!0,inside:t}],variable:t.variable,function:{pattern:/(^|\s|;|\||&)(?:alias|apropos|apt-get|aptitude|aspell|awk|basename|bash|bc|bg|builtin|bzip2|cal|cat|cd|cfdisk|chgrp|chmod|chown|chroot|chkconfig|cksum|clear|cmp|comm|command|cp|cron|crontab|csplit|cut|date|dc|dd|ddrescue|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|enable|env|ethtool|eval|exec|expand|expect|export|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|getopts|git|grep|groupadd|groupdel|groupmod|groups|gzip|hash|head|help|hg|history|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|jobs|join|kill|killall|less|link|ln|locate|logname|logout|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|make|man|mkdir|mkfifo|mkisofs|mknod|more|most|mount|mtools|mtr|mv|mmv|nano|netstat|nice|nl|nohup|notify-send|npm|nslookup|open|op|passwd|paste|pathchk|ping|pkill|popd|pr|printcap|printenv|printf|ps|pushd|pv|pwd|quota|quotacheck|quotactl|ram|rar|rcp|read|readarray|readonly|reboot|rename|renice|remsync|rev|rm|rmdir|rsync|screen|scp|sdiff|sed|seq|service|sftp|shift|shopt|shutdown|sleep|slocate|sort|source|split|ssh|stat|strace|su|sudo|sum|suspend|sync|tail|tar|tee|test|time|timeout|times|touch|top|traceroute|trap|tr|tsort|tty|type|ulimit|umask|umount|unalias|uname|unexpand|uniq|units|unrar|unshar|uptime|useradd|userdel|usermod|users|uuencode|uudecode|v|vdir|vi|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yes|zip)(?=$|\s|;|\||&)/,lookbehind:!0},keyword:{pattern:/(^|\s|;|\||&)(?:let|:|\.|if|then|else|elif|fi|for|break|continue|while|in|case|function|select|do|done|until|echo|exit|return|set|declare)(?=$|\s|;|\||&)/,lookbehind:!0},boolean:{pattern:/(^|\s|;|\||&)(?:true|false)(?=$|\s|;|\||&)/,lookbehind:!0},operator:/&&?|\|\|?|==?|!=?|<<>|<=?|>=?|=~/,punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];]/};var n=t.variable[1].inside;n.function=e.languages.bash.function,n.keyword=e.languages.bash.keyword,n.boolean=e.languages.bash.boolean,n.operator=e.languages.bash.operator,n.punctuation=e.languages.bash.punctuation}(Prism)},function(e,t){Prism.languages.fsharp=Prism.languages.extend("clike",{comment:[{pattern:/(^|[^\\])\(\*[\s\S]*?\*\)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],keyword:/\b(?:let|return|use|yield)(?:!\B|\b)|\b(abstract|and|as|assert|base|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|global|if|in|inherit|inline|interface|internal|lazy|match|member|module|mutable|namespace|new|not|null|of|open|or|override|private|public|rec|select|static|struct|then|to|true|try|type|upcast|val|void|when|while|with|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|include|method|mixin|object|parallel|process|protected|pure|sealed|tailcall|trait|virtual|volatile)\b/,string:{pattern:/(?:"""[\s\S]*?"""|@"(?:""|[^"])*"|("|')(?:\\\1|\\?(?!\1)[\s\S])*\1)B?/,greedy:!0},number:[/\b-?0x[\da-fA-F]+(un|lf|LF)?\b/,/\b-?0b[01]+(y|uy)?\b/,/\b-?(\d*\.?\d+|\d+\.)([fFmM]|[eE][+-]?\d+)?\b/,/\b-?\d+(y|uy|s|us|l|u|ul|L|UL|I)?\b/]}),Prism.languages.insertBefore("fsharp","keyword",{preprocessor:{pattern:/^[^\r\n\S]*#.*/m,alias:"property",inside:{directive:{pattern:/(\s*#)\b(else|endif|if|light|line|nowarn)\b/,lookbehind:!0,alias:"keyword"}}}})},function(e,t){Prism.languages.typescript=Prism.languages.extend("javascript",{keyword:/\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|var|void|while|with|yield|false|true|module|declare|constructor|string|Function|any|number|boolean|Array|enum|symbol|namespace|abstract|require|type)\b/}),Prism.languages.ts=Prism.languages.typescript},function(e,t){!function(e){var t={url:/url\((["']?).*?\1\)/i,string:{pattern:/("|')(?:[^\\\r\n]|\\(?:\r\n|[\s\S]))*?\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:if|else|for|return|unless)(?=\s+|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,number:/\b\d+(?:\.\d+)?%?/,boolean:/\b(?:true|false)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.+|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],punctuation:/[{}()\[\];:,]/};t.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:e.util.clone(t)},t.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:e.util.clone(t)}},e.languages.stylus={comment:{pattern:/(^|[^\\])(\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},"atrule-declaration":{pattern:/(^\s*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:t}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:(?:\{[^}]*\}|.+)|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:t}},statement:{pattern:/(^[ \t]*)(?:if|else|for|return|unless)[ \t]+.+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:t}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)[^{\r\n]*(?:;|[^{\r\n,](?=$)(?!(\r?\n|\r)(?:\{|\2[ \t]+)))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:t.interpolation}},rest:t}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\))?|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\))?|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t]+)))/m,lookbehind:!0,inside:{interpolation:t.interpolation,punctuation:/[{},]/}},func:t.func,string:t.string,interpolation:t.interpolation,punctuation:/[{}()\[\];:.]/}}(Prism)},function(e,t){Prism.languages.less=Prism.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-]+?(?:\([^{}]+\)|[^(){};])*?(?=\s*\{)/i,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\([^{}]*\)|[^{};@])*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/i,punctuation:/[{}();:,]/,operator:/[+\-*\/]/}),Prism.languages.insertBefore("less","punctuation",{function:Prism.languages.less.function}),Prism.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-]+.*?(?=[(;])/,lookbehind:!0,alias:"function"}})},function(e,t){!function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t]+.+)*/m,lookbehind:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,inside:{atrule:/(?:@[\w-]+|[+=])/m}}}),delete e.languages.sass.atrule;var t=/((\$[-_\w]+)|(#\{\$[-_\w]+\}))/i,n=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|or|not)\b/,{pattern:/(\s+)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,inside:{punctuation:/:/,variable:t,operator:n}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s]+.*)/m,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:t,operator:n,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,delete e.languages.sass.selector,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/([ \t]*)\S(?:,?[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,?[^,\r\n]+)*)*/,lookbehind:!0}})}(Prism)},function(e,t){!function(e){var t=/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g;e.languages.handlebars=e.languages.extend("markup",{handlebars:{pattern:t,inside:{delimiter:{pattern:/^\{\{\{?|\}\}\}?$/i,alias:"punctuation"},string:/(["'])(\\?.)*?\1/,number:/\b-?(0x[\dA-Fa-f]+|\d*\.?\d+([Ee][+-]?\d+)?)\b/,boolean:/\b(true|false)\b/,block:{pattern:/^(\s*~?\s*)[#\/]\S+?(?=\s*~?\s*$|\s)/i,lookbehind:!0,alias:"keyword"},brackets:{pattern:/\[[^\]]+\]/,inside:{punctuation:/\[|\]/,variable:/[\s\S]+/}},punctuation:/[!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,.\/;<=>@\[\\\]^`{|}~\s]+/}}}),e.languages.insertBefore("handlebars","tag",{"handlebars-comment":{pattern:/\{\{![\s\S]*?\}\}/,alias:["handlebars","comment"]}}),e.hooks.add("before-highlight",function(e){"handlebars"===e.language&&(e.tokenStack=[],e.backupCode=e.code,e.code=e.code.replace(t,function(t){for(var n=e.tokenStack.length;e.backupCode.indexOf("___HANDLEBARS"+n+"___")!==-1;)++n;return e.tokenStack[n]=t,"___HANDLEBARS"+n+"___"}))}),e.hooks.add("before-insert",function(e){"handlebars"===e.language&&(e.code=e.backupCode,delete e.backupCode)}),e.hooks.add("after-highlight",function(t){if("handlebars"===t.language){for(var n=0,i=Object.keys(t.tokenStack);n]=?/,/\b(?:(?:start|begin|end)s? with|(?:(?:does not|doesn't) contain|contains?)|(?:is|isn't|is not) (?:in|contained by)|(?:(?:is|isn't|is not) )?(?:greater|less) than(?: or equal)?(?: to)?|(?:(?:does not|doesn't) come|comes) (?:before|after)|(?:is|isn't|is not) equal(?: to)?|(?:(?:does not|doesn't) equal|equals|equal to|isn't|is not)|(?:a )?(?:ref(?: to)?|reference to)|(?:and|or|div|mod|as|not))\b/],keyword:/\b(?:about|above|after|against|apart from|around|aside from|at|back|before|beginning|behind|below|beneath|beside|between|but|by|considering|continue|copy|does|eighth|else|end|equal|error|every|exit|false|fifth|first|for|fourth|from|front|get|given|global|if|ignoring|in|instead of|into|is|it|its|last|local|me|middle|my|ninth|of|on|onto|out of|over|prop|property|put|repeat|return|returning|second|set|seventh|since|sixth|some|tell|tenth|that|the|then|third|through|thru|timeout|times|to|transaction|true|try|until|where|while|whose|with|without)\b/,class:{pattern:/\b(?:alias|application|boolean|class|constant|date|file|integer|list|number|POSIX file|real|record|reference|RGB color|script|text|centimetres|centimeters|feet|inches|kilometres|kilometers|metres|meters|miles|yards|square feet|square kilometres|square kilometers|square metres|square meters|square miles|square yards|cubic centimetres|cubic centimeters|cubic feet|cubic inches|cubic metres|cubic meters|cubic yards|gallons|litres|liters|quarts|grams|kilograms|ounces|pounds|degrees Celsius|degrees Fahrenheit|degrees Kelvin)\b/,alias:"builtin"},punctuation:/[{}():,¬«»《》]/}},function(e,t){Prism.languages.actionscript=Prism.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|else|extends|finally|for|function|if|implements|import|in|instanceof|interface|internal|is|native|new|null|package|private|protected|public|return|super|switch|this|throw|try|typeof|use|var|void|while|with|dynamic|each|final|get|include|namespace|native|override|set|static)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<>?>?|[!=]=?)=?|[~?@]/}),Prism.languages.actionscript["class-name"].alias="function",Prism.languages.markup&&Prism.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\\1|\\?(?!\1)[\s\S])*\2)*\s*\/?>/,lookbehind:!0,inside:{rest:Prism.languages.markup}}})},function(e,t){Prism.languages.aspnet=Prism.languages.extend("markup",{"page-directive tag":{pattern:/<%\s*@.*%>/i,inside:{"page-directive tag":/<%\s*@\s*(?:Assembly|Control|Implements|Import|Master(?:Type)?|OutputCache|Page|PreviousPageType|Reference|Register)?|%>/i,rest:Prism.languages.markup.tag.inside}},"directive tag":{pattern:/<%.*%>/i,inside:{"directive tag":/<%\s*?[$=%#:]{0,2}|%>/i,rest:Prism.languages.csharp}}}),Prism.languages.aspnet.tag.pattern=/<(?!%)\/?[^\s>\/]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\s\S])*\1|[^\s'">=]+))?)*\s*\/?>/i,Prism.languages.insertBefore("inside","punctuation",{"directive tag":Prism.languages.aspnet["directive tag"]},Prism.languages.aspnet.tag.inside["attr-value"]),Prism.languages.insertBefore("aspnet","comment",{"asp comment":/<%--[\s\S]*?--%>/}),Prism.languages.insertBefore("aspnet",Prism.languages.javascript?"script":"tag",{"asp script":{pattern:/()[\s\S]*?(?=<\/script>)/i,lookbehind:!0,inside:Prism.languages.csharp||{}}})},function(e,t){Prism.languages.basic={string:/"(?:""|[!#$%&'()*,\/:;<=>?^_ +\-.A-Z\d])*"/i,comment:{pattern:/(?:!|REM\b).+/i,inside:{keyword:/^REM/i}},number:/(?:\b|\B[.-])(?:\d+\.?\d*)(?:E[+-]?\d+)?/i,keyword:/\b(?:AS|BEEP|BLOAD|BSAVE|CALL(?: ABSOLUTE)?|CASE|CHAIN|CHDIR|CLEAR|CLOSE|CLS|COM|COMMON|CONST|DATA|DECLARE|DEF(?: FN| SEG|DBL|INT|LNG|SNG|STR)|DIM|DO|DOUBLE|ELSE|ELSEIF|END|ENVIRON|ERASE|ERROR|EXIT|FIELD|FILES|FOR|FUNCTION|GET|GOSUB|GOTO|IF|INPUT|INTEGER|IOCTL|KEY|KILL|LINE INPUT|LOCATE|LOCK|LONG|LOOP|LSET|MKDIR|NAME|NEXT|OFF|ON(?: COM| ERROR| KEY| TIMER)?|OPEN|OPTION BASE|OUT|POKE|PUT|READ|REDIM|REM|RESTORE|RESUME|RETURN|RMDIR|RSET|RUN|SHARED|SINGLE|SELECT CASE|SHELL|SLEEP|STATIC|STEP|STOP|STRING|SUB|SWAP|SYSTEM|THEN|TIMER|TO|TROFF|TRON|TYPE|UNLOCK|UNTIL|USING|VIEW PRINT|WAIT|WEND|WHILE|WRITE)(?:\$|\b)/i,function:/\b(?:ABS|ACCESS|ACOS|ANGLE|AREA|ARITHMETIC|ARRAY|ASIN|ASK|AT|ATN|BASE|BEGIN|BREAK|CAUSE|CEIL|CHR|CLIP|COLLATE|COLOR|CON|COS|COSH|COT|CSC|DATE|DATUM|DEBUG|DECIMAL|DEF|DEG|DEGREES|DELETE|DET|DEVICE|DISPLAY|DOT|ELAPSED|EPS|ERASABLE|EXLINE|EXP|EXTERNAL|EXTYPE|FILETYPE|FIXED|FP|GO|GRAPH|HANDLER|IDN|IMAGE|IN|INT|INTERNAL|IP|IS|KEYED|LBOUND|LCASE|LEFT|LEN|LENGTH|LET|LINE|LINES|LOG|LOG10|LOG2|LTRIM|MARGIN|MAT|MAX|MAXNUM|MID|MIN|MISSING|MOD|NATIVE|NUL|NUMERIC|OF|OPTION|ORD|ORGANIZATION|OUTIN|OUTPUT|PI|POINT|POINTER|POINTS|POS|PRINT|PROGRAM|PROMPT|RAD|RADIANS|RANDOMIZE|RECORD|RECSIZE|RECTYPE|RELATIVE|REMAINDER|REPEAT|REST|RETRY|REWRITE|RIGHT|RND|ROUND|RTRIM|SAME|SEC|SELECT|SEQUENTIAL|SET|SETTER|SGN|SIN|SINH|SIZE|SKIP|SQR|STANDARD|STATUS|STR|STREAM|STYLE|TAB|TAN|TANH|TEMPLATE|TEXT|THERE|TIME|TIMEOUT|TRACE|TRANSFORM|TRUNCATE|UBOUND|UCASE|USE|VAL|VARIABLE|VIEWPORT|WHEN|WINDOW|WITH|ZER|ZONEWIDTH)(?:\$|\b)/i,operator:/<[=>]?|>=?|[+\-*\/^=&]|\b(?:AND|EQV|IMP|NOT|OR|XOR)\b/i,punctuation:/[,;:()]/}},function(e,t){Prism.languages.c=Prism.languages.extend("clike",{keyword:/\b(_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/\-[>-]?|\+\+?|!=?|<>?=?|==?|&&?|\|?\||[~^%?*\/]/,number:/\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)[ful]*\b/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+([^\r\n\\]|\\.|\\(?:\r\n?|\n))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(<.+?>|("|')(\\?.)+?\3)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c["class-name"],delete Prism.languages.c.boolean},function(e,t){Prism.languages.pascal={comment:[/\(\*[\s\S]+?\*\)/,/\{[\s\S]+?\}/,/\/\/.*/],string:{pattern:/(?:'(?:''|[^'\r\n])*'|#[&$%]?[a-f\d]+)+|\^[a-z]/i,greedy:!0},keyword:[{pattern:/(^|[^&])\b(?:absolute|array|asm|begin|case|const|constructor|destructor|do|downto|else|end|file|for|function|goto|if|implementation|inherited|inline|interface|label|nil|object|of|operator|packed|procedure|program|record|reintroduce|repeat|self|set|string|then|to|type|unit|until|uses|var|while|with)\b/i,lookbehind:!0},{pattern:/(^|[^&])\b(?:dispose|exit|false|new|true)\b/i,lookbehind:!0},{pattern:/(^|[^&])\b(?:class|dispinterface|except|exports|finalization|finally|initialization|inline|library|on|out|packed|property|raise|resourcestring|threadvar|try)\b/i,lookbehind:!0},{pattern:/(^|[^&])\b(?:absolute|abstract|alias|assembler|bitpacked|break|cdecl|continue|cppdecl|cvar|default|deprecated|dynamic|enumerator|experimental|export|external|far|far16|forward|generic|helper|implements|index|interrupt|iochecks|local|message|name|near|nodefault|noreturn|nostackframe|oldfpccall|otherwise|overload|override|pascal|platform|private|protected|public|published|read|register|reintroduce|result|safecall|saveregisters|softfloat|specialize|static|stdcall|stored|strict|unaligned|unimplemented|varargs|virtual|write)\b/i,lookbehind:!0}],number:[/[+-]?(?:[&%]\d+|\$[a-f\d]+)/i,/([+-]|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?/i],operator:[/\.\.|\*\*|:=|<[<=>]?|>[>=]?|[+\-*\/]=?|[@^=]/i,{pattern:/(^|[^&])\b(?:and|as|div|exclude|in|include|is|mod|not|or|shl|shr|xor)\b/,lookbehind:!0}],punctuation:/\(\.|\.\)|[()\[\]:;,.]/}},function(e,t){Prism.languages.vim={string:/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\r\n]|'')*'/,comment:/".*/,function:/\w+(?=\()/,keyword:/\b(?:ab|abbreviate|abc|abclear|abo|aboveleft|al|all|arga|argadd|argd|argdelete|argdo|arge|argedit|argg|argglobal|argl|arglocal|ar|args|argu|argument|as|ascii|bad|badd|ba|ball|bd|bdelete|be|bel|belowright|bf|bfirst|bl|blast|bm|bmodified|bn|bnext|bN|bNext|bo|botright|bp|bprevious|brea|break|breaka|breakadd|breakd|breakdel|breakl|breaklist|br|brewind|bro|browse|bufdo|b|buffer|buffers|bun|bunload|bw|bwipeout|ca|cabbrev|cabc|cabclear|caddb|caddbuffer|cad|caddexpr|caddf|caddfile|cal|call|cat|catch|cb|cbuffer|cc|ccl|cclose|cd|ce|center|cex|cexpr|cf|cfile|cfir|cfirst|cgetb|cgetbuffer|cgete|cgetexpr|cg|cgetfile|c|change|changes|chd|chdir|che|checkpath|checkt|checktime|cla|clast|cl|clist|clo|close|cmapc|cmapclear|cnew|cnewer|cn|cnext|cN|cNext|cnf|cnfile|cNfcNfile|cnorea|cnoreabbrev|col|colder|colo|colorscheme|comc|comclear|comp|compiler|conf|confirm|con|continue|cope|copen|co|copy|cpf|cpfile|cp|cprevious|cq|cquit|cr|crewind|cuna|cunabbrev|cu|cunmap|cw|cwindow|debugg|debuggreedy|delc|delcommand|d|delete|delf|delfunction|delm|delmarks|diffg|diffget|diffoff|diffpatch|diffpu|diffput|diffsplit|diffthis|diffu|diffupdate|dig|digraphs|di|display|dj|djump|dl|dlist|dr|drop|ds|dsearch|dsp|dsplit|earlier|echoe|echoerr|echom|echomsg|echon|e|edit|el|else|elsei|elseif|em|emenu|endfo|endfor|endf|endfunction|endfun|en|endif|endt|endtry|endw|endwhile|ene|enew|ex|exi|exit|exu|exusage|f|file|files|filetype|fina|finally|fin|find|fini|finish|fir|first|fix|fixdel|fo|fold|foldc|foldclose|folddoc|folddoclosed|foldd|folddoopen|foldo|foldopen|for|fu|fun|function|go|goto|gr|grep|grepa|grepadd|ha|hardcopy|h|help|helpf|helpfind|helpg|helpgrep|helpt|helptags|hid|hide|his|history|ia|iabbrev|iabc|iabclear|if|ij|ijump|il|ilist|imapc|imapclear|in|inorea|inoreabbrev|isearch|isp|isplit|iuna|iunabbrev|iu|iunmap|j|join|ju|jumps|k|keepalt|keepj|keepjumps|kee|keepmarks|laddb|laddbuffer|lad|laddexpr|laddf|laddfile|lan|language|la|last|later|lb|lbuffer|lc|lcd|lch|lchdir|lcl|lclose|let|left|lefta|leftabove|lex|lexpr|lf|lfile|lfir|lfirst|lgetb|lgetbuffer|lgete|lgetexpr|lg|lgetfile|lgr|lgrep|lgrepa|lgrepadd|lh|lhelpgrep|l|list|ll|lla|llast|lli|llist|lmak|lmake|lm|lmap|lmapc|lmapclear|lnew|lnewer|lne|lnext|lN|lNext|lnf|lnfile|lNf|lNfile|ln|lnoremap|lo|loadview|loc|lockmarks|lockv|lockvar|lol|lolder|lop|lopen|lpf|lpfile|lp|lprevious|lr|lrewind|ls|lt|ltag|lu|lunmap|lv|lvimgrep|lvimgrepa|lvimgrepadd|lw|lwindow|mak|make|ma|mark|marks|mat|match|menut|menutranslate|mk|mkexrc|mks|mksession|mksp|mkspell|mkvie|mkview|mkv|mkvimrc|mod|mode|m|move|mzf|mzfile|mz|mzscheme|nbkey|new|n|next|N|Next|nmapc|nmapclear|noh|nohlsearch|norea|noreabbrev|nu|number|nun|nunmap|omapc|omapclear|on|only|o|open|opt|options|ou|ounmap|pc|pclose|ped|pedit|pe|perl|perld|perldo|po|pop|popu|popu|popup|pp|ppop|pre|preserve|prev|previous|p|print|P|Print|profd|profdel|prof|profile|promptf|promptfind|promptr|promptrepl|ps|psearch|pta|ptag|ptf|ptfirst|ptj|ptjump|ptl|ptlast|ptn|ptnext|ptN|ptNext|ptp|ptprevious|ptr|ptrewind|pts|ptselect|pu|put|pw|pwd|pyf|pyfile|py|python|qa|qall|q|quit|quita|quitall|r|read|rec|recover|redi|redir|red|redo|redr|redraw|redraws|redrawstatus|reg|registers|res|resize|ret|retab|retu|return|rew|rewind|ri|right|rightb|rightbelow|rub|ruby|rubyd|rubydo|rubyf|rubyfile|ru|runtime|rv|rviminfo|sal|sall|san|sandbox|sa|sargument|sav|saveas|sba|sball|sbf|sbfirst|sbl|sblast|sbm|sbmodified|sbn|sbnext|sbN|sbNext|sbp|sbprevious|sbr|sbrewind|sb|sbuffer|scripte|scriptencoding|scrip|scriptnames|se|set|setf|setfiletype|setg|setglobal|setl|setlocal|sf|sfind|sfir|sfirst|sh|shell|sign|sil|silent|sim|simalt|sla|slast|sl|sleep|sm|smagic|sm|smap|smapc|smapclear|sme|smenu|sn|snext|sN|sNext|sni|sniff|sno|snomagic|snor|snoremap|snoreme|snoremenu|sor|sort|so|source|spelld|spelldump|spe|spellgood|spelli|spellinfo|spellr|spellrepall|spellu|spellundo|spellw|spellwrong|sp|split|spr|sprevious|sre|srewind|sta|stag|startg|startgreplace|star|startinsert|startr|startreplace|stj|stjump|st|stop|stopi|stopinsert|sts|stselect|sun|sunhide|sunm|sunmap|sus|suspend|sv|sview|syncbind|t|tab|tabc|tabclose|tabd|tabdo|tabe|tabedit|tabf|tabfind|tabfir|tabfirst|tabl|tablast|tabm|tabmove|tabnew|tabn|tabnext|tabN|tabNext|tabo|tabonly|tabp|tabprevious|tabr|tabrewind|tabs|ta|tag|tags|tc|tcl|tcld|tcldo|tclf|tclfile|te|tearoff|tf|tfirst|th|throw|tj|tjump|tl|tlast|tm|tm|tmenu|tn|tnext|tN|tNext|to|topleft|tp|tprevious|tr|trewind|try|ts|tselect|tu|tu|tunmenu|una|unabbreviate|u|undo|undoj|undojoin|undol|undolist|unh|unhide|unlet|unlo|unlockvar|unm|unmap|up|update|verb|verbose|ve|version|vert|vertical|vie|view|vim|vimgrep|vimgrepa|vimgrepadd|vi|visual|viu|viusage|vmapc|vmapclear|vne|vnew|vs|vsplit|vu|vunmap|wa|wall|wh|while|winc|wincmd|windo|winp|winpos|win|winsize|wn|wnext|wN|wNext|wp|wprevious|wq|wqa|wqall|w|write|ws|wsverb|wv|wviminfo|X|xa|xall|x|xit|xm|xmap|xmapc|xmapclear|xme|xmenu|XMLent|XMLns|xn|xnoremap|xnoreme|xnoremenu|xu|xunmap|y|yank)\b/,builtin:/\b(?:autocmd|acd|ai|akm|aleph|allowrevins|altkeymap|ambiwidth|ambw|anti|antialias|arab|arabic|arabicshape|ari|arshape|autochdir|autoindent|autoread|autowrite|autowriteall|aw|awa|background|backspace|backup|backupcopy|backupdir|backupext|backupskip|balloondelay|ballooneval|balloonexpr|bdir|bdlay|beval|bex|bexpr|bg|bh|bin|binary|biosk|bioskey|bk|bkc|bomb|breakat|brk|browsedir|bs|bsdir|bsk|bt|bufhidden|buflisted|buftype|casemap|ccv|cdpath|cedit|cfu|ch|charconvert|ci|cin|cindent|cink|cinkeys|cino|cinoptions|cinw|cinwords|clipboard|cmdheight|cmdwinheight|cmp|cms|columns|com|comments|commentstring|compatible|complete|completefunc|completeopt|consk|conskey|copyindent|cot|cpo|cpoptions|cpt|cscopepathcomp|cscopeprg|cscopequickfix|cscopetag|cscopetagorder|cscopeverbose|cspc|csprg|csqf|cst|csto|csverb|cuc|cul|cursorcolumn|cursorline|cwh|debug|deco|def|define|delcombine|dex|dg|dict|dictionary|diff|diffexpr|diffopt|digraph|dip|dir|directory|dy|ea|ead|eadirection|eb|ed|edcompatible|ef|efm|ei|ek|enc|encoding|endofline|eol|ep|equalalways|equalprg|errorbells|errorfile|errorformat|esckeys|et|eventignore|expandtab|exrc|fcl|fcs|fdc|fde|fdi|fdl|fdls|fdm|fdn|fdo|fdt|fen|fenc|fencs|fex|ff|ffs|fileencoding|fileencodings|fileformat|fileformats|fillchars|fk|fkmap|flp|fml|fmr|foldcolumn|foldenable|foldexpr|foldignore|foldlevel|foldlevelstart|foldmarker|foldmethod|foldminlines|foldnestmax|foldtext|formatexpr|formatlistpat|formatoptions|formatprg|fp|fs|fsync|ft|gcr|gd|gdefault|gfm|gfn|gfs|gfw|ghr|gp|grepformat|grepprg|gtl|gtt|guicursor|guifont|guifontset|guifontwide|guiheadroom|guioptions|guipty|guitablabel|guitabtooltip|helpfile|helpheight|helplang|hf|hh|hi|hidden|highlight|hk|hkmap|hkmapp|hkp|hl|hlg|hls|hlsearch|ic|icon|iconstring|ignorecase|im|imactivatekey|imak|imc|imcmdline|imd|imdisable|imi|iminsert|ims|imsearch|inc|include|includeexpr|incsearch|inde|indentexpr|indentkeys|indk|inex|inf|infercase|insertmode|isf|isfname|isi|isident|isk|iskeyword|isprint|joinspaces|js|key|keymap|keymodel|keywordprg|km|kmp|kp|langmap|langmenu|laststatus|lazyredraw|lbr|lcs|linebreak|lines|linespace|lisp|lispwords|listchars|loadplugins|lpl|lsp|lz|macatsui|magic|makeef|makeprg|matchpairs|matchtime|maxcombine|maxfuncdepth|maxmapdepth|maxmem|maxmempattern|maxmemtot|mco|mef|menuitems|mfd|mh|mis|mkspellmem|ml|mls|mm|mmd|mmp|mmt|modeline|modelines|modifiable|modified|more|mouse|mousef|mousefocus|mousehide|mousem|mousemodel|mouses|mouseshape|mouset|mousetime|mp|mps|msm|mzq|mzquantum|nf|nrformats|numberwidth|nuw|odev|oft|ofu|omnifunc|opendevice|operatorfunc|opfunc|osfiletype|pa|para|paragraphs|paste|pastetoggle|patchexpr|patchmode|path|pdev|penc|pex|pexpr|pfn|ph|pheader|pi|pm|pmbcs|pmbfn|popt|preserveindent|previewheight|previewwindow|printdevice|printencoding|printexpr|printfont|printheader|printmbcharset|printmbfont|printoptions|prompt|pt|pumheight|pvh|pvw|qe|quoteescape|readonly|remap|report|restorescreen|revins|rightleft|rightleftcmd|rl|rlc|ro|rs|rtp|ruf|ruler|rulerformat|runtimepath|sbo|sc|scb|scr|scroll|scrollbind|scrolljump|scrolloff|scrollopt|scs|sect|sections|secure|sel|selection|selectmode|sessionoptions|sft|shcf|shellcmdflag|shellpipe|shellquote|shellredir|shellslash|shelltemp|shelltype|shellxquote|shiftround|shiftwidth|shm|shortmess|shortname|showbreak|showcmd|showfulltag|showmatch|showmode|showtabline|shq|si|sidescroll|sidescrolloff|siso|sj|slm|smartcase|smartindent|smarttab|smc|smd|softtabstop|sol|spc|spell|spellcapcheck|spellfile|spelllang|spellsuggest|spf|spl|splitbelow|splitright|sps|sr|srr|ss|ssl|ssop|stal|startofline|statusline|stl|stmp|su|sua|suffixes|suffixesadd|sw|swapfile|swapsync|swb|swf|switchbuf|sws|sxq|syn|synmaxcol|syntax|tabline|tabpagemax|tabstop|tagbsearch|taglength|tagrelative|tagstack|tal|tb|tbi|tbidi|tbis|tbs|tenc|term|termbidi|termencoding|terse|textauto|textmode|textwidth|tgst|thesaurus|tildeop|timeout|timeoutlen|title|titlelen|titleold|titlestring|toolbar|toolbariconsize|top|tpm|tsl|tsr|ttimeout|ttimeoutlen|ttm|tty|ttybuiltin|ttyfast|ttym|ttymouse|ttyscroll|ttytype|tw|tx|uc|ul|undolevels|updatecount|updatetime|ut|vb|vbs|vdir|verbosefile|vfile|viewdir|viewoptions|viminfo|virtualedit|visualbell|vop|wak|warn|wb|wc|wcm|wd|weirdinvert|wfh|wfw|whichwrap|wi|wig|wildchar|wildcharm|wildignore|wildmenu|wildmode|wildoptions|wim|winaltkeys|window|winfixheight|winfixwidth|winheight|winminheight|winminwidth|winwidth|wiv|wiw|wm|wmh|wmnu|wmw|wop|wrap|wrapmargin|wrapscan|writeany|writebackup|writedelay|ww|noacd|noai|noakm|noallowrevins|noaltkeymap|noanti|noantialias|noar|noarab|noarabic|noarabicshape|noari|noarshape|noautochdir|noautoindent|noautoread|noautowrite|noautowriteall|noaw|noawa|nobackup|noballooneval|nobeval|nobin|nobinary|nobiosk|nobioskey|nobk|nobl|nobomb|nobuflisted|nocf|noci|nocin|nocindent|nocompatible|noconfirm|noconsk|noconskey|nocopyindent|nocp|nocscopetag|nocscopeverbose|nocst|nocsverb|nocuc|nocul|nocursorcolumn|nocursorline|nodeco|nodelcombine|nodg|nodiff|nodigraph|nodisable|noea|noeb|noed|noedcompatible|noek|noendofline|noeol|noequalalways|noerrorbells|noesckeys|noet|noex|noexpandtab|noexrc|nofen|nofk|nofkmap|nofoldenable|nogd|nogdefault|noguipty|nohid|nohidden|nohk|nohkmap|nohkmapp|nohkp|nohls|noic|noicon|noignorecase|noim|noimc|noimcmdline|noimd|noincsearch|noinf|noinfercase|noinsertmode|nois|nojoinspaces|nojs|nolazyredraw|nolbr|nolinebreak|nolisp|nolist|noloadplugins|nolpl|nolz|noma|nomacatsui|nomagic|nomh|noml|nomod|nomodeline|nomodifiable|nomodified|nomore|nomousef|nomousefocus|nomousehide|nonu|nonumber|noodev|noopendevice|nopaste|nopi|nopreserveindent|nopreviewwindow|noprompt|nopvw|noreadonly|noremap|norestorescreen|norevins|nori|norightleft|norightleftcmd|norl|norlc|noro|nors|noru|noruler|nosb|nosc|noscb|noscrollbind|noscs|nosecure|nosft|noshellslash|noshelltemp|noshiftround|noshortname|noshowcmd|noshowfulltag|noshowmatch|noshowmode|nosi|nosm|nosmartcase|nosmartindent|nosmarttab|nosmd|nosn|nosol|nospell|nosplitbelow|nosplitright|nospr|nosr|nossl|nosta|nostartofline|nostmp|noswapfile|noswf|nota|notagbsearch|notagrelative|notagstack|notbi|notbidi|notbs|notermbidi|noterse|notextauto|notextmode|notf|notgst|notildeop|notimeout|notitle|noto|notop|notr|nottimeout|nottybuiltin|nottyfast|notx|novb|novisualbell|nowa|nowarn|nowb|noweirdinvert|nowfh|nowfw|nowildmenu|nowinfixheight|nowinfixwidth|nowiv|nowmnu|nowrap|nowrapscan|nowrite|nowriteany|nowritebackup|nows|invacd|invai|invakm|invallowrevins|invaltkeymap|invanti|invantialias|invar|invarab|invarabic|invarabicshape|invari|invarshape|invautochdir|invautoindent|invautoread|invautowrite|invautowriteall|invaw|invawa|invbackup|invballooneval|invbeval|invbin|invbinary|invbiosk|invbioskey|invbk|invbl|invbomb|invbuflisted|invcf|invci|invcin|invcindent|invcompatible|invconfirm|invconsk|invconskey|invcopyindent|invcp|invcscopetag|invcscopeverbose|invcst|invcsverb|invcuc|invcul|invcursorcolumn|invcursorline|invdeco|invdelcombine|invdg|invdiff|invdigraph|invdisable|invea|inveb|inved|invedcompatible|invek|invendofline|inveol|invequalalways|inverrorbells|invesckeys|invet|invex|invexpandtab|invexrc|invfen|invfk|invfkmap|invfoldenable|invgd|invgdefault|invguipty|invhid|invhidden|invhk|invhkmap|invhkmapp|invhkp|invhls|invhlsearch|invic|invicon|invignorecase|invim|invimc|invimcmdline|invimd|invincsearch|invinf|invinfercase|invinsertmode|invis|invjoinspaces|invjs|invlazyredraw|invlbr|invlinebreak|invlisp|invlist|invloadplugins|invlpl|invlz|invma|invmacatsui|invmagic|invmh|invml|invmod|invmodeline|invmodifiable|invmodified|invmore|invmousef|invmousefocus|invmousehide|invnu|invnumber|invodev|invopendevice|invpaste|invpi|invpreserveindent|invpreviewwindow|invprompt|invpvw|invreadonly|invremap|invrestorescreen|invrevins|invri|invrightleft|invrightleftcmd|invrl|invrlc|invro|invrs|invru|invruler|invsb|invsc|invscb|invscrollbind|invscs|invsecure|invsft|invshellslash|invshelltemp|invshiftround|invshortname|invshowcmd|invshowfulltag|invshowmatch|invshowmode|invsi|invsm|invsmartcase|invsmartindent|invsmarttab|invsmd|invsn|invsol|invspell|invsplitbelow|invsplitright|invspr|invsr|invssl|invsta|invstartofline|invstmp|invswapfile|invswf|invta|invtagbsearch|invtagrelative|invtagstack|invtbi|invtbidi|invtbs|invtermbidi|invterse|invtextauto|invtextmode|invtf|invtgst|invtildeop|invtimeout|invtitle|invto|invtop|invtr|invttimeout|invttybuiltin|invttyfast|invtx|invvb|invvisualbell|invwa|invwarn|invwb|invweirdinvert|invwfh|invwfw|invwildmenu|invwinfixheight|invwinfixwidth|invwiv|invwmnu|invwrap|invwrapscan|invwrite|invwriteany|invwritebackup|invws|t_AB|t_AF|t_al|t_AL|t_bc|t_cd|t_ce|t_Ce|t_cl|t_cm|t_Co|t_cs|t_Cs|t_CS|t_CV|t_da|t_db|t_dl|t_DL|t_EI|t_F1|t_F2|t_F3|t_F4|t_F5|t_F6|t_F7|t_F8|t_F9|t_fs|t_IE|t_IS|t_k1|t_K1|t_k2|t_k3|t_K3|t_k4|t_K4|t_k5|t_K5|t_k6|t_K6|t_k7|t_K7|t_k8|t_K8|t_k9|t_K9|t_KA|t_kb|t_kB|t_KB|t_KC|t_kd|t_kD|t_KD|t_ke|t_KE|t_KF|t_KG|t_kh|t_KH|t_kI|t_KI|t_KJ|t_KK|t_kl|t_KL|t_kN|t_kP|t_kr|t_ks|t_ku|t_le|t_mb|t_md|t_me|t_mr|t_ms|t_nd|t_op|t_RI|t_RV|t_Sb|t_se|t_Sf|t_SI|t_so|t_sr|t_te|t_ti|t_ts|t_ue|t_us|t_ut|t_vb|t_ve|t_vi|t_vs|t_WP|t_WS|t_xs|t_ZH|t_ZR)\b/, -number:/\b(?:0x[\da-f]+|\d+(?:\.\d+)?)\b/i,operator:/\|\||&&|[-+.]=?|[=!](?:[=~][#?]?)?|[<>]=?[#?]?|[*\/%?]|\b(?:is(?:not)?)\b/,punctuation:/[{}[\](),;:]/}},function(e,t){Prism.languages.swift=Prism.languages.extend("clike",{string:{pattern:/("|')(\\(?:\((?:[^()]|\([^)]+\))+\)|\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{interpolation:{pattern:/\\\((?:[^()]|\([^)]+\))+\)/,inside:{delimiter:{pattern:/^\\\(|\)$/,alias:"variable"}}}}},keyword:/\b(as|associativity|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic(?:Type)?|else|enum|extension|fallthrough|final|for|func|get|guard|if|import|in|infix|init|inout|internal|is|lazy|left|let|mutating|new|none|nonmutating|operator|optional|override|postfix|precedence|prefix|private|Protocol|public|repeat|required|rethrows|return|right|safe|self|Self|set|static|struct|subscript|super|switch|throws?|try|Type|typealias|unowned|unsafe|var|weak|where|while|willSet|__(?:COLUMN__|FILE__|FUNCTION__|LINE__))\b/,number:/\b([\d_]+(\.[\de_]+)?|0x[a-f0-9_]+(\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,constant:/\b(nil|[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,atrule:/@\b(IB(?:Outlet|Designable|Action|Inspectable)|class_protocol|exported|noreturn|NS(?:Copying|Managed)|objc|UIApplicationMain|auto_closure)\b/,builtin:/\b([A-Z]\S+|abs|advance|alignof(?:Value)?|assert|contains|count(?:Elements)?|debugPrint(?:ln)?|distance|drop(?:First|Last)|dump|enumerate|equal|filter|find|first|getVaList|indices|isEmpty|join|last|lexicographicalCompare|map|max(?:Element)?|min(?:Element)?|numericCast|overlaps|partition|print(?:ln)?|reduce|reflect|reverse|sizeof(?:Value)?|sort(?:ed)?|split|startsWith|stride(?:of(?:Value)?)?|suffix|swap|toDebugString|toString|transcode|underestimateCount|unsafeBitCast|with(?:ExtendedLifetime|Unsafe(?:MutablePointers?|Pointers?)|VaList))\b/}),Prism.languages.swift.string.inside.interpolation.inside.rest=Prism.util.clone(Prism.languages.swift)},function(e,t){Prism.languages.objectivec=Prism.languages.extend("c",{keyword:/\b(asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while|in|self|super)\b|(@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,string:/("|')(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|@"(\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,operator:/-[->]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/@]/})},function(e,t){Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},string:{pattern:/(^|[^@\\])("|')(?:\\?[\s\S])*?\2/,greedy:!0,lookbehind:!0},variable:/@[\w.$]+|@("|'|`)(?:\\?[\s\S])+?\1/,function:/\b(?:COUNT|SUM|AVG|MIN|MAX|FIRST|LAST|UCASE|LCASE|MID|LEN|ROUND|NOW|FORMAT)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR VARYING|CHARACTER (?:SET|VARYING)|CHARSET|CHECK|CHECKPOINT|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMN|COLUMNS|COMMENT|COMMIT|COMMITTED|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS|CONTAINSTABLE|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|DATA(?:BASES?)?|DATE(?:TIME)?|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITER(?:S)?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE(?: PRECISION)?|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE KEY|ELSE|ENABLE|ENCLOSED BY|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPE(?:D BY)?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTO|INVOKER|ISOLATION LEVEL|JOIN|KEYS?|KILL|LANGUAGE SQL|LAST|LEFT|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MODIFIES SQL DATA|MODIFY|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL(?: CHAR VARYING| CHARACTER(?: VARYING)?| VARCHAR)?|NATURAL|NCHAR(?: VARCHAR)?|NEXT|NO(?: SQL|CHECK|CYCLE)?|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READ(?:S SQL DATA|TEXT)?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEATABLE|REPLICATION|REQUIRE|RESTORE|RESTRICT|RETURNS?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE MODE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|START(?:ING BY)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED BY|TEXT(?:SIZE)?|THEN|TIMESTAMP|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNPIVOT|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?)\b/i,boolean:/\b(?:TRUE|FALSE|NULL)\b/i,number:/\b-?(?:0x)?\d*\.?[\da-f]+\b/,operator:/[-+*\/=%^~]|&&?|\|?\||!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|IN|LIKE|NOT|OR|IS|DIV|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}},function(e,t){Prism.languages.scheme={comment:/;.*/,string:{pattern:/"(?:[^"\\\r\n]|\\.)*?"|'[^('\s]*/,greedy:!0},keyword:{pattern:/(\()(?:define(?:-syntax|-library|-values)?|(?:case-)?lambda|let(?:\*|rec)?(?:-values)?|else|if|cond|begin|delay(?:-force)?|parameterize|guard|set!|(?:quasi-)?quote|syntax-rules)/,lookbehind:!0},builtin:{pattern:/(\()(?:(?:cons|car|cdr|list|call-with-current-continuation|call\/cc|append|abs|apply|eval)\b|null\?|pair\?|boolean\?|eof-object\?|char\?|procedure\?|number\?|port\?|string\?|vector\?|symbol\?|bytevector\?)/,lookbehind:!0},number:{pattern:/(\s|\))[-+]?\d*\.?\d+(?:\s*[-+]\s*\d*\.?\d+i)?\b/,lookbehind:!0},boolean:/#[tf]/,operator:{pattern:/(\()(?:[-+*%\/]|[<>]=?|=>?)/,lookbehind:!0},function:{pattern:/(\()[^\s()]*(?=\s)/,lookbehind:!0},punctuation:/[()]/}},function(e,t){!function(e){e.languages.ruby=e.languages.extend("clike",{comment:[/#(?!\{[^\r\n]*?\}).*/,/^=begin(?:\r?\n|\r)(?:.*(?:\r?\n|\r))*?=end/m],keyword:/\b(alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|false|for|if|in|module|new|next|nil|not|or|raise|redo|require|rescue|retry|return|self|super|then|throw|true|undef|unless|until|when|while|yield)\b/});var t={pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"tag"},rest:e.util.clone(e.languages.ruby)}};e.languages.insertBefore("ruby","keyword",{regex:[{pattern:/%r([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1[gim]{0,3}/,greedy:!0,inside:{interpolation:t}},{pattern:/%r\((?:[^()\\]|\\[\s\S])*\)[gim]{0,3}/,greedy:!0,inside:{interpolation:t}},{pattern:/%r\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}[gim]{0,3}/,greedy:!0,inside:{interpolation:t}},{pattern:/%r\[(?:[^\[\]\\]|\\[\s\S])*\][gim]{0,3}/,greedy:!0,inside:{interpolation:t}},{pattern:/%r<(?:[^<>\\]|\\[\s\S])*>[gim]{0,3}/,greedy:!0,inside:{interpolation:t}},{pattern:/(^|[^\/])\/(?!\/)(\[.+?]|\\.|[^\/\\\r\n])+\/[gim]{0,3}(?=\s*($|[\r\n,.;})]))/,lookbehind:!0,greedy:!0}],variable:/[@$]+[a-zA-Z_][a-zA-Z_0-9]*(?:[?!]|\b)/,symbol:/:[a-zA-Z_][a-zA-Z_0-9]*(?:[?!]|\b)/}),e.languages.insertBefore("ruby","number",{builtin:/\b(Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|File|Fixnum|Float|Hash|Integer|IO|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|String|Struct|TMS|Symbol|ThreadGroup|Thread|Time|TrueClass)\b/,constant:/\b[A-Z][a-zA-Z_0-9]*(?:[?!]|\b)/}),e.languages.ruby.string=[{pattern:/%[qQiIwWxs]?([^a-zA-Z0-9\s\{\(\[<])(?:[^\\]|\\[\s\S])*?\1/,greedy:!0,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?\((?:[^()\\]|\\[\s\S])*\)/,greedy:!0,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}/,greedy:!0,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?\[(?:[^\[\]\\]|\\[\s\S])*\]/,greedy:!0,inside:{interpolation:t}},{pattern:/%[qQiIwWxs]?<(?:[^<>\\]|\\[\s\S])*>/,greedy:!0,inside:{interpolation:t}},{pattern:/("|')(#\{[^}]+\}|\\(?:\r?\n|\r)|\\?.)*?\1/,greedy:!0,inside:{interpolation:t}}]}(Prism)},function(e,t){!function(e){var t=/\{\*[\s\S]+?\*\}|\{[\s\S]+?\}/g,n="{literal}",i="{/literal}",r=!1;e.languages.smarty=e.languages.extend("markup",{smarty:{pattern:t,inside:{delimiter:{pattern:/^\{|\}$/i,alias:"punctuation"},string:/(["'])(?:\\?.)*?\1/,number:/\b-?(?:0x[\dA-Fa-f]+|\d*\.?\d+(?:[Ee][-+]?\d+)?)\b/,variable:[/\$(?!\d)\w+/,/#(?!\d)\w+#/,{pattern:/(\.|->)(?!\d)\w+/,lookbehind:!0},{pattern:/(\[)(?!\d)\w+(?=\])/,lookbehind:!0}],function:[{pattern:/(\|\s*)@?(?!\d)\w+/,lookbehind:!0},/^\/?(?!\d)\w+/,/(?!\d)\w+(?=\()/],"attr-name":{pattern:/\w+\s*=\s*(?:(?!\d)\w+)?/,inside:{variable:{pattern:/(=\s*)(?!\d)\w+/,lookbehind:!0},operator:/=/}},punctuation:[/[\[\]().,:`]|\->/],operator:[/[+\-*\/%]|==?=?|[!<>]=?|&&|\|\|?/,/\bis\s+(?:not\s+)?(?:div|even|odd)(?:\s+by)?\b/,/\b(?:eq|neq?|gt|lt|gt?e|lt?e|not|mod|or|and)\b/],keyword:/\b(?:false|off|on|no|true|yes)\b/}}}),e.languages.insertBefore("smarty","tag",{"smarty-comment":{pattern:/\{\*[\s\S]*?\*\}/,alias:["smarty","comment"]}}),e.hooks.add("before-highlight",function(e){"smarty"===e.language&&(e.tokenStack=[],e.backupCode=e.code,e.code=e.code.replace(t,function(t){if(t===i&&(r=!1),!r){t===n&&(r=!0);for(var s=e.tokenStack.length;e.backupCode.indexOf("___SMARTY"+s+"___")!==-1;)++s;return e.tokenStack[s]=t,"___SMARTY"+s+"___"}return t}))}),e.hooks.add("before-insert",function(e){"smarty"===e.language&&(e.code=e.backupCode,delete e.backupCode)}),e.hooks.add("after-highlight",function(t){if("smarty"===t.language){for(var n=0,i=Object.keys(t.tokenStack);n=@%|&?!])\1?)|#(?=\()/i,"block-arguments":{pattern:/(\[\s*):[^\[|]*?\|/,lookbehind:!0,inside:{variable:/:[\da-z]+/i,punctuation:/\|/}},"temporary-variables":{pattern:/\|[^|]+\|/,inside:{variable:/[\da-z]+/i,punctuation:/\|/}},keyword:/\b(?:nil|true|false|self|super|new)\b/,character:{pattern:/\$./,alias:"string"},number:[/\d+r-?[\dA-Z]+(?:\.[\dA-Z]+)?(?:e-?\d+)?/,/(?:\B-|\b)\d+(?:\.\d+)?(?:e-?\d+)?/],operator:/[<=]=?|:=|~[~=]|\/\/?|\\\\|>[>=]?|[!^+\-*&|,@]/,punctuation:/[.;:?\[\](){}]/}},function(e,t){Prism.languages.rust={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:[{pattern:/b?r(#*)"(?:\\?.)*?"\1/,greedy:!0},{pattern:/b?("|')(?:\\?.)*?\1/,greedy:!0}],keyword:/\b(?:abstract|alignof|as|be|box|break|const|continue|crate|do|else|enum|extern|false|final|fn|for|if|impl|in|let|loop|match|mod|move|mut|offsetof|once|override|priv|pub|pure|ref|return|sizeof|static|self|struct|super|true|trait|type|typeof|unsafe|unsized|use|virtual|where|while|yield)\b/,attribute:{pattern:/#!?\[.+?\]/,greedy:!0,alias:"attr-name"},function:[/[a-z0-9_]+(?=\s*\()/i,/[a-z0-9_]+!(?=\s*\(|\[)/i],"macro-rules":{pattern:/[a-z0-9_]+!/i,alias:"function"},number:/\b-?(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(\d(_?\d)*)?\.?\d(_?\d)*([Ee][+-]?\d+)?)(?:_?(?:[iu](?:8|16|32|64)?|f32|f64))?\b/,"closure-params":{pattern:/\|[^|]*\|(?=\s*[{-])/,inside:{punctuation:/[\|:,]/,operator:/[&*]/}},punctuation:/[{}[\];(),:]|\.+|->/,operator:/[-+*\/%!^=]=?|@|&[&=]?|\|[|=]?|<>?=?/}},function(e,t){Prism.languages.r={comment:/#.*/,string:{pattern:/(['"])(?:\\?.)*?\1/,greedy:!0},"percent-operator":{pattern:/%[^%\s]*%/,alias:"operator"},boolean:/\b(?:TRUE|FALSE)\b/,ellipsis:/\.\.(?:\.|\d+)/,number:[/\b(?:NaN|Inf)\b/,/\b(?:0x[\dA-Fa-f]+(?:\.\d*)?|\d*\.?\d+)(?:[EePp][+-]?\d+)?[iL]?\b/],keyword:/\b(?:if|else|repeat|while|function|for|in|next|break|NULL|NA|NA_integer_|NA_real_|NA_complex_|NA_character_)\b/,operator:/->?>?|<(?:=|=!]=?|::?|&&?|\|\|?|[+*\/^$@~]/,punctuation:/[(){}\[\],;]/}},function(e,t){Prism.languages.d=Prism.languages.extend("clike",{string:[/\b[rx]"(\\.|[^\\"])*"[cwd]?/,/\bq"(?:\[[\s\S]*?\]|\([\s\S]*?\)|<[\s\S]*?>|\{[\s\S]*?\})"/,/\bq"([_a-zA-Z][_a-zA-Z\d]*)(?:\r?\n|\r)[\s\S]*?(?:\r?\n|\r)\1"/,/\bq"(.)[\s\S]*?\1"/,/'(?:\\'|\\?[^']+)'/,/(["`])(\\.|(?!\1)[^\\])*\1[cwd]?/],number:[/\b0x\.?[a-f\d_]+(?:(?!\.\.)\.[a-f\d_]*)?(?:p[+-]?[a-f\d_]+)?[ulfi]*/i,{pattern:/((?:\.\.)?)(?:\b0b\.?|\b|\.)\d[\d_]*(?:(?!\.\.)\.[\d_]*)?(?:e[+-]?\d[\d_]*)?[ulfi]*/i,lookbehind:!0}],keyword:/\$|\b(?:abstract|alias|align|asm|assert|auto|body|bool|break|byte|case|cast|catch|cdouble|cent|cfloat|char|class|const|continue|creal|dchar|debug|default|delegate|delete|deprecated|do|double|else|enum|export|extern|false|final|finally|float|for|foreach|foreach_reverse|function|goto|idouble|if|ifloat|immutable|import|inout|int|interface|invariant|ireal|lazy|long|macro|mixin|module|new|nothrow|null|out|override|package|pragma|private|protected|public|pure|real|ref|return|scope|shared|short|static|struct|super|switch|synchronized|template|this|throw|true|try|typedef|typeid|typeof|ubyte|ucent|uint|ulong|union|unittest|ushort|version|void|volatile|wchar|while|with|__(?:(?:FILE|MODULE|LINE|FUNCTION|PRETTY_FUNCTION|DATE|EOF|TIME|TIMESTAMP|VENDOR|VERSION)__|gshared|traits|vector|parameters)|string|wstring|dstring|size_t|ptrdiff_t)\b/,operator:/\|[|=]?|&[&=]?|\+[+=]?|-[-=]?|\.?\.\.|=[>=]?|!(?:i[ns]\b|<>?=?|>=?|=)?|\bi[ns]\b|(?:<[<>]?|>>?>?|\^\^|[*\/%^~])=?/}),Prism.languages.d.comment=[/^\s*#!.+/,{pattern:/(^|[^\\])\/\+(?:\/\+[\s\S]*?\+\/|[\s\S])*?\+\//,lookbehind:!0}].concat(Prism.languages.d.comment),Prism.languages.insertBefore("d","comment",{"token-string":{pattern:/\bq\{(?:|\{[^}]*\}|[^}])*\}/,alias:"string"}}),Prism.languages.insertBefore("d","keyword",{property:/\B@\w*/}),Prism.languages.insertBefore("d","function",{register:{pattern:/\b(?:[ABCD][LHX]|E[ABCD]X|E?(?:BP|SP|DI|SI)|[ECSDGF]S|CR[0234]|DR[012367]|TR[3-7]|X?MM[0-7]|R[ABCD]X|[BS]PL|R[BS]P|[DS]IL|R[DS]I|R(?:[89]|1[0-5])[BWD]?|XMM(?:[89]|1[0-5])|YMM(?:1[0-5]|\d))\b|\bST(?:\([0-7]\)|\b)/,alias:"variable"}})},function(e,t){Prism.languages.dart=Prism.languages.extend("clike",{string:[{pattern:/r?("""|''')[\s\S]*?\1/,greedy:!0},{pattern:/r?("|')(\\?.)*?\1/,greedy:!0}],keyword:[/\b(?:async|sync|yield)\*/,/\b(?:abstract|assert|async|await|break|case|catch|class|const|continue|default|deferred|do|dynamic|else|enum|export|external|extends|factory|final|finally|for|get|if|implements|import|in|library|new|null|operator|part|rethrow|return|set|static|super|switch|this|throw|try|typedef|var|void|while|with|yield)\b/],operator:/\bis!|\b(?:as|is)\b|\+\+|--|&&|\|\||<<=?|>>=?|~(?:\/=?)?|[+\-*\/%&^|=!<>]=?|\?/}),Prism.languages.insertBefore("dart","function",{metadata:{pattern:/@\w+/,alias:"symbol"}})},function(e,t){!function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\?[^\\])*?'/,greedy:!0},{pattern:/"(?:\\?[^\\])*?"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\?[\s\S])*?`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},rest:e.languages.javascript}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"]}(Prism)},function(e,t){!function(e){var t=/%%?[~:\w]+%?|!\S+!/,n={pattern:/\/[a-z?]+(?=[ :]|$):?|-[a-z]\b|--[a-z-]+\b/im,alias:"attr-name",inside:{punctuation:/:/}},i=/"[^"]*"/,r=/(?:\b|-)\d+\b/;e.languages.batch={comment:[/^::.*/m,{pattern:/((?:^|[&(])[ \t]*)rem\b(?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0}],label:{pattern:/^:.*/m,alias:"property"},command:[{pattern:/((?:^|[&(])[ \t]*)for(?: ?\/[a-z?](?:[ :](?:"[^"]*"|\S+))?)* \S+ in \([^)]+\) do/im,lookbehind:!0,inside:{keyword:/^for\b|\b(?:in|do)\b/i,string:i,parameter:n,variable:t,number:r,punctuation:/[()',]/}},{pattern:/((?:^|[&(])[ \t]*)if(?: ?\/[a-z?](?:[ :](?:"[^"]*"|\S+))?)* (?:not )?(?:cmdextversion \d+|defined \w+|errorlevel \d+|exist \S+|(?:"[^"]*"|\S+)?(?:==| (?:equ|neq|lss|leq|gtr|geq) )(?:"[^"]*"|\S+))/im,lookbehind:!0,inside:{keyword:/^if\b|\b(?:not|cmdextversion|defined|errorlevel|exist)\b/i,string:i,parameter:n,variable:t,number:r,operator:/\^|==|\b(?:equ|neq|lss|leq|gtr|geq)\b/i}},{pattern:/((?:^|[&()])[ \t]*)else\b/im,lookbehind:!0,inside:{keyword:/^else\b/i}},{pattern:/((?:^|[&(])[ \t]*)set(?: ?\/[a-z](?:[ :](?:"[^"]*"|\S+))?)* (?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0,inside:{keyword:/^set\b/i,string:i,parameter:n,variable:[t,/\w+(?=(?:[*\/%+\-&^|]|<<|>>)?=)/],number:r,operator:/[*\/%+\-&^|]=?|<<=?|>>=?|[!~_=]/,punctuation:/[()',]/}},{pattern:/((?:^|[&(])[ \t]*@?)\w+\b(?:[^^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0,inside:{keyword:/^\w+\b/i,string:i,parameter:n,label:{pattern:/(^\s*):\S+/m,lookbehind:!0,alias:"property"},variable:t,number:r,operator:/\^/}}],operator:/[&@]/,punctuation:/[()']/}}(Prism)},function(e,t){Prism.languages.cpp=Prism.languages.extend("c",{keyword:/\b(alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,boolean:/\b(true|false)\b/,operator:/[-+]{1,2}|!=?|<{1,2}=?|>{1,2}=?|\->|:{1,2}|={1,2}|\^|~|%|&{1,2}|\|?\||\?|\*|\/|\b(and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/}),Prism.languages.insertBefore("cpp","keyword",{"class-name":{pattern:/(class\s+)[a-z0-9_]+/i,lookbehind:!0}})},function(e,t){Prism.languages.lua={comment:/^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[\s\S]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,greedy:!0},number:/\b0x[a-f\d]+\.?[a-f\d]*(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|\.?\d*(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,keyword:/\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,function:/(?!\d)\w+(?=\s*(?:[({]))/,operator:[/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\.\.(?!\.)/,lookbehind:!0}],punctuation:/[\[\](){},;]|\.+|:+/}},function(e,t){Prism.languages.livescript={"interpolated-string":{pattern:/("""|")(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0,inside:{variable:{pattern:/(^|[^\\])#[a-z_](?:-?[a-z]|\d)*/m,lookbehind:!0},interpolation:{pattern:/(^|[^\\])#\{[^}]+\}/m,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^#\{|\}$/,alias:"variable"}}},string:/[\s\S]+/}},comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0}],string:[{pattern:/('''|')(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},{pattern:/<\[[\s\S]*?\]>/,greedy:!0},/\\[^\s,;\])}]+/],regex:[{pattern:/\/\/(\[.+?]|\\.|(?!\/\/)[^\\])+\/\/[gimyu]{0,5}/,greedy:!0,inside:{comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0}}},{pattern:/\/(\[.+?]|\\.|[^\/\\\r\n])+\/[gimyu]{0,5}/,greedy:!0}],keyword:{pattern:/(^|(?!-).)\b(?:break|case|catch|class|const|continue|default|do|else|extends|fallthrough|finally|for(?: ever)?|function|if|implements|it|let|loop|new|null|otherwise|own|return|super|switch|that|then|this|throw|try|unless|until|var|void|when|while|yield)(?!-)\b/m,lookbehind:!0},"keyword-operator":{pattern:/(^|[^-])\b(?:(?:delete|require|typeof)!|(?:and|by|delete|export|from|import(?: all)?|in|instanceof|is(?:nt| not)?|not|of|or|til|to|typeof|with|xor)(?!-)\b)/m,lookbehind:!0,alias:"operator"},boolean:{pattern:/(^|[^-])\b(?:false|no|off|on|true|yes)(?!-)\b/m,lookbehind:!0},argument:{pattern:/(^|(?!\.&\.)[^&])&(?!&)\d*/m,lookbehind:!0,alias:"variable"},number:/\b(?:\d+~[\da-z]+|\d[\d_]*(?:\.\d[\d_]*)?(?:[a-z]\w*)?)/i,identifier:/[a-z_](?:-?[a-z]|\d)*/i,operator:[{pattern:/( )\.(?= )/,lookbehind:!0},/\.(?:[=~]|\.\.?)|\.(?:[&|^]|<<|>>>?)\.|:(?:=|:=?)|&&|\|[|>]|<(?:<[>=?]?|-(?:->?|>)?|\+\+?|@@?|%%?|\*\*?|!(?:~?=|--?>|~?~>)?|~(?:~?>|=)?|==?|\^\^?|[\/?]/],punctuation:/[(){}\[\]|.,:;`]/},Prism.languages.livescript["interpolated-string"].inside.interpolation.inside.rest=Prism.languages.livescript},function(e,t){!function(e){var t=/\\([^a-z()[\]]|[a-z\*]+)/i,n={"equation-command":{pattern:t,alias:"regex"}};e.languages.latex={comment:/%.*/m,cdata:{pattern:/(\\begin\{((?:verbatim|lstlisting)\*?)\})([\s\S]*?)(?=\\end\{\2\})/,lookbehind:!0},equation:[{pattern:/\$(?:\\?[\s\S])*?\$|\\\((?:\\?[\s\S])*?\\\)|\\\[(?:\\?[\s\S])*?\\\]/,inside:n,alias:"string"},{pattern:/(\\begin\{((?:equation|math|eqnarray|align|multline|gather)\*?)\})([\s\S]*?)(?=\\end\{\2\})/,lookbehind:!0,inside:n,alias:"string"}],keyword:{pattern:/(\\(?:begin|end|ref|cite|label|usepackage|documentclass)(?:\[[^\]]+\])?\{)[^}]+(?=\})/,lookbehind:!0},url:{pattern:/(\\url\{)[^}]+(?=\})/,lookbehind:!0},headline:{pattern:/(\\(?:part|chapter|section|subsection|frametitle|subsubsection|paragraph|subparagraph|subsubparagraph|subsubsubparagraph)\*?(?:\[[^\]]+\])?\{)[^}]+(?=\}(?:\[[^\]]+\])?)/,lookbehind:!0,alias:"class-name"},function:{pattern:t,alias:"selector"},punctuation:/[[\]{}&]/}}(Prism)},function(e,t){Prism.languages.groovy=Prism.languages.extend("clike",{keyword:/\b(as|def|in|abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|strictfp|super|switch|synchronized|this|throw|throws|trait|transient|try|void|volatile|while)\b/,string:[{pattern:/("""|''')[\s\S]*?\1|(\$\/)(\$\/\$|[\s\S])*?\/\$/,greedy:!0},{pattern:/("|'|\/)(?:\\?.)*?\1/,greedy:!0}],number:/\b(?:0b[01_]+|0x[\da-f_]+(?:\.[\da-f_p\-]+)?|[\d_]+(?:\.[\d_]+)?(?:e[+-]?[\d]+)?)[glidf]?\b/i,operator:{pattern:/(^|[^.])(~|==?~?|\?[.:]?|\*(?:[.=]|\*=?)?|\.[@&]|\.\.<|\.{1,2}(?!\.)|-[-=>]?|\+[+=]?|!=?|<(?:<=?|=>?)?|>(?:>>?=?|=)?|&[&=]?|\|[|=]?|\/=?|\^=?|%=?)/,lookbehind:!0},punctuation:/\.+|[{}[\];(),:$]/}),Prism.languages.insertBefore("groovy","string",{shebang:{pattern:/#!.+/,alias:"comment"}}),Prism.languages.insertBefore("groovy","punctuation",{"spock-block":/\b(setup|given|when|then|and|cleanup|expect|where):/}),Prism.languages.insertBefore("groovy","function",{annotation:{alias:"punctuation",pattern:/(^|[^.])@\w+/,lookbehind:!0}}),Prism.hooks.add("wrap",function(e){if("groovy"===e.language&&"string"===e.type){var t=e.content[0];if("'"!=t){var n=/([^\\])(\$(\{.*?\}|[\w\.]+))/;"$"===t&&(n=/([^\$])(\$(\{.*?\}|[\w\.]+))/),e.content=e.content.replace(/</g,"<").replace(/&/g,"&"),e.content=Prism.highlight(e.content,{expression:{pattern:n,lookbehind:!0,inside:Prism.languages.groovy}}),e.classes.push("/"===t?"regex":"gstring")}}})},function(e,t){Prism.languages.graphql={comment:/#.*/,string:{pattern:/"(?:\\.|[^\\"])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:[eE][+-]?\d+)?\b/,boolean:/\b(?:true|false)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":/[a-z_]\w*(?=\s*:)/i,keyword:[{pattern:/(fragment\s+(?!on)[a-z_]\w*\s+|\.\.\.\s*)on\b/,lookbehind:!0},/\b(?:query|fragment|mutation)\b/],operator:/!|=|\.{3}/,punctuation:/[!(){}\[\]:=,]/}},function(e,t){Prism.languages.nginx=Prism.languages.extend("clike",{comment:{pattern:/(^|[^"{\\])#.*/,lookbehind:!0},keyword:/\b(?:CONTENT_|DOCUMENT_|GATEWAY_|HTTP_|HTTPS|if_not_empty|PATH_|QUERY_|REDIRECT_|REMOTE_|REQUEST_|SCGI|SCRIPT_|SERVER_|http|server|events|location|include|accept_mutex|accept_mutex_delay|access_log|add_after_body|add_before_body|add_header|addition_types|aio|alias|allow|ancient_browser|ancient_browser_value|auth|auth_basic|auth_basic_user_file|auth_http|auth_http_header|auth_http_timeout|autoindex|autoindex_exact_size|autoindex_localtime|break|charset|charset_map|charset_types|chunked_transfer_encoding|client_body_buffer_size|client_body_in_file_only|client_body_in_single_buffer|client_body_temp_path|client_body_timeout|client_header_buffer_size|client_header_timeout|client_max_body_size|connection_pool_size|create_full_put_path|daemon|dav_access|dav_methods|debug_connection|debug_points|default_type|deny|devpoll_changes|devpoll_events|directio|directio_alignment|disable_symlinks|empty_gif|env|epoll_events|error_log|error_page|expires|fastcgi_buffer_size|fastcgi_buffers|fastcgi_busy_buffers_size|fastcgi_cache|fastcgi_cache_bypass|fastcgi_cache_key|fastcgi_cache_lock|fastcgi_cache_lock_timeout|fastcgi_cache_methods|fastcgi_cache_min_uses|fastcgi_cache_path|fastcgi_cache_purge|fastcgi_cache_use_stale|fastcgi_cache_valid|fastcgi_connect_timeout|fastcgi_hide_header|fastcgi_ignore_client_abort|fastcgi_ignore_headers|fastcgi_index|fastcgi_intercept_errors|fastcgi_keep_conn|fastcgi_max_temp_file_size|fastcgi_next_upstream|fastcgi_no_cache|fastcgi_param|fastcgi_pass|fastcgi_pass_header|fastcgi_read_timeout|fastcgi_redirect_errors|fastcgi_send_timeout|fastcgi_split_path_info|fastcgi_store|fastcgi_store_access|fastcgi_temp_file_write_size|fastcgi_temp_path|flv|geo|geoip_city|geoip_country|google_perftools_profiles|gzip|gzip_buffers|gzip_comp_level|gzip_disable|gzip_http_version|gzip_min_length|gzip_proxied|gzip_static|gzip_types|gzip_vary|if|if_modified_since|ignore_invalid_headers|image_filter|image_filter_buffer|image_filter_jpeg_quality|image_filter_sharpen|image_filter_transparency|imap_capabilities|imap_client_buffer|include|index|internal|ip_hash|keepalive|keepalive_disable|keepalive_requests|keepalive_timeout|kqueue_changes|kqueue_events|large_client_header_buffers|limit_conn|limit_conn_log_level|limit_conn_zone|limit_except|limit_rate|limit_rate_after|limit_req|limit_req_log_level|limit_req_zone|limit_zone|lingering_close|lingering_time|lingering_timeout|listen|location|lock_file|log_format|log_format_combined|log_not_found|log_subrequest|map|map_hash_bucket_size|map_hash_max_size|master_process|max_ranges|memcached_buffer_size|memcached_connect_timeout|memcached_next_upstream|memcached_pass|memcached_read_timeout|memcached_send_timeout|merge_slashes|min_delete_depth|modern_browser|modern_browser_value|mp4|mp4_buffer_size|mp4_max_buffer_size|msie_padding|msie_refresh|multi_accept|open_file_cache|open_file_cache_errors|open_file_cache_min_uses|open_file_cache_valid|open_log_file_cache|optimize_server_names|override_charset|pcre_jit|perl|perl_modules|perl_require|perl_set|pid|pop3_auth|pop3_capabilities|port_in_redirect|post_action|postpone_output|protocol|proxy|proxy_buffer|proxy_buffer_size|proxy_buffering|proxy_buffers|proxy_busy_buffers_size|proxy_cache|proxy_cache_bypass|proxy_cache_key|proxy_cache_lock|proxy_cache_lock_timeout|proxy_cache_methods|proxy_cache_min_uses|proxy_cache_path|proxy_cache_use_stale|proxy_cache_valid|proxy_connect_timeout|proxy_cookie_domain|proxy_cookie_path|proxy_headers_hash_bucket_size|proxy_headers_hash_max_size|proxy_hide_header|proxy_http_version|proxy_ignore_client_abort|proxy_ignore_headers|proxy_intercept_errors|proxy_max_temp_file_size|proxy_method|proxy_next_upstream|proxy_no_cache|proxy_pass|proxy_pass_error_message|proxy_pass_header|proxy_pass_request_body|proxy_pass_request_headers|proxy_read_timeout|proxy_redirect|proxy_redirect_errors|proxy_send_lowat|proxy_send_timeout|proxy_set_body|proxy_set_header|proxy_ssl_session_reuse|proxy_store|proxy_store_access|proxy_temp_file_write_size|proxy_temp_path|proxy_timeout|proxy_upstream_fail_timeout|proxy_upstream_max_fails|random_index|read_ahead|real_ip_header|recursive_error_pages|request_pool_size|reset_timedout_connection|resolver|resolver_timeout|return|rewrite|root|rtsig_overflow_events|rtsig_overflow_test|rtsig_overflow_threshold|rtsig_signo|satisfy|satisfy_any|secure_link_secret|send_lowat|send_timeout|sendfile|sendfile_max_chunk|server|server_name|server_name_in_redirect|server_names_hash_bucket_size|server_names_hash_max_size|server_tokens|set|set_real_ip_from|smtp_auth|smtp_capabilities|so_keepalive|source_charset|split_clients|ssi|ssi_silent_errors|ssi_types|ssi_value_length|ssl|ssl_certificate|ssl_certificate_key|ssl_ciphers|ssl_client_certificate|ssl_crl|ssl_dhparam|ssl_engine|ssl_prefer_server_ciphers|ssl_protocols|ssl_session_cache|ssl_session_timeout|ssl_verify_client|ssl_verify_depth|starttls|stub_status|sub_filter|sub_filter_once|sub_filter_types|tcp_nodelay|tcp_nopush|timeout|timer_resolution|try_files|types|types_hash_bucket_size|types_hash_max_size|underscores_in_headers|uninitialized_variable_warn|upstream|use|user|userid|userid_domain|userid_expires|userid_name|userid_p3p|userid_path|userid_service|valid_referers|variables_hash_bucket_size|variables_hash_max_size|worker_connections|worker_cpu_affinity|worker_priority|worker_processes|worker_rlimit_core|worker_rlimit_nofile|worker_rlimit_sigpending|working_directory|xclient|xml_entities|xslt_entities|xslt_stylesheet|xslt_types)\b/i}),Prism.languages.insertBefore("nginx","keyword",{variable:/\$[a-z_]+/i})},function(e,t){Prism.languages.erlang={comment:/%.+/,string:{pattern:/"(?:\\?.)*?"/,greedy:!0},"quoted-function":{pattern:/'(?:\\.|[^'\\])+'(?=\()/,alias:"function"},"quoted-atom":{pattern:/'(?:\\.|[^'\\])+'/,alias:"atom"},boolean:/\b(?:true|false)\b/,keyword:/\b(?:fun|when|case|of|end|if|receive|after|try|catch)\b/,number:[/\$\\?./,/\d+#[a-z0-9]+/i,/(?:\b|-)\d*\.?\d+([Ee][+-]?\d+)?\b/],function:/\b[a-z][\w@]*(?=\()/,variable:{pattern:/(^|[^@])(?:\b|\?)[A-Z_][\w@]*/,lookbehind:!0},operator:[/[=\/<>:]=|=[:\/]=|\+\+?|--?|[=*\/!]|\b(?:bnot|div|rem|band|bor|bxor|bsl|bsr|not|and|or|xor|orelse|andalso)\b/,{pattern:/(^|[^<])<(?!<)/,lookbehind:!0},{pattern:/(^|[^>])>(?!>)/,lookbehind:!0}],atom:/\b[a-z][\w@]*/,punctuation:/[()[\]{}:;,.#|]|<<|>>/}},function(e,t){Prism.languages.powershell={comment:[{pattern:/(^|[^`])<#[\s\S]*?#>/,lookbehind:!0},{pattern:/(^|[^`])#.*/,lookbehind:!0}],string:[{pattern:/"(`?[\s\S])*?"/,greedy:!0,inside:{function:{pattern:/[^`]\$\(.*?\)/,inside:{}}}},{pattern:/'([^']|'')*'/,greedy:!0}],namespace:/\[[a-z][\s\S]*?\]/i,boolean:/\$(true|false)\b/i,variable:/\$\w+\b/i,function:[/\b(Add-(Computer|Content|History|Member|PSSnapin|Type)|Checkpoint-Computer|Clear-(Content|EventLog|History|Item|ItemProperty|Variable)|Compare-Object|Complete-Transaction|Connect-PSSession|ConvertFrom-(Csv|Json|StringData)|Convert-Path|ConvertTo-(Csv|Html|Json|Xml)|Copy-(Item|ItemProperty)|Debug-Process|Disable-(ComputerRestore|PSBreakpoint|PSRemoting|PSSessionConfiguration)|Disconnect-PSSession|Enable-(ComputerRestore|PSBreakpoint|PSRemoting|PSSessionConfiguration)|Enter-PSSession|Exit-PSSession|Export-(Alias|Clixml|Console|Csv|FormatData|ModuleMember|PSSession)|ForEach-Object|Format-(Custom|List|Table|Wide)|Get-(Alias|ChildItem|Command|ComputerRestorePoint|Content|ControlPanelItem|Culture|Date|Event|EventLog|EventSubscriber|FormatData|Help|History|Host|HotFix|Item|ItemProperty|Job|Location|Member|Module|Process|PSBreakpoint|PSCallStack|PSDrive|PSProvider|PSSession|PSSessionConfiguration|PSSnapin|Random|Service|TraceSource|Transaction|TypeData|UICulture|Unique|Variable|WmiObject)|Group-Object|Import-(Alias|Clixml|Csv|LocalizedData|Module|PSSession)|Invoke-(Command|Expression|History|Item|RestMethod|WebRequest|WmiMethod)|Join-Path|Limit-EventLog|Measure-(Command|Object)|Move-(Item|ItemProperty)|New-(Alias|Event|EventLog|Item|ItemProperty|Module|ModuleManifest|Object|PSDrive|PSSession|PSSessionConfigurationFile|PSSessionOption|PSTransportOption|Service|TimeSpan|Variable|WebServiceProxy)|Out-(Default|File|GridView|Host|Null|Printer|String)|Pop-Location|Push-Location|Read-Host|Receive-(Job|PSSession)|Register-(EngineEvent|ObjectEvent|PSSessionConfiguration|WmiEvent)|Remove-(Computer|Event|EventLog|Item|ItemProperty|Job|Module|PSBreakpoint|PSDrive|PSSession|PSSnapin|TypeData|Variable|WmiObject)|Rename-(Computer|Item|ItemProperty)|Reset-ComputerMachinePassword|Resolve-Path|Restart-(Computer|Service)|Restore-Computer|Resume-(Job|Service)|Save-Help|Select-(Object|String|Xml)|Send-MailMessage|Set-(Alias|Content|Date|Item|ItemProperty|Location|PSBreakpoint|PSDebug|PSSessionConfiguration|Service|StrictMode|TraceSource|Variable|WmiInstance)|Show-(Command|ControlPanelItem|EventLog)|Sort-Object|Split-Path|Start-(Job|Process|Service|Sleep|Transaction)|Stop-(Computer|Job|Process|Service)|Suspend-(Job|Service)|Tee-Object|Test-(ComputerSecureChannel|Connection|ModuleManifest|Path|PSSessionConfigurationFile)|Trace-Command|Unblock-File|Undo-Transaction|Unregister-(Event|PSSessionConfiguration)|Update-(FormatData|Help|List|TypeData)|Use-Transaction|Wait-(Event|Job|Process)|Where-Object|Write-(Debug|Error|EventLog|Host|Output|Progress|Verbose|Warning))\b/i,/\b(ac|cat|chdir|clc|cli|clp|clv|compare|copy|cp|cpi|cpp|cvpa|dbp|del|diff|dir|ebp|echo|epal|epcsv|epsn|erase|fc|fl|ft|fw|gal|gbp|gc|gci|gcs|gdr|gi|gl|gm|gp|gps|group|gsv|gu|gv|gwmi|iex|ii|ipal|ipcsv|ipsn|irm|iwmi|iwr|kill|lp|ls|measure|mi|mount|move|mp|mv|nal|ndr|ni|nv|ogv|popd|ps|pushd|pwd|rbp|rd|rdr|ren|ri|rm|rmdir|rni|rnp|rp|rv|rvpa|rwmi|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls|sort|sp|spps|spsv|start|sv|swmi|tee|trcm|type|write)\b/i], -keyword:/\b(Begin|Break|Catch|Class|Continue|Data|Define|Do|DynamicParam|Else|ElseIf|End|Exit|Filter|Finally|For|ForEach|From|Function|If|InlineScript|Parallel|Param|Process|Return|Sequence|Switch|Throw|Trap|Try|Until|Using|Var|While|Workflow)\b/i,operator:{pattern:/(\W?)(!|-(eq|ne|gt|ge|lt|le|sh[lr]|not|b?(and|x?or)|(Not)?(Like|Match|Contains|In)|Replace|Join|is(Not)?|as)\b|-[-=]?|\+[+=]?|[*\/%]=?)/i,lookbehind:!0},punctuation:/[|{}[\];(),.]/},Prism.languages.powershell.string[0].inside.boolean=Prism.languages.powershell.boolean,Prism.languages.powershell.string[0].inside.variable=Prism.languages.powershell.variable,Prism.languages.powershell.string[0].inside.function.inside=Prism.util.clone(Prism.languages.powershell)},function(e,t){Prism.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|.)*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},builtin:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,symbol:{pattern:/^[^:=\r\n]+(?=\s*:(?!=))/m,inside:{variable:/\$+(?:[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:[/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,{pattern:/(\()(?:addsuffix|abspath|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:s|list)?)(?=[ \t])/,lookbehind:!0}],operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/}},function(e,t){Prism.languages.markdown=Prism.languages.extend("markup",{}),Prism.languages.insertBefore("markdown","prolog",{blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},code:[{pattern:/^(?: {4}|\t).+/m,alias:"keyword"},{pattern:/``.+?``|`[^`\n]+`/,alias:"keyword"}],title:[{pattern:/\w+.*(?:\r?\n|\r)(?:==+|--+)/,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#+.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])([\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:/(^|[^\\])(\*\*|__)(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^\*\*|^__|\*\*$|__$/}},italic:{pattern:/(^|[^\\])([*_])(?:(?:\r?\n|\r)(?!\r?\n|\r)|.)+?\2/,lookbehind:!0,inside:{punctuation:/^[*_]|[*_]$/}},url:{pattern:/!?\[[^\]]+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)| ?\[[^\]\n]*\])/,inside:{variable:{pattern:/(!?\[)[^\]]+(?=\]$)/,lookbehind:!0},string:{pattern:/"(?:\\.|[^"\\])*"(?=\)$)/}}}}),Prism.languages.markdown.bold.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.italic.inside.url=Prism.util.clone(Prism.languages.markdown.url),Prism.languages.markdown.bold.inside.italic=Prism.util.clone(Prism.languages.markdown.italic),Prism.languages.markdown.italic.inside.bold=Prism.util.clone(Prism.languages.markdown.bold)},function(e,t){},,,,,,,function(e,t){},function(e,t){},function(e,t){},,function(e,t){e.exports='
    \n
    \n \n
    \n
    \n \n \n \n
    \n
    '}]); -//# sourceMappingURL=mditor.min.js.map \ No newline at end of file diff --git a/pywebio/output.py b/pywebio/output.py index 8a82d6e9..779b6dff 100644 --- a/pywebio/output.py +++ b/pywebio/output.py @@ -353,14 +353,16 @@ def put_code(content, language='', scope=Scope.Current, position=OutputPosition. return put_markdown(code, scope=scope, position=position) -def put_markdown(mdcontent, strip_indent=0, lstrip=False, scope=Scope.Current, - position=OutputPosition.BOTTOM) -> Output: +def put_markdown(mdcontent, strip_indent=0, lstrip=False, options=None, + scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output: """ 输出Markdown内容。 :param str mdcontent: Markdown文本 :param int strip_indent: 对于每一行,若前 ``strip_indent`` 个字符都为空格,则将其去除 :param bool lstrip: 是否去除每一行开始的空白符 + :param dict options: 解析Markdown时的配置参数。 + PyWebIO使用 `marked `_ 解析Markdown, 可配置项参见: https://marked.js.org/using_advanced#options (仅支持配置string和boolean类型的项) :param int scope, position: 与 `put_text` 函数的同名参数含义一致 当在函数中使用Python的三引号语法输出多行内容时,为了排版美观可能会对Markdown文本进行缩进, @@ -394,7 +396,7 @@ def hello(): lines = (i.lstrip() for i in mdcontent.splitlines()) mdcontent = '\n'.join(lines) - spec = _get_output_spec('markdown', content=mdcontent, scope=scope, position=position) + spec = _get_output_spec('markdown', content=mdcontent, options=options, scope=scope, position=position) return Output(spec) diff --git a/setup.py b/setup.py index 94ddac61..e01d7ccf 100644 --- a/setup.py +++ b/setup.py @@ -45,12 +45,12 @@ "html/codemirror/loadmode.js", "html/codemirror/python.js", "html/css/bootstrap.min.css", - "html/css/mditor.min.css", + "html/css/markdown.min.css", "html/css/toastify.min.css", "html/css/app.css", "html/css/codemirror.min.css", "html/js/FileSaver.min.js", - "html/js/mditor.min.js", + "html/js/highlight.min.js", "html/js/pywebio.min.js", "html/js/mustache.min.js", "html/js/jquery.min.js", diff --git a/webiojs/gulpfile.js b/webiojs/gulpfile.js index dc471178..3beaf438 100644 --- a/webiojs/gulpfile.js +++ b/webiojs/gulpfile.js @@ -4,7 +4,7 @@ var source = require('vinyl-source-stream'); var tsify = require('tsify'); var sourcemaps = require('gulp-sourcemaps'); var buffer = require('vinyl-buffer'); -var uglify = require('gulp-uglify'); +var uglify = require('gulp-uglify-es').default; gulp.task('default', function () { diff --git a/webiojs/package-lock.json b/webiojs/package-lock.json index 88bd0553..e0c20d2f 100644 --- a/webiojs/package-lock.json +++ b/webiojs/package-lock.json @@ -50,6 +50,12 @@ "@types/sizzle": "*" } }, + "@types/marked": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/marked/-/marked-1.2.2.tgz", + "integrity": "sha512-wLfw1hnuuDYrFz97IzJja0pdVsC0oedtS4QsKH1/inyW9qkLQbXgMUqEQT0MVtUBx3twjWeInUfjQbhBVLECXw==", + "dev": true + }, "@types/sizzle": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", @@ -2565,6 +2571,19 @@ "vinyl-sourcemaps-apply": "^0.2.0" } }, + "gulp-uglify-es": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/gulp-uglify-es/-/gulp-uglify-es-2.0.0.tgz", + "integrity": "sha512-00KkawzjWdjPo1YfD1FXKijVxZkyr6YSwJ2cJQgD1fNKFZCFPNjGc5sTyzyW8tZns8FmZafgHMrg7LUDNvIQ5A==", + "dev": true, + "requires": { + "o-stream": "^0.2.2", + "plugin-error": "^1.0.1", + "terser": "^4.3.9", + "vinyl": "^2.2.0", + "vinyl-sourcemaps-apply": "^0.2.1" + } + }, "gulplog": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", @@ -2679,6 +2698,12 @@ "minimalistic-assert": "^1.0.1" } }, + "highlight.js": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.5.0.tgz", + "integrity": "sha512-xTmvd9HiIHR6L53TMC7TKolEj65zG1XU+Onr8oi86mYa+nLcIbxTTWkpW7CsEwv/vK7u1zb8alZIMLDqqN6KTw==", + "dev": true + }, "hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", @@ -3226,6 +3251,12 @@ "object-visit": "^1.0.0" } }, + "marked": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/marked/-/marked-1.2.8.tgz", + "integrity": "sha512-lzmFjGnzWHkmbk85q/ILZjFoHHJIQGF+SxGEfIdGk/XhiTPhqGs37gbru6Kkd48diJnEyYwnG67nru0Z2gQtuQ==", + "dev": true + }, "matchdep": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", @@ -3493,6 +3524,12 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, + "o-stream": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/o-stream/-/o-stream-0.2.2.tgz", + "integrity": "sha512-V3j76KU3g/Gyl8rpdi2z72rn5zguMvTCQgAXfBe3pxEefKqXmOUOD7mvx/mNjykdxGqDVfpSoo8r+WdrkWg/1Q==", + "dev": true + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -4671,6 +4708,35 @@ "acorn-node": "^1.2.0" } }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + } + } + }, "through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", diff --git a/webiojs/package.json b/webiojs/package.json index 6f2c1624..31324ed6 100644 --- a/webiojs/package.json +++ b/webiojs/package.json @@ -10,6 +10,7 @@ "license": "ISC", "devDependencies": { "@types/jquery": "^3.3.38", + "@types/marked": "^1.2.2", "babel-core": "^6.26.3", "babel-preset-es2015": "^6.24.1", "babelify": "^8.0.0", @@ -19,6 +20,9 @@ "gulp-sourcemaps": "^2.6.5", "gulp-typescript": "^6.0.0-alpha.1", "gulp-uglify": "^3.0.2", + "gulp-uglify-es": "^2.0.0", + "highlight.js": "^10.5.0", + "marked": "^1.2.8", "tsify": "^4.0.1", "typescript": "^3.8.3", "vinyl-buffer": "^1.0.1", diff --git a/webiojs/src/models/output.ts b/webiojs/src/models/output.ts index 7922d55f..0b92fce6 100644 --- a/webiojs/src/models/output.ts +++ b/webiojs/src/models/output.ts @@ -1,5 +1,8 @@ import {b64toBlob} from "../utils"; - +// const marked = require('marked'); +// import {marked} from "../js/mdparser"; +// import 'marked'; +import * as marked from 'marked'; /* * 当前限制 * 若Widget被作为其他Widget的子项时,该Widget中绑定的事件将会失效 @@ -25,11 +28,26 @@ let Text = { } }; -let _md_parser = new Mditor.Parser(); +marked.setOptions({ + breaks: true, //可行尾不加两空格直接换行 + smartLists: true, + smartypants: false, + mangle: false, + highlight: function (code, language) { + try{ + const validLanguage = hljs.getLanguage(language) ? language : 'plaintext'; + return hljs.highlight(validLanguage, code).value; + }catch (e) { + return code + } + }, +}); + let Markdown = { handle_type: 'markdown', get_element: function (spec: any) { - return $(_md_parser.parse(spec.content)); + // https://marked.js.org/using_advanced#options + return $(marked(spec.content, spec.options)); } }; diff --git a/webiojs/src/vendor.d.ts b/webiojs/src/vendor.d.ts index f76387c2..5b1b7ef6 100644 --- a/webiojs/src/vendor.d.ts +++ b/webiojs/src/vendor.d.ts @@ -1,7 +1,7 @@ // declare var $: any; -declare let Mditor: any; declare let Mustache: any; declare let saveAs: any; declare let CodeMirror: any; declare let bsCustomFileInput: any; -declare let Toastify:any; \ No newline at end of file +declare let Toastify: any; +declare let hljs: any; // highlight.js \ No newline at end of file From 8cc00908583aad19f767819842e7f0fb536b10e0 Mon Sep 17 00:00:00 2001 From: wangweimin Date: Wed, 3 Feb 2021 15:32:22 +0800 Subject: [PATCH 016/445] maint: change md highlight engine to Prism --- pywebio/html/css/markdown.min.css | 9 +- pywebio/html/index.html | 2 +- pywebio/html/js/highlight.min.js | 1296 ----------------------------- pywebio/html/js/prism.min.js | 42 + setup.py | 2 +- webiojs/src/models/output.ts | 21 +- webiojs/src/vendor.d.ts | 2 +- 7 files changed, 62 insertions(+), 1312 deletions(-) delete mode 100644 pywebio/html/js/highlight.min.js create mode 100644 pywebio/html/js/prism.min.js diff --git a/pywebio/html/css/markdown.min.css b/pywebio/html/css/markdown.min.css index 2c51f175..5be26bec 100644 --- a/pywebio/html/css/markdown.min.css +++ b/pywebio/html/css/markdown.min.css @@ -4,9 +4,10 @@ * https://github.com/sindresorhus/github-markdown-css */ .markdown-body .octicon{display:inline-block;fill:currentColor;vertical-align:text-bottom}.markdown-body .anchor{float:left;line-height:1;margin-left:-20px;padding-right:4px}.markdown-body .anchor:focus{outline:0}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#1b1f23;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1:hover .anchor .octicon-link:before,.markdown-body h2:hover .anchor .octicon-link:before,.markdown-body h3:hover .anchor .octicon-link:before,.markdown-body h4:hover .anchor .octicon-link:before,.markdown-body h5:hover .anchor .octicon-link:before,.markdown-body h6:hover .anchor .octicon-link:before{width:16px;height:16px;content:' ';display:inline-block;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' version='1.1' width='16' height='16' aria-hidden='true'%3E%3Cpath fill-rule='evenodd' d='M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z'%3E%3C/path%3E%3C/svg%3E")}.markdown-body{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;line-height:1.5;color:#24292e;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;font-size:16px;line-height:1.5;word-wrap:break-word}.markdown-body details{display:block}.markdown-body summary{display:list-item}.markdown-body a{background-color:initial}.markdown-body a:active,.markdown-body a:hover{outline-width:0}.markdown-body strong{font-weight:inherit;font-weight:bolder}.markdown-body h1{font-size:2em;margin:.67em 0}.markdown-body img{border-style:none}.markdown-body code,.markdown-body kbd,.markdown-body pre{font-family:monospace,monospace;font-size:1em}.markdown-body hr{box-sizing:initial;height:0;overflow:visible}.markdown-body input{font:inherit;margin:0}.markdown-body input{overflow:visible}.markdown-body [type=checkbox]{box-sizing:border-box;padding:0}.markdown-body *{box-sizing:border-box}.markdown-body input{font-family:inherit;font-size:inherit;line-height:inherit}.markdown-body a{color:#0366d6;text-decoration:none}.markdown-body a:hover{text-decoration:underline}.markdown-body strong{font-weight:600}.markdown-body hr{height:0;margin:15px 0;overflow:hidden;background:0 0;border:0;border-bottom:1px solid #dfe2e5}.markdown-body hr:after,.markdown-body hr:before{display:table;content:""}.markdown-body hr:after{clear:both}.markdown-body table{border-spacing:0;border-collapse:collapse}.markdown-body td,.markdown-body th{padding:0}.markdown-body details summary{cursor:pointer}.markdown-body kbd{display:inline-block;padding:3px 5px;font:11px SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:1px solid #d1d5da;border-radius:3px;box-shadow:inset 0 -1px 0 #d1d5da}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:0;margin-bottom:0}.markdown-body h1{font-size:32px}.markdown-body h1,.markdown-body h2{font-weight:600}.markdown-body h2{font-size:24px}.markdown-body h3{font-size:20px}.markdown-body h3,.markdown-body h4{font-weight:600}.markdown-body h4{font-size:16px}.markdown-body h5{font-size:14px}.markdown-body h5,.markdown-body h6{font-weight:600}.markdown-body h6{font-size:12px}.markdown-body p{margin-top:0;margin-bottom:10px}.markdown-body blockquote{margin:0}.markdown-body ol,.markdown-body ul{padding-left:0;margin-top:0;margin-bottom:0}.markdown-body ol ol,.markdown-body ul ol{list-style-type:lower-roman}.markdown-body ol ol ol,.markdown-body ol ul ol,.markdown-body ul ol ol,.markdown-body ul ul ol{list-style-type:lower-alpha}.markdown-body dd{margin-left:0}.markdown-body code,.markdown-body pre{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:12px}.markdown-body pre{margin-top:0;margin-bottom:0}.markdown-body input::-webkit-inner-spin-button,.markdown-body input::-webkit-outer-spin-button{margin:0;-webkit-appearance:none;appearance:none}.markdown-body :checked+.radio-label{position:relative;z-index:1;border-color:#0366d6}.markdown-body .border{border:1px solid #e1e4e8!important}.markdown-body .border-0{border:0!important}.markdown-body .border-bottom{border-bottom:1px solid #e1e4e8!important}.markdown-body .rounded-1{border-radius:3px!important}.markdown-body .bg-white{background-color:#fff!important}.markdown-body .bg-gray-light{background-color:#fafbfc!important}.markdown-body .text-gray-light{color:#6a737d!important}.markdown-body .mb-0{margin-bottom:0!important}.markdown-body .my-2{margin-top:8px!important;margin-bottom:8px!important}.markdown-body .pl-0{padding-left:0!important}.markdown-body .py-0{padding-top:0!important;padding-bottom:0!important}.markdown-body .pl-1{padding-left:4px!important}.markdown-body .pl-2{padding-left:8px!important}.markdown-body .py-2{padding-top:8px!important;padding-bottom:8px!important}.markdown-body .pl-3,.markdown-body .px-3{padding-left:16px!important}.markdown-body .px-3{padding-right:16px!important}.markdown-body .pl-4{padding-left:24px!important}.markdown-body .pl-5{padding-left:32px!important}.markdown-body .pl-6{padding-left:40px!important}.markdown-body .f6{font-size:12px!important}.markdown-body .lh-condensed{line-height:1.25!important}.markdown-body .text-bold{font-weight:600!important}.markdown-body .pl-c{color:#6a737d}.markdown-body .pl-c1,.markdown-body .pl-s .pl-v{color:#005cc5}.markdown-body .pl-e,.markdown-body .pl-en{color:#6f42c1}.markdown-body .pl-s .pl-s1,.markdown-body .pl-smi{color:#24292e}.markdown-body .pl-ent{color:#22863a}.markdown-body .pl-k{color:#d73a49}.markdown-body .pl-pds,.markdown-body .pl-s,.markdown-body .pl-s .pl-pse .pl-s1,.markdown-body .pl-sr,.markdown-body .pl-sr .pl-cce,.markdown-body .pl-sr .pl-sra,.markdown-body .pl-sr .pl-sre{color:#032f62}.markdown-body .pl-smw,.markdown-body .pl-v{color:#e36209}.markdown-body .pl-bu{color:#b31d28}.markdown-body .pl-ii{color:#fafbfc;background-color:#b31d28}.markdown-body .pl-c2{color:#fafbfc;background-color:#d73a49}.markdown-body .pl-c2:before{content:"^M"}.markdown-body .pl-sr .pl-cce{font-weight:700;color:#22863a}.markdown-body .pl-ml{color:#735c0f}.markdown-body .pl-mh,.markdown-body .pl-mh .pl-en,.markdown-body .pl-ms{font-weight:700;color:#005cc5}.markdown-body .pl-mi{font-style:italic;color:#24292e}.markdown-body .pl-mb{font-weight:700;color:#24292e}.markdown-body .pl-md{color:#b31d28;background-color:#ffeef0}.markdown-body .pl-mi1{color:#22863a;background-color:#f0fff4}.markdown-body .pl-mc{color:#e36209;background-color:#ffebda}.markdown-body .pl-mi2{color:#f6f8fa;background-color:#005cc5}.markdown-body .pl-mdr{font-weight:700;color:#6f42c1}.markdown-body .pl-ba{color:#586069}.markdown-body .pl-sg{color:#959da5}.markdown-body .pl-corl{text-decoration:underline;color:#032f62}.markdown-body .mb-0{margin-bottom:0!important}.markdown-body .my-2{margin-bottom:8px!important}.markdown-body .my-2{margin-top:8px!important}.markdown-body .pl-0{padding-left:0!important}.markdown-body .py-0{padding-top:0!important;padding-bottom:0!important}.markdown-body .pl-1{padding-left:4px!important}.markdown-body .pl-2{padding-left:8px!important}.markdown-body .py-2{padding-top:8px!important;padding-bottom:8px!important}.markdown-body .pl-3{padding-left:16px!important}.markdown-body .pl-4{padding-left:24px!important}.markdown-body .pl-5{padding-left:32px!important}.markdown-body .pl-6{padding-left:40px!important}.markdown-body .pl-7{padding-left:48px!important}.markdown-body .pl-8{padding-left:64px!important}.markdown-body .pl-9{padding-left:80px!important}.markdown-body .pl-10{padding-left:96px!important}.markdown-body .pl-11{padding-left:112px!important}.markdown-body .pl-12{padding-left:128px!important}.markdown-body hr{border-bottom-color:#eee}.markdown-body kbd{display:inline-block;padding:3px 5px;font:11px SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;line-height:10px;color:#444d56;vertical-align:middle;background-color:#fafbfc;border:1px solid #d1d5da;border-radius:3px;box-shadow:inset 0 -1px 0 #d1d5da}.markdown-body:after,.markdown-body:before{display:table;content:""}.markdown-body:after{clear:both}.markdown-body>:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body blockquote,.markdown-body details,.markdown-body dl,.markdown-body ol,.markdown-body p,.markdown-body pre,.markdown-body table,.markdown-body ul{margin-top:0;margin-bottom:16px}.markdown-body hr{height:.25em;padding:0;margin:24px 0;background-color:#e1e4e8;border:0}.markdown-body blockquote{padding:0 1em;color:#6a737d;border-left:.25em solid #dfe2e5}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{margin-top:24px;margin-bottom:16px;font-weight:600;line-height:1.25}.markdown-body h1{font-size:2em}.markdown-body h1,.markdown-body h2{padding-bottom:.3em;border-bottom:1px solid #eaecef}.markdown-body h2{font-size:1.5em}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{font-size:.85em;color:#6a737d}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-top:0;margin-bottom:0}.markdown-body li{word-wrap:break-all}.markdown-body li>p{margin-top:16px}.markdown-body li+li{margin-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{padding:0;margin-top:16px;font-size:1em;font-style:italic;font-weight:600}.markdown-body dl dd{padding:0 16px;margin-bottom:16px}.markdown-body table{display:block;width:100%;overflow:auto}.markdown-body table th{font-weight:600}.markdown-body table td,.markdown-body table th{padding:6px 13px;border:1px solid #dfe2e5}.markdown-body table tr{background-color:#fff;border-top:1px solid #c6cbd1}.markdown-body table tr:nth-child(2n){background-color:#f6f8fa}.markdown-body img{max-width:100%;box-sizing:initial;background-color:#fff}.markdown-body img[align=right]{padding-left:20px}.markdown-body img[align=left]{padding-right:20px}.markdown-body code{padding:.2em .4em;margin:0;font-size:85%;background-color:rgba(27,31,35,.05);border-radius:3px}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{padding:0;margin:0;font-size:100%;word-break:normal;white-space:pre;background:0 0;border:0}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{padding:16px;overflow:auto;font-size:85%;line-height:1.45;background-color:#f6f8fa;border-radius:3px}.markdown-body pre code{display:inline;max-width:auto;padding:0;margin:0;overflow:visible;line-height:inherit;word-wrap:normal;background-color:initial;border:0}.markdown-body .commit-tease-sha{display:inline-block;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:90%;color:#444d56}.markdown-body .full-commit .btn-outline:not(:disabled):hover{color:#005cc5;border-color:#005cc5}.markdown-body .blob-wrapper{overflow-x:auto;overflow-y:hidden}.markdown-body .blob-wrapper-embedded{max-height:240px;overflow-y:auto}.markdown-body .blob-num{width:1%;min-width:50px;padding-right:10px;padding-left:10px;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:12px;line-height:20px;color:rgba(27,31,35,.3);text-align:right;white-space:nowrap;vertical-align:top;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.markdown-body .blob-num:hover{color:rgba(27,31,35,.6)}.markdown-body .blob-num:before{content:attr(data-line-number)}.markdown-body .blob-code{position:relative;padding-right:10px;padding-left:10px;line-height:20px;vertical-align:top}.markdown-body .blob-code-inner{overflow:visible;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:12px;color:#24292e;word-wrap:normal;white-space:pre}.markdown-body .pl-token.active,.markdown-body .pl-token:hover{cursor:pointer;background:#ffea7f}.markdown-body .tab-size[data-tab-size="1"]{-moz-tab-size:1;tab-size:1}.markdown-body .tab-size[data-tab-size="2"]{-moz-tab-size:2;tab-size:2}.markdown-body .tab-size[data-tab-size="3"]{-moz-tab-size:3;tab-size:3}.markdown-body .tab-size[data-tab-size="4"]{-moz-tab-size:4;tab-size:4}.markdown-body .tab-size[data-tab-size="5"]{-moz-tab-size:5;tab-size:5}.markdown-body .tab-size[data-tab-size="6"]{-moz-tab-size:6;tab-size:6}.markdown-body .tab-size[data-tab-size="7"]{-moz-tab-size:7;tab-size:7}.markdown-body .tab-size[data-tab-size="8"]{-moz-tab-size:8;tab-size:8}.markdown-body .tab-size[data-tab-size="9"]{-moz-tab-size:9;tab-size:9}.markdown-body .tab-size[data-tab-size="10"]{-moz-tab-size:10;tab-size:10}.markdown-body .tab-size[data-tab-size="11"]{-moz-tab-size:11;tab-size:11}.markdown-body .tab-size[data-tab-size="12"]{-moz-tab-size:12;tab-size:12}.markdown-body .task-list-item{list-style-type:none}.markdown-body .task-list-item+.task-list-item{margin-top:3px}.markdown-body .task-list-item input{margin:0 .2em .25em -1.6em;vertical-align:middle} + /** - * highlight.js github theme + * prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou (MIT Licensed) */ -code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal} -.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} -.hljs{display:block;background:#fff;padding:.5em;color:#333;overflow-x:auto}.hljs-comment,.hljs-meta{color:#969896}.hljs-emphasis,.hljs-quote,.hljs-strong,.hljs-template-variable,.hljs-variable{color:#df5000}.hljs-keyword,.hljs-selector-tag,.hljs-type{color:#d73a49}.hljs-attribute,.hljs-bullet,.hljs-literal,.hljs-symbol{color:#0086b3}.hljs-name,.hljs-section{color:#63a35c}.hljs-tag{color:#333}.hljs-attr,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-selector-pseudo,.hljs-title{color:#6f42c1}.hljs-addition{color:#55a532;background-color:#eaffea}.hljs-deletion{color:#bd2c00;background-color:#ffecec}.hljs-link{text-decoration:underline}.hljs-number{color:#005cc5}.hljs-string{color:#032f62} \ No newline at end of file +code[class*=language-],pre[class*=language-]{color:#000;background:0 0;text-shadow:0 1px #fff;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:#b3d4fc}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:#b3d4fc}@media print{code[class*=language-],pre[class*=language-]{text-shadow:none}}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#f5f2f0}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal} .token.cdata,.token.comment,.token.doctype,.token.prolog{color:#708090}.token.punctuation{color:#999}.token.namespace{opacity:.7}.token.boolean,.token.constant,.token.deleted,.token.number,.token.property,.token.symbol,.token.tag{color:#905}.token.attr-name,.token.builtin,.token.char,.token.inserted,.token.selector,.token.string{color:#690}.language-css .token.string,.style .token.string,.token.entity,.token.operator,.token.url{color:#9a6e3a;background:hsla(0,0%,100%,.5)}.token.atrule,.token.attr-value,.token.keyword{color:#07a}.token.class-name,.token.function{color:#dd4a68}.token.important,.token.regex,.token.variable{color:#e90}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help} \ No newline at end of file diff --git a/pywebio/html/index.html b/pywebio/html/index.html index 8e047d1d..a06e5899 100644 --- a/pywebio/html/index.html +++ b/pywebio/html/index.html @@ -39,7 +39,7 @@ - + diff --git a/pywebio/html/js/highlight.min.js b/pywebio/html/js/highlight.min.js deleted file mode 100644 index 532ae2a2..00000000 --- a/pywebio/html/js/highlight.min.js +++ /dev/null @@ -1,1296 +0,0 @@ -/* - Highlight.js 10.5.0 (af20048d) - License: BSD-3-Clause - Copyright (c) 2006-2020, Ivan Sagalaev -*/ -var hljs=function(){"use strict";function e(t){ -return t instanceof Map?t.clear=t.delete=t.set=()=>{ -throw Error("map is read-only")}:t instanceof Set&&(t.add=t.clear=t.delete=()=>{ -throw Error("set is read-only") -}),Object.freeze(t),Object.getOwnPropertyNames(t).forEach((n=>{var s=t[n] -;"object"!=typeof s||Object.isFrozen(s)||e(s)})),t}var t=e,n=e;t.default=n -;class s{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data} -ignoreMatch(){this.ignore=!0}}function r(e){ -return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") -}function a(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] -;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const i=e=>!!e.kind -;class o{constructor(e,t){ -this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ -this.buffer+=r(e)}openNode(e){if(!i(e))return;let t=e.kind -;e.sublanguage||(t=`${this.classPrefix}${t}`),this.span(t)}closeNode(e){ -i(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ -this.buffer+=``}}class l{constructor(){this.rootNode={ -children:[]},this.stack=[this.rootNode]}get top(){ -return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ -this.top.children.push(e)}openNode(e){const t={kind:e,children:[]} -;this.add(t),this.stack.push(t)}closeNode(){ -if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ -for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} -walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ -return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), -t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ -"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ -l._collapse(e)})))}}class c extends l{constructor(e){super(),this.options=e} -addKeyword(e,t){""!==e&&(this.openNode(t),this.addText(e),this.closeNode())} -addText(e){""!==e&&this.add(e)}addSublanguage(e,t){const n=e.root -;n.kind=t,n.sublanguage=!0,this.add(n)}toHTML(){ -return new o(this,this.options).value()}finalize(){return!0}}function u(e){ -return e?"string"==typeof e?e:e.source:null} -const g="[a-zA-Z]\\w*",d="[a-zA-Z_]\\w*",h="\\b\\d+(\\.\\d+)?",f="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",p="\\b(0b[01]+)",m={ -begin:"\\\\[\\s\\S]",relevance:0},b={className:"string",begin:"'",end:"'", -illegal:"\\n",contains:[m]},x={className:"string",begin:'"',end:'"', -illegal:"\\n",contains:[m]},E={ -begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ -},v=(e,t,n={})=>{const s=a({className:"comment",begin:e,end:t,contains:[]},n) -;return s.contains.push(E),s.contains.push({className:"doctag", -begin:"(?:TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):",relevance:0}),s -},N=v("//","$"),w=v("/\\*","\\*/"),R=v("#","$");var y=Object.freeze({ -__proto__:null,IDENT_RE:g,UNDERSCORE_IDENT_RE:d,NUMBER_RE:h,C_NUMBER_RE:f, -BINARY_NUMBER_RE:p, -RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", -SHEBANG:(e={})=>{const t=/^#![ ]*\// -;return e.binary&&(e.begin=((...e)=>e.map((e=>u(e))).join(""))(t,/.*\b/,e.binary,/\b.*/)), -a({className:"meta",begin:t,end:/$/,relevance:0,"on:begin":(e,t)=>{ -0!==e.index&&t.ignoreMatch()}},e)},BACKSLASH_ESCAPE:m,APOS_STRING_MODE:b, -QUOTE_STRING_MODE:x,PHRASAL_WORDS_MODE:E,COMMENT:v,C_LINE_COMMENT_MODE:N, -C_BLOCK_COMMENT_MODE:w,HASH_COMMENT_MODE:R,NUMBER_MODE:{className:"number", -begin:h,relevance:0},C_NUMBER_MODE:{className:"number",begin:f,relevance:0}, -BINARY_NUMBER_MODE:{className:"number",begin:p,relevance:0},CSS_NUMBER_MODE:{ -className:"number", -begin:h+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?", -relevance:0},REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{className:"regexp", -begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[m,{begin:/\[/,end:/\]/, -relevance:0,contains:[m]}]}]},TITLE_MODE:{className:"title",begin:g,relevance:0 -},UNDERSCORE_TITLE_MODE:{className:"title",begin:d,relevance:0},METHOD_GUARD:{ -begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:e=>Object.assign(e,{ -"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{ -t.data._beginMatch!==e[1]&&t.ignoreMatch()}})});function _(e,t){ -"."===e.input[e.index-1]&&t.ignoreMatch()}function k(e,t){ -t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", -e.__beforeBegin=_,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords) -}function M(e,t){ -Array.isArray(e.illegal)&&(e.illegal=((...e)=>"("+e.map((e=>u(e))).join("|")+")")(...e.illegal)) -}function O(e,t){if(e.match){ -if(e.begin||e.end)throw Error("begin & end are not supported with match") -;e.begin=e.match,delete e.match}}function A(e,t){ -void 0===e.relevance&&(e.relevance=1)} -const L=["of","and","for","in","not","or","if","then","parent","list","value"] -;function B(e,t){return t?Number(t):(e=>L.includes(e.toLowerCase()))(e)?0:1} -function I(e,{plugins:t}){function n(t,n){ -return RegExp(u(t),"m"+(e.case_insensitive?"i":"")+(n?"g":""))}class s{ -constructor(){ -this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} -addRule(e,t){ -t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), -this.matchAt+=(e=>RegExp(e.toString()+"|").exec("").length-1)(e)+1}compile(){ -0===this.regexes.length&&(this.exec=()=>null) -;const e=this.regexes.map((e=>e[1]));this.matcherRe=n(((e,t="|")=>{ -const n=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;let s=0,r="" -;for(let a=0;a0&&(r+=t),r+="(";o.length>0;){const e=n.exec(o);if(null==e){r+=o;break} -r+=o.substring(0,e.index), -o=o.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?r+="\\"+(Number(e[1])+i):(r+=e[0], -"("===e[0]&&s++)}r+=")"}return r})(e),!0),this.lastIndex=0}exec(e){ -this.matcherRe.lastIndex=this.lastIndex;const t=this.matcherRe.exec(e) -;if(!t)return null -;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),s=this.matchIndexes[n] -;return t.splice(0,n),Object.assign(t,s)}}class r{constructor(){ -this.rules=[],this.multiRegexes=[], -this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ -if(this.multiRegexes[e])return this.multiRegexes[e];const t=new s -;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), -t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ -return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ -this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ -const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex -;let n=t.exec(e) -;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ -const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} -return n&&(this.regexIndex+=n.position+1, -this.regexIndex===this.count&&this.considerAll()),n}} -if(e.compilerExtensions||(e.compilerExtensions=[]), -e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") -;return e.classNameAliases=a(e.classNameAliases||{}),function t(s,i){const o=s -;if(s.compiled)return o -;[O].forEach((e=>e(s,i))),e.compilerExtensions.forEach((e=>e(s,i))), -s.__beforeBegin=null,[k,M,A].forEach((e=>e(s,i))),s.compiled=!0;let l=null -;if("object"==typeof s.keywords&&(l=s.keywords.$pattern, -delete s.keywords.$pattern),s.keywords&&(s.keywords=((e,t)=>{const n={} -;return"string"==typeof e?s("keyword",e):Object.keys(e).forEach((t=>{s(t,e[t]) -})),n;function s(e,s){t&&(s=s.toLowerCase()),s.split(" ").forEach((t=>{ -const s=t.split("|");n[s[0]]=[e,B(s[0],s[1])]}))} -})(s.keywords,e.case_insensitive)), -s.lexemes&&l)throw Error("ERR: Prefer `keywords.$pattern` to `mode.lexemes`, BOTH are not allowed. (see mode reference) ") -;return l=l||s.lexemes||/\w+/, -o.keywordPatternRe=n(l,!0),i&&(s.begin||(s.begin=/\B|\b/), -o.beginRe=n(s.begin),s.endSameAsBegin&&(s.end=s.begin), -s.end||s.endsWithParent||(s.end=/\B|\b/), -s.end&&(o.endRe=n(s.end)),o.terminatorEnd=u(s.end)||"", -s.endsWithParent&&i.terminatorEnd&&(o.terminatorEnd+=(s.end?"|":"")+i.terminatorEnd)), -s.illegal&&(o.illegalRe=n(s.illegal)), -s.contains||(s.contains=[]),s.contains=[].concat(...s.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>a(e,{ -variants:null},t)))),e.cachedVariants?e.cachedVariants:T(e)?a(e,{ -starts:e.starts?a(e.starts):null -}):Object.isFrozen(e)?a(e):e))("self"===e?s:e)))),s.contains.forEach((e=>{t(e,o) -})),s.starts&&t(s.starts,i),o.matcher=(e=>{const t=new r -;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" -}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" -}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(o),o}(e)}function T(e){ -return!!e&&(e.endsWithParent||T(e.starts))}function j(e){const t={ -props:["language","code","autodetect"],data:()=>({detectedLanguage:"", -unknownLanguage:!1}),computed:{className(){ -return this.unknownLanguage?"":"hljs "+this.detectedLanguage},highlighted(){ -if(!this.autoDetect&&!e.getLanguage(this.language))return console.warn(`The language "${this.language}" you specified could not be found.`), -this.unknownLanguage=!0,r(this.code);let t={} -;return this.autoDetect?(t=e.highlightAuto(this.code), -this.detectedLanguage=t.language):(t=e.highlight(this.language,this.code,this.ignoreIllegals), -this.detectedLanguage=this.language),t.value},autoDetect(){ -return!(this.language&&(e=this.autodetect,!e&&""!==e));var e}, -ignoreIllegals:()=>!0},render(e){return e("pre",{},[e("code",{ -class:this.className,domProps:{innerHTML:this.highlighted}})])}};return{ -Component:t,VuePlugin:{install(e){e.component("highlightjs",t)}}}}const S={ -"after:highlightBlock":({block:e,result:t,text:n})=>{const s=D(e) -;if(!s.length)return;const a=document.createElement("div") -;a.innerHTML=t.value,t.value=((e,t,n)=>{let s=0,a="";const i=[];function o(){ -return e.length&&t.length?e[0].offset!==t[0].offset?e[0].offset"}function c(e){ -a+=""}function u(e){("start"===e.event?l:c)(e.node)} -for(;e.length||t.length;){let t=o() -;if(a+=r(n.substring(s,t[0].offset)),s=t[0].offset,t===e){i.reverse().forEach(c) -;do{u(t.splice(0,1)[0]),t=o()}while(t===e&&t.length&&t[0].offset===s) -;i.reverse().forEach(l) -}else"start"===t[0].event?i.push(t[0].node):i.pop(),u(t.splice(0,1)[0])} -return a+r(n.substr(s))})(s,D(a),n)}};function P(e){ -return e.nodeName.toLowerCase()}function D(e){const t=[];return function e(n,s){ -for(let r=n.firstChild;r;r=r.nextSibling)3===r.nodeType?s+=r.nodeValue.length:1===r.nodeType&&(t.push({ -event:"start",offset:s,node:r}),s=e(r,s),P(r).match(/br|hr|img|input/)||t.push({ -event:"stop",offset:s,node:r}));return s}(e,0),t}const C=e=>{console.error(e) -},H=(e,...t)=>{console.log("WARN: "+e,...t)},$=(e,t)=>{ -console.log(`Deprecated as of ${e}. ${t}`)},U=r,z=a,K=Symbol("nomatch") -;return(e=>{const n=Object.create(null),r=Object.create(null),a=[];let i=!0 -;const o=/(^(<[^>]+>|\t|)+|\n)/gm,l="Could not find the language '{}', did you forget to load/include a language module?",u={ -disableAutodetect:!0,name:"Plain text",contains:[]};let g={ -noHighlightRe:/^(no-?highlight)$/i, -languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", -tabReplace:null,useBR:!1,languages:null,__emitter:c};function d(e){ -return g.noHighlightRe.test(e)}function h(e,t,n,s){const r={code:t,language:e} -;_("before:highlight",r);const a=r.result?r.result:f(r.language,r.code,n,s) -;return a.code=r.code,_("after:highlight",a),a}function f(e,t,r,o){const c=t -;function u(e,t){const n=w.case_insensitive?t[0].toLowerCase():t[0] -;return Object.prototype.hasOwnProperty.call(e.keywords,n)&&e.keywords[n]} -function d(){null!=_.subLanguage?(()=>{if(""===O)return;let e=null -;if("string"==typeof _.subLanguage){ -if(!n[_.subLanguage])return void M.addText(O) -;e=f(_.subLanguage,O,!0,k[_.subLanguage]),k[_.subLanguage]=e.top -}else e=p(O,_.subLanguage.length?_.subLanguage:null) -;_.relevance>0&&(A+=e.relevance),M.addSublanguage(e.emitter,e.language) -})():(()=>{if(!_.keywords)return void M.addText(O);let e=0 -;_.keywordPatternRe.lastIndex=0;let t=_.keywordPatternRe.exec(O),n="";for(;t;){ -n+=O.substring(e,t.index);const s=u(_,t);if(s){const[e,r]=s -;M.addText(n),n="",A+=r;const a=w.classNameAliases[e]||e;M.addKeyword(t[0],a) -}else n+=t[0];e=_.keywordPatternRe.lastIndex,t=_.keywordPatternRe.exec(O)} -n+=O.substr(e),M.addText(n)})(),O=""}function h(e){ -return e.className&&M.openNode(w.classNameAliases[e.className]||e.className), -_=Object.create(e,{parent:{value:_}}),_}function m(e,t,n){let r=((e,t)=>{ -const n=e&&e.exec(t);return n&&0===n.index})(e.endRe,n);if(r){if(e["on:end"]){ -const n=new s(e);e["on:end"](t,n),n.ignore&&(r=!1)}if(r){ -for(;e.endsParent&&e.parent;)e=e.parent;return e}} -if(e.endsWithParent)return m(e.parent,t,n)}function b(e){ -return 0===_.matcher.regexIndex?(O+=e[0],1):(T=!0,0)}function x(e){ -const t=e[0],n=c.substr(e.index),s=m(_,e,n);if(!s)return K;const r=_ -;r.skip?O+=t:(r.returnEnd||r.excludeEnd||(O+=t),d(),r.excludeEnd&&(O=t));do{ -_.className&&M.closeNode(),_.skip||_.subLanguage||(A+=_.relevance),_=_.parent -}while(_!==s.parent) -;return s.starts&&(s.endSameAsBegin&&(s.starts.endRe=s.endRe), -h(s.starts)),r.returnEnd?0:t.length}let E={};function v(t,n){const a=n&&n[0] -;if(O+=t,null==a)return d(),0 -;if("begin"===E.type&&"end"===n.type&&E.index===n.index&&""===a){ -if(O+=c.slice(n.index,n.index+1),!i){const t=Error("0 width match regex") -;throw t.languageName=e,t.badRule=E.rule,t}return 1} -if(E=n,"begin"===n.type)return function(e){ -const t=e[0],n=e.rule,r=new s(n),a=[n.__beforeBegin,n["on:begin"]] -;for(const n of a)if(n&&(n(e,r),r.ignore))return b(t) -;return n&&n.endSameAsBegin&&(n.endRe=RegExp(t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),"m")), -n.skip?O+=t:(n.excludeBegin&&(O+=t), -d(),n.returnBegin||n.excludeBegin||(O=t)),h(n),n.returnBegin?0:t.length}(n) -;if("illegal"===n.type&&!r){ -const e=Error('Illegal lexeme "'+a+'" for mode "'+(_.className||"")+'"') -;throw e.mode=_,e}if("end"===n.type){const e=x(n);if(e!==K)return e} -if("illegal"===n.type&&""===a)return 1 -;if(B>1e5&&B>3*n.index)throw Error("potential infinite loop, way more iterations than matches") -;return O+=a,a.length}const w=N(e) -;if(!w)throw C(l.replace("{}",e)),Error('Unknown language: "'+e+'"') -;const R=I(w,{plugins:a});let y="",_=o||R;const k={},M=new g.__emitter(g);(()=>{ -const e=[];for(let t=_;t!==w;t=t.parent)t.className&&e.unshift(t.className) -;e.forEach((e=>M.openNode(e)))})();let O="",A=0,L=0,B=0,T=!1;try{ -for(_.matcher.considerAll();;){ -B++,T?T=!1:_.matcher.considerAll(),_.matcher.lastIndex=L -;const e=_.matcher.exec(c);if(!e)break;const t=v(c.substring(L,e.index),e) -;L=e.index+t}return v(c.substr(L)),M.closeAllNodes(),M.finalize(),y=M.toHTML(),{ -relevance:A,value:y,language:e,illegal:!1,emitter:M,top:_}}catch(t){ -if(t.message&&t.message.includes("Illegal"))return{illegal:!0,illegalBy:{ -msg:t.message,context:c.slice(L-100,L+100),mode:t.mode},sofar:y,relevance:0, -value:U(c),emitter:M};if(i)return{illegal:!1,relevance:0,value:U(c),emitter:M, -language:e,top:_,errorRaised:t};throw t}}function p(e,t){ -t=t||g.languages||Object.keys(n);const s=(e=>{const t={relevance:0, -emitter:new g.__emitter(g),value:U(e),illegal:!1,top:u} -;return t.emitter.addText(e),t})(e),r=t.filter(N).filter(R).map((t=>f(t,e,!1))) -;r.unshift(s);const a=r.sort(((e,t)=>{ -if(e.relevance!==t.relevance)return t.relevance-e.relevance -;if(e.language&&t.language){if(N(e.language).supersetOf===t.language)return 1 -;if(N(t.language).supersetOf===e.language)return-1}return 0})),[i,o]=a,l=i -;return l.second_best=o,l}const m={"before:highlightBlock":({block:e})=>{ -g.useBR&&(e.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")) -},"after:highlightBlock":({result:e})=>{ -g.useBR&&(e.value=e.value.replace(/\n/g,"
    "))}},b=/^(<[^>]+>|\t)+/gm,x={ -"after:highlightBlock":({result:e})=>{ -g.tabReplace&&(e.value=e.value.replace(b,(e=>e.replace(/\t/g,g.tabReplace))))}} -;function E(e){let t=null;const n=(e=>{let t=e.className+" " -;t+=e.parentNode?e.parentNode.className:"";const n=g.languageDetectRe.exec(t) -;if(n){const t=N(n[1]) -;return t||(H(l.replace("{}",n[1])),H("Falling back to no-highlight mode for this block.",e)), -t?n[1]:"no-highlight"}return t.split(/\s+/).find((e=>d(e)||N(e)))})(e) -;if(d(n))return;_("before:highlightBlock",{block:e,language:n}),t=e -;const s=t.textContent,a=n?h(n,s,!0):p(s);_("after:highlightBlock",{block:e, -result:a,text:s}),e.innerHTML=a.value,((e,t,n)=>{const s=t?r[t]:n -;e.classList.add("hljs"),s&&e.classList.add(s)})(e,n,a.language),e.result={ -language:a.language,re:a.relevance,relavance:a.relevance -},a.second_best&&(e.second_best={language:a.second_best.language, -re:a.second_best.relevance,relavance:a.second_best.relevance})}const v=()=>{ -v.called||(v.called=!0,document.querySelectorAll("pre code").forEach(E))} -;function N(e){return e=(e||"").toLowerCase(),n[e]||n[r[e]]} -function w(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{r[e]=t -}))}function R(e){const t=N(e);return t&&!t.disableAutodetect}function _(e,t){ -const n=e;a.forEach((e=>{e[n]&&e[n](t)}))}Object.assign(e,{highlight:h, -highlightAuto:p,fixMarkup:e=>{ -return $("10.2.0","fixMarkup will be removed entirely in v11.0"), -$("10.2.0","Please see https://github.com/highlightjs/highlight.js/issues/2534"), -t=e, -g.tabReplace||g.useBR?t.replace(o,(e=>"\n"===e?g.useBR?"
    ":e:g.tabReplace?e.replace(/\t/g,g.tabReplace):e)):t -;var t},highlightBlock:E,configure:e=>{ -e.useBR&&($("10.3.0","'useBR' will be removed entirely in v11.0"), -$("10.3.0","Please see https://github.com/highlightjs/highlight.js/issues/2559")), -g=z(g,e)},initHighlighting:v,initHighlightingOnLoad:()=>{ -window.addEventListener("DOMContentLoaded",v,!1)},registerLanguage:(t,s)=>{ -let r=null;try{r=s(e)}catch(e){ -if(C("Language definition for '{}' could not be registered.".replace("{}",t)), -!i)throw e;C(e),r=u} -r.name||(r.name=t),n[t]=r,r.rawDefinition=s.bind(null,e),r.aliases&&w(r.aliases,{ -languageName:t})},listLanguages:()=>Object.keys(n),getLanguage:N, -registerAliases:w,requireLanguage:e=>{ -$("10.4.0","requireLanguage will be removed entirely in v11."), -$("10.4.0","Please see https://github.com/highlightjs/highlight.js/pull/2844") -;const t=N(e);if(t)return t -;throw Error("The '{}' language is required, but not loaded.".replace("{}",e))}, -autoDetection:R,inherit:z,addPlugin:e=>{a.push(e)},vuePlugin:j(e).VuePlugin -}),e.debugMode=()=>{i=!1},e.safeMode=()=>{i=!0},e.versionString="10.5.0" -;for(const e in y)"object"==typeof y[e]&&t(y[e]) -;return Object.assign(e,y),e.addPlugin(m),e.addPlugin(S),e.addPlugin(x),e})({}) -}();"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs); -hljs.registerLanguage("apache",(()=>{"use strict";return e=>{const n={ -className:"number",begin:/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(:\d{1,5})?/} -;return{name:"Apache config",aliases:["apacheconf"],case_insensitive:!0, -contains:[e.HASH_COMMENT_MODE,{className:"section",begin:/<\/?/,end:/>/, -contains:[n,{className:"number",begin:/:\d{1,5}/ -},e.inherit(e.QUOTE_STRING_MODE,{relevance:0})]},{className:"attribute", -begin:/\w+/,relevance:0,keywords:{ -nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername" -},starts:{end:/$/,relevance:0,keywords:{literal:"on off all deny allow"}, -contains:[{className:"meta",begin:/\s\[/,end:/\]$/},{className:"variable", -begin:/[\$%]\{/,end:/\}/,contains:["self",{className:"number",begin:/[$%]\d+/}] -},n,{className:"number",begin:/\d+/},e.QUOTE_STRING_MODE]}}],illegal:/\S/}} -})()); -hljs.registerLanguage("bash",(()=>{"use strict";function e(...e){ -return e.map((e=>{return(s=e)?"string"==typeof s?s:s.source:null;var s -})).join("")}return s=>{const n={},t={begin:/\$\{/,end:/\}/,contains:["self",{ -begin:/:-/,contains:[n]}]};Object.assign(n,{className:"variable",variants:[{ -begin:e(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},t]});const a={ -className:"subst",begin:/\$\(/,end:/\)/,contains:[s.BACKSLASH_ESCAPE]},i={ -begin:/<<-?\s*(?=\w+)/,starts:{contains:[s.END_SAME_AS_BEGIN({begin:/(\w+)/, -end:/(\w+)/,className:"string"})]}},c={className:"string",begin:/"/,end:/"/, -contains:[s.BACKSLASH_ESCAPE,n,a]};a.contains.push(c);const o={begin:/\$\(\(/, -end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},s.NUMBER_MODE,n] -},r=s.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10 -}),l={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0, -contains:[s.inherit(s.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{ -name:"Bash",aliases:["sh","zsh"],keywords:{$pattern:/\b[a-z._-]+\b/, -keyword:"if then else elif fi for while in do done case esac function", -literal:"true false", -built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp" -},contains:[r,s.SHEBANG(),l,o,s.HASH_COMMENT_MODE,i,c,{className:"",begin:/\\"/ -},{className:"string",begin:/'/,end:/'/},n]}}})()); -hljs.registerLanguage("c",(()=>{"use strict";function e(e){ -return((...e)=>e.map((e=>(e=>e?"string"==typeof e?e:e.source:null)(e))).join(""))("(",e,")?") -}return t=>{const n=(t=>{const n=t.COMMENT("//","$",{contains:[{begin:/\\\n/}] -}),r="[a-zA-Z_]\\w*::",a="(decltype\\(auto\\)|"+e(r)+"[a-zA-Z_]\\w*"+e("<[^<>]+>")+")",s={ -className:"keyword",begin:"\\b[a-z\\d_]*_t\\b"},i={className:"string", -variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n", -contains:[t.BACKSLASH_ESCAPE]},{ -begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", -end:"'",illegal:"."},t.END_SAME_AS_BEGIN({ -begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={ -className:"number",variants:[{begin:"\\b(0b[01']+)"},{ -begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" -},{ -begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" -}],relevance:0},c={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ -"meta-keyword":"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" -},contains:[{begin:/\\\n/,relevance:0},t.inherit(i,{className:"meta-string"}),{ -className:"meta-string",begin:/<.*?>/,end:/$/,illegal:"\\n" -},n,t.C_BLOCK_COMMENT_MODE]},l={className:"title",begin:e(r)+t.IDENT_RE, -relevance:0},d=e(r)+t.IDENT_RE+"\\s*\\(",u={ -keyword:"int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid wchar_t short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignas alignof constexpr consteval constinit decltype concept co_await co_return co_yield requires noexcept static_assert thread_local restrict final override atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq", -built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr _Bool complex _Complex imaginary _Imaginary", -literal:"true false nullptr NULL"},m=[c,s,n,t.C_BLOCK_COMMENT_MODE,o,i],p={ -variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{ -beginKeywords:"new throw return else",end:/;/}],keywords:u,contains:m.concat([{ -begin:/\(/,end:/\)/,keywords:u,contains:m.concat(["self"]),relevance:0}]), -relevance:0},_={className:"function",begin:"("+a+"[\\*&\\s]+)+"+d, -returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:u,illegal:/[^\w\s\*&:<>.]/, -contains:[{begin:"decltype\\(auto\\)",keywords:u,relevance:0},{begin:d, -returnBegin:!0,contains:[l],relevance:0},{className:"params",begin:/\(/, -end:/\)/,keywords:u,relevance:0,contains:[n,t.C_BLOCK_COMMENT_MODE,i,o,s,{ -begin:/\(/,end:/\)/,keywords:u,relevance:0, -contains:["self",n,t.C_BLOCK_COMMENT_MODE,i,o,s]}] -},s,n,t.C_BLOCK_COMMENT_MODE,c]};return{ -aliases:["c","cc","h","c++","h++","hpp","hh","hxx","cxx"],keywords:u, -disableAutodetect:!0,illegal:"",keywords:u,contains:["self",s]},{begin:t.IDENT_RE+"::",keywords:u},{ -className:"class",beginKeywords:"enum class struct union",end:/[{;:<>=]/, -contains:[{beginKeywords:"final class struct"},t.TITLE_MODE]}]),exports:{ -preprocessor:c,strings:i,keywords:u}}})(t) -;return n.name="C",n.aliases=["c","h"],n}})()); -hljs.registerLanguage("coffeescript",(()=>{"use strict" -;const e=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],n=["true","false","null","undefined","NaN","Infinity"],a=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]) -;return r=>{const t={ -keyword:e.concat(["then","unless","until","loop","by","when","and","or","is","isnt","not"]).filter((i=["var","const","let","function","static"], -e=>!i.includes(e))).join(" "), -literal:n.concat(["yes","no","on","off"]).join(" "), -built_in:a.concat(["npm","print"]).join(" ")};var i -;const s="[A-Za-z$_][0-9A-Za-z$_]*",o={className:"subst",begin:/#\{/,end:/\}/, -keywords:t},c=[r.BINARY_NUMBER_MODE,r.inherit(r.C_NUMBER_MODE,{starts:{ -end:"(\\s*/)?",relevance:0}}),{className:"string",variants:[{begin:/'''/, -end:/'''/,contains:[r.BACKSLASH_ESCAPE]},{begin:/'/,end:/'/, -contains:[r.BACKSLASH_ESCAPE]},{begin:/"""/,end:/"""/, -contains:[r.BACKSLASH_ESCAPE,o]},{begin:/"/,end:/"/, -contains:[r.BACKSLASH_ESCAPE,o]}]},{className:"regexp",variants:[{begin:"///", -end:"///",contains:[o,r.HASH_COMMENT_MODE]},{begin:"//[gim]{0,3}(?=\\W)", -relevance:0},{begin:/\/(?![ *]).*?(?![\\]).\/[gim]{0,3}(?=\W)/}]},{begin:"@"+s -},{subLanguage:"javascript",excludeBegin:!0,excludeEnd:!0,variants:[{ -begin:"```",end:"```"},{begin:"`",end:"`"}]}];o.contains=c -;const l=r.inherit(r.TITLE_MODE,{begin:s}),d="(\\(.*\\)\\s*)?\\B[-=]>",g={ -className:"params",begin:"\\([^\\(]",returnBegin:!0,contains:[{begin:/\(/, -end:/\)/,keywords:t,contains:["self"].concat(c)}]};return{name:"CoffeeScript", -aliases:["coffee","cson","iced"],keywords:t,illegal:/\/\*/, -contains:c.concat([r.COMMENT("###","###"),r.HASH_COMMENT_MODE,{ -className:"function",begin:"^\\s*"+s+"\\s*=\\s*"+d,end:"[-=]>",returnBegin:!0, -contains:[l,g]},{begin:/[:\(,=]\s*/,relevance:0,contains:[{className:"function", -begin:d,end:"[-=]>",returnBegin:!0,contains:[g]}]},{className:"class", -beginKeywords:"class",end:"$",illegal:/[:="\[\]]/,contains:[{ -beginKeywords:"extends",endsWithParent:!0,illegal:/[:="\[\]]/,contains:[l]},l] -},{begin:s+":",end:":",returnBegin:!0,returnEnd:!0,relevance:0}])}}})()); -hljs.registerLanguage("cpp",(()=>{"use strict";function e(e){ -return((...e)=>e.map((e=>(e=>e?"string"==typeof e?e:e.source:null)(e))).join(""))("(",e,")?") -}return t=>{const n=(t=>{const n=t.COMMENT("//","$",{contains:[{begin:/\\\n/}] -}),r="[a-zA-Z_]\\w*::",a="(decltype\\(auto\\)|"+e(r)+"[a-zA-Z_]\\w*"+e("<[^<>]+>")+")",s={ -className:"keyword",begin:"\\b[a-z\\d_]*_t\\b"},i={className:"string", -variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n", -contains:[t.BACKSLASH_ESCAPE]},{ -begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)", -end:"'",illegal:"."},t.END_SAME_AS_BEGIN({ -begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},c={ -className:"number",variants:[{begin:"\\b(0b[01']+)"},{ -begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)" -},{ -begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" -}],relevance:0},o={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{ -"meta-keyword":"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include" -},contains:[{begin:/\\\n/,relevance:0},t.inherit(i,{className:"meta-string"}),{ -className:"meta-string",begin:/<.*?>/,end:/$/,illegal:"\\n" -},n,t.C_BLOCK_COMMENT_MODE]},l={className:"title",begin:e(r)+t.IDENT_RE, -relevance:0},d=e(r)+t.IDENT_RE+"\\s*\\(",u={ -keyword:"int float while private char char8_t char16_t char32_t catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid wchar_t short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignas alignof constexpr consteval constinit decltype concept co_await co_return co_yield requires noexcept static_assert thread_local restrict final override atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq", -built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr _Bool complex _Complex imaginary _Imaginary", -literal:"true false nullptr NULL"},p=[o,s,n,t.C_BLOCK_COMMENT_MODE,c,i],m={ -variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{ -beginKeywords:"new throw return else",end:/;/}],keywords:u,contains:p.concat([{ -begin:/\(/,end:/\)/,keywords:u,contains:p.concat(["self"]),relevance:0}]), -relevance:0},_={className:"function",begin:"("+a+"[\\*&\\s]+)+"+d, -returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:u,illegal:/[^\w\s\*&:<>.]/, -contains:[{begin:"decltype\\(auto\\)",keywords:u,relevance:0},{begin:d, -returnBegin:!0,contains:[l],relevance:0},{className:"params",begin:/\(/, -end:/\)/,keywords:u,relevance:0,contains:[n,t.C_BLOCK_COMMENT_MODE,i,c,s,{ -begin:/\(/,end:/\)/,keywords:u,relevance:0, -contains:["self",n,t.C_BLOCK_COMMENT_MODE,i,c,s]}] -},s,n,t.C_BLOCK_COMMENT_MODE,o]};return{ -aliases:["c","cc","h","c++","h++","hpp","hh","hxx","cxx"],keywords:u, -disableAutodetect:!0,illegal:"",keywords:u,contains:["self",s]},{begin:t.IDENT_RE+"::",keywords:u},{ -className:"class",beginKeywords:"enum class struct union",end:/[{;:<>=]/, -contains:[{beginKeywords:"final class struct"},t.TITLE_MODE]}]),exports:{ -preprocessor:o,strings:i,keywords:u}}})(t) -;return n.disableAutodetect=!1,n.name="C++", -n.aliases=["cc","c++","h++","hpp","hh","hxx","cxx"],n}})()); -hljs.registerLanguage("csharp",(()=>{"use strict";return e=>{var n={ -keyword:["abstract","as","base","break","case","class","const","continue","do","else","event","explicit","extern","finally","fixed","for","foreach","goto","if","implicit","in","interface","internal","is","lock","namespace","new","operator","out","override","params","private","protected","public","readonly","record","ref","return","sealed","sizeof","stackalloc","static","struct","switch","this","throw","try","typeof","unchecked","unsafe","using","virtual","void","volatile","while"].concat(["add","alias","and","ascending","async","await","by","descending","equals","from","get","global","group","init","into","join","let","nameof","not","notnull","on","or","orderby","partial","remove","select","set","unmanaged","value|0","var","when","where","with","yield"]).join(" "), -built_in:"bool byte char decimal delegate double dynamic enum float int long nint nuint object sbyte short string ulong unit ushort", -literal:"default false null true"},a=e.inherit(e.TITLE_MODE,{ -begin:"[a-zA-Z](\\.?\\w)*"}),i={className:"number",variants:[{ -begin:"\\b(0b[01']+)"},{ -begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{ -begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)" -}],relevance:0},s={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}] -},t=e.inherit(s,{illegal:/\n/}),r={className:"subst",begin:/\{/,end:/\}/, -keywords:n},l=e.inherit(r,{illegal:/\n/}),c={className:"string",begin:/\$"/, -end:'"',illegal:/\n/,contains:[{begin:/\{\{/},{begin:/\}\}/ -},e.BACKSLASH_ESCAPE,l]},o={className:"string",begin:/\$@"/,end:'"',contains:[{ -begin:/\{\{/},{begin:/\}\}/},{begin:'""'},r]},d=e.inherit(o,{illegal:/\n/, -contains:[{begin:/\{\{/},{begin:/\}\}/},{begin:'""'},l]}) -;r.contains=[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,i,e.C_BLOCK_COMMENT_MODE], -l.contains=[d,c,t,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,i,e.inherit(e.C_BLOCK_COMMENT_MODE,{ -illegal:/\n/})];var g={variants:[o,c,s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] -},E={begin:"<",end:">",contains:[{beginKeywords:"in out"},a] -},_=e.IDENT_RE+"(<"+e.IDENT_RE+"(\\s*,\\s*"+e.IDENT_RE+")*>)?(\\[\\])?",b={ -begin:"@"+e.IDENT_RE,relevance:0};return{name:"C#",aliases:["cs","c#"], -keywords:n,illegal:/::/,contains:[e.COMMENT("///","$",{returnBegin:!0, -contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{ -begin:"\x3c!--|--\x3e"},{begin:""}]}] -}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#", -end:"$",keywords:{ -"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum" -}},g,i,{beginKeywords:"class interface",relevance:0,end:/[{;=]/, -illegal:/[^\s:,]/,contains:[{beginKeywords:"where class" -},a,E,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace", -relevance:0,end:/[{;=]/,illegal:/[^\s:]/, -contains:[a,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{ -beginKeywords:"record",relevance:0,end:/[{;=]/,illegal:/[^\s:]/, -contains:[a,E,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"meta", -begin:"^\\s*\\[",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{ -className:"meta-string",begin:/"/,end:/"/}]},{ -beginKeywords:"new return throw await else",relevance:0},{className:"function", -begin:"("+_+"\\s+)+"+e.IDENT_RE+"\\s*(<.+>\\s*)?\\(",returnBegin:!0, -end:/\s*[{;=]/,excludeEnd:!0,keywords:n,contains:[{ -beginKeywords:"public private protected static internal protected abstract async extern override unsafe virtual new sealed partial", -relevance:0},{begin:e.IDENT_RE+"\\s*(<.+>\\s*)?\\(",returnBegin:!0, -contains:[e.TITLE_MODE,E],relevance:0},{className:"params",begin:/\(/,end:/\)/, -excludeBegin:!0,excludeEnd:!0,keywords:n,relevance:0, -contains:[g,i,e.C_BLOCK_COMMENT_MODE] -},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},b]}}})()); -hljs.registerLanguage("css",(()=>{"use strict";return e=>{ -var n="[a-zA-Z-][a-zA-Z0-9_-]*",a={ -begin:/([*]\s?)?(?:[A-Z_.\-\\]+|--[a-zA-Z0-9_-]+)\s*(\/\*\*\/)?:/, -returnBegin:!0,end:";",endsWithParent:!0,contains:[{className:"attribute", -begin:/\S/,end:":",excludeEnd:!0,starts:{endsWithParent:!0,excludeEnd:!0, -contains:[{begin:/[\w-]+\(/,returnBegin:!0,contains:[{className:"built_in", -begin:/[\w-]+/},{begin:/\(/,end:/\)/, -contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE]}] -},e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{ -className:"number",begin:"#[0-9A-Fa-f]+"},{className:"meta",begin:"!important"}] -}}]};return{name:"CSS",case_insensitive:!0,illegal:/[=|'\$]/, -contains:[e.C_BLOCK_COMMENT_MODE,{className:"selector-id", -begin:/#[A-Za-z0-9_-]+/},{className:"selector-class",begin:"\\."+n},{ -className:"selector-attr",begin:/\[/,end:/\]/,illegal:"$", -contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},{className:"selector-pseudo", -begin:/:(:)?[a-zA-Z0-9_+()"'.-]+/},{begin:"@(page|font-face)", -lexemes:"@[a-z-]+",keywords:"@page @font-face"},{begin:"@",end:"[{;]", -illegal:/:/,returnBegin:!0,contains:[{className:"keyword", -begin:/@-?\w[\w]*(-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0, -relevance:0,keywords:"and or not only",contains:[{begin:/[a-z-]+:/, -className:"attribute"},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,e.CSS_NUMBER_MODE] -}]},{className:"selector-tag",begin:n,relevance:0},{begin:/\{/,end:/\}/, -illegal:/\S/,contains:[e.C_BLOCK_COMMENT_MODE,{begin:/;/},a]}]}}})()); -hljs.registerLanguage("diff",(()=>{"use strict";return e=>({name:"Diff", -aliases:["patch"],contains:[{className:"meta",relevance:10,variants:[{ -begin:/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/},{begin:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{ -begin:/^--- +\d+,\d+ +----$/}]},{className:"comment",variants:[{begin:/Index: /, -end:/$/},{begin:/^index/,end:/$/},{begin:/={3,}/,end:/$/},{begin:/^-{3}/,end:/$/ -},{begin:/^\*{3} /,end:/$/},{begin:/^\+{3}/,end:/$/},{begin:/^\*{15}$/},{ -begin:/^diff --git/,end:/$/}]},{className:"addition",begin:/^\+/,end:/$/},{ -className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/, -end:/$/}]})})()); -hljs.registerLanguage("go",(()=>{"use strict";return e=>{const n={ -keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune", -literal:"true false iota nil", -built_in:"append cap close complex copy imag len make new panic print println real recover delete" -};return{name:"Go",aliases:["golang"],keywords:n,illegal:"{"use strict";function e(...e){ -return e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null;var n -})).join("")}return n=>{const a="HTTP/(2|1\\.[01])",s=[{className:"attribute", -begin:e("^",/[A-Za-z][A-Za-z0-9-]*/,"(?=\\:\\s)"),starts:{contains:[{ -className:"punctuation",begin:/: /,relevance:0,starts:{end:"$",relevance:0}}]} -},{begin:"\\n\\n",starts:{subLanguage:[],endsWithParent:!0}}];return{ -name:"HTTP",aliases:["https"],illegal:/\S/,contains:[{begin:"^(?="+a+" \\d{3})", -end:/$/,contains:[{className:"meta",begin:a},{className:"number", -begin:"\\b\\d{3}\\b"}],starts:{end:/\b\B/,illegal:/\S/,contains:s}},{ -begin:"(?=^[A-Z]+ (.*?) "+a+"$)",end:/$/,contains:[{className:"string", -begin:" ",end:" ",excludeBegin:!0,excludeEnd:!0},{className:"meta",begin:a},{ -className:"keyword",begin:"[A-Z]+"}],starts:{end:/\b\B/,illegal:/\S/,contains:s} -}]}}})()); -hljs.registerLanguage("ini",(()=>{"use strict";function e(e){ -return e?"string"==typeof e?e:e.source:null}function n(...n){ -return n.map((n=>e(n))).join("")}return s=>{const a={className:"number", -relevance:0,variants:[{begin:/([+-]+)?[\d]+_[\d_]+/},{begin:s.NUMBER_RE}] -},i=s.COMMENT();i.variants=[{begin:/;/,end:/$/},{begin:/#/,end:/$/}];const t={ -className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{begin:/\$\{(.*?)\}/ -}]},r={className:"literal",begin:/\bon|off|true|false|yes|no\b/},l={ -className:"string",contains:[s.BACKSLASH_ESCAPE],variants:[{begin:"'''", -end:"'''",relevance:10},{begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"' -},{begin:"'",end:"'"}]},c={begin:/\[/,end:/\]/,contains:[i,r,t,l,a,"self"], -relevance:0 -},g="("+[/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/].map((n=>e(n))).join("|")+")" -;return{name:"TOML, also INI",aliases:["toml"],case_insensitive:!0,illegal:/\S/, -contains:[i,{className:"section",begin:/\[+/,end:/\]+/},{ -begin:n(g,"(\\s*\\.\\s*",g,")*",n("(?=",/\s*=\s*[^#\s]/,")")),className:"attr", -starts:{end:/$/,contains:[i,c,r,t,l,a]}}]}}})()); -hljs.registerLanguage("java",(()=>{"use strict" -;var e="\\.([0-9](_*[0-9])*)",n="[0-9a-fA-F](_*[0-9a-fA-F])*",a={ -className:"number",variants:[{ -begin:`(\\b([0-9](_*[0-9])*)((${e})|\\.)?|(${e}))[eE][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` -},{begin:`\\b([0-9](_*[0-9])*)((${e})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{ -begin:`(${e})[fFdD]?\\b`},{begin:"\\b([0-9](_*[0-9])*)[fFdD]\\b"},{ -begin:`\\b0[xX]((${n})\\.?|(${n})?\\.(${n}))[pP][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` -},{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${n})[lL]?\\b`},{ -begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}], -relevance:0};return e=>{ -var n="false synchronized int abstract float private char boolean var static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports do",s={ -className:"meta",begin:"@[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*", -contains:[{begin:/\(/,end:/\)/,contains:["self"]}]};const r=a;return{ -name:"Java",aliases:["jsp"],keywords:n,illegal:/<\/|#/, -contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/, -relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),{ -begin:/import java\.[a-z]+\./,keywords:"import",relevance:2 -},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{ -className:"class",beginKeywords:"class interface enum",end:/[{;=]/, -excludeEnd:!0,keywords:"class interface enum",illegal:/[:"\[\]]/,contains:[{ -beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{ -beginKeywords:"new throw return else",relevance:0},{className:"class", -begin:"record\\s+"+e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,excludeEnd:!0, -end:/[{;=]/,keywords:n,contains:[{beginKeywords:"record"},{ -begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0, -contains:[e.UNDERSCORE_TITLE_MODE]},{className:"params",begin:/\(/,end:/\)/, -keywords:n,relevance:0,contains:[e.C_BLOCK_COMMENT_MODE] -},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"function", -begin:"([\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*(<[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*(\\s*,\\s*[\xc0-\u02b8a-zA-Z_$][\xc0-\u02b8a-zA-Z_$0-9]*)*>)?\\s+)+"+e.UNDERSCORE_IDENT_RE+"\\s*\\(", -returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:n,contains:[{ -begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0, -contains:[e.UNDERSCORE_TITLE_MODE]},{className:"params",begin:/\(/,end:/\)/, -keywords:n,relevance:0, -contains:[s,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,r,e.C_BLOCK_COMMENT_MODE] -},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},r,s]}}})()); -hljs.registerLanguage("javascript",(()=>{"use strict" -;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],s=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]) -;function r(e){return i("(?=",e,")")}function i(...e){return e.map((e=>{ -return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}return t=>{ -const c=e,o={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/, -isTrulyOpeningTag:(e,n)=>{const a=e[0].length+e.index,s=e.input[a] -;"<"!==s?">"===s&&(((e,{after:n})=>{const a="", -returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{ -begin:t.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0 -},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:l,contains:A}]}] -},{begin:/,/,relevance:0},{className:"",begin:/\s/,end:/\s*/,skip:!0},{ -variants:[{begin:"<>",end:""},{begin:o.begin,"on:begin":o.isTrulyOpeningTag, -end:o.end}],subLanguage:"xml",contains:[{begin:o.begin,end:o.end,skip:!0, -contains:["self"]}]}],relevance:0},{className:"function", -beginKeywords:"function",end:/[{;]/,excludeEnd:!0,keywords:l, -contains:["self",t.inherit(t.TITLE_MODE,{begin:c}),p],illegal:/%/},{ -beginKeywords:"while if switch catch for"},{className:"function", -begin:t.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", -returnBegin:!0,contains:[p,t.inherit(t.TITLE_MODE,{begin:c})]},{variants:[{ -begin:"\\."+c},{begin:"\\$"+c}],relevance:0},{className:"class", -beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"[\]]/,contains:[{ -beginKeywords:"extends"},t.UNDERSCORE_TITLE_MODE]},{begin:/\b(?=constructor)/, -end:/[{;]/,excludeEnd:!0,contains:[t.inherit(t.TITLE_MODE,{begin:c}),"self",p] -},{begin:"(get|set)\\s+(?="+c+"\\()",end:/\{/,keywords:"get set", -contains:[t.inherit(t.TITLE_MODE,{begin:c}),{begin:/\(\)/},p]},{begin:/\$[(.]/}] -}}})()); -hljs.registerLanguage("json",(()=>{"use strict";return n=>{const e={ -literal:"true false null" -},i=[n.C_LINE_COMMENT_MODE,n.C_BLOCK_COMMENT_MODE],a=[n.QUOTE_STRING_MODE,n.C_NUMBER_MODE],l={ -end:",",endsWithParent:!0,excludeEnd:!0,contains:a,keywords:e},t={begin:/\{/, -end:/\}/,contains:[{className:"attr",begin:/"/,end:/"/, -contains:[n.BACKSLASH_ESCAPE],illegal:"\\n"},n.inherit(l,{begin:/:/ -})].concat(i),illegal:"\\S"},s={begin:"\\[",end:"\\]",contains:[n.inherit(l)], -illegal:"\\S"};return a.push(t,s),i.forEach((n=>{a.push(n)})),{name:"JSON", -contains:a,keywords:e,illegal:"\\S"}}})()); -hljs.registerLanguage("kotlin",(()=>{"use strict" -;var e="\\.([0-9](_*[0-9])*)",n="[0-9a-fA-F](_*[0-9a-fA-F])*",a={ -className:"number",variants:[{ -begin:`(\\b([0-9](_*[0-9])*)((${e})|\\.)?|(${e}))[eE][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` -},{begin:`\\b([0-9](_*[0-9])*)((${e})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{ -begin:`(${e})[fFdD]?\\b`},{begin:"\\b([0-9](_*[0-9])*)[fFdD]\\b"},{ -begin:`\\b0[xX]((${n})\\.?|(${n})?\\.(${n}))[pP][+-]?([0-9](_*[0-9])*)[fFdD]?\\b` -},{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${n})[lL]?\\b`},{ -begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}], -relevance:0};return e=>{const n={ -keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual", -built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing", -literal:"true false null"},i={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@" -},s={className:"subst",begin:/\$\{/,end:/\}/,contains:[e.C_NUMBER_MODE]},t={ -className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},r={className:"string", -variants:[{begin:'"""',end:'"""(?=[^"])',contains:[t,s]},{begin:"'",end:"'", -illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/, -contains:[e.BACKSLASH_ESCAPE,t,s]}]};s.contains.push(r);const l={ -className:"meta", -begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?" -},c={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/, -end:/\)/,contains:[e.inherit(r,{className:"meta-string"})]}] -},o=a,b=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),E={ -variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/, -contains:[]}]},d=E;return d.variants[1].contains=[E],E.variants[1].contains=[d], -{name:"Kotlin",aliases:["kt"],keywords:n,contains:[e.COMMENT("/\\*\\*","\\*/",{ -relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+"}] -}),e.C_LINE_COMMENT_MODE,b,{className:"keyword", -begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol", -begin:/@\w+/}]}},i,l,c,{className:"function",beginKeywords:"fun",end:"[(]|$", -returnBegin:!0,excludeEnd:!0,keywords:n,relevance:5,contains:[{ -begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0, -contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://, -keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/, -endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/, -endsWithParent:!0,contains:[E,e.C_LINE_COMMENT_MODE,b],relevance:0 -},e.C_LINE_COMMENT_MODE,b,l,c,r,e.C_NUMBER_MODE]},b]},{className:"class", -beginKeywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0, -illegal:"extends implements",contains:[{ -beginKeywords:"public protected internal private constructor" -},e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0, -excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,]|$/, -excludeBegin:!0,returnEnd:!0},l,c]},r,{className:"meta",begin:"^#!/usr/bin/env", -end:"$",illegal:"\n"},o]}}})()); -hljs.registerLanguage("less",(()=>{"use strict";return e=>{ -var n="([\\w-]+|@\\{[\\w-]+\\})",a=[],s=[],t=e=>({className:"string", -begin:"~?"+e+".*?"+e}),r=(e,n,a)=>({className:e,begin:n,relevance:a}),i={ -begin:"\\(",end:"\\)",contains:s,relevance:0} -;s.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,t("'"),t('"'),e.CSS_NUMBER_MODE,{ -begin:"(url|data-uri)\\(",starts:{className:"string",end:"[\\)\\n]", -excludeEnd:!0} -},r("number","#[0-9A-Fa-f]+\\b"),i,r("variable","@@?[\\w-]+",10),r("variable","@\\{[\\w-]+\\}"),r("built_in","~?`[^`]*?`"),{ -className:"attribute",begin:"[\\w-]+\\s*:",end:":",returnBegin:!0,excludeEnd:!0 -},{className:"meta",begin:"!important"});var c=s.concat({begin:/\{/,end:/\}/, -contains:a}),l={beginKeywords:"when",endsWithParent:!0,contains:[{ -beginKeywords:"and not"}].concat(s)},g={begin:n+"\\s*:",returnBegin:!0, -end:"[;}]",relevance:0,contains:[{className:"attribute",begin:n,end:":", -excludeEnd:!0,starts:{endsWithParent:!0,illegal:"[<=$]",relevance:0,contains:s} -}]},d={className:"keyword", -begin:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b", -starts:{end:"[;{}]",returnEnd:!0,contains:s,relevance:0}},o={ -className:"variable",variants:[{begin:"@[\\w-]+\\s*:",relevance:15},{ -begin:"@[\\w-]+"}],starts:{end:"[;}]",returnEnd:!0,contains:c}},b={variants:[{ -begin:"[\\.#:&\\[>]",end:"[;{}]"},{begin:n,end:/\{/}],returnBegin:!0, -returnEnd:!0,illegal:"[<='$\"]",relevance:0, -contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,l,r("keyword","all\\b"),r("variable","@\\{[\\w-]+\\}"),r("selector-tag",n+"%?",0),r("selector-id","#"+n),r("selector-class","\\."+n,0),r("selector-tag","&",0),{ -className:"selector-attr",begin:"\\[",end:"\\]"},{className:"selector-pseudo", -begin:/:(:)?[a-zA-Z0-9_\-+()"'.]+/},{begin:"\\(",end:"\\)",contains:c},{ -begin:"!important"}]} -;return a.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,d,o,g,b),{ -name:"Less",case_insensitive:!0,illegal:"[=>'/<($\"]",contains:a}}})()); -hljs.registerLanguage("lua",(()=>{"use strict";return e=>{ -const t="\\[=*\\[",a="\\]=*\\]",n={begin:t,end:a,contains:["self"] -},o=[e.COMMENT("--(?!\\[=*\\[)","$"),e.COMMENT("--\\[=*\\[",a,{contains:[n], -relevance:10})];return{name:"Lua",keywords:{$pattern:e.UNDERSCORE_IDENT_RE, -literal:"true false nil", -keyword:"and break do else elseif end for goto if in local not or repeat return then until while", -built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove" -},contains:o.concat([{className:"function",beginKeywords:"function",end:"\\)", -contains:[e.inherit(e.TITLE_MODE,{ -begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params", -begin:"\\(",endsWithParent:!0,contains:o}].concat(o) -},e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"string", -begin:t,end:a,contains:[n],relevance:5}])}}})()); -hljs.registerLanguage("makefile",(()=>{"use strict";return e=>{const i={ -className:"variable",variants:[{begin:"\\$\\("+e.UNDERSCORE_IDENT_RE+"\\)", -contains:[e.BACKSLASH_ESCAPE]},{begin:/\$[@%{"use strict";function e(e){ -return e?"string"==typeof e?e:e.source:null}function n(e){return a("(?=",e,")")} -function a(...n){return n.map((n=>e(n))).join("")}function s(...n){ -return"("+n.map((n=>e(n))).join("|")+")"}return e=>{ -const t=a(/[A-Z_]/,a("(",/[A-Z0-9_.-]+:/,")?"),/[A-Z0-9_.-]*/),i={ -className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},r={begin:/\s/, -contains:[{className:"meta-keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}] -},c=e.inherit(r,{begin:/\(/,end:/\)/}),l=e.inherit(e.APOS_STRING_MODE,{ -className:"meta-string"}),g=e.inherit(e.QUOTE_STRING_MODE,{ -className:"meta-string"}),m={endsWithParent:!0,illegal:/`]+/}]}] -}]};return{name:"HTML, XML", -aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"], -case_insensitive:!0,contains:[{className:"meta",begin://, -relevance:10,contains:[r,g,l,c,{begin:/\[/,end:/\]/,contains:[{className:"meta", -begin://,contains:[r,c,g,l]}]}]},e.COMMENT(//,{ -relevance:10}),{begin://,relevance:10},i,{ -className:"meta",begin:/<\?xml/,end:/\?>/,relevance:10},{className:"tag", -begin:/)/,end:/>/,keywords:{name:"style"},contains:[m],starts:{ -end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag", -begin:/)/,end:/>/,keywords:{name:"script"},contains:[m],starts:{ -end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{ -className:"tag",begin:/<>|<\/>/},{className:"tag", -begin:a(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name", -begin:t,relevance:0,starts:m}]},{className:"tag",begin:a(/<\//,n(a(t,/>/))), -contains:[{className:"name",begin:t,relevance:0},{begin:/>/,relevance:0}]}]}} -})()); -hljs.registerLanguage("markdown",(()=>{"use strict";function n(...n){ -return n.map((n=>{return(e=n)?"string"==typeof e?e:e.source:null;var e -})).join("")}return e=>{const a={begin:/<\/?[A-Za-z_]/,end:">", -subLanguage:"xml",relevance:0},i={variants:[{begin:/\[.+?\]\[.*?\]/,relevance:0 -},{begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/, -relevance:2},{begin:n(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/), -relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{ -begin:/\[.+?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{ -className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0, -returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)", -excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[", -end:"\\]",excludeBegin:!0,excludeEnd:!0}]},s={className:"strong",contains:[], -variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},c={ -className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{ -begin:/_(?!_)/,end:/_/,relevance:0}]};s.contains.push(c),c.contains.push(s) -;let t=[a,i] -;return s.contains=s.contains.concat(t),c.contains=c.contains.concat(t), -t=t.concat(s,c),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{ -className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:t},{ -begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n", -contains:t}]}]},a,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)", -end:"\\s+",excludeEnd:!0},s,c,{className:"quote",begin:"^>\\s+",contains:t, -end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{ -begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{ -begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))", -contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{ -begin:"^[-\\*]{3,}",end:"$"},i,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{ -className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{ -className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}}})()); -hljs.registerLanguage("nginx",(()=>{"use strict";return e=>{const n={ -className:"variable",variants:[{begin:/\$\d+/},{begin:/\$\{/,end:/\}/},{ -begin:/[$@]/+e.UNDERSCORE_IDENT_RE}]},a={endsWithParent:!0,keywords:{ -$pattern:"[a-z/_]+", -literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll" -},relevance:0,illegal:"=>",contains:[e.HASH_COMMENT_MODE,{className:"string", -contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:/"/,end:/"/},{begin:/'/,end:/'/ -}]},{begin:"([a-z]+):/",end:"\\s",endsWithParent:!0,excludeEnd:!0,contains:[n] -},{className:"regexp",contains:[e.BACKSLASH_ESCAPE,n],variants:[{begin:"\\s\\^", -end:"\\s|\\{|;",returnEnd:!0},{begin:"~\\*?\\s+",end:"\\s|\\{|;",returnEnd:!0},{ -begin:"\\*(\\.[a-z\\-]+)+"},{begin:"([a-z\\-]+\\.)+\\*"}]},{className:"number", -begin:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{ -className:"number",begin:"\\b\\d+[kKmMgGdshdwy]*\\b",relevance:0},n]};return{ -name:"Nginx config",aliases:["nginxconf"],contains:[e.HASH_COMMENT_MODE,{ -begin:e.UNDERSCORE_IDENT_RE+"\\s+\\{",returnBegin:!0,end:/\{/,contains:[{ -className:"section",begin:e.UNDERSCORE_IDENT_RE}],relevance:0},{ -begin:e.UNDERSCORE_IDENT_RE+"\\s",end:";|\\{",returnBegin:!0,contains:[{ -className:"attribute",begin:e.UNDERSCORE_IDENT_RE,starts:a}],relevance:0}], -illegal:"[^\\s\\}]"}}})()); -hljs.registerLanguage("objectivec",(()=>{"use strict";return e=>{ -const n=/[a-zA-Z@][a-zA-Z0-9_]*/,_={$pattern:n, -keyword:"@interface @class @protocol @implementation"};return{ -name:"Objective-C",aliases:["mm","objc","obj-c","obj-c++","objective-c++"], -keywords:{$pattern:n, -keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required @encode @package @import @defs @compatibility_alias __bridge __bridge_transfer __bridge_retained __bridge_retain __covariant __contravariant __kindof _Nonnull _Nullable _Null_unspecified __FUNCTION__ __PRETTY_FUNCTION__ __attribute__ getter setter retain unsafe_unretained nonnull nullable null_unspecified null_resettable class instancetype NS_DESIGNATED_INITIALIZER NS_UNAVAILABLE NS_REQUIRES_SUPER NS_RETURNS_INNER_POINTER NS_INLINE NS_AVAILABLE NS_DEPRECATED NS_ENUM NS_OPTIONS NS_SWIFT_UNAVAILABLE NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END NS_REFINED_FOR_SWIFT NS_SWIFT_NAME NS_SWIFT_NOTHROW NS_DURING NS_HANDLER NS_ENDHANDLER NS_VALUERETURN NS_VOIDRETURN", -literal:"false true FALSE TRUE nil YES NO NULL", -built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once" -},illegal:"/,end:/$/, -illegal:"\\n"},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{ -className:"class",begin:"("+_.keyword.split(" ").join("|")+")\\b",end:/(\{|$)/, -excludeEnd:!0,keywords:_,contains:[e.UNDERSCORE_TITLE_MODE]},{ -begin:"\\."+e.UNDERSCORE_IDENT_RE,relevance:0}]}}})()); -hljs.registerLanguage("perl",(()=>{"use strict";function e(...e){ -return e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null;var n -})).join("")}return n=>{const t=/[dualxmsipn]{0,12}/,s={$pattern:/[\w.]+/, -keyword:"getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qq fileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmget sub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedir ioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when" -},r={className:"subst",begin:"[$@]\\{",end:"\\}",keywords:s},i={begin:/->\{/, -end:/\}/},a={variants:[{begin:/\$\d/},{ -begin:e(/[$%@](\^\w\b|#\w+(::\w+)*|\{\w+\}|\w+(::\w*)*)/,"(?![A-Za-z])(?![@$%])") -},{begin:/[$%@][^\s\w{]/,relevance:0}] -},o=[n.BACKSLASH_ESCAPE,r,a],c=[a,n.HASH_COMMENT_MODE,n.COMMENT(/^=\w/,/=cut/,{ -endsWithParent:!0}),i,{className:"string",contains:o,variants:[{ -begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[", -end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{ -begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*<",end:">", -relevance:5},{begin:"qw\\s+q",end:"q",relevance:5},{begin:"'",end:"'", -contains:[n.BACKSLASH_ESCAPE]},{begin:'"',end:'"'},{begin:"`",end:"`", -contains:[n.BACKSLASH_ESCAPE]},{begin:/\{\w+\}/,contains:[],relevance:0},{ -begin:"-?\\w+\\s*=>",contains:[],relevance:0}]},{className:"number", -begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b", -relevance:0},{ -begin:"(\\/\\/|"+n.RE_STARTERS_RE+"|\\b(split|return|print|reverse|grep)\\b)\\s*", -keywords:"split return print reverse grep",relevance:0, -contains:[n.HASH_COMMENT_MODE,{className:"regexp", -begin:e(/(s|tr|y)/,/\//,/(\\.|[^\\\/])*/,/\//,/(\\.|[^\\\/])*/,/\//,t), -relevance:10},{className:"regexp",begin:/(m|qr)?\//,end:e(/\//,t), -contains:[n.BACKSLASH_ESCAPE],relevance:0}]},{className:"function", -beginKeywords:"sub",end:"(\\s*\\(.*?\\))?[;{]",excludeEnd:!0,relevance:5, -contains:[n.TITLE_MODE]},{begin:"-\\w\\b",relevance:0},{begin:"^__DATA__$", -end:"^__END__$",subLanguage:"mojolicious",contains:[{begin:"^@@.*",end:"$", -className:"comment"}]}];return r.contains=c,i.contains=c,{name:"Perl", -aliases:["pl","pm"],keywords:s,contains:c}}})()); -hljs.registerLanguage("php",(()=>{"use strict";return e=>{const r={ -className:"variable", -begin:"\\$+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?![A-Za-z0-9])(?![$])"},t={ -className:"meta",variants:[{begin:/<\?php/,relevance:10},{begin:/<\?[=]?/},{ -begin:/\?>/}]},a={className:"subst",variants:[{begin:/\$\w+/},{begin:/\{\$/, -end:/\}/}]},n=e.inherit(e.APOS_STRING_MODE,{illegal:null -}),i=e.inherit(e.QUOTE_STRING_MODE,{illegal:null, -contains:e.QUOTE_STRING_MODE.contains.concat(a)}),o=e.END_SAME_AS_BEGIN({ -begin:/<<<[ \t]*(\w+)\n/,end:/[ \t]*(\w+)\b/, -contains:e.QUOTE_STRING_MODE.contains.concat(a)}),l={className:"string", -contains:[e.BACKSLASH_ESCAPE,t],variants:[e.inherit(n,{begin:"b'",end:"'" -}),e.inherit(i,{begin:'b"',end:'"'}),i,n,o]},c={ -variants:[e.BINARY_NUMBER_MODE,e.C_NUMBER_MODE]},s={ -keyword:"__CLASS__ __DIR__ __FILE__ __FUNCTION__ __LINE__ __METHOD__ __NAMESPACE__ __TRAIT__ die echo exit include include_once print require require_once array abstract and as binary bool boolean break callable case catch class clone const continue declare default do double else elseif empty enddeclare endfor endforeach endif endswitch endwhile eval extends final finally float for foreach from global goto if implements instanceof insteadof int integer interface isset iterable list match|0 new object or private protected public real return string switch throw trait try unset use var void while xor yield", -literal:"false null true", -built_in:"Error|0 AppendIterator ArgumentCountError ArithmeticError ArrayIterator ArrayObject AssertionError BadFunctionCallException BadMethodCallException CachingIterator CallbackFilterIterator CompileError Countable DirectoryIterator DivisionByZeroError DomainException EmptyIterator ErrorException Exception FilesystemIterator FilterIterator GlobIterator InfiniteIterator InvalidArgumentException IteratorIterator LengthException LimitIterator LogicException MultipleIterator NoRewindIterator OutOfBoundsException OutOfRangeException OuterIterator OverflowException ParentIterator ParseError RangeException RecursiveArrayIterator RecursiveCachingIterator RecursiveCallbackFilterIterator RecursiveDirectoryIterator RecursiveFilterIterator RecursiveIterator RecursiveIteratorIterator RecursiveRegexIterator RecursiveTreeIterator RegexIterator RuntimeException SeekableIterator SplDoublyLinkedList SplFileInfo SplFileObject SplFixedArray SplHeap SplMaxHeap SplMinHeap SplObjectStorage SplObserver SplObserver SplPriorityQueue SplQueue SplStack SplSubject SplSubject SplTempFileObject TypeError UnderflowException UnexpectedValueException ArrayAccess Closure Generator Iterator IteratorAggregate Serializable Throwable Traversable WeakReference Directory __PHP_Incomplete_Class parent php_user_filter self static stdClass" -};return{aliases:["php","php3","php4","php5","php6","php7","php8"], -case_insensitive:!0,keywords:s, -contains:[e.HASH_COMMENT_MODE,e.COMMENT("//","$",{contains:[t] -}),e.COMMENT("/\\*","\\*/",{contains:[{className:"doctag",begin:"@[A-Za-z]+"}] -}),e.COMMENT("__halt_compiler.+?;",!1,{endsWithParent:!0, -keywords:"__halt_compiler"}),t,{className:"keyword",begin:/\$this\b/},r,{ -begin:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{className:"function", -relevance:0,beginKeywords:"fn function",end:/[;{]/,excludeEnd:!0, -illegal:"[$%\\[]",contains:[e.UNDERSCORE_TITLE_MODE,{begin:"=>"},{ -className:"params",begin:"\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0, -keywords:s,contains:["self",r,e.C_BLOCK_COMMENT_MODE,l,c]}]},{className:"class", -beginKeywords:"class interface",relevance:0,end:/\{/,excludeEnd:!0, -illegal:/[:($"]/,contains:[{beginKeywords:"extends implements" -},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"namespace",relevance:0,end:";", -illegal:/[.']/,contains:[e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"use", -relevance:0,end:";",contains:[e.UNDERSCORE_TITLE_MODE]},l,c]}}})()); -hljs.registerLanguage("php-template",(()=>{"use strict";return n=>({ -name:"PHP template",subLanguage:"xml",contains:[{begin:/<\?(php|=)?/,end:/\?>/, -subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0},{begin:'b"', -end:'"',skip:!0},{begin:"b'",end:"'",skip:!0},n.inherit(n.APOS_STRING_MODE,{ -illegal:null,className:null,contains:null,skip:!0 -}),n.inherit(n.QUOTE_STRING_MODE,{illegal:null,className:null,contains:null, -skip:!0})]}]})})()); -hljs.registerLanguage("plaintext",(()=>{"use strict";return t=>({ -name:"Plain text",aliases:["text","txt"],disableAutodetect:!0})})()); -hljs.registerLanguage("properties",(()=>{"use strict";return e=>{ -var n="[ \\t\\f]*",a=n+"[:=]"+n,t="("+a+"|[ \\t\\f]+)",r="([^\\\\\\W:= \\t\\f\\n]|\\\\.)+",s="([^\\\\:= \\t\\f\\n]|\\\\.)+",i={ -end:t,relevance:0,starts:{className:"string",end:/$/,relevance:0,contains:[{ -begin:"\\\\\\\\"},{begin:"\\\\\\n"}]}};return{name:".properties", -case_insensitive:!0,illegal:/\S/,contains:[e.COMMENT("^\\s*[!#]","$"),{ -returnBegin:!0,variants:[{begin:r+a,relevance:1},{begin:r+"[ \\t\\f]+", -relevance:0}],contains:[{className:"attr",begin:r,endsParent:!0,relevance:0}], -starts:i},{begin:s+t,returnBegin:!0,relevance:0,contains:[{className:"meta", -begin:s,endsParent:!0,relevance:0}],starts:i},{className:"attr",relevance:0, -begin:s+n+"$"}]}}})()); -hljs.registerLanguage("python",(()=>{"use strict";return e=>{const n={ -keyword:"and as assert async await break class continue def del elif else except finally for from global if import in is lambda nonlocal|10 not or pass raise return try while with yield", -built_in:"__import__ abs all any ascii bin bool breakpoint bytearray bytes callable chr classmethod compile complex delattr dict dir divmod enumerate eval exec filter float format frozenset getattr globals hasattr hash help hex id input int isinstance issubclass iter len list locals map max memoryview min next object oct open ord pow print property range repr reversed round set setattr slice sorted staticmethod str sum super tuple type vars zip", -literal:"__debug__ Ellipsis False None NotImplemented True"},a={ -className:"meta",begin:/^(>>>|\.\.\.) /},s={className:"subst",begin:/\{/, -end:/\}/,keywords:n,illegal:/#/},i={begin:/\{\{/,relevance:0},r={ -className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{ -begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/, -contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{ -begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/, -contains:[e.BACKSLASH_ESCAPE,a],relevance:10},{ -begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/, -contains:[e.BACKSLASH_ESCAPE,a,i,s]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/, -end:/"""/,contains:[e.BACKSLASH_ESCAPE,a,i,s]},{begin:/([uU]|[rR])'/,end:/'/, -relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{ -begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/, -end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/, -contains:[e.BACKSLASH_ESCAPE,i,s]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/, -contains:[e.BACKSLASH_ESCAPE,i,s]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE] -},t="[0-9](_?[0-9])*",l=`(\\b(${t}))?\\.(${t})|\\b(${t})\\.`,b={ -className:"number",relevance:0,variants:[{ -begin:`(\\b(${t})|(${l}))[eE][+-]?(${t})[jJ]?\\b`},{begin:`(${l})[jJ]?`},{ -begin:"\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?\\b"},{ -begin:"\\b0[bB](_?[01])+[lL]?\\b"},{begin:"\\b0[oO](_?[0-7])+[lL]?\\b"},{ -begin:"\\b0[xX](_?[0-9a-fA-F])+[lL]?\\b"},{begin:`\\b(${t})[jJ]\\b`}]},o={ -className:"params",variants:[{begin:/\(\s*\)/,skip:!0,className:null},{ -begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n, -contains:["self",a,b,r,e.HASH_COMMENT_MODE]}]};return s.contains=[r,b,a],{ -name:"Python",aliases:["py","gyp","ipython"],keywords:n, -illegal:/(<\/|->|\?)|=>/,contains:[a,b,{begin:/\bself\b/},{beginKeywords:"if", -relevance:0},r,e.HASH_COMMENT_MODE,{variants:[{className:"function", -beginKeywords:"def"},{className:"class",beginKeywords:"class"}],end:/:/, -illegal:/[${=;\n,]/,contains:[e.UNDERSCORE_TITLE_MODE,o,{begin:/->/, -endsWithParent:!0,keywords:"None"}]},{className:"meta",begin:/^[\t ]*@/, -end:/(?=#)|$/,contains:[b,o,r]},{begin:/\b(print|exec)\(/}]}}})()); -hljs.registerLanguage("python-repl",(()=>{"use strict";return s=>({ -aliases:["pycon"],contains:[{className:"meta",starts:{end:/ |$/,starts:{end:"$", -subLanguage:"python"}},variants:[{begin:/^>>>(?=[ ]|$)/},{ -begin:/^\.\.\.(?=[ ]|$)/}]}]})})()); -hljs.registerLanguage("r",(()=>{"use strict";function e(...e){return e.map((e=>{ -return(a=e)?"string"==typeof a?a:a.source:null;var a})).join("")}return a=>{ -const n=/(?:(?:[a-zA-Z]|\.[._a-zA-Z])[._a-zA-Z0-9]*)|\.(?!\d)/;return{name:"R", -illegal:/->/,keywords:{$pattern:n, -keyword:"function if in break next repeat else for while", -literal:"NULL NA TRUE FALSE Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10", -built_in:"LETTERS letters month.abb month.name pi T F abs acos acosh all any anyNA Arg as.call as.character as.complex as.double as.environment as.integer as.logical as.null.default as.numeric as.raw asin asinh atan atanh attr attributes baseenv browser c call ceiling class Conj cos cosh cospi cummax cummin cumprod cumsum digamma dim dimnames emptyenv exp expression floor forceAndCall gamma gc.time globalenv Im interactive invisible is.array is.atomic is.call is.character is.complex is.double is.environment is.expression is.finite is.function is.infinite is.integer is.language is.list is.logical is.matrix is.na is.name is.nan is.null is.numeric is.object is.pairlist is.raw is.recursive is.single is.symbol lazyLoadDBfetch length lgamma list log max min missing Mod names nargs nzchar oldClass on.exit pos.to.env proc.time prod quote range Re rep retracemem return round seq_along seq_len seq.int sign signif sin sinh sinpi sqrt standardGeneric substitute sum switch tan tanh tanpi tracemem trigamma trunc unclass untracemem UseMethod xtfrm" -},compilerExtensions:[(a,n)=>{if(!a.beforeMatch)return -;if(a.starts)throw Error("beforeMatch cannot be used with starts") -;const i=Object.assign({},a);Object.keys(a).forEach((e=>{delete a[e] -})),a.begin=e(i.beforeMatch,e("(?=",i.begin,")")),a.starts={relevance:0, -contains:[Object.assign(i,{endsParent:!0})]},a.relevance=0,delete i.beforeMatch -}],contains:[a.COMMENT(/#'/,/$/,{contains:[{className:"doctag", -begin:"@examples",starts:{contains:[{begin:/\n/},{begin:/#'\s*(?=@[a-zA-Z]+)/, -endsParent:!0},{begin:/#'/,end:/$/,excludeBegin:!0}]}},{className:"doctag", -begin:"@param",end:/$/,contains:[{className:"variable",variants:[{begin:n},{ -begin:/`(?:\\.|[^`\\])+`/}],endsParent:!0}]},{className:"doctag", -begin:/@[a-zA-Z]+/},{className:"meta-keyword",begin:/\\[a-zA-Z]+/}] -}),a.HASH_COMMENT_MODE,{className:"string",contains:[a.BACKSLASH_ESCAPE], -variants:[a.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\(/,end:/\)(-*)"/ -}),a.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\{/,end:/\}(-*)"/ -}),a.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\[/,end:/\](-*)"/ -}),a.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\(/,end:/\)(-*)'/ -}),a.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\{/,end:/\}(-*)'/ -}),a.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\[/,end:/\](-*)'/}),{begin:'"',end:'"', -relevance:0},{begin:"'",end:"'",relevance:0}]},{className:"number",relevance:0, -beforeMatch:/([^a-zA-Z0-9._])/,variants:[{ -match:/0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?\d+i?/},{ -match:/0[xX][0-9a-fA-F]+([pP][+-]?\d+)?[Li]?/},{ -match:/(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?[Li]?/}]},{begin:"%",end:"%"},{ -begin:e(/[a-zA-Z][a-zA-Z_0-9]*/,"\\s+<-\\s+")},{begin:"`",end:"`",contains:[{ -begin:/\\./}]}]}}})()); -hljs.registerLanguage("ruby",(()=>{"use strict";function e(...e){ -return e.map((e=>{return(n=e)?"string"==typeof n?n:n.source:null;var n -})).join("")}return n=>{ -var a,i="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",s={ -keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor __FILE__", -built_in:"proc lambda",literal:"true false nil"},r={className:"doctag", -begin:"@[A-Za-z]+"},b={begin:"#<",end:">"},t=[n.COMMENT("#","$",{contains:[r] -}),n.COMMENT("^=begin","^=end",{contains:[r],relevance:10 -}),n.COMMENT("^__END__","\\n$")],c={className:"subst",begin:/#\{/,end:/\}/, -keywords:s},d={className:"string",contains:[n.BACKSLASH_ESCAPE,c],variants:[{ -begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:/%[qQwWx]?\(/, -end:/\)/},{begin:/%[qQwWx]?\[/,end:/\]/},{begin:/%[qQwWx]?\{/,end:/\}/},{ -begin:/%[qQwWx]?/},{begin:/%[qQwWx]?\//,end:/\//},{begin:/%[qQwWx]?%/, -end:/%/},{begin:/%[qQwWx]?-/,end:/-/},{begin:/%[qQwWx]?\|/,end:/\|/},{ -begin:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/},{ -begin:/<<[-~]?'?(\w+)\n(?:[^\n]*\n)*?\s*\1\b/,returnBegin:!0,contains:[{ -begin:/<<[-~]?'?/},n.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/, -contains:[n.BACKSLASH_ESCAPE,c]})]}]},g="[0-9](_?[0-9])*",l={className:"number", -relevance:0,variants:[{ -begin:`\\b([1-9](_?[0-9])*|0)(\\.(${g}))?([eE][+-]?(${g})|r)?i?\\b`},{ -begin:"\\b0[dD][0-9](_?[0-9])*r?i?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*r?i?\\b" -},{begin:"\\b0[oO][0-7](_?[0-7])*r?i?\\b"},{ -begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"},{ -begin:"\\b0(_?[0-7])+r?i?\\b"}]},o={className:"params",begin:"\\(",end:"\\)", -endsParent:!0,keywords:s},_=[d,{className:"class",beginKeywords:"class module", -end:"$|;",illegal:/=/,contains:[n.inherit(n.TITLE_MODE,{ -begin:"[A-Za-z_]\\w*(::\\w+)*(\\?|!)?"}),{begin:"<\\s*",contains:[{ -begin:"("+n.IDENT_RE+"::)?"+n.IDENT_RE}]}].concat(t)},{className:"function", -begin:e(/def\s*/,(a=i+"\\s*(\\(|;|$)",e("(?=",a,")"))),keywords:"def",end:"$|;", -contains:[n.inherit(n.TITLE_MODE,{begin:i}),o].concat(t)},{begin:n.IDENT_RE+"::" -},{className:"symbol",begin:n.UNDERSCORE_IDENT_RE+"(!|\\?)?:",relevance:0},{ -className:"symbol",begin:":(?!\\s)",contains:[d,{begin:i}],relevance:0},l,{ -className:"variable", -begin:"(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])(?![A-Za-z])(?![@$?'])"},{ -className:"params",begin:/\|/,end:/\|/,relevance:0,keywords:s},{ -begin:"("+n.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[{ -className:"regexp",contains:[n.BACKSLASH_ESCAPE,c],illegal:/\n/,variants:[{ -begin:"/",end:"/[a-z]*"},{begin:/%r\{/,end:/\}[a-z]*/},{begin:"%r\\(", -end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}] -}].concat(b,t),relevance:0}].concat(b,t);c.contains=_,o.contains=_;var E=[{ -begin:/^\s*=>/,starts:{end:"$",contains:_}},{className:"meta", -begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+>|(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>)(?=[ ])", -starts:{end:"$",contains:_}}];return t.unshift(b),{name:"Ruby", -aliases:["rb","gemspec","podspec","thor","irb"],keywords:s,illegal:/\/\*/, -contains:[n.SHEBANG({binary:"ruby"})].concat(E).concat(t).concat(_)}}})()); -hljs.registerLanguage("rust",(()=>{"use strict";return e=>{ -const n="([ui](8|16|32|64|128|size)|f(32|64))?",t="drop i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize f32 f64 str char bool Box Option Result String Vec Copy Send Sized Sync Drop Fn FnMut FnOnce ToOwned Clone Debug PartialEq PartialOrd Eq Ord AsRef AsMut Into From Default Iterator Extend IntoIterator DoubleEndedIterator ExactSizeIterator SliceConcatExt ToString assert! assert_eq! bitflags! bytes! cfg! col! concat! concat_idents! debug_assert! debug_assert_eq! env! panic! file! format! format_args! include_bin! include_str! line! local_data_key! module_path! option_env! print! println! select! stringify! try! unimplemented! unreachable! vec! write! writeln! macro_rules! assert_ne! debug_assert_ne!" -;return{name:"Rust",aliases:["rs"],keywords:{$pattern:e.IDENT_RE+"!?", -keyword:"abstract as async await become box break const continue crate do dyn else enum extern false final fn for if impl in let loop macro match mod move mut override priv pub ref return self Self static struct super trait true try type typeof unsafe unsized use virtual where while yield", -literal:"true false Some None Ok Err",built_in:t},illegal:""}]}}})()); -hljs.registerLanguage("scss",(()=>{"use strict";return e=>{var t="@[a-z-]+",i={ -className:"variable",begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b"},r={ -className:"number",begin:"#[0-9A-Fa-f]+"} -;return e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE, -e.APOS_STRING_MODE,e.C_BLOCK_COMMENT_MODE,{name:"SCSS",case_insensitive:!0, -illegal:"[=/|']",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{ -className:"selector-id",begin:"#[A-Za-z0-9_-]+",relevance:0},{ -className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0},{ -className:"selector-attr",begin:"\\[",end:"\\]",illegal:"$"},{ -className:"selector-tag", -begin:"\\b(a|abbr|acronym|address|area|article|aside|audio|b|base|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|command|datalist|dd|del|details|dfn|div|dl|dt|em|embed|fieldset|figcaption|figure|footer|form|frame|frameset|(h[1-6])|head|header|hgroup|hr|html|i|iframe|img|input|ins|kbd|keygen|label|legend|li|link|map|mark|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|pre|progress|q|rp|rt|ruby|samp|script|section|select|small|span|strike|strong|style|sub|sup|table|tbody|td|textarea|tfoot|th|thead|time|title|tr|tt|ul|var|video)\\b", -relevance:0},{className:"selector-pseudo", -begin:":(visited|valid|root|right|required|read-write|read-only|out-range|optional|only-of-type|only-child|nth-of-type|nth-last-of-type|nth-last-child|nth-child|not|link|left|last-of-type|last-child|lang|invalid|indeterminate|in-range|hover|focus|first-of-type|first-line|first-letter|first-child|first|enabled|empty|disabled|default|checked|before|after|active)" -},{className:"selector-pseudo", -begin:"::(after|before|choices|first-letter|first-line|repeat-index|repeat-item|selection|value)" -},i,{className:"attribute", -begin:"\\b(src|z-index|word-wrap|word-spacing|word-break|width|widows|white-space|visibility|vertical-align|unicode-bidi|transition-timing-function|transition-property|transition-duration|transition-delay|transition|transform-style|transform-origin|transform|top|text-underline-position|text-transform|text-shadow|text-rendering|text-overflow|text-indent|text-decoration-style|text-decoration-line|text-decoration-color|text-decoration|text-align-last|text-align|tab-size|table-layout|right|resize|quotes|position|pointer-events|perspective-origin|perspective|page-break-inside|page-break-before|page-break-after|padding-top|padding-right|padding-left|padding-bottom|padding|overflow-y|overflow-x|overflow-wrap|overflow|outline-width|outline-style|outline-offset|outline-color|outline|orphans|order|opacity|object-position|object-fit|normal|none|nav-up|nav-right|nav-left|nav-index|nav-down|min-width|min-height|max-width|max-height|mask|marks|margin-top|margin-right|margin-left|margin-bottom|margin|list-style-type|list-style-position|list-style-image|list-style|line-height|letter-spacing|left|justify-content|initial|inherit|ime-mode|image-orientation|image-resolution|image-rendering|icon|hyphens|height|font-weight|font-variant-ligatures|font-variant|font-style|font-stretch|font-size-adjust|font-size|font-language-override|font-kerning|font-feature-settings|font-family|font|float|flex-wrap|flex-shrink|flex-grow|flex-flow|flex-direction|flex-basis|flex|filter|empty-cells|display|direction|cursor|counter-reset|counter-increment|content|column-width|column-span|column-rule-width|column-rule-style|column-rule-color|column-rule|column-gap|column-fill|column-count|columns|color|clip-path|clip|clear|caption-side|break-inside|break-before|break-after|box-sizing|box-shadow|box-decoration-break|bottom|border-width|border-top-width|border-top-style|border-top-right-radius|border-top-left-radius|border-top-color|border-top|border-style|border-spacing|border-right-width|border-right-style|border-right-color|border-right|border-radius|border-left-width|border-left-style|border-left-color|border-left|border-image-width|border-image-source|border-image-slice|border-image-repeat|border-image-outset|border-image|border-color|border-collapse|border-bottom-width|border-bottom-style|border-bottom-right-radius|border-bottom-left-radius|border-bottom-color|border-bottom|border|background-size|background-repeat|background-position|background-origin|background-image|background-color|background-clip|background-attachment|background-blend-mode|background|backface-visibility|auto|animation-timing-function|animation-play-state|animation-name|animation-iteration-count|animation-fill-mode|animation-duration|animation-direction|animation-delay|animation|align-self|align-items|align-content)\\b", -illegal:"[^\\s]"},{ -begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b" -},{begin:":",end:";", -contains:[i,r,e.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,{ -className:"meta",begin:"!important"}]},{begin:"@(page|font-face)",lexemes:t, -keywords:"@page @font-face"},{begin:"@",end:"[{;]",returnBegin:!0, -keywords:"and or not only",contains:[{begin:t,className:"keyword" -},i,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,r,e.CSS_NUMBER_MODE]}]}}})()); -hljs.registerLanguage("shell",(()=>{"use strict";return s=>({ -name:"Shell Session",aliases:["console"],contains:[{className:"meta", -begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#]/,starts:{end:/[^\\](?=\s*$)/, -subLanguage:"bash"}}]})})()); -hljs.registerLanguage("sql",(()=>{"use strict";function e(e){ -return e?"string"==typeof e?e:e.source:null}function r(...r){ -return r.map((r=>e(r))).join("")}function t(...r){ -return"("+r.map((r=>e(r))).join("|")+")"}return e=>{ -const n=e.COMMENT("--","$"),a=["true","false","unknown"],i=["bigint","binary","blob","boolean","char","character","clob","date","dec","decfloat","decimal","float","int","integer","interval","nchar","nclob","national","numeric","real","row","smallint","time","timestamp","varchar","varying","varbinary"],s=["abs","acos","array_agg","asin","atan","avg","cast","ceil","ceiling","coalesce","corr","cos","cosh","count","covar_pop","covar_samp","cume_dist","dense_rank","deref","element","exp","extract","first_value","floor","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","last_value","lead","listagg","ln","log","log10","lower","max","min","mod","nth_value","ntile","nullif","percent_rank","percentile_cont","percentile_disc","position","position_regex","power","rank","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","row_number","sin","sinh","sqrt","stddev_pop","stddev_samp","substring","substring_regex","sum","tan","tanh","translate","translate_regex","treat","trim","trim_array","unnest","upper","value_of","var_pop","var_samp","width_bucket"],o=["create table","insert into","primary key","foreign key","not null","alter table","add constraint","grouping sets","on overflow","character set","respect nulls","ignore nulls","nulls first","nulls last","depth first","breadth first"],c=s,l=["abs","acos","all","allocate","alter","and","any","are","array","array_agg","array_max_cardinality","as","asensitive","asin","asymmetric","at","atan","atomic","authorization","avg","begin","begin_frame","begin_partition","between","bigint","binary","blob","boolean","both","by","call","called","cardinality","cascaded","case","cast","ceil","ceiling","char","char_length","character","character_length","check","classifier","clob","close","coalesce","collate","collect","column","commit","condition","connect","constraint","contains","convert","copy","corr","corresponding","cos","cosh","count","covar_pop","covar_samp","create","cross","cube","cume_dist","current","current_catalog","current_date","current_default_transform_group","current_path","current_role","current_row","current_schema","current_time","current_timestamp","current_path","current_role","current_transform_group_for_type","current_user","cursor","cycle","date","day","deallocate","dec","decimal","decfloat","declare","default","define","delete","dense_rank","deref","describe","deterministic","disconnect","distinct","double","drop","dynamic","each","element","else","empty","end","end_frame","end_partition","end-exec","equals","escape","every","except","exec","execute","exists","exp","external","extract","false","fetch","filter","first_value","float","floor","for","foreign","frame_row","free","from","full","function","fusion","get","global","grant","group","grouping","groups","having","hold","hour","identity","in","indicator","initial","inner","inout","insensitive","insert","int","integer","intersect","intersection","interval","into","is","join","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","language","large","last_value","lateral","lead","leading","left","like","like_regex","listagg","ln","local","localtime","localtimestamp","log","log10","lower","match","match_number","match_recognize","matches","max","member","merge","method","min","minute","mod","modifies","module","month","multiset","national","natural","nchar","nclob","new","no","none","normalize","not","nth_value","ntile","null","nullif","numeric","octet_length","occurrences_regex","of","offset","old","omit","on","one","only","open","or","order","out","outer","over","overlaps","overlay","parameter","partition","pattern","per","percent","percent_rank","percentile_cont","percentile_disc","period","portion","position","position_regex","power","precedes","precision","prepare","primary","procedure","ptf","range","rank","reads","real","recursive","ref","references","referencing","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","release","result","return","returns","revoke","right","rollback","rollup","row","row_number","rows","running","savepoint","scope","scroll","search","second","seek","select","sensitive","session_user","set","show","similar","sin","sinh","skip","smallint","some","specific","specifictype","sql","sqlexception","sqlstate","sqlwarning","sqrt","start","static","stddev_pop","stddev_samp","submultiset","subset","substring","substring_regex","succeeds","sum","symmetric","system","system_time","system_user","table","tablesample","tan","tanh","then","time","timestamp","timezone_hour","timezone_minute","to","trailing","translate","translate_regex","translation","treat","trigger","trim","trim_array","true","truncate","uescape","union","unique","unknown","unnest","update ","upper","user","using","value","values","value_of","var_pop","var_samp","varbinary","varchar","varying","versioning","when","whenever","where","width_bucket","window","with","within","without","year","add","asc","collation","desc","final","first","last","view"].filter((e=>!s.includes(e))),u={ -begin:r(/\b/,t(...c),/\s*\(/),keywords:{built_in:c.join(" ")}};return{ -name:"SQL",case_insensitive:!0,illegal:/[{}]|<\//,keywords:{ -$pattern:/\b[\w\.]+/,keyword:((e,{exceptions:r,when:t}={})=>{const n=t -;return r=r||[],e.map((e=>e.match(/\|\d+$/)||r.includes(e)?e:n(e)?e+"|0":e)) -})(l,{when:e=>e.length<3}).join(" "),literal:a.join(" "),type:i.join(" "), -built_in:"current_catalog current_date current_default_transform_group current_path current_role current_schema current_transform_group_for_type current_user session_user system_time system_user current_time localtime current_timestamp localtimestamp" -},contains:[{begin:t(...o),keywords:{$pattern:/[\w\.]+/, -keyword:l.concat(o).join(" "),literal:a.join(" "),type:i.join(" ")}},{ -className:"type", -begin:t("double precision","large object","with timezone","without timezone") -},u,{className:"variable",begin:/@[a-z0-9]+/},{className:"string",variants:[{ -begin:/'/,end:/'/,contains:[{begin:/''/}]}]},{begin:/"/,end:/"/,contains:[{ -begin:/""/}]},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,n,{className:"operator", -begin:/[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,relevance:0}]}}})()); -hljs.registerLanguage("swift",(()=>{"use strict";function e(e){ -return e?"string"==typeof e?e:e.source:null}function n(e){return i("(?=",e,")")} -function i(...n){return n.map((n=>e(n))).join("")}function a(...n){ -return"("+n.map((n=>e(n))).join("|")+")"} -const t=e=>i(/\b/,e,/\w$/.test(e)?/\b/:/\B/),u=["Protocol","Type"].map(t),s=["init","self"].map(t),r=["Any","Self"],o=["associatedtype",/as\?/,/as!/,"as","break","case","catch","class","continue","convenience","default","defer","deinit","didSet","do","dynamic","else","enum","extension","fallthrough","fileprivate(set)","fileprivate","final","for","func","get","guard","if","import","indirect","infix",/init\?/,/init!/,"inout","internal(set)","internal","in","is","lazy","let","mutating","nonmutating","open(set)","open","operator","optional","override","postfix","precedencegroup","prefix","private(set)","private","protocol","public(set)","public","repeat","required","rethrows","return","set","some","static","struct","subscript","super","switch","throws","throw",/try\?/,/try!/,"try","typealias","unowned(safe)","unowned(unsafe)","unowned","var","weak","where","while","willSet"],l=["false","nil","true"],c=["#colorLiteral","#column","#dsohandle","#else","#elseif","#endif","#error","#file","#fileID","#fileLiteral","#filePath","#function","#if","#imageLiteral","#keyPath","#line","#selector","#sourceLocation","#warn_unqualified_access","#warning"],b=["abs","all","any","assert","assertionFailure","debugPrint","dump","fatalError","getVaList","isKnownUniquelyReferenced","max","min","numericCast","pointwiseMax","pointwiseMin","precondition","preconditionFailure","print","readLine","repeatElement","sequence","stride","swap","swift_unboxFromSwiftValueWithType","transcode","type","unsafeBitCast","unsafeDowncast","withExtendedLifetime","withUnsafeMutablePointer","withUnsafePointer","withVaList","withoutActuallyEscaping","zip"],p=a(/[/=\-+!*%<>&|^~?]/,/[\u00A1-\u00A7]/,/[\u00A9\u00AB]/,/[\u00AC\u00AE]/,/[\u00B0\u00B1]/,/[\u00B6\u00BB\u00BF\u00D7\u00F7]/,/[\u2016-\u2017]/,/[\u2020-\u2027]/,/[\u2030-\u203E]/,/[\u2041-\u2053]/,/[\u2055-\u205E]/,/[\u2190-\u23FF]/,/[\u2500-\u2775]/,/[\u2794-\u2BFF]/,/[\u2E00-\u2E7F]/,/[\u3001-\u3003]/,/[\u3008-\u3020]/,/[\u3030]/),F=a(p,/[\u0300-\u036F]/,/[\u1DC0-\u1DFF]/,/[\u20D0-\u20FF]/,/[\uFE00-\uFE0F]/,/[\uFE20-\uFE2F]/),d=i(p,F,"*"),g=a(/[a-zA-Z_]/,/[\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-\u00BA]/,/[\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]/,/[\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]/,/[\u1E00-\u1FFF]/,/[\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]/,/[\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]/,/[\u2C00-\u2DFF\u2E80-\u2FFF]/,/[\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]/,/[\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-\uFE44]/,/[\uFE47-\uFFFD]/),f=a(g,/\d/,/[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/),m=i(g,f,"*"),w=i(/[A-Z]/,f,"*"),E=["autoclosure",i(/convention\(/,a("swift","block","c"),/\)/),"discardableResult","dynamicCallable","dynamicMemberLookup","escaping","frozen","GKInspectable","IBAction","IBDesignable","IBInspectable","IBOutlet","IBSegueAction","inlinable","main","nonobjc","NSApplicationMain","NSCopying","NSManaged",i(/objc\(/,m,/\)/),"objc","objcMembers","propertyWrapper","requires_stored_property_inits","testable","UIApplicationMain","unknown","usableFromInline"],y=["iOS","iOSApplicationExtension","macOS","macOSApplicationExtension","macCatalyst","macCatalystApplicationExtension","watchOS","watchOSApplicationExtension","tvOS","tvOSApplicationExtension","swift"] -;return e=>{const p=e.COMMENT("/\\*","\\*/",{contains:["self"]}),g={ -className:"keyword",begin:i(/\./,n(a(...u,...s))),end:a(...u,...s), -excludeBegin:!0},A={begin:i(/\./,a(...o)),relevance:0 -},C=o.filter((e=>"string"==typeof e)).concat(["_|0"]),v={variants:[{ -className:"keyword", -begin:a(...o.filter((e=>"string"!=typeof e)).concat(r).map(t),...s)}]},_={ -$pattern:a(/\b\w+(\(\w+\))?/,/#\w+/),keyword:C.concat(c).join(" "), -literal:l.join(" ")},N=[g,A,v],D=[{begin:i(/\./,a(...b)),relevance:0},{ -className:"built_in",begin:i(/\b/,a(...b),/(?=\()/)}],B={begin:/->/,relevance:0 -},M=[B,{className:"operator",relevance:0,variants:[{begin:d},{ -begin:`\\.(\\.|${F})+`}]}],h="([0-9a-fA-F]_*)+",S={className:"number", -relevance:0,variants:[{ -begin:"\\b(([0-9]_*)+)(\\.(([0-9]_*)+))?([eE][+-]?(([0-9]_*)+))?\\b"},{ -begin:`\\b0x(${h})(\\.(${h}))?([pP][+-]?(([0-9]_*)+))?\\b`},{ -begin:/\b0o([0-7]_*)+\b/},{begin:/\b0b([01]_*)+\b/}]},O=(e="")=>({ -className:"subst",variants:[{begin:i(/\\/,e,/[0\\tnr"']/)},{ -begin:i(/\\/,e,/u\{[0-9a-fA-F]{1,8}\}/)}]}),x=(e="")=>({className:"subst", -begin:i(/\\/,e,/[\t ]*(?:[\r\n]|\r\n)/)}),k=(e="")=>({className:"subst", -label:"interpol",begin:i(/\\/,e,/\(/),end:/\)/}),L=(e="")=>({begin:i(e,/"""/), -end:i(/"""/,e),contains:[O(e),x(e),k(e)]}),I=(e="")=>({begin:i(e,/"/), -end:i(/"/,e),contains:[O(e),k(e)]}),$={className:"string", -variants:[L(),L("#"),L("##"),L("###"),I(),I("#"),I("##"),I("###")]},T=[{ -begin:i(/`/,m,/`/)},{className:"variable",begin:/\$\d+/},{className:"variable", -begin:`\\$${f}+`}],j=[{begin:/(@|#)available\(/,end:/\)/,keywords:{ -$pattern:/[@#]?\w+/,keyword:y.concat(["@available","#available"]).join(" ")}, -contains:[...M,S,$]},{className:"keyword",begin:i(/@/,a(...E))},{ -className:"meta",begin:i(/@/,m)}],K={begin:n(/\b[A-Z]/),relevance:0,contains:[{ -className:"type", -begin:i(/(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)/,f,"+") -},{className:"type",begin:w,relevance:0},{begin:/[?!]+/,relevance:0},{ -begin:/\.\.\./,relevance:0},{begin:i(/\s+&\s+/,n(w)),relevance:0}]},P={ -begin://,keywords:_,contains:[...N,...j,B,K]};K.contains.push(P) -;for(const e of $.variants){const n=e.contains.find((e=>"interpol"===e.label)) -;n.keywords=_;const i=[...N,...D,...M,S,$,...T];n.contains=[...i,{begin:/\(/, -end:/\)/,contains:["self",...i]}]}return{name:"Swift",keywords:_, -contains:[e.C_LINE_COMMENT_MODE,p,{className:"function",beginKeywords:"func", -end:/\{/,excludeEnd:!0,contains:[e.inherit(e.TITLE_MODE,{ -begin:/[A-Za-z$_][0-9A-Za-z$_]*/}),{begin://},{className:"params", -begin:/\(/,end:/\)/,endsParent:!0,keywords:_, -contains:["self",...N,S,$,e.C_BLOCK_COMMENT_MODE,{begin:":"}],illegal:/["']/}], -illegal:/\[|%/},{className:"class", -beginKeywords:"struct protocol class extension enum",end:"\\{",excludeEnd:!0, -keywords:_,contains:[e.inherit(e.TITLE_MODE,{ -begin:/[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/}),...N]},{beginKeywords:"import", -end:/$/,contains:[e.C_LINE_COMMENT_MODE,p],relevance:0 -},...N,...D,...M,S,$,...T,...j,K]}}})()); -hljs.registerLanguage("typescript",(()=>{"use strict" -;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],s=[].concat(["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],["arguments","this","super","console","window","document","localStorage","module","global"],["Intl","DataView","Number","Math","Date","String","RegExp","Object","Function","Boolean","Error","Symbol","Set","Map","WeakSet","WeakMap","Proxy","Reflect","JSON","Promise","Float64Array","Int16Array","Int32Array","Int8Array","Uint16Array","Uint32Array","Float32Array","Array","Uint8Array","Uint8ClampedArray","ArrayBuffer"],["EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"]) -;function t(e){return i("(?=",e,")")}function i(...e){return e.map((e=>{ -return(n=e)?"string"==typeof n?n:n.source:null;var n})).join("")}return r=>{ -const c={$pattern:e, -keyword:n.concat(["type","namespace","typedef","interface","public","private","protected","implements","declare","abstract","readonly"]).join(" "), -literal:a.join(" "), -built_in:s.concat(["any","void","number","boolean","string","object","never","enum"]).join(" ") -},o={className:"meta",begin:"@[A-Za-z$_][0-9A-Za-z$_]*"},l=(e,n,a)=>{ -const s=e.contains.findIndex((e=>e.label===n)) -;if(-1===s)throw Error("can not find mode to replace");e.contains.splice(s,1,a) -},b=(r=>{const c=e,o={begin:/<[A-Za-z0-9\\._:-]+/, -end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ -const a=e[0].length+e.index,s=e.input[a];"<"!==s?">"===s&&(((e,{after:n})=>{ -const a="", -returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{ -begin:r.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0 -},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:l,contains:f}]}] -},{begin:/,/,relevance:0},{className:"",begin:/\s/,end:/\s*/,skip:!0},{ -variants:[{begin:"<>",end:""},{begin:o.begin,"on:begin":o.isTrulyOpeningTag, -end:o.end}],subLanguage:"xml",contains:[{begin:o.begin,end:o.end,skip:!0, -contains:["self"]}]}],relevance:0},{className:"function", -beginKeywords:"function",end:/[{;]/,excludeEnd:!0,keywords:l, -contains:["self",r.inherit(r.TITLE_MODE,{begin:c}),A],illegal:/%/},{ -beginKeywords:"while if switch catch for"},{className:"function", -begin:r.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", -returnBegin:!0,contains:[A,r.inherit(r.TITLE_MODE,{begin:c})]},{variants:[{ -begin:"\\."+c},{begin:"\\$"+c}],relevance:0},{className:"class", -beginKeywords:"class",end:/[{;=]/,excludeEnd:!0,illegal:/[:"[\]]/,contains:[{ -beginKeywords:"extends"},r.UNDERSCORE_TITLE_MODE]},{begin:/\b(?=constructor)/, -end:/[{;]/,excludeEnd:!0,contains:[r.inherit(r.TITLE_MODE,{begin:c}),"self",A] -},{begin:"(get|set)\\s+(?="+c+"\\()",end:/\{/,keywords:"get set", -contains:[r.inherit(r.TITLE_MODE,{begin:c}),{begin:/\(\)/},A]},{begin:/\$[(.]/}] -}})(r) -;return Object.assign(b.keywords,c),b.exports.PARAMS_CONTAINS.push(o),b.contains=b.contains.concat([o,{ -beginKeywords:"namespace",end:/\{/,excludeEnd:!0},{beginKeywords:"interface", -end:/\{/,excludeEnd:!0,keywords:"interface extends" -}]),l(b,"shebang",r.SHEBANG()),l(b,"use_strict",{className:"meta",relevance:10, -begin:/^\s*['"]use strict['"]/ -}),b.contains.find((e=>"function"===e.className)).relevance=0,Object.assign(b,{ -name:"TypeScript",aliases:["ts"]}),b}})()); -hljs.registerLanguage("vbnet",(()=>{"use strict";function e(e){ -return e?"string"==typeof e?e:e.source:null}function n(...n){ -return n.map((n=>e(n))).join("")}function t(...n){ -return"("+n.map((n=>e(n))).join("|")+")"}return e=>{ -const a=/\d{1,2}\/\d{1,2}\/\d{4}/,i=/\d{4}-\d{1,2}-\d{1,2}/,s=/(\d|1[012])(:\d+){0,2} *(AM|PM)/,r=/\d{1,2}(:\d{1,2}){1,2}/,o={ -className:"literal",variants:[{begin:n(/# */,t(i,a),/ *#/)},{ -begin:n(/# */,r,/ *#/)},{begin:n(/# */,s,/ *#/)},{ -begin:n(/# */,t(i,a),/ +/,t(s,r),/ *#/)}]},l=e.COMMENT(/'''/,/$/,{contains:[{ -className:"doctag",begin:/<\/?/,end:/>/}]}),c=e.COMMENT(null,/$/,{variants:[{ -begin:/'/},{begin:/([\t ]|^)REM(?=\s)/}]});return{name:"Visual Basic .NET", -aliases:["vb"],case_insensitive:!0,classNameAliases:{label:"symbol"},keywords:{ -keyword:"addhandler alias aggregate ansi as async assembly auto binary by byref byval call case catch class compare const continue custom declare default delegate dim distinct do each equals else elseif end enum erase error event exit explicit finally for friend from function get global goto group handles if implements imports in inherits interface into iterator join key let lib loop me mid module mustinherit mustoverride mybase myclass namespace narrowing new next notinheritable notoverridable of off on operator option optional order overloads overridable overrides paramarray partial preserve private property protected public raiseevent readonly redim removehandler resume return select set shadows shared skip static step stop structure strict sub synclock take text then throw to try unicode until using when where while widening with withevents writeonly yield", -built_in:"addressof and andalso await directcast gettype getxmlnamespace is isfalse isnot istrue like mod nameof new not or orelse trycast typeof xor cbool cbyte cchar cdate cdbl cdec cint clng cobj csbyte cshort csng cstr cuint culng cushort", -type:"boolean byte char date decimal double integer long object sbyte short single string uinteger ulong ushort", -literal:"true false nothing"}, -illegal:"//|\\{|\\}|endif|gosub|variant|wend|^\\$ ",contains:[{ -className:"string",begin:/"(""|[^/n])"C\b/},{className:"string",begin:/"/, -end:/"/,illegal:/\n/,contains:[{begin:/""/}]},o,{className:"number",relevance:0, -variants:[{begin:/\b\d[\d_]*((\.[\d_]+(E[+-]?[\d_]+)?)|(E[+-]?[\d_]+))[RFD@!#]?/ -},{begin:/\b\d[\d_]*((U?[SIL])|[%&])?/},{begin:/&H[\dA-F_]+((U?[SIL])|[%&])?/},{ -begin:/&O[0-7_]+((U?[SIL])|[%&])?/},{begin:/&B[01_]+((U?[SIL])|[%&])?/}]},{ -className:"label",begin:/^\w+:/},l,c,{className:"meta", -begin:/[\t ]*#(const|disable|else|elseif|enable|end|externalsource|if|region)\b/, -end:/$/,keywords:{ -"meta-keyword":"const disable else elseif enable end externalsource if region then" -},contains:[c]}]}}})()); -hljs.registerLanguage("yaml",(()=>{"use strict";return e=>{ -var n="true false yes no null",a="[\\w#;/?:@&=+$,.~*'()[\\]]+",s={ -className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/ -},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable", -variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},i=e.inherit(s,{ -variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),l={ -end:",",endsWithParent:!0,excludeEnd:!0,contains:[],keywords:n,relevance:0},t={ -begin:/\{/,end:/\}/,contains:[l],illegal:"\\n",relevance:0},g={begin:"\\[", -end:"\\]",contains:[l],illegal:"\\n",relevance:0},b=[{className:"attr", -variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{ -begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)" -}]},{className:"meta",begin:"^---\\s*$",relevance:10},{className:"string", -begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{ -begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0, -relevance:0},{className:"type",begin:"!\\w+!"+a},{className:"type", -begin:"!<"+a+">"},{className:"type",begin:"!"+a},{className:"type",begin:"!!"+a -},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta", -begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)", -relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{ -className:"number", -begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b" -},{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},t,g,s],r=[...b] -;return r.pop(),r.push(i),l.contains=r,{name:"YAML",case_insensitive:!0, -aliases:["yml","YAML"],contains:b}}})()); \ No newline at end of file diff --git a/pywebio/html/js/prism.min.js b/pywebio/html/js/prism.min.js new file mode 100644 index 00000000..df604f26 --- /dev/null +++ b/pywebio/html/js/prism.min.js @@ -0,0 +1,42 @@ +/* PrismJS 1.23.0 +https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript+bash+batch+docker+erlang+go+http+java+json+latex+less+lua+makefile+markdown+markup-templating+nginx+pascal+perl+php+powershell+python+r+ruby+rust+sass+sql+swift+typescript+yaml */ +var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,n=0,M={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof W?new W(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=l.reach);y+=m.value.length,m=m.next){var k=m.value;if(r.length>n.length)return;if(!(k instanceof W)){var b,x=1;if(h){if(!(b=z(p,y,n,f)))break;var w=b.index,A=b.index+b[0].length,P=y;for(P+=m.value.length;P<=w;)m=m.next,P+=m.value.length;if(P-=m.value.length,y=P,m.value instanceof W)continue;for(var S=m;S!==r.tail&&(Pl.reach&&(l.reach=N);var j=m.prev;O&&(j=I(r,j,O),y+=O.length),q(r,j,x);var C=new W(o,g?M.tokenize(E,g):E,d,E);if(m=I(r,j,C),L&&I(r,m,L),1l.reach&&(l.reach=_.reach)}}}}}}(e,a,n,a.head,0),function(e){var n=[],r=e.head.next;for(;r!==e.tail;)n.push(r.value),r=r.next;return n}(a)},hooks:{all:{},add:function(e,n){var r=M.hooks.all;r[e]=r[e]||[],r[e].push(n)},run:function(e,n){var r=M.hooks.all[e];if(r&&r.length)for(var t,a=0;t=r[a++];)t(n)}},Token:W};function W(e,n,r,t){this.type=e,this.content=n,this.alias=r,this.length=0|(t||"").length}function z(e,n,r,t){e.lastIndex=n;var a=e.exec(r);if(a&&t&&a[1]){var i=a[1].length;a.index+=i,a[0]=a[0].slice(i)}return a}function i(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function I(e,n,r){var t=n.next,a={value:r,prev:n,next:t};return n.next=a,t.prev=a,e.length++,a}function q(e,n,r){for(var t=n.next,a=0;a"+a.content+""},!u.document)return u.addEventListener&&(M.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),r=n.language,t=n.code,a=n.immediateClose;u.postMessage(M.highlight(t,M.languages[r],r)),a&&u.close()},!1)),M;var e=M.util.currentScript();function r(){M.manual||M.highlightAll()}if(e&&(M.filename=e.src,e.hasAttribute("data-manual")&&(M.manual=!0)),!M.manual){var t=document.readyState;"loading"===t||"interactive"===t&&e&&e.defer?document.addEventListener("DOMContentLoaded",r):window.requestAnimationFrame?window.requestAnimationFrame(r):window.setTimeout(r,16)}return M}(_self);"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism); +Prism.languages.markup={comment://,prolog:/<\?[\s\S]+?\?>/,doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/,name:/[^\s<>'"]+/}},cdata://i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(a,e){var s={};s["language-"+e]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[e]},s.cdata=/^$/i;var n={"included-cdata":{pattern://i,inside:s}};n["language-"+e]={pattern:/[\s\S]+/,inside:Prism.languages[e]};var t={};t[a]={pattern:RegExp("(<__[^>]*>)(?:))*\\]\\]>|(?!)".replace(/__/g,function(){return a}),"i"),lookbehind:!0,greedy:!0,inside:n},Prism.languages.insertBefore("markup","cdata",t)}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml; +!function(s){var e=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;s.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+e.source+"|(?:[^\\\\\r\n()\"']|\\\\[^])*)\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+e.source+"$"),alias:"url"}}},selector:RegExp("[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+e.source+")*(?=\\s*\\{)"),string:{pattern:e,greedy:!0},property:/(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,important:/!important\b/i,function:/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:,]/},s.languages.css.atrule.inside.rest=s.languages.css;var t=s.languages.markup;t&&(t.tag.addInlined("style","css"),s.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/(^|["'\s])style\s*=\s*(?:"[^"]*"|'[^']*')/i,lookbehind:!0,inside:{"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{style:{pattern:/(["'])[\s\S]+(?=["']$)/,lookbehind:!0,alias:"language-css",inside:s.languages.css},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},"attr-name":/^style/i}}},t.tag))}(Prism); +Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/}; +Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*]|\\.|[^/\\\[\r\n])+\/[gimyus]{0,6}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-flags":/[a-z]+$/,"regex-delimiter":/^\/|\/$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{"template-string":{pattern:/`(?:\\[\s\S]|\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}|(?!\${)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\${(?:[^{}]|{(?:[^{}]|{[^}]*})*})+}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\${|}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.js=Prism.languages.javascript; +!function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},a={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--?|-=|\+\+?|\+=|!=?|~|\*\*?|\*=|\/=?|%=?|<<=?|>>=?|<=?|>=?|==?|&&?|&=|\^=?|\|\|?|\|=|\?|:/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|x[0-9a-fA-F]{1,2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)\w+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b\w+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+?)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:a},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)(["'])(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|(?!\2)[^\\`$])*\2/,lookbehind:!0,greedy:!0,inside:a}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:a.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|aptitude|apt-cache|apt-get|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:if|then|else|elif|fi|for|while|in|case|esac|function|select|do|done|until)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|break|cd|continue|eval|exec|exit|export|getopts|hash|pwd|readonly|return|shift|test|times|trap|umask|unset|alias|bind|builtin|caller|command|declare|echo|enable|help|let|local|logout|mapfile|printf|read|readarray|source|type|typeset|ulimit|unalias|set|shopt)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:true|false)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|==?|!=?|=~|<<[<-]?|[&\d]?>>|\d?[<>]&?|&[>&]?|\|[&|]?|<=?|>=?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var s=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],i=a.variable[1].inside,o=0;o>)?=)/],number:i,operator:/[*\/%+\-&^|]=?|<<=?|>>=?|[!~_=]/,punctuation:/[()',]/}},{pattern:/((?:^|[&(])[ \t]*@?)\w+\b(?:"(?:[\\"]"|[^"])*"(?!")|[^"^&)\r\n]|\^(?:\r\n|[\s\S]))*/im,lookbehind:!0,inside:{keyword:/^\w+\b/i,string:n,parameter:t,label:{pattern:/(^\s*):\S+/m,lookbehind:!0,alias:"property"},variable:r,number:i,operator:/\^/}}],operator:/[&@]/,punctuation:/[()']/}}(); +!function(e){var r="(?:[ \t]+(?![ \t])(?:)?|)".replace(//g,function(){return"\\\\[\r\n](?:\\s|\\\\[\r\n]|#.*(?!.))*(?![\\s#]|\\\\[\r\n])"}),n="\"(?:[^\"\\\\\r\n]|\\\\(?:\r\n|[^]))*\"|'(?:[^'\\\\\r\n]|\\\\(?:\r\n|[^]))*'",t="--[\\w-]+=(?:|(?![\"'])(?:[^\\s\\\\]|\\\\.)+)".replace(//g,function(){return n}),o={pattern:RegExp(n),greedy:!0},i={pattern:/(^[ \t]*)#.*/m,lookbehind:!0,greedy:!0};function a(e,n){return e=e.replace(//g,function(){return t}).replace(//g,function(){return r}),RegExp(e,n)}e.languages.docker={instruction:{pattern:/(^[ \t]*)(?:ADD|ARG|CMD|COPY|ENTRYPOINT|ENV|EXPOSE|FROM|HEALTHCHECK|LABEL|MAINTAINER|ONBUILD|RUN|SHELL|STOPSIGNAL|USER|VOLUME|WORKDIR)(?=\s)(?:\\.|[^\r\n\\])*(?:\\$(?:\s|#.*$)*(?![\s#])(?:\\.|[^\r\n\\])*)*/im,lookbehind:!0,greedy:!0,inside:{options:{pattern:a("(^(?:ONBUILD)?\\w+)(?:)*","i"),lookbehind:!0,greedy:!0,inside:{property:{pattern:/(^|\s)--[\w-]+/,lookbehind:!0},string:[o,{pattern:/(=)(?!["'])(?:[^\s\\]|\\.)+/,lookbehind:!0}],operator:/\\$/m,punctuation:/=/}},keyword:[{pattern:a("(^(?:ONBUILD)?HEALTHCHECK(?:)*)(?:CMD|NONE)\\b","i"),lookbehind:!0,greedy:!0},{pattern:a("(^(?:ONBUILD)?FROM(?:)*(?!--)[^ \t\\\\]+)AS","i"),lookbehind:!0,greedy:!0},{pattern:a("(^ONBUILD)\\w+","i"),lookbehind:!0,greedy:!0},{pattern:/^\w+/,greedy:!0}],comment:i,string:o,variable:/\$(?:\w+|\{[^{}"'\\]*\})/,operator:/\\$/m}},comment:i},e.languages.dockerfile=e.languages.docker}(Prism); +Prism.languages.erlang={comment:/%.+/,string:{pattern:/"(?:\\.|[^\\"\r\n])*"/,greedy:!0},"quoted-function":{pattern:/'(?:\\.|[^\\'\r\n])+'(?=\()/,alias:"function"},"quoted-atom":{pattern:/'(?:\\.|[^\\'\r\n])+'/,alias:"atom"},boolean:/\b(?:true|false)\b/,keyword:/\b(?:fun|when|case|of|end|if|receive|after|try|catch)\b/,number:[/\$\\?./,/\d+#[a-z0-9]+/i,/(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i],function:/\b[a-z][\w@]*(?=\()/,variable:{pattern:/(^|[^@])(?:\b|\?)[A-Z_][\w@]*/,lookbehind:!0},operator:[/[=\/<>:]=|=[:\/]=|\+\+?|--?|[=*\/!]|\b(?:bnot|div|rem|band|bor|bxor|bsl|bsr|not|and|or|xor|orelse|andalso)\b/,{pattern:/(^|[^<])<(?!<)/,lookbehind:!0},{pattern:/(^|[^>])>(?!>)/,lookbehind:!0}],atom:/\b[a-z][\w@]*/,punctuation:/[()[\]{}:;,.#|]|<<|>>/}; +Prism.languages.go=Prism.languages.extend("clike",{string:{pattern:/(["'`])(?:\\[\s\S]|(?!\1)[^\\])*\1/,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|iota|nil|true|false)\b/,number:/(?:\b0x[a-f\d]+|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[-+]?\d+)?)i?/i,operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:bool|byte|complex(?:64|128)|error|float(?:32|64)|rune|string|u?int(?:8|16|32|64)?|uintptr|append|cap|close|complex|copy|delete|imag|len|make|new|panic|print(?:ln)?|real|recover)\b/}),delete Prism.languages.go["class-name"]; +!function(t){t.languages.http={"request-line":{pattern:/^(?:GET|HEAD|POST|PUT|DELETE|CONNECT|OPTIONS|TRACE|PATCH|PRI|SEARCH)\s(?:https?:\/\/|\/)\S*\sHTTP\/[0-9.]+/m,inside:{method:{pattern:/^[A-Z]+\b/,alias:"property"},"request-target":{pattern:/^(\s)(?:https?:\/\/|\/)\S*(?=\s)/,lookbehind:!0,alias:"url",inside:t.languages.uri},"http-version":{pattern:/^(\s)HTTP\/[0-9.]+/,lookbehind:!0,alias:"property"}}},"response-status":{pattern:/^HTTP\/[0-9.]+ \d+ .+/m,inside:{"http-version":{pattern:/^HTTP\/[0-9.]+/,alias:"property"},"status-code":{pattern:/^(\s)\d+(?=\s)/,lookbehind:!0,alias:"number"},"reason-phrase":{pattern:/^(\s).+/,lookbehind:!0,alias:"string"}}},"header-name":{pattern:/^[\w-]+:(?=.)/m,alias:"keyword"}};var a,e,s,n=t.languages,i={"application/javascript":n.javascript,"application/json":n.json||n.javascript,"application/xml":n.xml,"text/xml":n.xml,"text/html":n.html,"text/css":n.css},r={"application/json":!0,"application/xml":!0};for(var p in i)if(i[p]){a=a||{};var o=r[p]?(void 0,s=(e=p).replace(/^[a-z]+\//,""),"(?:"+e+"|\\w+/(?:[\\w.-]+\\+)+"+s+"(?![+\\w.-]))"):p;a[p.replace(/\//g,"-")]={pattern:RegExp("(content-type:\\s*"+o+".*)(?:\\r?\\n|\\r){2}[\\s\\S]*","i"),lookbehind:!0,inside:i[p]}}a&&t.languages.insertBefore("http","header-name",a)}(Prism); +!function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n="(^|[^\\w.])(?:[a-z]\\w*\\s*\\.\\s*)*(?:[A-Z]\\w*\\s*\\.\\s*)*",a={pattern:RegExp(n+"[A-Z](?:[\\d_A-Z]*[a-z]\\w*)?\\b"),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{"class-name":[a,{pattern:RegExp(n+"[A-Z]\\w*(?=\\s+\\w+\\s*[;,=())])"),lookbehind:!0,inside:a.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(\:\:\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<(?:[\w\s,.&?]|<[\w\s,.&?]*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},namespace:{pattern:RegExp("(\\b(?:exports|import(?:\\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\\s+)(?!)[a-z]\\w*(?:\\.[a-z]\\w*)*\\.?".replace(//g,function(){return t.source})),lookbehind:!0,inside:{punctuation:/\./}}})}(Prism); +Prism.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:true|false)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},Prism.languages.webmanifest=Prism.languages.json; +!function(a){var e=/\\(?:[^a-z()[\]]|[a-z*]+)/i,n={"equation-command":{pattern:e,alias:"regex"}};a.languages.latex={comment:/%.*/m,cdata:{pattern:/(\\begin\{((?:verbatim|lstlisting)\*?)\})[\s\S]*?(?=\\end\{\2\})/,lookbehind:!0},equation:[{pattern:/\$\$(?:\\[\s\S]|[^\\$])+\$\$|\$(?:\\[\s\S]|[^\\$])+\$|\\\([\s\S]*?\\\)|\\\[[\s\S]*?\\\]/,inside:n,alias:"string"},{pattern:/(\\begin\{((?:equation|math|eqnarray|align|multline|gather)\*?)\})[\s\S]*?(?=\\end\{\2\})/,lookbehind:!0,inside:n,alias:"string"}],keyword:{pattern:/(\\(?:begin|end|ref|cite|label|usepackage|documentclass)(?:\[[^\]]+\])?\{)[^}]+(?=\})/,lookbehind:!0},url:{pattern:/(\\url\{)[^}]+(?=\})/,lookbehind:!0},headline:{pattern:/(\\(?:part|chapter|section|subsection|frametitle|subsubsection|paragraph|subparagraph|subsubparagraph|subsubsubparagraph)\*?(?:\[[^\]]+\])?\{)[^}]+(?=\}(?:\[[^\]]+\])?)/,lookbehind:!0,alias:"class-name"},function:{pattern:e,alias:"selector"},punctuation:/[[\]{}&]/},a.languages.tex=a.languages.latex,a.languages.context=a.languages.latex}(Prism); +Prism.languages.less=Prism.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-](?:\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};@\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/i,operator:/[+\-*\/]/}),Prism.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}}); +Prism.languages.lua={comment:/^#!.+|--(?:\[(=*)\[[\s\S]*?\]\1\]|.*)/m,string:{pattern:/(["'])(?:(?!\1)[^\\\r\n]|\\z(?:\r\n|\s)|\\(?:\r\n|[^z]))*\1|\[(=*)\[[\s\S]*?\]\2\]/,greedy:!0},number:/\b0x[a-f\d]+(?:\.[a-f\d]*)?(?:p[+-]?\d+)?\b|\b\d+(?:\.\B|(?:\.\d*)?(?:e[+-]?\d+)?\b)|\B\.\d+(?:e[+-]?\d+)?\b/i,keyword:/\b(?:and|break|do|else|elseif|end|false|for|function|goto|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,function:/(?!\d)\w+(?=\s*(?:[({]))/,operator:[/[-+*%^&|#]|\/\/?|<[<=]?|>[>=]?|[=~]=?/,{pattern:/(^|[^.])\.\.(?!\.)/,lookbehind:!0}],punctuation:/[\[\](){},;]|\.+|:+/}; +Prism.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},builtin:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,symbol:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:[/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,{pattern:/(\()(?:addsuffix|abspath|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:s|list)?)(?=[ \t])/,lookbehind:!0}],operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/}; +!function(u){function n(n){return n=n.replace(//g,function(){return"(?:\\\\.|[^\\\\\n\r]|(?:\n|\r\n?)(?!\n|\r\n?))"}),RegExp("((?:^|[^\\\\])(?:\\\\{2})*)(?:"+n+")")}var e="(?:\\\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\\\|\r\n`])+",t="\\|?__(?:\\|__)+\\|?(?:(?:\n|\r\n?)|(?![^]))".replace(/__/g,function(){return e}),a="\\|?[ \t]*:?-{3,}:?[ \t]*(?:\\|[ \t]*:?-{3,}:?[ \t]*)+\\|?(?:\n|\r\n?)";u.languages.markdown=u.languages.extend("markup",{}),u.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"font-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:u.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+t+a+"(?:"+t+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+t+a+")(?:"+t+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(e),inside:u.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+t+")"+a+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+t+"$"),inside:{"table-header":{pattern:RegExp(e),alias:"important",inside:u.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/``.+?``|`[^`\r\n]+`/,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n("\\b__(?:(?!_)|_(?:(?!_))+_)+__\\b|\\*\\*(?:(?!\\*)|\\*(?:(?!\\*))+\\*)+\\*\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n("\\b_(?:(?!_)|__(?:(?!_))+__)+_\\b|\\*(?:(?!\\*)|\\*\\*(?:(?!\\*))+\\*\\*)+\\*"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n("(~~?)(?:(?!~))+?\\2"),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},url:{pattern:n('!?\\[(?:(?!\\]))+\\](?:\\([^\\s)]+(?:[\t ]+"(?:\\\\.|[^"\\\\])*")?\\)|[ \t]?\\[(?:(?!\\]))+\\])'),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach(function(e){["url","bold","italic","strike"].forEach(function(n){e!==n&&(u.languages.markdown[e].inside.content.inside[n]=u.languages.markdown[n])})}),u.hooks.add("after-tokenize",function(n){"markdown"!==n.language&&"md"!==n.language||!function n(e){if(e&&"string"!=typeof e)for(var t=0,a=e.length;t=d.length);t++){var a=n[t];if("string"==typeof a||a.content&&"string"==typeof a.content){var r=d[m],o=p.tokenStack[r],c="string"==typeof a?a:a.content,i=v(k,r),u=c.indexOf(i);if(-1]?|>[>=]?|[+\-*\/]=?|[@^=]/i,{pattern:/(^|[^&])\b(?:and|as|div|exclude|in|include|is|mod|not|or|shl|shr|xor)\b/,lookbehind:!0}],punctuation:/\(\.|\.\)|[()\[\]:;,.]/},Prism.languages.objectpascal=Prism.languages.pascal; +Prism.languages.perl={comment:[{pattern:/(^\s*)=\w[\s\S]*?=cut.*/m,lookbehind:!0},{pattern:/(^|[^\\$])#.*/,lookbehind:!0}],string:[{pattern:/\b(?:q|qq|qx|qw)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\((?:[^()\\]|\\[\s\S])*\)/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\{(?:[^{}\\]|\\[\s\S])*\}/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*\[(?:[^[\]\\]|\\[\s\S])*\]/,greedy:!0},{pattern:/\b(?:q|qq|qx|qw)\s*<(?:[^<>\\]|\\[\s\S])*>/,greedy:!0},{pattern:/("|`)(?:(?!\1)[^\\]|\\[\s\S])*\1/,greedy:!0},{pattern:/'(?:[^'\\\r\n]|\\.)*'/,greedy:!0}],regex:[{pattern:/\b(?:m|qr)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s+([a-zA-Z0-9])(?:(?!\1)[^\\]|\\[\s\S])*\1[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngc]*/,greedy:!0},{pattern:/\b(?:m|qr)\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngc]*/,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*([^a-zA-Z0-9\s{(\[<])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s+([a-zA-Z0-9])(?:(?!\2)[^\\]|\\[\s\S])*\2(?:(?!\2)[^\\]|\\[\s\S])*\2[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\((?:[^()\\]|\\[\s\S])*\)\s*\((?:[^()\\]|\\[\s\S])*\)[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\{(?:[^{}\\]|\\[\s\S])*\}\s*\{(?:[^{}\\]|\\[\s\S])*\}[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*\[(?:[^[\]\\]|\\[\s\S])*\]\s*\[(?:[^[\]\\]|\\[\s\S])*\][msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^-]\b)(?:s|tr|y)\s*<(?:[^<>\\]|\\[\s\S])*>\s*<(?:[^<>\\]|\\[\s\S])*>[msixpodualngcer]*/,lookbehind:!0,greedy:!0},{pattern:/\/(?:[^\/\\\r\n]|\\.)*\/[msixpodualngc]*(?=\s*(?:$|[\r\n,.;})&|\-+*~<>!?^]|(?:lt|gt|le|ge|eq|ne|cmp|not|and|or|xor|x)\b))/,greedy:!0}],variable:[/[&*$@%]\{\^[A-Z]+\}/,/[&*$@%]\^[A-Z_]/,/[&*$@%]#?(?=\{)/,/[&*$@%]#?(?:(?:::)*'?(?!\d)[\w$]+)+(?:::)*/i,/[&*$@%]\d+/,/(?!%=)[$@%][!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~]/],filehandle:{pattern:/<(?![<=])\S*>|\b_\b/,alias:"symbol"},vstring:{pattern:/v\d+(?:\.\d+)*|\d+(?:\.\d+){2,}/,alias:"string"},function:{pattern:/sub [a-z0-9_]+/i,inside:{keyword:/sub/}},keyword:/\b(?:any|break|continue|default|delete|die|do|else|elsif|eval|for|foreach|given|goto|if|last|local|my|next|our|package|print|redo|require|return|say|state|sub|switch|undef|unless|until|use|when|while)\b/,number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)\b/,operator:/-[rwxoRWXOezsfdlpSbctugkTBMAC]\b|\+[+=]?|-[-=>]?|\*\*?=?|\/\/?=?|=[=~>]?|~[~=]?|\|\|?=?|&&?=?|<(?:=>?|<=?)?|>>?=?|![~=]?|[%^]=?|\.(?:=|\.\.?)?|[\\?]|\bx(?:=|\b)|\b(?:lt|gt|le|ge|eq|ne|cmp|not|and|or|xor)\b/,punctuation:/[{}[\];(),:]/}; +!function(a){var e=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,t=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/,/\b(?:null)\b/i],i=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,n=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,s=/[{}\[\](),:;]/;a.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:e,variable:/\$+(?:\w+\b|(?={))/i,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},keyword:[{pattern:/(\(\s*)\b(?:bool|boolean|int|integer|float|string|object|array)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:bool|int|float|string|object|array(?!\s*\()|mixed|self|static|callable|iterable|(?:null|false)(?=\s*\|))\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*[a-z0-9_|]\|\s*)(?:null|false)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:bool|int|float|string|object|void|array(?!\s*\()|mixed|self|static|callable|iterable|(?:null|false)(?=\s*\|))\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?[a-z0-9_|]\|\s*)(?:null|false)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:bool|int|float|string|object|void|array(?!\s*\()|mixed|iterable|(?:null|false)(?=\s*\|))\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:null|false)\b/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},/\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|class|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|eval|exit|extends|final|finally|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|match|new|or|parent|print|private|protected|public|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i],"argument-name":/\b[a-z_]\w*(?=\s*:(?!:))/i,"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,function:/\w+\s*(?=\()/,property:{pattern:/(->)[\w]+/,lookbehind:!0},number:i,operator:n,punctuation:s};var l={pattern:/{\$(?:{(?:{[^{}]+}|[^{}]+)}|[^{}])+}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)*)/,lookbehind:!0,inside:a.languages.php},r=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:l}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:l}}];a.languages.insertBefore("php","variable",{string:r}),a.languages.insertBefore("php","variable",{attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=]$)/,lookbehind:!0,inside:{comment:e,string:r,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,number:i,operator:n,punctuation:s}},delimiter:{pattern:/^#\[|]$/,alias:"punctuation"}}}}),a.hooks.add("before-tokenize",function(e){if(/<\?/.test(e.code)){a.languages["markup-templating"].buildPlaceholders(e,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/gi)}}),a.hooks.add("after-tokenize",function(e){a.languages["markup-templating"].tokenizePlaceholders(e,"php")})}(Prism); +!function(e){var i=Prism.languages.powershell={comment:[{pattern:/(^|[^`])<#[\s\S]*?#>/,lookbehind:!0},{pattern:/(^|[^`])#.*/,lookbehind:!0}],string:[{pattern:/"(?:`[\s\S]|[^`"])*"/,greedy:!0,inside:{function:{pattern:/(^|[^`])\$\((?:\$\([^\r\n()]*\)|(?!\$\()[^\r\n)])*\)/,lookbehind:!0,inside:{}}}},{pattern:/'(?:[^']|'')*'/,greedy:!0}],namespace:/\[[a-z](?:\[(?:\[[^\]]*]|[^\[\]])*]|[^\[\]])*]/i,boolean:/\$(?:true|false)\b/i,variable:/\$\w+\b/,function:[/\b(?:Add|Approve|Assert|Backup|Block|Checkpoint|Clear|Close|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom|ConvertTo|Copy|Debug|Deny|Disable|Disconnect|Dismount|Edit|Enable|Enter|Exit|Expand|Export|Find|ForEach|Format|Get|Grant|Group|Hide|Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push|Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset|Resize|Resolve|Restart|Restore|Resume|Revoke|Save|Search|Select|Send|Set|Show|Skip|Sort|Split|Start|Step|Stop|Submit|Suspend|Switch|Sync|Tee|Test|Trace|Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish|Unregister|Update|Use|Wait|Watch|Where|Write)-[a-z]+\b/i,/\b(?:ac|cat|chdir|clc|cli|clp|clv|compare|copy|cp|cpi|cpp|cvpa|dbp|del|diff|dir|ebp|echo|epal|epcsv|epsn|erase|fc|fl|ft|fw|gal|gbp|gc|gci|gcs|gdr|gi|gl|gm|gp|gps|group|gsv|gu|gv|gwmi|iex|ii|ipal|ipcsv|ipsn|irm|iwmi|iwr|kill|lp|ls|measure|mi|mount|move|mp|mv|nal|ndr|ni|nv|ogv|popd|ps|pushd|pwd|rbp|rd|rdr|ren|ri|rm|rmdir|rni|rnp|rp|rv|rvpa|rwmi|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls|sort|sp|spps|spsv|start|sv|swmi|tee|trcm|type|write)\b/i],keyword:/\b(?:Begin|Break|Catch|Class|Continue|Data|Define|Do|DynamicParam|Else|ElseIf|End|Exit|Filter|Finally|For|ForEach|From|Function|If|InlineScript|Parallel|Param|Process|Return|Sequence|Switch|Throw|Trap|Try|Until|Using|Var|While|Workflow)\b/i,operator:{pattern:/(\W?)(?:!|-(?:eq|ne|gt|ge|lt|le|sh[lr]|not|b?(?:and|x?or)|(?:Not)?(?:Like|Match|Contains|In)|Replace|Join|is(?:Not)?|as)\b|-[-=]?|\+[+=]?|[*\/%]=?)/i,lookbehind:!0},punctuation:/[|{}[\];(),.]/},r=i.string[0].inside;r.boolean=i.boolean,r.variable=i.variable,r.function.inside=i}(); +Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},"string-interpolation":{pattern:/(?:f|rf|fr)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:{{)*){(?!{)(?:[^{}]|{(?!{)(?:[^{}]|{(?!{)(?:[^{}])+})+})+}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|rb|br)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^\s*)@\w+(?:\.\w+)*/im,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:True|False|None)\b/,number:/(?:\b(?=\d)|\B(?=\.))(?:0[bo])?(?:(?:\d|0x[\da-f])[\da-f]*(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python; +Prism.languages.r={comment:/#.*/,string:{pattern:/(['"])(?:\\.|(?!\1)[^\\\r\n])*\1/,greedy:!0},"percent-operator":{pattern:/%[^%\s]*%/,alias:"operator"},boolean:/\b(?:TRUE|FALSE)\b/,ellipsis:/\.\.(?:\.|\d+)/,number:[/\b(?:NaN|Inf)\b/,/(?:\b0x[\dA-Fa-f]+(?:\.\d*)?|\b\d+(?:\.\d*)?|\B\.\d+)(?:[EePp][+-]?\d+)?[iL]?/],keyword:/\b(?:if|else|repeat|while|function|for|in|next|break|NULL|NA|NA_integer_|NA_real_|NA_complex_|NA_character_)\b/,operator:/->?>?|<(?:=|=!]=?|::?|&&?|\|\|?|[+*\/^$@~]/,punctuation:/[(){}\[\],;]/}; +!function(e){e.languages.ruby=e.languages.extend("clike",{comment:[/#.*/,{pattern:/^=begin\s[\s\S]*?^=end/m,greedy:!0}],"class-name":{pattern:/(\b(?:class)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|protected|private|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/});var n={pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"tag"},rest:e.languages.ruby}};delete e.languages.ruby.function,e.languages.insertBefore("ruby","keyword",{regex:[{pattern:RegExp("%r(?:"+["([^a-zA-Z0-9\\s{(\\[<])(?:(?!\\1)[^\\\\]|\\\\[^])*\\1[gim]{0,3}","\\((?:[^()\\\\]|\\\\[^])*\\)[gim]{0,3}","\\{(?:[^#{}\\\\]|#(?:\\{[^}]+\\})?|\\\\[^])*\\}[gim]{0,3}","\\[(?:[^\\[\\]\\\\]|\\\\[^])*\\][gim]{0,3}","<(?:[^<>\\\\]|\\\\[^])*>[gim]{0,3}"].join("|")+")"),greedy:!0,inside:{interpolation:n}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[gim]{0,3}(?=\s*(?:$|[\r\n,.;})]))/,lookbehind:!0,greedy:!0}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:{pattern:/(^|[^:]):[a-zA-Z_]\w*(?:[?!]|\b)/,lookbehind:!0},"method-definition":{pattern:/(\bdef\s+)[\w.]+/,lookbehind:!0,inside:{function:/\w+$/,rest:e.languages.ruby}}}),e.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|Fixnum|Float|Hash|Integer|IO|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|String|Struct|TMS|Symbol|ThreadGroup|Thread|Time|TrueClass)\b/,constant:/\b[A-Z]\w*(?:[?!]|\b)/}),e.languages.ruby.string=[{pattern:RegExp("%[qQiIwWxs]?(?:"+["([^a-zA-Z0-9\\s{(\\[<])(?:(?!\\1)[^\\\\]|\\\\[^])*\\1","\\((?:[^()\\\\]|\\\\[^])*\\)","\\{(?:[^#{}\\\\]|#(?:\\{[^}]+\\})?|\\\\[^])*\\}","\\[(?:[^\\[\\]\\\\]|\\\\[^])*\\]","<(?:[^<>\\\\]|\\\\[^])*>"].join("|")+")"),greedy:!0,inside:{interpolation:n}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:n}}],e.languages.rb=e.languages.ruby}(Prism); +!function(e){for(var a="/\\*(?:[^*/]|\\*(?!/)|/(?!\\*)|)*\\*/",t=0;t<2;t++)a=a.replace(//g,function(){return a});a=a.replace(//g,function(){return"[^\\s\\S]"}),e.languages.rust={comment:[{pattern:RegExp("(^|[^\\\\])"+a),lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/b?"(?:\\[\s\S]|[^\\"])*"|b?r(#*)"(?:[^"]|"(?!\1))*"\1/,greedy:!0},char:{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u\{(?:[\da-fA-F]_*){1,6}\}|.)|[^\\\r\n\t'])'/,greedy:!0,alias:"string"},attribute:{pattern:/#!?\[(?:[^\[\]"]|"(?:\\[\s\S]|[^\\"])*")*\]/,greedy:!0,alias:"attr-name",inside:{string:null}},"closure-params":{pattern:/([=(,:]\s*|\bmove\s*)\|[^|]*\||\|[^|]*\|(?=\s*(?:\{|->))/,lookbehind:!0,greedy:!0,inside:{"closure-punctuation":{pattern:/^\||\|$/,alias:"punctuation"},rest:null}},"lifetime-annotation":{pattern:/'\w+/,alias:"symbol"},"fragment-specifier":{pattern:/(\$\w+:)[a-z]+/,lookbehind:!0,alias:"punctuation"},variable:/\$\w+/,"function-definition":{pattern:/(\bfn\s+)\w+/,lookbehind:!0,alias:"function"},"type-definition":{pattern:/(\b(?:enum|struct|union)\s+)\w+/,lookbehind:!0,alias:"class-name"},"module-declaration":[{pattern:/(\b(?:crate|mod)\s+)[a-z][a-z_\d]*/,lookbehind:!0,alias:"namespace"},{pattern:/(\b(?:crate|self|super)\s*)::\s*[a-z][a-z_\d]*\b(?:\s*::(?:\s*[a-z][a-z_\d]*\s*::)*)?/,lookbehind:!0,alias:"namespace",inside:{punctuation:/::/}}],keyword:[/\b(?:abstract|as|async|await|become|box|break|const|continue|crate|do|dyn|else|enum|extern|final|fn|for|if|impl|in|let|loop|macro|match|mod|move|mut|override|priv|pub|ref|return|self|Self|static|struct|super|trait|try|type|typeof|union|unsafe|unsized|use|virtual|where|while|yield)\b/,/\b(?:[ui](?:8|16|32|64|128|size)|f(?:32|64)|bool|char|str)\b/],function:/\b[a-z_]\w*(?=\s*(?:::\s*<|\())/,macro:{pattern:/\w+!/,alias:"property"},constant:/\b[A-Z_][A-Z_\d]+\b/,"class-name":/\b[A-Z]\w*\b/,namespace:{pattern:/(?:\b[a-z][a-z_\d]*\s*::\s*)*\b[a-z][a-z_\d]*\s*::(?!\s*<)/,inside:{punctuation:/::/}},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(?:(?:\d(?:_?\d)*)?\.)?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:[iu](?:8|16|32|64|size)?|f32|f64))?\b/,boolean:/\b(?:false|true)\b/,punctuation:/->|\.\.=|\.{1,3}|::|[{}[\];(),:]/,operator:/[-+*\/%!^]=?|=[=>]?|&[&=]?|\|[|=]?|<>?=?|[@?]/},e.languages.rust["closure-params"].inside.rest=e.languages.rust,e.languages.rust.attribute.inside.string=e.languages.rust.string}(Prism); +!function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t].+)*/m,lookbehind:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,inside:{atrule:/(?:@[\w-]+|[+=])/m}}}),delete e.languages.sass.atrule;var t=/\$[-\w]+|#\{\$[-\w]+\}/,a=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|or|not)\b/,{pattern:/(\s+)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,inside:{punctuation:/:/,variable:t,operator:a}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s].*)/m,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:t,operator:a,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/([ \t]*)\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*)*/,lookbehind:!0}})}(Prism); +Prism.languages.sql={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|(?:--|\/\/|#).*)/,lookbehind:!0},variable:[{pattern:/@(["'`])(?:\\[\s\S]|(?!\1)[^\\])+\1/,greedy:!0},/@[\w.$]+/],string:{pattern:/(^|[^@\\])("|')(?:\\[\s\S]|(?!\2)[^\\]|\2\2)*\2/,greedy:!0,lookbehind:!0},function:/\b(?:AVG|COUNT|FIRST|FORMAT|LAST|LCASE|LEN|MAX|MID|MIN|MOD|NOW|ROUND|SUM|UCASE)(?=\s*\()/i,keyword:/\b(?:ACTION|ADD|AFTER|ALGORITHM|ALL|ALTER|ANALYZE|ANY|APPLY|AS|ASC|AUTHORIZATION|AUTO_INCREMENT|BACKUP|BDB|BEGIN|BERKELEYDB|BIGINT|BINARY|BIT|BLOB|BOOL|BOOLEAN|BREAK|BROWSE|BTREE|BULK|BY|CALL|CASCADED?|CASE|CHAIN|CHAR(?:ACTER|SET)?|CHECK(?:POINT)?|CLOSE|CLUSTERED|COALESCE|COLLATE|COLUMNS?|COMMENT|COMMIT(?:TED)?|COMPUTE|CONNECT|CONSISTENT|CONSTRAINT|CONTAINS(?:TABLE)?|CONTINUE|CONVERT|CREATE|CROSS|CURRENT(?:_DATE|_TIME|_TIMESTAMP|_USER)?|CURSOR|CYCLE|DATA(?:BASES?)?|DATE(?:TIME)?|DAY|DBCC|DEALLOCATE|DEC|DECIMAL|DECLARE|DEFAULT|DEFINER|DELAYED|DELETE|DELIMITERS?|DENY|DESC|DESCRIBE|DETERMINISTIC|DISABLE|DISCARD|DISK|DISTINCT|DISTINCTROW|DISTRIBUTED|DO|DOUBLE|DROP|DUMMY|DUMP(?:FILE)?|DUPLICATE|ELSE(?:IF)?|ENABLE|ENCLOSED|END|ENGINE|ENUM|ERRLVL|ERRORS|ESCAPED?|EXCEPT|EXEC(?:UTE)?|EXISTS|EXIT|EXPLAIN|EXTENDED|FETCH|FIELDS|FILE|FILLFACTOR|FIRST|FIXED|FLOAT|FOLLOWING|FOR(?: EACH ROW)?|FORCE|FOREIGN|FREETEXT(?:TABLE)?|FROM|FULL|FUNCTION|GEOMETRY(?:COLLECTION)?|GLOBAL|GOTO|GRANT|GROUP|HANDLER|HASH|HAVING|HOLDLOCK|HOUR|IDENTITY(?:_INSERT|COL)?|IF|IGNORE|IMPORT|INDEX|INFILE|INNER|INNODB|INOUT|INSERT|INT|INTEGER|INTERSECT|INTERVAL|INTO|INVOKER|ISOLATION|ITERATE|JOIN|KEYS?|KILL|LANGUAGE|LAST|LEAVE|LEFT|LEVEL|LIMIT|LINENO|LINES|LINESTRING|LOAD|LOCAL|LOCK|LONG(?:BLOB|TEXT)|LOOP|MATCH(?:ED)?|MEDIUM(?:BLOB|INT|TEXT)|MERGE|MIDDLEINT|MINUTE|MODE|MODIFIES|MODIFY|MONTH|MULTI(?:LINESTRING|POINT|POLYGON)|NATIONAL|NATURAL|NCHAR|NEXT|NO|NONCLUSTERED|NULLIF|NUMERIC|OFF?|OFFSETS?|ON|OPEN(?:DATASOURCE|QUERY|ROWSET)?|OPTIMIZE|OPTION(?:ALLY)?|ORDER|OUT(?:ER|FILE)?|OVER|PARTIAL|PARTITION|PERCENT|PIVOT|PLAN|POINT|POLYGON|PRECEDING|PRECISION|PREPARE|PREV|PRIMARY|PRINT|PRIVILEGES|PROC(?:EDURE)?|PUBLIC|PURGE|QUICK|RAISERROR|READS?|REAL|RECONFIGURE|REFERENCES|RELEASE|RENAME|REPEAT(?:ABLE)?|REPLACE|REPLICATION|REQUIRE|RESIGNAL|RESTORE|RESTRICT|RETURN(?:S|ING)?|REVOKE|RIGHT|ROLLBACK|ROUTINE|ROW(?:COUNT|GUIDCOL|S)?|RTREE|RULE|SAVE(?:POINT)?|SCHEMA|SECOND|SELECT|SERIAL(?:IZABLE)?|SESSION(?:_USER)?|SET(?:USER)?|SHARE|SHOW|SHUTDOWN|SIMPLE|SMALLINT|SNAPSHOT|SOME|SONAME|SQL|START(?:ING)?|STATISTICS|STATUS|STRIPED|SYSTEM_USER|TABLES?|TABLESPACE|TEMP(?:ORARY|TABLE)?|TERMINATED|TEXT(?:SIZE)?|THEN|TIME(?:STAMP)?|TINY(?:BLOB|INT|TEXT)|TOP?|TRAN(?:SACTIONS?)?|TRIGGER|TRUNCATE|TSEQUAL|TYPES?|UNBOUNDED|UNCOMMITTED|UNDEFINED|UNION|UNIQUE|UNLOCK|UNPIVOT|UNSIGNED|UPDATE(?:TEXT)?|USAGE|USE|USER|USING|VALUES?|VAR(?:BINARY|CHAR|CHARACTER|YING)|VIEW|WAITFOR|WARNINGS|WHEN|WHERE|WHILE|WITH(?: ROLLUP|IN)?|WORK|WRITE(?:TEXT)?|YEAR)\b/i,boolean:/\b(?:TRUE|FALSE|NULL)\b/i,number:/\b0x[\da-f]+\b|\b\d+(?:\.\d*)?|\B\.\d+\b/i,operator:/[-+*\/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|IN|ILIKE|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/}; +Prism.languages.swift=Prism.languages.extend("clike",{string:{pattern:/("|')(?:\\(?:\((?:[^()]|\([^)]+\))+\)|\r\n|[^(])|(?!\1)[^\\\r\n])*\1/,greedy:!0,inside:{interpolation:{pattern:/\\\((?:[^()]|\([^)]+\))+\)/,inside:{delimiter:{pattern:/^\\\(|\)$/,alias:"variable"}}}}},keyword:/\b(?:as|associativity|break|case|catch|class|continue|convenience|default|defer|deinit|didSet|do|dynamic(?:Type)?|else|enum|extension|fallthrough|final|for|func|get|guard|if|import|in|infix|init|inout|internal|is|lazy|left|let|mutating|new|none|nonmutating|operator|optional|override|postfix|precedence|prefix|private|protocol|public|repeat|required|rethrows|return|right|safe|self|Self|set|static|struct|subscript|super|switch|throws?|try|Type|typealias|unowned|unsafe|var|weak|where|while|willSet|__(?:COLUMN__|FILE__|FUNCTION__|LINE__))\b/,number:/\b(?:[\d_]+(?:\.[\de_]+)?|0x[a-f0-9_]+(?:\.[a-f0-9p_]+)?|0b[01_]+|0o[0-7_]+)\b/i,constant:/\b(?:nil|[A-Z_]{2,}|k[A-Z][A-Za-z_]+)\b/,atrule:/@\b(?:IB(?:Outlet|Designable|Action|Inspectable)|class_protocol|exported|noreturn|NS(?:Copying|Managed)|objc|UIApplicationMain|auto_closure)\b/,builtin:/\b(?:[A-Z]\S+|abs|advance|alignof(?:Value)?|assert|contains|count(?:Elements)?|debugPrint(?:ln)?|distance|drop(?:First|Last)|dump|enumerate|equal|filter|find|first|getVaList|indices|isEmpty|join|last|lexicographicalCompare|map|max(?:Element)?|min(?:Element)?|numericCast|overlaps|partition|print(?:ln)?|reduce|reflect|reverse|sizeof(?:Value)?|sort(?:ed)?|split|startsWith|stride(?:of(?:Value)?)?|suffix|swap|toDebugString|toString|transcode|underestimateCount|unsafeBitCast|with(?:ExtendedLifetime|Unsafe(?:MutablePointers?|Pointers?)|VaList))\b/}),Prism.languages.swift.string.inside.interpolation.inside.rest=Prism.languages.swift; +!function(e){e.languages.typescript=e.languages.extend("javascript",{"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|type)\s+)(?!keyof\b)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?:\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},keyword:/\b(?:abstract|as|asserts|async|await|break|case|catch|class|const|constructor|continue|debugger|declare|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|is|keyof|let|module|namespace|new|null|of|package|private|protected|public|readonly|return|require|set|static|super|switch|this|throw|try|type|typeof|undefined|var|void|while|with|yield)\b/,builtin:/\b(?:string|Function|any|number|boolean|Array|symbol|console|Promise|unknown|never)\b/}),delete e.languages.typescript.parameter;var n=e.languages.extend("typescript",{});delete n["class-name"],e.languages.typescript["class-name"].inside=n,e.languages.insertBefore("typescript","function",{"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:n}}}}),e.languages.ts=e.languages.typescript}(Prism); +!function(e){var n=/[*&][^\s[\]{},]+/,r=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,t="(?:"+r.source+"(?:[ \t]+"+n.source+")?|"+n.source+"(?:[ \t]+"+r.source+")?)",a="(?:[^\\s\\x00-\\x08\\x0e-\\x1f!\"#%&'*,\\-:>?@[\\]`{|}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*".replace(//g,function(){return"[^\\s\\x00-\\x08\\x0e-\\x1f,[\\]{}\\x7f-\\x84\\x86-\\x9f\\ud800-\\udfff\\ufffe\\uffff]"}),d="\"(?:[^\"\\\\\r\n]|\\\\.)*\"|'(?:[^'\\\\\r\n]|\\\\.)*'";function o(e,n){n=(n||"").replace(/m/g,"")+"m";var r="([:\\-,[{]\\s*(?:\\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|]|}|(?:[\r\n]\\s*)?#))".replace(/<>/g,function(){return t}).replace(/<>/g,function(){return e});return RegExp(r,n)}e.languages.yaml={scalar:{pattern:RegExp("([\\-:]\\s*(?:\\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\\S[^\r\n]*(?:\\2[^\r\n]+)*)".replace(/<>/g,function(){return t})),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp("((?:^|[:\\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\\s*:\\s)".replace(/<>/g,function(){return t}).replace(/<>/g,function(){return"(?:"+a+"|"+d+")"})),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:o("\\d{4}-\\d\\d?-\\d\\d?(?:[tT]|[ \t]+)\\d\\d?:\\d{2}:\\d{2}(?:\\.\\d*)?(?:[ \t]*(?:Z|[-+]\\d\\d?(?::\\d{2})?))?|\\d{4}-\\d{2}-\\d{2}|\\d\\d?:\\d{2}(?::\\d{2}(?:\\.\\d*)?)?"),lookbehind:!0,alias:"number"},boolean:{pattern:o("true|false","i"),lookbehind:!0,alias:"important"},null:{pattern:o("null|~","i"),lookbehind:!0,alias:"important"},string:{pattern:o(d),lookbehind:!0,greedy:!0},number:{pattern:o("[+-]?(?:0x[\\da-f]+|0o[0-7]+|(?:\\d+(?:\\.\\d*)?|\\.?\\d+)(?:e[+-]?\\d+)?|\\.inf|\\.nan)","i"),lookbehind:!0},tag:r,important:n,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(Prism); +//alias +Prism.languages.js = Prism.languages.javascript; +Prism.languages.sh = Prism.languages.bash; +Prism.languages.md = Prism.languages.markdown; +Prism.languages.py = Prism.languages.python; +Prism.languages.yml = Prism.languages.yaml; +Prism.languages.rb = Prism.languages.ruby; diff --git a/setup.py b/setup.py index e01d7ccf..81536b3a 100644 --- a/setup.py +++ b/setup.py @@ -50,7 +50,7 @@ "html/css/app.css", "html/css/codemirror.min.css", "html/js/FileSaver.min.js", - "html/js/highlight.min.js", + "html/js/prism.min.js", "html/js/pywebio.min.js", "html/js/mustache.min.js", "html/js/jquery.min.js", diff --git a/webiojs/src/models/output.ts b/webiojs/src/models/output.ts index 0b92fce6..243163dc 100644 --- a/webiojs/src/models/output.ts +++ b/webiojs/src/models/output.ts @@ -1,8 +1,6 @@ import {b64toBlob} from "../utils"; -// const marked = require('marked'); -// import {marked} from "../js/mdparser"; -// import 'marked'; import * as marked from 'marked'; + /* * 当前限制 * 若Widget被作为其他Widget的子项时,该Widget中绑定的事件将会失效 @@ -33,13 +31,18 @@ marked.setOptions({ smartLists: true, smartypants: false, mangle: false, - highlight: function (code, language) { - try{ - const validLanguage = hljs.getLanguage(language) ? language : 'plaintext'; - return hljs.highlight(validLanguage, code).value; - }catch (e) { - return code + highlight: function (code, lang, callback) { + if (Prism.languages[lang]) { + try { + code = Prism.highlight(code, Prism.languages[lang]); + } catch (e) { + console.error('Prism highlight error:' + e) + } } + if (callback) + return callback(null, code); + else + return code; }, }); diff --git a/webiojs/src/vendor.d.ts b/webiojs/src/vendor.d.ts index 5b1b7ef6..d75a84cf 100644 --- a/webiojs/src/vendor.d.ts +++ b/webiojs/src/vendor.d.ts @@ -4,4 +4,4 @@ declare let saveAs: any; declare let CodeMirror: any; declare let bsCustomFileInput: any; declare let Toastify: any; -declare let hljs: any; // highlight.js \ No newline at end of file +declare let Prism: any; // Prism.js \ No newline at end of file From f85722fa727b7e9b82cc7f3a27933eb57767761d Mon Sep 17 00:00:00 2001 From: wangweimin Date: Wed, 3 Feb 2021 18:11:08 +0800 Subject: [PATCH 017/445] feat: support XSS sanitizer when output html and markdown --- docs/spec.rst | 12 ++++++++++-- pywebio/html/index.html | 1 + pywebio/html/js/purify.min.js | 2 ++ pywebio/output.py | 17 ++++++++++------- setup.py | 1 + webiojs/src/models/output.ts | 20 +++++++++++++++++--- webiojs/src/vendor.d.ts | 3 ++- 7 files changed, 43 insertions(+), 13 deletions(-) create mode 100644 pywebio/html/js/purify.min.js diff --git a/docs/spec.rst b/docs/spec.rst index 8597ef72..8cb7fa59 100644 --- a/docs/spec.rst +++ b/docs/spec.rst @@ -188,9 +188,17 @@ output ``type`` 的可选值及特有字段: -* type: markdown, html +* type: markdown + + * content: str + * options: dict, `marked.js `_ 选项 + * sanitize: bool, 是否使用 `DOMPurify `_ 对内容进行过滤来防止XSS攻击。 + +* type: html + + * content: str: + * sanitize: bool, 是否使用 `DOMPurify `_ 对内容进行过滤来防止XSS攻击。 - * content: str 输出内容的原始字符串 * type: text diff --git a/pywebio/html/index.html b/pywebio/html/index.html index a06e5899..5cf69ac5 100644 --- a/pywebio/html/index.html +++ b/pywebio/html/index.html @@ -46,6 +46,7 @@ + diff --git a/pywebio/html/js/purify.min.js b/pywebio/html/js/purify.min.js new file mode 100644 index 00000000..a261d3e7 --- /dev/null +++ b/pywebio/html/js/purify.min.js @@ -0,0 +1,2 @@ +/*! @license DOMPurify | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/2.2.2/LICENSE */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).DOMPurify=t()}(this,(function(){"use strict";var e=Object.hasOwnProperty,t=Object.setPrototypeOf,n=Object.isFrozen,r=Object.getPrototypeOf,o=Object.getOwnPropertyDescriptor,i=Object.freeze,a=Object.seal,l=Object.create,c="undefined"!=typeof Reflect&&Reflect,s=c.apply,u=c.construct;s||(s=function(e,t,n){return e.apply(t,n)}),i||(i=function(e){return e}),a||(a=function(e){return e}),u||(u=function(e,t){return new(Function.prototype.bind.apply(e,[null].concat(function(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t1?n-1:0),o=1;o/gm),U=a(/^data-[\-\w.\u00B7-\uFFFF]/),j=a(/^aria-[\-\w]+$/),P=a(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\-]+(?:[^a-z+.\-:]|$))/i),B=a(/^(?:\w+script|data):/i),W=a(/[\u0000-\u0020\u00A0\u1680\u180E\u2000-\u2029\u205F\u3000]/g),G="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function q(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t0&&void 0!==arguments[0]?arguments[0]:K(),n=function(t){return e(t)};if(n.version="2.2.6",n.removed=[],!t||!t.document||9!==t.document.nodeType)return n.isSupported=!1,n;var r=t.document,o=t.document,a=t.DocumentFragment,l=t.HTMLTemplateElement,c=t.Node,s=t.Element,u=t.NodeFilter,f=t.NamedNodeMap,x=void 0===f?t.NamedNodeMap||t.MozNamedAttrMap:f,Y=t.Text,X=t.Comment,$=t.DOMParser,Z=t.trustedTypes,J=s.prototype,Q=k(J,"cloneNode"),ee=k(J,"nextSibling"),te=k(J,"childNodes"),ne=k(J,"parentNode");if("function"==typeof l){var re=o.createElement("template");re.content&&re.content.ownerDocument&&(o=re.content.ownerDocument)}var oe=V(Z,r),ie=oe&&ze?oe.createHTML(""):"",ae=o,le=ae.implementation,ce=ae.createNodeIterator,se=ae.getElementsByTagName,ue=ae.createDocumentFragment,fe=r.importNode,me={};try{me=S(o).documentMode?o.documentMode:{}}catch(e){}var de={};n.isSupported=le&&void 0!==le.createHTMLDocument&&9!==me;var pe=z,ge=H,he=U,ye=j,ve=B,be=W,Te=P,Ae=null,xe=w({},[].concat(q(R),q(_),q(D),q(N),q(L))),we=null,Se=w({},[].concat(q(M),q(F),q(C),q(I))),ke=null,Re=null,_e=!0,De=!0,Ee=!1,Ne=!1,Oe=!1,Le=!1,Me=!1,Fe=!1,Ce=!1,Ie=!0,ze=!1,He=!0,Ue=!0,je=!1,Pe={},Be=w({},["annotation-xml","audio","colgroup","desc","foreignobject","head","iframe","math","mi","mn","mo","ms","mtext","noembed","noframes","noscript","plaintext","script","style","svg","template","thead","title","video","xmp"]),We=null,Ge=w({},["audio","video","img","source","image","track"]),qe=null,Ke=w({},["alt","class","for","id","label","name","pattern","placeholder","summary","title","value","style","xmlns"]),Ve=null,Ye=o.createElement("form"),Xe=function(e){Ve&&Ve===e||(e&&"object"===(void 0===e?"undefined":G(e))||(e={}),e=S(e),Ae="ALLOWED_TAGS"in e?w({},e.ALLOWED_TAGS):xe,we="ALLOWED_ATTR"in e?w({},e.ALLOWED_ATTR):Se,qe="ADD_URI_SAFE_ATTR"in e?w(S(Ke),e.ADD_URI_SAFE_ATTR):Ke,We="ADD_DATA_URI_TAGS"in e?w(S(Ge),e.ADD_DATA_URI_TAGS):Ge,ke="FORBID_TAGS"in e?w({},e.FORBID_TAGS):{},Re="FORBID_ATTR"in e?w({},e.FORBID_ATTR):{},Pe="USE_PROFILES"in e&&e.USE_PROFILES,_e=!1!==e.ALLOW_ARIA_ATTR,De=!1!==e.ALLOW_DATA_ATTR,Ee=e.ALLOW_UNKNOWN_PROTOCOLS||!1,Ne=e.SAFE_FOR_TEMPLATES||!1,Oe=e.WHOLE_DOCUMENT||!1,Fe=e.RETURN_DOM||!1,Ce=e.RETURN_DOM_FRAGMENT||!1,Ie=!1!==e.RETURN_DOM_IMPORT,ze=e.RETURN_TRUSTED_TYPE||!1,Me=e.FORCE_BODY||!1,He=!1!==e.SANITIZE_DOM,Ue=!1!==e.KEEP_CONTENT,je=e.IN_PLACE||!1,Te=e.ALLOWED_URI_REGEXP||Te,Ne&&(De=!1),Ce&&(Fe=!0),Pe&&(Ae=w({},[].concat(q(L))),we=[],!0===Pe.html&&(w(Ae,R),w(we,M)),!0===Pe.svg&&(w(Ae,_),w(we,F),w(we,I)),!0===Pe.svgFilters&&(w(Ae,D),w(we,F),w(we,I)),!0===Pe.mathMl&&(w(Ae,N),w(we,C),w(we,I))),e.ADD_TAGS&&(Ae===xe&&(Ae=S(Ae)),w(Ae,e.ADD_TAGS)),e.ADD_ATTR&&(we===Se&&(we=S(we)),w(we,e.ADD_ATTR)),e.ADD_URI_SAFE_ATTR&&w(qe,e.ADD_URI_SAFE_ATTR),Ue&&(Ae["#text"]=!0),Oe&&w(Ae,["html","head","body"]),Ae.table&&(w(Ae,["tbody"]),delete ke.tbody),i&&i(e),Ve=e)},$e=w({},["mi","mo","mn","ms","mtext"]),Ze=w({},["foreignobject","desc","title","annotation-xml"]),Je=w({},_);w(Je,D),w(Je,E);var Qe=w({},N);w(Qe,O);var et="http://www.w3.org/1998/Math/MathML",tt="http://www.w3.org/2000/svg",nt="http://www.w3.org/1999/xhtml",rt=function(e){var t=ne(e);t&&t.tagName||(t={namespaceURI:nt,tagName:"template"});var n=g(e.tagName),r=g(t.tagName);if(e.namespaceURI===tt)return t.namespaceURI===nt?"svg"===n:t.namespaceURI===et?"svg"===n&&("annotation-xml"===r||$e[r]):Boolean(Je[n]);if(e.namespaceURI===et)return t.namespaceURI===nt?"math"===n:t.namespaceURI===tt?"math"===n&&Ze[r]:Boolean(Qe[n]);if(e.namespaceURI===nt){if(t.namespaceURI===tt&&!Ze[r])return!1;if(t.namespaceURI===et&&!$e[r])return!1;var o=w({},["title","style","font","a","script"]);return!Qe[n]&&(o[n]||!Je[n])}return!1},ot=function(e){p(n.removed,{element:e});try{e.parentNode.removeChild(e)}catch(t){try{e.outerHTML=ie}catch(t){e.remove()}}},it=function(e,t){try{p(n.removed,{attribute:t.getAttributeNode(e),from:t})}catch(e){p(n.removed,{attribute:null,from:t})}if(t.removeAttribute(e),"is"===e&&!we[e])if(Fe||Ce)try{ot(t)}catch(e){}else try{t.setAttribute(e,"")}catch(e){}},at=function(e){var t=void 0,n=void 0;if(Me)e=""+e;else{var r=h(e,/^[\r\n\t ]+/);n=r&&r[0]}var i=oe?oe.createHTML(e):e;try{t=(new $).parseFromString(i,"text/html")}catch(e){}if(!t||!t.documentElement){var a=(t=le.createHTMLDocument("")).body;a.parentNode.removeChild(a.parentNode.firstElementChild),a.outerHTML=i}return e&&n&&t.body.insertBefore(o.createTextNode(n),t.body.childNodes[0]||null),se.call(t,Oe?"html":"body")[0]},lt=function(e){return ce.call(e.ownerDocument||e,e,u.SHOW_ELEMENT|u.SHOW_COMMENT|u.SHOW_TEXT,(function(){return u.FILTER_ACCEPT}),!1)},ct=function(e){return!(e instanceof Y||e instanceof X)&&!("string"==typeof e.nodeName&&"string"==typeof e.textContent&&"function"==typeof e.removeChild&&e.attributes instanceof x&&"function"==typeof e.removeAttribute&&"function"==typeof e.setAttribute&&"string"==typeof e.namespaceURI&&"function"==typeof e.insertBefore)},st=function(e){return"object"===(void 0===c?"undefined":G(c))?e instanceof c:e&&"object"===(void 0===e?"undefined":G(e))&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName},ut=function(e,t,r){de[e]&&m(de[e],(function(e){e.call(n,t,r,Ve)}))},ft=function(e){var t=void 0;if(ut("beforeSanitizeElements",e,null),ct(e))return ot(e),!0;if(h(e.nodeName,/[\u0080-\uFFFF]/))return ot(e),!0;var r=g(e.nodeName);if(ut("uponSanitizeElement",e,{tagName:r,allowedTags:Ae}),!st(e.firstElementChild)&&(!st(e.content)||!st(e.content.firstElementChild))&&T(/<[/\w]/g,e.innerHTML)&&T(/<[/\w]/g,e.textContent))return ot(e),!0;if(!Ae[r]||ke[r]){if(Ue&&!Be[r])for(var o=ne(e),i=te(e),a=i.length-1;a>=0;--a)o.insertBefore(Q(i[a],!0),ee(e));return ot(e),!0}return e instanceof s&&!rt(e)?(ot(e),!0):"noscript"!==r&&"noembed"!==r||!T(/<\/no(script|embed)/i,e.innerHTML)?(Ne&&3===e.nodeType&&(t=e.textContent,t=y(t,pe," "),t=y(t,ge," "),e.textContent!==t&&(p(n.removed,{element:e.cloneNode()}),e.textContent=t)),ut("afterSanitizeElements",e,null),!1):(ot(e),!0)},mt=function(e,t,n){if(He&&("id"===t||"name"===t)&&(n in o||n in Ye))return!1;if(De&&T(he,t));else if(_e&&T(ye,t));else{if(!we[t]||Re[t])return!1;if(qe[t]);else if(T(Te,y(n,be,"")));else if("src"!==t&&"xlink:href"!==t&&"href"!==t||"script"===e||0!==v(n,"data:")||!We[e]){if(Ee&&!T(ve,y(n,be,"")));else if(n)return!1}else;}return!0},dt=function(e){var t=void 0,r=void 0,o=void 0,i=void 0;ut("beforeSanitizeAttributes",e,null);var a=e.attributes;if(a){var l={attrName:"",attrValue:"",keepAttr:!0,allowedAttributes:we};for(i=a.length;i--;){var c=t=a[i],s=c.name,u=c.namespaceURI;if(r=b(t.value),o=g(s),l.attrName=o,l.attrValue=r,l.keepAttr=!0,l.forceKeepAttr=void 0,ut("uponSanitizeAttribute",e,l),r=l.attrValue,!l.forceKeepAttr&&(it(s,e),l.keepAttr))if(T(/\/>/i,r))it(s,e);else{Ne&&(r=y(r,pe," "),r=y(r,ge," "));var f=e.nodeName.toLowerCase();if(mt(f,o,r))try{u?e.setAttributeNS(u,s,r):e.setAttribute(s,r),d(n.removed)}catch(e){}}}ut("afterSanitizeAttributes",e,null)}},pt=function e(t){var n=void 0,r=lt(t);for(ut("beforeSanitizeShadowDOM",t,null);n=r.nextNode();)ut("uponSanitizeShadowNode",n,null),ft(n)||(n.content instanceof a&&e(n.content),dt(n));ut("afterSanitizeShadowDOM",t,null)};return n.sanitize=function(e,o){var i=void 0,l=void 0,s=void 0,u=void 0,f=void 0;if(e||(e="\x3c!--\x3e"),"string"!=typeof e&&!st(e)){if("function"!=typeof e.toString)throw A("toString is not a function");if("string"!=typeof(e=e.toString()))throw A("dirty is not a string, aborting")}if(!n.isSupported){if("object"===G(t.toStaticHTML)||"function"==typeof t.toStaticHTML){if("string"==typeof e)return t.toStaticHTML(e);if(st(e))return t.toStaticHTML(e.outerHTML)}return e}if(Le||Xe(o),n.removed=[],"string"==typeof e&&(je=!1),je);else if(e instanceof c)1===(l=(i=at("\x3c!----\x3e")).ownerDocument.importNode(e,!0)).nodeType&&"BODY"===l.nodeName||"HTML"===l.nodeName?i=l:i.appendChild(l);else{if(!Fe&&!Ne&&!Oe&&-1===e.indexOf("<"))return oe&&ze?oe.createHTML(e):e;if(!(i=at(e)))return Fe?null:ie}i&&Me&&ot(i.firstChild);for(var m=lt(je?e:i);s=m.nextNode();)3===s.nodeType&&s===u||ft(s)||(s.content instanceof a&&pt(s.content),dt(s),u=s);if(u=null,je)return e;if(Fe){if(Ce)for(f=ue.call(i.ownerDocument);i.firstChild;)f.appendChild(i.firstChild);else f=i;return Ie&&(f=fe.call(r,f,!0)),f}var d=Oe?i.outerHTML:i.innerHTML;return Ne&&(d=y(d,pe," "),d=y(d,ge," ")),oe&&ze?oe.createHTML(d):d},n.setConfig=function(e){Xe(e),Le=!0},n.clearConfig=function(){Ve=null,Le=!1},n.isValidAttribute=function(e,t,n){Ve||Xe({});var r=g(e),o=g(t);return mt(r,o,n)},n.addHook=function(e,t){"function"==typeof t&&(de[e]=de[e]||[],p(de[e],t))},n.removeHook=function(e){de[e]&&d(de[e])},n.removeHooks=function(e){de[e]&&(de[e]=[])},n.removeAllHooks=function(){de={}},n}()})); diff --git a/pywebio/output.py b/pywebio/output.py index 779b6dff..7ec6e763 100644 --- a/pywebio/output.py +++ b/pywebio/output.py @@ -317,19 +317,20 @@ def put_text(*texts, sep=' ', inline=False, scope=Scope.Current, position=Output return Output(spec) -def put_html(html, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output: +def put_html(html, sanitize=False, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output: """ 输出Html内容。 与支持通过Html输出内容到 `Jupyter Notebook `_ 的库兼容。 :param html: html字符串或实现了 `IPython.display.HTML` 接口的实例 + :param bool sanitize: 是否使用 `DOMPurify `_ 对内容进行过滤来防止XSS攻击。 :param int scope, position: 与 `put_text` 函数的同名参数含义一致 """ if hasattr(html, '__html__'): html = html.__html__() - spec = _get_output_spec('html', content=html, scope=scope, position=position) + spec = _get_output_spec('html', content=html, sanitize=sanitize, scope=scope, position=position) return Output(spec) @@ -353,7 +354,7 @@ def put_code(content, language='', scope=Scope.Current, position=OutputPosition. return put_markdown(code, scope=scope, position=position) -def put_markdown(mdcontent, strip_indent=0, lstrip=False, options=None, +def put_markdown(mdcontent, strip_indent=0, lstrip=False, options=None, sanitize=True, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output: """ 输出Markdown内容。 @@ -363,6 +364,7 @@ def put_markdown(mdcontent, strip_indent=0, lstrip=False, options=None, :param bool lstrip: 是否去除每一行开始的空白符 :param dict options: 解析Markdown时的配置参数。 PyWebIO使用 `marked `_ 解析Markdown, 可配置项参见: https://marked.js.org/using_advanced#options (仅支持配置string和boolean类型的项) + :param bool sanitize: 是否使用 `DOMPurify `_ 对内容进行过滤来防止XSS攻击。 :param int scope, position: 与 `put_text` 函数的同名参数含义一致 当在函数中使用Python的三引号语法输出多行内容时,为了排版美观可能会对Markdown文本进行缩进, @@ -396,7 +398,8 @@ def hello(): lines = (i.lstrip() for i in mdcontent.splitlines()) mdcontent = '\n'.join(lines) - spec = _get_output_spec('markdown', content=mdcontent, options=options, scope=scope, position=position) + spec = _get_output_spec('markdown', content=mdcontent, options=options, sanitize=sanitize, + scope=scope, position=position) return Output(spec) @@ -684,7 +687,7 @@ def put_image(src, format=None, title='', width=None, height=None, height = 'height="%s"' % height if height is not None else '' html = r'{title}'.format(src=src, title=title, height=height, width=width) - return put_html(html, scope=scope, position=position) + return put_html(html, sanitize=False, scope=scope, position=position) def put_file(name, content, label=None, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output: @@ -735,7 +738,7 @@ def put_link(name, url=None, app=None, new_window=False, scope=Scope.Current, href = 'javascript:WebIO.openApp(%r, %d)' % (app, new_window) if app is not None else url target = '_blank' if (new_window and url) else '_self' html = '
    {name}'.format(href=href, target=target, name=name) - return put_html(html, scope=scope, position=position) + return put_html(html, sanitize=False, scope=scope, position=position) def put_processbar(name, init=0, label=None, auto_close=False, scope=Scope.Current, @@ -831,7 +834,7 @@ def put_loading(shape='border', color='dark', scope=Scope.Current, position=Outp html = """
    Loading...
    """.format(shape=shape, color=color) - return put_html(html, scope=scope, position=position) + return put_html(html, sanitize=False, scope=scope, position=position) @safely_destruct_output_when_exp('content') diff --git a/setup.py b/setup.py index 81536b3a..aade759b 100644 --- a/setup.py +++ b/setup.py @@ -51,6 +51,7 @@ "html/css/codemirror.min.css", "html/js/FileSaver.min.js", "html/js/prism.min.js", + "html/js/purify.min.js", "html/js/pywebio.min.js", "html/js/mustache.min.js", "html/js/jquery.min.js", diff --git a/webiojs/src/models/output.ts b/webiojs/src/models/output.ts index 243163dc..3ab88bc9 100644 --- a/webiojs/src/models/output.ts +++ b/webiojs/src/models/output.ts @@ -49,8 +49,15 @@ marked.setOptions({ let Markdown = { handle_type: 'markdown', get_element: function (spec: any) { - // https://marked.js.org/using_advanced#options - return $(marked(spec.content, spec.options)); + // spec.options, see also https://marked.js.org/using_advanced#options + let html_str = marked(spec.content, spec.options); + if (spec.sanitize) + try { + html_str = DOMPurify.sanitize(html_str); + } catch (e) { + console.log('Sanitize html failed: %s\nHTML: \n%s', e, html_str); + } + return $(html_str); } }; @@ -68,7 +75,14 @@ function parseHtml(html_str: string) { let Html = { handle_type: 'html', get_element: function (spec: any) { - return parseHtml(spec.content); + let html_str = spec.content; + if (spec.sanitize) + try { + html_str = DOMPurify.sanitize(html_str); + } catch (e) { + console.log('Sanitize html failed: %s\nHTML: \n%s', e, html_str); + } + return parseHtml(html_str); } }; diff --git a/webiojs/src/vendor.d.ts b/webiojs/src/vendor.d.ts index d75a84cf..610caaee 100644 --- a/webiojs/src/vendor.d.ts +++ b/webiojs/src/vendor.d.ts @@ -4,4 +4,5 @@ declare let saveAs: any; declare let CodeMirror: any; declare let bsCustomFileInput: any; declare let Toastify: any; -declare let Prism: any; // Prism.js \ No newline at end of file +declare let Prism: any; // Prism.js +declare let DOMPurify: any; // DOMPurify.js \ No newline at end of file From a8e4a4fafcfae2978fe5b195eba864d444fd25e6 Mon Sep 17 00:00:00 2001 From: wangweimin Date: Wed, 3 Feb 2021 18:33:50 +0800 Subject: [PATCH 018/445] fix bokeh support --- pywebio/output.py | 7 +------ pywebio/platform/bokeh.py | 10 +++++----- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/pywebio/output.py b/pywebio/output.py index 7ec6e763..987c55c2 100644 --- a/pywebio/output.py +++ b/pywebio/output.py @@ -143,7 +143,7 @@ 'put_text', 'put_html', 'put_code', 'put_markdown', 'use_scope', 'set_scope', 'clear', 'remove', 'put_table', 'put_buttons', 'put_image', 'put_file', 'PopupSize', 'popup', 'close_popup', 'put_widget', 'put_collapse', 'put_link', 'put_scrollable', 'style', 'put_column', - 'put_row', 'put_grid', 'column', 'row', 'grid', 'span', 'put_processbar', 'set_processbar', 'put_loading', + 'put_row', 'put_grid', 'span', 'put_processbar', 'set_processbar', 'put_loading', 'output', 'toast', 'get_scope'] @@ -1108,11 +1108,6 @@ def put_grid(content, cell_width='auto', cell_height='auto', cell_widths=None, c return put_widget(template=tpl, data=dict(contents=content), scope=scope, position=position) -column = put_column -row = put_row -grid = put_grid - - @safely_destruct_output_when_exp('contents') def output(*contents): """返回一个handler,相当于 ``put_xxx()`` 的占位符,可以传入任何接收 ``put_xxx()`` 调用的地方,通过handler可对自身内容进行修改 diff --git a/pywebio/platform/bokeh.py b/pywebio/platform/bokeh.py index 716e7f5e..b5f19656 100644 --- a/pywebio/platform/bokeh.py +++ b/pywebio/platform/bokeh.py @@ -43,11 +43,11 @@ def load_notebook(resources=None, verbose=False, hide_banner=False, load_timeout js_gists.append('Bokeh.set_log_level("info");') js_gists.append("console.log('Set bokeh log level to INFO because you set `output_notebook(verbose=True)`')") - put_html(requirejs_tpl % (html, '\n'.join(js_gists))) + put_html(requirejs_tpl % (html, '\n'.join(js_gists)), sanitize=False) def show_doc(obj, state, notebook_handle): - """显示 Bokeh 单个 documents + """Show a document of Bokeh :param obj: :param state: @@ -62,11 +62,11 @@ def show_doc(obj, state, notebook_handle): elif isinstance(obj, dict): div = '\n'.join(div[k] for k in obj.keys()) - put_html(requirejs_tpl % (div, script)) + put_html(requirejs_tpl % (div, script), sanitize=False) def show_app(app, state, notebook_url, port=0, **kw): - """显示 Bokeh applications + """Show Bokeh applications :param app: A Bokeh Application to embed in PyWebIO. :param state: ** Unused ** @@ -110,7 +110,7 @@ def show_app(app, state, notebook_url, port=0, **kw): """, script) - put_html(script) + put_html(script, sanitize=False) def try_install_bokeh_hook(): From 83fc6d975b59e5588c4b7bb9ea546abefcd89afd Mon Sep 17 00:00:00 2001 From: wangweimin Date: Wed, 3 Feb 2021 19:16:58 +0800 Subject: [PATCH 019/445] main: add html escape to output functions --- pywebio/output.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/pywebio/output.py b/pywebio/output.py index 987c55c2..5a7d968c 100644 --- a/pywebio/output.py +++ b/pywebio/output.py @@ -120,6 +120,7 @@ .. autofunction:: output """ +import html import io import logging import string @@ -681,13 +682,15 @@ def put_image(src, format=None, title='', width=None, height=None, if isinstance(src, (bytes, bytearray)): b64content = b64encode(src).decode('ascii') format = '' if format is None else ('image/%s' % format) + format = html.escape(format, quote=True) src = "data:{format};base64, {b64content}".format(format=format, b64content=b64content) - width = 'width="%s"' % width if width is not None else '' - height = 'height="%s"' % height if height is not None else '' + width = 'width="%s"' % html.escape(width, quote=True) if width is not None else '' + height = 'height="%s"' % html.escape(height, quote=True) if height is not None else '' - html = r'{title}'.format(src=src, title=title, height=height, width=width) - return put_html(html, sanitize=False, scope=scope, position=position) + tag = r'{title}'.format(src=src, title=html.escape(title, quote=True), + height=height, width=width) + return put_html(tag, scope=scope, position=position) def put_file(name, content, label=None, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Output: @@ -737,8 +740,9 @@ def put_link(name, url=None, app=None, new_window=False, scope=Scope.Current, href = 'javascript:WebIO.openApp(%r, %d)' % (app, new_window) if app is not None else url target = '_blank' if (new_window and url) else '_self' - html = '{name}'.format(href=href, target=target, name=name) - return put_html(html, sanitize=False, scope=scope, position=position) + tag = '{name}'.format( + href=html.escape(href, quote=True), target=target, name=html.escape(name)) + return put_html(tag, scope=scope, position=position) def put_processbar(name, init=0, label=None, auto_close=False, scope=Scope.Current, @@ -1026,7 +1030,7 @@ def _row_column_layout(content, flow, size, scope=Scope.Current, position=Output {{#contents}} {{& pywebio_output_parse}} {{/contents}} -