tdrpa.tdworker 1.2.13.2__py312-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. tdrpa/_tdxlwings/__init__.py +193 -0
  2. tdrpa/_tdxlwings/__pycache__/__init__.cpython-311.pyc +0 -0
  3. tdrpa/_tdxlwings/__pycache__/__init__.cpython-38.pyc +0 -0
  4. tdrpa/_tdxlwings/__pycache__/_win32patch.cpython-311.pyc +0 -0
  5. tdrpa/_tdxlwings/__pycache__/_win32patch.cpython-38.pyc +0 -0
  6. tdrpa/_tdxlwings/__pycache__/_xlwindows.cpython-311.pyc +0 -0
  7. tdrpa/_tdxlwings/__pycache__/_xlwindows.cpython-38.pyc +0 -0
  8. tdrpa/_tdxlwings/__pycache__/apps.cpython-311.pyc +0 -0
  9. tdrpa/_tdxlwings/__pycache__/apps.cpython-38.pyc +0 -0
  10. tdrpa/_tdxlwings/__pycache__/base_classes.cpython-311.pyc +0 -0
  11. tdrpa/_tdxlwings/__pycache__/base_classes.cpython-38.pyc +0 -0
  12. tdrpa/_tdxlwings/__pycache__/com_server.cpython-311.pyc +0 -0
  13. tdrpa/_tdxlwings/__pycache__/com_server.cpython-38.pyc +0 -0
  14. tdrpa/_tdxlwings/__pycache__/constants.cpython-311.pyc +0 -0
  15. tdrpa/_tdxlwings/__pycache__/constants.cpython-38.pyc +0 -0
  16. tdrpa/_tdxlwings/__pycache__/expansion.cpython-311.pyc +0 -0
  17. tdrpa/_tdxlwings/__pycache__/expansion.cpython-38.pyc +0 -0
  18. tdrpa/_tdxlwings/__pycache__/main.cpython-311.pyc +0 -0
  19. tdrpa/_tdxlwings/__pycache__/main.cpython-38.pyc +0 -0
  20. tdrpa/_tdxlwings/__pycache__/udfs.cpython-311.pyc +0 -0
  21. tdrpa/_tdxlwings/__pycache__/udfs.cpython-38.pyc +0 -0
  22. tdrpa/_tdxlwings/__pycache__/utils.cpython-311.pyc +0 -0
  23. tdrpa/_tdxlwings/__pycache__/utils.cpython-38.pyc +0 -0
  24. tdrpa/_tdxlwings/_win32patch.py +90 -0
  25. tdrpa/_tdxlwings/_xlmac.py +2240 -0
  26. tdrpa/_tdxlwings/_xlwindows.py +2518 -0
  27. tdrpa/_tdxlwings/addin/Dictionary.cls +474 -0
  28. tdrpa/_tdxlwings/addin/IWebAuthenticator.cls +71 -0
  29. tdrpa/_tdxlwings/addin/WebClient.cls +772 -0
  30. tdrpa/_tdxlwings/addin/WebHelpers.bas +3203 -0
  31. tdrpa/_tdxlwings/addin/WebRequest.cls +875 -0
  32. tdrpa/_tdxlwings/addin/WebResponse.cls +453 -0
  33. tdrpa/_tdxlwings/addin/xlwings.xlam +0 -0
  34. tdrpa/_tdxlwings/apps.py +35 -0
  35. tdrpa/_tdxlwings/base_classes.py +1092 -0
  36. tdrpa/_tdxlwings/cli.py +1306 -0
  37. tdrpa/_tdxlwings/com_server.py +385 -0
  38. tdrpa/_tdxlwings/constants.py +3080 -0
  39. tdrpa/_tdxlwings/conversion/__init__.py +103 -0
  40. tdrpa/_tdxlwings/conversion/framework.py +147 -0
  41. tdrpa/_tdxlwings/conversion/numpy_conv.py +34 -0
  42. tdrpa/_tdxlwings/conversion/pandas_conv.py +184 -0
  43. tdrpa/_tdxlwings/conversion/standard.py +321 -0
  44. tdrpa/_tdxlwings/expansion.py +83 -0
  45. tdrpa/_tdxlwings/ext/__init__.py +3 -0
  46. tdrpa/_tdxlwings/ext/sql.py +73 -0
  47. tdrpa/_tdxlwings/html/xlwings-alert.html +71 -0
  48. tdrpa/_tdxlwings/js/xlwings.js +577 -0
  49. tdrpa/_tdxlwings/js/xlwings.ts +729 -0
  50. tdrpa/_tdxlwings/mac_dict.py +6399 -0
  51. tdrpa/_tdxlwings/main.py +5205 -0
  52. tdrpa/_tdxlwings/mistune/__init__.py +63 -0
  53. tdrpa/_tdxlwings/mistune/block_parser.py +366 -0
  54. tdrpa/_tdxlwings/mistune/inline_parser.py +216 -0
  55. tdrpa/_tdxlwings/mistune/markdown.py +84 -0
  56. tdrpa/_tdxlwings/mistune/renderers.py +220 -0
  57. tdrpa/_tdxlwings/mistune/scanner.py +121 -0
  58. tdrpa/_tdxlwings/mistune/util.py +41 -0
  59. tdrpa/_tdxlwings/pro/__init__.py +40 -0
  60. tdrpa/_tdxlwings/pro/_xlcalamine.py +536 -0
  61. tdrpa/_tdxlwings/pro/_xlofficejs.py +146 -0
  62. tdrpa/_tdxlwings/pro/_xlremote.py +1293 -0
  63. tdrpa/_tdxlwings/pro/custom_functions_code.js +150 -0
  64. tdrpa/_tdxlwings/pro/embedded_code.py +60 -0
  65. tdrpa/_tdxlwings/pro/udfs_officejs.py +549 -0
  66. tdrpa/_tdxlwings/pro/utils.py +199 -0
  67. tdrpa/_tdxlwings/quickstart.xlsm +0 -0
  68. tdrpa/_tdxlwings/quickstart_addin.xlam +0 -0
  69. tdrpa/_tdxlwings/quickstart_addin_ribbon.xlam +0 -0
  70. tdrpa/_tdxlwings/quickstart_fastapi/main.py +47 -0
  71. tdrpa/_tdxlwings/quickstart_fastapi/requirements.txt +3 -0
  72. tdrpa/_tdxlwings/quickstart_standalone.xlsm +0 -0
  73. tdrpa/_tdxlwings/reports.py +12 -0
  74. tdrpa/_tdxlwings/rest/__init__.py +1 -0
  75. tdrpa/_tdxlwings/rest/api.py +368 -0
  76. tdrpa/_tdxlwings/rest/serializers.py +103 -0
  77. tdrpa/_tdxlwings/server.py +14 -0
  78. tdrpa/_tdxlwings/udfs.py +775 -0
  79. tdrpa/_tdxlwings/utils.py +777 -0
  80. tdrpa/_tdxlwings/xlwings-0.31.6.applescript +30 -0
  81. tdrpa/_tdxlwings/xlwings.bas +2061 -0
  82. tdrpa/_tdxlwings/xlwings_custom_addin.bas +2042 -0
  83. tdrpa/_tdxlwings/xlwingslib.cp38-win_amd64.pyd +0 -0
  84. tdrpa/tdworker/__init__.pyi +12 -0
  85. tdrpa/tdworker/_clip.pyi +50 -0
  86. tdrpa/tdworker/_excel.pyi +743 -0
  87. tdrpa/tdworker/_file.pyi +77 -0
  88. tdrpa/tdworker/_img.pyi +226 -0
  89. tdrpa/tdworker/_network.pyi +94 -0
  90. tdrpa/tdworker/_os.pyi +47 -0
  91. tdrpa/tdworker/_sp.pyi +21 -0
  92. tdrpa/tdworker/_w.pyi +129 -0
  93. tdrpa/tdworker/_web.pyi +995 -0
  94. tdrpa/tdworker/_winE.pyi +228 -0
  95. tdrpa/tdworker/_winK.pyi +74 -0
  96. tdrpa/tdworker/_winM.pyi +117 -0
  97. tdrpa/tdworker.cp312-win_amd64.pyd +0 -0
  98. tdrpa_tdworker-1.2.13.2.dist-info/METADATA +38 -0
  99. tdrpa_tdworker-1.2.13.2.dist-info/RECORD +101 -0
  100. tdrpa_tdworker-1.2.13.2.dist-info/WHEEL +5 -0
  101. tdrpa_tdworker-1.2.13.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,63 @@
