docling 2.26.0__py3-none-any.whl → 2.27.0__py3-none-any.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 (50) hide show
  1. docling/backend/asciidoc_backend.py +1 -1
  2. docling/backend/csv_backend.py +1 -1
  3. docling/backend/docling_parse_backend.py +21 -13
  4. docling/backend/docling_parse_v2_backend.py +20 -12
  5. docling/backend/docling_parse_v4_backend.py +185 -0
  6. docling/backend/docx/__init__.py +0 -0
  7. docling/backend/docx/latex/__init__.py +0 -0
  8. docling/backend/docx/latex/latex_dict.py +271 -0
  9. docling/backend/docx/latex/omml.py +453 -0
  10. docling/backend/html_backend.py +7 -7
  11. docling/backend/md_backend.py +1 -1
  12. docling/backend/msexcel_backend.py +2 -45
  13. docling/backend/mspowerpoint_backend.py +1 -1
  14. docling/backend/msword_backend.py +65 -3
  15. docling/backend/pdf_backend.py +7 -2
  16. docling/backend/pypdfium2_backend.py +52 -30
  17. docling/backend/xml/uspto_backend.py +1 -1
  18. docling/cli/main.py +60 -21
  19. docling/cli/models.py +1 -1
  20. docling/datamodel/base_models.py +8 -10
  21. docling/datamodel/pipeline_options.py +26 -30
  22. docling/document_converter.py +5 -5
  23. docling/models/base_model.py +9 -1
  24. docling/models/base_ocr_model.py +27 -16
  25. docling/models/easyocr_model.py +28 -13
  26. docling/models/factories/__init__.py +27 -0
  27. docling/models/factories/base_factory.py +122 -0
  28. docling/models/factories/ocr_factory.py +11 -0
  29. docling/models/factories/picture_description_factory.py +11 -0
  30. docling/models/ocr_mac_model.py +39 -11
  31. docling/models/page_preprocessing_model.py +4 -0
  32. docling/models/picture_description_api_model.py +20 -3
  33. docling/models/picture_description_base_model.py +19 -3
  34. docling/models/picture_description_vlm_model.py +14 -2
  35. docling/models/plugins/__init__.py +0 -0
  36. docling/models/plugins/defaults.py +28 -0
  37. docling/models/rapid_ocr_model.py +34 -13
  38. docling/models/table_structure_model.py +13 -4
  39. docling/models/tesseract_ocr_cli_model.py +40 -15
  40. docling/models/tesseract_ocr_model.py +37 -12
  41. docling/pipeline/standard_pdf_pipeline.py +25 -78
  42. docling/utils/export.py +8 -6
  43. docling/utils/layout_postprocessor.py +26 -23
  44. docling/utils/visualization.py +1 -1
  45. {docling-2.26.0.dist-info → docling-2.27.0.dist-info}/METADATA +48 -19
  46. docling-2.27.0.dist-info/RECORD +83 -0
  47. {docling-2.26.0.dist-info → docling-2.27.0.dist-info}/entry_points.txt +3 -0
  48. docling-2.26.0.dist-info/RECORD +0 -72
  49. {docling-2.26.0.dist-info → docling-2.27.0.dist-info}/LICENSE +0 -0
  50. {docling-2.26.0.dist-info → docling-2.27.0.dist-info}/WHEEL +0 -0
@@ -380,7 +380,7 @@ class AsciiDocBackend(DeclarativeDocumentBackend):
380
380
  end_row_offset_idx=row_idx + row_span,
381
381
  start_col_offset_idx=col_idx,
382
382
  end_col_offset_idx=col_idx + col_span,
383
- col_header=False,
383
+ column_header=row_idx == 0,
384
384
  row_header=False,
385
385
  )
386
386
  data.table_cells.append(cell)
@@ -111,7 +111,7 @@ class CsvDocumentBackend(DeclarativeDocumentBackend):
111
111
  end_row_offset_idx=row_idx + 1,
112
112
  start_col_offset_idx=col_idx,
113
113
  end_col_offset_idx=col_idx + 1,
114
- col_header=row_idx == 0, # First row as header
114
+ column_header=row_idx == 0, # First row as header
115
115
  row_header=False,
116
116
  )
117
117
  table_data.table_cells.append(cell)
@@ -6,12 +6,12 @@ from typing import Iterable, List, Optional, Union
6
6
 
