Quellcode durchsuchen

maint: put_widget()、popup()、put_table() regard string input as put_text()

wangweimin vor 4 Jahren
Ursprung
Commit
767d130078
5 geänderte Dateien mit 49 neuen und 55 gelöschten Zeilen
  1. 4 4
      docs/guide.rst
  2. 14 12
      pywebio/output.py
  3. 6 6
      test/template.py
  4. 12 19
      webiojs/src/handlers/popup.ts
  5. 13 14
      webiojs/src/models/output.ts

+ 4 - 4
docs/guide.rst

@@ -143,8 +143,8 @@ PyWebIO提供的全部输出函数见 :doc:`pywebio.output </output>` 模块
 
     put_table([
         ['Type', 'Content'],
-        ['html', 'X<sup>2</sup>'],
-        ['text', put_text('<hr/>')],
+        ['html', put_html('X<sup>2</sup>')],
+        ['text', '<hr/>'],  # 等价于 ['text', put_text('<hr/>')]
         ['buttons', put_buttons(['A', 'B'], onclick=...)],
         ['markdown', put_markdown('`Awesome PyWebIO!`')],
         ['file', put_file('hello.text', b'')],
@@ -158,8 +158,8 @@ PyWebIO提供的全部输出函数见 :doc:`pywebio.output </output>` 模块
 类似地, `popup() <pywebio.output.popup>` 也可以将 ``put_xxx()`` 调用作为弹窗内容::
 
     popup('Popup title', [
-        '<h3>Popup Content</h3>',
-        put_text('html: <br/>'),
+        put_html('<h3>Popup Content</h3>'),
+        'plain html: <br/>',  # 等价于 put_text('plain html: <br/>')
         put_table([['A', 'B'], ['C', 'D']]),
         put_buttons(['close_popup()'], onclick=lambda _: close_popup())
     ])

+ 14 - 12
pywebio/output.py

@@ -229,7 +229,7 @@ def put_html(html, scope=Scope.Current, position=OutputPosition.BOTTOM) -> Outpu
 
     与支持通过Html输出内容到 `Jupyter Notebook <https://nbviewer.jupyter.org/github/ipython/ipython/blob/master/examples/IPython%20Kernel/Rich%20Output.ipynb#HTML>`_ 的库兼容。
 
-    :param html: html字符串或 实现了 `IPython.display.HTML` 接口的类的实例
+    :param html: html字符串或实现了 `IPython.display.HTML` 接口的类的实例
     :param int scope, position: 与 `put_text` 函数的同名参数含义一致
     """
     if hasattr(html, '__html__'):
@@ -332,8 +332,8 @@ def put_table(tdata, header=None, scope=Scope.Current, position=OutputPosition.B
     """
     输出表格
 
-    :param list tdata: 表格数据。列表项可以为 ``list`` 或者 ``dict`` , 单元格的内容可以为字符串或 ``put_xxx`` 类型的输出函数
-       字符串内容的单元格显示时会被当作html。数组项可以使用 :func:`span()` 函数来设定单元格跨度。
+    :param list tdata: 表格数据。列表项可以为 ``list`` 或者 ``dict`` , 单元格的内容可以为字符串或 ``put_xxx`` 类型的输出函数
+       数组项可以使用 :func:`span()` 函数来设定单元格跨度。
     :param list header: 设定表头。
        当 ``tdata`` 的列表项为 ``list`` 类型时,若省略 ``header`` 参数,则使用 ``tdata`` 的第一项作为表头。表头项可以使用 :func:`span()` 函数来设定单元格跨度。
 
@@ -355,8 +355,8 @@ def put_table(tdata, header=None, scope=Scope.Current, position=OutputPosition.B
         # 单元格为 ``put_xxx`` 类型的输出函数
         put_table([
             ['Type', 'Content'],
-            ['html', 'X<sup>2</sup>'],
-            ['text', put_text('<hr/>')],
+            ['html', put_html('X<sup>2</sup>')],
+            ['text', '<hr/>'],
             ['buttons', put_buttons(['A', 'B'], onclick=...)],
             ['markdown', put_markdown('`Awesome PyWebIO!`')],
             ['file', put_file('hello.text', b'')],
@@ -400,6 +400,8 @@ def put_table(tdata, header=None, scope=Scope.Current, position=OutputPosition.B
     for x in range(len(tdata)):
         for y in range(len(tdata[x])):
             cell = tdata[x][y]
+            if isinstance(cell, str):
+                tdata[x][y] = put_text(cell)
             if isinstance(cell, span_):
                 tdata[x][y] = cell.content
                 span['%s,%s' % (x, y)] = dict(col=cell.col, row=cell.row)
@@ -673,7 +675,7 @@ def put_collapse(title, content, open=False, scope=Scope.Current, position=Outpu
 
     :param str title: 内容标题
     :type content: list/str/put_xxx()
-    :param content: 内容可以为字符串或 ``put_xxx`` 类输出函数的返回值,或者为它们组成的列表。字符串内容会被看作html
+    :param content: 内容可以为字符串或 ``put_xxx`` 类输出函数的返回值,或者由它们组成的列表。
     :param bool open: 是否默认展开折叠内容。默认不展开内容
     :param int scope, position: 与 `put_text` 函数的同名参数含义一致
     """
@@ -698,7 +700,7 @@ def put_scrollable(content, max_height=400, horizon_scroll=False, border=True, s
     """宽高限制的内容输出区域,内容超出限制则显示滚动条
 
     :type content: list/str/put_xxx()
-    :param content: 内容可以为字符串或 ``put_xxx`` 类输出函数的返回值,或者为它们组成的列表。字符串内容会被看作html
+    :param content: 内容可以为字符串或 ``put_xxx`` 类输出函数的返回值,或者由它们组成的列表。
     :param int max_height: 区域的最大高度(像素),内容超出次高度则使用滚动条
     :param bool horizon_scroll: 是否显示水平滚动条
     :param bool border: 是否显示边框
@@ -736,7 +738,7 @@ def put_widget(template, data, scope=Scope.Current, position=OutputPosition.BOTT
     :param template: html模版,使用 `mustache.js <https://github.com/janl/mustache.js>`_ 语法
     :param dict data:  渲染模版使用的数据.
 
-       数据可以包含输出函数( ``put_xxx()`` )的返回值, 可以使用 ``pywebio_output_parse`` 函数来解析 ``put_xxx()`` 内容;对于字符串输入, ``pywebio_output_parse`` 会将解析成html.
+       数据可以包含输出函数( ``put_xxx()`` )的返回值, 可以使用 ``pywebio_output_parse`` 函数来解析 ``put_xxx()`` 内容;对于字符串输入, ``pywebio_output_parse`` 会将解析成文本.
 
        ⚠️:使用 ``pywebio_output_parse`` 函数时,需要关闭mustache的html转义: ``{{& pywebio_output_parse}}`` , 参见下文示例.
     :param int scope, position: 与 `put_text` 函数的同名参数含义一致
@@ -757,7 +759,7 @@ def put_widget(template, data, scope=Scope.Current, position=OutputPosition.BOTT
         put_widget(tpl, {
             "title": 'More content',
             "contents": [
-                put_text('text'),
+                'text',
                 put_markdown('~~删除线~~'),
                 put_table([
                     ['商品', '价格'],
@@ -1051,7 +1053,7 @@ def popup(title, content, size=PopupSize.NORMAL, implicit_close=True, closable=T
 
     :param str title: 弹窗标题
     :type content: list/str/put_xxx()
-    :param content: 弹窗内容. 可以为字符串或 ``put_xxx`` 类输出函数的返回值,或者为它们组成的列表。字符串内容会被看作html
+    :param content: 弹窗内容. 可以为字符串或 ``put_xxx`` 类输出函数的返回值,或者为它们组成的列表。
     :param str size: 弹窗窗口大小,可选值:
 
          * ``LARGE`` : 大尺寸
@@ -1067,8 +1069,8 @@ def popup(title, content, size=PopupSize.NORMAL, implicit_close=True, closable=T
         popup('popup title', 'popup html content', size=PopupSize.SMALL)
 
         popup('Popup title', [
-            '<h3>Popup Content</h3>',
-            put_text('html: <br/>'),
+            put_html('<h3>Popup Content</h3>'),
+            'html: <br/>',
             put_table([['A', 'B'], ['C', 'D']]),
             put_buttons(['close_popup()'], onclick=lambda _: close_popup())
         ])

+ 6 - 6
test/template.py

@@ -103,8 +103,8 @@ def basic_output():
     img_data = open(path.join(here_dir, 'assets', 'img.png'), 'rb').read()
     put_table([
         ['Type', 'Content'],
-        ['text', put_text('<hr/>', inline=True)],
-        ['html', 'X<sup>2</sup>'],
+        ['text', '<hr/>'],
+        ['html', put_html('X<sup>2</sup>')],
         ['buttons', put_buttons(['A', 'B'], onclick=None, small=True)],
         ['markdown', put_markdown('`awesome PyWebIO!`\n - 1\n - 2\n - 3')],
         ['file', put_file('hello.text', b'')],
@@ -130,11 +130,11 @@ def basic_output():
     def show_popup():
         popup('Popup title', [
             '<h3>Popup Content</h3>',
-            put_text('html: <br/>'),
+            'html: <br/>',
             put_table([
                 ['Type', 'Content'],
-                ['html', 'X<sup>2</sup>'],
-                ['text', put_text('<hr/>')],
+                ['html', put_html('X<sup>2</sup>')],
+                ['text', '<hr/>'],
                 ['buttons', put_buttons(['A', 'B'], onclick=...)],
                 ['markdown', put_markdown('`Awesome PyWebIO!`')],
                 ['file', put_file('hello.text', b'')],
@@ -170,7 +170,7 @@ def basic_output():
     put_file('hello_word.txt', b'hello word!')
 
     put_collapse('Collapse', [
-        put_text('text'),
+        'text',
         put_markdown('~~删除线~~'),
         put_table([
             ['商品', '价格'],

+ 12 - 19
webiojs/src/handlers/popup.ts

@@ -1,7 +1,7 @@
 import {Command, Session} from "../session";
 import {randomid} from "../utils";
 
-import {getWidgetElement} from "../models/output"
+import {getWidgetElement, outputSpecToHtml} from "../models/output"
 import {CommandHandler} from "./base";
 
 
@@ -70,7 +70,9 @@ export class PopupHandler implements CommandHandler {
                 {{/closable}}
               </div>
               <div class="modal-body markdown-body">
-                {{& content }}
+                {{#content}}
+                    {{& pywebio_output_parse}}
+                {{/content}}
               </div>
               <!--  
               <div class="modal-footer">
@@ -83,31 +85,22 @@ export class PopupHandler implements CommandHandler {
         </div>`;
         let mid = randomid(10);
 
-        let body_html = '';
-
-        for (let output_item of spec.content) {
-            if (typeof output_item === 'object') {
-                try {
-                    let nodes = getWidgetElement(output_item);
-                    for (let node of nodes)
-                        body_html += node.outerHTML || '';
-                } catch (e) {
-                    console.error('Get widget html error,', e, output_item);
-                }
-            } else {
-                body_html += output_item;
-            }
-        }
-
         if (!spec.closable)
             spec.implicit_close = false;
 
+        let pywebio_output_parse = function () {
+            if (this.type)
+                return outputSpecToHtml(this);
+            else
+                return outputSpecToHtml({type: 'text', content: this, inline: true});
+        };
+
         let html = Mustache.render(tpl, {
             ...spec,  // 字段: content, title, size, implicit_close, closable
             large: spec.size == 'large',
             small: spec.size == 'small',
             mid: mid,
-            content: body_html,
+            pywebio_output_parse: pywebio_output_parse
         });
         return $(html as string);
     }

+ 13 - 14
webiojs/src/models/output.ts

@@ -92,18 +92,6 @@ let File = {
     }
 };
 
-// 将output指令的spec字段解析成html字符串
-function outputSpecToHtml(spec: any) {
-    let html = '';
-    try {
-        let nodes = getWidgetElement(spec);
-        for (let node of nodes)
-            html += node.outerHTML || '';
-    } catch (e) {
-        console.error('Get sub widget html error,', e, spec);
-    }
-    return html;
-}
 
 let Table = {
     handle_type: 'table',
@@ -165,7 +153,7 @@ let CustomWidget = {
             if (this.type)
                 return outputSpecToHtml(this);
             else
-                return this
+                return outputSpecToHtml({type: 'text', content: this, inline: true});
         };
         let html = Mustache.render(spec.template, spec.data);
         return parseHtml(html);
@@ -191,6 +179,17 @@ export function getWidgetElement(spec: any) {
     return elem;
 }
 
-
+// 将output指令的spec字段解析成html字符串
+export function outputSpecToHtml(spec: any) {
+    let html = '';
+    try {
+        let nodes = getWidgetElement(spec);
+        for (let node of nodes)
+            html += node.outerHTML || '';
+    } catch (e) {
+        console.error('Get sub widget html error,', e, spec);
+    }
+    return html;
+}