1
+ from .markdown import Markdown
2
+ from .block_parser import BlockParser
3
+ from .inline_parser import InlineParser
4
+ from .renderers import AstRenderer, HTMLRenderer
5
+ from .plugins import PLUGINS
6
+ from .util import escape, escape_url, escape_html, unikey
7
+
8
+
9
+ def create_markdown(escape=True, hard_wrap=False, renderer=None, plugins=None):
10
+ """Create a Markdown instance based on the given condition.
11
+
12
+ :param escape: Boolean. If using html renderer, escape html.
13
+ :param hard_wrap: Boolean. Break every new line into ``<br>``.
14
+ :param renderer: renderer instance or string of ``html`` and ``ast``.
15
+ :param plugins: List of plugins, string or callable.
16
+
17
+ This method is used when you want to re-use a Markdown instance::
18
+
19
+ markdown = create_markdown(
20
+ escape=False,
21
+ renderer='html',
22
+ plugins=['url', 'strikethrough', 'footnotes', 'table'],
23
+ )
24
+ # re-use markdown function
25
+ markdown('.... your text ...')
26
+ """
27
+ if renderer is None or renderer == 'html':
28
+ renderer = HTMLRenderer(escape=escape)
29
+ elif renderer == 'ast':
30
+ renderer = AstRenderer()
31
+
32
+ if plugins:
33
+ _plugins = []
34
+ for p in plugins:
35
+ if isinstance(p, str):
36
+ _plugins.append(PLUGINS[p])
37
+ else:
38
+ _plugins.append(p)
39
+ plugins = _plugins
40
+
41
+ return Markdown(renderer, inline=InlineParser(renderer, hard_wrap=hard_wrap), plugins=plugins)
42
+
43
+
44
+ html = create_markdown(
45
+ escape=False,
46
+ renderer='html',
47
+ plugins=['strikethrough', 'footnotes', 'table'],
48
+ )
49
+
50
+
51
+ def markdown(text, escape=True, renderer=None, plugins=None):
52
+ md = create_markdown(escape=escape, renderer=renderer, plugins=plugins)
53
+ return md(text)
54
+
55
+
56
+ __all__ = [
57
+ 'Markdown', 'AstRenderer', 'HTMLRenderer',
58
+ 'BlockParser', 'InlineParser',
59
+ 'escape', 'escape_url', 'escape_html', 'unikey',
60
+ 'html', 'create_markdown', 'markdown'
61
+ ]
62
+
63
+ __version__ = '2.0.2'
@@ -0,0 +1,366 @@
1
+ import re
2
+ from .scanner import ScannerParser, Matcher
3
+ from .inline_parser import ESCAPE_CHAR, LINK_LABEL
4
+ from .util import unikey
5
+
6
+ _NEW_LINES = re.compile(r'\r\n|\r')
7
+ _BLANK_LINES = re.compile(r'^ +$', re.M)
8
+
9
+ _TRIM_4 = re.compile(r'^ {1,4}')
10
+ _EXPAND_TAB = re.compile(r'^( {0,3})\t', flags=re.M)
11
+ _INDENT_CODE_TRIM = re.compile(r'^ {1,4}', flags=re.M)
12
+ _BLOCK_QUOTE_TRIM = re.compile(r'^ {0,1}', flags=re.M)
13
+ _BLOCK_QUOTE_LEADING = re.compile(r'^ *>', flags=re.M)
14
+ _BLOCK_TAGS = {
15
+ 'address', 'article', 'aside', 'base', 'basefont', 'blockquote',
16
+ 'body', 'caption', 'center', 'col', 'colgroup', 'dd', 'details',
17
+ 'dialog', 'dir', 'div', 'dl', 'dt', 'fieldset', 'figcaption',
18
+ 'figure', 'footer', 'form', 'frame', 'frameset', 'h1', 'h2', 'h3',
19
+ 'h4', 'h5', 'h6', 'head', 'header', 'hr', 'html', 'iframe',
20
+ 'legend', 'li', 'link', 'main', 'menu', 'menuitem', 'meta', 'nav',
21
+ 'noframes', 'ol', 'optgroup', 'option', 'p', 'param', 'section',
22
+ 'source', 'summary', 'table', 'tbody', 'td', 'tfoot', 'th', 'thead',
23
+ 'title', 'tr', 'track', 'ul'
24
+ }
25
+ _BLOCK_HTML_RULE6 = (
26
+ r'</?(?:' + '|'.join(_BLOCK_TAGS) + r')'
27
+ r'(?: +|\n|/?>)[\s\S]*?'
28
+ r'(?:\n{2,}|\n*$)'
29
+ )
30
+ _BLOCK_HTML_RULE7 = (
31
+ # open tag
32
+ r'<(?!script|pre|style)([a-z][\w-]*)(?:'
33
+ r' +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"|'
34
+ r''' *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?'''
35
+ r')*? */?>(?=\s*\n)[\s\S]*?(?:\n{2,}|\n*$)|'
36
+ # close tag
37
+ r'</(?!script|pre|style)[a-z][\w-]*\s*>(?=\s*\n)[\s\S]*?(?:\n{2,}|\n*$)'
38
+ )
39
+
40
+ _PARAGRAPH_SPLIT = re.compile(r'\n{2,}')
41
+ _LIST_BULLET = re.compile(r'^ *([\*\+-]|\d+[.)])')
42
+
43
+
44
+ class BlockParser(ScannerParser):
45
+ scanner_cls = Matcher
46
+
47
+ NEWLINE = re.compile(r'\n+')
48
+ DEF_LINK = re.compile(
49
+ r' {0,3}\[(' + LINK_LABEL + r')\]:(?:[ \t]*\n)?[ \t]*'
50
+ r'<?([^\s>]+)>?(?:[ \t]*\n)?'
51
+ r'(?: +["(]([^\n]+)[")])? *\n+'
52
+ )
53
+
54
+ AXT_HEADING = re.compile(
55
+ r' {0,3}(#{1,6})(?!#+)(?: *\n+|'
56
+ r'\s+([^\n]*?)(?:\n+|\s+?#+\s*\n+))'
57
+ )
58
+ SETEX_HEADING = re.compile(r'([^\n]+)\n *(=|-){2,}[ \t]*\n+')
59
+ THEMATIC_BREAK = re.compile(
60
+ r' {0,3}((?:-[ \t]*){3,}|'
61
+ r'(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})\n+'
62
+ )
63
+
64
+ INDENT_CODE = re.compile(r'(?:\n*)(?:(?: {4}| *\t)[^\n]+\n*)+')
65
+
66
+ FENCED_CODE = re.compile(
67
+ r'( {0,3})(`{3,}|~{3,})([^`\n]*)\n'
68
+ r'(?:|([\s\S]*?)\n)'
69
+ r'(?: {0,3}\2[~`]* *\n+|$)'
70
+ )
71
+ BLOCK_QUOTE = re.compile(
72
+ r'(?: {0,3}>[^\n]*\n)+'
73
+ )
74
+ LIST_START = re.compile(
75
+ r'( {0,3})([\*\+-]|\d{1,9}[.)])(?:[ \t]*|[ \t][^\n]+)\n+'
76
+ )
77
+
78
+ BLOCK_HTML = re.compile((
79
+ r' {0,3}(?:'
80
+ r'<(script|pre|style)[\s>][\s\S]*?(?:</\1>[^\n]*\n+|$)|'
81
+ r'<!--(?!-?>)[\s\S]*?-->[^\n]*\n+|'
82
+ r'<\?[\s\S]*?\?>[^\n]*\n+|'
83
+ r'<![A-Z][\s\S]*?>[^\n]*\n+|'
84
+ r'<!\[CDATA\[[\s\S]*?\]\]>[^\n]*\n+'
85
+ r'|' + _BLOCK_HTML_RULE6 + '|' + _BLOCK_HTML_RULE7 + ')'
86
+ ), re.I)
87
+
88
+ LIST_MAX_DEPTH = 6
89
+ BLOCK_QUOTE_MAX_DEPTH = 6
90
+ RULE_NAMES = (
91
+ 'newline', 'thematic_break',
92
+ 'fenced_code', 'indent_code',
93
+ 'block_quote', 'block_html',
94
+ 'list_start',
95
+ 'axt_heading', 'setex_heading',
96
+ 'def_link',
97
+ )
98
+
99
+ def __init__(self):
100
+ super(BlockParser, self).__init__()
101
+ self.block_quote_rules = list(self.RULE_NAMES)
102
+ self.list_rules = list(self.RULE_NAMES)
103
+
104
+ def parse_newline(self, m, state):
105
+ return {'type': 'newline', 'blank': True}
106
+
107
+ def parse_thematic_break(self, m, state):
108
+ return {'type': 'thematic_break', 'blank': True}
109
+
110
+ def parse_indent_code(self, m, state):
111
+ text = expand_leading_tab(m.group(0))
112
+ code = _INDENT_CODE_TRIM.sub('', text)
113
+ code = code.lstrip('\n')
114
+ return self.tokenize_block_code(code, None, state)
115
+
116
+ def parse_fenced_code(self, m, state):
117
+ info = ESCAPE_CHAR.sub(r'\1', m.group(3))
118
+ spaces = m.group(1)
119
+ code = m.group(4) or ''
120
+ if spaces and code:
121
+ _trim_pattern = re.compile('^' + spaces, re.M)
122
+ code = _trim_pattern.sub('', code)
123
+ return self.tokenize_block_code(code + '\n', info, state)
124
+
125
+ def tokenize_block_code(self, code, info, state):
126
+ token = {'type': 'block_code', 'raw': code}
127
+ if info:
128
+ token['params'] = (info, )
129
+ return token
130
+
131
+ def parse_axt_heading(self, m, state):
132
+ level = len(m.group(1))
133
+ text = m.group(2) or ''
134
+ text = text.strip()
135
+ if set(text) == {'#'}:
136
+ text = ''
137
+ return self.tokenize_heading(text, level, state)
138
+
139
+ def parse_setex_heading(self, m, state):
140
+ level = 1 if m.group(2) == '=' else 2
141
+ text = m.group(1)
142
+ text = text.strip()
143
+ return self.tokenize_heading(text, level, state)
144
+
145
+ def tokenize_heading(self, text, level, state):
146
+ return {'type': 'heading', 'text': text, 'params': (level,)}
147
+
148
+ def get_block_quote_rules(self, depth):
149
+ if depth > self.BLOCK_QUOTE_MAX_DEPTH - 1:
150
+ rules = list(self.block_quote_rules)
151
+ rules.remove('block_quote')
152
+ return rules
153
+ return self.block_quote_rules
154
+
155
+ def parse_block_quote(self, m, state):
156
+ depth = state.get('block_quote_depth', 0) + 1
157
+ state['block_quote_depth'] = depth
158
+
159
+ # normalize block quote text
160
+ text = _BLOCK_QUOTE_LEADING.sub('', m.group(0))
161
+ text = expand_leading_tab(text)
162
+ text = _BLOCK_QUOTE_TRIM.sub('', text)
163
+ text = cleanup_lines(text)
164
+
165
+ rules = self.get_block_quote_rules(depth)
166
+ children = self.parse(text, state, rules)
167
+ state['block_quote_depth'] = depth - 1
168
+ return {'type': 'block_quote', 'children': children}
169
+
170
+ def get_list_rules(self, depth):
171
+ if depth > self.LIST_MAX_DEPTH - 1:
172
+ rules = list(self.list_rules)
173
+ rules.remove('list_start')
174
+ return rules
175
+ return self.list_rules
176
+
177
+ def parse_list_start(self, m, state, string):
178
+ items = []
179
+ spaces = m.group(1)
180
+ marker = m.group(2)
181
+ items, pos = _find_list_items(string, m.start(), spaces, marker)
182
+ tight = '\n\n' not in ''.join(items).strip()
183
+
184
+ ordered = len(marker) != 1
185
+ if ordered:
186
+ start = int(marker[:-1])
187
+ if start == 1:
188
+ start = None
189
+ else:
190
+ start = None
191
+
192
+ list_tights = state.get('list_tights', [])
193
+ list_tights.append(tight)
194
+ state['list_tights'] = list_tights
195
+
196
+ depth = len(list_tights)
197
+ rules = self.get_list_rules(depth)
198
+ children = [
199
+ self.parse_list_item(item, depth, state, rules)
200
+ for item in items
201
+ ]
202
+ list_tights.pop()
203
+ params = (ordered, depth, start)
204
+ token = {'type': 'list', 'children': children, 'params': params}
205
+ return token, pos
206
+
207
+ def parse_list_item(self, text, depth, state, rules):
208
+ text = self.normalize_list_item_text(text)
209
+ if not text:
210
+ children = [{'type': 'block_text', 'text': ''}]
211
+ else:
212
+ children = self.parse(text, state, rules)
213
+ return {
214
+ 'type': 'list_item',
215
+ 'params': (depth,),
216
+ 'children': children,
217
+ }
218
+
219
+ @staticmethod
220
+ def normalize_list_item_text(text):
221
+ text_length = len(text)
222
+ text = _LIST_BULLET.sub('', text)
223
+
224
+ if not text.strip():
225
+ return ''
226
+
227
+ space = text_length - len(text)
228
+ text = expand_leading_tab(text)
229
+ if text.startswith(' '):
230
+ text = text[1:]
231
+ space += 1
232
+ else:
233
+ text_length = len(text)
234
+ text = _TRIM_4.sub('', text)
235
+ space += max(text_length - len(text), 1)
236
+
237
+ # outdent
238
+ if '\n ' in text:
239
+ pattern = re.compile(r'\n {1,' + str(space) + r'}')
240
+ text = pattern.sub(r'\n', text)
241
+ return text
242
+
243
+ def parse_block_html(self, m, state):
244
+ html = m.group(0).rstrip()
245
+ return {'type': 'block_html', 'raw': html}
246
+
247
+ def parse_def_link(self, m, state):
248
+ key = unikey(m.group(1))
249
+ link = m.group(2)
250
+ title = m.group(3)
251
+ if key not in state['def_links']:
252
+ state['def_links'][key] = (link, title)
253
+
254
+ def parse_text(self, text, state):
255
+ list_tights = state.get('list_tights')
256
+ if list_tights and list_tights[-1]:
257
+ return {'type': 'block_text', 'text': text.strip()}
258
+
259
+ tokens = []
260
+ for s in _PARAGRAPH_SPLIT.split(text):
261
+ s = s.strip()
262
+ if s:
263
+ tokens.append({'type': 'paragraph', 'text': s})
264
+ return tokens
265
+
266
+ def parse(self, s, state, rules=None):
267
+ if rules is None:
268
+ rules = self.rules
269
+
270
+ return list(self._scan(s, state, rules))
271
+
272
+ def render(self, tokens, inline, state):
273
+ data = self._iter_render(tokens, inline, state)
274
+ return inline.renderer.finalize(data)
275
+
276
+ def _iter_render(self, tokens, inline, state):
277
+ for tok in tokens:
278
+ method = inline.renderer._get_method(tok['type'])
279
+ if 'blank' in tok:
280
+ yield method()
281
+ continue
282
+
283
+ if 'children' in tok:
284
+ children = self.render(tok['children'], inline, state)
285
+ elif 'raw' in tok:
286
+ children = tok['raw']
287
+ else:
288
+ children = inline(tok['text'], state)
289
+ params = tok.get('params')
290
+ if params:
291
+ yield method(children, *params)
292
+ else:
293
+ yield method(children)
294
+
295
+
296
+ def cleanup_lines(s):
297
+ s = _NEW_LINES.sub('\n', s)
298
+ s = _BLANK_LINES.sub('', s)
299
+ return s
300
+
301
+
302
+ def expand_leading_tab(text):
303
+ return _EXPAND_TAB.sub(_expand_tab_repl, text)
304
+
305
+
306
+ def _expand_tab_repl(m):
307
+ s = m.group(1)
308
+ return s + ' ' * (4 - len(s))
309
+
310
+
311
+ def _create_list_item_pattern(spaces, marker):
312
+ prefix = r'( {0,' + str(len(spaces) + len(marker)) + r'})'
313
+
314
+ if len(marker) > 1:
315
+ if marker[-1] == '.':
316
+ prefix = prefix + r'\d{0,9}\.'
317
+ else:
318
+ prefix = prefix + r'\d{0,9}\)'
319
+ else:
320
+ if marker == '*':
321
+ prefix = prefix + r'\*'
322
+ elif marker == '+':
323
+ prefix = prefix + r'\+'
324
+ else:
325
+ prefix = prefix + r'-'
326
+
327
+ s1 = ' {' + str(len(marker) + 1) + ',}'
328
+ if len(marker) > 4:
329
+ s2 = ' {' + str(len(marker) - 4) + r',}\t'
330
+ else:
331
+ s2 = r' *\t'
332
+ return re.compile(
333
+ prefix + r'(?:[ \t]*|[ \t]+[^\n]+)\n+'
334
+ r'(?:\1(?:' + s1 + '|' + s2 + ')'
335
+ r'[^\n]+\n+)*'
336
+ )
337
+
338
+
339
+ def _find_list_items(string, pos, spaces, marker):
340
+ items = []
341
+
342
+ if marker in {'*', '-'}:
343
+ is_hr = re.compile(
344
+ r' *((?:-[ \t]*){3,}|(?:\*[ \t]*){3,})\n+'
345
+ )
346
+ else:
347
+ is_hr = None
348
+
349
+ pattern = _create_list_item_pattern(spaces, marker)
350
+ while 1:
351
+ m = pattern.match(string, pos)
352
+ if not m:
353
+ break
354
+
355
+ text = m.group(0)
356
+ if is_hr and is_hr.match(text):
357
+ break
358
+
359
+ new_spaces = m.group(1)
360
+ if new_spaces != spaces:
361
+ spaces = new_spaces
362
+ pattern = _create_list_item_pattern(spaces, marker)
363
+
364
+ items.append(text)
365
+ pos = m.end()
366
+ return items, pos
@@ -0,0 +1,216 @@
1
+ import re
2
+ from .scanner import ScannerParser
3
+ from .util import PUNCTUATION, ESCAPE_TEXT, escape_url, unikey
4
+
5
+ HTML_TAGNAME = r'[A-Za-z][A-Za-z0-9-]*'
6
+ HTML_ATTRIBUTES = (
7
+ r'(?:\s+[A-Za-z_:][A-Za-z0-9_.:-]*'
8
+ r'(?:\s*=\s*(?:[^ "\'=<>`]+|\'[^\']*?\'|"[^\"]*?"))?)*'
9
+ )
10
+ ESCAPE_CHAR = re.compile(r'\\([' + PUNCTUATION + r'])')
11
+ LINK_TEXT = r'(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?'
12
+ LINK_LABEL = r'(?:[^\\\[\]]|' + ESCAPE_TEXT + r'){0,1000}'
13
+
14
+
15
+ class InlineParser(ScannerParser):
16
+ ESCAPE = ESCAPE_TEXT
17
+
18
+ #: link or email syntax::
19
+ #:
20
+ #: <https://example.com>
21
+ AUTO_LINK = (
22
+ r'(?<!\\)(?:\\\\)*<([A-Za-z][A-Za-z0-9+.-]{1,31}:'
23
+ r"[^ <>]*?|[A-Za-z0-9.!#$%&'*+/=?^_`{|}~-]+@[A-Za-z0-9]"
24
+ r'(?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?'
25
+ r'(?:\.[A-Za-z0-9](?:[A-Za-z0-9-]{0,61}[A-Za-z0-9])?)*)>'
26
+ )
27
+
28
+ #: link or image syntax::
29
+ #:
30
+ #: [text](/link "title")
31
+ #: ![alt](/src "title")
32
+ STD_LINK = (
33
+ r'!?\[(' + LINK_TEXT + r')\]\(\s*'
34
+
35
+ r'(<(?:\\[<>]?|[^\s<>\\])*>|'
36
+ r'(?:\\[()]?|\([^\s\x00-\x1f\\]*\)|[^\s\x00-\x1f()\\])*?)'
37
+
38
+ r'(?:\s+('
39
+ r'''"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)'''
40
+ r'))?\s*\)'
41
+ )
42
+
43
+ #: Get link from references. References are defined in DEF_LINK in blocks.
44
+ #: The syntax looks like::
45
+ #:
46
+ #: [an example][id]
47
+ #:
48
+ #: [id]: https://example.com "optional title"
49
+ REF_LINK = (
50
+ r'!?\[(' + LINK_TEXT + r')\]'
51
+ r'\[(' + LINK_LABEL + r')\]'
52
+ )
53
+
54
+ #: Simple form of reference link::
55
+ #:
56
+ #: [an example]
57
+ #:
58
+ #: [an example]: https://example.com "optional title"
59
+ REF_LINK2 = r'!?\[(' + LINK_LABEL + r')\]'
60
+
61
+ #: emphasis and strong * or _::
62
+ #:
63
+ #: *emphasis* **strong**
64
+ #: _emphasis_ __strong__
65
+ ASTERISK_EMPHASIS = (
66
+ r'(\*{1,2})(?=[^\s*])('
67
+ r'(?:\\[\\*]|[^*])*'
68
+ r'(?:' + ESCAPE_TEXT + r'|[^\s*]))\1'
69
+ )
70
+ UNDERSCORE_EMPHASIS = (
71
+ r'\b(_{1,2})(?=[^\s_])([\s\S]*?'
72
+ r'(?:' + ESCAPE_TEXT + r'|[^\s_]))\1'
73
+ r'(?!_|[^\s' + PUNCTUATION + r'])\b'
74
+ )
75
+
76
+ #: codespan with `::
77
+ #:
78
+ #: `code`
79
+ CODESPAN = (
80
+ r'(?<!\\|`)(?:\\\\)*(`+)(?!`)([\s\S]+?)(?<!`)\1(?!`)'
81
+ )
82
+
83
+ #: linebreak leaves two spaces at the end of line
84
+ LINEBREAK = r'(?:\\| {2,})\n(?!\s*$)'
85
+
86
+ INLINE_HTML = (
87
+ r'(?<!\\)<' + HTML_TAGNAME + HTML_ATTRIBUTES + r'\s*/?>|' # open tag
88
+ r'(?<!\\)</' + HTML_TAGNAME + r'\s*>|' # close tag
89
+ r'(?<!\\)<!--(?!>|->)(?:(?!--)[\s\S])+?(?<!-)-->|' # comment
90
+ r'(?<!\\)<\?[\s\S]+?\?>|'
91
+ r'(?<!\\)<![A-Z][\s\S]+?>|' # doctype
92
+ r'(?<!\\)<!\[CDATA[\s\S]+?\]\]>' # cdata
93
+ )
94
+
95
+ RULE_NAMES = (
96
+ 'escape', 'inline_html', 'auto_link',
97
+ 'std_link', 'ref_link', 'ref_link2',
98
+ 'asterisk_emphasis', 'underscore_emphasis',
99
+ 'codespan', 'linebreak',
100
+ )
101
+
102
+ def __init__(self, renderer, hard_wrap=False):
103
+ super(InlineParser, self).__init__()
104
+ if hard_wrap:
105
+ #: every new line becomes <br>
106
+ self.LINEBREAK = r' *\n(?!\s*$)'
107
+ self.renderer = renderer
108
+ rules = list(self.RULE_NAMES)
109
+ rules.remove('ref_link')
110
+ rules.remove('ref_link2')
111
+ self.ref_link_rules = rules
112
+
113
+ def parse_escape(self, m, state):
114
+ text = m.group(0)[1:]
115
+ return 'text', text
116
+
117
+ def parse_auto_link(self, m, state):
118
+ if state.get('_in_link'):
119
+ return 'text', m.group(0)
120
+
121
+ text = m.group(1)
122
+ schemes = ('mailto:', 'http://', 'https://')
123
+ if '@' in text and not text.lower().startswith(schemes):
124
+ link = 'mailto:' + text
125
+ else:
126
+ link = text
127
+ return 'link', escape_url(link), text
128
+
129
+ def parse_std_link(self, m, state):
130
+ line = m.group(0)
131
+ text = m.group(1)
132
+ link = ESCAPE_CHAR.sub(r'\1', m.group(2))
133
+ if link.startswith('<') and link.endswith('>'):
134
+ link = link[1:-1]
135
+
136
+ title = m.group(3)
137
+ if title:
138
+ title = ESCAPE_CHAR.sub(r'\1', title[1:-1])
139
+
140
+ if line[0] == '!':
141
+ return 'image', escape_url(link), text, title
142
+
143
+ return self.tokenize_link(line, link, text, title, state)
144
+
145
+ def parse_ref_link(self, m, state):
146
+ line = m.group(0)
147
+ text = m.group(1)
148
+ key = unikey(m.group(2) or text)
149
+ def_links = state.get('def_links')
150
+ if not def_links or key not in def_links:
151
+ return list(self._scan(line, state, self.ref_link_rules))
152
+
153
+ link, title = def_links.get(key)
154
+ link = ESCAPE_CHAR.sub(r'\1', link)
155
+ if title:
156
+ title = ESCAPE_CHAR.sub(r'\1', title)
157
+
158
+ if line[0] == '!':
159
+ return 'image', escape_url(link), text, title
160
+
161
+ return self.tokenize_link(line, link, text, title, state)
162
+
163
+ def parse_ref_link2(self, m, state):
164
+ return self.parse_ref_link(m, state)
165
+
166
+ def tokenize_link(self, line, link, text, title, state):
167
+ if state.get('_in_link'):
168
+ return 'text', line
169
+ state['_in_link'] = True
170
+ text = self.render(text, state)
171
+ state['_in_link'] = False
172
+ return 'link', escape_url(link), text, title
173
+
174
+ def parse_asterisk_emphasis(self, m, state):
175
+ return self.tokenize_emphasis(m, state)
176
+
177
+ def parse_underscore_emphasis(self, m, state):
178
+ return self.tokenize_emphasis(m, state)
179
+
180
+ def tokenize_emphasis(self, m, state):
181
+ marker = m.group(1)
182
+ text = m.group(2)
183
+ if len(marker) == 1:
184
+ return 'emphasis', self.render(text, state)
185
+ return 'strong', self.render(text, state)
186
+
187
+ def parse_codespan(self, m, state):
188
+ code = re.sub(r'[ \n]+', ' ', m.group(2).strip())
189
+ return 'codespan', code
190
+
191
+ def parse_linebreak(self, m, state):
192
+ return 'linebreak',
193
+
194
+ def parse_inline_html(self, m, state):
195
+ html = m.group(0)
196
+ return 'inline_html', html
197
+
198
+ def parse_text(self, text, state):
199
+ return 'text', text
200
+
201
+ def parse(self, s, state, rules=None):
202
+ if rules is None:
203
+ rules = self.rules
204
+
205
+ tokens = (
206
+ self.renderer._get_method(t[0])(*t[1:])
207
+ for t in self._scan(s, state, rules)
208
+ )
209
+ return tokens
210
+
211
+ def render(self, s, state, rules=None):
212
+ tokens = self.parse(s, state, rules)
213
+ return self.renderer.finalize(tokens)
214
+
215
+ def __call__(self, s, state):
216
+ return self.render(s, state)