7
7
  import pypdfium2 as pdfium
8
8
  from docling_core.types.doc import BoundingBox, CoordOrigin, Size
9
+ from docling_core.types.doc.page import BoundingRectangle, SegmentedPdfPage, TextCell
9
10
  from docling_parse.pdf_parsers import pdf_parser_v1
10
11
  from PIL import Image, ImageDraw
11
12
  from pypdfium2 import PdfPage
12
13
 
13
14
  from docling.backend.pdf_backend import PdfDocumentBackend, PdfPageBackend
14
- from docling.datamodel.base_models import Cell
15
15
  from docling.datamodel.document import InputDocument
16
16
 
17
17
  _log = logging.getLogger(__name__)
@@ -68,8 +68,11 @@ class DoclingParsePageBackend(PdfPageBackend):
68
68
 
69
69
  return text_piece
70
70
 
71
- def get_text_cells(self) -> Iterable[Cell]:
72
- cells: List[Cell] = []
71
+ def get_segmented_page(self) -> Optional[SegmentedPdfPage]:
72
+ return None
73
+
74
+ def get_text_cells(self) -> Iterable[TextCell]:
75
+ cells: List[TextCell] = []
73
76
  cell_counter = 0
74
77
 
75
78
  if not self.valid:
@@ -91,19 +94,24 @@ class DoclingParsePageBackend(PdfPageBackend):
91
94
 
92
95
  text_piece = self._dpage["cells"][i]["content"]["rnormalized"]
