├── tests
├── run.py
├── HTMLText_untagged.json
├── HTMLLabel_untagged.json
├── HTMLScrolledText_untagged.json
├── test_widgets.py
├── HTMLText_images.json
├── HTMLScrolledText_images.json
├── HTMLLabel_images.json
├── HTMLText_styles.json
├── HTMLScrolledText_styles.json
├── HTMLLabel_styles.json
└── HTMLText_tags.json
├── examples
├── py.png
├── img
│ ├── tags_tk.png
│ ├── images_tk.png
│ ├── styles_tk.png
│ ├── tags_pyqt5.png
│ ├── images_pyqt5.png
│ ├── styles_pyqt5.png
│ ├── tags_firefox.png
│ ├── images_firefox.png
│ └── styles_firefox.png
├── example.py
├── example2.py
├── tk_load_html.py
├── tags.html
├── images.html
├── pyqt5_load_html.py
└── styles.html
├── setup.py
├── LICENSE
├── README.md
└── tk_html_widgets
├── __init__.py
└── html_parser.py
/tests/run.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 | pytest.main()
--------------------------------------------------------------------------------
/examples/py.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paolo-gurisatti/tk_html_widgets/HEAD/examples/py.png
--------------------------------------------------------------------------------
/examples/img/tags_tk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paolo-gurisatti/tk_html_widgets/HEAD/examples/img/tags_tk.png
--------------------------------------------------------------------------------
/examples/img/images_tk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paolo-gurisatti/tk_html_widgets/HEAD/examples/img/images_tk.png
--------------------------------------------------------------------------------
/examples/img/styles_tk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paolo-gurisatti/tk_html_widgets/HEAD/examples/img/styles_tk.png
--------------------------------------------------------------------------------
/examples/img/tags_pyqt5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paolo-gurisatti/tk_html_widgets/HEAD/examples/img/tags_pyqt5.png
--------------------------------------------------------------------------------
/examples/img/images_pyqt5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paolo-gurisatti/tk_html_widgets/HEAD/examples/img/images_pyqt5.png
--------------------------------------------------------------------------------
/examples/img/styles_pyqt5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paolo-gurisatti/tk_html_widgets/HEAD/examples/img/styles_pyqt5.png
--------------------------------------------------------------------------------
/examples/img/tags_firefox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paolo-gurisatti/tk_html_widgets/HEAD/examples/img/tags_firefox.png
--------------------------------------------------------------------------------
/examples/img/images_firefox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paolo-gurisatti/tk_html_widgets/HEAD/examples/img/images_firefox.png
--------------------------------------------------------------------------------
/examples/img/styles_firefox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/paolo-gurisatti/tk_html_widgets/HEAD/examples/img/styles_firefox.png
--------------------------------------------------------------------------------
/examples/example.py:
--------------------------------------------------------------------------------
1 | import tkinter as tk
2 | from tk_html_widgets import HTMLLabel
3 |
4 | root = tk.Tk()
5 | html_label = HTMLLabel(root, html='
Hello World
')
6 | html_label.pack(fill="both", expand=True)
7 | html_label.fit_height()
8 | root.mainloop()
--------------------------------------------------------------------------------
/tests/HTMLText_untagged.json:
--------------------------------------------------------------------------------
1 | {
2 | "1.0": {
3 | "bind": {
4 | "link": null
5 | },
6 | "config": {
7 | "background": "SystemWindow",
8 | "foreground": "black",
9 | "justify": "left",
10 | "tabs": []
11 | },
12 | "end_index": "end",
13 | "font": {
14 | "family": "Segoe ui",
15 | "overstrike": false,
16 | "size": 9,
17 | "slant": "roman",
18 | "underline": false,
19 | "weight": "normal"
20 | },
21 | "start_index": "1.0"
22 | }
23 | }
--------------------------------------------------------------------------------
/tests/HTMLLabel_untagged.json:
--------------------------------------------------------------------------------
1 | {
2 | "1.0": {
3 | "bind": {
4 | "link": null
5 | },
6 | "config": {
7 | "background": "SystemButtonFace",
8 | "foreground": "black",
9 | "justify": "left",
10 | "tabs": []
11 | },
12 | "end_index": "end",
13 | "font": {
14 | "family": "Segoe ui",
15 | "overstrike": false,
16 | "size": 9,
17 | "slant": "roman",
18 | "underline": false,
19 | "weight": "normal"
20 | },
21 | "start_index": "1.0"
22 | }
23 | }
--------------------------------------------------------------------------------
/tests/HTMLScrolledText_untagged.json:
--------------------------------------------------------------------------------
1 | {
2 | "1.0": {
3 | "bind": {
4 | "link": null
5 | },
6 | "config": {
7 | "background": "SystemWindow",
8 | "foreground": "black",
9 | "justify": "left",
10 | "tabs": []
11 | },
12 | "end_index": "end",
13 | "font": {
14 | "family": "Segoe ui",
15 | "overstrike": false,
16 | "size": 9,
17 | "slant": "roman",
18 | "underline": false,
19 | "weight": "normal"
20 | },
21 | "start_index": "1.0"
22 | }
23 | }
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import setuptools
2 | import tk_html_widgets
3 |
4 | with open("README.md", "r") as fh:
5 | long_description = fh.read()
6 |
7 | setuptools.setup(
8 | name="tk_html_widgets",
9 | version=tk_html_widgets.VERSION,
10 | author="Paolo Gurisatti",
11 | author_email="paolo@fastmail.com",
12 | description="HTML widgets for tkinter",
13 | long_description=long_description,
14 | long_description_content_type="text/markdown",
15 | url="https://github.com/paolo-gurisatti/tk_html_widgets",
16 | packages=setuptools.find_packages(),
17 | classifiers=[
18 | "Programming Language :: Python :: 3",
19 | "License :: OSI Approved :: MIT License",
20 | "Operating System :: OS Independent",
21 | ],
22 | python_requires=">=3.4.*",
23 | install_requires=['Pillow>=5.3.0',],
24 | )
--------------------------------------------------------------------------------
/examples/example2.py:
--------------------------------------------------------------------------------
1 | import tkinter as tk
2 | from tk_html_widgets import HTMLLabel
3 |
4 | HTML = """
5 |
6 |
7 |
8 | www.python.org
9 |
10 |
11 |
12 |
"""
13 |
14 | root = tk.Tk()
15 | html_label = HTMLLabel(root, html=HTML % (0, 0, 0), width=50)
16 | html_label.pack(fill="both", expand=True)
17 | html_label.fit_height()
18 |
19 | rgb = [0, 0, 0]
20 | i = 0
21 | while True:
22 | for v in range(256):
23 | if i == 0:
24 | rgb[i] = v
25 | elif i == 1 or i == 2:
26 | rgb[i] = v
27 | rgb[i-1] = 255 - v
28 | elif i == 3:
29 | rgb[i-1] = 255 - v
30 |
31 | html_label.set_html(HTML % tuple(rgb))
32 | root.update()
33 | i += 1
34 | if i == 4:
35 | i = 0
--------------------------------------------------------------------------------
/examples/tk_load_html.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import tkinter as tk
4 | from argparse import ArgumentParser
5 |
6 | sys.path.insert(0, '..')
7 | from tk_html_widgets import HTMLText, HTMLScrolledText, HTMLLabel
8 |
9 | def start_gui(html):
10 | #----------------------------------------------------------------------------------------------
11 | root = tk.Tk()
12 | text = HTMLText(root)
13 | text.pack(fill="both", expand=True)
14 | text.set_html(html)
15 | text.fit_height()
16 | return root.mainloop()
17 |
18 |
19 | if __name__ == "__main__":
20 | #----------------------------------------------------------------------------------------------
21 | parser = ArgumentParser(usage="python3 %s " % __file__)
22 |
23 | parser.add_argument('html_file', help='Set html file to load')
24 |
25 | args = parser.parse_args()
26 |
27 | if os.path.exists(args.html_file):
28 | sys.exit(start_gui(open(args.html_file, "r" ).read()))
29 | else:
30 | print("File not found")
31 | sys.exit(1)
32 |
33 |
--------------------------------------------------------------------------------
/examples/tags.html:
--------------------------------------------------------------------------------
1 | unordered list 1st level
2 | - 1st element
3 | - 2nd element
4 | unordered list 2nd level
5 | - 1st element
6 | - 2nd element
7 |
8 |
9 |
10 |
11 | - 1st level 1st element
12 | - 1st level 2nd element
13 |
14 | - 2nd level 1st element
15 | - 2ndt level 2nd element
16 |
17 | - 3rd level 1st element
18 | - 3rd level 2nd element
19 |
20 |
21 |
22 |
23 | hyperlink
24 | bold
25 | strong
26 | italic
27 | emphasized
28 | underline
29 | marked
30 | spanned
31 | division
32 | paragraph
33 | preformatted
34 | heading 1
35 | heading 2
36 | heading 3
37 | heading 4
38 | heading 5
39 | heading 6
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 paolo-gurisatti
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/examples/images.html:
--------------------------------------------------------------------------------
1 | image:
2 | span
3 |
4 | span
5 |
6 | resized image:
7 | span
8 |
9 | span again
10 |
11 |
12 | links:
13 | default style link
14 | custom style link
15 | clickable image
16 |
17 |
18 | - clickable image list1
19 | - clickable image list2
20 |
21 |
22 |
--------------------------------------------------------------------------------
/examples/pyqt5_load_html.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | from argparse import ArgumentParser
4 |
5 | from PyQt5.QtWidgets import QApplication, QTextBrowser
6 | from PyQt5 import QtGui
7 |
8 | #__________________________________________________________________________________________________
9 | # Terminal Tab viewer
10 |
11 | def start_gui(argv, html):
12 | #----------------------------------------------------------------------------------------------
13 | app = QApplication(argv)
14 | text = QTextBrowser()
15 | text.setOpenLinks(False)
16 | text.setReadOnly(True)
17 | text.setHtml(html)
18 | text.show()
19 | return app.exec_()
20 |
21 |
22 | if __name__ == "__main__":
23 | #----------------------------------------------------------------------------------------------
24 | parser = ArgumentParser(usage="python3 %s " % __file__)
25 |
26 | parser.add_argument('html_file', help='Set html file to load')
27 |
28 | args = parser.parse_args()
29 |
30 | if os.path.exists(args.html_file):
31 | sys.exit(start_gui(sys.argv, open(args.html_file, "r" ).read()))
32 | else:
33 | print("File not found")
34 | sys.exit(1)
35 |
36 |
--------------------------------------------------------------------------------
/examples/styles.html:
--------------------------------------------------------------------------------
1 | a style
2 | b style
3 | strong style
4 | i style
5 | em style
6 | u style
7 | mark style
8 | span style
9 | div style
10 | p style
11 | pre style
12 | h1 style
13 | h2 style
14 | h3 style
15 | h4 style
16 | h5 style
17 | h6 style
18 |
19 | red
20 | green
21 | yellow
22 |
23 |
24 | red again
25 |
26 |
--------------------------------------------------------------------------------
/tests/test_widgets.py:
--------------------------------------------------------------------------------
1 | import json
2 | import sys
3 | import pytest
4 | import tkinter as tk
5 |
6 | sys.path.insert(0, '..')
7 | from tk_html_widgets import HTMLText, HTMLScrolledText, HTMLLabel
8 | from tk_html_widgets.html_parser import *
9 |
10 |
11 | @pytest.mark.parametrize("f", ('tags', 'styles', 'images'))
12 | @pytest.mark.parametrize("Widget", (HTMLText, HTMLScrolledText, HTMLLabel))
13 | def test_tags(Widget, f):
14 | #----------------------------------------------------------------------------------------------
15 | for _ in range(10):
16 | try:
17 | root = tk.Tk()
18 | break
19 | except Exception as e:
20 | exception = e
21 | else:
22 | raise exception
23 | text = Widget(root)
24 | text.pack(fill="both", expand=True)
25 | text.set_html(open("../examples/%s.html" % f, 'r').read(), strip=True)
26 | text.fit_height()
27 | tags_json = json.dumps(text.html_parser._w_tags, sort_keys=True, indent=4)
28 | #open(Widget.__name__ + '_%s.json' % f, 'w').write(tags_json)
29 | assert open(Widget.__name__ + '_%s.json' % f, 'r').read() == tags_json
30 |
31 | # check stack lenght
32 | assert len(text.html_parser.stack[WCfg.KEY][WCfg.BACKGROUND]) == 1
33 | assert len(text.html_parser.stack[WCfg.KEY][WCfg.FOREGROUND]) == 1
34 | assert len(text.html_parser.stack[WCfg.KEY][WCfg.JUSTIFY]) == 1
35 | assert len(text.html_parser.stack[WCfg.KEY][WCfg.TABS]) == 1
36 | assert len(text.html_parser.stack[Fnt.KEY][Fnt.FAMILY]) == 1
37 | assert len(text.html_parser.stack[Fnt.KEY][Fnt.SIZE]) == 1
38 | assert len(text.html_parser.stack[Fnt.KEY][Fnt.WEIGHT]) == 1
39 | assert len(text.html_parser.stack[Fnt.KEY][Fnt.SLANT]) == 1
40 | assert len(text.html_parser.stack[Fnt.KEY][Fnt.UNDERLINE]) == 1
41 | assert len(text.html_parser.stack[Fnt.KEY][Fnt.OVERSTRIKE]) == 1
42 | assert len(text.html_parser.stack[Bind.KEY][Bind.LINK]) == 1
43 | root.destroy()
44 |
45 |
46 | @pytest.mark.parametrize("Widget", (HTMLText, HTMLScrolledText, HTMLLabel))
47 | def test_untagged(Widget):
48 | #----------------------------------------------------------------------------------------------
49 | for _ in range(10):
50 | try:
51 | root = tk.Tk()
52 | break
53 | except Exception as e:
54 | exception = e
55 | else:
56 | raise exception
57 | text = Widget(root)
58 | text.pack(fill="both", expand=True)
59 | text.set_html("untagged")
60 | text.fit_height()
61 | tags_json = json.dumps(text.html_parser._w_tags, sort_keys=True, indent=4)
62 | #open(Widget.__name__ + '_untagged.json', 'w').write(tags_json)
63 | assert open(Widget.__name__ + '_untagged.json', 'r').read() == tags_json
64 |
65 | # check stack lenght
66 | assert len(text.html_parser.stack[WCfg.KEY][WCfg.BACKGROUND]) == 1
67 | assert len(text.html_parser.stack[WCfg.KEY][WCfg.FOREGROUND]) == 1
68 | assert len(text.html_parser.stack[WCfg.KEY][WCfg.JUSTIFY]) == 1
69 | assert len(text.html_parser.stack[WCfg.KEY][WCfg.TABS]) == 1
70 | assert len(text.html_parser.stack[Fnt.KEY][Fnt.FAMILY]) == 1
71 | assert len(text.html_parser.stack[Fnt.KEY][Fnt.SIZE]) == 1
72 | assert len(text.html_parser.stack[Fnt.KEY][Fnt.WEIGHT]) == 1
73 | assert len(text.html_parser.stack[Fnt.KEY][Fnt.SLANT]) == 1
74 | assert len(text.html_parser.stack[Fnt.KEY][Fnt.UNDERLINE]) == 1
75 | assert len(text.html_parser.stack[Fnt.KEY][Fnt.OVERSTRIKE]) == 1
76 | assert len(text.html_parser.stack[Bind.KEY][Bind.LINK]) == 1
77 | root.destroy()
78 |
79 |
80 | def test_html_format():
81 | #----------------------------------------------------------------------------------------------
82 | TEXT = ' text color #%06x'
83 | for _ in range(10):
84 | try:
85 | root = tk.Tk()
86 | break
87 | except Exception as e:
88 | exception = e
89 | else:
90 | raise exception
91 | text = HTMLLabel(root, height=10)
92 | text.pack(fill="both", expand=True)
93 | for increment in (0x010000, 0x000100, 0x000001):
94 | for i in range(0, increment*256, increment):
95 | text.set_html(TEXT % (i, increment*255, i))
96 | root.update()
97 | root.destroy()
98 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # tk_html_widgets
2 | HTML widgets for tkinter
3 |
4 | ## Overview
5 | This module is a collection of tkinter widgets whose text can be set in HTML format.
6 | A HTML widget isn't a web browser frame, it's only a simple and lightweight HTML parser that formats the tags used by the tkinter Text base class.
7 | The widgets behaviour is similar to the PyQt5 text widgets (see the [PyQt5 HTML markup subset](http://doc.qt.io/qt-5/richtext-html-subset.html)).
8 |
9 | ## Installation
10 | ``pip install tk_html_widgets``
11 |
12 | ## Requirements
13 | - [Python 3.4 or later](https://www.python.org/downloads/) with tcl/tk support
14 | - [Pillow 5.3.0](https://github.com/python-pillow/Pillow)
15 |
16 | ## Example
17 | ```python
18 | import tkinter as tk
19 | from tk_html_widgets import HTMLLabel
20 |
21 | root = tk.Tk()
22 | html_label = HTMLLabel(root, html=' Hello World
')
23 | html_label.pack(fill="both", expand=True)
24 | html_label.fit_height()
25 | root.mainloop()
26 | ```
27 |
28 | ## Documentation
29 |
30 | ### Classes:
31 | All widget classes inherits from the tkinter.Text() base class.
32 |
33 | #### class HTMLScrolledText(tkinter.Text)
34 | > Text-box widget with vertical scrollbar
35 | #### class HTMLText(tkinter.Text)
36 | > Text-box widget without vertical scrollbar
37 | #### class HTMLLabel(tkinter.Text)
38 | > Text-box widget with label appereance
39 |
40 | ### Methods:
41 | #### def set_html(self, html, strip=True):
42 | > **Description:** Sets the text in HTML format.
43 | > **Args:**
44 | > - *html*: input HTML string
45 | > - *strip*: if True (default) handles spaces in HTML-like style
46 |
47 | #### def fit_height(self):
48 | > **Description:** Fit widget height in order to display all wrapped lines
49 |
50 | ### HTML support:
51 | Only a subset of the whole HTML tags and attributes are supported (see table below).
52 | Where is possibile, I hope to add more HTML support in the next releases.
53 |
54 | **Tags** | **Attributes** | **Notes**
55 | --- | --- | ---
56 | a| style, href |
57 | b| style |
58 | br||
59 | code | style |
60 | div | style |
61 | em| style |
62 | h1 | style |
63 | h2 | style |
64 | h3 | style |
65 | h4 | style |
66 | h5 | style |
67 | h6 | style |
68 | i| style |
69 | img| src, width, height | local images only
70 | li| style |
71 | mark| style |
72 | ol| style, type | 1, a, A list types only
73 | p | style |
74 | pre | style |
75 | span| style |
76 | strong| style |
77 | u| style |
78 | ul| style | bullet glyphs only
79 |
80 | ## Comparison chart
81 | In order to check the appearance of the HTML text displayed by the tk_html_widgets, I made some HTML templates and I compared the text displayed by the HTMLText widget with the text displayed by Firefox and the PyQt5 QTextBrowser widget.
82 | See details and templates HTML code in the [examples folder](https://github.com/paolo-gurisatti/tk_html_widgets/tree/master/examples).
83 |
84 | ### Tags template comparison:
85 | **Firefox** | **tk_html_widgets.HTMLText** | **PyQt5.QtWidgets.QTextBrowser**
86 | --- | --- | ---
87 | ||
88 |
89 | ### Styles template comparison:
90 | **Firefox** | **tk_html_widgets.HTMLText** | **PyQt5.QtWidgets.QTextBrowser**
91 | --- | --- | ---
92 | ||
93 |
94 | ### Images template comparison:
95 | **Firefox** | **tk_html_widgets.HTMLText** | **PyQt5.QtWidgets.QTextBrowser**
96 | --- | --- | ---
97 | ||
98 |
99 |
100 | ## Acknowledgements
101 | Thanks to my mentor, valued collegue and friend [JayZar21](https://github.com/JayZar21).
102 |
--------------------------------------------------------------------------------
/tk_html_widgets/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | tkinter HTML text widgets
3 | """
4 | import sys
5 | import tkinter as tk
6 | from tkinter import scrolledtext
7 | from tkinter import font
8 | from tk_html_widgets import html_parser
9 |
10 | VERSION = "0.4.0"
11 |
12 | class _ScrolledText(tk.Text):
13 | #----------------------------------------------------------------------------------------------
14 | def __init__(self, master=None, **kw):
15 | self.frame = tk.Frame(master)
16 |
17 | self.vbar = tk.Scrollbar(self.frame)
18 | kw.update({'yscrollcommand': self.vbar.set})
19 | self.vbar.pack(side=tk.RIGHT, fill=tk.Y)
20 | self.vbar['command'] = self.yview
21 |
22 | tk.Text.__init__(self, self.frame, **kw)
23 | self.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
24 |
25 | text_meths = vars(tk.Text).keys()
26 | methods = vars(tk.Pack).keys() | vars(tk.Grid).keys() | vars(tk.Place).keys()
27 | methods = methods.difference(text_meths)
28 |
29 | for m in methods:
30 | if m[0] != '_' and m != 'config' and m != 'configure':
31 | setattr(self, m, getattr(self.frame, m))
32 |
33 | def __str__(self):
34 | return str(self.frame)
35 |
36 | class HTMLScrolledText(_ScrolledText):
37 | #----------------------------------------------------------------------------------------------
38 | """
39 | HTML scrolled text widget
40 | """
41 | def __init__(self, *args, html=None, **kwargs):
42 | #------------------------------------------------------------------------------------------
43 | super().__init__(*args, **kwargs)
44 | self._w_init(kwargs)
45 | self.html_parser = html_parser.HTMLTextParser()
46 | if isinstance(html, str):
47 | self.set_html(html)
48 |
49 |
50 | def _w_init(self, kwargs):
51 | #------------------------------------------------------------------------------------------
52 | if not 'wrap' in kwargs.keys():
53 | self.config(wrap='word')
54 | if not 'background' in kwargs.keys():
55 | if sys.platform.startswith('win'):
56 | self.config(background='SystemWindow')
57 | else:
58 | self.config(background='white')
59 |
60 |
61 | def fit_height(self):
62 | #------------------------------------------------------------------------------------------
63 | """
64 | Fit widget height to wrapped lines
65 | """
66 | for h in range(1, 4):
67 | self.config(height=h)
68 | self.master.update()
69 | if self.yview()[1] >= 1:
70 | break
71 | else:
72 | self.config(height=0.5+3/self.yview()[1])
73 |
74 |
75 | def set_html(self, html, strip=True):
76 | #------------------------------------------------------------------------------------------
77 | """
78 | Set HTML widget text. If strip is enabled (default) it ignores spaces and new lines.
79 |
80 | """
81 | prev_state = self.cget('state')
82 | self.config(state=tk.NORMAL)
83 | self.delete('1.0', tk.END)
84 | self.tag_delete(self.tag_names)
85 | self.html_parser.w_set_html(self, html, strip=strip)
86 | self.config(state=prev_state)
87 |
88 |
89 | class HTMLText(HTMLScrolledText):
90 | #----------------------------------------------------------------------------------------------
91 | """
92 | HTML text widget
93 | """
94 | def _w_init(self, kwargs):
95 | #------------------------------------------------------------------------------------------
96 | super()._w_init(kwargs)
97 | self.vbar.pack_forget()
98 |
99 | def fit_height(self):
100 | #------------------------------------------------------------------------------------------
101 | super().fit_height()
102 | #self.master.update()
103 | self.vbar.pack_forget()
104 |
105 | class HTMLLabel(HTMLText):
106 | #----------------------------------------------------------------------------------------------
107 | """
108 | HTML label widget
109 | """
110 | def _w_init(self, kwargs):
111 | #------------------------------------------------------------------------------------------
112 | super()._w_init(kwargs)
113 | if not 'background' in kwargs.keys():
114 | if sys.platform.startswith('win'):
115 | self.config(background='SystemButtonFace')
116 | else:
117 | self.config(background='#d9d9d9')
118 |
119 | if not 'borderwidth' in kwargs.keys():
120 | self.config(borderwidth=0)
121 |
122 | if not 'padx' in kwargs.keys():
123 | self.config(padx=3)
124 |
125 | def set_html(self, *args, **kwargs):
126 | #------------------------------------------------------------------------------------------
127 | super().set_html(*args, **kwargs)
128 | self.config(state=tk.DISABLED)
129 |
130 |
--------------------------------------------------------------------------------
/tests/HTMLText_images.json:
--------------------------------------------------------------------------------
1 | {
2 | "1.0": {
3 | "bind": {
4 | "link": null
5 | },
6 | "config": {
7 | "background": "SystemWindow",
8 | "foreground": "black",
9 | "justify": "center",
10 | "tabs": []
11 | },
12 | "end_index": "2.0",
13 | "font": {
14 | "family": "Segoe ui",
15 | "overstrike": false,
16 | "size": 16,
17 | "slant": "roman",
18 | "underline": false,
19 | "weight": "bold"
20 | },
21 | "start_index": "1.0"
22 | },
23 | "10.0": {
24 | "bind": {
25 | "link": null
26 | },
27 | "config": {
28 | "background": "SystemWindow",
29 | "foreground": "black",
30 | "justify": "left",
31 | "tabs": []
32 | },
33 | "end_index": "11.0",
34 | "font": {
35 | "family": "Segoe ui",
36 | "overstrike": false,
37 | "size": 9,
38 | "slant": "roman",
39 | "underline": false,
40 | "weight": "normal"
41 | },
42 | "start_index": "10.0"
43 | },
44 | "11.0": {
45 | "bind": {
46 | "link": "https://www.python.org"
47 | },
48 | "config": {
49 | "background": "SystemWindow",
50 | "foreground": "blue",
51 | "justify": "left",
52 | "tabs": []
53 | },
54 | "end_index": "11.19",
55 | "font": {
56 | "family": "Segoe ui",
57 | "overstrike": false,
58 | "size": 9,
59 | "slant": "roman",
60 | "underline": true,
61 | "weight": "normal"
62 | },
63 | "start_index": "11.0"
64 | },
65 | "11.19": {
66 | "bind": {
67 | "link": null
68 | },
69 | "config": {
70 | "background": "SystemWindow",
71 | "foreground": "black",
72 | "justify": "left",
73 | "tabs": []
74 | },
75 | "end_index": "12.0",
76 | "font": {
77 | "family": "Segoe ui",
78 | "overstrike": false,
79 | "size": 9,
80 | "slant": "roman",
81 | "underline": false,
82 | "weight": "normal"
83 | },
84 | "start_index": "11.19"
85 | },
86 | "12.0": {
87 | "bind": {
88 | "link": "https://www.python.org"
89 | },
90 | "config": {
91 | "background": "SystemWindow",
92 | "foreground": "red",
93 | "justify": "left",
94 | "tabs": []
95 | },
96 | "end_index": "12.18",
97 | "font": {
98 | "family": "Segoe ui",
99 | "overstrike": false,
100 | "size": 9,
101 | "slant": "roman",
102 | "underline": false,
103 | "weight": "normal"
104 | },
105 | "start_index": "12.0"
106 | },
107 | "12.18": {
108 | "bind": {
109 | "link": null
110 | },
111 | "config": {
112 | "background": "SystemWindow",
113 | "foreground": "black",
114 | "justify": "left",
115 | "tabs": []
116 | },
117 | "end_index": "13.0",
118 | "font": {
119 | "family": "Segoe ui",
120 | "overstrike": false,
121 | "size": 9,
122 | "slant": "roman",
123 | "underline": false,
124 | "weight": "normal"
125 | },
126 | "start_index": "12.18"
127 | },
128 | "13.0": {
129 | "bind": {
130 | "link": null
131 | },
132 | "config": {
133 | "background": "SystemWindow",
134 | "foreground": "black",
135 | "justify": "left",
136 | "tabs": []
137 | },
138 | "end_index": "13.16",
139 | "font": {
140 | "family": "Segoe ui",
141 | "overstrike": false,
142 | "size": 9,
143 | "slant": "roman",
144 | "underline": false,
145 | "weight": "normal"
146 | },
147 | "start_index": "13.0"
148 | },
149 | "13.16": {
150 | "bind": {
151 | "link": null
152 | },
153 | "config": {
154 | "background": "SystemWindow",
155 | "foreground": "black",
156 | "justify": "left",
157 | "tabs": []
158 | },
159 | "end_index": "14.0",
160 | "font": {
161 | "family": "Segoe ui",
162 | "overstrike": false,
163 | "size": 9,
164 | "slant": "roman",
165 | "underline": false,
166 | "weight": "normal"
167 | },
168 | "start_index": "13.16"
169 | },
170 | "14.0": {
171 | "bind": {
172 | "link": null
173 | },
174 | "config": {
175 | "background": "SystemWindow",
176 | "foreground": "black",
177 | "justify": "left",
178 | "tabs": []
179 | },
180 | "end_index": "15.0",
181 | "font": {
182 | "family": "Segoe ui",
183 | "overstrike": false,
184 | "size": 9,
185 | "slant": "roman",
186 | "underline": false,
187 | "weight": "normal"
188 | },
189 | "start_index": "14.0"
190 | },
191 | "15.0": {
192 | "bind": {
193 | "link": null
194 | },
195 | "config": {
196 | "background": "SystemWindow",
197 | "foreground": "#3333ff",
198 | "justify": "left",
199 | "tabs": [
200 | 30,
201 | "right",
202 | 35,
203 | "left"
204 | ]
205 | },
206 | "end_index": "15.3",
207 | "font": {
208 | "family": "Segoe ui",
209 | "overstrike": false,
210 | "size": 9,
211 | "slant": "roman",
212 | "underline": false,
213 | "weight": "normal"
214 | },
215 | "start_index": "15.0"
216 | },
217 | "15.26": {
218 | "bind": {
219 | "link": null
220 | },
221 | "config": {
222 | "background": "SystemWindow",
223 | "foreground": "#3333ff",
224 | "justify": "left",
225 | "tabs": [
226 | 30,
227 | "right",
228 | 35,
229 | "left"
230 | ]
231 | },
232 | "end_index": "16.0",
233 | "font": {
234 | "family": "Segoe ui",
235 | "overstrike": false,
236 | "size": 9,
237 | "slant": "roman",
238 | "underline": false,
239 | "weight": "normal"
240 | },
241 | "start_index": "15.26"
242 | },
243 | "15.3": {
244 | "bind": {
245 | "link": null
246 | },
247 | "config": {
248 | "background": "SystemWindow",
249 | "foreground": "#3333ff",
250 | "justify": "left",
251 | "tabs": [
252 | 30,
253 | "right",
254 | 35,
255 | "left"
256 | ]
257 | },
258 | "end_index": "15.26",
259 | "font": {
260 | "family": "Segoe ui",
261 | "overstrike": false,
262 | "size": 9,
263 | "slant": "roman",
264 | "underline": false,
265 | "weight": "normal"
266 | },
267 | "start_index": "15.3"
268 | },
269 | "16.0": {
270 | "bind": {
271 | "link": null
272 | },
273 | "config": {
274 | "background": "SystemWindow",
275 | "foreground": "#33aaff",
276 | "justify": "left",
277 | "tabs": [
278 | 30,
279 | "right",
280 | 35,
281 | "left"
282 | ]
283 | },
284 | "end_index": "16.3",
285 | "font": {
286 | "family": "Segoe ui",
287 | "overstrike": false,
288 | "size": 9,
289 | "slant": "roman",
290 | "underline": false,
291 | "weight": "normal"
292 | },
293 | "start_index": "16.0"
294 | },
295 | "16.26": {
296 | "bind": {
297 | "link": null
298 | },
299 | "config": {
300 | "background": "SystemWindow",
301 | "foreground": "#33aaff",
302 | "justify": "left",
303 | "tabs": [
304 | 30,
305 | "right",
306 | 35,
307 | "left"
308 | ]
309 | },
310 | "end_index": "17.0",
311 | "font": {
312 | "family": "Segoe ui",
313 | "overstrike": false,
314 | "size": 9,
315 | "slant": "roman",
316 | "underline": false,
317 | "weight": "normal"
318 | },
319 | "start_index": "16.26"
320 | },
321 | "16.3": {
322 | "bind": {
323 | "link": null
324 | },
325 | "config": {
326 | "background": "SystemWindow",
327 | "foreground": "#33aaff",
328 | "justify": "left",
329 | "tabs": [
330 | 30,
331 | "right",
332 | 35,
333 | "left"
334 | ]
335 | },
336 | "end_index": "16.26",
337 | "font": {
338 | "family": "Segoe ui",
339 | "overstrike": false,
340 | "size": 9,
341 | "slant": "roman",
342 | "underline": false,
343 | "weight": "normal"
344 | },
345 | "start_index": "16.3"
346 | },
347 | "17.0": {
348 | "bind": {
349 | "link": null
350 | },
351 | "config": {
352 | "background": "SystemWindow",
353 | "foreground": "black",
354 | "justify": "left",
355 | "tabs": []
356 | },
357 | "end_index": "end",
358 | "font": {
359 | "family": "Segoe ui",
360 | "overstrike": false,
361 | "size": 9,
362 | "slant": "roman",
363 | "underline": false,
364 | "weight": "normal"
365 | },
366 | "start_index": "17.0"
367 | },
368 | "2.0": {
369 | "bind": {
370 | "link": null
371 | },
372 | "config": {
373 | "background": "SystemWindow",
374 | "foreground": "black",
375 | "justify": "left",
376 | "tabs": []
377 | },
378 | "end_index": "3.0",
379 | "font": {
380 | "family": "Segoe ui",
381 | "overstrike": false,
382 | "size": 9,
383 | "slant": "roman",
384 | "underline": false,
385 | "weight": "normal"
386 | },
387 | "start_index": "2.0"
388 | },
389 | "3.0": {
390 | "bind": {
391 | "link": null
392 | },
393 | "config": {
394 | "background": "black",
395 | "foreground": "yellow",
396 | "justify": "left",
397 | "tabs": []
398 | },
399 | "end_index": "3.5",
400 | "font": {
401 | "family": "Segoe ui",
402 | "overstrike": false,
403 | "size": 13,
404 | "slant": "roman",
405 | "underline": false,
406 | "weight": "normal"
407 | },
408 | "start_index": "3.0"
409 | },
410 | "3.10": {
411 | "bind": {
412 | "link": null
413 | },
414 | "config": {
415 | "background": "SystemWindow",
416 | "foreground": "black",
417 | "justify": "left",
418 | "tabs": []
419 | },
420 | "end_index": "5.0",
421 | "font": {
422 | "family": "Segoe ui",
423 | "overstrike": false,
424 | "size": 9,
425 | "slant": "roman",
426 | "underline": false,
427 | "weight": "normal"
428 | },
429 | "start_index": "3.10"
430 | },
431 | "3.5": {
432 | "bind": {
433 | "link": null
434 | },
435 | "config": {
436 | "background": "black",
437 | "foreground": "yellow",
438 | "justify": "left",
439 | "tabs": []
440 | },
441 | "end_index": "3.10",
442 | "font": {
443 | "family": "Segoe ui",
444 | "overstrike": false,
445 | "size": 13,
446 | "slant": "roman",
447 | "underline": false,
448 | "weight": "normal"
449 | },
450 | "start_index": "3.5"
451 | },
452 | "5.0": {
453 | "bind": {
454 | "link": null
455 | },
456 | "config": {
457 | "background": "SystemWindow",
458 | "foreground": "black",
459 | "justify": "center",
460 | "tabs": []
461 | },
462 | "end_index": "6.0",
463 | "font": {
464 | "family": "Segoe ui",
465 | "overstrike": false,
466 | "size": 16,
467 | "slant": "roman",
468 | "underline": false,
469 | "weight": "bold"
470 | },
471 | "start_index": "5.0"
472 | },
473 | "6.0": {
474 | "bind": {
475 | "link": null
476 | },
477 | "config": {
478 | "background": "SystemWindow",
479 | "foreground": "black",
480 | "justify": "left",
481 | "tabs": []
482 | },
483 | "end_index": "7.0",
484 | "font": {
485 | "family": "Segoe ui",
486 | "overstrike": false,
487 | "size": 9,
488 | "slant": "roman",
489 | "underline": false,
490 | "weight": "normal"
491 | },
492 | "start_index": "6.0"
493 | },
494 | "7.0": {
495 | "bind": {
496 | "link": null
497 | },
498 | "config": {
499 | "background": "black",
500 | "foreground": "yellow",
501 | "justify": "left",
502 | "tabs": []
503 | },
504 | "end_index": "7.5",
505 | "font": {
506 | "family": "Segoe ui",
507 | "overstrike": false,
508 | "size": 20,
509 | "slant": "roman",
510 | "underline": false,
511 | "weight": "normal"
512 | },
513 | "start_index": "7.0"
514 | },
515 | "7.16": {
516 | "bind": {
517 | "link": null
518 | },
519 | "config": {
520 | "background": "SystemWindow",
521 | "foreground": "black",
522 | "justify": "left",
523 | "tabs": []
524 | },
525 | "end_index": "9.0",
526 | "font": {
527 | "family": "Segoe ui",
528 | "overstrike": false,
529 | "size": 9,
530 | "slant": "roman",
531 | "underline": false,
532 | "weight": "normal"
533 | },
534 | "start_index": "7.16"
535 | },
536 | "7.5": {
537 | "bind": {
538 | "link": null
539 | },
540 | "config": {
541 | "background": "black",
542 | "foreground": "yellow",
543 | "justify": "left",
544 | "tabs": []
545 | },
546 | "end_index": "7.16",
547 | "font": {
548 | "family": "Segoe ui",
549 | "overstrike": false,
550 | "size": 20,
551 | "slant": "roman",
552 | "underline": false,
553 | "weight": "normal"
554 | },
555 | "start_index": "7.5"
556 | },
557 | "9.0": {
558 | "bind": {
559 | "link": null
560 | },
561 | "config": {
562 | "background": "SystemWindow",
563 | "foreground": "black",
564 | "justify": "center",
565 | "tabs": []
566 | },
567 | "end_index": "10.0",
568 | "font": {
569 | "family": "Segoe ui",
570 | "overstrike": false,
571 | "size": 16,
572 | "slant": "roman",
573 | "underline": false,
574 | "weight": "bold"
575 | },
576 | "start_index": "9.0"
577 | }
578 | }
--------------------------------------------------------------------------------
/tests/HTMLScrolledText_images.json:
--------------------------------------------------------------------------------
1 | {
2 | "1.0": {
3 | "bind": {
4 | "link": null
5 | },
6 | "config": {
7 | "background": "SystemWindow",
8 | "foreground": "black",
9 | "justify": "center",
10 | "tabs": []
11 | },
12 | "end_index": "2.0",
13 | "font": {
14 | "family": "Segoe ui",
15 | "overstrike": false,
16 | "size": 16,
17 | "slant": "roman",
18 | "underline": false,
19 | "weight": "bold"
20 | },
21 | "start_index": "1.0"
22 | },
23 | "10.0": {
24 | "bind": {
25 | "link": null
26 | },
27 | "config": {
28 | "background": "SystemWindow",
29 | "foreground": "black",
30 | "justify": "left",
31 | "tabs": []
32 | },
33 | "end_index": "11.0",
34 | "font": {
35 | "family": "Segoe ui",
36 | "overstrike": false,
37 | "size": 9,
38 | "slant": "roman",
39 | "underline": false,
40 | "weight": "normal"
41 | },
42 | "start_index": "10.0"
43 | },
44 | "11.0": {
45 | "bind": {
46 | "link": "https://www.python.org"
47 | },
48 | "config": {
49 | "background": "SystemWindow",
50 | "foreground": "blue",
51 | "justify": "left",
52 | "tabs": []
53 | },
54 | "end_index": "11.19",
55 | "font": {
56 | "family": "Segoe ui",
57 | "overstrike": false,
58 | "size": 9,
59 | "slant": "roman",
60 | "underline": true,
61 | "weight": "normal"
62 | },
63 | "start_index": "11.0"
64 | },
65 | "11.19": {
66 | "bind": {
67 | "link": null
68 | },
69 | "config": {
70 | "background": "SystemWindow",
71 | "foreground": "black",
72 | "justify": "left",
73 | "tabs": []
74 | },
75 | "end_index": "12.0",
76 | "font": {
77 | "family": "Segoe ui",
78 | "overstrike": false,
79 | "size": 9,
80 | "slant": "roman",
81 | "underline": false,
82 | "weight": "normal"
83 | },
84 | "start_index": "11.19"
85 | },
86 | "12.0": {
87 | "bind": {
88 | "link": "https://www.python.org"
89 | },
90 | "config": {
91 | "background": "SystemWindow",
92 | "foreground": "red",
93 | "justify": "left",
94 | "tabs": []
95 | },
96 | "end_index": "12.18",
97 | "font": {
98 | "family": "Segoe ui",
99 | "overstrike": false,
100 | "size": 9,
101 | "slant": "roman",
102 | "underline": false,
103 | "weight": "normal"
104 | },
105 | "start_index": "12.0"
106 | },
107 | "12.18": {
108 | "bind": {
109 | "link": null
110 | },
111 | "config": {
112 | "background": "SystemWindow",
113 | "foreground": "black",
114 | "justify": "left",
115 | "tabs": []
116 | },
117 | "end_index": "13.0",
118 | "font": {
119 | "family": "Segoe ui",
120 | "overstrike": false,
121 | "size": 9,
122 | "slant": "roman",
123 | "underline": false,
124 | "weight": "normal"
125 | },
126 | "start_index": "12.18"
127 | },
128 | "13.0": {
129 | "bind": {
130 | "link": null
131 | },
132 | "config": {
133 | "background": "SystemWindow",
134 | "foreground": "black",
135 | "justify": "left",
136 | "tabs": []
137 | },
138 | "end_index": "13.16",
139 | "font": {
140 | "family": "Segoe ui",
141 | "overstrike": false,
142 | "size": 9,
143 | "slant": "roman",
144 | "underline": false,
145 | "weight": "normal"
146 | },
147 | "start_index": "13.0"
148 | },
149 | "13.16": {
150 | "bind": {
151 | "link": null
152 | },
153 | "config": {
154 | "background": "SystemWindow",
155 | "foreground": "black",
156 | "justify": "left",
157 | "tabs": []
158 | },
159 | "end_index": "14.0",
160 | "font": {
161 | "family": "Segoe ui",
162 | "overstrike": false,
163 | "size": 9,
164 | "slant": "roman",
165 | "underline": false,
166 | "weight": "normal"
167 | },
168 | "start_index": "13.16"
169 | },
170 | "14.0": {
171 | "bind": {
172 | "link": null
173 | },
174 | "config": {
175 | "background": "SystemWindow",
176 | "foreground": "black",
177 | "justify": "left",
178 | "tabs": []
179 | },
180 | "end_index": "15.0",
181 | "font": {
182 | "family": "Segoe ui",
183 | "overstrike": false,
184 | "size": 9,
185 | "slant": "roman",
186 | "underline": false,
187 | "weight": "normal"
188 | },
189 | "start_index": "14.0"
190 | },
191 | "15.0": {
192 | "bind": {
193 | "link": null
194 | },
195 | "config": {
196 | "background": "SystemWindow",
197 | "foreground": "#3333ff",
198 | "justify": "left",
199 | "tabs": [
200 | 30,
201 | "right",
202 | 35,
203 | "left"
204 | ]
205 | },
206 | "end_index": "15.3",
207 | "font": {
208 | "family": "Segoe ui",
209 | "overstrike": false,
210 | "size": 9,
211 | "slant": "roman",
212 | "underline": false,
213 | "weight": "normal"
214 | },
215 | "start_index": "15.0"
216 | },
217 | "15.26": {
218 | "bind": {
219 | "link": null
220 | },
221 | "config": {
222 | "background": "SystemWindow",
223 | "foreground": "#3333ff",
224 | "justify": "left",
225 | "tabs": [
226 | 30,
227 | "right",
228 | 35,
229 | "left"
230 | ]
231 | },
232 | "end_index": "16.0",
233 | "font": {
234 | "family": "Segoe ui",
235 | "overstrike": false,
236 | "size": 9,
237 | "slant": "roman",
238 | "underline": false,
239 | "weight": "normal"
240 | },
241 | "start_index": "15.26"
242 | },
243 | "15.3": {
244 | "bind": {
245 | "link": null
246 | },
247 | "config": {
248 | "background": "SystemWindow",
249 | "foreground": "#3333ff",
250 | "justify": "left",
251 | "tabs": [
252 | 30,
253 | "right",
254 | 35,
255 | "left"
256 | ]
257 | },
258 | "end_index": "15.26",
259 | "font": {
260 | "family": "Segoe ui",
261 | "overstrike": false,
262 | "size": 9,
263 | "slant": "roman",
264 | "underline": false,
265 | "weight": "normal"
266 | },
267 | "start_index": "15.3"
268 | },
269 | "16.0": {
270 | "bind": {
271 | "link": null
272 | },
273 | "config": {
274 | "background": "SystemWindow",
275 | "foreground": "#33aaff",
276 | "justify": "left",
277 | "tabs": [
278 | 30,
279 | "right",
280 | 35,
281 | "left"
282 | ]
283 | },
284 | "end_index": "16.3",
285 | "font": {
286 | "family": "Segoe ui",
287 | "overstrike": false,
288 | "size": 9,
289 | "slant": "roman",
290 | "underline": false,
291 | "weight": "normal"
292 | },
293 | "start_index": "16.0"
294 | },
295 | "16.26": {
296 | "bind": {
297 | "link": null
298 | },
299 | "config": {
300 | "background": "SystemWindow",
301 | "foreground": "#33aaff",
302 | "justify": "left",
303 | "tabs": [
304 | 30,
305 | "right",
306 | 35,
307 | "left"
308 | ]
309 | },
310 | "end_index": "17.0",
311 | "font": {
312 | "family": "Segoe ui",
313 | "overstrike": false,
314 | "size": 9,
315 | "slant": "roman",
316 | "underline": false,
317 | "weight": "normal"
318 | },
319 | "start_index": "16.26"
320 | },
321 | "16.3": {
322 | "bind": {
323 | "link": null
324 | },
325 | "config": {
326 | "background": "SystemWindow",
327 | "foreground": "#33aaff",
328 | "justify": "left",
329 | "tabs": [
330 | 30,
331 | "right",
332 | 35,
333 | "left"
334 | ]
335 | },
336 | "end_index": "16.26",
337 | "font": {
338 | "family": "Segoe ui",
339 | "overstrike": false,
340 | "size": 9,
341 | "slant": "roman",
342 | "underline": false,
343 | "weight": "normal"
344 | },
345 | "start_index": "16.3"
346 | },
347 | "17.0": {
348 | "bind": {
349 | "link": null
350 | },
351 | "config": {
352 | "background": "SystemWindow",
353 | "foreground": "black",
354 | "justify": "left",
355 | "tabs": []
356 | },
357 | "end_index": "end",
358 | "font": {
359 | "family": "Segoe ui",
360 | "overstrike": false,
361 | "size": 9,
362 | "slant": "roman",
363 | "underline": false,
364 | "weight": "normal"
365 | },
366 | "start_index": "17.0"
367 | },
368 | "2.0": {
369 | "bind": {
370 | "link": null
371 | },
372 | "config": {
373 | "background": "SystemWindow",
374 | "foreground": "black",
375 | "justify": "left",
376 | "tabs": []
377 | },
378 | "end_index": "3.0",
379 | "font": {
380 | "family": "Segoe ui",
381 | "overstrike": false,
382 | "size": 9,
383 | "slant": "roman",
384 | "underline": false,
385 | "weight": "normal"
386 | },
387 | "start_index": "2.0"
388 | },
389 | "3.0": {
390 | "bind": {
391 | "link": null
392 | },
393 | "config": {
394 | "background": "black",
395 | "foreground": "yellow",
396 | "justify": "left",
397 | "tabs": []
398 | },
399 | "end_index": "3.5",
400 | "font": {
401 | "family": "Segoe ui",
402 | "overstrike": false,
403 | "size": 13,
404 | "slant": "roman",
405 | "underline": false,
406 | "weight": "normal"
407 | },
408 | "start_index": "3.0"
409 | },
410 | "3.10": {
411 | "bind": {
412 | "link": null
413 | },
414 | "config": {
415 | "background": "SystemWindow",
416 | "foreground": "black",
417 | "justify": "left",
418 | "tabs": []
419 | },
420 | "end_index": "5.0",
421 | "font": {
422 | "family": "Segoe ui",
423 | "overstrike": false,
424 | "size": 9,
425 | "slant": "roman",
426 | "underline": false,
427 | "weight": "normal"
428 | },
429 | "start_index": "3.10"
430 | },
431 | "3.5": {
432 | "bind": {
433 | "link": null
434 | },
435 | "config": {
436 | "background": "black",
437 | "foreground": "yellow",
438 | "justify": "left",
439 | "tabs": []
440 | },
441 | "end_index": "3.10",
442 | "font": {
443 | "family": "Segoe ui",
444 | "overstrike": false,
445 | "size": 13,
446 | "slant": "roman",
447 | "underline": false,
448 | "weight": "normal"
449 | },
450 | "start_index": "3.5"
451 | },
452 | "5.0": {
453 | "bind": {
454 | "link": null
455 | },
456 | "config": {
457 | "background": "SystemWindow",
458 | "foreground": "black",
459 | "justify": "center",
460 | "tabs": []
461 | },
462 | "end_index": "6.0",
463 | "font": {
464 | "family": "Segoe ui",
465 | "overstrike": false,
466 | "size": 16,
467 | "slant": "roman",
468 | "underline": false,
469 | "weight": "bold"
470 | },
471 | "start_index": "5.0"
472 | },
473 | "6.0": {
474 | "bind": {
475 | "link": null
476 | },
477 | "config": {
478 | "background": "SystemWindow",
479 | "foreground": "black",
480 | "justify": "left",
481 | "tabs": []
482 | },
483 | "end_index": "7.0",
484 | "font": {
485 | "family": "Segoe ui",
486 | "overstrike": false,
487 | "size": 9,
488 | "slant": "roman",
489 | "underline": false,
490 | "weight": "normal"
491 | },
492 | "start_index": "6.0"
493 | },
494 | "7.0": {
495 | "bind": {
496 | "link": null
497 | },
498 | "config": {
499 | "background": "black",
500 | "foreground": "yellow",
501 | "justify": "left",
502 | "tabs": []
503 | },
504 | "end_index": "7.5",
505 | "font": {
506 | "family": "Segoe ui",
507 | "overstrike": false,
508 | "size": 20,
509 | "slant": "roman",
510 | "underline": false,
511 | "weight": "normal"
512 | },
513 | "start_index": "7.0"
514 | },
515 | "7.16": {
516 | "bind": {
517 | "link": null
518 | },
519 | "config": {
520 | "background": "SystemWindow",
521 | "foreground": "black",
522 | "justify": "left",
523 | "tabs": []
524 | },
525 | "end_index": "9.0",
526 | "font": {
527 | "family": "Segoe ui",
528 | "overstrike": false,
529 | "size": 9,
530 | "slant": "roman",
531 | "underline": false,
532 | "weight": "normal"
533 | },
534 | "start_index": "7.16"
535 | },
536 | "7.5": {
537 | "bind": {
538 | "link": null
539 | },
540 | "config": {
541 | "background": "black",
542 | "foreground": "yellow",
543 | "justify": "left",
544 | "tabs": []
545 | },
546 | "end_index": "7.16",
547 | "font": {
548 | "family": "Segoe ui",
549 | "overstrike": false,
550 | "size": 20,
551 | "slant": "roman",
552 | "underline": false,
553 | "weight": "normal"
554 | },
555 | "start_index": "7.5"
556 | },
557 | "9.0": {
558 | "bind": {
559 | "link": null
560 | },
561 | "config": {
562 | "background": "SystemWindow",
563 | "foreground": "black",
564 | "justify": "center",
565 | "tabs": []
566 | },
567 | "end_index": "10.0",
568 | "font": {
569 | "family": "Segoe ui",
570 | "overstrike": false,
571 | "size": 16,
572 | "slant": "roman",
573 | "underline": false,
574 | "weight": "bold"
575 | },
576 | "start_index": "9.0"
577 | }
578 | }
--------------------------------------------------------------------------------
/tests/HTMLLabel_images.json:
--------------------------------------------------------------------------------
1 | {
2 | "1.0": {
3 | "bind": {
4 | "link": null
5 | },
6 | "config": {
7 | "background": "SystemButtonFace",
8 | "foreground": "black",
9 | "justify": "center",
10 | "tabs": []
11 | },
12 | "end_index": "2.0",
13 | "font": {
14 | "family": "Segoe ui",
15 | "overstrike": false,
16 | "size": 16,
17 | "slant": "roman",
18 | "underline": false,
19 | "weight": "bold"
20 | },
21 | "start_index": "1.0"
22 | },
23 | "10.0": {
24 | "bind": {
25 | "link": null
26 | },
27 | "config": {
28 | "background": "SystemButtonFace",
29 | "foreground": "black",
30 | "justify": "left",
31 | "tabs": []
32 | },
33 | "end_index": "11.0",
34 | "font": {
35 | "family": "Segoe ui",
36 | "overstrike": false,
37 | "size": 9,
38 | "slant": "roman",
39 | "underline": false,
40 | "weight": "normal"
41 | },
42 | "start_index": "10.0"
43 | },
44 | "11.0": {
45 | "bind": {
46 | "link": "https://www.python.org"
47 | },
48 | "config": {
49 | "background": "SystemButtonFace",
50 | "foreground": "blue",
51 | "justify": "left",
52 | "tabs": []
53 | },
54 | "end_index": "11.19",
55 | "font": {
56 | "family": "Segoe ui",
57 | "overstrike": false,
58 | "size": 9,
59 | "slant": "roman",
60 | "underline": true,
61 | "weight": "normal"
62 | },
63 | "start_index": "11.0"
64 | },
65 | "11.19": {
66 | "bind": {
67 | "link": null
68 | },
69 | "config": {
70 | "background": "SystemButtonFace",
71 | "foreground": "black",
72 | "justify": "left",
73 | "tabs": []
74 | },
75 | "end_index": "12.0",
76 | "font": {
77 | "family": "Segoe ui",
78 | "overstrike": false,
79 | "size": 9,
80 | "slant": "roman",
81 | "underline": false,
82 | "weight": "normal"
83 | },
84 | "start_index": "11.19"
85 | },
86 | "12.0": {
87 | "bind": {
88 | "link": "https://www.python.org"
89 | },
90 | "config": {
91 | "background": "SystemButtonFace",
92 | "foreground": "red",
93 | "justify": "left",
94 | "tabs": []
95 | },
96 | "end_index": "12.18",
97 | "font": {
98 | "family": "Segoe ui",
99 | "overstrike": false,
100 | "size": 9,
101 | "slant": "roman",
102 | "underline": false,
103 | "weight": "normal"
104 | },
105 | "start_index": "12.0"
106 | },
107 | "12.18": {
108 | "bind": {
109 | "link": null
110 | },
111 | "config": {
112 | "background": "SystemButtonFace",
113 | "foreground": "black",
114 | "justify": "left",
115 | "tabs": []
116 | },
117 | "end_index": "13.0",
118 | "font": {
119 | "family": "Segoe ui",
120 | "overstrike": false,
121 | "size": 9,
122 | "slant": "roman",
123 | "underline": false,
124 | "weight": "normal"
125 | },
126 | "start_index": "12.18"
127 | },
128 | "13.0": {
129 | "bind": {
130 | "link": null
131 | },
132 | "config": {
133 | "background": "SystemButtonFace",
134 | "foreground": "black",
135 | "justify": "left",
136 | "tabs": []
137 | },
138 | "end_index": "13.16",
139 | "font": {
140 | "family": "Segoe ui",
141 | "overstrike": false,
142 | "size": 9,
143 | "slant": "roman",
144 | "underline": false,
145 | "weight": "normal"
146 | },
147 | "start_index": "13.0"
148 | },
149 | "13.16": {
150 | "bind": {
151 | "link": null
152 | },
153 | "config": {
154 | "background": "SystemButtonFace",
155 | "foreground": "black",
156 | "justify": "left",
157 | "tabs": []
158 | },
159 | "end_index": "14.0",
160 | "font": {
161 | "family": "Segoe ui",
162 | "overstrike": false,
163 | "size": 9,
164 | "slant": "roman",
165 | "underline": false,
166 | "weight": "normal"
167 | },
168 | "start_index": "13.16"
169 | },
170 | "14.0": {
171 | "bind": {
172 | "link": null
173 | },
174 | "config": {
175 | "background": "SystemButtonFace",
176 | "foreground": "black",
177 | "justify": "left",
178 | "tabs": []
179 | },
180 | "end_index": "15.0",
181 | "font": {
182 | "family": "Segoe ui",
183 | "overstrike": false,
184 | "size": 9,
185 | "slant": "roman",
186 | "underline": false,
187 | "weight": "normal"
188 | },
189 | "start_index": "14.0"
190 | },
191 | "15.0": {
192 | "bind": {
193 | "link": null
194 | },
195 | "config": {
196 | "background": "SystemButtonFace",
197 | "foreground": "#3333ff",
198 | "justify": "left",
199 | "tabs": [
200 | 30,
201 | "right",
202 | 35,
203 | "left"
204 | ]
205 | },
206 | "end_index": "15.3",
207 | "font": {
208 | "family": "Segoe ui",
209 | "overstrike": false,
210 | "size": 9,
211 | "slant": "roman",
212 | "underline": false,
213 | "weight": "normal"
214 | },
215 | "start_index": "15.0"
216 | },
217 | "15.26": {
218 | "bind": {
219 | "link": null
220 | },
221 | "config": {
222 | "background": "SystemButtonFace",
223 | "foreground": "#3333ff",
224 | "justify": "left",
225 | "tabs": [
226 | 30,
227 | "right",
228 | 35,
229 | "left"
230 | ]
231 | },
232 | "end_index": "16.0",
233 | "font": {
234 | "family": "Segoe ui",
235 | "overstrike": false,
236 | "size": 9,
237 | "slant": "roman",
238 | "underline": false,
239 | "weight": "normal"
240 | },
241 | "start_index": "15.26"
242 | },
243 | "15.3": {
244 | "bind": {
245 | "link": null
246 | },
247 | "config": {
248 | "background": "SystemButtonFace",
249 | "foreground": "#3333ff",
250 | "justify": "left",
251 | "tabs": [
252 | 30,
253 | "right",
254 | 35,
255 | "left"
256 | ]
257 | },
258 | "end_index": "15.26",
259 | "font": {
260 | "family": "Segoe ui",
261 | "overstrike": false,
262 | "size": 9,
263 | "slant": "roman",
264 | "underline": false,
265 | "weight": "normal"
266 | },
267 | "start_index": "15.3"
268 | },
269 | "16.0": {
270 | "bind": {
271 | "link": null
272 | },
273 | "config": {
274 | "background": "SystemButtonFace",
275 | "foreground": "#33aaff",
276 | "justify": "left",
277 | "tabs": [
278 | 30,
279 | "right",
280 | 35,
281 | "left"
282 | ]
283 | },
284 | "end_index": "16.3",
285 | "font": {
286 | "family": "Segoe ui",
287 | "overstrike": false,
288 | "size": 9,
289 | "slant": "roman",
290 | "underline": false,
291 | "weight": "normal"
292 | },
293 | "start_index": "16.0"
294 | },
295 | "16.26": {
296 | "bind": {
297 | "link": null
298 | },
299 | "config": {
300 | "background": "SystemButtonFace",
301 | "foreground": "#33aaff",
302 | "justify": "left",
303 | "tabs": [
304 | 30,
305 | "right",
306 | 35,
307 | "left"
308 | ]
309 | },
310 | "end_index": "17.0",
311 | "font": {
312 | "family": "Segoe ui",
313 | "overstrike": false,
314 | "size": 9,
315 | "slant": "roman",
316 | "underline": false,
317 | "weight": "normal"
318 | },
319 | "start_index": "16.26"
320 | },
321 | "16.3": {
322 | "bind": {
323 | "link": null
324 | },
325 | "config": {
326 | "background": "SystemButtonFace",
327 | "foreground": "#33aaff",
328 | "justify": "left",
329 | "tabs": [
330 | 30,
331 | "right",
332 | 35,
333 | "left"
334 | ]
335 | },
336 | "end_index": "16.26",
337 | "font": {
338 | "family": "Segoe ui",
339 | "overstrike": false,
340 | "size": 9,
341 | "slant": "roman",
342 | "underline": false,
343 | "weight": "normal"
344 | },
345 | "start_index": "16.3"
346 | },
347 | "17.0": {
348 | "bind": {
349 | "link": null
350 | },
351 | "config": {
352 | "background": "SystemButtonFace",
353 | "foreground": "black",
354 | "justify": "left",
355 | "tabs": []
356 | },
357 | "end_index": "end",
358 | "font": {
359 | "family": "Segoe ui",
360 | "overstrike": false,
361 | "size": 9,
362 | "slant": "roman",
363 | "underline": false,
364 | "weight": "normal"
365 | },
366 | "start_index": "17.0"
367 | },
368 | "2.0": {
369 | "bind": {
370 | "link": null
371 | },
372 | "config": {
373 | "background": "SystemButtonFace",
374 | "foreground": "black",
375 | "justify": "left",
376 | "tabs": []
377 | },
378 | "end_index": "3.0",
379 | "font": {
380 | "family": "Segoe ui",
381 | "overstrike": false,
382 | "size": 9,
383 | "slant": "roman",
384 | "underline": false,
385 | "weight": "normal"
386 | },
387 | "start_index": "2.0"
388 | },
389 | "3.0": {
390 | "bind": {
391 | "link": null
392 | },
393 | "config": {
394 | "background": "black",
395 | "foreground": "yellow",
396 | "justify": "left",
397 | "tabs": []
398 | },
399 | "end_index": "3.5",
400 | "font": {
401 | "family": "Segoe ui",
402 | "overstrike": false,
403 | "size": 13,
404 | "slant": "roman",
405 | "underline": false,
406 | "weight": "normal"
407 | },
408 | "start_index": "3.0"
409 | },
410 | "3.10": {
411 | "bind": {
412 | "link": null
413 | },
414 | "config": {
415 | "background": "SystemButtonFace",
416 | "foreground": "black",
417 | "justify": "left",
418 | "tabs": []
419 | },
420 | "end_index": "5.0",
421 | "font": {
422 | "family": "Segoe ui",
423 | "overstrike": false,
424 | "size": 9,
425 | "slant": "roman",
426 | "underline": false,
427 | "weight": "normal"
428 | },
429 | "start_index": "3.10"
430 | },
431 | "3.5": {
432 | "bind": {
433 | "link": null
434 | },
435 | "config": {
436 | "background": "black",
437 | "foreground": "yellow",
438 | "justify": "left",
439 | "tabs": []
440 | },
441 | "end_index": "3.10",
442 | "font": {
443 | "family": "Segoe ui",
444 | "overstrike": false,
445 | "size": 13,
446 | "slant": "roman",
447 | "underline": false,
448 | "weight": "normal"
449 | },
450 | "start_index": "3.5"
451 | },
452 | "5.0": {
453 | "bind": {
454 | "link": null
455 | },
456 | "config": {
457 | "background": "SystemButtonFace",
458 | "foreground": "black",
459 | "justify": "center",
460 | "tabs": []
461 | },
462 | "end_index": "6.0",
463 | "font": {
464 | "family": "Segoe ui",
465 | "overstrike": false,
466 | "size": 16,
467 | "slant": "roman",
468 | "underline": false,
469 | "weight": "bold"
470 | },
471 | "start_index": "5.0"
472 | },
473 | "6.0": {
474 | "bind": {
475 | "link": null
476 | },
477 | "config": {
478 | "background": "SystemButtonFace",
479 | "foreground": "black",
480 | "justify": "left",
481 | "tabs": []
482 | },
483 | "end_index": "7.0",
484 | "font": {
485 | "family": "Segoe ui",
486 | "overstrike": false,
487 | "size": 9,
488 | "slant": "roman",
489 | "underline": false,
490 | "weight": "normal"
491 | },
492 | "start_index": "6.0"
493 | },
494 | "7.0": {
495 | "bind": {
496 | "link": null
497 | },
498 | "config": {
499 | "background": "black",
500 | "foreground": "yellow",
501 | "justify": "left",
502 | "tabs": []
503 | },
504 | "end_index": "7.5",
505 | "font": {
506 | "family": "Segoe ui",
507 | "overstrike": false,
508 | "size": 20,
509 | "slant": "roman",
510 | "underline": false,
511 | "weight": "normal"
512 | },
513 | "start_index": "7.0"
514 | },
515 | "7.16": {
516 | "bind": {
517 | "link": null
518 | },
519 | "config": {
520 | "background": "SystemButtonFace",
521 | "foreground": "black",
522 | "justify": "left",
523 | "tabs": []
524 | },
525 | "end_index": "9.0",
526 | "font": {
527 | "family": "Segoe ui",
528 | "overstrike": false,
529 | "size": 9,
530 | "slant": "roman",
531 | "underline": false,
532 | "weight": "normal"
533 | },
534 | "start_index": "7.16"
535 | },
536 | "7.5": {
537 | "bind": {
538 | "link": null
539 | },
540 | "config": {
541 | "background": "black",
542 | "foreground": "yellow",
543 | "justify": "left",
544 | "tabs": []
545 | },
546 | "end_index": "7.16",
547 | "font": {
548 | "family": "Segoe ui",
549 | "overstrike": false,
550 | "size": 20,
551 | "slant": "roman",
552 | "underline": false,
553 | "weight": "normal"
554 | },
555 | "start_index": "7.5"
556 | },
557 | "9.0": {
558 | "bind": {
559 | "link": null
560 | },
561 | "config": {
562 | "background": "SystemButtonFace",
563 | "foreground": "black",
564 | "justify": "center",
565 | "tabs": []
566 | },
567 | "end_index": "10.0",
568 | "font": {
569 | "family": "Segoe ui",
570 | "overstrike": false,
571 | "size": 16,
572 | "slant": "roman",
573 | "underline": false,
574 | "weight": "bold"
575 | },
576 | "start_index": "9.0"
577 | }
578 | }
--------------------------------------------------------------------------------
/tests/HTMLText_styles.json:
--------------------------------------------------------------------------------
1 | {
2 | "1.0": {
3 | "bind": {
4 | "link": null
5 | },
6 | "config": {
7 | "background": "blue",
8 | "foreground": "yellow",
9 | "justify": "left",
10 | "tabs": []
11 | },
12 | "end_index": "1.8",
13 | "font": {
14 | "family": "impact",
15 | "overstrike": false,
16 | "size": 13,
17 | "slant": "roman",
18 | "underline": true,
19 | "weight": "normal"
20 | },
21 | "start_index": "1.0"
22 | },
23 | "1.16": {
24 | "bind": {
25 | "link": null
26 | },
27 | "config": {
28 | "background": "blue",
29 | "foreground": "yellow",
30 | "justify": "left",
31 | "tabs": []
32 | },
33 | "end_index": "1.29",
34 | "font": {
35 | "family": "impact",
36 | "overstrike": false,
37 | "size": 13,
38 | "slant": "roman",
39 | "underline": false,
40 | "weight": "bold"
41 | },
42 | "start_index": "1.16"
43 | },
44 | "1.29": {
45 | "bind": {
46 | "link": null
47 | },
48 | "config": {
49 | "background": "blue",
50 | "foreground": "yellow",
51 | "justify": "left",
52 | "tabs": []
53 | },
54 | "end_index": "1.37",
55 | "font": {
56 | "family": "impact",
57 | "overstrike": false,
58 | "size": 13,
59 | "slant": "italic",
60 | "underline": true,
61 | "weight": "normal"
62 | },
63 | "start_index": "1.29"
64 | },
65 | "1.37": {
66 | "bind": {
67 | "link": null
68 | },
69 | "config": {
70 | "background": "blue",
71 | "foreground": "yellow",
72 | "justify": "left",
73 | "tabs": []
74 | },
75 | "end_index": "1.46",
76 | "font": {
77 | "family": "impact",
78 | "overstrike": false,
79 | "size": 13,
80 | "slant": "italic",
81 | "underline": true,
82 | "weight": "normal"
83 | },
84 | "start_index": "1.37"
85 | },
86 | "1.46": {
87 | "bind": {
88 | "link": null
89 | },
90 | "config": {
91 | "background": "blue",
92 | "foreground": "yellow",
93 | "justify": "left",
94 | "tabs": []
95 | },
96 | "end_index": "1.54",
97 | "font": {
98 | "family": "impact",
99 | "overstrike": false,
100 | "size": 13,
101 | "slant": "roman",
102 | "underline": true,
103 | "weight": "normal"
104 | },
105 | "start_index": "1.46"
106 | },
107 | "1.54": {
108 | "bind": {
109 | "link": null
110 | },
111 | "config": {
112 | "background": "blue",
113 | "foreground": "yellow",
114 | "justify": "left",
115 | "tabs": []
116 | },
117 | "end_index": "1.65",
118 | "font": {
119 | "family": "impact",
120 | "overstrike": false,
121 | "size": 13,
122 | "slant": "roman",
123 | "underline": true,
124 | "weight": "normal"
125 | },
126 | "start_index": "1.54"
127 | },
128 | "1.65": {
129 | "bind": {
130 | "link": null
131 | },
132 | "config": {
133 | "background": "blue",
134 | "foreground": "yellow",
135 | "justify": "left",
136 | "tabs": []
137 | },
138 | "end_index": "1.76",
139 | "font": {
140 | "family": "impact",
141 | "overstrike": false,
142 | "size": 13,
143 | "slant": "roman",
144 | "underline": true,
145 | "weight": "normal"
146 | },
147 | "start_index": "1.65"
148 | },
149 | "1.76": {
150 | "bind": {
151 | "link": null
152 | },
153 | "config": {
154 | "background": "SystemWindow",
155 | "foreground": "black",
156 | "justify": "left",
157 | "tabs": []
158 | },
159 | "end_index": "2.0",
160 | "font": {
161 | "family": "Segoe ui",
162 | "overstrike": false,
163 | "size": 9,
164 | "slant": "roman",
165 | "underline": false,
166 | "weight": "normal"
167 | },
168 | "start_index": "1.76"
169 | },
170 | "1.8": {
171 | "bind": {
172 | "link": null
173 | },
174 | "config": {
175 | "background": "blue",
176 | "foreground": "yellow",
177 | "justify": "left",
178 | "tabs": []
179 | },
180 | "end_index": "1.16",
181 | "font": {
182 | "family": "impact",
183 | "overstrike": false,
184 | "size": 13,
185 | "slant": "roman",
186 | "underline": true,
187 | "weight": "bold"
188 | },
189 | "start_index": "1.8"
190 | },
191 | "10.0": {
192 | "bind": {
193 | "link": null
194 | },
195 | "config": {
196 | "background": "blue",
197 | "foreground": "yellow",
198 | "justify": "center",
199 | "tabs": []
200 | },
201 | "end_index": "11.0",
202 | "font": {
203 | "family": "impact",
204 | "overstrike": false,
205 | "size": 13,
206 | "slant": "roman",
207 | "underline": true,
208 | "weight": "bold"
209 | },
210 | "start_index": "10.0"
211 | },
212 | "11.0": {
213 | "bind": {
214 | "link": null
215 | },
216 | "config": {
217 | "background": "SystemWindow",
218 | "foreground": "black",
219 | "justify": "left",
220 | "tabs": []
221 | },
222 | "end_index": "12.0",
223 | "font": {
224 | "family": "Segoe ui",
225 | "overstrike": false,
226 | "size": 9,
227 | "slant": "roman",
228 | "underline": false,
229 | "weight": "normal"
230 | },
231 | "start_index": "11.0"
232 | },
233 | "12.0": {
234 | "bind": {
235 | "link": null
236 | },
237 | "config": {
238 | "background": "blue",
239 | "foreground": "yellow",
240 | "justify": "center",
241 | "tabs": []
242 | },
243 | "end_index": "13.0",
244 | "font": {
245 | "family": "impact",
246 | "overstrike": false,
247 | "size": 13,
248 | "slant": "roman",
249 | "underline": true,
250 | "weight": "bold"
251 | },
252 | "start_index": "12.0"
253 | },
254 | "13.0": {
255 | "bind": {
256 | "link": null
257 | },
258 | "config": {
259 | "background": "SystemWindow",
260 | "foreground": "black",
261 | "justify": "left",
262 | "tabs": []
263 | },
264 | "end_index": "14.0",
265 | "font": {
266 | "family": "Segoe ui",
267 | "overstrike": false,
268 | "size": 9,
269 | "slant": "roman",
270 | "underline": false,
271 | "weight": "normal"
272 | },
273 | "start_index": "13.0"
274 | },
275 | "14.0": {
276 | "bind": {
277 | "link": null
278 | },
279 | "config": {
280 | "background": "blue",
281 | "foreground": "yellow",
282 | "justify": "center",
283 | "tabs": []
284 | },
285 | "end_index": "15.0",
286 | "font": {
287 | "family": "impact",
288 | "overstrike": false,
289 | "size": 13,
290 | "slant": "roman",
291 | "underline": true,
292 | "weight": "bold"
293 | },
294 | "start_index": "14.0"
295 | },
296 | "15.0": {
297 | "bind": {
298 | "link": null
299 | },
300 | "config": {
301 | "background": "SystemWindow",
302 | "foreground": "black",
303 | "justify": "left",
304 | "tabs": []
305 | },
306 | "end_index": "16.0",
307 | "font": {
308 | "family": "Segoe ui",
309 | "overstrike": false,
310 | "size": 9,
311 | "slant": "roman",
312 | "underline": false,
313 | "weight": "normal"
314 | },
315 | "start_index": "15.0"
316 | },
317 | "16.0": {
318 | "bind": {
319 | "link": null
320 | },
321 | "config": {
322 | "background": "blue",
323 | "foreground": "yellow",
324 | "justify": "center",
325 | "tabs": []
326 | },
327 | "end_index": "17.0",
328 | "font": {
329 | "family": "impact",
330 | "overstrike": false,
331 | "size": 13,
332 | "slant": "roman",
333 | "underline": true,
334 | "weight": "bold"
335 | },
336 | "start_index": "16.0"
337 | },
338 | "17.0": {
339 | "bind": {
340 | "link": null
341 | },
342 | "config": {
343 | "background": "SystemWindow",
344 | "foreground": "black",
345 | "justify": "left",
346 | "tabs": []
347 | },
348 | "end_index": "18.0",
349 | "font": {
350 | "family": "Segoe ui",
351 | "overstrike": false,
352 | "size": 9,
353 | "slant": "roman",
354 | "underline": false,
355 | "weight": "normal"
356 | },
357 | "start_index": "17.0"
358 | },
359 | "18.0": {
360 | "bind": {
361 | "link": null
362 | },
363 | "config": {
364 | "background": "blue",
365 | "foreground": "yellow",
366 | "justify": "center",
367 | "tabs": []
368 | },
369 | "end_index": "19.0",
370 | "font": {
371 | "family": "impact",
372 | "overstrike": false,
373 | "size": 13,
374 | "slant": "roman",
375 | "underline": true,
376 | "weight": "bold"
377 | },
378 | "start_index": "18.0"
379 | },
380 | "19.0": {
381 | "bind": {
382 | "link": null
383 | },
384 | "config": {
385 | "background": "SystemWindow",
386 | "foreground": "black",
387 | "justify": "left",
388 | "tabs": []
389 | },
390 | "end_index": "20.0",
391 | "font": {
392 | "family": "Segoe ui",
393 | "overstrike": false,
394 | "size": 9,
395 | "slant": "roman",
396 | "underline": false,
397 | "weight": "normal"
398 | },
399 | "start_index": "19.0"
400 | },
401 | "2.0": {
402 | "bind": {
403 | "link": null
404 | },
405 | "config": {
406 | "background": "blue",
407 | "foreground": "yellow",
408 | "justify": "center",
409 | "tabs": []
410 | },
411 | "end_index": "3.0",
412 | "font": {
413 | "family": "impact",
414 | "overstrike": false,
415 | "size": 13,
416 | "slant": "roman",
417 | "underline": true,
418 | "weight": "normal"
419 | },
420 | "start_index": "2.0"
421 | },
422 | "20.0": {
423 | "bind": {
424 | "link": null
425 | },
426 | "config": {
427 | "background": "red",
428 | "foreground": "black",
429 | "justify": "left",
430 | "tabs": []
431 | },
432 | "end_index": "20.4",
433 | "font": {
434 | "family": "Segoe ui",
435 | "overstrike": false,
436 | "size": 9,
437 | "slant": "roman",
438 | "underline": false,
439 | "weight": "normal"
440 | },
441 | "start_index": "20.0"
442 | },
443 | "20.10": {
444 | "bind": {
445 | "link": null
446 | },
447 | "config": {
448 | "background": "yellow",
449 | "foreground": "black",
450 | "justify": "left",
451 | "tabs": []
452 | },
453 | "end_index": "20.17",
454 | "font": {
455 | "family": "Segoe ui",
456 | "overstrike": false,
457 | "size": 9,
458 | "slant": "roman",
459 | "underline": false,
460 | "weight": "normal"
461 | },
462 | "start_index": "20.10"
463 | },
464 | "20.17": {
465 | "bind": {
466 | "link": null
467 | },
468 | "config": {
469 | "background": "red",
470 | "foreground": "black",
471 | "justify": "left",
472 | "tabs": []
473 | },
474 | "end_index": "20.27",
475 | "font": {
476 | "family": "Segoe ui",
477 | "overstrike": false,
478 | "size": 9,
479 | "slant": "roman",
480 | "underline": false,
481 | "weight": "normal"
482 | },
483 | "start_index": "20.17"
484 | },
485 | "20.27": {
486 | "bind": {
487 | "link": null
488 | },
489 | "config": {
490 | "background": "SystemWindow",
491 | "foreground": "black",
492 | "justify": "left",
493 | "tabs": []
494 | },
495 | "end_index": "end",
496 | "font": {
497 | "family": "Segoe ui",
498 | "overstrike": false,
499 | "size": 9,
500 | "slant": "roman",
501 | "underline": false,
502 | "weight": "normal"
503 | },
504 | "start_index": "20.27"
505 | },
506 | "20.4": {
507 | "bind": {
508 | "link": null
509 | },
510 | "config": {
511 | "background": "green",
512 | "foreground": "black",
513 | "justify": "left",
514 | "tabs": []
515 | },
516 | "end_index": "20.10",
517 | "font": {
518 | "family": "Segoe ui",
519 | "overstrike": false,
520 | "size": 9,
521 | "slant": "roman",
522 | "underline": false,
523 | "weight": "normal"
524 | },
525 | "start_index": "20.4"
526 | },
527 | "3.0": {
528 | "bind": {
529 | "link": null
530 | },
531 | "config": {
532 | "background": "SystemWindow",
533 | "foreground": "black",
534 | "justify": "left",
535 | "tabs": []
536 | },
537 | "end_index": "4.0",
538 | "font": {
539 | "family": "Segoe ui",
540 | "overstrike": false,
541 | "size": 9,
542 | "slant": "roman",
543 | "underline": false,
544 | "weight": "normal"
545 | },
546 | "start_index": "3.0"
547 | },
548 | "4.0": {
549 | "bind": {
550 | "link": null
551 | },
552 | "config": {
553 | "background": "blue",
554 | "foreground": "yellow",
555 | "justify": "center",
556 | "tabs": []
557 | },
558 | "end_index": "5.0",
559 | "font": {
560 | "family": "impact",
561 | "overstrike": false,
562 | "size": 13,
563 | "slant": "roman",
564 | "underline": true,
565 | "weight": "normal"
566 | },
567 | "start_index": "4.0"
568 | },
569 | "5.0": {
570 | "bind": {
571 | "link": null
572 | },
573 | "config": {
574 | "background": "SystemWindow",
575 | "foreground": "black",
576 | "justify": "left",
577 | "tabs": []
578 | },
579 | "end_index": "6.0",
580 | "font": {
581 | "family": "Segoe ui",
582 | "overstrike": false,
583 | "size": 9,
584 | "slant": "roman",
585 | "underline": false,
586 | "weight": "normal"
587 | },
588 | "start_index": "5.0"
589 | },
590 | "6.0": {
591 | "bind": {
592 | "link": null
593 | },
594 | "config": {
595 | "background": "blue",
596 | "foreground": "yellow",
597 | "justify": "center",
598 | "tabs": []
599 | },
600 | "end_index": "7.0",
601 | "font": {
602 | "family": "impact",
603 | "overstrike": false,
604 | "size": 13,
605 | "slant": "roman",
606 | "underline": true,
607 | "weight": "normal"
608 | },
609 | "start_index": "6.0"
610 | },
611 | "7.0": {
612 | "bind": {
613 | "link": null
614 | },
615 | "config": {
616 | "background": "SystemWindow",
617 | "foreground": "black",
618 | "justify": "left",
619 | "tabs": []
620 | },
621 | "end_index": "8.0",
622 | "font": {
623 | "family": "Segoe ui",
624 | "overstrike": false,
625 | "size": 9,
626 | "slant": "roman",
627 | "underline": false,
628 | "weight": "normal"
629 | },
630 | "start_index": "7.0"
631 | },
632 | "8.0": {
633 | "bind": {
634 | "link": null
635 | },
636 | "config": {
637 | "background": "blue",
638 | "foreground": "yellow",
639 | "justify": "center",
640 | "tabs": []
641 | },
642 | "end_index": "9.0",
643 | "font": {
644 | "family": "impact",
645 | "overstrike": false,
646 | "size": 13,
647 | "slant": "roman",
648 | "underline": true,
649 | "weight": "bold"
650 | },
651 | "start_index": "8.0"
652 | },
653 | "9.0": {
654 | "bind": {
655 | "link": null
656 | },
657 | "config": {
658 | "background": "SystemWindow",
659 | "foreground": "black",
660 | "justify": "left",
661 | "tabs": []
662 | },
663 | "end_index": "10.0",
664 | "font": {
665 | "family": "Segoe ui",
666 | "overstrike": false,
667 | "size": 9,
668 | "slant": "roman",
669 | "underline": false,
670 | "weight": "normal"
671 | },
672 | "start_index": "9.0"
673 | }
674 | }
--------------------------------------------------------------------------------
/tests/HTMLScrolledText_styles.json:
--------------------------------------------------------------------------------
1 | {
2 | "1.0": {
3 | "bind": {
4 | "link": null
5 | },
6 | "config": {
7 | "background": "blue",
8 | "foreground": "yellow",
9 | "justify": "left",
10 | "tabs": []
11 | },
12 | "end_index": "1.8",
13 | "font": {
14 | "family": "impact",
15 | "overstrike": false,
16 | "size": 13,
17 | "slant": "roman",
18 | "underline": true,
19 | "weight": "normal"
20 | },
21 | "start_index": "1.0"
22 | },
23 | "1.16": {
24 | "bind": {
25 | "link": null
26 | },
27 | "config": {
28 | "background": "blue",
29 | "foreground": "yellow",
30 | "justify": "left",
31 | "tabs": []
32 | },
33 | "end_index": "1.29",
34 | "font": {
35 | "family": "impact",
36 | "overstrike": false,
37 | "size": 13,
38 | "slant": "roman",
39 | "underline": false,
40 | "weight": "bold"
41 | },
42 | "start_index": "1.16"
43 | },
44 | "1.29": {
45 | "bind": {
46 | "link": null
47 | },
48 | "config": {
49 | "background": "blue",
50 | "foreground": "yellow",
51 | "justify": "left",
52 | "tabs": []
53 | },
54 | "end_index": "1.37",
55 | "font": {
56 | "family": "impact",
57 | "overstrike": false,
58 | "size": 13,
59 | "slant": "italic",
60 | "underline": true,
61 | "weight": "normal"
62 | },
63 | "start_index": "1.29"
64 | },
65 | "1.37": {
66 | "bind": {
67 | "link": null
68 | },
69 | "config": {
70 | "background": "blue",
71 | "foreground": "yellow",
72 | "justify": "left",
73 | "tabs": []
74 | },
75 | "end_index": "1.46",
76 | "font": {
77 | "family": "impact",
78 | "overstrike": false,
79 | "size": 13,
80 | "slant": "italic",
81 | "underline": true,
82 | "weight": "normal"
83 | },
84 | "start_index": "1.37"
85 | },
86 | "1.46": {
87 | "bind": {
88 | "link": null
89 | },
90 | "config": {
91 | "background": "blue",
92 | "foreground": "yellow",
93 | "justify": "left",
94 | "tabs": []
95 | },
96 | "end_index": "1.54",
97 | "font": {
98 | "family": "impact",
99 | "overstrike": false,
100 | "size": 13,
101 | "slant": "roman",
102 | "underline": true,
103 | "weight": "normal"
104 | },
105 | "start_index": "1.46"
106 | },
107 | "1.54": {
108 | "bind": {
109 | "link": null
110 | },
111 | "config": {
112 | "background": "blue",
113 | "foreground": "yellow",
114 | "justify": "left",
115 | "tabs": []
116 | },
117 | "end_index": "1.65",
118 | "font": {
119 | "family": "impact",
120 | "overstrike": false,
121 | "size": 13,
122 | "slant": "roman",
123 | "underline": true,
124 | "weight": "normal"
125 | },
126 | "start_index": "1.54"
127 | },
128 | "1.65": {
129 | "bind": {
130 | "link": null
131 | },
132 | "config": {
133 | "background": "blue",
134 | "foreground": "yellow",
135 | "justify": "left",
136 | "tabs": []
137 | },
138 | "end_index": "1.76",
139 | "font": {
140 | "family": "impact",
141 | "overstrike": false,
142 | "size": 13,
143 | "slant": "roman",
144 | "underline": true,
145 | "weight": "normal"
146 | },
147 | "start_index": "1.65"
148 | },
149 | "1.76": {
150 | "bind": {
151 | "link": null
152 | },
153 | "config": {
154 | "background": "SystemWindow",
155 | "foreground": "black",
156 | "justify": "left",
157 | "tabs": []
158 | },
159 | "end_index": "2.0",
160 | "font": {
161 | "family": "Segoe ui",
162 | "overstrike": false,
163 | "size": 9,
164 | "slant": "roman",
165 | "underline": false,
166 | "weight": "normal"
167 | },
168 | "start_index": "1.76"
169 | },
170 | "1.8": {
171 | "bind": {
172 | "link": null
173 | },
174 | "config": {
175 | "background": "blue",
176 | "foreground": "yellow",
177 | "justify": "left",
178 | "tabs": []
179 | },
180 | "end_index": "1.16",
181 | "font": {
182 | "family": "impact",
183 | "overstrike": false,
184 | "size": 13,
185 | "slant": "roman",
186 | "underline": true,
187 | "weight": "bold"
188 | },
189 | "start_index": "1.8"
190 | },
191 | "10.0": {
192 | "bind": {
193 | "link": null
194 | },
195 | "config": {
196 | "background": "blue",
197 | "foreground": "yellow",
198 | "justify": "center",
199 | "tabs": []
200 | },
201 | "end_index": "11.0",
202 | "font": {
203 | "family": "impact",
204 | "overstrike": false,
205 | "size": 13,
206 | "slant": "roman",
207 | "underline": true,
208 | "weight": "bold"
209 | },
210 | "start_index": "10.0"
211 | },
212 | "11.0": {
213 | "bind": {
214 | "link": null
215 | },
216 | "config": {
217 | "background": "SystemWindow",
218 | "foreground": "black",
219 | "justify": "left",
220 | "tabs": []
221 | },
222 | "end_index": "12.0",
223 | "font": {
224 | "family": "Segoe ui",
225 | "overstrike": false,
226 | "size": 9,
227 | "slant": "roman",
228 | "underline": false,
229 | "weight": "normal"
230 | },
231 | "start_index": "11.0"
232 | },
233 | "12.0": {
234 | "bind": {
235 | "link": null
236 | },
237 | "config": {
238 | "background": "blue",
239 | "foreground": "yellow",
240 | "justify": "center",
241 | "tabs": []
242 | },
243 | "end_index": "13.0",
244 | "font": {
245 | "family": "impact",
246 | "overstrike": false,
247 | "size": 13,
248 | "slant": "roman",
249 | "underline": true,
250 | "weight": "bold"
251 | },
252 | "start_index": "12.0"
253 | },
254 | "13.0": {
255 | "bind": {
256 | "link": null
257 | },
258 | "config": {
259 | "background": "SystemWindow",
260 | "foreground": "black",
261 | "justify": "left",
262 | "tabs": []
263 | },
264 | "end_index": "14.0",
265 | "font": {
266 | "family": "Segoe ui",
267 | "overstrike": false,
268 | "size": 9,
269 | "slant": "roman",
270 | "underline": false,
271 | "weight": "normal"
272 | },
273 | "start_index": "13.0"
274 | },
275 | "14.0": {
276 | "bind": {
277 | "link": null
278 | },
279 | "config": {
280 | "background": "blue",
281 | "foreground": "yellow",
282 | "justify": "center",
283 | "tabs": []
284 | },
285 | "end_index": "15.0",
286 | "font": {
287 | "family": "impact",
288 | "overstrike": false,
289 | "size": 13,
290 | "slant": "roman",
291 | "underline": true,
292 | "weight": "bold"
293 | },
294 | "start_index": "14.0"
295 | },
296 | "15.0": {
297 | "bind": {
298 | "link": null
299 | },
300 | "config": {
301 | "background": "SystemWindow",
302 | "foreground": "black",
303 | "justify": "left",
304 | "tabs": []
305 | },
306 | "end_index": "16.0",
307 | "font": {
308 | "family": "Segoe ui",
309 | "overstrike": false,
310 | "size": 9,
311 | "slant": "roman",
312 | "underline": false,
313 | "weight": "normal"
314 | },
315 | "start_index": "15.0"
316 | },
317 | "16.0": {
318 | "bind": {
319 | "link": null
320 | },
321 | "config": {
322 | "background": "blue",
323 | "foreground": "yellow",
324 | "justify": "center",
325 | "tabs": []
326 | },
327 | "end_index": "17.0",
328 | "font": {
329 | "family": "impact",
330 | "overstrike": false,
331 | "size": 13,
332 | "slant": "roman",
333 | "underline": true,
334 | "weight": "bold"
335 | },
336 | "start_index": "16.0"
337 | },
338 | "17.0": {
339 | "bind": {
340 | "link": null
341 | },
342 | "config": {
343 | "background": "SystemWindow",
344 | "foreground": "black",
345 | "justify": "left",
346 | "tabs": []
347 | },
348 | "end_index": "18.0",
349 | "font": {
350 | "family": "Segoe ui",
351 | "overstrike": false,
352 | "size": 9,
353 | "slant": "roman",
354 | "underline": false,
355 | "weight": "normal"
356 | },
357 | "start_index": "17.0"
358 | },
359 | "18.0": {
360 | "bind": {
361 | "link": null
362 | },
363 | "config": {
364 | "background": "blue",
365 | "foreground": "yellow",
366 | "justify": "center",
367 | "tabs": []
368 | },
369 | "end_index": "19.0",
370 | "font": {
371 | "family": "impact",
372 | "overstrike": false,
373 | "size": 13,
374 | "slant": "roman",
375 | "underline": true,
376 | "weight": "bold"
377 | },
378 | "start_index": "18.0"
379 | },
380 | "19.0": {
381 | "bind": {
382 | "link": null
383 | },
384 | "config": {
385 | "background": "SystemWindow",
386 | "foreground": "black",
387 | "justify": "left",
388 | "tabs": []
389 | },
390 | "end_index": "20.0",
391 | "font": {
392 | "family": "Segoe ui",
393 | "overstrike": false,
394 | "size": 9,
395 | "slant": "roman",
396 | "underline": false,
397 | "weight": "normal"
398 | },
399 | "start_index": "19.0"
400 | },
401 | "2.0": {
402 | "bind": {
403 | "link": null
404 | },
405 | "config": {
406 | "background": "blue",
407 | "foreground": "yellow",
408 | "justify": "center",
409 | "tabs": []
410 | },
411 | "end_index": "3.0",
412 | "font": {
413 | "family": "impact",
414 | "overstrike": false,
415 | "size": 13,
416 | "slant": "roman",
417 | "underline": true,
418 | "weight": "normal"
419 | },
420 | "start_index": "2.0"
421 | },
422 | "20.0": {
423 | "bind": {
424 | "link": null
425 | },
426 | "config": {
427 | "background": "red",
428 | "foreground": "black",
429 | "justify": "left",
430 | "tabs": []
431 | },
432 | "end_index": "20.4",
433 | "font": {
434 | "family": "Segoe ui",
435 | "overstrike": false,
436 | "size": 9,
437 | "slant": "roman",
438 | "underline": false,
439 | "weight": "normal"
440 | },
441 | "start_index": "20.0"
442 | },
443 | "20.10": {
444 | "bind": {
445 | "link": null
446 | },
447 | "config": {
448 | "background": "yellow",
449 | "foreground": "black",
450 | "justify": "left",
451 | "tabs": []
452 | },
453 | "end_index": "20.17",
454 | "font": {
455 | "family": "Segoe ui",
456 | "overstrike": false,
457 | "size": 9,
458 | "slant": "roman",
459 | "underline": false,
460 | "weight": "normal"
461 | },
462 | "start_index": "20.10"
463 | },
464 | "20.17": {
465 | "bind": {
466 | "link": null
467 | },
468 | "config": {
469 | "background": "red",
470 | "foreground": "black",
471 | "justify": "left",
472 | "tabs": []
473 | },
474 | "end_index": "20.27",
475 | "font": {
476 | "family": "Segoe ui",
477 | "overstrike": false,
478 | "size": 9,
479 | "slant": "roman",
480 | "underline": false,
481 | "weight": "normal"
482 | },
483 | "start_index": "20.17"
484 | },
485 | "20.27": {
486 | "bind": {
487 | "link": null
488 | },
489 | "config": {
490 | "background": "SystemWindow",
491 | "foreground": "black",
492 | "justify": "left",
493 | "tabs": []
494 | },
495 | "end_index": "end",
496 | "font": {
497 | "family": "Segoe ui",
498 | "overstrike": false,
499 | "size": 9,
500 | "slant": "roman",
501 | "underline": false,
502 | "weight": "normal"
503 | },
504 | "start_index": "20.27"
505 | },
506 | "20.4": {
507 | "bind": {
508 | "link": null
509 | },
510 | "config": {
511 | "background": "green",
512 | "foreground": "black",
513 | "justify": "left",
514 | "tabs": []
515 | },
516 | "end_index": "20.10",
517 | "font": {
518 | "family": "Segoe ui",
519 | "overstrike": false,
520 | "size": 9,
521 | "slant": "roman",
522 | "underline": false,
523 | "weight": "normal"
524 | },
525 | "start_index": "20.4"
526 | },
527 | "3.0": {
528 | "bind": {
529 | "link": null
530 | },
531 | "config": {
532 | "background": "SystemWindow",
533 | "foreground": "black",
534 | "justify": "left",
535 | "tabs": []
536 | },
537 | "end_index": "4.0",
538 | "font": {
539 | "family": "Segoe ui",
540 | "overstrike": false,
541 | "size": 9,
542 | "slant": "roman",
543 | "underline": false,
544 | "weight": "normal"
545 | },
546 | "start_index": "3.0"
547 | },
548 | "4.0": {
549 | "bind": {
550 | "link": null
551 | },
552 | "config": {
553 | "background": "blue",
554 | "foreground": "yellow",
555 | "justify": "center",
556 | "tabs": []
557 | },
558 | "end_index": "5.0",
559 | "font": {
560 | "family": "impact",
561 | "overstrike": false,
562 | "size": 13,
563 | "slant": "roman",
564 | "underline": true,
565 | "weight": "normal"
566 | },
567 | "start_index": "4.0"
568 | },
569 | "5.0": {
570 | "bind": {
571 | "link": null
572 | },
573 | "config": {
574 | "background": "SystemWindow",
575 | "foreground": "black",
576 | "justify": "left",
577 | "tabs": []
578 | },
579 | "end_index": "6.0",
580 | "font": {
581 | "family": "Segoe ui",
582 | "overstrike": false,
583 | "size": 9,
584 | "slant": "roman",
585 | "underline": false,
586 | "weight": "normal"
587 | },
588 | "start_index": "5.0"
589 | },
590 | "6.0": {
591 | "bind": {
592 | "link": null
593 | },
594 | "config": {
595 | "background": "blue",
596 | "foreground": "yellow",
597 | "justify": "center",
598 | "tabs": []
599 | },
600 | "end_index": "7.0",
601 | "font": {
602 | "family": "impact",
603 | "overstrike": false,
604 | "size": 13,
605 | "slant": "roman",
606 | "underline": true,
607 | "weight": "normal"
608 | },
609 | "start_index": "6.0"
610 | },
611 | "7.0": {
612 | "bind": {
613 | "link": null
614 | },
615 | "config": {
616 | "background": "SystemWindow",
617 | "foreground": "black",
618 | "justify": "left",
619 | "tabs": []
620 | },
621 | "end_index": "8.0",
622 | "font": {
623 | "family": "Segoe ui",
624 | "overstrike": false,
625 | "size": 9,
626 | "slant": "roman",
627 | "underline": false,
628 | "weight": "normal"
629 | },
630 | "start_index": "7.0"
631 | },
632 | "8.0": {
633 | "bind": {
634 | "link": null
635 | },
636 | "config": {
637 | "background": "blue",
638 | "foreground": "yellow",
639 | "justify": "center",
640 | "tabs": []
641 | },
642 | "end_index": "9.0",
643 | "font": {
644 | "family": "impact",
645 | "overstrike": false,
646 | "size": 13,
647 | "slant": "roman",
648 | "underline": true,
649 | "weight": "bold"
650 | },
651 | "start_index": "8.0"
652 | },
653 | "9.0": {
654 | "bind": {
655 | "link": null
656 | },
657 | "config": {
658 | "background": "SystemWindow",
659 | "foreground": "black",
660 | "justify": "left",
661 | "tabs": []
662 | },
663 | "end_index": "10.0",
664 | "font": {
665 | "family": "Segoe ui",
666 | "overstrike": false,
667 | "size": 9,
668 | "slant": "roman",
669 | "underline": false,
670 | "weight": "normal"
671 | },
672 | "start_index": "9.0"
673 | }
674 | }
--------------------------------------------------------------------------------
/tests/HTMLLabel_styles.json:
--------------------------------------------------------------------------------
1 | {
2 | "1.0": {
3 | "bind": {
4 | "link": null
5 | },
6 | "config": {
7 | "background": "blue",
8 | "foreground": "yellow",
9 | "justify": "left",
10 | "tabs": []
11 | },
12 | "end_index": "1.8",
13 | "font": {
14 | "family": "impact",
15 | "overstrike": false,
16 | "size": 13,
17 | "slant": "roman",
18 | "underline": true,
19 | "weight": "normal"
20 | },
21 | "start_index": "1.0"
22 | },
23 | "1.16": {
24 | "bind": {
25 | "link": null
26 | },
27 | "config": {
28 | "background": "blue",
29 | "foreground": "yellow",
30 | "justify": "left",
31 | "tabs": []
32 | },
33 | "end_index": "1.29",
34 | "font": {
35 | "family": "impact",
36 | "overstrike": false,
37 | "size": 13,
38 | "slant": "roman",
39 | "underline": false,
40 | "weight": "bold"
41 | },
42 | "start_index": "1.16"
43 | },
44 | "1.29": {
45 | "bind": {
46 | "link": null
47 | },
48 | "config": {
49 | "background": "blue",
50 | "foreground": "yellow",
51 | "justify": "left",
52 | "tabs": []
53 | },
54 | "end_index": "1.37",
55 | "font": {
56 | "family": "impact",
57 | "overstrike": false,
58 | "size": 13,
59 | "slant": "italic",
60 | "underline": true,
61 | "weight": "normal"
62 | },
63 | "start_index": "1.29"
64 | },
65 | "1.37": {
66 | "bind": {
67 | "link": null
68 | },
69 | "config": {
70 | "background": "blue",
71 | "foreground": "yellow",
72 | "justify": "left",
73 | "tabs": []
74 | },
75 | "end_index": "1.46",
76 | "font": {
77 | "family": "impact",
78 | "overstrike": false,
79 | "size": 13,
80 | "slant": "italic",
81 | "underline": true,
82 | "weight": "normal"
83 | },
84 | "start_index": "1.37"
85 | },
86 | "1.46": {
87 | "bind": {
88 | "link": null
89 | },
90 | "config": {
91 | "background": "blue",
92 | "foreground": "yellow",
93 | "justify": "left",
94 | "tabs": []
95 | },
96 | "end_index": "1.54",
97 | "font": {
98 | "family": "impact",
99 | "overstrike": false,
100 | "size": 13,
101 | "slant": "roman",
102 | "underline": true,
103 | "weight": "normal"
104 | },
105 | "start_index": "1.46"
106 | },
107 | "1.54": {
108 | "bind": {
109 | "link": null
110 | },
111 | "config": {
112 | "background": "blue",
113 | "foreground": "yellow",
114 | "justify": "left",
115 | "tabs": []
116 | },
117 | "end_index": "1.65",
118 | "font": {
119 | "family": "impact",
120 | "overstrike": false,
121 | "size": 13,
122 | "slant": "roman",
123 | "underline": true,
124 | "weight": "normal"
125 | },
126 | "start_index": "1.54"
127 | },
128 | "1.65": {
129 | "bind": {
130 | "link": null
131 | },
132 | "config": {
133 | "background": "blue",
134 | "foreground": "yellow",
135 | "justify": "left",
136 | "tabs": []
137 | },
138 | "end_index": "1.76",
139 | "font": {
140 | "family": "impact",
141 | "overstrike": false,
142 | "size": 13,
143 | "slant": "roman",
144 | "underline": true,
145 | "weight": "normal"
146 | },
147 | "start_index": "1.65"
148 | },
149 | "1.76": {
150 | "bind": {
151 | "link": null
152 | },
153 | "config": {
154 | "background": "SystemButtonFace",
155 | "foreground": "black",
156 | "justify": "left",
157 | "tabs": []
158 | },
159 | "end_index": "2.0",
160 | "font": {
161 | "family": "Segoe ui",
162 | "overstrike": false,
163 | "size": 9,
164 | "slant": "roman",
165 | "underline": false,
166 | "weight": "normal"
167 | },
168 | "start_index": "1.76"
169 | },
170 | "1.8": {
171 | "bind": {
172 | "link": null
173 | },
174 | "config": {
175 | "background": "blue",
176 | "foreground": "yellow",
177 | "justify": "left",
178 | "tabs": []
179 | },
180 | "end_index": "1.16",
181 | "font": {
182 | "family": "impact",
183 | "overstrike": false,
184 | "size": 13,
185 | "slant": "roman",
186 | "underline": true,
187 | "weight": "bold"
188 | },
189 | "start_index": "1.8"
190 | },
191 | "10.0": {
192 | "bind": {
193 | "link": null
194 | },
195 | "config": {
196 | "background": "blue",
197 | "foreground": "yellow",
198 | "justify": "center",
199 | "tabs": []
200 | },
201 | "end_index": "11.0",
202 | "font": {
203 | "family": "impact",
204 | "overstrike": false,
205 | "size": 13,
206 | "slant": "roman",
207 | "underline": true,
208 | "weight": "bold"
209 | },
210 | "start_index": "10.0"
211 | },
212 | "11.0": {
213 | "bind": {
214 | "link": null
215 | },
216 | "config": {
217 | "background": "SystemButtonFace",
218 | "foreground": "black",
219 | "justify": "left",
220 | "tabs": []
221 | },
222 | "end_index": "12.0",
223 | "font": {
224 | "family": "Segoe ui",
225 | "overstrike": false,
226 | "size": 9,
227 | "slant": "roman",
228 | "underline": false,
229 | "weight": "normal"
230 | },
231 | "start_index": "11.0"
232 | },
233 | "12.0": {
234 | "bind": {
235 | "link": null
236 | },
237 | "config": {
238 | "background": "blue",
239 | "foreground": "yellow",
240 | "justify": "center",
241 | "tabs": []
242 | },
243 | "end_index": "13.0",
244 | "font": {
245 | "family": "impact",
246 | "overstrike": false,
247 | "size": 13,
248 | "slant": "roman",
249 | "underline": true,
250 | "weight": "bold"
251 | },
252 | "start_index": "12.0"
253 | },
254 | "13.0": {
255 | "bind": {
256 | "link": null
257 | },
258 | "config": {
259 | "background": "SystemButtonFace",
260 | "foreground": "black",
261 | "justify": "left",
262 | "tabs": []
263 | },
264 | "end_index": "14.0",
265 | "font": {
266 | "family": "Segoe ui",
267 | "overstrike": false,
268 | "size": 9,
269 | "slant": "roman",
270 | "underline": false,
271 | "weight": "normal"
272 | },
273 | "start_index": "13.0"
274 | },
275 | "14.0": {
276 | "bind": {
277 | "link": null
278 | },
279 | "config": {
280 | "background": "blue",
281 | "foreground": "yellow",
282 | "justify": "center",
283 | "tabs": []
284 | },
285 | "end_index": "15.0",
286 | "font": {
287 | "family": "impact",
288 | "overstrike": false,
289 | "size": 13,
290 | "slant": "roman",
291 | "underline": true,
292 | "weight": "bold"
293 | },
294 | "start_index": "14.0"
295 | },
296 | "15.0": {
297 | "bind": {
298 | "link": null
299 | },
300 | "config": {
301 | "background": "SystemButtonFace",
302 | "foreground": "black",
303 | "justify": "left",
304 | "tabs": []
305 | },
306 | "end_index": "16.0",
307 | "font": {
308 | "family": "Segoe ui",
309 | "overstrike": false,
310 | "size": 9,
311 | "slant": "roman",
312 | "underline": false,
313 | "weight": "normal"
314 | },
315 | "start_index": "15.0"
316 | },
317 | "16.0": {
318 | "bind": {
319 | "link": null
320 | },
321 | "config": {
322 | "background": "blue",
323 | "foreground": "yellow",
324 | "justify": "center",
325 | "tabs": []
326 | },
327 | "end_index": "17.0",
328 | "font": {
329 | "family": "impact",
330 | "overstrike": false,
331 | "size": 13,
332 | "slant": "roman",
333 | "underline": true,
334 | "weight": "bold"
335 | },
336 | "start_index": "16.0"
337 | },
338 | "17.0": {
339 | "bind": {
340 | "link": null
341 | },
342 | "config": {
343 | "background": "SystemButtonFace",
344 | "foreground": "black",
345 | "justify": "left",
346 | "tabs": []
347 | },
348 | "end_index": "18.0",
349 | "font": {
350 | "family": "Segoe ui",
351 | "overstrike": false,
352 | "size": 9,
353 | "slant": "roman",
354 | "underline": false,
355 | "weight": "normal"
356 | },
357 | "start_index": "17.0"
358 | },
359 | "18.0": {
360 | "bind": {
361 | "link": null
362 | },
363 | "config": {
364 | "background": "blue",
365 | "foreground": "yellow",
366 | "justify": "center",
367 | "tabs": []
368 | },
369 | "end_index": "19.0",
370 | "font": {
371 | "family": "impact",
372 | "overstrike": false,
373 | "size": 13,
374 | "slant": "roman",
375 | "underline": true,
376 | "weight": "bold"
377 | },
378 | "start_index": "18.0"
379 | },
380 | "19.0": {
381 | "bind": {
382 | "link": null
383 | },
384 | "config": {
385 | "background": "SystemButtonFace",
386 | "foreground": "black",
387 | "justify": "left",
388 | "tabs": []
389 | },
390 | "end_index": "20.0",
391 | "font": {
392 | "family": "Segoe ui",
393 | "overstrike": false,
394 | "size": 9,
395 | "slant": "roman",
396 | "underline": false,
397 | "weight": "normal"
398 | },
399 | "start_index": "19.0"
400 | },
401 | "2.0": {
402 | "bind": {
403 | "link": null
404 | },
405 | "config": {
406 | "background": "blue",
407 | "foreground": "yellow",
408 | "justify": "center",
409 | "tabs": []
410 | },
411 | "end_index": "3.0",
412 | "font": {
413 | "family": "impact",
414 | "overstrike": false,
415 | "size": 13,
416 | "slant": "roman",
417 | "underline": true,
418 | "weight": "normal"
419 | },
420 | "start_index": "2.0"
421 | },
422 | "20.0": {
423 | "bind": {
424 | "link": null
425 | },
426 | "config": {
427 | "background": "red",
428 | "foreground": "black",
429 | "justify": "left",
430 | "tabs": []
431 | },
432 | "end_index": "20.4",
433 | "font": {
434 | "family": "Segoe ui",
435 | "overstrike": false,
436 | "size": 9,
437 | "slant": "roman",
438 | "underline": false,
439 | "weight": "normal"
440 | },
441 | "start_index": "20.0"
442 | },
443 | "20.10": {
444 | "bind": {
445 | "link": null
446 | },
447 | "config": {
448 | "background": "yellow",
449 | "foreground": "black",
450 | "justify": "left",
451 | "tabs": []
452 | },
453 | "end_index": "20.17",
454 | "font": {
455 | "family": "Segoe ui",
456 | "overstrike": false,
457 | "size": 9,
458 | "slant": "roman",
459 | "underline": false,
460 | "weight": "normal"
461 | },
462 | "start_index": "20.10"
463 | },
464 | "20.17": {
465 | "bind": {
466 | "link": null
467 | },
468 | "config": {
469 | "background": "red",
470 | "foreground": "black",
471 | "justify": "left",
472 | "tabs": []
473 | },
474 | "end_index": "20.27",
475 | "font": {
476 | "family": "Segoe ui",
477 | "overstrike": false,
478 | "size": 9,
479 | "slant": "roman",
480 | "underline": false,
481 | "weight": "normal"
482 | },
483 | "start_index": "20.17"
484 | },
485 | "20.27": {
486 | "bind": {
487 | "link": null
488 | },
489 | "config": {
490 | "background": "SystemButtonFace",
491 | "foreground": "black",
492 | "justify": "left",
493 | "tabs": []
494 | },
495 | "end_index": "end",
496 | "font": {
497 | "family": "Segoe ui",
498 | "overstrike": false,
499 | "size": 9,
500 | "slant": "roman",
501 | "underline": false,
502 | "weight": "normal"
503 | },
504 | "start_index": "20.27"
505 | },
506 | "20.4": {
507 | "bind": {
508 | "link": null
509 | },
510 | "config": {
511 | "background": "green",
512 | "foreground": "black",
513 | "justify": "left",
514 | "tabs": []
515 | },
516 | "end_index": "20.10",
517 | "font": {
518 | "family": "Segoe ui",
519 | "overstrike": false,
520 | "size": 9,
521 | "slant": "roman",
522 | "underline": false,
523 | "weight": "normal"
524 | },
525 | "start_index": "20.4"
526 | },
527 | "3.0": {
528 | "bind": {
529 | "link": null
530 | },
531 | "config": {
532 | "background": "SystemButtonFace",
533 | "foreground": "black",
534 | "justify": "left",
535 | "tabs": []
536 | },
537 | "end_index": "4.0",
538 | "font": {
539 | "family": "Segoe ui",
540 | "overstrike": false,
541 | "size": 9,
542 | "slant": "roman",
543 | "underline": false,
544 | "weight": "normal"
545 | },
546 | "start_index": "3.0"
547 | },
548 | "4.0": {
549 | "bind": {
550 | "link": null
551 | },
552 | "config": {
553 | "background": "blue",
554 | "foreground": "yellow",
555 | "justify": "center",
556 | "tabs": []
557 | },
558 | "end_index": "5.0",
559 | "font": {
560 | "family": "impact",
561 | "overstrike": false,
562 | "size": 13,
563 | "slant": "roman",
564 | "underline": true,
565 | "weight": "normal"
566 | },
567 | "start_index": "4.0"
568 | },
569 | "5.0": {
570 | "bind": {
571 | "link": null
572 | },
573 | "config": {
574 | "background": "SystemButtonFace",
575 | "foreground": "black",
576 | "justify": "left",
577 | "tabs": []
578 | },
579 | "end_index": "6.0",
580 | "font": {
581 | "family": "Segoe ui",
582 | "overstrike": false,
583 | "size": 9,
584 | "slant": "roman",
585 | "underline": false,
586 | "weight": "normal"
587 | },
588 | "start_index": "5.0"
589 | },
590 | "6.0": {
591 | "bind": {
592 | "link": null
593 | },
594 | "config": {
595 | "background": "blue",
596 | "foreground": "yellow",
597 | "justify": "center",
598 | "tabs": []
599 | },
600 | "end_index": "7.0",
601 | "font": {
602 | "family": "impact",
603 | "overstrike": false,
604 | "size": 13,
605 | "slant": "roman",
606 | "underline": true,
607 | "weight": "normal"
608 | },
609 | "start_index": "6.0"
610 | },
611 | "7.0": {
612 | "bind": {
613 | "link": null
614 | },
615 | "config": {
616 | "background": "SystemButtonFace",
617 | "foreground": "black",
618 | "justify": "left",
619 | "tabs": []
620 | },
621 | "end_index": "8.0",
622 | "font": {
623 | "family": "Segoe ui",
624 | "overstrike": false,
625 | "size": 9,
626 | "slant": "roman",
627 | "underline": false,
628 | "weight": "normal"
629 | },
630 | "start_index": "7.0"
631 | },
632 | "8.0": {
633 | "bind": {
634 | "link": null
635 | },
636 | "config": {
637 | "background": "blue",
638 | "foreground": "yellow",
639 | "justify": "center",
640 | "tabs": []
641 | },
642 | "end_index": "9.0",
643 | "font": {
644 | "family": "impact",
645 | "overstrike": false,
646 | "size": 13,
647 | "slant": "roman",
648 | "underline": true,
649 | "weight": "bold"
650 | },
651 | "start_index": "8.0"
652 | },
653 | "9.0": {
654 | "bind": {
655 | "link": null
656 | },
657 | "config": {
658 | "background": "SystemButtonFace",
659 | "foreground": "black",
660 | "justify": "left",
661 | "tabs": []
662 | },
663 | "end_index": "10.0",
664 | "font": {
665 | "family": "Segoe ui",
666 | "overstrike": false,
667 | "size": 9,
668 | "slant": "roman",
669 | "underline": false,
670 | "weight": "normal"
671 | },
672 | "start_index": "9.0"
673 | }
674 | }
--------------------------------------------------------------------------------
/tk_html_widgets/html_parser.py:
--------------------------------------------------------------------------------
1 | """
2 | HTML parser
3 | """
4 | import os
5 | import webbrowser
6 | import tkinter as tk
7 | from tkinter import font
8 | from copy import deepcopy
9 | from PIL import Image, ImageTk
10 | from html.parser import HTMLParser
11 | from collections import OrderedDict
12 |
13 |
14 | #__________________________________________________________________________________________________
15 | class Defs():
16 | DEFAULT_TEXT_FONT_FAMILY = ("Segoe ui", "Calibri", "Helvetica", "TkTextFont")
17 | FONT_SIZE = 9
18 | PREFORMATTED_FONT_FAMILY = ("Courier", "DejaVu Sans Mono", "TkFixedFont")
19 | HEADINGS_FONT_SIZE = {
20 | 'h1':21,
21 | 'h2':16,
22 | 'h3':12,
23 | 'h4':11,
24 | 'h5':8,
25 | 'h6':7,
26 | }
27 |
28 |
29 | class HTML:
30 | #----------------------------------------------------------------------------------------------
31 | """
32 | List of supported HTML tags and attrs
33 | """
34 | class Tag():
35 | BR = 'br'
36 | UL = 'ul'
37 | OL = 'ol'
38 | LI = 'li'
39 | IMG = 'img'
40 | A = 'a'
41 | B = 'b'
42 | STRONG = 'strong'
43 | I = 'i'
44 | EM = 'em'
45 | U = 'u'
46 | MARK = 'mark'
47 | SPAN = 'span'
48 | DIV = 'div'
49 | P = 'p'
50 | PRE = 'pre'
51 | CODE = 'code'
52 | H1 = 'h1'
53 | H2 = 'h2'
54 | H3 = 'h3'
55 | H4 = 'h4'
56 | H5 = 'h5'
57 | H6 = 'h6'
58 |
59 | class Attrs():
60 | STYLE = 'style'
61 | HREF ='href'
62 | SRC = 'src'
63 | WIDTH = 'width'
64 | HEIGHT = 'height'
65 | TYPE = 'type'
66 |
67 | class TypeOrderedList():
68 | _1 = '1'
69 | a = 'a'
70 | A = 'A'
71 |
72 | class Style():
73 | COLOR = 'color'
74 | BACKGROUD_COLOR = 'background-color'
75 | FONT_FAMILY = 'font-family'
76 | FONT_SIZE = 'font-size'
77 | TEXT_ALIGN = 'text-align'
78 | TEXT_DECORATION = 'text-decoration'
79 |
80 | class StyleTextDecoration():
81 | UNDERLINE = 'underline'
82 | LINE_THROUGH = 'line-through'
83 |
84 | HEADING_TAGS = (
85 | Tag.H1,
86 | Tag.H2,
87 | Tag.H3,
88 | Tag.H4,
89 | Tag.H5,
90 | Tag.H6,
91 | )
92 |
93 | TEXT_ALIGN_TAGS = HEADING_TAGS + (
94 | Tag.UL,
95 | Tag.OL,
96 | Tag.LI,
97 | Tag.DIV,
98 | Tag.P,
99 | Tag.PRE,
100 | Tag.CODE,
101 | )
102 |
103 | NEW_LINE_TAGS = HEADING_TAGS + (
104 | Tag.UL,
105 | Tag.OL,
106 | Tag.DIV,
107 | Tag.P,
108 | Tag.PRE,
109 | Tag.CODE,
110 | )
111 |
112 | STYLE_TAGS = TEXT_ALIGN_TAGS + (
113 | Tag.A,
114 | Tag.B,
115 | Tag.STRONG,
116 | Tag.I,
117 | Tag.EM,
118 | Tag.U,
119 | Tag.MARK,
120 | Tag.SPAN,
121 | )
122 |
123 |
124 |
125 | #--------------------------------------------------------------------------------------------------
126 | # Text widget defs
127 |
128 | class WCfg():
129 | KEY = "config"
130 | BACKGROUND = "background"
131 | FOREGROUND = "foreground"
132 | JUSTIFY = "justify"
133 | TABS = "tabs"
134 |
135 | class Fnt():
136 | KEY = "font"
137 | FAMILY = "family"
138 | SIZE = "size"
139 | WEIGHT = "weight"
140 | SLANT = "slant"
141 | UNDERLINE = "underline"
142 | OVERSTRIKE = "overstrike"
143 |
144 | class Bind():
145 | KEY = "bind"
146 | LINK = "link"
147 | IMAGE = "image"
148 |
149 | class WTag():
150 | START_INDEX = "start_index"
151 | END_INDEX = "end_index"
152 |
153 | DEFAULT_STACK = {
154 | WCfg.KEY:{
155 | WCfg.BACKGROUND:[],
156 | WCfg.FOREGROUND:[("__DEFAULT__", "black")],
157 | WCfg.JUSTIFY:[("__DEFAULT__", 'left')],
158 | WCfg.TABS:[("__DEFAULT__", ())],
159 | },
160 | Fnt.KEY:{
161 | Fnt.FAMILY:[],
162 | Fnt.SIZE:[("__DEFAULT__", Defs.FONT_SIZE)],
163 | Fnt.WEIGHT:[("__DEFAULT__", 'normal')],
164 | Fnt.SLANT:[("__DEFAULT__", 'roman')],
165 | Fnt.UNDERLINE:[("__DEFAULT__", False)],
166 | Fnt.OVERSTRIKE:[("__DEFAULT__", False)],
167 | },
168 | Bind.KEY:{
169 | Bind.LINK:[("__DEFAULT__", None)],
170 | },
171 | }
172 |
173 | #__________________________________________________________________________________________________
174 | # functions
175 | def get_existing_font(font_families):
176 | #------------------------------------------------------------------------------------------
177 | try:
178 | return next(filter(lambda f: f.lower() in (f.lower() for f in font.families()), font_families))
179 | except:
180 | return "TkTextFont"
181 |
182 |
183 | #__________________________________________________________________________________________________
184 | # classes
185 | class HLinkSlot():
186 | #----------------------------------------------------------------------------------------------
187 |
188 | def __init__(self, w, tag_name, url):
189 | #------------------------------------------------------------------------------------------
190 | self._w = w
191 | self.tag_name = tag_name
192 | self.URL = url
193 |
194 | def call(self, event):
195 | #------------------------------------------------------------------------------------------
196 | webbrowser.open(self.URL)
197 | self._w.tag_config(self.tag_name, foreground="purple")
198 |
199 | def enter(self, event):
200 | #------------------------------------------------------------------------------------------
201 | self._w.config(cursor="hand2")
202 |
203 | def leave(self, event):
204 | #------------------------------------------------------------------------------------------
205 | self._w.config(cursor="")
206 |
207 |
208 |
209 |
210 | class ListTag():
211 | #----------------------------------------------------------------------------------------------
212 | def __init__(self, ordered:bool, list_type=None):
213 | #------------------------------------------------------------------------------------------
214 | self.ordered = ordered
215 | self.type = list_type
216 | self.index = 0
217 |
218 | def add(self):
219 | #------------------------------------------------------------------------------------------
220 | if self.ordered:
221 | self.index += 1
222 |
223 | def line_index(self):
224 | #------------------------------------------------------------------------------------------
225 | if self.ordered:
226 | if self.type == HTML.TypeOrderedList._1:
227 | return str(self.index)
228 | elif self.type == HTML.TypeOrderedList.a:
229 | return self._index_to_str(self.index).lower()
230 | elif self.type == HTML.TypeOrderedList.A:
231 | return self._index_to_str(self.index).upper()
232 | else:
233 | return chr(8226)
234 |
235 | def _index_to_str(self, index):
236 | #------------------------------------------------------------------------------------------
237 | prefix = ""
238 | if index > 26:
239 | prefix = self._index_to_str(index // 26)
240 | index = index % 26
241 |
242 | return prefix + chr(0x60 + index)
243 |
244 |
245 |
246 | class HTMLTextParser(HTMLParser):
247 | #----------------------------------------------------------------------------------------------
248 |
249 | def __init__(self):
250 | #------------------------------------------------------------------------------------------
251 | super().__init__()
252 | # set list tabs
253 | self.cached_images = {}
254 |
255 | self.DEFAULT_TEXT_FONT_FAMILY = get_existing_font(Defs.DEFAULT_TEXT_FONT_FAMILY)
256 | self.PREFORMATTED_FONT_FAMILY = get_existing_font(Defs.PREFORMATTED_FONT_FAMILY)
257 |
258 |
259 | def _parse_attrs(self, attrs):
260 | #------------------------------------------------------------------------------------------
261 | attrs_dict = {
262 | HTML.Attrs.STYLE:{},
263 | HTML.Attrs.HREF:None,
264 | HTML.Attrs.SRC:None,
265 | HTML.Attrs.WIDTH:None,
266 | HTML.Attrs.HEIGHT:None,
267 | HTML.Attrs.TYPE:None,
268 | }
269 | for k, v in attrs:
270 | k = k.lower()
271 | if k == HTML.Attrs.STYLE:
272 | for p in v.split(";"):
273 | try:
274 | p_key = p.split(":")[0].strip().lower()
275 | p_value = p.split(":")[1].strip().lower()
276 | attrs_dict[HTML.Attrs.STYLE][p_key] = p_value
277 | except:
278 | pass
279 | elif k in (HTML.Attrs.HREF, HTML.Attrs.SRC, HTML.Attrs.WIDTH, HTML.Attrs.HEIGHT, HTML.Attrs.TYPE):
280 | attrs_dict[k] = v
281 | return attrs_dict
282 |
283 |
284 | def _w_tags_add(self):
285 | #------------------------------------------------------------------------------------------
286 | tag = {
287 | WCfg.KEY:{},
288 | Fnt.KEY:{},
289 | Bind.KEY:{}
290 | }
291 |
292 | for k1 in (WCfg.KEY, Fnt.KEY, Bind.KEY):
293 | for k2 in DEFAULT_STACK[k1]:
294 | tag[k1][k2] = self.stack[k1][k2][-1][1]
295 |
296 | self._w_tags[self._w.index("end-1c")] = tag
297 |
298 |
299 | def _stack_get_main_key(self, key):
300 | #------------------------------------------------------------------------------------------
301 | if key in WCfg.__dict__.values():
302 | main_key = WCfg.KEY
303 | elif key in Fnt.__dict__.values():
304 | main_key = Fnt.KEY
305 | elif key in Bind.__dict__.values():
306 | main_key = Bind.KEY
307 | else:
308 | raise ValueError("key %s doesn't exists" % key)
309 |
310 | return main_key
311 |
312 |
313 | def _stack_add(self, tag, key, value=None):
314 | #------------------------------------------------------------------------------------------
315 | main_key = self._stack_get_main_key(key)
316 |
317 | if value is None:
318 | # if value is none, add the previous value
319 | value = self.stack[main_key][key][-1][1]
320 |
321 | self.stack[main_key][key].append((tag, value))
322 |
323 |
324 | def _stack_index(self, tag, key):
325 | #------------------------------------------------------------------------------------------
326 | main_key = self._stack_get_main_key(key)
327 | index = None
328 | for i, v in enumerate(self.stack[main_key][key]):
329 | if v[0] == tag:
330 | index = i
331 |
332 | return index
333 |
334 |
335 | def _stack_pop(self, tag, key):
336 | #------------------------------------------------------------------------------------------
337 | main_key = self._stack_get_main_key(key)
338 |
339 | index = None
340 | if len(self.stack[main_key][key]) > 1:
341 | index = self._stack_index(tag, key)
342 |
343 | if index is not None:
344 | return self.stack[main_key][key].pop(index)[1]
345 |
346 |
347 | def _parse_styles(self, tag, attrs):
348 | #------------------------------------------------------------------------------------------
349 | #-------------------------------------------------------------------------------- [ COLOR ]
350 | if HTML.Style.COLOR in attrs[HTML.Attrs.STYLE].keys():
351 | self._stack_add(tag, WCfg.FOREGROUND, attrs[HTML.Attrs.STYLE][HTML.Style.COLOR])
352 | elif tag == HTML.Tag.A and attrs[HTML.Attrs.HREF]:
353 | self._stack_add(tag, WCfg.FOREGROUND, "blue")
354 | else:
355 | self._stack_add(tag, WCfg.FOREGROUND)
356 |
357 | #---------------------------------------------------------------------- [ BACKGROUD_COLOR ]
358 | if HTML.Style.BACKGROUD_COLOR in attrs[HTML.Attrs.STYLE].keys():
359 | self._stack_add(tag, WCfg.BACKGROUND, attrs[HTML.Attrs.STYLE][HTML.Style.BACKGROUD_COLOR])
360 | elif tag == HTML.Tag.MARK:
361 | self._stack_add(tag, WCfg.BACKGROUND, "yellow")
362 | else:
363 | self._stack_add(tag, WCfg.BACKGROUND)
364 |
365 | #-------------------------------------------------------------------------- [ FONT_FAMILY ]
366 | # font family
367 | if HTML.Style.FONT_FAMILY in attrs[HTML.Attrs.STYLE].keys():
368 | font_family = Defs.DEFAULT_TEXT_FONT_FAMILY
369 | for f in attrs[HTML.Attrs.STYLE][HTML.Style.FONT_FAMILY].split(","):
370 | f = f.strip()
371 | if f in map(lambda f: f.lower(), font.families()):
372 | font_family = f
373 | break
374 | self._stack_add(tag, Fnt.FAMILY, font_family)
375 | elif tag in (HTML.Tag.PRE, HTML.Tag.CODE):
376 | self._stack_add(tag, Fnt.FAMILY, self.PREFORMATTED_FONT_FAMILY)
377 | else:
378 | self._stack_add(tag, Fnt.FAMILY)
379 |
380 | #---------------------------------------------------------------------------- [ FONT_SIZE ]
381 | if HTML.Style.FONT_SIZE in attrs[HTML.Attrs.STYLE].keys():
382 | size = Defs.FONT_SIZE
383 | if attrs[HTML.Attrs.STYLE][HTML.Style.FONT_SIZE].endswith("px"):
384 | if attrs[HTML.Attrs.STYLE][HTML.Style.FONT_SIZE][:-2].isdigit():
385 | size = int(attrs[HTML.Attrs.STYLE][HTML.Style.FONT_SIZE][:-2])
386 | elif attrs[HTML.Attrs.STYLE][HTML.Style.FONT_SIZE].endswith(r"%"):
387 | if attrs[HTML.Attrs.STYLE][HTML.Style.FONT_SIZE][:-1].isdigit():
388 | size = int((int(attrs[HTML.Attrs.STYLE][HTML.Style.FONT_SIZE][:-1]) * Defs.FONT_SIZE)/100)
389 | self._stack_add(tag, Fnt.SIZE, size)
390 | elif tag.startswith('h') and len(tag) == 2:
391 | self._stack_add(tag, Fnt.SIZE, Defs.HEADINGS_FONT_SIZE[tag])
392 | else:
393 | self._stack_add(tag, Fnt.SIZE)
394 |
395 | #--------------------------------------------------------------------------- [ TEXT_ALIGN ]
396 | if HTML.Style.TEXT_ALIGN in attrs[HTML.Attrs.STYLE].keys() and tag in HTML.TEXT_ALIGN_TAGS:
397 | self._stack_add(tag, WCfg.JUSTIFY, attrs[HTML.Attrs.STYLE][HTML.Style.TEXT_ALIGN])
398 | else:
399 | self._stack_add(tag, WCfg.JUSTIFY)
400 |
401 | #---------------------------------------------------------------------- [ TEXT_DECORATION ]
402 | if HTML.Style.TEXT_DECORATION in attrs[HTML.Attrs.STYLE].keys():
403 | if tag == HTML.Tag.STRONG:
404 | self._stack_add(tag, Fnt.UNDERLINE, False)
405 | self._stack_add(tag, Fnt.OVERSTRIKE, False)
406 | elif HTML.StyleTextDecoration.UNDERLINE in attrs[HTML.Attrs.STYLE][HTML.Style.TEXT_DECORATION]:
407 | self._stack_add(tag, Fnt.UNDERLINE, True)
408 | self._stack_add(tag, Fnt.OVERSTRIKE, False)
409 | elif HTML.StyleTextDecoration.LINE_THROUGH in attrs[HTML.Attrs.STYLE][HTML.Style.TEXT_DECORATION]:
410 | self._stack_add(tag, Fnt.UNDERLINE, False)
411 | self._stack_add(tag, Fnt.OVERSTRIKE, True)
412 | else:
413 | self._stack_add(tag, Fnt.UNDERLINE)
414 | self._stack_add(tag, Fnt.OVERSTRIKE)
415 | else:
416 | if tag == HTML.Tag.A and attrs[HTML.Attrs.HREF]:
417 | self._stack_add(tag, Fnt.UNDERLINE, True)
418 | self._stack_add(tag, Fnt.OVERSTRIKE, False)
419 | elif tag == HTML.Tag.U:
420 | self._stack_add(tag, Fnt.UNDERLINE, True)
421 | self._stack_add(tag, Fnt.OVERSTRIKE, False)
422 | else:
423 | self._stack_add(tag, Fnt.UNDERLINE)
424 | self._stack_add(tag, Fnt.OVERSTRIKE)
425 |
426 |
427 | def handle_starttag(self, tag, attrs):
428 | #------------------------------------------------------------------------------------------
429 | tag = tag.lower()
430 | attrs = self._parse_attrs(attrs)
431 |
432 | if tag in HTML.STYLE_TAGS:
433 | #---------------------------------------------------------------------- [ STYLED_TAGS ]
434 | self._parse_styles(tag, attrs)
435 |
436 | if tag == HTML.Tag.B or tag == HTML.Tag.STRONG or tag in HTML.HEADING_TAGS:
437 | self._stack_add(tag, Fnt.WEIGHT, "bold")
438 |
439 | elif tag == HTML.Tag.I or tag == HTML.Tag.EM:
440 | self._stack_add(tag, Fnt.SLANT, "italic")
441 |
442 | elif tag == HTML.Tag.A:
443 | self._stack_add(tag, Bind.LINK, attrs[HTML.Attrs.HREF])
444 |
445 | elif tag == HTML.Tag.OL:
446 | #---------------------------------------------------------------- [ ORDERED_LISTS ]
447 | if attrs[HTML.Attrs.TYPE] and attrs[HTML.Attrs.TYPE] in HTML.TypeOrderedList.__dict__.values():
448 | list_type = attrs[HTML.Attrs.TYPE]
449 | else:
450 | list_type = HTML.TypeOrderedList._1
451 | self.list_tags.append(ListTag(ordered=True, list_type=list_type))
452 |
453 | tabs = []
454 | for i in range(len(self.list_tags)):
455 | offset = 30 * (i + 1)
456 | tabs += [offset, tk.RIGHT, offset+5, tk.LEFT ]
457 | self._stack_add(tag, WCfg.TABS, tabs)
458 |
459 | elif tag == HTML.Tag.UL:
460 | #-------------------------------------------------------------- [ UNORDERED_LISTS ]
461 | self.list_tags.append(ListTag(ordered=False))
462 |
463 | tabs = []
464 | for i in range(len(self.list_tags)):
465 | offset = 30 * (i + 1)
466 | tabs += [offset, tk.RIGHT, offset+5, tk.LEFT ]
467 | self._stack_add(tag, WCfg.TABS, tabs)
468 |
469 | elif tag == HTML.Tag.LI:
470 | #------------------------------------------------------------------ [ LISTS_LINES ]
471 | level = len(self.list_tags)
472 | if level:
473 | self.list_tags[-1].add()
474 |
475 | if self.strip:
476 | self._insert_new_line()
477 |
478 | line_index = self.list_tags[-1].line_index()
479 | if self.list_tags[-1].ordered:
480 | line_index = "\t" + "\t\t" * (level-1) + line_index + ".\t"
481 | else:
482 | line_index = "\t" + "\t\t" * (level-1) + line_index + "\t"
483 |
484 | self._stack_add(tag, Fnt.UNDERLINE, False)
485 | self._stack_add(tag, Fnt.OVERSTRIKE, False)
486 | self._w_tags_add()
487 | self._w.insert(tk.INSERT, line_index)
488 | self._stack_pop(tag, Fnt.UNDERLINE)
489 | self._stack_pop(tag, Fnt.OVERSTRIKE)
490 |
491 | elif tag == HTML.Tag.IMG and attrs[HTML.Attrs.SRC]:
492 | #-------------------------------------------------------------------- [ UNSTYLED_TAGS ]
493 | image = None
494 | if attrs[HTML.Attrs.SRC] in self.cached_images.keys():
495 | image = deepcopy(self.cached_images[attrs[HTML.Attrs.SRC]])
496 | elif os.path.exists(attrs[HTML.Attrs.SRC]):
497 | image = Image.open(attrs[HTML.Attrs.SRC])
498 | self.cached_images[attrs[HTML.Attrs.SRC]] = deepcopy(image)
499 | if image:
500 | width = image.size[0]
501 | height = image.size[1]
502 | resize = False
503 | if str(attrs[HTML.Attrs.WIDTH]).isdigit():
504 | width = int(attrs[HTML.Attrs.WIDTH])
505 | resize = True
506 | if str(attrs[HTML.Attrs.HEIGHT]).isdigit():
507 | height = int(attrs[HTML.Attrs.HEIGHT])
508 | resize = True
509 | if resize:
510 | image = image.resize((width, height), Image.ANTIALIAS)
511 | self.images.append(ImageTk.PhotoImage(image))
512 | self._w.image_create(tk.INSERT, image=self.images[-1])
513 |
514 | if self.strip:
515 | #------------------------------------------------------------------------ [ NEW_LINES ]
516 | if tag == HTML.Tag.BR:
517 | self._insert_new_line()
518 | else:
519 | self.html_tags.append(tag)
520 |
521 | if tag in HTML.NEW_LINE_TAGS and self.strip and self._w.index("end-1c") != "1.0":
522 | if tag in (HTML.Tag.DIV,):
523 | self._insert_new_line()
524 | elif tag in (HTML.Tag.UL, HTML.Tag.OL):
525 | if len(self.list_tags) == 1:
526 | self._insert_new_line(double=True)
527 | else:
528 | self._insert_new_line(double=False)
529 | else:
530 | self._insert_new_line(double=True)
531 |
532 | self._w_tags_add()
533 |
534 |
535 | def handle_charref(self, data):
536 | #------------------------------------------------------------------------------------------
537 | try:
538 | char = chr(int(data))
539 | self._w.insert(tk.INSERT, char)
540 | except:
541 | pass
542 |
543 |
544 | def _insert_new_line(self, double=False):
545 | #------------------------------------------------------------------------------------------
546 | self._remove_last_space()
547 | if self._w.get("end-3c", "end-1c") == "\n\n":
548 | pass
549 | elif self._w.get("end-2c", "end-1c") == "\n":
550 | if double:
551 | self._w.insert(tk.INSERT, "\n")
552 | else:
553 | if double:
554 | self._w.insert(tk.INSERT, "\n\n")
555 | else:
556 | self._w.insert(tk.INSERT, "\n")
557 |
558 |
559 | def _text_rstrip(self):
560 | #------------------------------------------------------------------------------------------
561 | for _ in range(3):
562 | if self._w.get("end-2c", "end-1c") in (" ", "\n"):
563 | self._w.delete("end-2c", "end-1c")
564 |
565 |
566 | def _remove_last_space(self):
567 | #------------------------------------------------------------------------------------------
568 | if self._w.get("end-2c", "end-1c") == " ":
569 | self._w.delete("end-2c", "end-1c")
570 |
571 |
572 | def _remove_multi_spaces(self, data):
573 | #------------------------------------------------------------------------------------------
574 | data = data.replace(" ", " ")
575 | if " " in data:
576 | data = self._remove_multi_spaces(data)
577 | return data
578 |
579 |
580 | def handle_data(self, data):
581 | #------------------------------------------------------------------------------------------
582 | if self.strip:
583 | if len(self.html_tags) and self.html_tags[-1] in (HTML.Tag.PRE, HTML.Tag.CODE):
584 | pass
585 | elif not data.strip():
586 | data = ""
587 | else:
588 | # left strip
589 | if self._w.index("end-1c").endswith(".0"):
590 | data = data.lstrip()
591 | elif self._w.get("end-2c", "end-1c") == " ":
592 | data = data.lstrip()
593 |
594 | data = data.replace("\n", " ").replace("\t", " ")
595 | data = data + " "
596 | data = self._remove_multi_spaces(data)
597 | if len(self.html_tags):
598 | level = len(self.list_tags)
599 | if self.html_tags[-1] in (HTML.Tag.UL, HTML.Tag.OL):
600 | self._w.insert(tk.INSERT, "\t" * 2 * level)
601 |
602 | self._w.insert(tk.INSERT, data)
603 |
604 |
605 | def handle_endtag(self, tag):
606 | #------------------------------------------------------------------------------------------
607 | tag = tag.lower()
608 |
609 | try:
610 | index = len(self.html_tags) - self.html_tags[::-1].index(tag) - 1
611 | self.html_tags.pop(index)
612 | except:
613 | pass
614 |
615 | if tag in HTML.STYLE_TAGS:
616 |
617 | self._stack_pop(tag, WCfg.FOREGROUND)
618 | self._stack_pop(tag, WCfg.BACKGROUND)
619 | self._stack_pop(tag, WCfg.JUSTIFY)
620 | self._stack_pop(tag, Fnt.FAMILY)
621 | self._stack_pop(tag, Fnt.SIZE)
622 | self._stack_pop(tag, Fnt.UNDERLINE)
623 | self._stack_pop(tag, Fnt.OVERSTRIKE)
624 |
625 | if tag == HTML.Tag.B or tag == HTML.Tag.STRONG or tag in HTML.HEADING_TAGS:
626 | self._stack_pop(tag, Fnt.WEIGHT)
627 |
628 | elif tag == HTML.Tag.I or tag == HTML.Tag.EM:
629 | self._stack_pop(tag, Fnt.SLANT)
630 |
631 | elif tag == HTML.Tag.A:
632 | self._stack_pop(tag, Bind.LINK)
633 |
634 | elif tag == HTML.Tag.OL or tag == HTML.Tag.UL:
635 | if len(self.list_tags):
636 | self.list_tags = self.list_tags[:-1]
637 |
638 | self._stack_pop(tag, WCfg.TABS)
639 |
640 | if tag in HTML.NEW_LINE_TAGS and self.strip:
641 | self._insert_new_line()
642 |
643 | self._w_tags_add()
644 |
645 | if tag in HTML.NEW_LINE_TAGS and self.strip:
646 | if tag in (HTML.Tag.DIV, HTML.Tag.UL, HTML.Tag.OL):
647 | if not len(self.list_tags):
648 | self._insert_new_line(double=True)
649 | else:
650 | self._insert_new_line(double=True)
651 |
652 |
653 | def _w_tags_apply_all(self):
654 | #------------------------------------------------------------------------------------------
655 | # update indexes
656 | if self.strip:
657 | self._text_rstrip()
658 | end_index = tk.END
659 | for key, tag in reversed(tuple(self._w_tags.items())):
660 | tag[WTag.START_INDEX] = key
661 | tag[WTag.END_INDEX] = end_index
662 | end_index = key
663 |
664 | # add tags
665 | self.hlink_slots = []
666 | for key, tag in self._w_tags.items():
667 | self._w.tag_add(key, tag[WTag.START_INDEX], tag[WTag.END_INDEX])
668 | self._w.tag_config(key, font=font.Font(**tag[Fnt.KEY]), **tag[WCfg.KEY])
669 | if tag[Bind.KEY][Bind.LINK]:
670 | self.hlink_slots.append(HLinkSlot(self._w, key, tag[Bind.KEY][Bind.LINK]))
671 | self._w.tag_bind(key, "", self.hlink_slots[-1].call)
672 | self._w.tag_bind(key, "", self.hlink_slots[-1].leave)
673 | self._w.tag_bind(key, "", self.hlink_slots[-1].enter)
674 |
675 |
676 | def w_set_html(self, w, html, strip):
677 | #------------------------------------------------------------------------------------------
678 | self._w = w
679 | self.stack = deepcopy(DEFAULT_STACK)
680 | self.stack[WCfg.KEY][WCfg.BACKGROUND].append(("__DEFAULT__", self._w.cget("background")))
681 | self.stack[Fnt.KEY][Fnt.FAMILY].append(("__DEFAULT__", self.DEFAULT_TEXT_FONT_FAMILY))
682 | self._w_tags = OrderedDict()
683 | self.html_tags = []
684 | self.images = []
685 | self.list_tags = []
686 | self.strip = strip
687 | self._w_tags_add()
688 | self.feed(html)
689 | self._w_tags_apply_all()
690 | del self._w
691 |
--------------------------------------------------------------------------------
/tests/HTMLText_tags.json:
--------------------------------------------------------------------------------
1 | {
2 | "1.0": {
3 | "bind": {
4 | "link": null
5 | },
6 | "config": {
7 | "background": "SystemWindow",
8 | "foreground": "black",
9 | "justify": "left",
10 | "tabs": [
11 | 30,
12 | "right",
13 | 35,
14 | "left"
15 | ]
16 | },
17 | "end_index": "2.0",
18 | "font": {
19 | "family": "Segoe ui",
20 | "overstrike": false,
21 | "size": 9,
22 | "slant": "roman",
23 | "underline": false,
24 | "weight": "normal"
25 | },
26 | "start_index": "1.0"
27 | },
28 | "10.0": {
29 | "bind": {
30 | "link": null
31 | },
32 | "config": {
33 | "background": "SystemWindow",
34 | "foreground": "black",
35 | "justify": "left",
36 | "tabs": [
37 | 30,
38 | "right",
39 | 35,
40 | "left",
41 | 60,
42 | "right",
43 | 65,
44 | "left"
45 | ]
46 | },
47 | "end_index": "10.6",
48 | "font": {
49 | "family": "Segoe ui",
50 | "overstrike": false,
51 | "size": 9,
52 | "slant": "roman",
53 | "underline": false,
54 | "weight": "normal"
55 | },
56 | "start_index": "10.0"
57 | },
58 | "10.29": {
59 | "bind": {
60 | "link": null
61 | },
62 | "config": {
63 | "background": "SystemWindow",
64 | "foreground": "black",
65 | "justify": "left",
66 | "tabs": [
67 | 30,
68 | "right",
69 | 35,
70 | "left",
71 | 60,
72 | "right",
73 | 65,
74 | "left"
75 | ]
76 | },
77 | "end_index": "11.0",
78 | "font": {
79 | "family": "Segoe ui",
80 | "overstrike": false,
81 | "size": 9,
82 | "slant": "roman",
83 | "underline": false,
84 | "weight": "normal"
85 | },
86 | "start_index": "10.29"
87 | },
88 | "10.6": {
89 | "bind": {
90 | "link": null
91 | },
92 | "config": {
93 | "background": "SystemWindow",
94 | "foreground": "black",
95 | "justify": "left",
96 | "tabs": [
97 | 30,
98 | "right",
99 | 35,
100 | "left",
101 | 60,
102 | "right",
103 | 65,
104 | "left"
105 | ]
106 | },
107 | "end_index": "10.29",
108 | "font": {
109 | "family": "Segoe ui",
110 | "overstrike": false,
111 | "size": 9,
112 | "slant": "roman",
113 | "underline": false,
114 | "weight": "normal"
115 | },
116 | "start_index": "10.6"
117 | },
118 | "11.0": {
119 | "bind": {
120 | "link": null
121 | },
122 | "config": {
123 | "background": "SystemWindow",
124 | "foreground": "black",
125 | "justify": "left",
126 | "tabs": [
127 | 30,
128 | "right",
129 | 35,
130 | "left",
131 | 60,
132 | "right",
133 | 65,
134 | "left"
135 | ]
136 | },
137 | "end_index": "11.6",
138 | "font": {
139 | "family": "Segoe ui",
140 | "overstrike": false,
141 | "size": 9,
142 | "slant": "roman",
143 | "underline": false,
144 | "weight": "normal"
145 | },
146 | "start_index": "11.0"
147 | },
148 | "11.30": {
149 | "bind": {
150 | "link": null
151 | },
152 | "config": {
153 | "background": "SystemWindow",
154 | "foreground": "black",
155 | "justify": "left",
156 | "tabs": [
157 | 30,
158 | "right",
159 | 35,
160 | "left",
161 | 60,
162 | "right",
163 | 65,
164 | "left"
165 | ]
166 | },
167 | "end_index": "12.0",
168 | "font": {
169 | "family": "Segoe ui",
170 | "overstrike": false,
171 | "size": 9,
172 | "slant": "roman",
173 | "underline": false,
174 | "weight": "normal"
175 | },
176 | "start_index": "11.30"
177 | },
178 | "11.6": {
179 | "bind": {
180 | "link": null
181 | },
182 | "config": {
183 | "background": "SystemWindow",
184 | "foreground": "black",
185 | "justify": "left",
186 | "tabs": [
187 | 30,
188 | "right",
189 | 35,
190 | "left",
191 | 60,
192 | "right",
193 | 65,
194 | "left"
195 | ]
196 | },
197 | "end_index": "11.30",
198 | "font": {
199 | "family": "Segoe ui",
200 | "overstrike": false,
201 | "size": 9,
202 | "slant": "roman",
203 | "underline": false,
204 | "weight": "normal"
205 | },
206 | "start_index": "11.6"
207 | },
208 | "12.0": {
209 | "bind": {
210 | "link": null
211 | },
212 | "config": {
213 | "background": "SystemWindow",
214 | "foreground": "black",
215 | "justify": "left",
216 | "tabs": [
217 | 30,
218 | "right",
219 | 35,
220 | "left",
221 | 60,
222 | "right",
223 | 65,
224 | "left",
225 | 90,
226 | "right",
227 | 95,
228 | "left"
229 | ]
230 | },
231 | "end_index": "12.8",
232 | "font": {
233 | "family": "Segoe ui",
234 | "overstrike": false,
235 | "size": 9,
236 | "slant": "roman",
237 | "underline": false,
238 | "weight": "normal"
239 | },
240 | "start_index": "12.0"
241 | },
242 | "12.31": {
243 | "bind": {
244 | "link": null
245 | },
246 | "config": {
247 | "background": "SystemWindow",
248 | "foreground": "black",
249 | "justify": "left",
250 | "tabs": [
251 | 30,
252 | "right",
253 | 35,
254 | "left",
255 | 60,
256 | "right",
257 | 65,
258 | "left",
259 | 90,
260 | "right",
261 | 95,
262 | "left"
263 | ]
264 | },
265 | "end_index": "13.0",
266 | "font": {
267 | "family": "Segoe ui",
268 | "overstrike": false,
269 | "size": 9,
270 | "slant": "roman",
271 | "underline": false,
272 | "weight": "normal"
273 | },
274 | "start_index": "12.31"
275 | },
276 | "12.8": {
277 | "bind": {
278 | "link": null
279 | },
280 | "config": {
281 | "background": "SystemWindow",
282 | "foreground": "black",
283 | "justify": "left",
284 | "tabs": [
285 | 30,
286 | "right",
287 | 35,
288 | "left",
289 | 60,
290 | "right",
291 | 65,
292 | "left",
293 | 90,
294 | "right",
295 | 95,
296 | "left"
297 | ]
298 | },
299 | "end_index": "12.31",
300 | "font": {
301 | "family": "Segoe ui",
302 | "overstrike": false,
303 | "size": 9,
304 | "slant": "roman",
305 | "underline": false,
306 | "weight": "normal"
307 | },
308 | "start_index": "12.8"
309 | },
310 | "13.0": {
311 | "bind": {
312 | "link": null
313 | },
314 | "config": {
315 | "background": "SystemWindow",
316 | "foreground": "black",
317 | "justify": "left",
318 | "tabs": [
319 | 30,
320 | "right",
321 | 35,
322 | "left",
323 | 60,
324 | "right",
325 | 65,
326 | "left",
327 | 90,
328 | "right",
329 | 95,
330 | "left"
331 | ]
332 | },
333 | "end_index": "13.8",
334 | "font": {
335 | "family": "Segoe ui",
336 | "overstrike": false,
337 | "size": 9,
338 | "slant": "roman",
339 | "underline": false,
340 | "weight": "normal"
341 | },
342 | "start_index": "13.0"
343 | },
344 | "13.31": {
345 | "bind": {
346 | "link": null
347 | },
348 | "config": {
349 | "background": "SystemWindow",
350 | "foreground": "black",
351 | "justify": "left",
352 | "tabs": [
353 | 30,
354 | "right",
355 | 35,
356 | "left",
357 | 60,
358 | "right",
359 | 65,
360 | "left",
361 | 90,
362 | "right",
363 | 95,
364 | "left"
365 | ]
366 | },
367 | "end_index": "14.0",
368 | "font": {
369 | "family": "Segoe ui",
370 | "overstrike": false,
371 | "size": 9,
372 | "slant": "roman",
373 | "underline": false,
374 | "weight": "normal"
375 | },
376 | "start_index": "13.31"
377 | },
378 | "13.8": {
379 | "bind": {
380 | "link": null
381 | },
382 | "config": {
383 | "background": "SystemWindow",
384 | "foreground": "black",
385 | "justify": "left",
386 | "tabs": [
387 | 30,
388 | "right",
389 | 35,
390 | "left",
391 | 60,
392 | "right",
393 | 65,
394 | "left",
395 | 90,
396 | "right",
397 | 95,
398 | "left"
399 | ]
400 | },
401 | "end_index": "13.31",
402 | "font": {
403 | "family": "Segoe ui",
404 | "overstrike": false,
405 | "size": 9,
406 | "slant": "roman",
407 | "underline": false,
408 | "weight": "normal"
409 | },
410 | "start_index": "13.8"
411 | },
412 | "14.0": {
413 | "bind": {
414 | "link": null
415 | },
416 | "config": {
417 | "background": "SystemWindow",
418 | "foreground": "black",
419 | "justify": "left",
420 | "tabs": []
421 | },
422 | "end_index": "15.0",
423 | "font": {
424 | "family": "Segoe ui",
425 | "overstrike": false,
426 | "size": 9,
427 | "slant": "roman",
428 | "underline": false,
429 | "weight": "normal"
430 | },
431 | "start_index": "14.0"
432 | },
433 | "15.0": {
434 | "bind": {
435 | "link": "https://www.python.org"
436 | },
437 | "config": {
438 | "background": "SystemWindow",
439 | "foreground": "blue",
440 | "justify": "left",
441 | "tabs": []
442 | },
443 | "end_index": "15.10",
444 | "font": {
445 | "family": "Segoe ui",
446 | "overstrike": false,
447 | "size": 9,
448 | "slant": "roman",
449 | "underline": true,
450 | "weight": "normal"
451 | },
452 | "start_index": "15.0"
453 | },
454 | "15.10": {
455 | "bind": {
456 | "link": null
457 | },
458 | "config": {
459 | "background": "SystemWindow",
460 | "foreground": "black",
461 | "justify": "left",
462 | "tabs": []
463 | },
464 | "end_index": "16.0",
465 | "font": {
466 | "family": "Segoe ui",
467 | "overstrike": false,
468 | "size": 9,
469 | "slant": "roman",
470 | "underline": false,
471 | "weight": "normal"
472 | },
473 | "start_index": "15.10"
474 | },
475 | "16.0": {
476 | "bind": {
477 | "link": null
478 | },
479 | "config": {
480 | "background": "SystemWindow",
481 | "foreground": "black",
482 | "justify": "left",
483 | "tabs": []
484 | },
485 | "end_index": "16.5",
486 | "font": {
487 | "family": "Segoe ui",
488 | "overstrike": false,
489 | "size": 9,
490 | "slant": "roman",
491 | "underline": false,
492 | "weight": "bold"
493 | },
494 | "start_index": "16.0"
495 | },
496 | "16.5": {
497 | "bind": {
498 | "link": null
499 | },
500 | "config": {
501 | "background": "SystemWindow",
502 | "foreground": "black",
503 | "justify": "left",
504 | "tabs": []
505 | },
506 | "end_index": "17.0",
507 | "font": {
508 | "family": "Segoe ui",
509 | "overstrike": false,
510 | "size": 9,
511 | "slant": "roman",
512 | "underline": false,
513 | "weight": "normal"
514 | },
515 | "start_index": "16.5"
516 | },
517 | "17.0": {
518 | "bind": {
519 | "link": null
520 | },
521 | "config": {
522 | "background": "SystemWindow",
523 | "foreground": "black",
524 | "justify": "left",
525 | "tabs": []
526 | },
527 | "end_index": "17.7",
528 | "font": {
529 | "family": "Segoe ui",
530 | "overstrike": false,
531 | "size": 9,
532 | "slant": "roman",
533 | "underline": false,
534 | "weight": "bold"
535 | },
536 | "start_index": "17.0"
537 | },
538 | "17.7": {
539 | "bind": {
540 | "link": null
541 | },
542 | "config": {
543 | "background": "SystemWindow",
544 | "foreground": "black",
545 | "justify": "left",
546 | "tabs": []
547 | },
548 | "end_index": "18.0",
549 | "font": {
550 | "family": "Segoe ui",
551 | "overstrike": false,
552 | "size": 9,
553 | "slant": "roman",
554 | "underline": false,
555 | "weight": "normal"
556 | },
557 | "start_index": "17.7"
558 | },
559 | "18.0": {
560 | "bind": {
561 | "link": null
562 | },
563 | "config": {
564 | "background": "SystemWindow",
565 | "foreground": "black",
566 | "justify": "left",
567 | "tabs": []
568 | },
569 | "end_index": "18.7",
570 | "font": {
571 | "family": "Segoe ui",
572 | "overstrike": false,
573 | "size": 9,
574 | "slant": "italic",
575 | "underline": false,
576 | "weight": "normal"
577 | },
578 | "start_index": "18.0"
579 | },
580 | "18.7": {
581 | "bind": {
582 | "link": null
583 | },
584 | "config": {
585 | "background": "SystemWindow",
586 | "foreground": "black",
587 | "justify": "left",
588 | "tabs": []
589 | },
590 | "end_index": "19.0",
591 | "font": {
592 | "family": "Segoe ui",
593 | "overstrike": false,
594 | "size": 9,
595 | "slant": "roman",
596 | "underline": false,
597 | "weight": "normal"
598 | },
599 | "start_index": "18.7"
600 | },
601 | "19.0": {
602 | "bind": {
603 | "link": null
604 | },
605 | "config": {
606 | "background": "SystemWindow",
607 | "foreground": "black",
608 | "justify": "left",
609 | "tabs": []
610 | },
611 | "end_index": "19.11",
612 | "font": {
613 | "family": "Segoe ui",
614 | "overstrike": false,
615 | "size": 9,
616 | "slant": "italic",
617 | "underline": false,
618 | "weight": "normal"
619 | },
620 | "start_index": "19.0"
621 | },
622 | "19.11": {
623 | "bind": {
624 | "link": null
625 | },
626 | "config": {
627 | "background": "SystemWindow",
628 | "foreground": "black",
629 | "justify": "left",
630 | "tabs": []
631 | },
632 | "end_index": "20.0",
633 | "font": {
634 | "family": "Segoe ui",
635 | "overstrike": false,
636 | "size": 9,
637 | "slant": "roman",
638 | "underline": false,
639 | "weight": "normal"
640 | },
641 | "start_index": "19.11"
642 | },
643 | "2.0": {
644 | "bind": {
645 | "link": null
646 | },
647 | "config": {
648 | "background": "SystemWindow",
649 | "foreground": "black",
650 | "justify": "left",
651 | "tabs": [
652 | 30,
653 | "right",
654 | 35,
655 | "left"
656 | ]
657 | },
658 | "end_index": "2.3",
659 | "font": {
660 | "family": "Segoe ui",
661 | "overstrike": false,
662 | "size": 9,
663 | "slant": "roman",
664 | "underline": false,
665 | "weight": "normal"
666 | },
667 | "start_index": "2.0"
668 | },
669 | "2.16": {
670 | "bind": {
671 | "link": null
672 | },
673 | "config": {
674 | "background": "SystemWindow",
675 | "foreground": "black",
676 | "justify": "left",
677 | "tabs": [
678 | 30,
679 | "right",
680 | 35,
681 | "left"
682 | ]
683 | },
684 | "end_index": "3.0",
685 | "font": {
686 | "family": "Segoe ui",
687 | "overstrike": false,
688 | "size": 9,
689 | "slant": "roman",
690 | "underline": false,
691 | "weight": "normal"
692 | },
693 | "start_index": "2.16"
694 | },
695 | "2.3": {
696 | "bind": {
697 | "link": null
698 | },
699 | "config": {
700 | "background": "SystemWindow",
701 | "foreground": "black",
702 | "justify": "left",
703 | "tabs": [
704 | 30,
705 | "right",
706 | 35,
707 | "left"
708 | ]
709 | },
710 | "end_index": "2.16",
711 | "font": {
712 | "family": "Segoe ui",
713 | "overstrike": false,
714 | "size": 9,
715 | "slant": "roman",
716 | "underline": false,
717 | "weight": "normal"
718 | },
719 | "start_index": "2.3"
720 | },
721 | "20.0": {
722 | "bind": {
723 | "link": null
724 | },
725 | "config": {
726 | "background": "SystemWindow",
727 | "foreground": "black",
728 | "justify": "left",
729 | "tabs": []
730 | },
731 | "end_index": "20.10",
732 | "font": {
733 | "family": "Segoe ui",
734 | "overstrike": false,
735 | "size": 9,
736 | "slant": "roman",
737 | "underline": true,
738 | "weight": "normal"
739 | },
740 | "start_index": "20.0"
741 | },
742 | "20.10": {
743 | "bind": {
744 | "link": null
745 | },
746 | "config": {
747 | "background": "SystemWindow",
748 | "foreground": "black",
749 | "justify": "left",
750 | "tabs": []
751 | },
752 | "end_index": "21.0",
753 | "font": {
754 | "family": "Segoe ui",
755 | "overstrike": false,
756 | "size": 9,
757 | "slant": "roman",
758 | "underline": false,
759 | "weight": "normal"
760 | },
761 | "start_index": "20.10"
762 | },
763 | "21.0": {
764 | "bind": {
765 | "link": null
766 | },
767 | "config": {
768 | "background": "yellow",
769 | "foreground": "black",
770 | "justify": "left",
771 | "tabs": []
772 | },
773 | "end_index": "21.7",
774 | "font": {
775 | "family": "Segoe ui",
776 | "overstrike": false,
777 | "size": 9,
778 | "slant": "roman",
779 | "underline": false,
780 | "weight": "normal"
781 | },
782 | "start_index": "21.0"
783 | },
784 | "21.7": {
785 | "bind": {
786 | "link": null
787 | },
788 | "config": {
789 | "background": "SystemWindow",
790 | "foreground": "black",
791 | "justify": "left",
792 | "tabs": []
793 | },
794 | "end_index": "22.0",
795 | "font": {
796 | "family": "Segoe ui",
797 | "overstrike": false,
798 | "size": 9,
799 | "slant": "roman",
800 | "underline": false,
801 | "weight": "normal"
802 | },
803 | "start_index": "21.7"
804 | },
805 | "22.0": {
806 | "bind": {
807 | "link": null
808 | },
809 | "config": {
810 | "background": "SystemWindow",
811 | "foreground": "black",
812 | "justify": "left",
813 | "tabs": []
814 | },
815 | "end_index": "22.8",
816 | "font": {
817 | "family": "Segoe ui",
818 | "overstrike": false,
819 | "size": 9,
820 | "slant": "roman",
821 | "underline": false,
822 | "weight": "normal"
823 | },
824 | "start_index": "22.0"
825 | },
826 | "22.8": {
827 | "bind": {
828 | "link": null
829 | },
830 | "config": {
831 | "background": "SystemWindow",
832 | "foreground": "black",
833 | "justify": "left",
834 | "tabs": []
835 | },
836 | "end_index": "23.0",
837 | "font": {
838 | "family": "Segoe ui",
839 | "overstrike": false,
840 | "size": 9,
841 | "slant": "roman",
842 | "underline": false,
843 | "weight": "normal"
844 | },
845 | "start_index": "22.8"
846 | },
847 | "23.0": {
848 | "bind": {
849 | "link": null
850 | },
851 | "config": {
852 | "background": "SystemWindow",
853 | "foreground": "black",
854 | "justify": "left",
855 | "tabs": []
856 | },
857 | "end_index": "24.0",
858 | "font": {
859 | "family": "Segoe ui",
860 | "overstrike": false,
861 | "size": 9,
862 | "slant": "roman",
863 | "underline": false,
864 | "weight": "normal"
865 | },
866 | "start_index": "23.0"
867 | },
868 | "24.0": {
869 | "bind": {
870 | "link": null
871 | },
872 | "config": {
873 | "background": "SystemWindow",
874 | "foreground": "black",
875 | "justify": "left",
876 | "tabs": []
877 | },
878 | "end_index": "25.0",
879 | "font": {
880 | "family": "Segoe ui",
881 | "overstrike": false,
882 | "size": 9,
883 | "slant": "roman",
884 | "underline": false,
885 | "weight": "normal"
886 | },
887 | "start_index": "24.0"
888 | },
889 | "25.0": {
890 | "bind": {
891 | "link": null
892 | },
893 | "config": {
894 | "background": "SystemWindow",
895 | "foreground": "black",
896 | "justify": "left",
897 | "tabs": []
898 | },
899 | "end_index": "26.0",
900 | "font": {
901 | "family": "Segoe ui",
902 | "overstrike": false,
903 | "size": 9,
904 | "slant": "roman",
905 | "underline": false,
906 | "weight": "normal"
907 | },
908 | "start_index": "25.0"
909 | },
910 | "26.0": {
911 | "bind": {
912 | "link": null
913 | },
914 | "config": {
915 | "background": "SystemWindow",
916 | "foreground": "black",
917 | "justify": "left",
918 | "tabs": []
919 | },
920 | "end_index": "27.0",
921 | "font": {
922 | "family": "Segoe ui",
923 | "overstrike": false,
924 | "size": 9,
925 | "slant": "roman",
926 | "underline": false,
927 | "weight": "normal"
928 | },
929 | "start_index": "26.0"
930 | },
931 | "27.0": {
932 | "bind": {
933 | "link": null
934 | },
935 | "config": {
936 | "background": "SystemWindow",
937 | "foreground": "black",
938 | "justify": "left",
939 | "tabs": []
940 | },
941 | "end_index": "28.0",
942 | "font": {
943 | "family": "Courier",
944 | "overstrike": false,
945 | "size": 9,
946 | "slant": "roman",
947 | "underline": false,
948 | "weight": "normal"
949 | },
950 | "start_index": "27.0"
951 | },
952 | "28.0": {
953 | "bind": {
954 | "link": null
955 | },
956 | "config": {
957 | "background": "SystemWindow",
958 | "foreground": "black",
959 | "justify": "left",
960 | "tabs": []
961 | },
962 | "end_index": "29.0",
963 | "font": {
964 | "family": "Segoe ui",
965 | "overstrike": false,
966 | "size": 9,
967 | "slant": "roman",
968 | "underline": false,
969 | "weight": "normal"
970 | },
971 | "start_index": "28.0"
972 | },
973 | "29.0": {
974 | "bind": {
975 | "link": null
976 | },
977 | "config": {
978 | "background": "SystemWindow",
979 | "foreground": "black",
980 | "justify": "left",
981 | "tabs": []
982 | },
983 | "end_index": "30.0",
984 | "font": {
985 | "family": "Segoe ui",
986 | "overstrike": false,
987 | "size": 21,
988 | "slant": "roman",
989 | "underline": false,
990 | "weight": "bold"
991 | },
992 | "start_index": "29.0"
993 | },
994 | "3.0": {
995 | "bind": {
996 | "link": null
997 | },
998 | "config": {
999 | "background": "SystemWindow",
1000 | "foreground": "black",
1001 | "justify": "left",
1002 | "tabs": [
1003 | 30,
1004 | "right",
1005 | 35,
1006 | "left"
1007 | ]
1008 | },
1009 | "end_index": "3.3",
1010 | "font": {
1011 | "family": "Segoe ui",
1012 | "overstrike": false,
1013 | "size": 9,
1014 | "slant": "roman",
1015 | "underline": false,
1016 | "weight": "normal"
1017 | },
1018 | "start_index": "3.0"
1019 | },
1020 | "3.16": {
1021 | "bind": {
1022 | "link": null
1023 | },
1024 | "config": {
1025 | "background": "SystemWindow",
1026 | "foreground": "black",
1027 | "justify": "left",
1028 | "tabs": [
1029 | 30,
1030 | "right",
1031 | 35,
1032 | "left"
1033 | ]
1034 | },
1035 | "end_index": "4.0",
1036 | "font": {
1037 | "family": "Segoe ui",
1038 | "overstrike": false,
1039 | "size": 9,
1040 | "slant": "roman",
1041 | "underline": false,
1042 | "weight": "normal"
1043 | },
1044 | "start_index": "3.16"
1045 | },
1046 | "3.3": {
1047 | "bind": {
1048 | "link": null
1049 | },
1050 | "config": {
1051 | "background": "SystemWindow",
1052 | "foreground": "black",
1053 | "justify": "left",
1054 | "tabs": [
1055 | 30,
1056 | "right",
1057 | 35,
1058 | "left"
1059 | ]
1060 | },
1061 | "end_index": "3.16",
1062 | "font": {
1063 | "family": "Segoe ui",
1064 | "overstrike": false,
1065 | "size": 9,
1066 | "slant": "roman",
1067 | "underline": false,
1068 | "weight": "normal"
1069 | },
1070 | "start_index": "3.3"
1071 | },
1072 | "30.0": {
1073 | "bind": {
1074 | "link": null
1075 | },
1076 | "config": {
1077 | "background": "SystemWindow",
1078 | "foreground": "black",
1079 | "justify": "left",
1080 | "tabs": []
1081 | },
1082 | "end_index": "31.0",
1083 | "font": {
1084 | "family": "Segoe ui",
1085 | "overstrike": false,
1086 | "size": 9,
1087 | "slant": "roman",
1088 | "underline": false,
1089 | "weight": "normal"
1090 | },
1091 | "start_index": "30.0"
1092 | },
1093 | "31.0": {
1094 | "bind": {
1095 | "link": null
1096 | },
1097 | "config": {
1098 | "background": "SystemWindow",
1099 | "foreground": "black",
1100 | "justify": "left",
1101 | "tabs": []
1102 | },
1103 | "end_index": "32.0",
1104 | "font": {
1105 | "family": "Segoe ui",
1106 | "overstrike": false,
1107 | "size": 16,
1108 | "slant": "roman",
1109 | "underline": false,
1110 | "weight": "bold"
1111 | },
1112 | "start_index": "31.0"
1113 | },
1114 | "32.0": {
1115 | "bind": {
1116 | "link": null
1117 | },
1118 | "config": {
1119 | "background": "SystemWindow",
1120 | "foreground": "black",
1121 | "justify": "left",
1122 | "tabs": []
1123 | },
1124 | "end_index": "33.0",
1125 | "font": {
1126 | "family": "Segoe ui",
1127 | "overstrike": false,
1128 | "size": 9,
1129 | "slant": "roman",
1130 | "underline": false,
1131 | "weight": "normal"
1132 | },
1133 | "start_index": "32.0"
1134 | },
1135 | "33.0": {
1136 | "bind": {
1137 | "link": null
1138 | },
1139 | "config": {
1140 | "background": "SystemWindow",
1141 | "foreground": "black",
1142 | "justify": "left",
1143 | "tabs": []
1144 | },
1145 | "end_index": "34.0",
1146 | "font": {
1147 | "family": "Segoe ui",
1148 | "overstrike": false,
1149 | "size": 12,
1150 | "slant": "roman",
1151 | "underline": false,
1152 | "weight": "bold"
1153 | },
1154 | "start_index": "33.0"
1155 | },
1156 | "34.0": {
1157 | "bind": {
1158 | "link": null
1159 | },
1160 | "config": {
1161 | "background": "SystemWindow",
1162 | "foreground": "black",
1163 | "justify": "left",
1164 | "tabs": []
1165 | },
1166 | "end_index": "35.0",
1167 | "font": {
1168 | "family": "Segoe ui",
1169 | "overstrike": false,
1170 | "size": 9,
1171 | "slant": "roman",
1172 | "underline": false,
1173 | "weight": "normal"
1174 | },
1175 | "start_index": "34.0"
1176 | },
1177 | "35.0": {
1178 | "bind": {
1179 | "link": null
1180 | },
1181 | "config": {
1182 | "background": "SystemWindow",
1183 | "foreground": "black",
1184 | "justify": "left",
1185 | "tabs": []
1186 | },
1187 | "end_index": "36.0",
1188 | "font": {
1189 | "family": "Segoe ui",
1190 | "overstrike": false,
1191 | "size": 11,
1192 | "slant": "roman",
1193 | "underline": false,
1194 | "weight": "bold"
1195 | },
1196 | "start_index": "35.0"
1197 | },
1198 | "36.0": {
1199 | "bind": {
1200 | "link": null
1201 | },
1202 | "config": {
1203 | "background": "SystemWindow",
1204 | "foreground": "black",
1205 | "justify": "left",
1206 | "tabs": []
1207 | },
1208 | "end_index": "37.0",
1209 | "font": {
1210 | "family": "Segoe ui",
1211 | "overstrike": false,
1212 | "size": 9,
1213 | "slant": "roman",
1214 | "underline": false,
1215 | "weight": "normal"
1216 | },
1217 | "start_index": "36.0"
1218 | },
1219 | "37.0": {
1220 | "bind": {
1221 | "link": null
1222 | },
1223 | "config": {
1224 | "background": "SystemWindow",
1225 | "foreground": "black",
1226 | "justify": "left",
1227 | "tabs": []
1228 | },
1229 | "end_index": "38.0",
1230 | "font": {
1231 | "family": "Segoe ui",
1232 | "overstrike": false,
1233 | "size": 8,
1234 | "slant": "roman",
1235 | "underline": false,
1236 | "weight": "bold"
1237 | },
1238 | "start_index": "37.0"
1239 | },
1240 | "38.0": {
1241 | "bind": {
1242 | "link": null
1243 | },
1244 | "config": {
1245 | "background": "SystemWindow",
1246 | "foreground": "black",
1247 | "justify": "left",
1248 | "tabs": []
1249 | },
1250 | "end_index": "39.0",
1251 | "font": {
1252 | "family": "Segoe ui",
1253 | "overstrike": false,
1254 | "size": 9,
1255 | "slant": "roman",
1256 | "underline": false,
1257 | "weight": "normal"
1258 | },
1259 | "start_index": "38.0"
1260 | },
1261 | "39.0": {
1262 | "bind": {
1263 | "link": null
1264 | },
1265 | "config": {
1266 | "background": "SystemWindow",
1267 | "foreground": "black",
1268 | "justify": "left",
1269 | "tabs": []
1270 | },
1271 | "end_index": "40.0",
1272 | "font": {
1273 | "family": "Segoe ui",
1274 | "overstrike": false,
1275 | "size": 7,
1276 | "slant": "roman",
1277 | "underline": false,
1278 | "weight": "bold"
1279 | },
1280 | "start_index": "39.0"
1281 | },
1282 | "4.0": {
1283 | "bind": {
1284 | "link": null
1285 | },
1286 | "config": {
1287 | "background": "SystemWindow",
1288 | "foreground": "black",
1289 | "justify": "left",
1290 | "tabs": [
1291 | 30,
1292 | "right",
1293 | 35,
1294 | "left",
1295 | 60,
1296 | "right",
1297 | 65,
1298 | "left"
1299 | ]
1300 | },
1301 | "end_index": "5.0",
1302 | "font": {
1303 | "family": "Segoe ui",
1304 | "overstrike": false,
1305 | "size": 9,
1306 | "slant": "roman",
1307 | "underline": false,
1308 | "weight": "normal"
1309 | },
1310 | "start_index": "4.0"
1311 | },
1312 | "40.0": {
1313 | "bind": {
1314 | "link": null
1315 | },
1316 | "config": {
1317 | "background": "SystemWindow",
1318 | "foreground": "black",
1319 | "justify": "left",
1320 | "tabs": []
1321 | },
1322 | "end_index": "end",
1323 | "font": {
1324 | "family": "Segoe ui",
1325 | "overstrike": false,
1326 | "size": 9,
1327 | "slant": "roman",
1328 | "underline": false,
1329 | "weight": "normal"
1330 | },
1331 | "start_index": "40.0"
1332 | },
1333 | "5.0": {
1334 | "bind": {
1335 | "link": null
1336 | },
1337 | "config": {
1338 | "background": "SystemWindow",
1339 | "foreground": "black",
1340 | "justify": "left",
1341 | "tabs": [
1342 | 30,
1343 | "right",
1344 | 35,
1345 | "left",
1346 | 60,
1347 | "right",
1348 | 65,
1349 | "left"
1350 | ]
1351 | },
1352 | "end_index": "5.5",
1353 | "font": {
1354 | "family": "Segoe ui",
1355 | "overstrike": false,
1356 | "size": 9,
1357 | "slant": "roman",
1358 | "underline": false,
1359 | "weight": "normal"
1360 | },
1361 | "start_index": "5.0"
1362 | },
1363 | "5.18": {
1364 | "bind": {
1365 | "link": null
1366 | },
1367 | "config": {
1368 | "background": "SystemWindow",
1369 | "foreground": "black",
1370 | "justify": "left",
1371 | "tabs": [
1372 | 30,
1373 | "right",
1374 | 35,
1375 | "left",
1376 | 60,
1377 | "right",
1378 | 65,
1379 | "left"
1380 | ]
1381 | },
1382 | "end_index": "6.0",
1383 | "font": {
1384 | "family": "Segoe ui",
1385 | "overstrike": false,
1386 | "size": 9,
1387 | "slant": "roman",
1388 | "underline": false,
1389 | "weight": "normal"
1390 | },
1391 | "start_index": "5.18"
1392 | },
1393 | "5.5": {
1394 | "bind": {
1395 | "link": null
1396 | },
1397 | "config": {
1398 | "background": "SystemWindow",
1399 | "foreground": "black",
1400 | "justify": "left",
1401 | "tabs": [
1402 | 30,
1403 | "right",
1404 | 35,
1405 | "left",
1406 | 60,
1407 | "right",
1408 | 65,
1409 | "left"
1410 | ]
1411 | },
1412 | "end_index": "5.18",
1413 | "font": {
1414 | "family": "Segoe ui",
1415 | "overstrike": false,
1416 | "size": 9,
1417 | "slant": "roman",
1418 | "underline": false,
1419 | "weight": "normal"
1420 | },
1421 | "start_index": "5.5"
1422 | },
1423 | "6.0": {
1424 | "bind": {
1425 | "link": null
1426 | },
1427 | "config": {
1428 | "background": "SystemWindow",
1429 | "foreground": "black",
1430 | "justify": "left",
1431 | "tabs": [
1432 | 30,
1433 | "right",
1434 | 35,
1435 | "left",
1436 | 60,
1437 | "right",
1438 | 65,
1439 | "left"
1440 | ]
1441 | },
1442 | "end_index": "6.5",
1443 | "font": {
1444 | "family": "Segoe ui",
1445 | "overstrike": false,
1446 | "size": 9,
1447 | "slant": "roman",
1448 | "underline": false,
1449 | "weight": "normal"
1450 | },
1451 | "start_index": "6.0"
1452 | },
1453 | "6.18": {
1454 | "bind": {
1455 | "link": null
1456 | },
1457 | "config": {
1458 | "background": "SystemWindow",
1459 | "foreground": "black",
1460 | "justify": "left",
1461 | "tabs": [
1462 | 30,
1463 | "right",
1464 | 35,
1465 | "left",
1466 | 60,
1467 | "right",
1468 | 65,
1469 | "left"
1470 | ]
1471 | },
1472 | "end_index": "7.0",
1473 | "font": {
1474 | "family": "Segoe ui",
1475 | "overstrike": false,
1476 | "size": 9,
1477 | "slant": "roman",
1478 | "underline": false,
1479 | "weight": "normal"
1480 | },
1481 | "start_index": "6.18"
1482 | },
1483 | "6.5": {
1484 | "bind": {
1485 | "link": null
1486 | },
1487 | "config": {
1488 | "background": "SystemWindow",
1489 | "foreground": "black",
1490 | "justify": "left",
1491 | "tabs": [
1492 | 30,
1493 | "right",
1494 | 35,
1495 | "left",
1496 | 60,
1497 | "right",
1498 | 65,
1499 | "left"
1500 | ]
1501 | },
1502 | "end_index": "6.18",
1503 | "font": {
1504 | "family": "Segoe ui",
1505 | "overstrike": false,
1506 | "size": 9,
1507 | "slant": "roman",
1508 | "underline": false,
1509 | "weight": "normal"
1510 | },
1511 | "start_index": "6.5"
1512 | },
1513 | "7.0": {
1514 | "bind": {
1515 | "link": null
1516 | },
1517 | "config": {
1518 | "background": "SystemWindow",
1519 | "foreground": "black",
1520 | "justify": "left",
1521 | "tabs": []
1522 | },
1523 | "end_index": "8.0",
1524 | "font": {
1525 | "family": "Segoe ui",
1526 | "overstrike": false,
1527 | "size": 9,
1528 | "slant": "roman",
1529 | "underline": false,
1530 | "weight": "normal"
1531 | },
1532 | "start_index": "7.0"
1533 | },
1534 | "8.0": {
1535 | "bind": {
1536 | "link": null
1537 | },
1538 | "config": {
1539 | "background": "SystemWindow",
1540 | "foreground": "black",
1541 | "justify": "left",
1542 | "tabs": [
1543 | 30,
1544 | "right",
1545 | 35,
1546 | "left"
1547 | ]
1548 | },
1549 | "end_index": "8.4",
1550 | "font": {
1551 | "family": "Segoe ui",
1552 | "overstrike": false,
1553 | "size": 9,
1554 | "slant": "roman",
1555 | "underline": false,
1556 | "weight": "normal"
1557 | },
1558 | "start_index": "8.0"
1559 | },
1560 | "8.27": {
1561 | "bind": {
1562 | "link": null
1563 | },
1564 | "config": {
1565 | "background": "SystemWindow",
1566 | "foreground": "black",
1567 | "justify": "left",
1568 | "tabs": [
1569 | 30,
1570 | "right",
1571 | 35,
1572 | "left"
1573 | ]
1574 | },
1575 | "end_index": "9.0",
1576 | "font": {
1577 | "family": "Segoe ui",
1578 | "overstrike": false,
1579 | "size": 9,
1580 | "slant": "roman",
1581 | "underline": false,
1582 | "weight": "normal"
1583 | },
1584 | "start_index": "8.27"
1585 | },
1586 | "8.4": {
1587 | "bind": {
1588 | "link": null
1589 | },
1590 | "config": {
1591 | "background": "SystemWindow",
1592 | "foreground": "black",
1593 | "justify": "left",
1594 | "tabs": [
1595 | 30,
1596 | "right",
1597 | 35,
1598 | "left"
1599 | ]
1600 | },
1601 | "end_index": "8.27",
1602 | "font": {
1603 | "family": "Segoe ui",
1604 | "overstrike": false,
1605 | "size": 9,
1606 | "slant": "roman",
1607 | "underline": false,
1608 | "weight": "normal"
1609 | },
1610 | "start_index": "8.4"
1611 | },
1612 | "9.0": {
1613 | "bind": {
1614 | "link": null
1615 | },
1616 | "config": {
1617 | "background": "SystemWindow",
1618 | "foreground": "black",
1619 | "justify": "left",
1620 | "tabs": [
1621 | 30,
1622 | "right",
1623 | 35,
1624 | "left"
1625 | ]
1626 | },
1627 | "end_index": "9.4",
1628 | "font": {
1629 | "family": "Segoe ui",
1630 | "overstrike": false,
1631 | "size": 9,
1632 | "slant": "roman",
1633 | "underline": false,
1634 | "weight": "normal"
1635 | },
1636 | "start_index": "9.0"
1637 | },
1638 | "9.27": {
1639 | "bind": {
1640 | "link": null
1641 | },
1642 | "config": {
1643 | "background": "SystemWindow",
1644 | "foreground": "black",
1645 | "justify": "left",
1646 | "tabs": [
1647 | 30,
1648 | "right",
1649 | 35,
1650 | "left"
1651 | ]
1652 | },
1653 | "end_index": "10.0",
1654 | "font": {
1655 | "family": "Segoe ui",
1656 | "overstrike": false,
1657 | "size": 9,
1658 | "slant": "roman",
1659 | "underline": false,
1660 | "weight": "normal"
1661 | },
1662 | "start_index": "9.27"
1663 | },
1664 | "9.4": {
1665 | "bind": {
1666 | "link": null
1667 | },
1668 | "config": {
1669 | "background": "SystemWindow",
1670 | "foreground": "black",
1671 | "justify": "left",
1672 | "tabs": [
1673 | 30,
1674 | "right",
1675 | 35,
1676 | "left"
1677 | ]
1678 | },
1679 | "end_index": "9.27",
1680 | "font": {
1681 | "family": "Segoe ui",
1682 | "overstrike": false,
1683 | "size": 9,
1684 | "slant": "roman",
1685 | "underline": false,
1686 | "weight": "normal"
1687 | },
1688 | "start_index": "9.4"
1689 | }
1690 | }
--------------------------------------------------------------------------------