doc2dict 0.2.0__tar.gz → 0.2.2__tar.gz
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.
- {doc2dict-0.2.0 → doc2dict-0.2.2}/PKG-INFO +1 -1
- doc2dict-0.2.2/doc2dict/__init__.py +7 -0
- doc2dict-0.2.2/doc2dict/dict2dict.py +50 -0
- doc2dict-0.2.2/doc2dict/html/__init__.py +0 -0
- doc2dict-0.2.2/doc2dict/html/html_parser.py +294 -0
- doc2dict-0.2.2/doc2dict/html/visualizer.py +100 -0
- doc2dict-0.2.2/doc2dict/txt/__init__.py +0 -0
- doc2dict-0.2.2/doc2dict/txt/parser.py +21 -0
- doc2dict-0.2.2/doc2dict/xml/__init__.py +0 -0
- doc2dict-0.2.2/doc2dict/xml/parser.py +12 -0
- {doc2dict-0.2.0 → doc2dict-0.2.2}/doc2dict.egg-info/PKG-INFO +1 -1
- doc2dict-0.2.2/doc2dict.egg-info/SOURCES.txt +16 -0
- {doc2dict-0.2.0 → doc2dict-0.2.2}/setup.py +1 -1
- doc2dict-0.2.0/doc2dict/__init__.py +0 -4
- doc2dict-0.2.0/doc2dict.egg-info/SOURCES.txt +0 -8
- {doc2dict-0.2.0 → doc2dict-0.2.2}/doc2dict/mapping.py +0 -0
- {doc2dict-0.2.0 → doc2dict-0.2.2}/doc2dict.egg-info/dependency_links.txt +0 -0
- {doc2dict-0.2.0 → doc2dict-0.2.2}/doc2dict.egg-info/requires.txt +0 -0
- {doc2dict-0.2.0 → doc2dict-0.2.2}/doc2dict.egg-info/top_level.txt +0 -0
- {doc2dict-0.2.0 → doc2dict-0.2.2}/setup.cfg +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from .html.html_parser import html_reduction
|
|
2
|
+
from .html.visualizer import format_list_html
|
|
3
|
+
from .xml.parser import xml2dict
|
|
4
|
+
from .txt.parser import txt2dict
|
|
5
|
+
from .dict2dict import dict2dict
|
|
6
|
+
|
|
7
|
+
__all__ = ['html_reduction', 'format_list_html', 'xml2dict', 'txt2dict','dict2dict']
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
def dict2dict(data):
|
|
2
|
+
result = {}
|
|
3
|
+
|
|
4
|
+
def process_item(item):
|
|
5
|
+
# If item is a string, return it directly
|
|
6
|
+
if isinstance(item, str):
|
|
7
|
+
return item.strip()
|
|
8
|
+
|
|
9
|
+
# If item is not a dict, return string version
|
|
10
|
+
if not isinstance(item, dict):
|
|
11
|
+
return str(item).strip()
|
|
12
|
+
|
|
13
|
+
# Base case: if there's no further content, return the item itself
|
|
14
|
+
if 'content' not in item:
|
|
15
|
+
return item
|
|
16
|
+
|
|
17
|
+
# If there's a text key, use it as the dict key, otherwise use the type
|
|
18
|
+
key = item.get('text', item.get('type', ''))
|
|
19
|
+
|
|
20
|
+
# Process the content
|
|
21
|
+
if isinstance(item['content'], list):
|
|
22
|
+
# Check if content contains dictionaries with type/text
|
|
23
|
+
if any(isinstance(x, dict) and ('type' in x or 'text' in x) for x in item['content']):
|
|
24
|
+
nested_result = {}
|
|
25
|
+
for content_item in item['content']:
|
|
26
|
+
if isinstance(content_item, dict):
|
|
27
|
+
nested_key = content_item.get('text', content_item.get('type', ''))
|
|
28
|
+
nested_result[nested_key] = process_item(content_item)
|
|
29
|
+
return nested_result
|
|
30
|
+
# If content items are simple values (strings/numbers), join with newlines and strip
|
|
31
|
+
else:
|
|
32
|
+
return '\n'.join(str(x) for x in item['content']).strip()
|
|
33
|
+
else:
|
|
34
|
+
return str(item['content']).strip()
|
|
35
|
+
|
|
36
|
+
# Handle case where data itself might be a string
|
|
37
|
+
if isinstance(data, str):
|
|
38
|
+
return data.strip()
|
|
39
|
+
|
|
40
|
+
# Handle case where content is a list directly
|
|
41
|
+
if isinstance(data.get('content', []), list):
|
|
42
|
+
for item in data['content']:
|
|
43
|
+
if isinstance(item, dict):
|
|
44
|
+
key = item.get('text', item.get('type', ''))
|
|
45
|
+
result[key] = process_item(item)
|
|
46
|
+
else:
|
|
47
|
+
# If we have a string in content, use it as both key and value
|
|
48
|
+
result[str(item).strip()] = str(item).strip()
|
|
49
|
+
|
|
50
|
+
return result
|
|
File without changes
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import re
|
|
2
|
+
|
|
3
|
+
def iterwalk(root, include_text):
|
|
4
|
+
def walk(node, inherited_styles=None, inherited_text_style=None):
|
|
5
|
+
current_styles = dict(inherited_styles or {})
|
|
6
|
+
node_styles = get_node_styles(node)
|
|
7
|
+
current_styles.update(node_styles)
|
|
8
|
+
|
|
9
|
+
if current_styles.get('display', [''])[0] == 'none':
|
|
10
|
+
return
|
|
11
|
+
|
|
12
|
+
text_content = node.text_content
|
|
13
|
+
if text_content:
|
|
14
|
+
text_transform = current_styles.get('text-transform', [''])[0]
|
|
15
|
+
if text_transform == 'uppercase':
|
|
16
|
+
text_content = text_content.upper()
|
|
17
|
+
elif text_transform == 'lowercase':
|
|
18
|
+
text_content = text_content.lower()
|
|
19
|
+
elif text_transform == 'capitalize':
|
|
20
|
+
text_content = text_content.capitalize()
|
|
21
|
+
|
|
22
|
+
text_style = get_text_style(node, current_styles, inherited_text_style)
|
|
23
|
+
|
|
24
|
+
yield ("start", node, current_styles, text_content, text_style)
|
|
25
|
+
for child in node.iter(include_text=include_text):
|
|
26
|
+
if child is not node:
|
|
27
|
+
yield from walk(child, current_styles, text_style)
|
|
28
|
+
yield ("end", node, current_styles, text_content, text_style)
|
|
29
|
+
|
|
30
|
+
for node in root.iter(include_text=include_text):
|
|
31
|
+
if node is not root:
|
|
32
|
+
yield from walk(node)
|
|
33
|
+
|
|
34
|
+
class Ctx:
|
|
35
|
+
def __init__(self, base=16.0):
|
|
36
|
+
self.base = base # base font size
|
|
37
|
+
self.vh = 900 # viewport height
|
|
38
|
+
self.vw = 1600 # viewport width
|
|
39
|
+
|
|
40
|
+
class Box:
|
|
41
|
+
def __init__(self):
|
|
42
|
+
self.mt = self.mb = self.pt = self.pb = self.bt = self.bb = 0 # margins, padding, borders
|
|
43
|
+
self.ch = 0 # content height
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def height(self):
|
|
47
|
+
return self.mt + self.pt + self.bt + self.ch + self.mb + self.pb + self.bb
|
|
48
|
+
|
|
49
|
+
def parse_val(val, ctx, parent):
|
|
50
|
+
"""Parse CSS values with unit support"""
|
|
51
|
+
if not val or val == 'auto' or val == 'none': return 0
|
|
52
|
+
|
|
53
|
+
try:
|
|
54
|
+
m = re.match(r'^(-?\d*\.?\d+)(\D*)$', val.strip())
|
|
55
|
+
if not m: return 0
|
|
56
|
+
|
|
57
|
+
n, u = float(m.group(1)), m.group(2)
|
|
58
|
+
|
|
59
|
+
units = {
|
|
60
|
+
'': n,
|
|
61
|
+
'px': n,
|
|
62
|
+
'em': n * parent,
|
|
63
|
+
'rem': n * ctx.base,
|
|
64
|
+
'%': (n/100) * parent,
|
|
65
|
+
'vh': (n/100) * ctx.vh,
|
|
66
|
+
'vw': (n/100) * ctx.vw,
|
|
67
|
+
'pt': n * 1.333333,
|
|
68
|
+
'pc': n * 16,
|
|
69
|
+
'in': n * 96,
|
|
70
|
+
'cm': n * 37.795276,
|
|
71
|
+
'mm': n * 3.779528
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return units.get(u, 0)
|
|
75
|
+
except:
|
|
76
|
+
return 0
|
|
77
|
+
|
|
78
|
+
def parse_border(val, ctx, parent):
|
|
79
|
+
"""Parse border values"""
|
|
80
|
+
if not val: return 0
|
|
81
|
+
return next((parse_val(p, ctx, parent) for p in val.split() if re.match(r'^\d', p)), 0)
|
|
82
|
+
|
|
83
|
+
def calc_line_height(fs, lh):
|
|
84
|
+
"""Calculate line height"""
|
|
85
|
+
if not lh: return fs # Default to font size
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
if isinstance(lh, (int, float)):
|
|
89
|
+
return fs * float(lh) # multiplier
|
|
90
|
+
elif lh.endswith('px'):
|
|
91
|
+
return float(lh[:-2])
|
|
92
|
+
elif lh.endswith('%'):
|
|
93
|
+
return fs * (float(lh[:-1])/100)
|
|
94
|
+
return fs # Default to font size for any other value
|
|
95
|
+
except:
|
|
96
|
+
return fs
|
|
97
|
+
|
|
98
|
+
class StyleChain:
|
|
99
|
+
def __init__(self, ctx):
|
|
100
|
+
self.ctx = ctx
|
|
101
|
+
self.chain = []
|
|
102
|
+
|
|
103
|
+
def push(self, s): self.chain.append(s)
|
|
104
|
+
def pop(self): self.chain.pop() if self.chain else None
|
|
105
|
+
|
|
106
|
+
def get(self, prop, default=''):
|
|
107
|
+
"""Get computed style"""
|
|
108
|
+
for s in reversed(self.chain):
|
|
109
|
+
if prop in s: return s[prop][0]
|
|
110
|
+
return default
|
|
111
|
+
|
|
112
|
+
def font_size(self):
|
|
113
|
+
"""Calculate font size through chain"""
|
|
114
|
+
size = self.ctx.base
|
|
115
|
+
for s in self.chain:
|
|
116
|
+
if 'font-size' in s:
|
|
117
|
+
size = parse_val(s['font-size'][0], self.ctx, size)
|
|
118
|
+
return size
|
|
119
|
+
|
|
120
|
+
def get_box_metrics(styles, chain):
|
|
121
|
+
"""Calculate box model metrics"""
|
|
122
|
+
ctx = chain.ctx
|
|
123
|
+
fs = chain.font_size()
|
|
124
|
+
box = Box()
|
|
125
|
+
|
|
126
|
+
# Get box properties
|
|
127
|
+
props = {
|
|
128
|
+
'margin-top': 'mt', 'margin-bottom': 'mb',
|
|
129
|
+
'padding-top': 'pt', 'padding-bottom': 'pb'
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
for css_prop, box_prop in props.items():
|
|
133
|
+
if css_prop in styles:
|
|
134
|
+
setattr(box, box_prop, parse_val(styles[css_prop][0], ctx, fs))
|
|
135
|
+
|
|
136
|
+
# Borders
|
|
137
|
+
if 'border-top' in styles: box.bt = parse_border(styles['border-top'][0], ctx, fs)
|
|
138
|
+
if 'border-bottom' in styles: box.bb = parse_border(styles['border-bottom'][0], ctx, fs)
|
|
139
|
+
|
|
140
|
+
# Content height
|
|
141
|
+
box.ch = calc_line_height(fs, chain.get('line-height'))
|
|
142
|
+
|
|
143
|
+
# Handle border-box
|
|
144
|
+
if chain.get('box-sizing') == 'border-box':
|
|
145
|
+
extra = box.pt + box.pb + box.bt + box.bb
|
|
146
|
+
box.ch = max(0, box.ch - extra)
|
|
147
|
+
|
|
148
|
+
return box
|
|
149
|
+
|
|
150
|
+
def process_height(node, chain):
|
|
151
|
+
"""Process element height"""
|
|
152
|
+
styles = get_node_styles(node)
|
|
153
|
+
chain.push(styles)
|
|
154
|
+
|
|
155
|
+
try:
|
|
156
|
+
box = get_box_metrics(styles, chain)
|
|
157
|
+
fs = chain.font_size()
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
'font_size': round(fs, 2),
|
|
161
|
+
'content_height': round(box.ch, 2),
|
|
162
|
+
'total_height': round(box.ch, 2), # Only use content height
|
|
163
|
+
'box': {
|
|
164
|
+
'mt': 0, 'mb': 0,
|
|
165
|
+
'pt': 0, 'pb': 0,
|
|
166
|
+
'bt': 0, 'bb': 0
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
finally:
|
|
170
|
+
chain.pop()
|
|
171
|
+
|
|
172
|
+
def standardize_css(style):
|
|
173
|
+
if not style:
|
|
174
|
+
return {}
|
|
175
|
+
return {
|
|
176
|
+
k.strip(): v.strip().split()
|
|
177
|
+
for k, v in (pair.split(':') for pair in style.split(';') if ':' in pair)
|
|
178
|
+
if k.strip() and v.strip()
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
def get_node_styles(node):
|
|
182
|
+
style = node.attributes.get('style')
|
|
183
|
+
if not style:
|
|
184
|
+
return {}
|
|
185
|
+
return standardize_css(style)
|
|
186
|
+
|
|
187
|
+
def get_text_style(node, styles, inherited_style=None):
|
|
188
|
+
text_style = inherited_style.copy() if inherited_style else {
|
|
189
|
+
'bold': False,
|
|
190
|
+
'italic': False,
|
|
191
|
+
'underline': False
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if node.tag in {'b', 'strong'}: text_style['bold'] = True
|
|
195
|
+
if node.tag in {'i', 'em'}: text_style['italic'] = True
|
|
196
|
+
if node.tag == 'u': text_style['underline'] = True
|
|
197
|
+
|
|
198
|
+
font_weight = styles.get('font-weight', [''])[0]
|
|
199
|
+
if font_weight in {'bold', '700', '800', '900'}:
|
|
200
|
+
text_style['bold'] = True
|
|
201
|
+
|
|
202
|
+
if styles.get('font-style', [''])[0] == 'italic':
|
|
203
|
+
text_style['italic'] = True
|
|
204
|
+
|
|
205
|
+
if 'underline' in styles.get('text-decoration', [''])[0]:
|
|
206
|
+
text_style['underline'] = True
|
|
207
|
+
|
|
208
|
+
return text_style
|
|
209
|
+
|
|
210
|
+
def is_inline(node, styles):
|
|
211
|
+
if node.tag in {'span', 'a', 'strong', 'em', 'b', 'i', 'u'}:
|
|
212
|
+
return True
|
|
213
|
+
return styles.get('display', [''])[0] == 'inline'
|
|
214
|
+
|
|
215
|
+
def html_reduction(tree):
|
|
216
|
+
"""Main processing function"""
|
|
217
|
+
ctx = Ctx()
|
|
218
|
+
chain = StyleChain(ctx)
|
|
219
|
+
blocks = {'p', 'div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'article', 'section', 'li'}
|
|
220
|
+
skip = {'script', 'style', 'noscript'}
|
|
221
|
+
lines = []
|
|
222
|
+
cur_line = []
|
|
223
|
+
row_items = []
|
|
224
|
+
in_row = False
|
|
225
|
+
|
|
226
|
+
def flush():
|
|
227
|
+
if cur_line:
|
|
228
|
+
items = []
|
|
229
|
+
for text, style, node in cur_line:
|
|
230
|
+
if text.strip():
|
|
231
|
+
metrics = process_height(node, chain)
|
|
232
|
+
items.append({
|
|
233
|
+
"text": text.strip(),
|
|
234
|
+
"bold": style.get('bold', False),
|
|
235
|
+
"italic": style.get('italic', False),
|
|
236
|
+
"underline": style.get('underline', False),
|
|
237
|
+
"height": metrics['total_height'],
|
|
238
|
+
"font_size": metrics['font_size']
|
|
239
|
+
})
|
|
240
|
+
if items: lines.append(items)
|
|
241
|
+
cur_line.clear()
|
|
242
|
+
|
|
243
|
+
for event, node, styles, text, style in iterwalk(tree.body, include_text=True):
|
|
244
|
+
if node.tag in skip: continue
|
|
245
|
+
|
|
246
|
+
if event == "start": chain.push(styles)
|
|
247
|
+
|
|
248
|
+
if node.tag == 'tr':
|
|
249
|
+
if event == "start":
|
|
250
|
+
in_row = True
|
|
251
|
+
row_items = []
|
|
252
|
+
elif event == "end":
|
|
253
|
+
if row_items:
|
|
254
|
+
lines.append([{
|
|
255
|
+
"text": t,
|
|
256
|
+
"bold": s['bold'],
|
|
257
|
+
"italic": s['italic'],
|
|
258
|
+
"underline": s['underline'],
|
|
259
|
+
"height": process_height(n, chain)['total_height'],
|
|
260
|
+
"font_size": process_height(n, chain)['font_size']
|
|
261
|
+
} for t, s, n in row_items])
|
|
262
|
+
in_row = False
|
|
263
|
+
row_items = []
|
|
264
|
+
|
|
265
|
+
if in_row and event == "start" and text:
|
|
266
|
+
t = text.strip()
|
|
267
|
+
if t: row_items.append((t, style, node))
|
|
268
|
+
continue
|
|
269
|
+
|
|
270
|
+
if (node.tag in blocks or styles.get('display', [''])[0] == 'flex') and not is_inline(node, styles):
|
|
271
|
+
if event == "start":
|
|
272
|
+
flush()
|
|
273
|
+
if text:
|
|
274
|
+
t = text.strip()
|
|
275
|
+
if t:
|
|
276
|
+
metrics = process_height(node, chain)
|
|
277
|
+
lines.append([{
|
|
278
|
+
"text": t,
|
|
279
|
+
"bold": style['bold'],
|
|
280
|
+
"italic": style['italic'],
|
|
281
|
+
"underline": style['underline'],
|
|
282
|
+
"height": metrics['total_height'],
|
|
283
|
+
"font_size": metrics['font_size']
|
|
284
|
+
}])
|
|
285
|
+
elif event == "end":
|
|
286
|
+
flush()
|
|
287
|
+
elif event == "start" and text:
|
|
288
|
+
t = text.strip()
|
|
289
|
+
if t: cur_line.append((t, style, node))
|
|
290
|
+
|
|
291
|
+
if event == "end": chain.pop()
|
|
292
|
+
|
|
293
|
+
flush()
|
|
294
|
+
return lines
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import webbrowser
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
def format_list_html(nested_list):
|
|
5
|
+
# Simplified color scheme
|
|
6
|
+
single_line_color = '#E6F3FF' # Blue hue
|
|
7
|
+
multi_first_color = '#E6FFE6' # Green hue
|
|
8
|
+
multi_rest_color = '#FFE6E6' # Red hue
|
|
9
|
+
|
|
10
|
+
html_content = """
|
|
11
|
+
<html>
|
|
12
|
+
<head>
|
|
13
|
+
<style>
|
|
14
|
+
body {
|
|
15
|
+
font-family: Arial, sans-serif;
|
|
16
|
+
line-height: 1.6;
|
|
17
|
+
margin: 20px;
|
|
18
|
+
}
|
|
19
|
+
.row {
|
|
20
|
+
margin-bottom: 20px;
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-wrap: wrap;
|
|
23
|
+
}
|
|
24
|
+
.item {
|
|
25
|
+
padding: 10px 15px;
|
|
26
|
+
border-radius: 5px;
|
|
27
|
+
margin-right: 15px;
|
|
28
|
+
margin-bottom: 10px;
|
|
29
|
+
display: inline-block;
|
|
30
|
+
}
|
|
31
|
+
</style>
|
|
32
|
+
</head>
|
|
33
|
+
<body>
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def get_styled_text(item):
|
|
37
|
+
"""Helper function to apply text styling"""
|
|
38
|
+
if not isinstance(item, dict):
|
|
39
|
+
return str(item)
|
|
40
|
+
|
|
41
|
+
height = str(item.get('height', ''))
|
|
42
|
+
text = item.get('text', '')
|
|
43
|
+
style_properties = []
|
|
44
|
+
|
|
45
|
+
if item.get('bold', False):
|
|
46
|
+
style_properties.append('font-weight: bold')
|
|
47
|
+
if item.get('italic', False):
|
|
48
|
+
style_properties.append('font-style: italic')
|
|
49
|
+
if item.get('underline', False):
|
|
50
|
+
style_properties.append('text-decoration: underline')
|
|
51
|
+
if height: # Change height to font-size
|
|
52
|
+
style_properties.append(f'font-size: {height}')
|
|
53
|
+
|
|
54
|
+
if style_properties:
|
|
55
|
+
return f"<span style='{'; '.join(style_properties)}'>{text}</span>"
|
|
56
|
+
return text
|
|
57
|
+
|
|
58
|
+
for items in nested_list:
|
|
59
|
+
if isinstance(items, list):
|
|
60
|
+
first_indent = items[0].get('indent', 0) if isinstance(items[0], dict) else 0
|
|
61
|
+
html_content += f"<div class='row' style='padding-left: {first_indent}em'>\n"
|
|
62
|
+
|
|
63
|
+
for i, item in enumerate(items):
|
|
64
|
+
# Single item -> blue
|
|
65
|
+
if len(items) == 1:
|
|
66
|
+
color = single_line_color
|
|
67
|
+
# Multiple items: first -> green, rest -> red
|
|
68
|
+
else:
|
|
69
|
+
color = multi_first_color if i == 0 else multi_rest_color
|
|
70
|
+
|
|
71
|
+
styled_text = get_styled_text(item)
|
|
72
|
+
html_content += f" <span class='item' style='background-color: {color}'>{styled_text}</span>\n"
|
|
73
|
+
|
|
74
|
+
html_content += "</div>\n"
|
|
75
|
+
else:
|
|
76
|
+
if isinstance(items, dict):
|
|
77
|
+
indent = items.get('indent', 0)
|
|
78
|
+
styled_text = get_styled_text(items)
|
|
79
|
+
height = items.get('height', '')
|
|
80
|
+
height_style = f'height: {height};' if height else ''
|
|
81
|
+
html_content += f"<div class='row' style='padding-left: {indent}em'><span class='item' style='background-color: {single_line_color}; {height_style}'>{styled_text}</span></div>\n"
|
|
82
|
+
else:
|
|
83
|
+
styled_text = str(items)
|
|
84
|
+
indent = 0
|
|
85
|
+
html_content += f"<div class='row' style='padding-left: {indent}em'><span class='item' style='background-color: {single_line_color}'>{styled_text}</span></div>\n"
|
|
86
|
+
|
|
87
|
+
html_content += """
|
|
88
|
+
</body>
|
|
89
|
+
</html>
|
|
90
|
+
"""
|
|
91
|
+
|
|
92
|
+
# Write HTML content to a temporary file
|
|
93
|
+
with open('temp.html', 'w', encoding='utf-8') as f:
|
|
94
|
+
f.write(html_content)
|
|
95
|
+
|
|
96
|
+
# Get the absolute path of the file
|
|
97
|
+
file_path = os.path.abspath('temp.html')
|
|
98
|
+
|
|
99
|
+
# Open the HTML file in the default web browser
|
|
100
|
+
webbrowser.open('file://' + file_path)
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from doc2dict.mapping import DocumentProcessor
|
|
2
|
+
|
|
3
|
+
def txt2dict(content,mapping_dict):
|
|
4
|
+
# Split by double newlines to get paragraphs
|
|
5
|
+
paragraphs = content.split('\n\n')
|
|
6
|
+
|
|
7
|
+
# Process each paragraph
|
|
8
|
+
lines = []
|
|
9
|
+
for paragraph in paragraphs:
|
|
10
|
+
if paragraph.strip(): # Skip empty paragraphs
|
|
11
|
+
processed = paragraph.strip()
|
|
12
|
+
processed = processed.split('\n')
|
|
13
|
+
# Add double newlines at start of each paragraph
|
|
14
|
+
processed[0] = '\n\n' + processed[0]
|
|
15
|
+
# Add single newline to other lines
|
|
16
|
+
processed[1:] = ['\n' + line for line in processed[1:]]
|
|
17
|
+
lines.extend(processed)
|
|
18
|
+
|
|
19
|
+
processor = DocumentProcessor(mapping_dict)
|
|
20
|
+
result = processor.process(lines)
|
|
21
|
+
return result
|
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import xmltodict
|
|
2
|
+
from ..mapping import JSONTransformer
|
|
3
|
+
|
|
4
|
+
def xml2dict(content, mapping_dict=None):
|
|
5
|
+
data = xmltodict.parse(content)
|
|
6
|
+
|
|
7
|
+
if mapping_dict is None:
|
|
8
|
+
return data
|
|
9
|
+
|
|
10
|
+
transformer = JSONTransformer(mapping_dict)
|
|
11
|
+
transformed_data = transformer.transform(data)
|
|
12
|
+
return transformed_data
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
setup.py
|
|
2
|
+
doc2dict/__init__.py
|
|
3
|
+
doc2dict/dict2dict.py
|
|
4
|
+
doc2dict/mapping.py
|
|
5
|
+
doc2dict.egg-info/PKG-INFO
|
|
6
|
+
doc2dict.egg-info/SOURCES.txt
|
|
7
|
+
doc2dict.egg-info/dependency_links.txt
|
|
8
|
+
doc2dict.egg-info/requires.txt
|
|
9
|
+
doc2dict.egg-info/top_level.txt
|
|
10
|
+
doc2dict/html/__init__.py
|
|
11
|
+
doc2dict/html/html_parser.py
|
|
12
|
+
doc2dict/html/visualizer.py
|
|
13
|
+
doc2dict/txt/__init__.py
|
|
14
|
+
doc2dict/txt/parser.py
|
|
15
|
+
doc2dict/xml/__init__.py
|
|
16
|
+
doc2dict/xml/parser.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|