93
96
  cells.append(
94
- Cell(
95
- id=cell_counter,
97
+ TextCell(
98
+ index=cell_counter,
96
99
  text=text_piece,
97
- bbox=BoundingBox(
98
- # l=x0, b=y0, r=x1, t=y1,
99
- l=x0 * page_size.width / parser_width,
100
- b=y0 * page_size.height / parser_height,
101
- r=x1 * page_size.width / parser_width,
102
- t=y1 * page_size.height / parser_height,
103
- coord_origin=CoordOrigin.BOTTOMLEFT,
100
+ orig=text_piece,
101
+ from_ocr=False,
102
+ rect=BoundingRectangle.from_bounding_box(
103
+ BoundingBox(
104
+ # l=x0, b=y0, r=x1, t=y1,
105
+ l=x0 * page_size.width / parser_width,
106
+ b=y0 * page_size.height / parser_height,
107
+ r=x1 * page_size.width / parser_width,
108
+ t=y1 * page_size.height / parser_height,
109
+ coord_origin=CoordOrigin.BOTTOMLEFT,
110
+ )
104
111
  ).to_top_left_origin(page_size.height),
105
112
  )
106
113
  )
114
+
107
115
  cell_counter += 1
108
116
 
109
117
  def draw_clusters_and_cells():
@@ -112,7 +120,7 @@ class DoclingParsePageBackend(PdfPageBackend):
112
120
  ) # make new image to avoid drawing on the saved ones
113
121
  draw = ImageDraw.Draw(image)
114
122
  for c in cells:
115
- x0, y0, x1, y1 = c.bbox.as_tuple()
123
+ x0, y0, x1, y1 = c.rect.to_bounding_box().as_tuple()
116
124
  cell_color = (
117
125
  random.randint(30, 140),
118
126
  random.randint(30, 140),
@@ -6,12 +6,13 @@ from typing import TYPE_CHECKING, Iterable, List, Optional, Union
6
6
 
7
7
  import pypdfium2 as pdfium
8
8
  from docling_core.types.doc import BoundingBox, CoordOrigin
9
+ from docling_core.types.doc.page import BoundingRectangle, SegmentedPdfPage, TextCell
9
10
  from docling_parse.pdf_parsers import pdf_parser_v2
10
11
  from PIL import Image, ImageDraw
11
12
  from pypdfium2 import PdfPage
12
13
 
13
14
  from docling.backend.pdf_backend import PdfDocumentBackend, PdfPageBackend
14
- from docling.datamodel.base_models import Cell, Size
15
+ from docling.datamodel.base_models import Size
15
16
  from docling.utils.locks import pypdfium2_lock
16
17
 
17
18
  if TYPE_CHECKING:
@@ -78,8 +79,11 @@ class DoclingParseV2PageBackend(PdfPageBackend):
78
79
 
79
80
  return text_piece
80
81
 
81
- def get_text_cells(self) -> Iterable[Cell]:
82
- cells: List[Cell] = []
82
+ def get_segmented_page(self) -> Optional[SegmentedPdfPage]:
83
+ return None
84
+
85
+ def get_text_cells(self) -> Iterable[TextCell]:
86
+ cells: List[TextCell] = []
83
87
  cell_counter = 0
84
88
 
85
89
  if not self.valid:
@@ -106,16 +110,20 @@ class DoclingParseV2PageBackend(PdfPageBackend):
106
110
 
107
111
  text_piece = cell_data[cells_header.index("text")]
108
112
  cells.append(
109
- Cell(
110
- id=cell_counter,
113
+ TextCell(
114
+ index=cell_counter,
111
115
  text=text_piece,
112
- bbox=BoundingBox(
113
- # l=x0, b=y0, r=x1, t=y1,
114
- l=x0 * page_size.width / parser_width,
115
- b=y0 * page_size.height / parser_height,
116
- r=x1 * page_size.width / parser_width,
117
- t=y1 * page_size.height / parser_height,
118
- coord_origin=CoordOrigin.BOTTOMLEFT,
116
+ orig=text_piece,
117
+ from_ocr=False,
118
+ rect=BoundingRectangle.from_bounding_box(
119
+ BoundingBox(
120
+ # l=x0, b=y0, r=x1, t=y1,
121
+ l=x0 * page_size.width / parser_width,
122
+ b=y0 * page_size.height / parser_height,
123
+ r=x1 * page_size.width / parser_width,
124
+ t=y1 * page_size.height / parser_height,
125
+ coord_origin=CoordOrigin.BOTTOMLEFT,
126
+ )
119
127
  ).to_top_left_origin(page_size.height),
120
128
  )
121
129
  )
@@ -0,0 +1,185 @@
1
+ import logging
2
+ import random
3
+ from io import BytesIO
4
+ from pathlib import Path
5
+ from typing import TYPE_CHECKING, Iterable, List, Optional, Union
6
+
7
+ import pypdfium2 as pdfium
8
+ from docling_core.types.doc import BoundingBox, CoordOrigin
9
+ from docling_core.types.doc.page import SegmentedPdfPage, TextCell
10
+ from docling_parse.pdf_parser import DoclingPdfParser, PdfDocument
11
+ from PIL import Image, ImageDraw
12
+ from pypdfium2 import PdfPage
13
+
14
+ from docling.backend.pdf_backend import PdfDocumentBackend, PdfPageBackend
15
+ from docling.datamodel.base_models import Size
16
+ from docling.utils.locks import pypdfium2_lock
17
+
18
+ if TYPE_CHECKING:
19
+ from docling.datamodel.document import InputDocument
20
+
21
+ _log = logging.getLogger(__name__)
22
+
23
+
24
+ class DoclingParseV4PageBackend(PdfPageBackend):
25
+ def __init__(self, parsed_page: SegmentedPdfPage, page_obj: PdfPage):
26
+ self._ppage = page_obj
27
+ self._dpage = parsed_page
28
+ self.valid = parsed_page is not None
29
+
30
+ def is_valid(self) -> bool:
31
+ return self.valid
32
+
33
+ def get_text_in_rect(self, bbox: BoundingBox) -> str:
34
+ # Find intersecting cells on the page
35
+ text_piece = ""
36
+ page_size = self.get_size()
37
+
38
+ scale = (
39
+ 1 # FIX - Replace with param in get_text_in_rect across backends (optional)
40
+ )
41
+
42
+ for i, cell in enumerate(self._dpage.textline_cells):
43
+ cell_bbox = (
44
+ cell.rect.to_bounding_box()
45
+ .to_top_left_origin(page_height=page_size.height)
46
+ .scaled(scale)
47
+ )
48
+
49
+ overlap_frac = cell_bbox.intersection_area_with(bbox) / cell_bbox.area()
50
+
51
+ if overlap_frac > 0.5:
52
+ if len(text_piece) > 0:
53
+ text_piece += " "
54
+ text_piece += cell.text
55
+
56
+ return text_piece
57
+
58
+ def get_segmented_page(self) -> Optional[SegmentedPdfPage]:
59
+ return self._dpage
60
+
61
+ def get_text_cells(self) -> Iterable[TextCell]:
62
+ page_size = self.get_size()
63
+
64
+ [tc.to_top_left_origin(page_size.height) for tc in self._dpage.textline_cells]
65
+
66
+ # for cell in self._dpage.textline_cells:
67
+ # rect = cell.rect
68
+ #
69
+ # assert (
70
+ # rect.to_bounding_box().l <= rect.to_bounding_box().r
71
+ # ), f"left is > right on bounding box {rect.to_bounding_box()} of rect {rect}"
72
+ # assert (
73
+ # rect.to_bounding_box().t <= rect.to_bounding_box().b
74
+ # ), f"top is > bottom on bounding box {rect.to_bounding_box()} of rect {rect}"
75
+
76
+ return self._dpage.textline_cells
77
+
78
+ def get_bitmap_rects(self, scale: float = 1) -> Iterable[BoundingBox]:
79
+ AREA_THRESHOLD = 0 # 32 * 32
80
+
81
+ images = self._dpage.bitmap_resources
82
+
83
+ for img in images:
84
+ cropbox = img.rect.to_bounding_box().to_top_left_origin(
85
+ self.get_size().height
86
+ )
87
+
88
+ if cropbox.area() > AREA_THRESHOLD:
89
+ cropbox = cropbox.scaled(scale=scale)
90
+
91
+ yield cropbox
92
+
93
+ def get_page_image(
94
+ self, scale: float = 1, cropbox: Optional[BoundingBox] = None
95
+ ) -> Image.Image:
96
+
97
+ page_size = self.get_size()
98
+
99
+ if not cropbox:
100
+ cropbox = BoundingBox(
101
+ l=0,
102
+ r=page_size.width,
103
+ t=0,
104
+ b=page_size.height,
105
+ coord_origin=CoordOrigin.TOPLEFT,
106
+ )
107
+ padbox = BoundingBox(
108
+ l=0, r=0, t=0, b=0, coord_origin=CoordOrigin.BOTTOMLEFT
109
+ )
110
+ else:
111
+ padbox = cropbox.to_bottom_left_origin(page_size.height).model_copy()
112
+ padbox.r = page_size.width - padbox.r
113
+ padbox.t = page_size.height - padbox.t
114
+
115
+ image = (
116
+ self._ppage.render(
117
+ scale=scale * 1.5,
118
+ rotation=0, # no additional rotation
119
+ crop=padbox.as_tuple(),
120
+ )
121
+ .to_pil()
122
+ .resize(size=(round(cropbox.width * scale), round(cropbox.height * scale)))
123
+ ) # We resize the image from 1.5x the given scale to make it sharper.
124
+
125
+ return image
126
+
127
+ def get_size(self) -> Size:
128
+ return Size(
129
+ width=self._dpage.dimension.width,
130
+ height=self._dpage.dimension.height,
131
+ )
132
+
133
+ def unload(self):
134
+ self._ppage = None
135
+ self._dpage = None
136
+
137
+
138
+ class DoclingParseV4DocumentBackend(PdfDocumentBackend):
139
+ def __init__(self, in_doc: "InputDocument", path_or_stream: Union[BytesIO, Path]):
140
+ super().__init__(in_doc, path_or_stream)
141
+
142
+ with pypdfium2_lock:
143
+ self._pdoc = pdfium.PdfDocument(self.path_or_stream)
144
+ self.parser = DoclingPdfParser(loglevel="fatal")
145
+ self.dp_doc: PdfDocument = self.parser.load(path_or_stream=self.path_or_stream)
146
+ success = self.dp_doc is not None
147
+
148
+ if not success:
149
+ raise RuntimeError(
150
+ f"docling-parse v4 could not load document {self.document_hash}."
151
+ )
152
+
153
+ def page_count(self) -> int:
154
+ # return len(self._pdoc) # To be replaced with docling-parse API
155
+
156
+ len_1 = len(self._pdoc)
157
+ len_2 = self.dp_doc.number_of_pages()
158
+
159
+ if len_1 != len_2:
160
+ _log.error(f"Inconsistent number of pages: {len_1}!={len_2}")
161
+
162
+ return len_2
163
+
164
+ def load_page(
165
+ self, page_no: int, create_words: bool = True, create_textlines: bool = True
166
+ ) -> DoclingParseV4PageBackend:
167
+ with pypdfium2_lock:
168
+ return DoclingParseV4PageBackend(
169
+ self.dp_doc.get_page(
170
+ page_no + 1,
171
+ create_words=create_words,
172
+ create_textlines=create_textlines,
173
+ ),
174
+ self._pdoc[page_no],
175
+ )
176
+
177
+ def is_valid(self) -> bool:
178
+ return self.page_count() > 0
179
+
180
+ def unload(self):
181
+ super().unload()
182
+ self.dp_doc.unload()
183
+ with pypdfium2_lock:
184
+ self._pdoc.close()
185
+ self._pdoc = None
File without changes
File without changes
@@ -0,0 +1,271 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ """
4
+ Adapted from https://github.com/xiilei/dwml/blob/master/dwml/latex_dict.py
5
+ On 23/01/2025
6
+ """
7
+
8
+ from __future__ import unicode_literals
9
+
10
+ CHARS = ("{", "}", "_", "^", "#", "&", "$", "%", "~")
11
+
12
+ BLANK = ""
13
+ BACKSLASH = "\\"
14
+ ALN = "&"
15
+
16
+ CHR = {
17
+ # Unicode : Latex Math Symbols
18
+ # Top accents
19
+ "\u0300": "\\grave{{{0}}}",
20
+ "\u0301": "\\acute{{{0}}}",
21
+ "\u0302": "\\hat{{{0}}}",
22
+ "\u0303": "\\tilde{{{0}}}",
23
+ "\u0304": "\\bar{{{0}}}",
24
+ "\u0305": "\\overbar{{{0}}}",
25
+ "\u0306": "\\breve{{{0}}}",
26
+ "\u0307": "\\dot{{{0}}}",
27
+ "\u0308": "\\ddot{{{0}}}",
28
+ "\u0309": "\\ovhook{{{0}}}",
29
+ "\u030a": "\\ocirc{{{0}}}}",
30
+ "\u030c": "\\check{{{0}}}}",
31
+ "\u0310": "\\candra{{{0}}}",
32
+ "\u0312": "\\oturnedcomma{{{0}}}",
33
+ "\u0315": "\\ocommatopright{{{0}}}",
34
+ "\u031a": "\\droang{{{0}}}",
35
+ "\u0338": "\\not{{{0}}}",
36
+ "\u20d0": "\\leftharpoonaccent{{{0}}}",
37
+ "\u20d1": "\\rightharpoonaccent{{{0}}}",
38
+ "\u20d2": "\\vertoverlay{{{0}}}",
39
+ "\u20d6": "\\overleftarrow{{{0}}}",
40
+ "\u20d7": "\\vec{{{0}}}",
41
+ "\u20db": "\\dddot{{{0}}}",
42
+ "\u20dc": "\\ddddot{{{0}}}",
43
+ "\u20e1": "\\overleftrightarrow{{{0}}}",
44
+ "\u20e7": "\\annuity{{{0}}}",
45
+ "\u20e9": "\\widebridgeabove{{{0}}}",
46
+ "\u20f0": "\\asteraccent{{{0}}}",
47
+ # Bottom accents
48
+ "\u0330": "\\wideutilde{{{0}}}",
49
+ "\u0331": "\\underbar{{{0}}}",
50
+ "\u20e8": "\\threeunderdot{{{0}}}",
51
+ "\u20ec": "\\underrightharpoondown{{{0}}}",
52
+ "\u20ed": "\\underleftharpoondown{{{0}}}",
53
+ "\u20ee": "\\underledtarrow{{{0}}}",
54
+ "\u20ef": "\\underrightarrow{{{0}}}",
55
+ # Over | group
56
+ "\u23b4": "\\overbracket{{{0}}}",
57
+ "\u23dc": "\\overparen{{{0}}}",
58
+ "\u23de": "\\overbrace{{{0}}}",
59
+ # Under| group
60
+ "\u23b5": "\\underbracket{{{0}}}",
61
+ "\u23dd": "\\underparen{{{0}}}",
62
+ "\u23df": "\\underbrace{{{0}}}",
63
+ }
64
+
65
+ CHR_BO = {
66
+ # Big operators,
67
+ "\u2140": "\\Bbbsum",
68
+ "\u220f": "\\prod",
69
+ "\u2210": "\\coprod",
70
+ "\u2211": "\\sum",
71
+ "\u222b": "\\int",
72
+ "\u22c0": "\\bigwedge",
73
+ "\u22c1": "\\bigvee",
74
+ "\u22c2": "\\bigcap",
75
+ "\u22c3": "\\bigcup",
76
+ "\u2a00": "\\bigodot",
77
+ "\u2a01": "\\bigoplus",
78
+ "\u2a02": "\\bigotimes",
79
+ }
80
+
81
+ T = {
82
+ "\u2192": "\\rightarrow ",
83
+ # Greek letters
84
+ "\U0001d6fc": "\\alpha ",
85
+ "\U0001d6fd": "\\beta ",
86
+ "\U0001d6fe": "\\gamma ",
87
+ "\U0001d6ff": "\\theta ",
88
+ "\U0001d700": "\\epsilon ",
89
+ "\U0001d701": "\\zeta ",
90
+ "\U0001d702": "\\eta ",
91
+ "\U0001d703": "\\theta ",
92
+ "\U0001d704": "\\iota ",
93
+ "\U0001d705": "\\kappa ",
94
+ "\U0001d706": "\\lambda ",
95
+ "\U0001d707": "\\m ",
96
+ "\U0001d708": "\\n ",
97
+ "\U0001d709": "\\xi ",
98
+ "\U0001d70a": "\\omicron ",
99
+ "\U0001d70b": "\\pi ",
100
+ "\U0001d70c": "\\rho ",
101
+ "\U0001d70d": "\\varsigma ",
102
+ "\U0001d70e": "\\sigma ",
103
+ "\U0001d70f": "\\ta ",
104
+ "\U0001d710": "\\upsilon ",
105
+ "\U0001d711": "\\phi ",
106
+ "\U0001d712": "\\chi ",
107
+ "\U0001d713": "\\psi ",
108
+ "\U0001d714": "\\omega ",
109
+ "\U0001d715": "\\partial ",
110
+ "\U0001d716": "\\varepsilon ",
111
+ "\U0001d717": "\\vartheta ",
112
+ "\U0001d718": "\\varkappa ",
113
+ "\U0001d719": "\\varphi ",
114
+ "\U0001d71a": "\\varrho ",
115
+ "\U0001d71b": "\\varpi ",
116
+ # Relation symbols
117
+ "\u2190": "\\leftarrow ",
118
+ "\u2191": "\\uparrow ",
119
+ "\u2192": "\\rightarrow ",
120
+ "\u2193": "\\downright ",
121
+ "\u2194": "\\leftrightarrow ",
122
+ "\u2195": "\\updownarrow ",
123
+ "\u2196": "\\nwarrow ",
124
+ "\u2197": "\\nearrow ",
125
+ "\u2198": "\\searrow ",
126
+ "\u2199": "\\swarrow ",
127
+ "\u22ee": "\\vdots ",
128
+ "\u22ef": "\\cdots ",
129
+ "\u22f0": "\\adots ",
130
+ "\u22f1": "\\ddots ",
131
+ "\u2260": "\\ne ",
132
+ "\u2264": "\\leq ",
133
+ "\u2265": "\\geq ",
134
+ "\u2266": "\\leqq ",
135
+ "\u2267": "\\geqq ",
136
+ "\u2268": "\\lneqq ",
137
+ "\u2269": "\\gneqq ",
138
+ "\u226a": "\\ll ",
139
+ "\u226b": "\\gg ",
140
+ "\u2208": "\\in ",
141
+ "\u2209": "\\notin ",
142
+ "\u220b": "\\ni ",
143
+ "\u220c": "\\nni ",
144
+ # Ordinary symbols
145
+ "\u221e": "\\infty ",
146
+ # Binary relations
147
+ "\u00b1": "\\pm ",
148
+ "\u2213": "\\mp ",
149
+ # Italic, Latin, uppercase
150
+ "\U0001d434": "A",
151
+ "\U0001d435": "B",
152
+ "\U0001d436": "C",
153
+ "\U0001d437": "D",
154
+ "\U0001d438": "E",
155
+ "\U0001d439": "F",
156
+ "\U0001d43a": "G",
157
+ "\U0001d43b": "H",
158
+ "\U0001d43c": "I",
159
+ "\U0001d43d": "J",
160
+ "\U0001d43e": "K",
161
+ "\U0001d43f": "L",
162
+ "\U0001d440": "M",
163
+ "\U0001d441": "N",
164
+ "\U0001d442": "O",
165
+ "\U0001d443": "P",
166
+ "\U0001d444": "Q",
167
+ "\U0001d445": "R",
168
+ "\U0001d446": "S",
169
+ "\U0001d447": "T",
170
+ "\U0001d448": "U",
171
+ "\U0001d449": "V",
172
+ "\U0001d44a": "W",
173
+ "\U0001d44b": "X",
174
+ "\U0001d44c": "Y",
175
+ "\U0001d44d": "Z",
176
+ # Italic, Latin, lowercase
177
+ "\U0001d44e": "a",
178
+ "\U0001d44f": "b",
179
+ "\U0001d450": "c",
180
+ "\U0001d451": "d",
181
+ "\U0001d452": "e",
182
+ "\U0001d453": "f",
183
+ "\U0001d454": "g",
184
+ "\U0001d456": "i",
185
+ "\U0001d457": "j",
186
+ "\U0001d458": "k",
187
+ "\U0001d459": "l",
188
+ "\U0001d45a": "m",
189
+ "\U0001d45b": "n",
190
+ "\U0001d45c": "o",
191
+ "\U0001d45d": "p",
192
+ "\U0001d45e": "q",
193
+ "\U0001d45f": "r",
194
+ "\U0001d460": "s",
195
+ "\U0001d461": "t",
196
+ "\U0001d462": "u",
197
+ "\U0001d463": "v",
198
+ "\U0001d464": "w",
199
+ "\U0001d465": "x",
200
+ "\U0001d466": "y",
201
+ "\U0001d467": "z",
202
+ }
203
+
204
+ FUNC = {
205
+ "sin": "\\sin({fe})",
206
+ "cos": "\\cos({fe})",
207
+ "tan": "\\tan({fe})",
208
+ "arcsin": "\\arcsin({fe})",
209
+ "arccos": "\\arccos({fe})",
210
+ "arctan": "\\arctan({fe})",
211
+ "arccot": "\\arccot({fe})",
212
+ "sinh": "\\sinh({fe})",
213
+ "cosh": "\\cosh({fe})",
214
+ "tanh": "\\tanh({fe})",
215
+ "coth": "\\coth({fe})",
216
+ "sec": "\\sec({fe})",
217
+ "csc": "\\csc({fe})",
218
+ }
219
+
220
+ FUNC_PLACE = "{fe}"
221
+
222
+ BRK = "\\\\"
223
+
224
+ CHR_DEFAULT = {
225
+ "ACC_VAL": "\\hat{{{0}}}",
226
+ }
227
+
228
+ POS = {
229
+ "top": "\\overline{{{0}}}", # not sure
230
+ "bot": "\\underline{{{0}}}",
231
+ }
232
+
233
+ POS_DEFAULT = {
234
+ "BAR_VAL": "\\overline{{{0}}}",
235
+ }
236
+
237
+ SUB = "_{{{0}}}"
238
+
239
+ SUP = "^{{{0}}}"
240
+
241
+ F = {
242
+ "bar": "\\frac{{{num}}}{{{den}}}",
243
+ "skw": r"^{{{num}}}/_{{{den}}}",
244
+ "noBar": "\\genfrac{{}}{{}}{{0pt}}{{}}{{{num}}}{{{den}}}",
245
+ "lin": "{{{num}}}/{{{den}}}",
246
+ }
247
+ F_DEFAULT = "\\frac{{{num}}}{{{den}}}"
248
+
249
+ D = "\\left{left}{text}\\right{right}"
250
+
251
+ D_DEFAULT = {
252
+ "left": "(",
253
+ "right": ")",
254
+ "null": ".",
255
+ }
256
+
257
+ RAD = "\\sqrt[{deg}]{{{text}}}"
258
+ RAD_DEFAULT = "\\sqrt{{{text}}}"
259
+ ARR = "{text}"
260
+
261
+ LIM_FUNC = {
262
+ "lim": "\\lim_{{{lim}}}",
263
+ "max": "\\max_{{{lim}}}",
264
+ "min": "\\min_{{{lim}}}",
265
+ }
266
+
267
+ LIM_TO = ("\\rightarrow", "\\to")
268
+
269
+ LIM_UPP = "\\overset{{{lim}}}{{{text}}}"
270
+
271
+ M = "\\begin{{matrix}}{text}\\end{{matrix}}"