From 1b0ead69078030a0e4d25b51450ef2aa4a2e79fc Mon Sep 17 00:00:00 2001 From: Cesar Berrospi Ramis <75900930+ceberam@users.noreply.github.com> Date: Mon, 24 Feb 2025 12:38:29 +0100 Subject: [PATCH 01/13] fix(html): Parse text in div elements as TextItem (#1041) feat(html): Parse text in div elements as TextItem Signed-off-by: Cesar Berrospi Ramis <75900930+ceberam@users.noreply.github.com> --- docling/backend/html_backend.py | 45 +- .../docling_v2/example_06.html.itxt | 7 + .../docling_v2/example_06.html.json | 108 + .../groundtruth/docling_v2/example_06.html.md | 10 + .../docling_v2/wiki_duck.html.itxt | 919 ++--- .../docling_v2/wiki_duck.html.json | 2955 +++++++++-------- .../groundtruth/docling_v2/wiki_duck.html.md | 39 + tests/data/html/example_06.html | 12 + 8 files changed, 2291 insertions(+), 1804 deletions(-) create mode 100644 tests/data/groundtruth/docling_v2/example_06.html.itxt create mode 100644 tests/data/groundtruth/docling_v2/example_06.html.json create mode 100644 tests/data/groundtruth/docling_v2/example_06.html.md create mode 100644 tests/data/html/example_06.html diff --git a/docling/backend/html_backend.py b/docling/backend/html_backend.py index 5b7f5d81..00ef05b4 100644 --- a/docling/backend/html_backend.py +++ b/docling/backend/html_backend.py @@ -1,9 +1,10 @@ import logging from io import BytesIO from pathlib import Path -from typing import Optional, Union, cast +from typing import Final, Optional, Union, cast from bs4 import BeautifulSoup, NavigableString, PageElement, Tag +from bs4.element import PreformattedString from docling_core.types.doc import ( DocItem, DocItemLabel, @@ -22,12 +23,29 @@ from docling.datamodel.document import InputDocument _log = logging.getLogger(__name__) +# tags that generate NodeItem elements +TAGS_FOR_NODE_ITEMS: Final = [ + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "p", + "pre", + "ul", + "ol", + "li", + "table", + "figure", + "img", +] + class HTMLDocumentBackend(DeclarativeDocumentBackend): @override def __init__(self, in_doc: "InputDocument", path_or_stream: Union[BytesIO, Path]): super().__init__(in_doc, path_or_stream) - _log.debug("About to init HTML backend...") self.soup: Optional[Tag] = None # HTML file: self.path_or_stream = path_or_stream @@ -88,6 +106,7 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): assert self.soup is not None content = self.soup.body or self.soup # Replace
tags with newline characters + # TODO: remove style to avoid losing text from tags like i, b, span, ... for br in content("br"): br.replace_with(NavigableString("\n")) self.walk(content, doc) @@ -99,6 +118,7 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): def walk(self, tag: Tag, doc: DoclingDocument) -> None: # Iterate over elements in the body of the document + text: str = "" for element in tag.children: if isinstance(element, Tag): try: @@ -108,6 +128,25 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): f"Error processing child from tag{tag.name}: {exc_child}" ) raise exc_child + elif isinstance(element, NavigableString) and not isinstance( + element, PreformattedString + ): + # Floating text outside paragraphs or analyzed tags + text += element + siblings: list[Tag] = [ + item for item in element.next_siblings if isinstance(item, Tag) + ] + if element.next_sibling is None or any( + [item.name in TAGS_FOR_NODE_ITEMS for item in siblings] + ): + text = text.strip() + if text and tag.name in ["div"]: + doc.add_text( + parent=self.parents[self.level], + label=DocItemLabel.PARAGRAPH, + text=text, + ) + text = "" return @@ -158,7 +197,7 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): text = element.text.strip() if hlevel == 1: - for key, val in self.parents.items(): + for key in self.parents.keys(): self.parents[key] = None self.level = 1 diff --git a/tests/data/groundtruth/docling_v2/example_06.html.itxt b/tests/data/groundtruth/docling_v2/example_06.html.itxt new file mode 100644 index 00000000..2ecad16f --- /dev/null +++ b/tests/data/groundtruth/docling_v2/example_06.html.itxt @@ -0,0 +1,7 @@ +item-0 at level 0: unspecified: group _root_ + item-1 at level 1: paragraph: This is a div with text. + item-2 at level 1: paragraph: This is another div with text. + item-3 at level 1: paragraph: This is a regular paragraph. + item-4 at level 1: paragraph: This is a third div +with a new line. + item-5 at level 1: paragraph: This is a fourth div with a bold paragraph. \ No newline at end of file diff --git a/tests/data/groundtruth/docling_v2/example_06.html.json b/tests/data/groundtruth/docling_v2/example_06.html.json new file mode 100644 index 00000000..03ce776b --- /dev/null +++ b/tests/data/groundtruth/docling_v2/example_06.html.json @@ -0,0 +1,108 @@ +{ + "schema_name": "DoclingDocument", + "version": "1.1.0", + "name": "example_06", + "origin": { + "mimetype": "text/html", + "binary_hash": 14574683870626799530, + "filename": "example_06.html" + }, + "furniture": { + "self_ref": "#/furniture", + "children": [], + "content_layer": "furniture", + "name": "_root_", + "label": "unspecified" + }, + "body": { + "self_ref": "#/body", + "children": [ + { + "$ref": "#/texts/0" + }, + { + "$ref": "#/texts/1" + }, + { + "$ref": "#/texts/2" + }, + { + "$ref": "#/texts/3" + }, + { + "$ref": "#/texts/4" + } + ], + "content_layer": "body", + "name": "_root_", + "label": "unspecified" + }, + "groups": [], + "texts": [ + { + "self_ref": "#/texts/0", + "parent": { + "$ref": "#/body" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "This is a div with text.", + "text": "This is a div with text." + }, + { + "self_ref": "#/texts/1", + "parent": { + "$ref": "#/body" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "This is another div with text.", + "text": "This is another div with text." + }, + { + "self_ref": "#/texts/2", + "parent": { + "$ref": "#/body" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "This is a regular paragraph.", + "text": "This is a regular paragraph." + }, + { + "self_ref": "#/texts/3", + "parent": { + "$ref": "#/body" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "This is a third div\nwith a new line.", + "text": "This is a third div\nwith a new line." + }, + { + "self_ref": "#/texts/4", + "parent": { + "$ref": "#/body" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "This is a fourth div with a bold paragraph.", + "text": "This is a fourth div with a bold paragraph." + } + ], + "pictures": [], + "tables": [], + "key_value_items": [], + "form_items": [], + "pages": {} +} \ No newline at end of file diff --git a/tests/data/groundtruth/docling_v2/example_06.html.md b/tests/data/groundtruth/docling_v2/example_06.html.md new file mode 100644 index 00000000..ed105e65 --- /dev/null +++ b/tests/data/groundtruth/docling_v2/example_06.html.md @@ -0,0 +1,10 @@ +This is a div with text. + +This is another div with text. + +This is a regular paragraph. + +This is a third div +with a new line. + +This is a fourth div with a bold paragraph. \ No newline at end of file diff --git a/tests/data/groundtruth/docling_v2/wiki_duck.html.itxt b/tests/data/groundtruth/docling_v2/wiki_duck.html.itxt index 3ae39e8c..4e22c090 100644 --- a/tests/data/groundtruth/docling_v2/wiki_duck.html.itxt +++ b/tests/data/groundtruth/docling_v2/wiki_duck.html.itxt @@ -1,474 +1,491 @@ item-0 at level 0: unspecified: group _root_ - item-1 at level 1: list: group list - item-2 at level 2: list_item: Main page - item-3 at level 2: list_item: Contents - item-4 at level 2: list_item: Current events - item-5 at level 2: list_item: Random article - item-6 at level 2: list_item: About Wikipedia - item-7 at level 2: list_item: Contact us - item-8 at level 1: list: group list - item-9 at level 2: list_item: Help - item-10 at level 2: list_item: Learn to edit - item-11 at level 2: list_item: Community portal - item-12 at level 2: list_item: Recent changes - item-13 at level 2: list_item: Upload file - item-14 at level 1: picture - item-15 at level 1: picture - item-16 at level 1: picture - item-17 at level 1: list: group list - item-18 at level 1: list: group list - item-19 at level 2: list_item: Donate + item-1 at level 1: paragraph: Main menu + item-2 at level 1: paragraph: Navigation + item-3 at level 1: list: group list + item-4 at level 2: list_item: Main page + item-5 at level 2: list_item: Contents + item-6 at level 2: list_item: Current events + item-7 at level 2: list_item: Random article + item-8 at level 2: list_item: About Wikipedia + item-9 at level 2: list_item: Contact us + item-10 at level 1: paragraph: Contribute + item-11 at level 1: list: group list + item-12 at level 2: list_item: Help + item-13 at level 2: list_item: Learn to edit + item-14 at level 2: list_item: Community portal + item-15 at level 2: list_item: Recent changes + item-16 at level 2: list_item: Upload file + item-17 at level 1: picture + item-18 at level 1: picture + item-19 at level 1: picture item-20 at level 1: list: group list item-21 at level 1: list: group list - item-22 at level 2: list_item: Create account - item-23 at level 2: list_item: Log in + item-22 at level 2: list_item: Donate + item-23 at level 1: list: group list item-24 at level 1: list: group list item-25 at level 2: list_item: Create account item-26 at level 2: list_item: Log in item-27 at level 1: list: group list - item-28 at level 2: list_item: Contributions - item-29 at level 2: list_item: Talk - item-30 at level 1: section: group header-1 - item-31 at level 2: section_header: Contents - item-32 at level 3: list: group list - item-33 at level 4: list_item: (Top) - item-34 at level 4: list_item: 1 Etymology - item-35 at level 5: list: group list - item-36 at level 4: list_item: 2 Taxonomy - item-37 at level 5: list: group list - item-38 at level 4: list_item: 3 Morphology + item-28 at level 2: list_item: Create account + item-29 at level 2: list_item: Log in + item-30 at level 1: paragraph: Pages for logged out editors + item-31 at level 1: list: group list + item-32 at level 2: list_item: Contributions + item-33 at level 2: list_item: Talk + item-34 at level 1: section: group header-1 + item-35 at level 2: section_header: Contents + item-36 at level 3: list: group list + item-37 at level 4: list_item: (Top) + item-38 at level 4: list_item: 1 Etymology item-39 at level 5: list: group list - item-40 at level 4: list_item: 4 Distribution and habitat + item-40 at level 4: list_item: 2 Taxonomy item-41 at level 5: list: group list - item-42 at level 4: list_item: 5 Behaviour Toggle Behaviour subsection + item-42 at level 4: list_item: 3 Morphology item-43 at level 5: list: group list - item-44 at level 6: list_item: 5.1 Feeding - item-45 at level 7: list: group list - item-46 at level 6: list_item: 5.2 Breeding - item-47 at level 7: list: group list - item-48 at level 6: list_item: 5.3 Communication + item-44 at level 4: list_item: 4 Distribution and habitat + item-45 at level 5: list: group list + item-46 at level 4: list_item: 5 Behaviour Toggle Behaviour subsection + item-47 at level 5: list: group list + item-48 at level 6: list_item: 5.1 Feeding item-49 at level 7: list: group list - item-50 at level 6: list_item: 5.4 Predators + item-50 at level 6: list_item: 5.2 Breeding item-51 at level 7: list: group list - item-52 at level 4: list_item: 6 Relationship with humans Toggle Relationship with humans subsection - item-53 at level 5: list: group list - item-54 at level 6: list_item: 6.1 Hunting + item-52 at level 6: list_item: 5.3 Communication + item-53 at level 7: list: group list + item-54 at level 6: list_item: 5.4 Predators item-55 at level 7: list: group list - item-56 at level 6: list_item: 6.2 Domestication - item-57 at level 7: list: group list - item-58 at level 6: list_item: 6.3 Heraldry + item-56 at level 4: list_item: 6 Relationship with humans Toggle Relationship with humans subsection + item-57 at level 5: list: group list + item-58 at level 6: list_item: 6.1 Hunting item-59 at level 7: list: group list - item-60 at level 6: list_item: 6.4 Cultural references + item-60 at level 6: list_item: 6.2 Domestication item-61 at level 7: list: group list - item-62 at level 4: list_item: 7 See also - item-63 at level 5: list: group list - item-64 at level 4: list_item: 8 Notes Toggle Notes subsection - item-65 at level 5: list: group list - item-66 at level 6: list_item: 8.1 Citations - item-67 at level 7: list: group list - item-68 at level 6: list_item: 8.2 Sources - item-69 at level 7: list: group list - item-70 at level 4: list_item: 9 External links - item-71 at level 5: list: group list - item-72 at level 1: title: Duck - item-73 at level 2: list: group list - item-74 at level 3: list_item: Acèh - item-75 at level 3: list_item: Afrikaans - item-76 at level 3: list_item: Alemannisch - item-77 at level 3: list_item: አማርኛ - item-78 at level 3: list_item: Ænglisc - item-79 at level 3: list_item: العربية - item-80 at level 3: list_item: Aragonés - item-81 at level 3: list_item: ܐܪܡܝܐ - item-82 at level 3: list_item: Armãneashti - item-83 at level 3: list_item: Asturianu - item-84 at level 3: list_item: Atikamekw - item-85 at level 3: list_item: Авар - item-86 at level 3: list_item: Aymar aru - item-87 at level 3: list_item: تۆرکجه - item-88 at level 3: list_item: Basa Bali - item-89 at level 3: list_item: বাংলা - item-90 at level 3: list_item: 閩南語 / Bân-lâm-gú - item-91 at level 3: list_item: Беларуская - item-92 at level 3: list_item: Беларуская (тарашкевіца) - item-93 at level 3: list_item: Bikol Central - item-94 at level 3: list_item: Български - item-95 at level 3: list_item: Brezhoneg - item-96 at level 3: list_item: Буряад - item-97 at level 3: list_item: Català - item-98 at level 3: list_item: Чӑвашла - item-99 at level 3: list_item: Čeština - item-100 at level 3: list_item: ChiShona - item-101 at level 3: list_item: Cymraeg - item-102 at level 3: list_item: Dagbanli - item-103 at level 3: list_item: Dansk - item-104 at level 3: list_item: Deitsch - item-105 at level 3: list_item: Deutsch - item-106 at level 3: list_item: डोटेली - item-107 at level 3: list_item: Ελληνικά - item-108 at level 3: list_item: Emiliàn e rumagnòl - item-109 at level 3: list_item: Español - item-110 at level 3: list_item: Esperanto - item-111 at level 3: list_item: Euskara - item-112 at level 3: list_item: فارسی - item-113 at level 3: list_item: Français - item-114 at level 3: list_item: Gaeilge - item-115 at level 3: list_item: Galego - item-116 at level 3: list_item: ГӀалгӀай - item-117 at level 3: list_item: 贛語 - item-118 at level 3: list_item: گیلکی - item-119 at level 3: list_item: 𐌲𐌿𐍄𐌹𐍃𐌺 - item-120 at level 3: list_item: गोंयची कोंकणी / Gõychi Konknni - item-121 at level 3: list_item: 客家語 / Hak-kâ-ngî - item-122 at level 3: list_item: 한국어 - item-123 at level 3: list_item: Hausa - item-124 at level 3: list_item: Հայերեն - item-125 at level 3: list_item: हिन्दी - item-126 at level 3: list_item: Hrvatski - item-127 at level 3: list_item: Ido - item-128 at level 3: list_item: Bahasa Indonesia - item-129 at level 3: list_item: Iñupiatun - item-130 at level 3: list_item: Íslenska - item-131 at level 3: list_item: Italiano - item-132 at level 3: list_item: עברית - item-133 at level 3: list_item: Jawa - item-134 at level 3: list_item: ಕನ್ನಡ - item-135 at level 3: list_item: Kapampangan - item-136 at level 3: list_item: ქართული - item-137 at level 3: list_item: कॉशुर / کٲشُر - item-138 at level 3: list_item: Қазақша - item-139 at level 3: list_item: Ikirundi - item-140 at level 3: list_item: Kongo - item-141 at level 3: list_item: Kreyòl ayisyen - item-142 at level 3: list_item: Кырык мары - item-143 at level 3: list_item: ລາວ - item-144 at level 3: list_item: Latina - item-145 at level 3: list_item: Latviešu - item-146 at level 3: list_item: Lietuvių - item-147 at level 3: list_item: Li Niha - item-148 at level 3: list_item: Ligure - item-149 at level 3: list_item: Limburgs - item-150 at level 3: list_item: Lingála - item-151 at level 3: list_item: Malagasy - item-152 at level 3: list_item: മലയാളം - item-153 at level 3: list_item: मराठी - item-154 at level 3: list_item: مازِرونی - item-155 at level 3: list_item: Bahasa Melayu - item-156 at level 3: list_item: ꯃꯤꯇꯩ ꯂꯣꯟ - item-157 at level 3: list_item: 閩東語 / Mìng-dĕ̤ng-ngṳ̄ - item-158 at level 3: list_item: Мокшень - item-159 at level 3: list_item: Монгол - item-160 at level 3: list_item: မြန်မာဘာသာ - item-161 at level 3: list_item: Nederlands - item-162 at level 3: list_item: Nedersaksies - item-163 at level 3: list_item: नेपाली - item-164 at level 3: list_item: नेपाल भाषा - item-165 at level 3: list_item: 日本語 - item-166 at level 3: list_item: Нохчийн - item-167 at level 3: list_item: Norsk nynorsk - item-168 at level 3: list_item: Occitan - item-169 at level 3: list_item: Oromoo - item-170 at level 3: list_item: ਪੰਜਾਬੀ - item-171 at level 3: list_item: Picard - item-172 at level 3: list_item: Plattdüütsch - item-173 at level 3: list_item: Polski - item-174 at level 3: list_item: Português - item-175 at level 3: list_item: Qırımtatarca - item-176 at level 3: list_item: Română - item-177 at level 3: list_item: Русский - item-178 at level 3: list_item: Саха тыла - item-179 at level 3: list_item: ᱥᱟᱱᱛᱟᱲᱤ - item-180 at level 3: list_item: Sardu - item-181 at level 3: list_item: Scots - item-182 at level 3: list_item: Seeltersk - item-183 at level 3: list_item: Shqip - item-184 at level 3: list_item: Sicilianu - item-185 at level 3: list_item: සිංහල - item-186 at level 3: list_item: Simple English - item-187 at level 3: list_item: سنڌي - item-188 at level 3: list_item: کوردی - item-189 at level 3: list_item: Српски / srpski - item-190 at level 3: list_item: Srpskohrvatski / српскохрватски - item-191 at level 3: list_item: Sunda - item-192 at level 3: list_item: Svenska - item-193 at level 3: list_item: Tagalog - item-194 at level 3: list_item: தமிழ் - item-195 at level 3: list_item: Taqbaylit - item-196 at level 3: list_item: Татарча / tatarça - item-197 at level 3: list_item: ไทย - item-198 at level 3: list_item: Türkçe - item-199 at level 3: list_item: Українська - item-200 at level 3: list_item: ئۇيغۇرچە / Uyghurche - item-201 at level 3: list_item: Vahcuengh - item-202 at level 3: list_item: Tiếng Việt - item-203 at level 3: list_item: Walon - item-204 at level 3: list_item: 文言 - item-205 at level 3: list_item: Winaray - item-206 at level 3: list_item: 吴语 - item-207 at level 3: list_item: 粵語 - item-208 at level 3: list_item: Žemaitėška - item-209 at level 3: list_item: 中文 - item-210 at level 2: list: group list - item-211 at level 3: list_item: Article - item-212 at level 3: list_item: Talk - item-213 at level 2: list: group list + item-62 at level 6: list_item: 6.3 Heraldry + item-63 at level 7: list: group list + item-64 at level 6: list_item: 6.4 Cultural references + item-65 at level 7: list: group list + item-66 at level 4: list_item: 7 See also + item-67 at level 5: list: group list + item-68 at level 4: list_item: 8 Notes Toggle Notes subsection + item-69 at level 5: list: group list + item-70 at level 6: list_item: 8.1 Citations + item-71 at level 7: list: group list + item-72 at level 6: list_item: 8.2 Sources + item-73 at level 7: list: group list + item-74 at level 4: list_item: 9 External links + item-75 at level 5: list: group list + item-76 at level 1: title: Duck + item-77 at level 2: list: group list + item-78 at level 3: list_item: Acèh + item-79 at level 3: list_item: Afrikaans + item-80 at level 3: list_item: Alemannisch + item-81 at level 3: list_item: አማርኛ + item-82 at level 3: list_item: Ænglisc + item-83 at level 3: list_item: العربية + item-84 at level 3: list_item: Aragonés + item-85 at level 3: list_item: ܐܪܡܝܐ + item-86 at level 3: list_item: Armãneashti + item-87 at level 3: list_item: Asturianu + item-88 at level 3: list_item: Atikamekw + item-89 at level 3: list_item: Авар + item-90 at level 3: list_item: Aymar aru + item-91 at level 3: list_item: تۆرکجه + item-92 at level 3: list_item: Basa Bali + item-93 at level 3: list_item: বাংলা + item-94 at level 3: list_item: 閩南語 / Bân-lâm-gú + item-95 at level 3: list_item: Беларуская + item-96 at level 3: list_item: Беларуская (тарашкевіца) + item-97 at level 3: list_item: Bikol Central + item-98 at level 3: list_item: Български + item-99 at level 3: list_item: Brezhoneg + item-100 at level 3: list_item: Буряад + item-101 at level 3: list_item: Català + item-102 at level 3: list_item: Чӑвашла + item-103 at level 3: list_item: Čeština + item-104 at level 3: list_item: ChiShona + item-105 at level 3: list_item: Cymraeg + item-106 at level 3: list_item: Dagbanli + item-107 at level 3: list_item: Dansk + item-108 at level 3: list_item: Deitsch + item-109 at level 3: list_item: Deutsch + item-110 at level 3: list_item: डोटेली + item-111 at level 3: list_item: Ελληνικά + item-112 at level 3: list_item: Emiliàn e rumagnòl + item-113 at level 3: list_item: Español + item-114 at level 3: list_item: Esperanto + item-115 at level 3: list_item: Euskara + item-116 at level 3: list_item: فارسی + item-117 at level 3: list_item: Français + item-118 at level 3: list_item: Gaeilge + item-119 at level 3: list_item: Galego + item-120 at level 3: list_item: ГӀалгӀай + item-121 at level 3: list_item: 贛語 + item-122 at level 3: list_item: گیلکی + item-123 at level 3: list_item: 𐌲𐌿𐍄𐌹𐍃𐌺 + item-124 at level 3: list_item: गोंयची कोंकणी / Gõychi Konknni + item-125 at level 3: list_item: 客家語 / Hak-kâ-ngî + item-126 at level 3: list_item: 한국어 + item-127 at level 3: list_item: Hausa + item-128 at level 3: list_item: Հայերեն + item-129 at level 3: list_item: हिन्दी + item-130 at level 3: list_item: Hrvatski + item-131 at level 3: list_item: Ido + item-132 at level 3: list_item: Bahasa Indonesia + item-133 at level 3: list_item: Iñupiatun + item-134 at level 3: list_item: Íslenska + item-135 at level 3: list_item: Italiano + item-136 at level 3: list_item: עברית + item-137 at level 3: list_item: Jawa + item-138 at level 3: list_item: ಕನ್ನಡ + item-139 at level 3: list_item: Kapampangan + item-140 at level 3: list_item: ქართული + item-141 at level 3: list_item: कॉशुर / کٲشُر + item-142 at level 3: list_item: Қазақша + item-143 at level 3: list_item: Ikirundi + item-144 at level 3: list_item: Kongo + item-145 at level 3: list_item: Kreyòl ayisyen + item-146 at level 3: list_item: Кырык мары + item-147 at level 3: list_item: ລາວ + item-148 at level 3: list_item: Latina + item-149 at level 3: list_item: Latviešu + item-150 at level 3: list_item: Lietuvių + item-151 at level 3: list_item: Li Niha + item-152 at level 3: list_item: Ligure + item-153 at level 3: list_item: Limburgs + item-154 at level 3: list_item: Lingála + item-155 at level 3: list_item: Malagasy + item-156 at level 3: list_item: മലയാളം + item-157 at level 3: list_item: मराठी + item-158 at level 3: list_item: مازِرونی + item-159 at level 3: list_item: Bahasa Melayu + item-160 at level 3: list_item: ꯃꯤꯇꯩ ꯂꯣꯟ + item-161 at level 3: list_item: 閩東語 / Mìng-dĕ̤ng-ngṳ̄ + item-162 at level 3: list_item: Мокшень + item-163 at level 3: list_item: Монгол + item-164 at level 3: list_item: မြန်မာဘာသာ + item-165 at level 3: list_item: Nederlands + item-166 at level 3: list_item: Nedersaksies + item-167 at level 3: list_item: नेपाली + item-168 at level 3: list_item: नेपाल भाषा + item-169 at level 3: list_item: 日本語 + item-170 at level 3: list_item: Нохчийн + item-171 at level 3: list_item: Norsk nynorsk + item-172 at level 3: list_item: Occitan + item-173 at level 3: list_item: Oromoo + item-174 at level 3: list_item: ਪੰਜਾਬੀ + item-175 at level 3: list_item: Picard + item-176 at level 3: list_item: Plattdüütsch + item-177 at level 3: list_item: Polski + item-178 at level 3: list_item: Português + item-179 at level 3: list_item: Qırımtatarca + item-180 at level 3: list_item: Română + item-181 at level 3: list_item: Русский + item-182 at level 3: list_item: Саха тыла + item-183 at level 3: list_item: ᱥᱟᱱᱛᱟᱲᱤ + item-184 at level 3: list_item: Sardu + item-185 at level 3: list_item: Scots + item-186 at level 3: list_item: Seeltersk + item-187 at level 3: list_item: Shqip + item-188 at level 3: list_item: Sicilianu + item-189 at level 3: list_item: සිංහල + item-190 at level 3: list_item: Simple English + item-191 at level 3: list_item: سنڌي + item-192 at level 3: list_item: کوردی + item-193 at level 3: list_item: Српски / srpski + item-194 at level 3: list_item: Srpskohrvatski / српскохрватски + item-195 at level 3: list_item: Sunda + item-196 at level 3: list_item: Svenska + item-197 at level 3: list_item: Tagalog + item-198 at level 3: list_item: தமிழ் + item-199 at level 3: list_item: Taqbaylit + item-200 at level 3: list_item: Татарча / tatarça + item-201 at level 3: list_item: ไทย + item-202 at level 3: list_item: Türkçe + item-203 at level 3: list_item: Українська + item-204 at level 3: list_item: ئۇيغۇرچە / Uyghurche + item-205 at level 3: list_item: Vahcuengh + item-206 at level 3: list_item: Tiếng Việt + item-207 at level 3: list_item: Walon + item-208 at level 3: list_item: 文言 + item-209 at level 3: list_item: Winaray + item-210 at level 3: list_item: 吴语 + item-211 at level 3: list_item: 粵語 + item-212 at level 3: list_item: Žemaitėška + item-213 at level 3: list_item: 中文 item-214 at level 2: list: group list - item-215 at level 3: list_item: Read - item-216 at level 3: list_item: View source - item-217 at level 3: list_item: View history + item-215 at level 3: list_item: Article + item-216 at level 3: list_item: Talk + item-217 at level 2: list: group list item-218 at level 2: list: group list item-219 at level 3: list_item: Read item-220 at level 3: list_item: View source item-221 at level 3: list_item: View history - item-222 at level 2: list: group list - item-223 at level 3: list_item: What links here - item-224 at level 3: list_item: Related changes - item-225 at level 3: list_item: Upload file - item-226 at level 3: list_item: Special pages - item-227 at level 3: list_item: Permanent link - item-228 at level 3: list_item: Page information - item-229 at level 3: list_item: Cite this page - item-230 at level 3: list_item: Get shortened URL - item-231 at level 3: list_item: Download QR code - item-232 at level 3: list_item: Wikidata item - item-233 at level 2: list: group list - item-234 at level 3: list_item: Download as PDF - item-235 at level 3: list_item: Printable version - item-236 at level 2: list: group list - item-237 at level 3: list_item: Wikimedia Commons - item-238 at level 3: list_item: Wikiquote - item-239 at level 2: picture - item-240 at level 2: table with [13x2] - item-241 at level 2: paragraph: Duck is the common name for nume ... und in both fresh water and sea water. - item-242 at level 2: paragraph: Ducks are sometimes confused wit ... divers, grebes, gallinules and coots. - item-243 at level 2: section_header: Etymology - item-244 at level 3: paragraph: The word duck comes from Old Eng ... h duiken and German tauchen 'to dive'. - item-245 at level 3: picture - item-245 at level 4: caption: Pacific black duck displaying the characteristic upending "duck" - item-246 at level 3: paragraph: This word replaced Old English e ... nskrit ātí 'water bird', among others. - item-247 at level 3: paragraph: A duckling is a young duck in do ... , is sometimes labelled as a duckling. - item-248 at level 3: paragraph: A male is called a drake and the ... a duck, or in ornithology a hen.[3][4] - item-249 at level 3: picture - item-249 at level 4: caption: Male mallard. - item-250 at level 3: picture - item-250 at level 4: caption: Wood ducks. - item-251 at level 2: section_header: Taxonomy - item-252 at level 3: paragraph: All ducks belong to the biologic ... ationships between various species.[9] - item-253 at level 3: picture - item-253 at level 4: caption: Mallard landing in approach - item-254 at level 3: paragraph: In most modern classifications, ... all size and stiff, upright tails.[14] - item-255 at level 3: paragraph: A number of other species called ... shelducks in the tribe Tadornini.[15] - item-256 at level 2: section_header: Morphology - item-257 at level 3: picture - item-257 at level 4: caption: Male Mandarin duck - item-258 at level 3: paragraph: The overall body plan of ducks i ... is moult typically precedes migration. - item-259 at level 3: paragraph: The drakes of northern species o ... rkscrew shaped vagina to prevent rape. - item-260 at level 2: section_header: Distribution and habitat - item-261 at level 3: picture - item-261 at level 4: caption: Flying steamer ducks in Ushuaia, Argentina - item-262 at level 3: paragraph: Ducks have a cosmopolitan distri ... endemic to such far-flung islands.[21] + item-222 at level 2: paragraph: Tools + item-223 at level 2: paragraph: Actions + item-224 at level 2: list: group list + item-225 at level 3: list_item: Read + item-226 at level 3: list_item: View source + item-227 at level 3: list_item: View history + item-228 at level 2: paragraph: General + item-229 at level 2: list: group list + item-230 at level 3: list_item: What links here + item-231 at level 3: list_item: Related changes + item-232 at level 3: list_item: Upload file + item-233 at level 3: list_item: Special pages + item-234 at level 3: list_item: Permanent link + item-235 at level 3: list_item: Page information + item-236 at level 3: list_item: Cite this page + item-237 at level 3: list_item: Get shortened URL + item-238 at level 3: list_item: Download QR code + item-239 at level 3: list_item: Wikidata item + item-240 at level 2: paragraph: Print/export + item-241 at level 2: list: group list + item-242 at level 3: list_item: Download as PDF + item-243 at level 3: list_item: Printable version + item-244 at level 2: paragraph: In other projects + item-245 at level 2: list: group list + item-246 at level 3: list_item: Wikimedia Commons + item-247 at level 3: list_item: Wikiquote + item-248 at level 2: paragraph: Appearance + item-249 at level 2: picture + item-250 at level 2: paragraph: From Wikipedia, the free encyclopedia + item-251 at level 2: paragraph: Common name for many species of bird + item-252 at level 2: paragraph: This article is about the bird. ... as a food, see . For other uses, see . + item-253 at level 2: paragraph: "Duckling" redirects here. For other uses, see . + item-254 at level 2: table with [13x2] + item-255 at level 2: paragraph: Duck is the common name for nume ... und in both fresh water and sea water. + item-256 at level 2: paragraph: Ducks are sometimes confused wit ... divers, grebes, gallinules and coots. + item-257 at level 2: section_header: Etymology + item-258 at level 3: paragraph: The word duck comes from Old Eng ... h duiken and German tauchen 'to dive'. + item-259 at level 3: picture + item-259 at level 4: caption: Pacific black duck displaying the characteristic upending "duck" + item-260 at level 3: paragraph: This word replaced Old English e ... nskrit ātí 'water bird', among others. + item-261 at level 3: paragraph: A duckling is a young duck in do ... , is sometimes labelled as a duckling. + item-262 at level 3: paragraph: A male is called a drake and the ... a duck, or in ornithology a hen.[3][4] item-263 at level 3: picture - item-263 at level 4: caption: Female mallard in Cornwall, England - item-264 at level 3: paragraph: Some duck species, mainly those ... t form after localised heavy rain.[23] - item-265 at level 2: section_header: Behaviour - item-266 at level 3: section_header: Feeding - item-267 at level 4: picture - item-267 at level 5: caption: Pecten along the bill - item-268 at level 4: picture - item-268 at level 5: caption: Mallard duckling preening - item-269 at level 4: paragraph: Ducks eat food sources such as g ... amphibians, worms, and small molluscs. - item-270 at level 4: paragraph: Dabbling ducks feed on the surfa ... thers and to hold slippery food items. - item-271 at level 4: paragraph: Diving ducks and sea ducks forag ... ave more difficulty taking off to fly. - item-272 at level 4: paragraph: A few specialized species such a ... apted to catch and swallow large fish. - item-273 at level 4: paragraph: The others have the characterist ... e nostrils come out through hard horn. - item-274 at level 4: paragraph: The Guardian published an articl ... the ducks and pollutes waterways.[25] - item-275 at level 3: section_header: Breeding - item-276 at level 4: picture - item-276 at level 5: caption: A Muscovy duckling - item-277 at level 4: paragraph: Ducks generally only have one pa ... st and led her ducklings to water.[28] - item-278 at level 3: section_header: Communication - item-279 at level 4: paragraph: Female mallard ducks (as well as ... laying calls or quieter contact calls. - item-280 at level 4: paragraph: A common urban legend claims tha ... annel television show MythBusters.[32] - item-281 at level 3: section_header: Predators + item-263 at level 4: caption: Male mallard. + item-264 at level 3: picture + item-264 at level 4: caption: Wood ducks. + item-265 at level 2: section_header: Taxonomy + item-266 at level 3: paragraph: All ducks belong to the biologic ... ationships between various species.[9] + item-267 at level 3: picture + item-267 at level 4: caption: Mallard landing in approach + item-268 at level 3: paragraph: In most modern classifications, ... all size and stiff, upright tails.[14] + item-269 at level 3: paragraph: A number of other species called ... shelducks in the tribe Tadornini.[15] + item-270 at level 2: section_header: Morphology + item-271 at level 3: picture + item-271 at level 4: caption: Male Mandarin duck + item-272 at level 3: paragraph: The overall body plan of ducks i ... is moult typically precedes migration. + item-273 at level 3: paragraph: The drakes of northern species o ... rkscrew shaped vagina to prevent rape. + item-274 at level 2: section_header: Distribution and habitat + item-275 at level 3: picture + item-275 at level 4: caption: Flying steamer ducks in Ushuaia, Argentina + item-276 at level 3: paragraph: Ducks have a cosmopolitan distri ... endemic to such far-flung islands.[21] + item-277 at level 3: picture + item-277 at level 4: caption: Female mallard in Cornwall, England + item-278 at level 3: paragraph: Some duck species, mainly those ... t form after localised heavy rain.[23] + item-279 at level 2: section_header: Behaviour + item-280 at level 3: section_header: Feeding + item-281 at level 4: picture + item-281 at level 5: caption: Pecten along the bill item-282 at level 4: picture - item-282 at level 5: caption: Ringed teal - item-283 at level 4: paragraph: Ducks have many predators. Duckl ... or large birds, such as hawks or owls. - item-284 at level 4: paragraph: Adult ducks are fast fliers, but ... its speed and strength to catch ducks. - item-285 at level 2: section_header: Relationship with humans - item-286 at level 3: section_header: Hunting - item-287 at level 4: paragraph: Humans have hunted ducks since p ... evidence of this is uncommon.[35][42] - item-288 at level 4: paragraph: In many areas, wild ducks (inclu ... inated by pollutants such as PCBs.[44] - item-289 at level 3: section_header: Domestication + item-282 at level 5: caption: Mallard duckling preening + item-283 at level 4: paragraph: Ducks eat food sources such as g ... amphibians, worms, and small molluscs. + item-284 at level 4: paragraph: Dabbling ducks feed on the surfa ... thers and to hold slippery food items. + item-285 at level 4: paragraph: Diving ducks and sea ducks forag ... ave more difficulty taking off to fly. + item-286 at level 4: paragraph: A few specialized species such a ... apted to catch and swallow large fish. + item-287 at level 4: paragraph: The others have the characterist ... e nostrils come out through hard horn. + item-288 at level 4: paragraph: The Guardian published an articl ... the ducks and pollutes waterways.[25] + item-289 at level 3: section_header: Breeding item-290 at level 4: picture - item-290 at level 5: caption: Indian Runner ducks, a common breed of domestic ducks - item-291 at level 4: paragraph: Ducks have many economic uses, b ... it weighs less than 1 kg (2.2 lb).[48] - item-292 at level 3: section_header: Heraldry - item-293 at level 4: picture - item-293 at level 5: caption: Three black-colored ducks in the coat of arms of Maaninka[49] - item-294 at level 4: paragraph: Ducks appear on several coats of ... the coat of arms of Föglö (Åland).[51] - item-295 at level 3: section_header: Cultural references - item-296 at level 4: paragraph: In 2002, psychologist Richard Wi ... 54] and was made into a movie in 1986. - item-297 at level 4: paragraph: The 1992 Disney film The Mighty ... Ducks minor league baseball team.[55] - item-298 at level 2: section_header: See also - item-299 at level 3: list: group list - item-300 at level 4: list_item: Birds portal - item-301 at level 3: list: group list - item-302 at level 4: list_item: Domestic duck - item-303 at level 4: list_item: Duck as food - item-304 at level 4: list_item: Duck test - item-305 at level 4: list_item: Duck breeds - item-306 at level 4: list_item: Fictional ducks - item-307 at level 4: list_item: Rubber duck - item-308 at level 2: section_header: Notes - item-309 at level 3: section_header: Citations - item-310 at level 4: ordered_list: group ordered list - item-311 at level 5: list_item: ^ "Duckling". The American Herit ... n Company. 2006. Retrieved 2015-05-22. - item-312 at level 5: list_item: ^ "Duckling". Kernerman English ... Ltd. 2000–2006. Retrieved 2015-05-22. - item-313 at level 5: list_item: ^ Dohner, Janet Vorwald (2001). ... University Press. ISBN 978-0300138139. - item-314 at level 5: list_item: ^ Visca, Curt; Visca, Kelley (20 ... Publishing Group. ISBN 9780823961566. - item-315 at level 5: list_item: ^ a b c d Carboneras 1992, p. 536. - item-316 at level 5: list_item: ^ Livezey 1986, pp. 737–738. - item-317 at level 5: list_item: ^ Madsen, McHugh & de Kloet 1988, p. 452. - item-318 at level 5: list_item: ^ Donne-Goussé, Laudet & Hänni 2002, pp. 353–354. - item-319 at level 5: list_item: ^ a b c d e f Carboneras 1992, p. 540. - item-320 at level 5: list_item: ^ Elphick, Dunning & Sibley 2001, p. 191. - item-321 at level 5: list_item: ^ Kear 2005, p. 448. - item-322 at level 5: list_item: ^ Kear 2005, p. 622–623. - item-323 at level 5: list_item: ^ Kear 2005, p. 686. - item-324 at level 5: list_item: ^ Elphick, Dunning & Sibley 2001, p. 193. - item-325 at level 5: list_item: ^ a b c d e f g Carboneras 1992, p. 537. - item-326 at level 5: list_item: ^ American Ornithologists' Union 1998, p. xix. - item-327 at level 5: list_item: ^ American Ornithologists' Union 1998. - item-328 at level 5: list_item: ^ Carboneras 1992, p. 538. - item-329 at level 5: list_item: ^ Christidis & Boles 2008, p. 62. - item-330 at level 5: list_item: ^ Shirihai 2008, pp. 239, 245. - item-331 at level 5: list_item: ^ a b Pratt, Bruner & Berrett 1987, pp. 98–107. - item-332 at level 5: list_item: ^ Fitter, Fitter & Hosking 2000, pp. 52–3. - item-333 at level 5: list_item: ^ "Pacific Black Duck". www.wiresnr.org. Retrieved 2018-04-27. - item-334 at level 5: list_item: ^ Ogden, Evans. "Dabbling Ducks". CWE. Retrieved 2006-11-02. - item-335 at level 5: list_item: ^ Karl Mathiesen (16 March 2015) ... Guardian. Retrieved 13 November 2016. - item-336 at level 5: list_item: ^ Rohwer, Frank C.; Anderson, Mi ... 4615-6787-5_4. ISBN 978-1-4615-6789-9. - item-337 at level 5: list_item: ^ Smith, Cyndi M.; Cooke, Fred; ... 093/condor/102.1.201. hdl:10315/13797. - item-338 at level 5: list_item: ^ "If You Find An Orphaned Duckl ... l on 2018-09-23. Retrieved 2018-12-22. - item-339 at level 5: list_item: ^ Carver, Heather (2011). The Du ...  9780557901562.[self-published source] - item-340 at level 5: list_item: ^ Titlow, Budd (2013-09-03). Bir ... man & Littlefield. ISBN 9780762797707. - item-341 at level 5: list_item: ^ Amos, Jonathan (2003-09-08). " ... kers". BBC News. Retrieved 2006-11-02. - item-342 at level 5: list_item: ^ "Mythbusters Episode 8". 12 December 2003. - item-343 at level 5: list_item: ^ Erlandson 1994, p. 171. - item-344 at level 5: list_item: ^ Jeffries 2008, pp. 168, 243. - item-345 at level 5: list_item: ^ a b Sued-Badillo 2003, p. 65. - item-346 at level 5: list_item: ^ Thorpe 1996, p. 68. - item-347 at level 5: list_item: ^ Maisels 1999, p. 42. - item-348 at level 5: list_item: ^ Rau 1876, p. 133. - item-349 at level 5: list_item: ^ Higman 2012, p. 23. - item-350 at level 5: list_item: ^ Hume 2012, p. 53. - item-351 at level 5: list_item: ^ Hume 2012, p. 52. - item-352 at level 5: list_item: ^ Fieldhouse 2002, p. 167. - item-353 at level 5: list_item: ^ Livingston, A. D. (1998-01-01) ... Editions, Limited. ISBN 9781853263774. - item-354 at level 5: list_item: ^ "Study plan for waterfowl inju ... on 2022-10-09. Retrieved 2 July 2019. - item-355 at level 5: list_item: ^ "FAOSTAT". www.fao.org. Retrieved 2019-10-25. - item-356 at level 5: list_item: ^ "Anas platyrhynchos, Domestic ... . Digimorph.org. Retrieved 2012-12-23. - item-357 at level 5: list_item: ^ Sy Montgomery. "Mallard; Encyc ... Britannica.com. Retrieved 2012-12-23. - item-358 at level 5: list_item: ^ Glenday, Craig (2014). Guinnes ... ited. pp. 135. ISBN 978-1-908843-15-9. - item-359 at level 5: list_item: ^ Suomen kunnallisvaakunat (in F ... tto. 1982. p. 147. ISBN 951-773-085-3. - item-360 at level 5: list_item: ^ "Lubānas simbolika" (in Latvian). Retrieved September 9, 2021. - item-361 at level 5: list_item: ^ "Föglö" (in Swedish). Retrieved September 9, 2021. - item-362 at level 5: list_item: ^ Young, Emma. "World's funniest ... w Scientist. Retrieved 7 January 2019. - item-363 at level 5: list_item: ^ "Howard the Duck (character)". Grand Comics Database. - item-364 at level 5: list_item: ^ Sanderson, Peter; Gilbert, Lau ... luding this bad-tempered talking duck. - item-365 at level 5: list_item: ^ "The Duck". University of Oregon Athletics. Retrieved 2022-01-20. - item-366 at level 3: section_header: Sources - item-367 at level 4: list: group list - item-368 at level 5: list_item: American Ornithologists' Union ( ... (PDF) from the original on 2022-10-09. - item-369 at level 5: list_item: Carboneras, Carlos (1992). del H ... Lynx Edicions. ISBN 978-84-87334-10-8. - item-370 at level 5: list_item: Christidis, Les; Boles, Walter E ... ro Publishing. ISBN 978-0-643-06511-6. - item-371 at level 5: list_item: Donne-Goussé, Carole; Laudet, Vi ... /S1055-7903(02)00019-2. PMID 12099792. - item-372 at level 5: list_item: Elphick, Chris; Dunning, John B. ... istopher Helm. ISBN 978-0-7136-6250-4. - item-373 at level 5: list_item: Erlandson, Jon M. (1994). Early ... usiness Media. ISBN 978-1-4419-3231-0. - item-374 at level 5: list_item: Fieldhouse, Paul (2002). Food, F ... ara: ABC-CLIO. ISBN 978-1-61069-412-4. - item-375 at level 5: list_item: Fitter, Julian; Fitter, Daniel; ... versity Press. ISBN 978-0-691-10295-5. - item-376 at level 5: list_item: Higman, B. W. (2012). How Food M ... Wiley & Sons. ISBN 978-1-4051-8947-7. - item-377 at level 5: list_item: Hume, Julian H. (2012). Extinct ... istopher Helm. ISBN 978-1-4729-3744-5. - item-378 at level 5: list_item: Jeffries, Richard (2008). Holoce ... Alabama Press. ISBN 978-0-8173-1658-7. - item-379 at level 5: list_item: Kear, Janet, ed. (2005). Ducks, ... versity Press. ISBN 978-0-19-861009-0. - item-380 at level 5: list_item: Livezey, Bradley C. (October 198 ... (PDF) from the original on 2022-10-09. - item-381 at level 5: list_item: Madsen, Cort S.; McHugh, Kevin P ... (PDF) from the original on 2022-10-09. - item-382 at level 5: list_item: Maisels, Charles Keith (1999). E ... on: Routledge. ISBN 978-0-415-10975-8. - item-383 at level 5: list_item: Pratt, H. Douglas; Bruner, Phill ... University Press. ISBN 0-691-02399-9. - item-384 at level 5: list_item: Rau, Charles (1876). Early Man i ... ork: Harper & Brothers. LCCN 05040168. - item-385 at level 5: list_item: Shirihai, Hadoram (2008). A Comp ... versity Press. ISBN 978-0-691-13666-0. - item-386 at level 5: list_item: Sued-Badillo, Jalil (2003). Auto ... Paris: UNESCO. ISBN 978-92-3-103832-7. - item-387 at level 5: list_item: Thorpe, I. J. (1996). The Origin ... rk: Routledge. ISBN 978-0-415-08009-5. - item-388 at level 2: section_header: External links - item-389 at level 3: list: group list - item-390 at level 4: list_item: Definitions from Wiktionary - item-391 at level 4: list_item: Media from Commons - item-392 at level 4: list_item: Quotations from Wikiquote - item-393 at level 4: list_item: Recipes from Wikibooks - item-394 at level 4: list_item: Taxa from Wikispecies - item-395 at level 4: list_item: Data from Wikidata - item-396 at level 3: list: group list - item-397 at level 4: list_item: list of books (useful looking abstracts) - item-398 at level 4: list_item: Ducks on postage stamps Archived 2013-05-13 at the Wayback Machine - item-399 at level 4: list_item: Ducks at a Distance, by Rob Hine ... uide to identification of US waterfowl - item-400 at level 3: table with [3x2] - item-401 at level 3: picture - item-402 at level 3: list: group list - item-403 at level 4: list_item: Ducks - item-404 at level 4: list_item: Game birds - item-405 at level 4: list_item: Bird common names - item-406 at level 3: list: group list - item-407 at level 4: list_item: All accuracy disputes - item-408 at level 4: list_item: Accuracy disputes from February 2020 - item-409 at level 4: list_item: CS1 Finnish-language sources (fi) - item-410 at level 4: list_item: CS1 Latvian-language sources (lv) - item-411 at level 4: list_item: CS1 Swedish-language sources (sv) - item-412 at level 4: list_item: Articles with short description - item-413 at level 4: list_item: Short description is different from Wikidata - item-414 at level 4: list_item: Wikipedia indefinitely move-protected pages - item-415 at level 4: list_item: Wikipedia indefinitely semi-protected pages - item-416 at level 4: list_item: Articles with 'species' microformats - item-417 at level 4: list_item: Articles containing Old English (ca. 450-1100)-language text - item-418 at level 4: list_item: Articles containing Dutch-language text - item-419 at level 4: list_item: Articles containing German-language text - item-420 at level 4: list_item: Articles containing Norwegian-language text - item-421 at level 4: list_item: Articles containing Lithuanian-language text - item-422 at level 4: list_item: Articles containing Ancient Greek (to 1453)-language text - item-423 at level 4: list_item: All articles with self-published sources - item-424 at level 4: list_item: Articles with self-published sources from February 2020 - item-425 at level 4: list_item: All articles with unsourced statements - item-426 at level 4: list_item: Articles with unsourced statements from January 2022 - item-427 at level 4: list_item: CS1: long volume value - item-428 at level 4: list_item: Pages using Sister project links with wikidata mismatch - item-429 at level 4: list_item: Pages using Sister project links with hidden wikidata - item-430 at level 4: list_item: Webarchive template wayback links - item-431 at level 4: list_item: Articles with Project Gutenberg links - item-432 at level 4: list_item: Articles containing video clips - item-433 at level 3: list: group list - item-434 at level 4: list_item: This page was last edited on 21 September 2024, at 12:11 (UTC). - item-435 at level 4: list_item: Text is available under the Crea ... tion, Inc., a non-profit organization. - item-436 at level 3: list: group list - item-437 at level 4: list_item: Privacy policy - item-438 at level 4: list_item: About Wikipedia - item-439 at level 4: list_item: Disclaimers - item-440 at level 4: list_item: Contact Wikipedia - item-441 at level 4: list_item: Code of Conduct - item-442 at level 4: list_item: Developers - item-443 at level 4: list_item: Statistics - item-444 at level 4: list_item: Cookie statement - item-445 at level 4: list_item: Mobile view - item-446 at level 3: list: group list - item-447 at level 3: list: group list - item-448 at level 1: caption: Pacific black duck displaying the characteristic upending "duck" - item-449 at level 1: caption: Male mallard. - item-450 at level 1: caption: Wood ducks. - item-451 at level 1: caption: Mallard landing in approach - item-452 at level 1: caption: Male Mandarin duck - item-453 at level 1: caption: Flying steamer ducks in Ushuaia, Argentina - item-454 at level 1: caption: Female mallard in Cornwall, England - item-455 at level 1: caption: Pecten along the bill - item-456 at level 1: caption: Mallard duckling preening - item-457 at level 1: caption: A Muscovy duckling - item-458 at level 1: caption: Ringed teal - item-459 at level 1: caption: Indian Runner ducks, a common breed of domestic ducks - item-460 at level 1: caption: Three black-colored ducks in the coat of arms of Maaninka[49] \ No newline at end of file + item-290 at level 5: caption: A Muscovy duckling + item-291 at level 4: paragraph: Ducks generally only have one pa ... st and led her ducklings to water.[28] + item-292 at level 3: section_header: Communication + item-293 at level 4: paragraph: Female mallard ducks (as well as ... laying calls or quieter contact calls. + item-294 at level 4: paragraph: A common urban legend claims tha ... annel television show MythBusters.[32] + item-295 at level 3: section_header: Predators + item-296 at level 4: picture + item-296 at level 5: caption: Ringed teal + item-297 at level 4: paragraph: Ducks have many predators. Duckl ... or large birds, such as hawks or owls. + item-298 at level 4: paragraph: Adult ducks are fast fliers, but ... its speed and strength to catch ducks. + item-299 at level 2: section_header: Relationship with humans + item-300 at level 3: section_header: Hunting + item-301 at level 4: paragraph: Humans have hunted ducks since p ... evidence of this is uncommon.[35][42] + item-302 at level 4: paragraph: In many areas, wild ducks (inclu ... inated by pollutants such as PCBs.[44] + item-303 at level 3: section_header: Domestication + item-304 at level 4: picture + item-304 at level 5: caption: Indian Runner ducks, a common breed of domestic ducks + item-305 at level 4: paragraph: Ducks have many economic uses, b ... it weighs less than 1 kg (2.2 lb).[48] + item-306 at level 3: section_header: Heraldry + item-307 at level 4: picture + item-307 at level 5: caption: Three black-colored ducks in the coat of arms of Maaninka[49] + item-308 at level 4: paragraph: Ducks appear on several coats of ... the coat of arms of Föglö (Åland).[51] + item-309 at level 3: section_header: Cultural references + item-310 at level 4: paragraph: In 2002, psychologist Richard Wi ... 54] and was made into a movie in 1986. + item-311 at level 4: paragraph: The 1992 Disney film The Mighty ... Ducks minor league baseball team.[55] + item-312 at level 2: section_header: See also + item-313 at level 3: list: group list + item-314 at level 4: list_item: Birds portal + item-315 at level 3: list: group list + item-316 at level 4: list_item: Domestic duck + item-317 at level 4: list_item: Duck as food + item-318 at level 4: list_item: Duck test + item-319 at level 4: list_item: Duck breeds + item-320 at level 4: list_item: Fictional ducks + item-321 at level 4: list_item: Rubber duck + item-322 at level 2: section_header: Notes + item-323 at level 3: section_header: Citations + item-324 at level 4: ordered_list: group ordered list + item-325 at level 5: list_item: ^ "Duckling". The American Herit ... n Company. 2006. Retrieved 2015-05-22. + item-326 at level 5: list_item: ^ "Duckling". Kernerman English ... Ltd. 2000–2006. Retrieved 2015-05-22. + item-327 at level 5: list_item: ^ Dohner, Janet Vorwald (2001). ... University Press. ISBN 978-0300138139. + item-328 at level 5: list_item: ^ Visca, Curt; Visca, Kelley (20 ... Publishing Group. ISBN 9780823961566. + item-329 at level 5: list_item: ^ a b c d Carboneras 1992, p. 536. + item-330 at level 5: list_item: ^ Livezey 1986, pp. 737–738. + item-331 at level 5: list_item: ^ Madsen, McHugh & de Kloet 1988, p. 452. + item-332 at level 5: list_item: ^ Donne-Goussé, Laudet & Hänni 2002, pp. 353–354. + item-333 at level 5: list_item: ^ a b c d e f Carboneras 1992, p. 540. + item-334 at level 5: list_item: ^ Elphick, Dunning & Sibley 2001, p. 191. + item-335 at level 5: list_item: ^ Kear 2005, p. 448. + item-336 at level 5: list_item: ^ Kear 2005, p. 622–623. + item-337 at level 5: list_item: ^ Kear 2005, p. 686. + item-338 at level 5: list_item: ^ Elphick, Dunning & Sibley 2001, p. 193. + item-339 at level 5: list_item: ^ a b c d e f g Carboneras 1992, p. 537. + item-340 at level 5: list_item: ^ American Ornithologists' Union 1998, p. xix. + item-341 at level 5: list_item: ^ American Ornithologists' Union 1998. + item-342 at level 5: list_item: ^ Carboneras 1992, p. 538. + item-343 at level 5: list_item: ^ Christidis & Boles 2008, p. 62. + item-344 at level 5: list_item: ^ Shirihai 2008, pp. 239, 245. + item-345 at level 5: list_item: ^ a b Pratt, Bruner & Berrett 1987, pp. 98–107. + item-346 at level 5: list_item: ^ Fitter, Fitter & Hosking 2000, pp. 52–3. + item-347 at level 5: list_item: ^ "Pacific Black Duck". www.wiresnr.org. Retrieved 2018-04-27. + item-348 at level 5: list_item: ^ Ogden, Evans. "Dabbling Ducks". CWE. Retrieved 2006-11-02. + item-349 at level 5: list_item: ^ Karl Mathiesen (16 March 2015) ... Guardian. Retrieved 13 November 2016. + item-350 at level 5: list_item: ^ Rohwer, Frank C.; Anderson, Mi ... 4615-6787-5_4. ISBN 978-1-4615-6789-9. + item-351 at level 5: list_item: ^ Smith, Cyndi M.; Cooke, Fred; ... 093/condor/102.1.201. hdl:10315/13797. + item-352 at level 5: list_item: ^ "If You Find An Orphaned Duckl ... l on 2018-09-23. Retrieved 2018-12-22. + item-353 at level 5: list_item: ^ Carver, Heather (2011). The Du ...  9780557901562.[self-published source] + item-354 at level 5: list_item: ^ Titlow, Budd (2013-09-03). Bir ... man & Littlefield. ISBN 9780762797707. + item-355 at level 5: list_item: ^ Amos, Jonathan (2003-09-08). " ... kers". BBC News. Retrieved 2006-11-02. + item-356 at level 5: list_item: ^ "Mythbusters Episode 8". 12 December 2003. + item-357 at level 5: list_item: ^ Erlandson 1994, p. 171. + item-358 at level 5: list_item: ^ Jeffries 2008, pp. 168, 243. + item-359 at level 5: list_item: ^ a b Sued-Badillo 2003, p. 65. + item-360 at level 5: list_item: ^ Thorpe 1996, p. 68. + item-361 at level 5: list_item: ^ Maisels 1999, p. 42. + item-362 at level 5: list_item: ^ Rau 1876, p. 133. + item-363 at level 5: list_item: ^ Higman 2012, p. 23. + item-364 at level 5: list_item: ^ Hume 2012, p. 53. + item-365 at level 5: list_item: ^ Hume 2012, p. 52. + item-366 at level 5: list_item: ^ Fieldhouse 2002, p. 167. + item-367 at level 5: list_item: ^ Livingston, A. D. (1998-01-01) ... Editions, Limited. ISBN 9781853263774. + item-368 at level 5: list_item: ^ "Study plan for waterfowl inju ... on 2022-10-09. Retrieved 2 July 2019. + item-369 at level 5: list_item: ^ "FAOSTAT". www.fao.org. Retrieved 2019-10-25. + item-370 at level 5: list_item: ^ "Anas platyrhynchos, Domestic ... . Digimorph.org. Retrieved 2012-12-23. + item-371 at level 5: list_item: ^ Sy Montgomery. "Mallard; Encyc ... Britannica.com. Retrieved 2012-12-23. + item-372 at level 5: list_item: ^ Glenday, Craig (2014). Guinnes ... ited. pp. 135. ISBN 978-1-908843-15-9. + item-373 at level 5: list_item: ^ Suomen kunnallisvaakunat (in F ... tto. 1982. p. 147. ISBN 951-773-085-3. + item-374 at level 5: list_item: ^ "Lubānas simbolika" (in Latvian). Retrieved September 9, 2021. + item-375 at level 5: list_item: ^ "Föglö" (in Swedish). Retrieved September 9, 2021. + item-376 at level 5: list_item: ^ Young, Emma. "World's funniest ... w Scientist. Retrieved 7 January 2019. + item-377 at level 5: list_item: ^ "Howard the Duck (character)". Grand Comics Database. + item-378 at level 5: list_item: ^ Sanderson, Peter; Gilbert, Lau ... luding this bad-tempered talking duck. + item-379 at level 5: list_item: ^ "The Duck". University of Oregon Athletics. Retrieved 2022-01-20. + item-380 at level 3: section_header: Sources + item-381 at level 4: list: group list + item-382 at level 5: list_item: American Ornithologists' Union ( ... (PDF) from the original on 2022-10-09. + item-383 at level 5: list_item: Carboneras, Carlos (1992). del H ... Lynx Edicions. ISBN 978-84-87334-10-8. + item-384 at level 5: list_item: Christidis, Les; Boles, Walter E ... ro Publishing. ISBN 978-0-643-06511-6. + item-385 at level 5: list_item: Donne-Goussé, Carole; Laudet, Vi ... /S1055-7903(02)00019-2. PMID 12099792. + item-386 at level 5: list_item: Elphick, Chris; Dunning, John B. ... istopher Helm. ISBN 978-0-7136-6250-4. + item-387 at level 5: list_item: Erlandson, Jon M. (1994). Early ... usiness Media. ISBN 978-1-4419-3231-0. + item-388 at level 5: list_item: Fieldhouse, Paul (2002). Food, F ... ara: ABC-CLIO. ISBN 978-1-61069-412-4. + item-389 at level 5: list_item: Fitter, Julian; Fitter, Daniel; ... versity Press. ISBN 978-0-691-10295-5. + item-390 at level 5: list_item: Higman, B. W. (2012). How Food M ... Wiley & Sons. ISBN 978-1-4051-8947-7. + item-391 at level 5: list_item: Hume, Julian H. (2012). Extinct ... istopher Helm. ISBN 978-1-4729-3744-5. + item-392 at level 5: list_item: Jeffries, Richard (2008). Holoce ... Alabama Press. ISBN 978-0-8173-1658-7. + item-393 at level 5: list_item: Kear, Janet, ed. (2005). Ducks, ... versity Press. ISBN 978-0-19-861009-0. + item-394 at level 5: list_item: Livezey, Bradley C. (October 198 ... (PDF) from the original on 2022-10-09. + item-395 at level 5: list_item: Madsen, Cort S.; McHugh, Kevin P ... (PDF) from the original on 2022-10-09. + item-396 at level 5: list_item: Maisels, Charles Keith (1999). E ... on: Routledge. ISBN 978-0-415-10975-8. + item-397 at level 5: list_item: Pratt, H. Douglas; Bruner, Phill ... University Press. ISBN 0-691-02399-9. + item-398 at level 5: list_item: Rau, Charles (1876). Early Man i ... ork: Harper & Brothers. LCCN 05040168. + item-399 at level 5: list_item: Shirihai, Hadoram (2008). A Comp ... versity Press. ISBN 978-0-691-13666-0. + item-400 at level 5: list_item: Sued-Badillo, Jalil (2003). Auto ... Paris: UNESCO. ISBN 978-92-3-103832-7. + item-401 at level 5: list_item: Thorpe, I. J. (1996). The Origin ... rk: Routledge. ISBN 978-0-415-08009-5. + item-402 at level 2: section_header: External links + item-403 at level 3: list: group list + item-404 at level 4: list_item: Definitions from Wiktionary + item-405 at level 4: list_item: Media from Commons + item-406 at level 4: list_item: Quotations from Wikiquote + item-407 at level 4: list_item: Recipes from Wikibooks + item-408 at level 4: list_item: Taxa from Wikispecies + item-409 at level 4: list_item: Data from Wikidata + item-410 at level 3: list: group list + item-411 at level 4: list_item: list of books (useful looking abstracts) + item-412 at level 4: list_item: Ducks on postage stamps Archived 2013-05-13 at the Wayback Machine + item-413 at level 4: list_item: Ducks at a Distance, by Rob Hine ... uide to identification of US waterfowl + item-414 at level 3: table with [3x2] + item-415 at level 3: picture + item-416 at level 3: paragraph: Retrieved from "" + item-417 at level 3: paragraph: : + item-418 at level 3: list: group list + item-419 at level 4: list_item: Ducks + item-420 at level 4: list_item: Game birds + item-421 at level 4: list_item: Bird common names + item-422 at level 3: paragraph: Hidden categories: + item-423 at level 3: list: group list + item-424 at level 4: list_item: All accuracy disputes + item-425 at level 4: list_item: Accuracy disputes from February 2020 + item-426 at level 4: list_item: CS1 Finnish-language sources (fi) + item-427 at level 4: list_item: CS1 Latvian-language sources (lv) + item-428 at level 4: list_item: CS1 Swedish-language sources (sv) + item-429 at level 4: list_item: Articles with short description + item-430 at level 4: list_item: Short description is different from Wikidata + item-431 at level 4: list_item: Wikipedia indefinitely move-protected pages + item-432 at level 4: list_item: Wikipedia indefinitely semi-protected pages + item-433 at level 4: list_item: Articles with 'species' microformats + item-434 at level 4: list_item: Articles containing Old English (ca. 450-1100)-language text + item-435 at level 4: list_item: Articles containing Dutch-language text + item-436 at level 4: list_item: Articles containing German-language text + item-437 at level 4: list_item: Articles containing Norwegian-language text + item-438 at level 4: list_item: Articles containing Lithuanian-language text + item-439 at level 4: list_item: Articles containing Ancient Greek (to 1453)-language text + item-440 at level 4: list_item: All articles with self-published sources + item-441 at level 4: list_item: Articles with self-published sources from February 2020 + item-442 at level 4: list_item: All articles with unsourced statements + item-443 at level 4: list_item: Articles with unsourced statements from January 2022 + item-444 at level 4: list_item: CS1: long volume value + item-445 at level 4: list_item: Pages using Sister project links with wikidata mismatch + item-446 at level 4: list_item: Pages using Sister project links with hidden wikidata + item-447 at level 4: list_item: Webarchive template wayback links + item-448 at level 4: list_item: Articles with Project Gutenberg links + item-449 at level 4: list_item: Articles containing video clips + item-450 at level 3: list: group list + item-451 at level 4: list_item: This page was last edited on 21 September 2024, at 12:11 (UTC). + item-452 at level 4: list_item: Text is available under the Crea ... tion, Inc., a non-profit organization. + item-453 at level 3: list: group list + item-454 at level 4: list_item: Privacy policy + item-455 at level 4: list_item: About Wikipedia + item-456 at level 4: list_item: Disclaimers + item-457 at level 4: list_item: Contact Wikipedia + item-458 at level 4: list_item: Code of Conduct + item-459 at level 4: list_item: Developers + item-460 at level 4: list_item: Statistics + item-461 at level 4: list_item: Cookie statement + item-462 at level 4: list_item: Mobile view + item-463 at level 3: list: group list + item-464 at level 3: list: group list + item-465 at level 1: caption: Pacific black duck displaying the characteristic upending "duck" + item-466 at level 1: caption: Male mallard. + item-467 at level 1: caption: Wood ducks. + item-468 at level 1: caption: Mallard landing in approach + item-469 at level 1: caption: Male Mandarin duck + item-470 at level 1: caption: Flying steamer ducks in Ushuaia, Argentina + item-471 at level 1: caption: Female mallard in Cornwall, England + item-472 at level 1: caption: Pecten along the bill + item-473 at level 1: caption: Mallard duckling preening + item-474 at level 1: caption: A Muscovy duckling + item-475 at level 1: caption: Ringed teal + item-476 at level 1: caption: Indian Runner ducks, a common breed of domestic ducks + item-477 at level 1: caption: Three black-colored ducks in the coat of arms of Maaninka[49] \ No newline at end of file diff --git a/tests/data/groundtruth/docling_v2/wiki_duck.html.json b/tests/data/groundtruth/docling_v2/wiki_duck.html.json index 4ac93595..3c61c1a5 100644 --- a/tests/data/groundtruth/docling_v2/wiki_duck.html.json +++ b/tests/data/groundtruth/docling_v2/wiki_duck.html.json @@ -17,9 +17,18 @@ "body": { "self_ref": "#/body", "children": [ + { + "$ref": "#/texts/0" + }, + { + "$ref": "#/texts/1" + }, { "$ref": "#/groups/0" }, + { + "$ref": "#/texts/8" + }, { "$ref": "#/groups/1" }, @@ -47,6 +56,9 @@ { "$ref": "#/groups/6" }, + { + "$ref": "#/texts/19" + }, { "$ref": "#/groups/7" }, @@ -54,37 +66,31 @@ "$ref": "#/groups/8" }, { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, { - "$ref": "#/texts/202" - }, - { - "$ref": "#/texts/206" - }, - { - "$ref": "#/texts/207" - }, - { - "$ref": "#/texts/210" - }, - { - "$ref": "#/texts/214" - }, - { - "$ref": "#/texts/218" + "$ref": "#/texts/216" }, { "$ref": "#/texts/220" }, + { + "$ref": "#/texts/221" + }, { "$ref": "#/texts/224" }, { - "$ref": "#/texts/225" + "$ref": "#/texts/228" }, { - "$ref": "#/texts/233" + "$ref": "#/texts/232" + }, + { + "$ref": "#/texts/234" + }, + { + "$ref": "#/texts/238" }, { "$ref": "#/texts/239" @@ -93,7 +99,13 @@ "$ref": "#/texts/247" }, { - "$ref": "#/texts/250" + "$ref": "#/texts/253" + }, + { + "$ref": "#/texts/261" + }, + { + "$ref": "#/texts/264" } ], "content_layer": "body", @@ -107,12 +119,6 @@ "$ref": "#/body" }, "children": [ - { - "$ref": "#/texts/0" - }, - { - "$ref": "#/texts/1" - }, { "$ref": "#/texts/2" }, @@ -124,6 +130,12 @@ }, { "$ref": "#/texts/5" + }, + { + "$ref": "#/texts/6" + }, + { + "$ref": "#/texts/7" } ], "content_layer": "body", @@ -136,20 +148,20 @@ "$ref": "#/body" }, "children": [ - { - "$ref": "#/texts/6" - }, - { - "$ref": "#/texts/7" - }, - { - "$ref": "#/texts/8" - }, { "$ref": "#/texts/9" }, { "$ref": "#/texts/10" + }, + { + "$ref": "#/texts/11" + }, + { + "$ref": "#/texts/12" + }, + { + "$ref": "#/texts/13" } ], "content_layer": "body", @@ -173,7 +185,7 @@ }, "children": [ { - "$ref": "#/texts/11" + "$ref": "#/texts/14" } ], "content_layer": "body", @@ -197,10 +209,10 @@ }, "children": [ { - "$ref": "#/texts/12" + "$ref": "#/texts/15" }, { - "$ref": "#/texts/13" + "$ref": "#/texts/16" } ], "content_layer": "body", @@ -214,10 +226,10 @@ }, "children": [ { - "$ref": "#/texts/14" + "$ref": "#/texts/17" }, { - "$ref": "#/texts/15" + "$ref": "#/texts/18" } ], "content_layer": "body", @@ -231,10 +243,10 @@ }, "children": [ { - "$ref": "#/texts/16" + "$ref": "#/texts/20" }, { - "$ref": "#/texts/17" + "$ref": "#/texts/21" } ], "content_layer": "body", @@ -248,7 +260,7 @@ }, "children": [ { - "$ref": "#/texts/18" + "$ref": "#/texts/22" } ], "content_layer": "body", @@ -258,90 +270,15 @@ { "self_ref": "#/groups/9", "parent": { - "$ref": "#/texts/18" + "$ref": "#/texts/22" }, "children": [ - { - "$ref": "#/texts/19" - }, - { - "$ref": "#/texts/20" - }, - { - "$ref": "#/texts/21" - }, - { - "$ref": "#/texts/22" - }, { "$ref": "#/texts/23" }, { "$ref": "#/texts/24" }, - { - "$ref": "#/texts/29" - }, - { - "$ref": "#/texts/34" - }, - { - "$ref": "#/texts/35" - }, - { - "$ref": "#/texts/38" - } - ], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/10", - "parent": { - "$ref": "#/texts/20" - }, - "children": [], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/11", - "parent": { - "$ref": "#/texts/21" - }, - "children": [], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/12", - "parent": { - "$ref": "#/texts/22" - }, - "children": [], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/13", - "parent": { - "$ref": "#/texts/23" - }, - "children": [], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/14", - "parent": { - "$ref": "#/texts/24" - }, - "children": [ { "$ref": "#/texts/25" }, @@ -353,6 +290,18 @@ }, { "$ref": "#/texts/28" + }, + { + "$ref": "#/texts/33" + }, + { + "$ref": "#/texts/38" + }, + { + "$ref": "#/texts/39" + }, + { + "$ref": "#/texts/42" } ], "content_layer": "body", @@ -360,7 +309,17 @@ "label": "list" }, { - "self_ref": "#/groups/15", + "self_ref": "#/groups/10", + "parent": { + "$ref": "#/texts/24" + }, + "children": [], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/11", "parent": { "$ref": "#/texts/25" }, @@ -370,7 +329,7 @@ "label": "list" }, { - "self_ref": "#/groups/16", + "self_ref": "#/groups/12", "parent": { "$ref": "#/texts/26" }, @@ -380,7 +339,7 @@ "label": "list" }, { - "self_ref": "#/groups/17", + "self_ref": "#/groups/13", "parent": { "$ref": "#/texts/27" }, @@ -390,21 +349,14 @@ "label": "list" }, { - "self_ref": "#/groups/18", + "self_ref": "#/groups/14", "parent": { "$ref": "#/texts/28" }, - "children": [], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/19", - "parent": { - "$ref": "#/texts/29" - }, "children": [ + { + "$ref": "#/texts/29" + }, { "$ref": "#/texts/30" }, @@ -413,9 +365,6 @@ }, { "$ref": "#/texts/32" - }, - { - "$ref": "#/texts/33" } ], "content_layer": "body", @@ -423,7 +372,17 @@ "label": "list" }, { - "self_ref": "#/groups/20", + "self_ref": "#/groups/15", + "parent": { + "$ref": "#/texts/29" + }, + "children": [], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/16", "parent": { "$ref": "#/texts/30" }, @@ -433,7 +392,7 @@ "label": "list" }, { - "self_ref": "#/groups/21", + "self_ref": "#/groups/17", "parent": { "$ref": "#/texts/31" }, @@ -443,7 +402,7 @@ "label": "list" }, { - "self_ref": "#/groups/22", + "self_ref": "#/groups/18", "parent": { "$ref": "#/texts/32" }, @@ -453,31 +412,17 @@ "label": "list" }, { - "self_ref": "#/groups/23", + "self_ref": "#/groups/19", "parent": { "$ref": "#/texts/33" }, - "children": [], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/24", - "parent": { - "$ref": "#/texts/34" - }, - "children": [], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/25", - "parent": { - "$ref": "#/texts/35" - }, "children": [ + { + "$ref": "#/texts/34" + }, + { + "$ref": "#/texts/35" + }, { "$ref": "#/texts/36" }, @@ -490,7 +435,27 @@ "label": "list" }, { - "self_ref": "#/groups/26", + "self_ref": "#/groups/20", + "parent": { + "$ref": "#/texts/34" + }, + "children": [], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/21", + "parent": { + "$ref": "#/texts/35" + }, + "children": [], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/22", "parent": { "$ref": "#/texts/36" }, @@ -500,7 +465,7 @@ "label": "list" }, { - "self_ref": "#/groups/27", + "self_ref": "#/groups/23", "parent": { "$ref": "#/texts/37" }, @@ -510,7 +475,7 @@ "label": "list" }, { - "self_ref": "#/groups/28", + "self_ref": "#/groups/24", "parent": { "$ref": "#/texts/38" }, @@ -520,7 +485,7 @@ "label": "list" }, { - "self_ref": "#/groups/29", + "self_ref": "#/groups/25", "parent": { "$ref": "#/texts/39" }, @@ -530,13 +495,48 @@ }, { "$ref": "#/texts/41" - }, - { - "$ref": "#/texts/42" - }, - { - "$ref": "#/texts/43" - }, + } + ], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/26", + "parent": { + "$ref": "#/texts/40" + }, + "children": [], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/27", + "parent": { + "$ref": "#/texts/41" + }, + "children": [], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/28", + "parent": { + "$ref": "#/texts/42" + }, + "children": [], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/29", + "parent": { + "$ref": "#/texts/43" + }, + "children": [ { "$ref": "#/texts/44" }, @@ -932,6 +932,18 @@ }, { "$ref": "#/texts/175" + }, + { + "$ref": "#/texts/176" + }, + { + "$ref": "#/texts/177" + }, + { + "$ref": "#/texts/178" + }, + { + "$ref": "#/texts/179" } ], "content_layer": "body", @@ -941,14 +953,14 @@ { "self_ref": "#/groups/30", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [ { - "$ref": "#/texts/176" + "$ref": "#/texts/180" }, { - "$ref": "#/texts/177" + "$ref": "#/texts/181" } ], "content_layer": "body", @@ -958,7 +970,7 @@ { "self_ref": "#/groups/31", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [], "content_layer": "body", @@ -968,17 +980,17 @@ { "self_ref": "#/groups/32", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [ { - "$ref": "#/texts/178" + "$ref": "#/texts/182" }, { - "$ref": "#/texts/179" + "$ref": "#/texts/183" }, { - "$ref": "#/texts/180" + "$ref": "#/texts/184" } ], "content_layer": "body", @@ -988,17 +1000,17 @@ { "self_ref": "#/groups/33", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [ { - "$ref": "#/texts/181" + "$ref": "#/texts/187" }, { - "$ref": "#/texts/182" + "$ref": "#/texts/188" }, { - "$ref": "#/texts/183" + "$ref": "#/texts/189" } ], "content_layer": "body", @@ -1008,30 +1020,9 @@ { "self_ref": "#/groups/34", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [ - { - "$ref": "#/texts/184" - }, - { - "$ref": "#/texts/185" - }, - { - "$ref": "#/texts/186" - }, - { - "$ref": "#/texts/187" - }, - { - "$ref": "#/texts/188" - }, - { - "$ref": "#/texts/189" - }, - { - "$ref": "#/texts/190" - }, { "$ref": "#/texts/191" }, @@ -1040,6 +1031,27 @@ }, { "$ref": "#/texts/193" + }, + { + "$ref": "#/texts/194" + }, + { + "$ref": "#/texts/195" + }, + { + "$ref": "#/texts/196" + }, + { + "$ref": "#/texts/197" + }, + { + "$ref": "#/texts/198" + }, + { + "$ref": "#/texts/199" + }, + { + "$ref": "#/texts/200" } ], "content_layer": "body", @@ -1049,14 +1061,14 @@ { "self_ref": "#/groups/35", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [ { - "$ref": "#/texts/194" + "$ref": "#/texts/202" }, { - "$ref": "#/texts/195" + "$ref": "#/texts/203" } ], "content_layer": "body", @@ -1066,14 +1078,14 @@ { "self_ref": "#/groups/36", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [ { - "$ref": "#/texts/196" + "$ref": "#/texts/205" }, { - "$ref": "#/texts/197" + "$ref": "#/texts/206" } ], "content_layer": "body", @@ -1083,11 +1095,11 @@ { "self_ref": "#/groups/37", "parent": { - "$ref": "#/texts/255" + "$ref": "#/texts/269" }, "children": [ { - "$ref": "#/texts/256" + "$ref": "#/texts/270" } ], "content_layer": "body", @@ -1097,56 +1109,9 @@ { "self_ref": "#/groups/38", "parent": { - "$ref": "#/texts/255" + "$ref": "#/texts/269" }, "children": [ - { - "$ref": "#/texts/257" - }, - { - "$ref": "#/texts/258" - }, - { - "$ref": "#/texts/259" - }, - { - "$ref": "#/texts/260" - }, - { - "$ref": "#/texts/261" - }, - { - "$ref": "#/texts/262" - } - ], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/39", - "parent": { - "$ref": "#/texts/264" - }, - "children": [ - { - "$ref": "#/texts/265" - }, - { - "$ref": "#/texts/266" - }, - { - "$ref": "#/texts/267" - }, - { - "$ref": "#/texts/268" - }, - { - "$ref": "#/texts/269" - }, - { - "$ref": "#/texts/270" - }, { "$ref": "#/texts/271" }, @@ -1164,13 +1129,18 @@ }, { "$ref": "#/texts/276" - }, - { - "$ref": "#/texts/277" - }, - { - "$ref": "#/texts/278" - }, + } + ], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/39", + "parent": { + "$ref": "#/texts/278" + }, + "children": [ { "$ref": "#/texts/279" }, @@ -1293,18 +1263,10 @@ }, { "$ref": "#/texts/319" - } - ], - "content_layer": "body", - "name": "ordered list", - "label": "ordered_list" - }, - { - "self_ref": "#/groups/40", - "parent": { - "$ref": "#/texts/320" - }, - "children": [ + }, + { + "$ref": "#/texts/320" + }, { "$ref": "#/texts/321" }, @@ -1343,10 +1305,18 @@ }, { "$ref": "#/texts/333" - }, - { - "$ref": "#/texts/334" - }, + } + ], + "content_layer": "body", + "name": "ordered list", + "label": "ordered_list" + }, + { + "self_ref": "#/groups/40", + "parent": { + "$ref": "#/texts/334" + }, + "children": [ { "$ref": "#/texts/335" }, @@ -1364,18 +1334,10 @@ }, { "$ref": "#/texts/340" - } - ], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/41", - "parent": { - "$ref": "#/texts/341" - }, - "children": [ + }, + { + "$ref": "#/texts/341" + }, { "$ref": "#/texts/342" }, @@ -1393,18 +1355,7 @@ }, { "$ref": "#/texts/347" - } - ], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/42", - "parent": { - "$ref": "#/texts/341" - }, - "children": [ + }, { "$ref": "#/texts/348" }, @@ -1413,18 +1364,7 @@ }, { "$ref": "#/texts/350" - } - ], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/43", - "parent": { - "$ref": "#/texts/341" - }, - "children": [ + }, { "$ref": "#/texts/351" }, @@ -1433,6 +1373,9 @@ }, { "$ref": "#/texts/353" + }, + { + "$ref": "#/texts/354" } ], "content_layer": "body", @@ -1440,17 +1383,11 @@ "label": "list" }, { - "self_ref": "#/groups/44", + "self_ref": "#/groups/41", "parent": { - "$ref": "#/texts/341" + "$ref": "#/texts/355" }, "children": [ - { - "$ref": "#/texts/354" - }, - { - "$ref": "#/texts/355" - }, { "$ref": "#/texts/356" }, @@ -1468,7 +1405,18 @@ }, { "$ref": "#/texts/361" - }, + } + ], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/42", + "parent": { + "$ref": "#/texts/355" + }, + "children": [ { "$ref": "#/texts/362" }, @@ -1477,13 +1425,18 @@ }, { "$ref": "#/texts/364" - }, - { - "$ref": "#/texts/365" - }, - { - "$ref": "#/texts/366" - }, + } + ], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/43", + "parent": { + "$ref": "#/texts/355" + }, + "children": [ { "$ref": "#/texts/367" }, @@ -1492,10 +1445,18 @@ }, { "$ref": "#/texts/369" - }, - { - "$ref": "#/texts/370" - }, + } + ], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/44", + "parent": { + "$ref": "#/texts/355" + }, + "children": [ { "$ref": "#/texts/371" }, @@ -1522,35 +1483,13 @@ }, { "$ref": "#/texts/379" - } - ], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/45", - "parent": { - "$ref": "#/texts/341" - }, - "children": [ + }, { "$ref": "#/texts/380" }, { "$ref": "#/texts/381" - } - ], - "content_layer": "body", - "name": "list", - "label": "list" - }, - { - "self_ref": "#/groups/46", - "parent": { - "$ref": "#/texts/341" - }, - "children": [ + }, { "$ref": "#/texts/382" }, @@ -1577,6 +1516,79 @@ }, { "$ref": "#/texts/390" + }, + { + "$ref": "#/texts/391" + }, + { + "$ref": "#/texts/392" + }, + { + "$ref": "#/texts/393" + }, + { + "$ref": "#/texts/394" + }, + { + "$ref": "#/texts/395" + }, + { + "$ref": "#/texts/396" + } + ], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/45", + "parent": { + "$ref": "#/texts/355" + }, + "children": [ + { + "$ref": "#/texts/397" + }, + { + "$ref": "#/texts/398" + } + ], + "content_layer": "body", + "name": "list", + "label": "list" + }, + { + "self_ref": "#/groups/46", + "parent": { + "$ref": "#/texts/355" + }, + "children": [ + { + "$ref": "#/texts/399" + }, + { + "$ref": "#/texts/400" + }, + { + "$ref": "#/texts/401" + }, + { + "$ref": "#/texts/402" + }, + { + "$ref": "#/texts/403" + }, + { + "$ref": "#/texts/404" + }, + { + "$ref": "#/texts/405" + }, + { + "$ref": "#/texts/406" + }, + { + "$ref": "#/texts/407" } ], "content_layer": "body", @@ -1586,7 +1598,7 @@ { "self_ref": "#/groups/47", "parent": { - "$ref": "#/texts/341" + "$ref": "#/texts/355" }, "children": [], "content_layer": "body", @@ -1596,7 +1608,7 @@ { "self_ref": "#/groups/48", "parent": { - "$ref": "#/texts/341" + "$ref": "#/texts/355" }, "children": [], "content_layer": "body", @@ -1607,6 +1619,30 @@ "texts": [ { "self_ref": "#/texts/0", + "parent": { + "$ref": "#/body" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Main menu", + "text": "Main menu" + }, + { + "self_ref": "#/texts/1", + "parent": { + "$ref": "#/body" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Navigation", + "text": "Navigation" + }, + { + "self_ref": "#/texts/2", "parent": { "$ref": "#/groups/0" }, @@ -1620,7 +1656,7 @@ "marker": "-" }, { - "self_ref": "#/texts/1", + "self_ref": "#/texts/3", "parent": { "$ref": "#/groups/0" }, @@ -1634,7 +1670,7 @@ "marker": "-" }, { - "self_ref": "#/texts/2", + "self_ref": "#/texts/4", "parent": { "$ref": "#/groups/0" }, @@ -1648,7 +1684,7 @@ "marker": "-" }, { - "self_ref": "#/texts/3", + "self_ref": "#/texts/5", "parent": { "$ref": "#/groups/0" }, @@ -1662,7 +1698,7 @@ "marker": "-" }, { - "self_ref": "#/texts/4", + "self_ref": "#/texts/6", "parent": { "$ref": "#/groups/0" }, @@ -1676,7 +1712,7 @@ "marker": "-" }, { - "self_ref": "#/texts/5", + "self_ref": "#/texts/7", "parent": { "$ref": "#/groups/0" }, @@ -1690,7 +1726,19 @@ "marker": "-" }, { - "self_ref": "#/texts/6", + "self_ref": "#/texts/8", + "parent": { + "$ref": "#/body" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Contribute", + "text": "Contribute" + }, + { + "self_ref": "#/texts/9", "parent": { "$ref": "#/groups/1" }, @@ -1704,7 +1752,7 @@ "marker": "-" }, { - "self_ref": "#/texts/7", + "self_ref": "#/texts/10", "parent": { "$ref": "#/groups/1" }, @@ -1718,7 +1766,7 @@ "marker": "-" }, { - "self_ref": "#/texts/8", + "self_ref": "#/texts/11", "parent": { "$ref": "#/groups/1" }, @@ -1732,7 +1780,7 @@ "marker": "-" }, { - "self_ref": "#/texts/9", + "self_ref": "#/texts/12", "parent": { "$ref": "#/groups/1" }, @@ -1746,7 +1794,7 @@ "marker": "-" }, { - "self_ref": "#/texts/10", + "self_ref": "#/texts/13", "parent": { "$ref": "#/groups/1" }, @@ -1760,7 +1808,7 @@ "marker": "-" }, { - "self_ref": "#/texts/11", + "self_ref": "#/texts/14", "parent": { "$ref": "#/groups/3" }, @@ -1773,64 +1821,76 @@ "enumerated": false, "marker": "-" }, - { - "self_ref": "#/texts/12", - "parent": { - "$ref": "#/groups/5" - }, - "children": [], - "content_layer": "body", - "label": "list_item", - "prov": [], - "orig": "Create account", - "text": "Create account", - "enumerated": false, - "marker": "-" - }, - { - "self_ref": "#/texts/13", - "parent": { - "$ref": "#/groups/5" - }, - "children": [], - "content_layer": "body", - "label": "list_item", - "prov": [], - "orig": "Log in", - "text": "Log in", - "enumerated": false, - "marker": "-" - }, - { - "self_ref": "#/texts/14", - "parent": { - "$ref": "#/groups/6" - }, - "children": [], - "content_layer": "body", - "label": "list_item", - "prov": [], - "orig": "Create account", - "text": "Create account", - "enumerated": false, - "marker": "-" - }, { "self_ref": "#/texts/15", "parent": { - "$ref": "#/groups/6" + "$ref": "#/groups/5" }, "children": [], "content_layer": "body", "label": "list_item", "prov": [], - "orig": "Log in", - "text": "Log in", + "orig": "Create account", + "text": "Create account", "enumerated": false, "marker": "-" }, { "self_ref": "#/texts/16", + "parent": { + "$ref": "#/groups/5" + }, + "children": [], + "content_layer": "body", + "label": "list_item", + "prov": [], + "orig": "Log in", + "text": "Log in", + "enumerated": false, + "marker": "-" + }, + { + "self_ref": "#/texts/17", + "parent": { + "$ref": "#/groups/6" + }, + "children": [], + "content_layer": "body", + "label": "list_item", + "prov": [], + "orig": "Create account", + "text": "Create account", + "enumerated": false, + "marker": "-" + }, + { + "self_ref": "#/texts/18", + "parent": { + "$ref": "#/groups/6" + }, + "children": [], + "content_layer": "body", + "label": "list_item", + "prov": [], + "orig": "Log in", + "text": "Log in", + "enumerated": false, + "marker": "-" + }, + { + "self_ref": "#/texts/19", + "parent": { + "$ref": "#/body" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Pages for logged out editors", + "text": "Pages for logged out editors" + }, + { + "self_ref": "#/texts/20", "parent": { "$ref": "#/groups/7" }, @@ -1844,7 +1904,7 @@ "marker": "-" }, { - "self_ref": "#/texts/17", + "self_ref": "#/texts/21", "parent": { "$ref": "#/groups/7" }, @@ -1858,7 +1918,7 @@ "marker": "-" }, { - "self_ref": "#/texts/18", + "self_ref": "#/texts/22", "parent": { "$ref": "#/groups/8" }, @@ -1875,7 +1935,7 @@ "level": 2 }, { - "self_ref": "#/texts/19", + "self_ref": "#/texts/23", "parent": { "$ref": "#/groups/9" }, @@ -1889,7 +1949,7 @@ "marker": "-" }, { - "self_ref": "#/texts/20", + "self_ref": "#/texts/24", "parent": { "$ref": "#/groups/9" }, @@ -1907,7 +1967,7 @@ "marker": "-" }, { - "self_ref": "#/texts/21", + "self_ref": "#/texts/25", "parent": { "$ref": "#/groups/9" }, @@ -1925,7 +1985,7 @@ "marker": "-" }, { - "self_ref": "#/texts/22", + "self_ref": "#/texts/26", "parent": { "$ref": "#/groups/9" }, @@ -1943,7 +2003,7 @@ "marker": "-" }, { - "self_ref": "#/texts/23", + "self_ref": "#/texts/27", "parent": { "$ref": "#/groups/9" }, @@ -1961,7 +2021,7 @@ "marker": "-" }, { - "self_ref": "#/texts/24", + "self_ref": "#/texts/28", "parent": { "$ref": "#/groups/9" }, @@ -1979,7 +2039,7 @@ "marker": "-" }, { - "self_ref": "#/texts/25", + "self_ref": "#/texts/29", "parent": { "$ref": "#/groups/14" }, @@ -1997,7 +2057,7 @@ "marker": "-" }, { - "self_ref": "#/texts/26", + "self_ref": "#/texts/30", "parent": { "$ref": "#/groups/14" }, @@ -2015,7 +2075,7 @@ "marker": "-" }, { - "self_ref": "#/texts/27", + "self_ref": "#/texts/31", "parent": { "$ref": "#/groups/14" }, @@ -2033,7 +2093,7 @@ "marker": "-" }, { - "self_ref": "#/texts/28", + "self_ref": "#/texts/32", "parent": { "$ref": "#/groups/14" }, @@ -2051,7 +2111,7 @@ "marker": "-" }, { - "self_ref": "#/texts/29", + "self_ref": "#/texts/33", "parent": { "$ref": "#/groups/9" }, @@ -2069,7 +2129,7 @@ "marker": "-" }, { - "self_ref": "#/texts/30", + "self_ref": "#/texts/34", "parent": { "$ref": "#/groups/19" }, @@ -2087,7 +2147,7 @@ "marker": "-" }, { - "self_ref": "#/texts/31", + "self_ref": "#/texts/35", "parent": { "$ref": "#/groups/19" }, @@ -2105,7 +2165,7 @@ "marker": "-" }, { - "self_ref": "#/texts/32", + "self_ref": "#/texts/36", "parent": { "$ref": "#/groups/19" }, @@ -2123,7 +2183,7 @@ "marker": "-" }, { - "self_ref": "#/texts/33", + "self_ref": "#/texts/37", "parent": { "$ref": "#/groups/19" }, @@ -2141,7 +2201,7 @@ "marker": "-" }, { - "self_ref": "#/texts/34", + "self_ref": "#/texts/38", "parent": { "$ref": "#/groups/9" }, @@ -2159,7 +2219,7 @@ "marker": "-" }, { - "self_ref": "#/texts/35", + "self_ref": "#/texts/39", "parent": { "$ref": "#/groups/9" }, @@ -2177,7 +2237,7 @@ "marker": "-" }, { - "self_ref": "#/texts/36", + "self_ref": "#/texts/40", "parent": { "$ref": "#/groups/25" }, @@ -2195,7 +2255,7 @@ "marker": "-" }, { - "self_ref": "#/texts/37", + "self_ref": "#/texts/41", "parent": { "$ref": "#/groups/25" }, @@ -2213,7 +2273,7 @@ "marker": "-" }, { - "self_ref": "#/texts/38", + "self_ref": "#/texts/42", "parent": { "$ref": "#/groups/9" }, @@ -2231,7 +2291,7 @@ "marker": "-" }, { - "self_ref": "#/texts/39", + "self_ref": "#/texts/43", "parent": { "$ref": "#/body" }, @@ -2248,56 +2308,86 @@ { "$ref": "#/groups/32" }, + { + "$ref": "#/texts/185" + }, + { + "$ref": "#/texts/186" + }, { "$ref": "#/groups/33" }, + { + "$ref": "#/texts/190" + }, { "$ref": "#/groups/34" }, + { + "$ref": "#/texts/201" + }, { "$ref": "#/groups/35" }, + { + "$ref": "#/texts/204" + }, { "$ref": "#/groups/36" }, + { + "$ref": "#/texts/207" + }, { "$ref": "#/pictures/3" }, - { - "$ref": "#/tables/0" - }, - { - "$ref": "#/texts/198" - }, - { - "$ref": "#/texts/199" - }, - { - "$ref": "#/texts/200" - }, { "$ref": "#/texts/208" }, + { + "$ref": "#/texts/209" + }, + { + "$ref": "#/texts/210" + }, + { + "$ref": "#/texts/211" + }, + { + "$ref": "#/tables/0" + }, + { + "$ref": "#/texts/212" + }, { "$ref": "#/texts/213" }, { - "$ref": "#/texts/217" + "$ref": "#/texts/214" }, { "$ref": "#/texts/222" }, { - "$ref": "#/texts/242" + "$ref": "#/texts/227" }, { - "$ref": "#/texts/255" + "$ref": "#/texts/231" }, { - "$ref": "#/texts/263" + "$ref": "#/texts/236" }, { - "$ref": "#/texts/341" + "$ref": "#/texts/256" + }, + { + "$ref": "#/texts/269" + }, + { + "$ref": "#/texts/277" + }, + { + "$ref": "#/texts/355" } ], "content_layer": "body", @@ -2307,7 +2397,7 @@ "text": "Duck" }, { - "self_ref": "#/texts/40", + "self_ref": "#/texts/44", "parent": { "$ref": "#/groups/29" }, @@ -2321,7 +2411,7 @@ "marker": "-" }, { - "self_ref": "#/texts/41", + "self_ref": "#/texts/45", "parent": { "$ref": "#/groups/29" }, @@ -2335,7 +2425,7 @@ "marker": "-" }, { - "self_ref": "#/texts/42", + "self_ref": "#/texts/46", "parent": { "$ref": "#/groups/29" }, @@ -2349,7 +2439,7 @@ "marker": "-" }, { - "self_ref": "#/texts/43", + "self_ref": "#/texts/47", "parent": { "$ref": "#/groups/29" }, @@ -2363,7 +2453,7 @@ "marker": "-" }, { - "self_ref": "#/texts/44", + "self_ref": "#/texts/48", "parent": { "$ref": "#/groups/29" }, @@ -2377,7 +2467,7 @@ "marker": "-" }, { - "self_ref": "#/texts/45", + "self_ref": "#/texts/49", "parent": { "$ref": "#/groups/29" }, @@ -2391,7 +2481,7 @@ "marker": "-" }, { - "self_ref": "#/texts/46", + "self_ref": "#/texts/50", "parent": { "$ref": "#/groups/29" }, @@ -2405,7 +2495,7 @@ "marker": "-" }, { - "self_ref": "#/texts/47", + "self_ref": "#/texts/51", "parent": { "$ref": "#/groups/29" }, @@ -2419,7 +2509,7 @@ "marker": "-" }, { - "self_ref": "#/texts/48", + "self_ref": "#/texts/52", "parent": { "$ref": "#/groups/29" }, @@ -2433,7 +2523,7 @@ "marker": "-" }, { - "self_ref": "#/texts/49", + "self_ref": "#/texts/53", "parent": { "$ref": "#/groups/29" }, @@ -2447,7 +2537,7 @@ "marker": "-" }, { - "self_ref": "#/texts/50", + "self_ref": "#/texts/54", "parent": { "$ref": "#/groups/29" }, @@ -2461,7 +2551,7 @@ "marker": "-" }, { - "self_ref": "#/texts/51", + "self_ref": "#/texts/55", "parent": { "$ref": "#/groups/29" }, @@ -2475,7 +2565,7 @@ "marker": "-" }, { - "self_ref": "#/texts/52", + "self_ref": "#/texts/56", "parent": { "$ref": "#/groups/29" }, @@ -2489,7 +2579,7 @@ "marker": "-" }, { - "self_ref": "#/texts/53", + "self_ref": "#/texts/57", "parent": { "$ref": "#/groups/29" }, @@ -2503,7 +2593,7 @@ "marker": "-" }, { - "self_ref": "#/texts/54", + "self_ref": "#/texts/58", "parent": { "$ref": "#/groups/29" }, @@ -2517,7 +2607,7 @@ "marker": "-" }, { - "self_ref": "#/texts/55", + "self_ref": "#/texts/59", "parent": { "$ref": "#/groups/29" }, @@ -2531,7 +2621,7 @@ "marker": "-" }, { - "self_ref": "#/texts/56", + "self_ref": "#/texts/60", "parent": { "$ref": "#/groups/29" }, @@ -2545,7 +2635,7 @@ "marker": "-" }, { - "self_ref": "#/texts/57", + "self_ref": "#/texts/61", "parent": { "$ref": "#/groups/29" }, @@ -2559,7 +2649,7 @@ "marker": "-" }, { - "self_ref": "#/texts/58", + "self_ref": "#/texts/62", "parent": { "$ref": "#/groups/29" }, @@ -2573,7 +2663,7 @@ "marker": "-" }, { - "self_ref": "#/texts/59", + "self_ref": "#/texts/63", "parent": { "$ref": "#/groups/29" }, @@ -2587,7 +2677,7 @@ "marker": "-" }, { - "self_ref": "#/texts/60", + "self_ref": "#/texts/64", "parent": { "$ref": "#/groups/29" }, @@ -2601,7 +2691,7 @@ "marker": "-" }, { - "self_ref": "#/texts/61", + "self_ref": "#/texts/65", "parent": { "$ref": "#/groups/29" }, @@ -2615,7 +2705,7 @@ "marker": "-" }, { - "self_ref": "#/texts/62", + "self_ref": "#/texts/66", "parent": { "$ref": "#/groups/29" }, @@ -2629,7 +2719,7 @@ "marker": "-" }, { - "self_ref": "#/texts/63", + "self_ref": "#/texts/67", "parent": { "$ref": "#/groups/29" }, @@ -2643,7 +2733,7 @@ "marker": "-" }, { - "self_ref": "#/texts/64", + "self_ref": "#/texts/68", "parent": { "$ref": "#/groups/29" }, @@ -2657,7 +2747,7 @@ "marker": "-" }, { - "self_ref": "#/texts/65", + "self_ref": "#/texts/69", "parent": { "$ref": "#/groups/29" }, @@ -2671,7 +2761,7 @@ "marker": "-" }, { - "self_ref": "#/texts/66", + "self_ref": "#/texts/70", "parent": { "$ref": "#/groups/29" }, @@ -2685,7 +2775,7 @@ "marker": "-" }, { - "self_ref": "#/texts/67", + "self_ref": "#/texts/71", "parent": { "$ref": "#/groups/29" }, @@ -2699,7 +2789,7 @@ "marker": "-" }, { - "self_ref": "#/texts/68", + "self_ref": "#/texts/72", "parent": { "$ref": "#/groups/29" }, @@ -2713,7 +2803,7 @@ "marker": "-" }, { - "self_ref": "#/texts/69", + "self_ref": "#/texts/73", "parent": { "$ref": "#/groups/29" }, @@ -2727,7 +2817,7 @@ "marker": "-" }, { - "self_ref": "#/texts/70", + "self_ref": "#/texts/74", "parent": { "$ref": "#/groups/29" }, @@ -2741,7 +2831,7 @@ "marker": "-" }, { - "self_ref": "#/texts/71", + "self_ref": "#/texts/75", "parent": { "$ref": "#/groups/29" }, @@ -2755,7 +2845,7 @@ "marker": "-" }, { - "self_ref": "#/texts/72", + "self_ref": "#/texts/76", "parent": { "$ref": "#/groups/29" }, @@ -2769,7 +2859,7 @@ "marker": "-" }, { - "self_ref": "#/texts/73", + "self_ref": "#/texts/77", "parent": { "$ref": "#/groups/29" }, @@ -2783,7 +2873,7 @@ "marker": "-" }, { - "self_ref": "#/texts/74", + "self_ref": "#/texts/78", "parent": { "$ref": "#/groups/29" }, @@ -2797,7 +2887,7 @@ "marker": "-" }, { - "self_ref": "#/texts/75", + "self_ref": "#/texts/79", "parent": { "$ref": "#/groups/29" }, @@ -2811,7 +2901,7 @@ "marker": "-" }, { - "self_ref": "#/texts/76", + "self_ref": "#/texts/80", "parent": { "$ref": "#/groups/29" }, @@ -2825,7 +2915,7 @@ "marker": "-" }, { - "self_ref": "#/texts/77", + "self_ref": "#/texts/81", "parent": { "$ref": "#/groups/29" }, @@ -2839,7 +2929,7 @@ "marker": "-" }, { - "self_ref": "#/texts/78", + "self_ref": "#/texts/82", "parent": { "$ref": "#/groups/29" }, @@ -2853,7 +2943,7 @@ "marker": "-" }, { - "self_ref": "#/texts/79", + "self_ref": "#/texts/83", "parent": { "$ref": "#/groups/29" }, @@ -2867,7 +2957,7 @@ "marker": "-" }, { - "self_ref": "#/texts/80", + "self_ref": "#/texts/84", "parent": { "$ref": "#/groups/29" }, @@ -2881,7 +2971,7 @@ "marker": "-" }, { - "self_ref": "#/texts/81", + "self_ref": "#/texts/85", "parent": { "$ref": "#/groups/29" }, @@ -2895,7 +2985,7 @@ "marker": "-" }, { - "self_ref": "#/texts/82", + "self_ref": "#/texts/86", "parent": { "$ref": "#/groups/29" }, @@ -2909,7 +2999,7 @@ "marker": "-" }, { - "self_ref": "#/texts/83", + "self_ref": "#/texts/87", "parent": { "$ref": "#/groups/29" }, @@ -2923,7 +3013,7 @@ "marker": "-" }, { - "self_ref": "#/texts/84", + "self_ref": "#/texts/88", "parent": { "$ref": "#/groups/29" }, @@ -2937,7 +3027,7 @@ "marker": "-" }, { - "self_ref": "#/texts/85", + "self_ref": "#/texts/89", "parent": { "$ref": "#/groups/29" }, @@ -2951,7 +3041,7 @@ "marker": "-" }, { - "self_ref": "#/texts/86", + "self_ref": "#/texts/90", "parent": { "$ref": "#/groups/29" }, @@ -2965,7 +3055,7 @@ "marker": "-" }, { - "self_ref": "#/texts/87", + "self_ref": "#/texts/91", "parent": { "$ref": "#/groups/29" }, @@ -2979,7 +3069,7 @@ "marker": "-" }, { - "self_ref": "#/texts/88", + "self_ref": "#/texts/92", "parent": { "$ref": "#/groups/29" }, @@ -2993,7 +3083,7 @@ "marker": "-" }, { - "self_ref": "#/texts/89", + "self_ref": "#/texts/93", "parent": { "$ref": "#/groups/29" }, @@ -3007,7 +3097,7 @@ "marker": "-" }, { - "self_ref": "#/texts/90", + "self_ref": "#/texts/94", "parent": { "$ref": "#/groups/29" }, @@ -3021,7 +3111,7 @@ "marker": "-" }, { - "self_ref": "#/texts/91", + "self_ref": "#/texts/95", "parent": { "$ref": "#/groups/29" }, @@ -3035,7 +3125,7 @@ "marker": "-" }, { - "self_ref": "#/texts/92", + "self_ref": "#/texts/96", "parent": { "$ref": "#/groups/29" }, @@ -3049,7 +3139,7 @@ "marker": "-" }, { - "self_ref": "#/texts/93", + "self_ref": "#/texts/97", "parent": { "$ref": "#/groups/29" }, @@ -3063,7 +3153,7 @@ "marker": "-" }, { - "self_ref": "#/texts/94", + "self_ref": "#/texts/98", "parent": { "$ref": "#/groups/29" }, @@ -3077,7 +3167,7 @@ "marker": "-" }, { - "self_ref": "#/texts/95", + "self_ref": "#/texts/99", "parent": { "$ref": "#/groups/29" }, @@ -3091,7 +3181,7 @@ "marker": "-" }, { - "self_ref": "#/texts/96", + "self_ref": "#/texts/100", "parent": { "$ref": "#/groups/29" }, @@ -3105,7 +3195,7 @@ "marker": "-" }, { - "self_ref": "#/texts/97", + "self_ref": "#/texts/101", "parent": { "$ref": "#/groups/29" }, @@ -3119,7 +3209,7 @@ "marker": "-" }, { - "self_ref": "#/texts/98", + "self_ref": "#/texts/102", "parent": { "$ref": "#/groups/29" }, @@ -3133,7 +3223,7 @@ "marker": "-" }, { - "self_ref": "#/texts/99", + "self_ref": "#/texts/103", "parent": { "$ref": "#/groups/29" }, @@ -3147,7 +3237,7 @@ "marker": "-" }, { - "self_ref": "#/texts/100", + "self_ref": "#/texts/104", "parent": { "$ref": "#/groups/29" }, @@ -3161,7 +3251,7 @@ "marker": "-" }, { - "self_ref": "#/texts/101", + "self_ref": "#/texts/105", "parent": { "$ref": "#/groups/29" }, @@ -3175,7 +3265,7 @@ "marker": "-" }, { - "self_ref": "#/texts/102", + "self_ref": "#/texts/106", "parent": { "$ref": "#/groups/29" }, @@ -3189,7 +3279,7 @@ "marker": "-" }, { - "self_ref": "#/texts/103", + "self_ref": "#/texts/107", "parent": { "$ref": "#/groups/29" }, @@ -3203,7 +3293,7 @@ "marker": "-" }, { - "self_ref": "#/texts/104", + "self_ref": "#/texts/108", "parent": { "$ref": "#/groups/29" }, @@ -3217,7 +3307,7 @@ "marker": "-" }, { - "self_ref": "#/texts/105", + "self_ref": "#/texts/109", "parent": { "$ref": "#/groups/29" }, @@ -3231,7 +3321,7 @@ "marker": "-" }, { - "self_ref": "#/texts/106", + "self_ref": "#/texts/110", "parent": { "$ref": "#/groups/29" }, @@ -3245,7 +3335,7 @@ "marker": "-" }, { - "self_ref": "#/texts/107", + "self_ref": "#/texts/111", "parent": { "$ref": "#/groups/29" }, @@ -3259,7 +3349,7 @@ "marker": "-" }, { - "self_ref": "#/texts/108", + "self_ref": "#/texts/112", "parent": { "$ref": "#/groups/29" }, @@ -3273,7 +3363,7 @@ "marker": "-" }, { - "self_ref": "#/texts/109", + "self_ref": "#/texts/113", "parent": { "$ref": "#/groups/29" }, @@ -3287,7 +3377,7 @@ "marker": "-" }, { - "self_ref": "#/texts/110", + "self_ref": "#/texts/114", "parent": { "$ref": "#/groups/29" }, @@ -3301,7 +3391,7 @@ "marker": "-" }, { - "self_ref": "#/texts/111", + "self_ref": "#/texts/115", "parent": { "$ref": "#/groups/29" }, @@ -3315,7 +3405,7 @@ "marker": "-" }, { - "self_ref": "#/texts/112", + "self_ref": "#/texts/116", "parent": { "$ref": "#/groups/29" }, @@ -3329,7 +3419,7 @@ "marker": "-" }, { - "self_ref": "#/texts/113", + "self_ref": "#/texts/117", "parent": { "$ref": "#/groups/29" }, @@ -3343,7 +3433,7 @@ "marker": "-" }, { - "self_ref": "#/texts/114", + "self_ref": "#/texts/118", "parent": { "$ref": "#/groups/29" }, @@ -3357,7 +3447,7 @@ "marker": "-" }, { - "self_ref": "#/texts/115", + "self_ref": "#/texts/119", "parent": { "$ref": "#/groups/29" }, @@ -3371,7 +3461,7 @@ "marker": "-" }, { - "self_ref": "#/texts/116", + "self_ref": "#/texts/120", "parent": { "$ref": "#/groups/29" }, @@ -3385,7 +3475,7 @@ "marker": "-" }, { - "self_ref": "#/texts/117", + "self_ref": "#/texts/121", "parent": { "$ref": "#/groups/29" }, @@ -3399,7 +3489,7 @@ "marker": "-" }, { - "self_ref": "#/texts/118", + "self_ref": "#/texts/122", "parent": { "$ref": "#/groups/29" }, @@ -3413,7 +3503,7 @@ "marker": "-" }, { - "self_ref": "#/texts/119", + "self_ref": "#/texts/123", "parent": { "$ref": "#/groups/29" }, @@ -3427,7 +3517,7 @@ "marker": "-" }, { - "self_ref": "#/texts/120", + "self_ref": "#/texts/124", "parent": { "$ref": "#/groups/29" }, @@ -3441,7 +3531,7 @@ "marker": "-" }, { - "self_ref": "#/texts/121", + "self_ref": "#/texts/125", "parent": { "$ref": "#/groups/29" }, @@ -3455,7 +3545,7 @@ "marker": "-" }, { - "self_ref": "#/texts/122", + "self_ref": "#/texts/126", "parent": { "$ref": "#/groups/29" }, @@ -3469,7 +3559,7 @@ "marker": "-" }, { - "self_ref": "#/texts/123", + "self_ref": "#/texts/127", "parent": { "$ref": "#/groups/29" }, @@ -3483,7 +3573,7 @@ "marker": "-" }, { - "self_ref": "#/texts/124", + "self_ref": "#/texts/128", "parent": { "$ref": "#/groups/29" }, @@ -3497,7 +3587,7 @@ "marker": "-" }, { - "self_ref": "#/texts/125", + "self_ref": "#/texts/129", "parent": { "$ref": "#/groups/29" }, @@ -3511,7 +3601,7 @@ "marker": "-" }, { - "self_ref": "#/texts/126", + "self_ref": "#/texts/130", "parent": { "$ref": "#/groups/29" }, @@ -3525,7 +3615,7 @@ "marker": "-" }, { - "self_ref": "#/texts/127", + "self_ref": "#/texts/131", "parent": { "$ref": "#/groups/29" }, @@ -3539,7 +3629,7 @@ "marker": "-" }, { - "self_ref": "#/texts/128", + "self_ref": "#/texts/132", "parent": { "$ref": "#/groups/29" }, @@ -3553,7 +3643,7 @@ "marker": "-" }, { - "self_ref": "#/texts/129", + "self_ref": "#/texts/133", "parent": { "$ref": "#/groups/29" }, @@ -3567,7 +3657,7 @@ "marker": "-" }, { - "self_ref": "#/texts/130", + "self_ref": "#/texts/134", "parent": { "$ref": "#/groups/29" }, @@ -3581,7 +3671,7 @@ "marker": "-" }, { - "self_ref": "#/texts/131", + "self_ref": "#/texts/135", "parent": { "$ref": "#/groups/29" }, @@ -3595,7 +3685,7 @@ "marker": "-" }, { - "self_ref": "#/texts/132", + "self_ref": "#/texts/136", "parent": { "$ref": "#/groups/29" }, @@ -3609,7 +3699,7 @@ "marker": "-" }, { - "self_ref": "#/texts/133", + "self_ref": "#/texts/137", "parent": { "$ref": "#/groups/29" }, @@ -3623,7 +3713,7 @@ "marker": "-" }, { - "self_ref": "#/texts/134", + "self_ref": "#/texts/138", "parent": { "$ref": "#/groups/29" }, @@ -3637,7 +3727,7 @@ "marker": "-" }, { - "self_ref": "#/texts/135", + "self_ref": "#/texts/139", "parent": { "$ref": "#/groups/29" }, @@ -3651,7 +3741,7 @@ "marker": "-" }, { - "self_ref": "#/texts/136", + "self_ref": "#/texts/140", "parent": { "$ref": "#/groups/29" }, @@ -3665,7 +3755,7 @@ "marker": "-" }, { - "self_ref": "#/texts/137", + "self_ref": "#/texts/141", "parent": { "$ref": "#/groups/29" }, @@ -3679,7 +3769,7 @@ "marker": "-" }, { - "self_ref": "#/texts/138", + "self_ref": "#/texts/142", "parent": { "$ref": "#/groups/29" }, @@ -3693,7 +3783,7 @@ "marker": "-" }, { - "self_ref": "#/texts/139", + "self_ref": "#/texts/143", "parent": { "$ref": "#/groups/29" }, @@ -3707,7 +3797,7 @@ "marker": "-" }, { - "self_ref": "#/texts/140", + "self_ref": "#/texts/144", "parent": { "$ref": "#/groups/29" }, @@ -3721,7 +3811,7 @@ "marker": "-" }, { - "self_ref": "#/texts/141", + "self_ref": "#/texts/145", "parent": { "$ref": "#/groups/29" }, @@ -3735,7 +3825,7 @@ "marker": "-" }, { - "self_ref": "#/texts/142", + "self_ref": "#/texts/146", "parent": { "$ref": "#/groups/29" }, @@ -3749,7 +3839,7 @@ "marker": "-" }, { - "self_ref": "#/texts/143", + "self_ref": "#/texts/147", "parent": { "$ref": "#/groups/29" }, @@ -3763,7 +3853,7 @@ "marker": "-" }, { - "self_ref": "#/texts/144", + "self_ref": "#/texts/148", "parent": { "$ref": "#/groups/29" }, @@ -3777,7 +3867,7 @@ "marker": "-" }, { - "self_ref": "#/texts/145", + "self_ref": "#/texts/149", "parent": { "$ref": "#/groups/29" }, @@ -3791,7 +3881,7 @@ "marker": "-" }, { - "self_ref": "#/texts/146", + "self_ref": "#/texts/150", "parent": { "$ref": "#/groups/29" }, @@ -3805,7 +3895,7 @@ "marker": "-" }, { - "self_ref": "#/texts/147", + "self_ref": "#/texts/151", "parent": { "$ref": "#/groups/29" }, @@ -3819,7 +3909,7 @@ "marker": "-" }, { - "self_ref": "#/texts/148", + "self_ref": "#/texts/152", "parent": { "$ref": "#/groups/29" }, @@ -3833,7 +3923,7 @@ "marker": "-" }, { - "self_ref": "#/texts/149", + "self_ref": "#/texts/153", "parent": { "$ref": "#/groups/29" }, @@ -3847,7 +3937,7 @@ "marker": "-" }, { - "self_ref": "#/texts/150", + "self_ref": "#/texts/154", "parent": { "$ref": "#/groups/29" }, @@ -3861,7 +3951,7 @@ "marker": "-" }, { - "self_ref": "#/texts/151", + "self_ref": "#/texts/155", "parent": { "$ref": "#/groups/29" }, @@ -3875,7 +3965,7 @@ "marker": "-" }, { - "self_ref": "#/texts/152", + "self_ref": "#/texts/156", "parent": { "$ref": "#/groups/29" }, @@ -3889,7 +3979,7 @@ "marker": "-" }, { - "self_ref": "#/texts/153", + "self_ref": "#/texts/157", "parent": { "$ref": "#/groups/29" }, @@ -3903,7 +3993,7 @@ "marker": "-" }, { - "self_ref": "#/texts/154", + "self_ref": "#/texts/158", "parent": { "$ref": "#/groups/29" }, @@ -3917,7 +4007,7 @@ "marker": "-" }, { - "self_ref": "#/texts/155", + "self_ref": "#/texts/159", "parent": { "$ref": "#/groups/29" }, @@ -3931,7 +4021,7 @@ "marker": "-" }, { - "self_ref": "#/texts/156", + "self_ref": "#/texts/160", "parent": { "$ref": "#/groups/29" }, @@ -3945,7 +4035,7 @@ "marker": "-" }, { - "self_ref": "#/texts/157", + "self_ref": "#/texts/161", "parent": { "$ref": "#/groups/29" }, @@ -3959,7 +4049,7 @@ "marker": "-" }, { - "self_ref": "#/texts/158", + "self_ref": "#/texts/162", "parent": { "$ref": "#/groups/29" }, @@ -3973,7 +4063,7 @@ "marker": "-" }, { - "self_ref": "#/texts/159", + "self_ref": "#/texts/163", "parent": { "$ref": "#/groups/29" }, @@ -3987,7 +4077,7 @@ "marker": "-" }, { - "self_ref": "#/texts/160", + "self_ref": "#/texts/164", "parent": { "$ref": "#/groups/29" }, @@ -4001,7 +4091,7 @@ "marker": "-" }, { - "self_ref": "#/texts/161", + "self_ref": "#/texts/165", "parent": { "$ref": "#/groups/29" }, @@ -4015,7 +4105,7 @@ "marker": "-" }, { - "self_ref": "#/texts/162", + "self_ref": "#/texts/166", "parent": { "$ref": "#/groups/29" }, @@ -4029,7 +4119,7 @@ "marker": "-" }, { - "self_ref": "#/texts/163", + "self_ref": "#/texts/167", "parent": { "$ref": "#/groups/29" }, @@ -4043,7 +4133,7 @@ "marker": "-" }, { - "self_ref": "#/texts/164", + "self_ref": "#/texts/168", "parent": { "$ref": "#/groups/29" }, @@ -4057,7 +4147,7 @@ "marker": "-" }, { - "self_ref": "#/texts/165", + "self_ref": "#/texts/169", "parent": { "$ref": "#/groups/29" }, @@ -4071,7 +4161,7 @@ "marker": "-" }, { - "self_ref": "#/texts/166", + "self_ref": "#/texts/170", "parent": { "$ref": "#/groups/29" }, @@ -4085,7 +4175,7 @@ "marker": "-" }, { - "self_ref": "#/texts/167", + "self_ref": "#/texts/171", "parent": { "$ref": "#/groups/29" }, @@ -4099,7 +4189,7 @@ "marker": "-" }, { - "self_ref": "#/texts/168", + "self_ref": "#/texts/172", "parent": { "$ref": "#/groups/29" }, @@ -4113,7 +4203,7 @@ "marker": "-" }, { - "self_ref": "#/texts/169", + "self_ref": "#/texts/173", "parent": { "$ref": "#/groups/29" }, @@ -4127,7 +4217,7 @@ "marker": "-" }, { - "self_ref": "#/texts/170", + "self_ref": "#/texts/174", "parent": { "$ref": "#/groups/29" }, @@ -4141,7 +4231,7 @@ "marker": "-" }, { - "self_ref": "#/texts/171", + "self_ref": "#/texts/175", "parent": { "$ref": "#/groups/29" }, @@ -4155,7 +4245,7 @@ "marker": "-" }, { - "self_ref": "#/texts/172", + "self_ref": "#/texts/176", "parent": { "$ref": "#/groups/29" }, @@ -4169,7 +4259,7 @@ "marker": "-" }, { - "self_ref": "#/texts/173", + "self_ref": "#/texts/177", "parent": { "$ref": "#/groups/29" }, @@ -4183,7 +4273,7 @@ "marker": "-" }, { - "self_ref": "#/texts/174", + "self_ref": "#/texts/178", "parent": { "$ref": "#/groups/29" }, @@ -4197,7 +4287,7 @@ "marker": "-" }, { - "self_ref": "#/texts/175", + "self_ref": "#/texts/179", "parent": { "$ref": "#/groups/29" }, @@ -4211,7 +4301,7 @@ "marker": "-" }, { - "self_ref": "#/texts/176", + "self_ref": "#/texts/180", "parent": { "$ref": "#/groups/30" }, @@ -4225,7 +4315,7 @@ "marker": "-" }, { - "self_ref": "#/texts/177", + "self_ref": "#/texts/181", "parent": { "$ref": "#/groups/30" }, @@ -4238,78 +4328,102 @@ "enumerated": false, "marker": "-" }, - { - "self_ref": "#/texts/178", - "parent": { - "$ref": "#/groups/32" - }, - "children": [], - "content_layer": "body", - "label": "list_item", - "prov": [], - "orig": "Read", - "text": "Read", - "enumerated": false, - "marker": "-" - }, - { - "self_ref": "#/texts/179", - "parent": { - "$ref": "#/groups/32" - }, - "children": [], - "content_layer": "body", - "label": "list_item", - "prov": [], - "orig": "View source", - "text": "View source", - "enumerated": false, - "marker": "-" - }, - { - "self_ref": "#/texts/180", - "parent": { - "$ref": "#/groups/32" - }, - "children": [], - "content_layer": "body", - "label": "list_item", - "prov": [], - "orig": "View history", - "text": "View history", - "enumerated": false, - "marker": "-" - }, - { - "self_ref": "#/texts/181", - "parent": { - "$ref": "#/groups/33" - }, - "children": [], - "content_layer": "body", - "label": "list_item", - "prov": [], - "orig": "Read", - "text": "Read", - "enumerated": false, - "marker": "-" - }, { "self_ref": "#/texts/182", "parent": { - "$ref": "#/groups/33" + "$ref": "#/groups/32" }, "children": [], "content_layer": "body", "label": "list_item", "prov": [], - "orig": "View source", - "text": "View source", + "orig": "Read", + "text": "Read", "enumerated": false, "marker": "-" }, { "self_ref": "#/texts/183", + "parent": { + "$ref": "#/groups/32" + }, + "children": [], + "content_layer": "body", + "label": "list_item", + "prov": [], + "orig": "View source", + "text": "View source", + "enumerated": false, + "marker": "-" + }, + { + "self_ref": "#/texts/184", + "parent": { + "$ref": "#/groups/32" + }, + "children": [], + "content_layer": "body", + "label": "list_item", + "prov": [], + "orig": "View history", + "text": "View history", + "enumerated": false, + "marker": "-" + }, + { + "self_ref": "#/texts/185", + "parent": { + "$ref": "#/texts/43" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Tools", + "text": "Tools" + }, + { + "self_ref": "#/texts/186", + "parent": { + "$ref": "#/texts/43" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Actions", + "text": "Actions" + }, + { + "self_ref": "#/texts/187", + "parent": { + "$ref": "#/groups/33" + }, + "children": [], + "content_layer": "body", + "label": "list_item", + "prov": [], + "orig": "Read", + "text": "Read", + "enumerated": false, + "marker": "-" + }, + { + "self_ref": "#/texts/188", + "parent": { + "$ref": "#/groups/33" + }, + "children": [], + "content_layer": "body", + "label": "list_item", + "prov": [], + "orig": "View source", + "text": "View source", + "enumerated": false, + "marker": "-" + }, + { + "self_ref": "#/texts/189", "parent": { "$ref": "#/groups/33" }, @@ -4323,7 +4437,19 @@ "marker": "-" }, { - "self_ref": "#/texts/184", + "self_ref": "#/texts/190", + "parent": { + "$ref": "#/texts/43" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "General", + "text": "General" + }, + { + "self_ref": "#/texts/191", "parent": { "$ref": "#/groups/34" }, @@ -4337,7 +4463,7 @@ "marker": "-" }, { - "self_ref": "#/texts/185", + "self_ref": "#/texts/192", "parent": { "$ref": "#/groups/34" }, @@ -4351,7 +4477,7 @@ "marker": "-" }, { - "self_ref": "#/texts/186", + "self_ref": "#/texts/193", "parent": { "$ref": "#/groups/34" }, @@ -4365,7 +4491,7 @@ "marker": "-" }, { - "self_ref": "#/texts/187", + "self_ref": "#/texts/194", "parent": { "$ref": "#/groups/34" }, @@ -4379,7 +4505,7 @@ "marker": "-" }, { - "self_ref": "#/texts/188", + "self_ref": "#/texts/195", "parent": { "$ref": "#/groups/34" }, @@ -4393,7 +4519,7 @@ "marker": "-" }, { - "self_ref": "#/texts/189", + "self_ref": "#/texts/196", "parent": { "$ref": "#/groups/34" }, @@ -4407,7 +4533,7 @@ "marker": "-" }, { - "self_ref": "#/texts/190", + "self_ref": "#/texts/197", "parent": { "$ref": "#/groups/34" }, @@ -4421,7 +4547,7 @@ "marker": "-" }, { - "self_ref": "#/texts/191", + "self_ref": "#/texts/198", "parent": { "$ref": "#/groups/34" }, @@ -4435,7 +4561,7 @@ "marker": "-" }, { - "self_ref": "#/texts/192", + "self_ref": "#/texts/199", "parent": { "$ref": "#/groups/34" }, @@ -4449,7 +4575,7 @@ "marker": "-" }, { - "self_ref": "#/texts/193", + "self_ref": "#/texts/200", "parent": { "$ref": "#/groups/34" }, @@ -4463,7 +4589,19 @@ "marker": "-" }, { - "self_ref": "#/texts/194", + "self_ref": "#/texts/201", + "parent": { + "$ref": "#/texts/43" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Print/export", + "text": "Print/export" + }, + { + "self_ref": "#/texts/202", "parent": { "$ref": "#/groups/35" }, @@ -4477,7 +4615,7 @@ "marker": "-" }, { - "self_ref": "#/texts/195", + "self_ref": "#/texts/203", "parent": { "$ref": "#/groups/35" }, @@ -4491,7 +4629,19 @@ "marker": "-" }, { - "self_ref": "#/texts/196", + "self_ref": "#/texts/204", + "parent": { + "$ref": "#/texts/43" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "In other projects", + "text": "In other projects" + }, + { + "self_ref": "#/texts/205", "parent": { "$ref": "#/groups/36" }, @@ -4505,7 +4655,7 @@ "marker": "-" }, { - "self_ref": "#/texts/197", + "self_ref": "#/texts/206", "parent": { "$ref": "#/groups/36" }, @@ -4519,9 +4669,69 @@ "marker": "-" }, { - "self_ref": "#/texts/198", + "self_ref": "#/texts/207", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Appearance", + "text": "Appearance" + }, + { + "self_ref": "#/texts/208", + "parent": { + "$ref": "#/texts/43" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "From Wikipedia, the free encyclopedia", + "text": "From Wikipedia, the free encyclopedia" + }, + { + "self_ref": "#/texts/209", + "parent": { + "$ref": "#/texts/43" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Common name for many species of bird", + "text": "Common name for many species of bird" + }, + { + "self_ref": "#/texts/210", + "parent": { + "$ref": "#/texts/43" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "This article is about the bird. For duck as a food, see . For other uses, see .", + "text": "This article is about the bird. For duck as a food, see . For other uses, see ." + }, + { + "self_ref": "#/texts/211", + "parent": { + "$ref": "#/texts/43" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "\"Duckling\" redirects here. For other uses, see .", + "text": "\"Duckling\" redirects here. For other uses, see ." + }, + { + "self_ref": "#/texts/212", + "parent": { + "$ref": "#/texts/43" }, "children": [], "content_layer": "body", @@ -4531,9 +4741,9 @@ "text": "Duck is the common name for numerous species of waterfowl in the family Anatidae. Ducks are generally smaller and shorter-necked than swans and geese, which are members of the same family. Divided among several subfamilies, they are a form taxon; they do not represent a monophyletic group (the group of all descendants of a single common ancestral species), since swans and geese are not considered ducks. Ducks are mostly aquatic birds, and may be found in both fresh water and sea water." }, { - "self_ref": "#/texts/199", + "self_ref": "#/texts/213", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [], "content_layer": "body", @@ -4543,25 +4753,25 @@ "text": "Ducks are sometimes confused with several types of unrelated water birds with similar forms, such as loons or divers, grebes, gallinules and coots." }, { - "self_ref": "#/texts/200", + "self_ref": "#/texts/214", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [ { - "$ref": "#/texts/201" + "$ref": "#/texts/215" }, { "$ref": "#/pictures/4" }, { - "$ref": "#/texts/203" + "$ref": "#/texts/217" }, { - "$ref": "#/texts/204" + "$ref": "#/texts/218" }, { - "$ref": "#/texts/205" + "$ref": "#/texts/219" }, { "$ref": "#/pictures/5" @@ -4578,9 +4788,9 @@ "level": 2 }, { - "self_ref": "#/texts/201", + "self_ref": "#/texts/215", "parent": { - "$ref": "#/texts/200" + "$ref": "#/texts/214" }, "children": [], "content_layer": "body", @@ -4590,7 +4800,7 @@ "text": "The word duck comes from Old English d\u016bce 'diver', a derivative of the verb *d\u016bcan 'to duck, bend down low as if to get under something, or dive', because of the way many species in the dabbling duck group feed by upending; compare with Dutch duiken and German tauchen 'to dive'." }, { - "self_ref": "#/texts/202", + "self_ref": "#/texts/216", "parent": { "$ref": "#/body" }, @@ -4602,9 +4812,9 @@ "text": "Pacific black duck displaying the characteristic upending \"duck\"" }, { - "self_ref": "#/texts/203", + "self_ref": "#/texts/217", "parent": { - "$ref": "#/texts/200" + "$ref": "#/texts/214" }, "children": [], "content_layer": "body", @@ -4614,9 +4824,9 @@ "text": "This word replaced Old English ened /\u00e6nid 'duck', possibly to avoid confusion with other words, such as ende 'end' with similar forms. Other Germanic languages still have similar words for duck, for example, Dutch eend, German Ente and Norwegian and. The word ened /\u00e6nid was inherited from Proto-Indo-European; cf. Latin anas \"duck\", Lithuanian \u00e1ntis 'duck', Ancient Greek \u03bd\u1fc6\u03c3\u03c3\u03b1 /\u03bd\u1fc6\u03c4\u03c4\u03b1 (n\u0113ssa /n\u0113tta) 'duck', and Sanskrit \u0101t\u00ed 'water bird', among others." }, { - "self_ref": "#/texts/204", + "self_ref": "#/texts/218", "parent": { - "$ref": "#/texts/200" + "$ref": "#/texts/214" }, "children": [], "content_layer": "body", @@ -4626,9 +4836,9 @@ "text": "A duckling is a young duck in downy plumage[1] or baby duck,[2] but in the food trade a young domestic duck which has just reached adult size and bulk and its meat is still fully tender, is sometimes labelled as a duckling." }, { - "self_ref": "#/texts/205", + "self_ref": "#/texts/219", "parent": { - "$ref": "#/texts/200" + "$ref": "#/texts/214" }, "children": [], "content_layer": "body", @@ -4638,7 +4848,7 @@ "text": "A male is called a drake and the female is called a duck, or in ornithology a hen.[3][4]" }, { - "self_ref": "#/texts/206", + "self_ref": "#/texts/220", "parent": { "$ref": "#/body" }, @@ -4650,7 +4860,7 @@ "text": "Male mallard." }, { - "self_ref": "#/texts/207", + "self_ref": "#/texts/221", "parent": { "$ref": "#/body" }, @@ -4662,22 +4872,22 @@ "text": "Wood ducks." }, { - "self_ref": "#/texts/208", + "self_ref": "#/texts/222", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [ { - "$ref": "#/texts/209" + "$ref": "#/texts/223" }, { "$ref": "#/pictures/7" }, { - "$ref": "#/texts/211" + "$ref": "#/texts/225" }, { - "$ref": "#/texts/212" + "$ref": "#/texts/226" } ], "content_layer": "body", @@ -4688,9 +4898,9 @@ "level": 2 }, { - "self_ref": "#/texts/209", + "self_ref": "#/texts/223", "parent": { - "$ref": "#/texts/208" + "$ref": "#/texts/222" }, "children": [], "content_layer": "body", @@ -4700,7 +4910,7 @@ "text": "All ducks belong to the biological order Anseriformes, a group that contains the ducks, geese and swans, as well as the screamers, and the magpie goose.[5] All except the screamers belong to the biological family Anatidae.[5] Within the family, ducks are split into a variety of subfamilies and 'tribes'. The number and composition of these subfamilies and tribes is the cause of considerable disagreement among taxonomists.[5] Some base their decisions on morphological characteristics, others on shared behaviours or genetic studies.[6][7] The number of suggested subfamilies containing ducks ranges from two to five.[8][9] The significant level of hybridisation that occurs among wild ducks complicates efforts to tease apart the relationships between various species.[9]" }, { - "self_ref": "#/texts/210", + "self_ref": "#/texts/224", "parent": { "$ref": "#/body" }, @@ -4712,9 +4922,9 @@ "text": "Mallard landing in approach" }, { - "self_ref": "#/texts/211", + "self_ref": "#/texts/225", "parent": { - "$ref": "#/texts/208" + "$ref": "#/texts/222" }, "children": [], "content_layer": "body", @@ -4724,9 +4934,9 @@ "text": "In most modern classifications, the so-called 'true ducks' belong to the subfamily Anatinae, which is further split into a varying number of tribes.[10] The largest of these, the Anatini, contains the 'dabbling' or 'river' ducks \u2013 named for their method of feeding primarily at the surface of fresh water.[11] The 'diving ducks', also named for their primary feeding method, make up the tribe Aythyini.[12] The 'sea ducks' of the tribe Mergini are diving ducks which specialise on fish and shellfish and spend a majority of their lives in saltwater.[13] The tribe Oxyurini contains the 'stifftails', diving ducks notable for their small size and stiff, upright tails.[14]" }, { - "self_ref": "#/texts/212", + "self_ref": "#/texts/226", "parent": { - "$ref": "#/texts/208" + "$ref": "#/texts/222" }, "children": [], "content_layer": "body", @@ -4736,19 +4946,19 @@ "text": "A number of other species called ducks are not considered to be 'true ducks', and are typically placed in other subfamilies or tribes. The whistling ducks are assigned either to a tribe (Dendrocygnini) in the subfamily Anatinae or the subfamily Anserinae,[15] or to their own subfamily (Dendrocygninae) or family (Dendrocyganidae).[9][16] The freckled duck of Australia is either the sole member of the tribe Stictonettini in the subfamily Anserinae,[15] or in its own family, the Stictonettinae.[9] The shelducks make up the tribe Tadornini in the family Anserinae in some classifications,[15] and their own subfamily, Tadorninae, in others,[17] while the steamer ducks are either placed in the family Anserinae in the tribe Tachyerini[15] or lumped with the shelducks in the tribe Tadorini.[9] The perching ducks make up in the tribe Cairinini in the subfamily Anserinae in some classifications, while that tribe is eliminated in other classifications and its members assigned to the tribe Anatini.[9] The torrent duck is generally included in the subfamily Anserinae in the monotypic tribe Merganettini,[15] but is sometimes included in the tribe Tadornini.[18] The pink-eared duck is sometimes included as a true duck either in the tribe Anatini[15] or the tribe Malacorhynchini,[19] and other times is included with the shelducks in the tribe Tadornini.[15]" }, { - "self_ref": "#/texts/213", + "self_ref": "#/texts/227", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [ { "$ref": "#/pictures/8" }, { - "$ref": "#/texts/215" + "$ref": "#/texts/229" }, { - "$ref": "#/texts/216" + "$ref": "#/texts/230" } ], "content_layer": "body", @@ -4759,7 +4969,7 @@ "level": 2 }, { - "self_ref": "#/texts/214", + "self_ref": "#/texts/228", "parent": { "$ref": "#/body" }, @@ -4771,9 +4981,9 @@ "text": "Male Mandarin duck" }, { - "self_ref": "#/texts/215", + "self_ref": "#/texts/229", "parent": { - "$ref": "#/texts/213" + "$ref": "#/texts/227" }, "children": [], "content_layer": "body", @@ -4783,9 +4993,9 @@ "text": "The overall body plan of ducks is elongated and broad, and they are also relatively long-necked, albeit not as long-necked as the geese and swans. The body shape of diving ducks varies somewhat from this in being more rounded. The bill is usually broad and contains serrated pectens, which are particularly well defined in the filter-feeding species. In the case of some fishing species the bill is long and strongly serrated. The scaled legs are strong and well developed, and generally set far back on the body, more so in the highly aquatic species. The wings are very strong and are generally short and pointed, and the flight of ducks requires fast continuous strokes, requiring in turn strong wing muscles. Three species of steamer duck are almost flightless, however. Many species of duck are temporarily flightless while moulting; they seek out protected habitat with good food supplies during this period. This moult typically precedes migration." }, { - "self_ref": "#/texts/216", + "self_ref": "#/texts/230", "parent": { - "$ref": "#/texts/213" + "$ref": "#/texts/227" }, "children": [], "content_layer": "body", @@ -4795,22 +5005,22 @@ "text": "The drakes of northern species often have extravagant plumage, but that is moulted in summer to give a more female-like appearance, the \"eclipse\" plumage. Southern resident species typically show less sexual dimorphism, although there are exceptions such as the paradise shelduck of New Zealand, which is both strikingly sexually dimorphic and in which the female's plumage is brighter than that of the male. The plumage of juvenile birds generally resembles that of the female. Female ducks have evolved to have a corkscrew shaped vagina to prevent rape." }, { - "self_ref": "#/texts/217", + "self_ref": "#/texts/231", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [ { "$ref": "#/pictures/9" }, { - "$ref": "#/texts/219" + "$ref": "#/texts/233" }, { "$ref": "#/pictures/10" }, { - "$ref": "#/texts/221" + "$ref": "#/texts/235" } ], "content_layer": "body", @@ -4821,7 +5031,7 @@ "level": 2 }, { - "self_ref": "#/texts/218", + "self_ref": "#/texts/232", "parent": { "$ref": "#/body" }, @@ -4833,9 +5043,9 @@ "text": "Flying steamer ducks in Ushuaia, Argentina" }, { - "self_ref": "#/texts/219", + "self_ref": "#/texts/233", "parent": { - "$ref": "#/texts/217" + "$ref": "#/texts/231" }, "children": [], "content_layer": "body", @@ -4845,7 +5055,7 @@ "text": "Ducks have a cosmopolitan distribution, and are found on every continent except Antarctica.[5] Several species manage to live on subantarctic islands, including South Georgia and the Auckland Islands.[20] Ducks have reached a number of isolated oceanic islands, including the Hawaiian Islands, Micronesia and the Gal\u00e1pagos Islands, where they are often vagrants and less often residents.[21][22] A handful are endemic to such far-flung islands.[21]" }, { - "self_ref": "#/texts/220", + "self_ref": "#/texts/234", "parent": { "$ref": "#/body" }, @@ -4857,9 +5067,9 @@ "text": "Female mallard in Cornwall, England" }, { - "self_ref": "#/texts/221", + "self_ref": "#/texts/235", "parent": { - "$ref": "#/texts/217" + "$ref": "#/texts/231" }, "children": [], "content_layer": "body", @@ -4868,321 +5078,14 @@ "orig": "Some duck species, mainly those breeding in the temperate and Arctic Northern Hemisphere, are migratory; those in the tropics are generally not. Some ducks, particularly in Australia where rainfall is erratic, are nomadic, seeking out the temporary lakes and pools that form after localised heavy rain.[23]", "text": "Some duck species, mainly those breeding in the temperate and Arctic Northern Hemisphere, are migratory; those in the tropics are generally not. Some ducks, particularly in Australia where rainfall is erratic, are nomadic, seeking out the temporary lakes and pools that form after localised heavy rain.[23]" }, - { - "self_ref": "#/texts/222", - "parent": { - "$ref": "#/texts/39" - }, - "children": [ - { - "$ref": "#/texts/223" - }, - { - "$ref": "#/texts/232" - }, - { - "$ref": "#/texts/235" - }, - { - "$ref": "#/texts/238" - } - ], - "content_layer": "body", - "label": "section_header", - "prov": [], - "orig": "Behaviour", - "text": "Behaviour", - "level": 2 - }, - { - "self_ref": "#/texts/223", - "parent": { - "$ref": "#/texts/222" - }, - "children": [ - { - "$ref": "#/pictures/11" - }, - { - "$ref": "#/pictures/12" - }, - { - "$ref": "#/texts/226" - }, - { - "$ref": "#/texts/227" - }, - { - "$ref": "#/texts/228" - }, - { - "$ref": "#/texts/229" - }, - { - "$ref": "#/texts/230" - }, - { - "$ref": "#/texts/231" - } - ], - "content_layer": "body", - "label": "section_header", - "prov": [], - "orig": "Feeding", - "text": "Feeding", - "level": 3 - }, - { - "self_ref": "#/texts/224", - "parent": { - "$ref": "#/body" - }, - "children": [], - "content_layer": "body", - "label": "caption", - "prov": [], - "orig": "Pecten along the bill", - "text": "Pecten along the bill" - }, - { - "self_ref": "#/texts/225", - "parent": { - "$ref": "#/body" - }, - "children": [], - "content_layer": "body", - "label": "caption", - "prov": [], - "orig": "Mallard duckling preening", - "text": "Mallard duckling preening" - }, - { - "self_ref": "#/texts/226", - "parent": { - "$ref": "#/texts/223" - }, - "children": [], - "content_layer": "body", - "label": "paragraph", - "prov": [], - "orig": "Ducks eat food sources such as grasses, aquatic plants, fish, insects, small amphibians, worms, and small molluscs.", - "text": "Ducks eat food sources such as grasses, aquatic plants, fish, insects, small amphibians, worms, and small molluscs." - }, - { - "self_ref": "#/texts/227", - "parent": { - "$ref": "#/texts/223" - }, - "children": [], - "content_layer": "body", - "label": "paragraph", - "prov": [], - "orig": "Dabbling ducks feed on the surface of water or on land, or as deep as they can reach by up-ending without completely submerging.[24] Along the edge of the bill, there is a comb-like structure called a pecten. This strains the water squirting from the side of the bill and traps any food. The pecten is also used to preen feathers and to hold slippery food items.", - "text": "Dabbling ducks feed on the surface of water or on land, or as deep as they can reach by up-ending without completely submerging.[24] Along the edge of the bill, there is a comb-like structure called a pecten. This strains the water squirting from the side of the bill and traps any food. The pecten is also used to preen feathers and to hold slippery food items." - }, - { - "self_ref": "#/texts/228", - "parent": { - "$ref": "#/texts/223" - }, - "children": [], - "content_layer": "body", - "label": "paragraph", - "prov": [], - "orig": "Diving ducks and sea ducks forage deep underwater. To be able to submerge more easily, the diving ducks are heavier than dabbling ducks, and therefore have more difficulty taking off to fly.", - "text": "Diving ducks and sea ducks forage deep underwater. To be able to submerge more easily, the diving ducks are heavier than dabbling ducks, and therefore have more difficulty taking off to fly." - }, - { - "self_ref": "#/texts/229", - "parent": { - "$ref": "#/texts/223" - }, - "children": [], - "content_layer": "body", - "label": "paragraph", - "prov": [], - "orig": "A few specialized species such as the mergansers are adapted to catch and swallow large fish.", - "text": "A few specialized species such as the mergansers are adapted to catch and swallow large fish." - }, - { - "self_ref": "#/texts/230", - "parent": { - "$ref": "#/texts/223" - }, - "children": [], - "content_layer": "body", - "label": "paragraph", - "prov": [], - "orig": "The others have the characteristic wide flat bill adapted to dredging-type jobs such as pulling up waterweed, pulling worms and small molluscs out of mud, searching for insect larvae, and bulk jobs such as dredging out, holding, turning head first, and swallowing a squirming frog. To avoid injury when digging into sediment it has no cere, but the nostrils come out through hard horn.", - "text": "The others have the characteristic wide flat bill adapted to dredging-type jobs such as pulling up waterweed, pulling worms and small molluscs out of mud, searching for insect larvae, and bulk jobs such as dredging out, holding, turning head first, and swallowing a squirming frog. To avoid injury when digging into sediment it has no cere, but the nostrils come out through hard horn." - }, - { - "self_ref": "#/texts/231", - "parent": { - "$ref": "#/texts/223" - }, - "children": [], - "content_layer": "body", - "label": "paragraph", - "prov": [], - "orig": "The Guardian published an article advising that ducks should not be fed with bread because it damages the health of the ducks and pollutes waterways.[25]", - "text": "The Guardian published an article advising that ducks should not be fed with bread because it damages the health of the ducks and pollutes waterways.[25]" - }, - { - "self_ref": "#/texts/232", - "parent": { - "$ref": "#/texts/222" - }, - "children": [ - { - "$ref": "#/pictures/13" - }, - { - "$ref": "#/texts/234" - } - ], - "content_layer": "body", - "label": "section_header", - "prov": [], - "orig": "Breeding", - "text": "Breeding", - "level": 3 - }, - { - "self_ref": "#/texts/233", - "parent": { - "$ref": "#/body" - }, - "children": [], - "content_layer": "body", - "label": "caption", - "prov": [], - "orig": "A Muscovy duckling", - "text": "A Muscovy duckling" - }, - { - "self_ref": "#/texts/234", - "parent": { - "$ref": "#/texts/232" - }, - "children": [], - "content_layer": "body", - "label": "paragraph", - "prov": [], - "orig": "Ducks generally only have one partner at a time, although the partnership usually only lasts one year.[26] Larger species and the more sedentary species (like fast-river specialists) tend to have pair-bonds that last numerous years.[27] Most duck species breed once a year, choosing to do so in favourable conditions (spring/summer or wet seasons). Ducks also tend to make a nest before breeding, and, after hatching, lead their ducklings to water. Mother ducks are very caring and protective of their young, but may abandon some of their ducklings if they are physically stuck in an area they cannot get out of (such as nesting in an enclosed courtyard) or are not prospering due to genetic defects or sickness brought about by hypothermia, starvation, or disease. Ducklings can also be orphaned by inconsistent late hatching where a few eggs hatch after the mother has abandoned the nest and led her ducklings to water.[28]", - "text": "Ducks generally only have one partner at a time, although the partnership usually only lasts one year.[26] Larger species and the more sedentary species (like fast-river specialists) tend to have pair-bonds that last numerous years.[27] Most duck species breed once a year, choosing to do so in favourable conditions (spring/summer or wet seasons). Ducks also tend to make a nest before breeding, and, after hatching, lead their ducklings to water. Mother ducks are very caring and protective of their young, but may abandon some of their ducklings if they are physically stuck in an area they cannot get out of (such as nesting in an enclosed courtyard) or are not prospering due to genetic defects or sickness brought about by hypothermia, starvation, or disease. Ducklings can also be orphaned by inconsistent late hatching where a few eggs hatch after the mother has abandoned the nest and led her ducklings to water.[28]" - }, - { - "self_ref": "#/texts/235", - "parent": { - "$ref": "#/texts/222" - }, - "children": [ - { - "$ref": "#/texts/236" - }, - { - "$ref": "#/texts/237" - } - ], - "content_layer": "body", - "label": "section_header", - "prov": [], - "orig": "Communication", - "text": "Communication", - "level": 3 - }, { "self_ref": "#/texts/236", "parent": { - "$ref": "#/texts/235" - }, - "children": [], - "content_layer": "body", - "label": "paragraph", - "prov": [], - "orig": "Female mallard ducks (as well as several other species in the genus Anas, such as the American and Pacific black ducks, spot-billed duck, northern pintail and common teal) make the classic \"quack\" sound while males make a similar but raspier sound that is sometimes written as \"breeeeze\",[29][self-published source?] but, despite widespread misconceptions, most species of duck do not \"quack\".[30] In general, ducks make a range of calls, including whistles, cooing, yodels and grunts. For example, the scaup \u2013 which are diving ducks \u2013 make a noise like \"scaup\" (hence their name). Calls may be loud displaying calls or quieter contact calls.", - "text": "Female mallard ducks (as well as several other species in the genus Anas, such as the American and Pacific black ducks, spot-billed duck, northern pintail and common teal) make the classic \"quack\" sound while males make a similar but raspier sound that is sometimes written as \"breeeeze\",[29][self-published source?] but, despite widespread misconceptions, most species of duck do not \"quack\".[30] In general, ducks make a range of calls, including whistles, cooing, yodels and grunts. For example, the scaup \u2013 which are diving ducks \u2013 make a noise like \"scaup\" (hence their name). Calls may be loud displaying calls or quieter contact calls." - }, - { - "self_ref": "#/texts/237", - "parent": { - "$ref": "#/texts/235" - }, - "children": [], - "content_layer": "body", - "label": "paragraph", - "prov": [], - "orig": "A common urban legend claims that duck quacks do not echo; however, this has been proven to be false. This myth was first debunked by the Acoustics Research Centre at the University of Salford in 2003 as part of the British Association's Festival of Science.[31] It was also debunked in one of the earlier episodes of the popular Discovery Channel television show MythBusters.[32]", - "text": "A common urban legend claims that duck quacks do not echo; however, this has been proven to be false. This myth was first debunked by the Acoustics Research Centre at the University of Salford in 2003 as part of the British Association's Festival of Science.[31] It was also debunked in one of the earlier episodes of the popular Discovery Channel television show MythBusters.[32]" - }, - { - "self_ref": "#/texts/238", - "parent": { - "$ref": "#/texts/222" + "$ref": "#/texts/43" }, "children": [ { - "$ref": "#/pictures/14" - }, - { - "$ref": "#/texts/240" - }, - { - "$ref": "#/texts/241" - } - ], - "content_layer": "body", - "label": "section_header", - "prov": [], - "orig": "Predators", - "text": "Predators", - "level": 3 - }, - { - "self_ref": "#/texts/239", - "parent": { - "$ref": "#/body" - }, - "children": [], - "content_layer": "body", - "label": "caption", - "prov": [], - "orig": "Ringed teal", - "text": "Ringed teal" - }, - { - "self_ref": "#/texts/240", - "parent": { - "$ref": "#/texts/238" - }, - "children": [], - "content_layer": "body", - "label": "paragraph", - "prov": [], - "orig": "Ducks have many predators. Ducklings are particularly vulnerable, since their inability to fly makes them easy prey not only for predatory birds but also for large fish like pike, crocodilians, predatory testudines such as the alligator snapping turtle, and other aquatic hunters, including fish-eating birds such as herons. Ducks' nests are raided by land-based predators, and brooding females may be caught unaware on the nest by mammals, such as foxes, or large birds, such as hawks or owls.", - "text": "Ducks have many predators. Ducklings are particularly vulnerable, since their inability to fly makes them easy prey not only for predatory birds but also for large fish like pike, crocodilians, predatory testudines such as the alligator snapping turtle, and other aquatic hunters, including fish-eating birds such as herons. Ducks' nests are raided by land-based predators, and brooding females may be caught unaware on the nest by mammals, such as foxes, or large birds, such as hawks or owls." - }, - { - "self_ref": "#/texts/241", - "parent": { - "$ref": "#/texts/238" - }, - "children": [], - "content_layer": "body", - "label": "paragraph", - "prov": [], - "orig": "Adult ducks are fast fliers, but may be caught on the water by large aquatic predators including big fish such as the North American muskie and the European pike. In flight, ducks are safe from all but a few predators such as humans and the peregrine falcon, which uses its speed and strength to catch ducks.", - "text": "Adult ducks are fast fliers, but may be caught on the water by large aquatic predators including big fish such as the North American muskie and the European pike. In flight, ducks are safe from all but a few predators such as humans and the peregrine falcon, which uses its speed and strength to catch ducks." - }, - { - "self_ref": "#/texts/242", - "parent": { - "$ref": "#/texts/39" - }, - "children": [ - { - "$ref": "#/texts/243" + "$ref": "#/texts/237" }, { "$ref": "#/texts/246" @@ -5197,16 +5100,34 @@ "content_layer": "body", "label": "section_header", "prov": [], - "orig": "Relationship with humans", - "text": "Relationship with humans", + "orig": "Behaviour", + "text": "Behaviour", "level": 2 }, { - "self_ref": "#/texts/243", + "self_ref": "#/texts/237", "parent": { - "$ref": "#/texts/242" + "$ref": "#/texts/236" }, "children": [ + { + "$ref": "#/pictures/11" + }, + { + "$ref": "#/pictures/12" + }, + { + "$ref": "#/texts/240" + }, + { + "$ref": "#/texts/241" + }, + { + "$ref": "#/texts/242" + }, + { + "$ref": "#/texts/243" + }, { "$ref": "#/texts/244" }, @@ -5217,42 +5138,114 @@ "content_layer": "body", "label": "section_header", "prov": [], - "orig": "Hunting", - "text": "Hunting", + "orig": "Feeding", + "text": "Feeding", "level": 3 }, + { + "self_ref": "#/texts/238", + "parent": { + "$ref": "#/body" + }, + "children": [], + "content_layer": "body", + "label": "caption", + "prov": [], + "orig": "Pecten along the bill", + "text": "Pecten along the bill" + }, + { + "self_ref": "#/texts/239", + "parent": { + "$ref": "#/body" + }, + "children": [], + "content_layer": "body", + "label": "caption", + "prov": [], + "orig": "Mallard duckling preening", + "text": "Mallard duckling preening" + }, + { + "self_ref": "#/texts/240", + "parent": { + "$ref": "#/texts/237" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Ducks eat food sources such as grasses, aquatic plants, fish, insects, small amphibians, worms, and small molluscs.", + "text": "Ducks eat food sources such as grasses, aquatic plants, fish, insects, small amphibians, worms, and small molluscs." + }, + { + "self_ref": "#/texts/241", + "parent": { + "$ref": "#/texts/237" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Dabbling ducks feed on the surface of water or on land, or as deep as they can reach by up-ending without completely submerging.[24] Along the edge of the bill, there is a comb-like structure called a pecten. This strains the water squirting from the side of the bill and traps any food. The pecten is also used to preen feathers and to hold slippery food items.", + "text": "Dabbling ducks feed on the surface of water or on land, or as deep as they can reach by up-ending without completely submerging.[24] Along the edge of the bill, there is a comb-like structure called a pecten. This strains the water squirting from the side of the bill and traps any food. The pecten is also used to preen feathers and to hold slippery food items." + }, + { + "self_ref": "#/texts/242", + "parent": { + "$ref": "#/texts/237" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Diving ducks and sea ducks forage deep underwater. To be able to submerge more easily, the diving ducks are heavier than dabbling ducks, and therefore have more difficulty taking off to fly.", + "text": "Diving ducks and sea ducks forage deep underwater. To be able to submerge more easily, the diving ducks are heavier than dabbling ducks, and therefore have more difficulty taking off to fly." + }, + { + "self_ref": "#/texts/243", + "parent": { + "$ref": "#/texts/237" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "A few specialized species such as the mergansers are adapted to catch and swallow large fish.", + "text": "A few specialized species such as the mergansers are adapted to catch and swallow large fish." + }, { "self_ref": "#/texts/244", "parent": { - "$ref": "#/texts/243" + "$ref": "#/texts/237" }, "children": [], "content_layer": "body", "label": "paragraph", "prov": [], - "orig": "Humans have hunted ducks since prehistoric times. Excavations of middens in California dating to 7800 \u2013 6400 BP have turned up bones of ducks, including at least one now-extinct flightless species.[33] Ducks were captured in \"significant numbers\" by Holocene inhabitants of the lower Ohio River valley, suggesting they took advantage of the seasonal bounty provided by migrating waterfowl.[34] Neolithic hunters in locations as far apart as the Caribbean,[35] Scandinavia,[36] Egypt,[37] Switzerland,[38] and China relied on ducks as a source of protein for some or all of the year.[39] Archeological evidence shows that M\u0101ori people in New Zealand hunted the flightless Finsch's duck, possibly to extinction, though rat predation may also have contributed to its fate.[40] A similar end awaited the Chatham duck, a species with reduced flying capabilities which went extinct shortly after its island was colonised by Polynesian settlers.[41] It is probable that duck eggs were gathered by Neolithic hunter-gathers as well, though hard evidence of this is uncommon.[35][42]", - "text": "Humans have hunted ducks since prehistoric times. Excavations of middens in California dating to 7800 \u2013 6400 BP have turned up bones of ducks, including at least one now-extinct flightless species.[33] Ducks were captured in \"significant numbers\" by Holocene inhabitants of the lower Ohio River valley, suggesting they took advantage of the seasonal bounty provided by migrating waterfowl.[34] Neolithic hunters in locations as far apart as the Caribbean,[35] Scandinavia,[36] Egypt,[37] Switzerland,[38] and China relied on ducks as a source of protein for some or all of the year.[39] Archeological evidence shows that M\u0101ori people in New Zealand hunted the flightless Finsch's duck, possibly to extinction, though rat predation may also have contributed to its fate.[40] A similar end awaited the Chatham duck, a species with reduced flying capabilities which went extinct shortly after its island was colonised by Polynesian settlers.[41] It is probable that duck eggs were gathered by Neolithic hunter-gathers as well, though hard evidence of this is uncommon.[35][42]" + "orig": "The others have the characteristic wide flat bill adapted to dredging-type jobs such as pulling up waterweed, pulling worms and small molluscs out of mud, searching for insect larvae, and bulk jobs such as dredging out, holding, turning head first, and swallowing a squirming frog. To avoid injury when digging into sediment it has no cere, but the nostrils come out through hard horn.", + "text": "The others have the characteristic wide flat bill adapted to dredging-type jobs such as pulling up waterweed, pulling worms and small molluscs out of mud, searching for insect larvae, and bulk jobs such as dredging out, holding, turning head first, and swallowing a squirming frog. To avoid injury when digging into sediment it has no cere, but the nostrils come out through hard horn." }, { "self_ref": "#/texts/245", "parent": { - "$ref": "#/texts/243" + "$ref": "#/texts/237" }, "children": [], "content_layer": "body", "label": "paragraph", "prov": [], - "orig": "In many areas, wild ducks (including ducks farmed and released into the wild) are hunted for food or sport,[43] by shooting, or by being trapped using duck decoys. Because an idle floating duck or a duck squatting on land cannot react to fly or move quickly, \"a sitting duck\" has come to mean \"an easy target\". These ducks may be contaminated by pollutants such as PCBs.[44]", - "text": "In many areas, wild ducks (including ducks farmed and released into the wild) are hunted for food or sport,[43] by shooting, or by being trapped using duck decoys. Because an idle floating duck or a duck squatting on land cannot react to fly or move quickly, \"a sitting duck\" has come to mean \"an easy target\". These ducks may be contaminated by pollutants such as PCBs.[44]" + "orig": "The Guardian published an article advising that ducks should not be fed with bread because it damages the health of the ducks and pollutes waterways.[25]", + "text": "The Guardian published an article advising that ducks should not be fed with bread because it damages the health of the ducks and pollutes waterways.[25]" }, { "self_ref": "#/texts/246", "parent": { - "$ref": "#/texts/242" + "$ref": "#/texts/236" }, "children": [ { - "$ref": "#/pictures/15" + "$ref": "#/pictures/13" }, { "$ref": "#/texts/248" @@ -5261,8 +5254,8 @@ "content_layer": "body", "label": "section_header", "prov": [], - "orig": "Domestication", - "text": "Domestication", + "orig": "Breeding", + "text": "Breeding", "level": 3 }, { @@ -5274,8 +5267,8 @@ "content_layer": "body", "label": "caption", "prov": [], - "orig": "Indian Runner ducks, a common breed of domestic ducks", - "text": "Indian Runner ducks, a common breed of domestic ducks" + "orig": "A Muscovy duckling", + "text": "A Muscovy duckling" }, { "self_ref": "#/texts/248", @@ -5286,20 +5279,237 @@ "content_layer": "body", "label": "paragraph", "prov": [], - "orig": "Ducks have many economic uses, being farmed for their meat, eggs, and feathers (particularly their down). Approximately 3 billion ducks are slaughtered each year for meat worldwide.[45] They are also kept and bred by aviculturists and often displayed in zoos. Almost all the varieties of domestic ducks are descended from the mallard (Anas platyrhynchos), apart from the Muscovy duck (Cairina moschata).[46][47] The Call duck is another example of a domestic duck breed. Its name comes from its original use established by hunters, as a decoy to attract wild mallards from the sky, into traps set for them on the ground. The call duck is the world's smallest domestic duck breed, as it weighs less than 1\u00a0kg (2.2\u00a0lb).[48]", - "text": "Ducks have many economic uses, being farmed for their meat, eggs, and feathers (particularly their down). Approximately 3 billion ducks are slaughtered each year for meat worldwide.[45] They are also kept and bred by aviculturists and often displayed in zoos. Almost all the varieties of domestic ducks are descended from the mallard (Anas platyrhynchos), apart from the Muscovy duck (Cairina moschata).[46][47] The Call duck is another example of a domestic duck breed. Its name comes from its original use established by hunters, as a decoy to attract wild mallards from the sky, into traps set for them on the ground. The call duck is the world's smallest domestic duck breed, as it weighs less than 1\u00a0kg (2.2\u00a0lb).[48]" + "orig": "Ducks generally only have one partner at a time, although the partnership usually only lasts one year.[26] Larger species and the more sedentary species (like fast-river specialists) tend to have pair-bonds that last numerous years.[27] Most duck species breed once a year, choosing to do so in favourable conditions (spring/summer or wet seasons). Ducks also tend to make a nest before breeding, and, after hatching, lead their ducklings to water. Mother ducks are very caring and protective of their young, but may abandon some of their ducklings if they are physically stuck in an area they cannot get out of (such as nesting in an enclosed courtyard) or are not prospering due to genetic defects or sickness brought about by hypothermia, starvation, or disease. Ducklings can also be orphaned by inconsistent late hatching where a few eggs hatch after the mother has abandoned the nest and led her ducklings to water.[28]", + "text": "Ducks generally only have one partner at a time, although the partnership usually only lasts one year.[26] Larger species and the more sedentary species (like fast-river specialists) tend to have pair-bonds that last numerous years.[27] Most duck species breed once a year, choosing to do so in favourable conditions (spring/summer or wet seasons). Ducks also tend to make a nest before breeding, and, after hatching, lead their ducklings to water. Mother ducks are very caring and protective of their young, but may abandon some of their ducklings if they are physically stuck in an area they cannot get out of (such as nesting in an enclosed courtyard) or are not prospering due to genetic defects or sickness brought about by hypothermia, starvation, or disease. Ducklings can also be orphaned by inconsistent late hatching where a few eggs hatch after the mother has abandoned the nest and led her ducklings to water.[28]" }, { "self_ref": "#/texts/249", "parent": { - "$ref": "#/texts/242" + "$ref": "#/texts/236" + }, + "children": [ + { + "$ref": "#/texts/250" + }, + { + "$ref": "#/texts/251" + } + ], + "content_layer": "body", + "label": "section_header", + "prov": [], + "orig": "Communication", + "text": "Communication", + "level": 3 + }, + { + "self_ref": "#/texts/250", + "parent": { + "$ref": "#/texts/249" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Female mallard ducks (as well as several other species in the genus Anas, such as the American and Pacific black ducks, spot-billed duck, northern pintail and common teal) make the classic \"quack\" sound while males make a similar but raspier sound that is sometimes written as \"breeeeze\",[29][self-published source?] but, despite widespread misconceptions, most species of duck do not \"quack\".[30] In general, ducks make a range of calls, including whistles, cooing, yodels and grunts. For example, the scaup \u2013 which are diving ducks \u2013 make a noise like \"scaup\" (hence their name). Calls may be loud displaying calls or quieter contact calls.", + "text": "Female mallard ducks (as well as several other species in the genus Anas, such as the American and Pacific black ducks, spot-billed duck, northern pintail and common teal) make the classic \"quack\" sound while males make a similar but raspier sound that is sometimes written as \"breeeeze\",[29][self-published source?] but, despite widespread misconceptions, most species of duck do not \"quack\".[30] In general, ducks make a range of calls, including whistles, cooing, yodels and grunts. For example, the scaup \u2013 which are diving ducks \u2013 make a noise like \"scaup\" (hence their name). Calls may be loud displaying calls or quieter contact calls." + }, + { + "self_ref": "#/texts/251", + "parent": { + "$ref": "#/texts/249" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "A common urban legend claims that duck quacks do not echo; however, this has been proven to be false. This myth was first debunked by the Acoustics Research Centre at the University of Salford in 2003 as part of the British Association's Festival of Science.[31] It was also debunked in one of the earlier episodes of the popular Discovery Channel television show MythBusters.[32]", + "text": "A common urban legend claims that duck quacks do not echo; however, this has been proven to be false. This myth was first debunked by the Acoustics Research Centre at the University of Salford in 2003 as part of the British Association's Festival of Science.[31] It was also debunked in one of the earlier episodes of the popular Discovery Channel television show MythBusters.[32]" + }, + { + "self_ref": "#/texts/252", + "parent": { + "$ref": "#/texts/236" + }, + "children": [ + { + "$ref": "#/pictures/14" + }, + { + "$ref": "#/texts/254" + }, + { + "$ref": "#/texts/255" + } + ], + "content_layer": "body", + "label": "section_header", + "prov": [], + "orig": "Predators", + "text": "Predators", + "level": 3 + }, + { + "self_ref": "#/texts/253", + "parent": { + "$ref": "#/body" + }, + "children": [], + "content_layer": "body", + "label": "caption", + "prov": [], + "orig": "Ringed teal", + "text": "Ringed teal" + }, + { + "self_ref": "#/texts/254", + "parent": { + "$ref": "#/texts/252" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Ducks have many predators. Ducklings are particularly vulnerable, since their inability to fly makes them easy prey not only for predatory birds but also for large fish like pike, crocodilians, predatory testudines such as the alligator snapping turtle, and other aquatic hunters, including fish-eating birds such as herons. Ducks' nests are raided by land-based predators, and brooding females may be caught unaware on the nest by mammals, such as foxes, or large birds, such as hawks or owls.", + "text": "Ducks have many predators. Ducklings are particularly vulnerable, since their inability to fly makes them easy prey not only for predatory birds but also for large fish like pike, crocodilians, predatory testudines such as the alligator snapping turtle, and other aquatic hunters, including fish-eating birds such as herons. Ducks' nests are raided by land-based predators, and brooding females may be caught unaware on the nest by mammals, such as foxes, or large birds, such as hawks or owls." + }, + { + "self_ref": "#/texts/255", + "parent": { + "$ref": "#/texts/252" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Adult ducks are fast fliers, but may be caught on the water by large aquatic predators including big fish such as the North American muskie and the European pike. In flight, ducks are safe from all but a few predators such as humans and the peregrine falcon, which uses its speed and strength to catch ducks.", + "text": "Adult ducks are fast fliers, but may be caught on the water by large aquatic predators including big fish such as the North American muskie and the European pike. In flight, ducks are safe from all but a few predators such as humans and the peregrine falcon, which uses its speed and strength to catch ducks." + }, + { + "self_ref": "#/texts/256", + "parent": { + "$ref": "#/texts/43" + }, + "children": [ + { + "$ref": "#/texts/257" + }, + { + "$ref": "#/texts/260" + }, + { + "$ref": "#/texts/263" + }, + { + "$ref": "#/texts/266" + } + ], + "content_layer": "body", + "label": "section_header", + "prov": [], + "orig": "Relationship with humans", + "text": "Relationship with humans", + "level": 2 + }, + { + "self_ref": "#/texts/257", + "parent": { + "$ref": "#/texts/256" + }, + "children": [ + { + "$ref": "#/texts/258" + }, + { + "$ref": "#/texts/259" + } + ], + "content_layer": "body", + "label": "section_header", + "prov": [], + "orig": "Hunting", + "text": "Hunting", + "level": 3 + }, + { + "self_ref": "#/texts/258", + "parent": { + "$ref": "#/texts/257" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Humans have hunted ducks since prehistoric times. Excavations of middens in California dating to 7800 \u2013 6400 BP have turned up bones of ducks, including at least one now-extinct flightless species.[33] Ducks were captured in \"significant numbers\" by Holocene inhabitants of the lower Ohio River valley, suggesting they took advantage of the seasonal bounty provided by migrating waterfowl.[34] Neolithic hunters in locations as far apart as the Caribbean,[35] Scandinavia,[36] Egypt,[37] Switzerland,[38] and China relied on ducks as a source of protein for some or all of the year.[39] Archeological evidence shows that M\u0101ori people in New Zealand hunted the flightless Finsch's duck, possibly to extinction, though rat predation may also have contributed to its fate.[40] A similar end awaited the Chatham duck, a species with reduced flying capabilities which went extinct shortly after its island was colonised by Polynesian settlers.[41] It is probable that duck eggs were gathered by Neolithic hunter-gathers as well, though hard evidence of this is uncommon.[35][42]", + "text": "Humans have hunted ducks since prehistoric times. Excavations of middens in California dating to 7800 \u2013 6400 BP have turned up bones of ducks, including at least one now-extinct flightless species.[33] Ducks were captured in \"significant numbers\" by Holocene inhabitants of the lower Ohio River valley, suggesting they took advantage of the seasonal bounty provided by migrating waterfowl.[34] Neolithic hunters in locations as far apart as the Caribbean,[35] Scandinavia,[36] Egypt,[37] Switzerland,[38] and China relied on ducks as a source of protein for some or all of the year.[39] Archeological evidence shows that M\u0101ori people in New Zealand hunted the flightless Finsch's duck, possibly to extinction, though rat predation may also have contributed to its fate.[40] A similar end awaited the Chatham duck, a species with reduced flying capabilities which went extinct shortly after its island was colonised by Polynesian settlers.[41] It is probable that duck eggs were gathered by Neolithic hunter-gathers as well, though hard evidence of this is uncommon.[35][42]" + }, + { + "self_ref": "#/texts/259", + "parent": { + "$ref": "#/texts/257" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "In many areas, wild ducks (including ducks farmed and released into the wild) are hunted for food or sport,[43] by shooting, or by being trapped using duck decoys. Because an idle floating duck or a duck squatting on land cannot react to fly or move quickly, \"a sitting duck\" has come to mean \"an easy target\". These ducks may be contaminated by pollutants such as PCBs.[44]", + "text": "In many areas, wild ducks (including ducks farmed and released into the wild) are hunted for food or sport,[43] by shooting, or by being trapped using duck decoys. Because an idle floating duck or a duck squatting on land cannot react to fly or move quickly, \"a sitting duck\" has come to mean \"an easy target\". These ducks may be contaminated by pollutants such as PCBs.[44]" + }, + { + "self_ref": "#/texts/260", + "parent": { + "$ref": "#/texts/256" + }, + "children": [ + { + "$ref": "#/pictures/15" + }, + { + "$ref": "#/texts/262" + } + ], + "content_layer": "body", + "label": "section_header", + "prov": [], + "orig": "Domestication", + "text": "Domestication", + "level": 3 + }, + { + "self_ref": "#/texts/261", + "parent": { + "$ref": "#/body" + }, + "children": [], + "content_layer": "body", + "label": "caption", + "prov": [], + "orig": "Indian Runner ducks, a common breed of domestic ducks", + "text": "Indian Runner ducks, a common breed of domestic ducks" + }, + { + "self_ref": "#/texts/262", + "parent": { + "$ref": "#/texts/260" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Ducks have many economic uses, being farmed for their meat, eggs, and feathers (particularly their down). Approximately 3 billion ducks are slaughtered each year for meat worldwide.[45] They are also kept and bred by aviculturists and often displayed in zoos. Almost all the varieties of domestic ducks are descended from the mallard (Anas platyrhynchos), apart from the Muscovy duck (Cairina moschata).[46][47] The Call duck is another example of a domestic duck breed. Its name comes from its original use established by hunters, as a decoy to attract wild mallards from the sky, into traps set for them on the ground. The call duck is the world's smallest domestic duck breed, as it weighs less than 1\u00a0kg (2.2\u00a0lb).[48]", + "text": "Ducks have many economic uses, being farmed for their meat, eggs, and feathers (particularly their down). Approximately 3 billion ducks are slaughtered each year for meat worldwide.[45] They are also kept and bred by aviculturists and often displayed in zoos. Almost all the varieties of domestic ducks are descended from the mallard (Anas platyrhynchos), apart from the Muscovy duck (Cairina moschata).[46][47] The Call duck is another example of a domestic duck breed. Its name comes from its original use established by hunters, as a decoy to attract wild mallards from the sky, into traps set for them on the ground. The call duck is the world's smallest domestic duck breed, as it weighs less than 1\u00a0kg (2.2\u00a0lb).[48]" + }, + { + "self_ref": "#/texts/263", + "parent": { + "$ref": "#/texts/256" }, "children": [ { "$ref": "#/pictures/16" }, { - "$ref": "#/texts/251" + "$ref": "#/texts/265" } ], "content_layer": "body", @@ -5310,7 +5520,7 @@ "level": 3 }, { - "self_ref": "#/texts/250", + "self_ref": "#/texts/264", "parent": { "$ref": "#/body" }, @@ -5322,9 +5532,9 @@ "text": "Three black-colored ducks in the coat of arms of Maaninka[49]" }, { - "self_ref": "#/texts/251", + "self_ref": "#/texts/265", "parent": { - "$ref": "#/texts/249" + "$ref": "#/texts/263" }, "children": [], "content_layer": "body", @@ -5334,16 +5544,16 @@ "text": "Ducks appear on several coats of arms, including the coat of arms of Lub\u0101na (Latvia)[50] and the coat of arms of F\u00f6gl\u00f6 (\u00c5land).[51]" }, { - "self_ref": "#/texts/252", + "self_ref": "#/texts/266", "parent": { - "$ref": "#/texts/242" + "$ref": "#/texts/256" }, "children": [ { - "$ref": "#/texts/253" + "$ref": "#/texts/267" }, { - "$ref": "#/texts/254" + "$ref": "#/texts/268" } ], "content_layer": "body", @@ -5354,9 +5564,9 @@ "level": 3 }, { - "self_ref": "#/texts/253", + "self_ref": "#/texts/267", "parent": { - "$ref": "#/texts/252" + "$ref": "#/texts/266" }, "children": [], "content_layer": "body", @@ -5366,9 +5576,9 @@ "text": "In 2002, psychologist Richard Wiseman and colleagues at the University of Hertfordshire, UK, finished a year-long LaughLab experiment, concluding that of all animals, ducks attract the most humor and silliness; he said, \"If you're going to tell a joke involving an animal, make it a duck.\"[52] The word \"duck\" may have become an inherently funny word in many languages, possibly because ducks are seen as silly in their looks or behavior. Of the many ducks in fiction, many are cartoon characters, such as Walt Disney's Donald Duck, and Warner Bros.' Daffy Duck. Howard the Duck started as a comic book character in 1973[53][54] and was made into a movie in 1986." }, { - "self_ref": "#/texts/254", + "self_ref": "#/texts/268", "parent": { - "$ref": "#/texts/252" + "$ref": "#/texts/266" }, "children": [], "content_layer": "body", @@ -5378,9 +5588,9 @@ "text": "The 1992 Disney film The Mighty Ducks, starring Emilio Estevez, chose the duck as the mascot for the fictional youth hockey team who are protagonists of the movie, based on the duck being described as a fierce fighter. This led to the duck becoming the nickname and mascot for the eventual National Hockey League professional team of the Anaheim Ducks, who were founded with the name the Mighty Ducks of Anaheim.[citation needed] The duck is also the nickname of the University of Oregon sports teams as well as the Long Island Ducks minor league baseball team.[55]" }, { - "self_ref": "#/texts/255", + "self_ref": "#/texts/269", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [ { @@ -5398,7 +5608,7 @@ "level": 2 }, { - "self_ref": "#/texts/256", + "self_ref": "#/texts/270", "parent": { "$ref": "#/groups/37" }, @@ -5412,7 +5622,7 @@ "marker": "-" }, { - "self_ref": "#/texts/257", + "self_ref": "#/texts/271", "parent": { "$ref": "#/groups/38" }, @@ -5426,7 +5636,7 @@ "marker": "-" }, { - "self_ref": "#/texts/258", + "self_ref": "#/texts/272", "parent": { "$ref": "#/groups/38" }, @@ -5440,7 +5650,7 @@ "marker": "-" }, { - "self_ref": "#/texts/259", + "self_ref": "#/texts/273", "parent": { "$ref": "#/groups/38" }, @@ -5454,7 +5664,7 @@ "marker": "-" }, { - "self_ref": "#/texts/260", + "self_ref": "#/texts/274", "parent": { "$ref": "#/groups/38" }, @@ -5468,7 +5678,7 @@ "marker": "-" }, { - "self_ref": "#/texts/261", + "self_ref": "#/texts/275", "parent": { "$ref": "#/groups/38" }, @@ -5482,7 +5692,7 @@ "marker": "-" }, { - "self_ref": "#/texts/262", + "self_ref": "#/texts/276", "parent": { "$ref": "#/groups/38" }, @@ -5496,16 +5706,16 @@ "marker": "-" }, { - "self_ref": "#/texts/263", + "self_ref": "#/texts/277", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [ { - "$ref": "#/texts/264" + "$ref": "#/texts/278" }, { - "$ref": "#/texts/320" + "$ref": "#/texts/334" } ], "content_layer": "body", @@ -5516,9 +5726,9 @@ "level": 2 }, { - "self_ref": "#/texts/264", + "self_ref": "#/texts/278", "parent": { - "$ref": "#/texts/263" + "$ref": "#/texts/277" }, "children": [ { @@ -5533,7 +5743,7 @@ "level": 3 }, { - "self_ref": "#/texts/265", + "self_ref": "#/texts/279", "parent": { "$ref": "#/groups/39" }, @@ -5547,7 +5757,7 @@ "marker": "1." }, { - "self_ref": "#/texts/266", + "self_ref": "#/texts/280", "parent": { "$ref": "#/groups/39" }, @@ -5561,7 +5771,7 @@ "marker": "2." }, { - "self_ref": "#/texts/267", + "self_ref": "#/texts/281", "parent": { "$ref": "#/groups/39" }, @@ -5575,7 +5785,7 @@ "marker": "3." }, { - "self_ref": "#/texts/268", + "self_ref": "#/texts/282", "parent": { "$ref": "#/groups/39" }, @@ -5589,7 +5799,7 @@ "marker": "4." }, { - "self_ref": "#/texts/269", + "self_ref": "#/texts/283", "parent": { "$ref": "#/groups/39" }, @@ -5603,7 +5813,7 @@ "marker": "5." }, { - "self_ref": "#/texts/270", + "self_ref": "#/texts/284", "parent": { "$ref": "#/groups/39" }, @@ -5617,7 +5827,7 @@ "marker": "6." }, { - "self_ref": "#/texts/271", + "self_ref": "#/texts/285", "parent": { "$ref": "#/groups/39" }, @@ -5631,7 +5841,7 @@ "marker": "7." }, { - "self_ref": "#/texts/272", + "self_ref": "#/texts/286", "parent": { "$ref": "#/groups/39" }, @@ -5645,7 +5855,7 @@ "marker": "8." }, { - "self_ref": "#/texts/273", + "self_ref": "#/texts/287", "parent": { "$ref": "#/groups/39" }, @@ -5659,7 +5869,7 @@ "marker": "9." }, { - "self_ref": "#/texts/274", + "self_ref": "#/texts/288", "parent": { "$ref": "#/groups/39" }, @@ -5673,7 +5883,7 @@ "marker": "10." }, { - "self_ref": "#/texts/275", + "self_ref": "#/texts/289", "parent": { "$ref": "#/groups/39" }, @@ -5687,7 +5897,7 @@ "marker": "11." }, { - "self_ref": "#/texts/276", + "self_ref": "#/texts/290", "parent": { "$ref": "#/groups/39" }, @@ -5701,7 +5911,7 @@ "marker": "12." }, { - "self_ref": "#/texts/277", + "self_ref": "#/texts/291", "parent": { "$ref": "#/groups/39" }, @@ -5715,7 +5925,7 @@ "marker": "13." }, { - "self_ref": "#/texts/278", + "self_ref": "#/texts/292", "parent": { "$ref": "#/groups/39" }, @@ -5729,7 +5939,7 @@ "marker": "14." }, { - "self_ref": "#/texts/279", + "self_ref": "#/texts/293", "parent": { "$ref": "#/groups/39" }, @@ -5743,7 +5953,7 @@ "marker": "15." }, { - "self_ref": "#/texts/280", + "self_ref": "#/texts/294", "parent": { "$ref": "#/groups/39" }, @@ -5757,7 +5967,7 @@ "marker": "16." }, { - "self_ref": "#/texts/281", + "self_ref": "#/texts/295", "parent": { "$ref": "#/groups/39" }, @@ -5771,7 +5981,7 @@ "marker": "17." }, { - "self_ref": "#/texts/282", + "self_ref": "#/texts/296", "parent": { "$ref": "#/groups/39" }, @@ -5785,7 +5995,7 @@ "marker": "18." }, { - "self_ref": "#/texts/283", + "self_ref": "#/texts/297", "parent": { "$ref": "#/groups/39" }, @@ -5799,7 +6009,7 @@ "marker": "19." }, { - "self_ref": "#/texts/284", + "self_ref": "#/texts/298", "parent": { "$ref": "#/groups/39" }, @@ -5813,7 +6023,7 @@ "marker": "20." }, { - "self_ref": "#/texts/285", + "self_ref": "#/texts/299", "parent": { "$ref": "#/groups/39" }, @@ -5827,7 +6037,7 @@ "marker": "21." }, { - "self_ref": "#/texts/286", + "self_ref": "#/texts/300", "parent": { "$ref": "#/groups/39" }, @@ -5841,7 +6051,7 @@ "marker": "22." }, { - "self_ref": "#/texts/287", + "self_ref": "#/texts/301", "parent": { "$ref": "#/groups/39" }, @@ -5855,7 +6065,7 @@ "marker": "23." }, { - "self_ref": "#/texts/288", + "self_ref": "#/texts/302", "parent": { "$ref": "#/groups/39" }, @@ -5869,7 +6079,7 @@ "marker": "24." }, { - "self_ref": "#/texts/289", + "self_ref": "#/texts/303", "parent": { "$ref": "#/groups/39" }, @@ -5883,7 +6093,7 @@ "marker": "25." }, { - "self_ref": "#/texts/290", + "self_ref": "#/texts/304", "parent": { "$ref": "#/groups/39" }, @@ -5897,7 +6107,7 @@ "marker": "26." }, { - "self_ref": "#/texts/291", + "self_ref": "#/texts/305", "parent": { "$ref": "#/groups/39" }, @@ -5911,7 +6121,7 @@ "marker": "27." }, { - "self_ref": "#/texts/292", + "self_ref": "#/texts/306", "parent": { "$ref": "#/groups/39" }, @@ -5925,7 +6135,7 @@ "marker": "28." }, { - "self_ref": "#/texts/293", + "self_ref": "#/texts/307", "parent": { "$ref": "#/groups/39" }, @@ -5939,7 +6149,7 @@ "marker": "29." }, { - "self_ref": "#/texts/294", + "self_ref": "#/texts/308", "parent": { "$ref": "#/groups/39" }, @@ -5953,7 +6163,7 @@ "marker": "30." }, { - "self_ref": "#/texts/295", + "self_ref": "#/texts/309", "parent": { "$ref": "#/groups/39" }, @@ -5967,7 +6177,7 @@ "marker": "31." }, { - "self_ref": "#/texts/296", + "self_ref": "#/texts/310", "parent": { "$ref": "#/groups/39" }, @@ -5981,7 +6191,7 @@ "marker": "32." }, { - "self_ref": "#/texts/297", + "self_ref": "#/texts/311", "parent": { "$ref": "#/groups/39" }, @@ -5995,7 +6205,7 @@ "marker": "33." }, { - "self_ref": "#/texts/298", + "self_ref": "#/texts/312", "parent": { "$ref": "#/groups/39" }, @@ -6009,7 +6219,7 @@ "marker": "34." }, { - "self_ref": "#/texts/299", + "self_ref": "#/texts/313", "parent": { "$ref": "#/groups/39" }, @@ -6023,7 +6233,7 @@ "marker": "35." }, { - "self_ref": "#/texts/300", + "self_ref": "#/texts/314", "parent": { "$ref": "#/groups/39" }, @@ -6037,7 +6247,7 @@ "marker": "36." }, { - "self_ref": "#/texts/301", + "self_ref": "#/texts/315", "parent": { "$ref": "#/groups/39" }, @@ -6051,7 +6261,7 @@ "marker": "37." }, { - "self_ref": "#/texts/302", + "self_ref": "#/texts/316", "parent": { "$ref": "#/groups/39" }, @@ -6065,7 +6275,7 @@ "marker": "38." }, { - "self_ref": "#/texts/303", + "self_ref": "#/texts/317", "parent": { "$ref": "#/groups/39" }, @@ -6079,7 +6289,7 @@ "marker": "39." }, { - "self_ref": "#/texts/304", + "self_ref": "#/texts/318", "parent": { "$ref": "#/groups/39" }, @@ -6093,7 +6303,7 @@ "marker": "40." }, { - "self_ref": "#/texts/305", + "self_ref": "#/texts/319", "parent": { "$ref": "#/groups/39" }, @@ -6107,7 +6317,7 @@ "marker": "41." }, { - "self_ref": "#/texts/306", + "self_ref": "#/texts/320", "parent": { "$ref": "#/groups/39" }, @@ -6121,7 +6331,7 @@ "marker": "42." }, { - "self_ref": "#/texts/307", + "self_ref": "#/texts/321", "parent": { "$ref": "#/groups/39" }, @@ -6135,7 +6345,7 @@ "marker": "43." }, { - "self_ref": "#/texts/308", + "self_ref": "#/texts/322", "parent": { "$ref": "#/groups/39" }, @@ -6149,7 +6359,7 @@ "marker": "44." }, { - "self_ref": "#/texts/309", + "self_ref": "#/texts/323", "parent": { "$ref": "#/groups/39" }, @@ -6163,7 +6373,7 @@ "marker": "45." }, { - "self_ref": "#/texts/310", + "self_ref": "#/texts/324", "parent": { "$ref": "#/groups/39" }, @@ -6177,7 +6387,7 @@ "marker": "46." }, { - "self_ref": "#/texts/311", + "self_ref": "#/texts/325", "parent": { "$ref": "#/groups/39" }, @@ -6191,7 +6401,7 @@ "marker": "47." }, { - "self_ref": "#/texts/312", + "self_ref": "#/texts/326", "parent": { "$ref": "#/groups/39" }, @@ -6205,7 +6415,7 @@ "marker": "48." }, { - "self_ref": "#/texts/313", + "self_ref": "#/texts/327", "parent": { "$ref": "#/groups/39" }, @@ -6219,7 +6429,7 @@ "marker": "49." }, { - "self_ref": "#/texts/314", + "self_ref": "#/texts/328", "parent": { "$ref": "#/groups/39" }, @@ -6233,7 +6443,7 @@ "marker": "50." }, { - "self_ref": "#/texts/315", + "self_ref": "#/texts/329", "parent": { "$ref": "#/groups/39" }, @@ -6247,7 +6457,7 @@ "marker": "51." }, { - "self_ref": "#/texts/316", + "self_ref": "#/texts/330", "parent": { "$ref": "#/groups/39" }, @@ -6261,7 +6471,7 @@ "marker": "52." }, { - "self_ref": "#/texts/317", + "self_ref": "#/texts/331", "parent": { "$ref": "#/groups/39" }, @@ -6275,7 +6485,7 @@ "marker": "53." }, { - "self_ref": "#/texts/318", + "self_ref": "#/texts/332", "parent": { "$ref": "#/groups/39" }, @@ -6289,7 +6499,7 @@ "marker": "54." }, { - "self_ref": "#/texts/319", + "self_ref": "#/texts/333", "parent": { "$ref": "#/groups/39" }, @@ -6303,9 +6513,9 @@ "marker": "55." }, { - "self_ref": "#/texts/320", + "self_ref": "#/texts/334", "parent": { - "$ref": "#/texts/263" + "$ref": "#/texts/277" }, "children": [ { @@ -6320,7 +6530,7 @@ "level": 3 }, { - "self_ref": "#/texts/321", + "self_ref": "#/texts/335", "parent": { "$ref": "#/groups/40" }, @@ -6334,7 +6544,7 @@ "marker": "-" }, { - "self_ref": "#/texts/322", + "self_ref": "#/texts/336", "parent": { "$ref": "#/groups/40" }, @@ -6348,7 +6558,7 @@ "marker": "-" }, { - "self_ref": "#/texts/323", + "self_ref": "#/texts/337", "parent": { "$ref": "#/groups/40" }, @@ -6362,7 +6572,7 @@ "marker": "-" }, { - "self_ref": "#/texts/324", + "self_ref": "#/texts/338", "parent": { "$ref": "#/groups/40" }, @@ -6376,7 +6586,7 @@ "marker": "-" }, { - "self_ref": "#/texts/325", + "self_ref": "#/texts/339", "parent": { "$ref": "#/groups/40" }, @@ -6390,7 +6600,7 @@ "marker": "-" }, { - "self_ref": "#/texts/326", + "self_ref": "#/texts/340", "parent": { "$ref": "#/groups/40" }, @@ -6404,7 +6614,7 @@ "marker": "-" }, { - "self_ref": "#/texts/327", + "self_ref": "#/texts/341", "parent": { "$ref": "#/groups/40" }, @@ -6418,7 +6628,7 @@ "marker": "-" }, { - "self_ref": "#/texts/328", + "self_ref": "#/texts/342", "parent": { "$ref": "#/groups/40" }, @@ -6432,7 +6642,7 @@ "marker": "-" }, { - "self_ref": "#/texts/329", + "self_ref": "#/texts/343", "parent": { "$ref": "#/groups/40" }, @@ -6446,7 +6656,7 @@ "marker": "-" }, { - "self_ref": "#/texts/330", + "self_ref": "#/texts/344", "parent": { "$ref": "#/groups/40" }, @@ -6460,7 +6670,7 @@ "marker": "-" }, { - "self_ref": "#/texts/331", + "self_ref": "#/texts/345", "parent": { "$ref": "#/groups/40" }, @@ -6474,7 +6684,7 @@ "marker": "-" }, { - "self_ref": "#/texts/332", + "self_ref": "#/texts/346", "parent": { "$ref": "#/groups/40" }, @@ -6488,7 +6698,7 @@ "marker": "-" }, { - "self_ref": "#/texts/333", + "self_ref": "#/texts/347", "parent": { "$ref": "#/groups/40" }, @@ -6502,7 +6712,7 @@ "marker": "-" }, { - "self_ref": "#/texts/334", + "self_ref": "#/texts/348", "parent": { "$ref": "#/groups/40" }, @@ -6516,7 +6726,7 @@ "marker": "-" }, { - "self_ref": "#/texts/335", + "self_ref": "#/texts/349", "parent": { "$ref": "#/groups/40" }, @@ -6530,7 +6740,7 @@ "marker": "-" }, { - "self_ref": "#/texts/336", + "self_ref": "#/texts/350", "parent": { "$ref": "#/groups/40" }, @@ -6544,7 +6754,7 @@ "marker": "-" }, { - "self_ref": "#/texts/337", + "self_ref": "#/texts/351", "parent": { "$ref": "#/groups/40" }, @@ -6558,7 +6768,7 @@ "marker": "-" }, { - "self_ref": "#/texts/338", + "self_ref": "#/texts/352", "parent": { "$ref": "#/groups/40" }, @@ -6572,7 +6782,7 @@ "marker": "-" }, { - "self_ref": "#/texts/339", + "self_ref": "#/texts/353", "parent": { "$ref": "#/groups/40" }, @@ -6586,7 +6796,7 @@ "marker": "-" }, { - "self_ref": "#/texts/340", + "self_ref": "#/texts/354", "parent": { "$ref": "#/groups/40" }, @@ -6600,9 +6810,9 @@ "marker": "-" }, { - "self_ref": "#/texts/341", + "self_ref": "#/texts/355", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [ { @@ -6617,9 +6827,18 @@ { "$ref": "#/pictures/17" }, + { + "$ref": "#/texts/365" + }, + { + "$ref": "#/texts/366" + }, { "$ref": "#/groups/43" }, + { + "$ref": "#/texts/370" + }, { "$ref": "#/groups/44" }, @@ -6644,7 +6863,7 @@ "level": 2 }, { - "self_ref": "#/texts/342", + "self_ref": "#/texts/356", "parent": { "$ref": "#/groups/41" }, @@ -6658,7 +6877,7 @@ "marker": "-" }, { - "self_ref": "#/texts/343", + "self_ref": "#/texts/357", "parent": { "$ref": "#/groups/41" }, @@ -6672,7 +6891,7 @@ "marker": "-" }, { - "self_ref": "#/texts/344", + "self_ref": "#/texts/358", "parent": { "$ref": "#/groups/41" }, @@ -6686,7 +6905,7 @@ "marker": "-" }, { - "self_ref": "#/texts/345", + "self_ref": "#/texts/359", "parent": { "$ref": "#/groups/41" }, @@ -6700,7 +6919,7 @@ "marker": "-" }, { - "self_ref": "#/texts/346", + "self_ref": "#/texts/360", "parent": { "$ref": "#/groups/41" }, @@ -6714,7 +6933,7 @@ "marker": "-" }, { - "self_ref": "#/texts/347", + "self_ref": "#/texts/361", "parent": { "$ref": "#/groups/41" }, @@ -6728,7 +6947,7 @@ "marker": "-" }, { - "self_ref": "#/texts/348", + "self_ref": "#/texts/362", "parent": { "$ref": "#/groups/42" }, @@ -6742,7 +6961,7 @@ "marker": "-" }, { - "self_ref": "#/texts/349", + "self_ref": "#/texts/363", "parent": { "$ref": "#/groups/42" }, @@ -6756,7 +6975,7 @@ "marker": "-" }, { - "self_ref": "#/texts/350", + "self_ref": "#/texts/364", "parent": { "$ref": "#/groups/42" }, @@ -6770,7 +6989,31 @@ "marker": "-" }, { - "self_ref": "#/texts/351", + "self_ref": "#/texts/365", + "parent": { + "$ref": "#/texts/355" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Retrieved from \"\"", + "text": "Retrieved from \"\"" + }, + { + "self_ref": "#/texts/366", + "parent": { + "$ref": "#/texts/355" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": ":", + "text": ":" + }, + { + "self_ref": "#/texts/367", "parent": { "$ref": "#/groups/43" }, @@ -6784,7 +7027,7 @@ "marker": "-" }, { - "self_ref": "#/texts/352", + "self_ref": "#/texts/368", "parent": { "$ref": "#/groups/43" }, @@ -6798,7 +7041,7 @@ "marker": "-" }, { - "self_ref": "#/texts/353", + "self_ref": "#/texts/369", "parent": { "$ref": "#/groups/43" }, @@ -6812,7 +7055,19 @@ "marker": "-" }, { - "self_ref": "#/texts/354", + "self_ref": "#/texts/370", + "parent": { + "$ref": "#/texts/355" + }, + "children": [], + "content_layer": "body", + "label": "paragraph", + "prov": [], + "orig": "Hidden categories:", + "text": "Hidden categories:" + }, + { + "self_ref": "#/texts/371", "parent": { "$ref": "#/groups/44" }, @@ -6826,7 +7081,7 @@ "marker": "-" }, { - "self_ref": "#/texts/355", + "self_ref": "#/texts/372", "parent": { "$ref": "#/groups/44" }, @@ -6840,7 +7095,7 @@ "marker": "-" }, { - "self_ref": "#/texts/356", + "self_ref": "#/texts/373", "parent": { "$ref": "#/groups/44" }, @@ -6854,7 +7109,7 @@ "marker": "-" }, { - "self_ref": "#/texts/357", + "self_ref": "#/texts/374", "parent": { "$ref": "#/groups/44" }, @@ -6868,7 +7123,7 @@ "marker": "-" }, { - "self_ref": "#/texts/358", + "self_ref": "#/texts/375", "parent": { "$ref": "#/groups/44" }, @@ -6882,7 +7137,7 @@ "marker": "-" }, { - "self_ref": "#/texts/359", + "self_ref": "#/texts/376", "parent": { "$ref": "#/groups/44" }, @@ -6896,7 +7151,7 @@ "marker": "-" }, { - "self_ref": "#/texts/360", + "self_ref": "#/texts/377", "parent": { "$ref": "#/groups/44" }, @@ -6910,7 +7165,7 @@ "marker": "-" }, { - "self_ref": "#/texts/361", + "self_ref": "#/texts/378", "parent": { "$ref": "#/groups/44" }, @@ -6924,7 +7179,7 @@ "marker": "-" }, { - "self_ref": "#/texts/362", + "self_ref": "#/texts/379", "parent": { "$ref": "#/groups/44" }, @@ -6938,7 +7193,7 @@ "marker": "-" }, { - "self_ref": "#/texts/363", + "self_ref": "#/texts/380", "parent": { "$ref": "#/groups/44" }, @@ -6952,7 +7207,7 @@ "marker": "-" }, { - "self_ref": "#/texts/364", + "self_ref": "#/texts/381", "parent": { "$ref": "#/groups/44" }, @@ -6966,7 +7221,7 @@ "marker": "-" }, { - "self_ref": "#/texts/365", + "self_ref": "#/texts/382", "parent": { "$ref": "#/groups/44" }, @@ -6980,7 +7235,7 @@ "marker": "-" }, { - "self_ref": "#/texts/366", + "self_ref": "#/texts/383", "parent": { "$ref": "#/groups/44" }, @@ -6994,7 +7249,7 @@ "marker": "-" }, { - "self_ref": "#/texts/367", + "self_ref": "#/texts/384", "parent": { "$ref": "#/groups/44" }, @@ -7008,7 +7263,7 @@ "marker": "-" }, { - "self_ref": "#/texts/368", + "self_ref": "#/texts/385", "parent": { "$ref": "#/groups/44" }, @@ -7022,7 +7277,7 @@ "marker": "-" }, { - "self_ref": "#/texts/369", + "self_ref": "#/texts/386", "parent": { "$ref": "#/groups/44" }, @@ -7036,7 +7291,7 @@ "marker": "-" }, { - "self_ref": "#/texts/370", + "self_ref": "#/texts/387", "parent": { "$ref": "#/groups/44" }, @@ -7050,7 +7305,7 @@ "marker": "-" }, { - "self_ref": "#/texts/371", + "self_ref": "#/texts/388", "parent": { "$ref": "#/groups/44" }, @@ -7064,7 +7319,7 @@ "marker": "-" }, { - "self_ref": "#/texts/372", + "self_ref": "#/texts/389", "parent": { "$ref": "#/groups/44" }, @@ -7078,7 +7333,7 @@ "marker": "-" }, { - "self_ref": "#/texts/373", + "self_ref": "#/texts/390", "parent": { "$ref": "#/groups/44" }, @@ -7092,7 +7347,7 @@ "marker": "-" }, { - "self_ref": "#/texts/374", + "self_ref": "#/texts/391", "parent": { "$ref": "#/groups/44" }, @@ -7106,7 +7361,7 @@ "marker": "-" }, { - "self_ref": "#/texts/375", + "self_ref": "#/texts/392", "parent": { "$ref": "#/groups/44" }, @@ -7120,7 +7375,7 @@ "marker": "-" }, { - "self_ref": "#/texts/376", + "self_ref": "#/texts/393", "parent": { "$ref": "#/groups/44" }, @@ -7134,7 +7389,7 @@ "marker": "-" }, { - "self_ref": "#/texts/377", + "self_ref": "#/texts/394", "parent": { "$ref": "#/groups/44" }, @@ -7148,7 +7403,7 @@ "marker": "-" }, { - "self_ref": "#/texts/378", + "self_ref": "#/texts/395", "parent": { "$ref": "#/groups/44" }, @@ -7162,7 +7417,7 @@ "marker": "-" }, { - "self_ref": "#/texts/379", + "self_ref": "#/texts/396", "parent": { "$ref": "#/groups/44" }, @@ -7176,7 +7431,7 @@ "marker": "-" }, { - "self_ref": "#/texts/380", + "self_ref": "#/texts/397", "parent": { "$ref": "#/groups/45" }, @@ -7190,7 +7445,7 @@ "marker": "-" }, { - "self_ref": "#/texts/381", + "self_ref": "#/texts/398", "parent": { "$ref": "#/groups/45" }, @@ -7204,7 +7459,7 @@ "marker": "-" }, { - "self_ref": "#/texts/382", + "self_ref": "#/texts/399", "parent": { "$ref": "#/groups/46" }, @@ -7218,7 +7473,7 @@ "marker": "-" }, { - "self_ref": "#/texts/383", + "self_ref": "#/texts/400", "parent": { "$ref": "#/groups/46" }, @@ -7232,7 +7487,7 @@ "marker": "-" }, { - "self_ref": "#/texts/384", + "self_ref": "#/texts/401", "parent": { "$ref": "#/groups/46" }, @@ -7246,7 +7501,7 @@ "marker": "-" }, { - "self_ref": "#/texts/385", + "self_ref": "#/texts/402", "parent": { "$ref": "#/groups/46" }, @@ -7260,7 +7515,7 @@ "marker": "-" }, { - "self_ref": "#/texts/386", + "self_ref": "#/texts/403", "parent": { "$ref": "#/groups/46" }, @@ -7274,7 +7529,7 @@ "marker": "-" }, { - "self_ref": "#/texts/387", + "self_ref": "#/texts/404", "parent": { "$ref": "#/groups/46" }, @@ -7288,7 +7543,7 @@ "marker": "-" }, { - "self_ref": "#/texts/388", + "self_ref": "#/texts/405", "parent": { "$ref": "#/groups/46" }, @@ -7302,7 +7557,7 @@ "marker": "-" }, { - "self_ref": "#/texts/389", + "self_ref": "#/texts/406", "parent": { "$ref": "#/groups/46" }, @@ -7316,7 +7571,7 @@ "marker": "-" }, { - "self_ref": "#/texts/390", + "self_ref": "#/texts/407", "parent": { "$ref": "#/groups/46" }, @@ -7376,7 +7631,7 @@ { "self_ref": "#/pictures/3", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [], "content_layer": "body", @@ -7390,7 +7645,7 @@ { "self_ref": "#/pictures/4", "parent": { - "$ref": "#/texts/200" + "$ref": "#/texts/214" }, "children": [], "content_layer": "body", @@ -7398,7 +7653,7 @@ "prov": [], "captions": [ { - "$ref": "#/texts/202" + "$ref": "#/texts/216" } ], "references": [], @@ -7408,97 +7663,7 @@ { "self_ref": "#/pictures/5", "parent": { - "$ref": "#/texts/200" - }, - "children": [], - "content_layer": "body", - "label": "picture", - "prov": [], - "captions": [ - { - "$ref": "#/texts/206" - } - ], - "references": [], - "footnotes": [], - "annotations": [] - }, - { - "self_ref": "#/pictures/6", - "parent": { - "$ref": "#/texts/200" - }, - "children": [], - "content_layer": "body", - "label": "picture", - "prov": [], - "captions": [ - { - "$ref": "#/texts/207" - } - ], - "references": [], - "footnotes": [], - "annotations": [] - }, - { - "self_ref": "#/pictures/7", - "parent": { - "$ref": "#/texts/208" - }, - "children": [], - "content_layer": "body", - "label": "picture", - "prov": [], - "captions": [ - { - "$ref": "#/texts/210" - } - ], - "references": [], - "footnotes": [], - "annotations": [] - }, - { - "self_ref": "#/pictures/8", - "parent": { - "$ref": "#/texts/213" - }, - "children": [], - "content_layer": "body", - "label": "picture", - "prov": [], - "captions": [ - { - "$ref": "#/texts/214" - } - ], - "references": [], - "footnotes": [], - "annotations": [] - }, - { - "self_ref": "#/pictures/9", - "parent": { - "$ref": "#/texts/217" - }, - "children": [], - "content_layer": "body", - "label": "picture", - "prov": [], - "captions": [ - { - "$ref": "#/texts/218" - } - ], - "references": [], - "footnotes": [], - "annotations": [] - }, - { - "self_ref": "#/pictures/10", - "parent": { - "$ref": "#/texts/217" + "$ref": "#/texts/214" }, "children": [], "content_layer": "body", @@ -7514,9 +7679,27 @@ "annotations": [] }, { - "self_ref": "#/pictures/11", + "self_ref": "#/pictures/6", "parent": { - "$ref": "#/texts/223" + "$ref": "#/texts/214" + }, + "children": [], + "content_layer": "body", + "label": "picture", + "prov": [], + "captions": [ + { + "$ref": "#/texts/221" + } + ], + "references": [], + "footnotes": [], + "annotations": [] + }, + { + "self_ref": "#/pictures/7", + "parent": { + "$ref": "#/texts/222" }, "children": [], "content_layer": "body", @@ -7531,46 +7714,82 @@ "footnotes": [], "annotations": [] }, + { + "self_ref": "#/pictures/8", + "parent": { + "$ref": "#/texts/227" + }, + "children": [], + "content_layer": "body", + "label": "picture", + "prov": [], + "captions": [ + { + "$ref": "#/texts/228" + } + ], + "references": [], + "footnotes": [], + "annotations": [] + }, + { + "self_ref": "#/pictures/9", + "parent": { + "$ref": "#/texts/231" + }, + "children": [], + "content_layer": "body", + "label": "picture", + "prov": [], + "captions": [ + { + "$ref": "#/texts/232" + } + ], + "references": [], + "footnotes": [], + "annotations": [] + }, + { + "self_ref": "#/pictures/10", + "parent": { + "$ref": "#/texts/231" + }, + "children": [], + "content_layer": "body", + "label": "picture", + "prov": [], + "captions": [ + { + "$ref": "#/texts/234" + } + ], + "references": [], + "footnotes": [], + "annotations": [] + }, + { + "self_ref": "#/pictures/11", + "parent": { + "$ref": "#/texts/237" + }, + "children": [], + "content_layer": "body", + "label": "picture", + "prov": [], + "captions": [ + { + "$ref": "#/texts/238" + } + ], + "references": [], + "footnotes": [], + "annotations": [] + }, { "self_ref": "#/pictures/12", "parent": { - "$ref": "#/texts/223" - }, - "children": [], - "content_layer": "body", - "label": "picture", - "prov": [], - "captions": [ - { - "$ref": "#/texts/225" - } - ], - "references": [], - "footnotes": [], - "annotations": [] - }, - { - "self_ref": "#/pictures/13", - "parent": { - "$ref": "#/texts/232" - }, - "children": [], - "content_layer": "body", - "label": "picture", - "prov": [], - "captions": [ - { - "$ref": "#/texts/233" - } - ], - "references": [], - "footnotes": [], - "annotations": [] - }, - { - "self_ref": "#/pictures/14", - "parent": { - "$ref": "#/texts/238" + "$ref": "#/texts/237" }, "children": [], "content_layer": "body", @@ -7586,7 +7805,7 @@ "annotations": [] }, { - "self_ref": "#/pictures/15", + "self_ref": "#/pictures/13", "parent": { "$ref": "#/texts/246" }, @@ -7604,9 +7823,9 @@ "annotations": [] }, { - "self_ref": "#/pictures/16", + "self_ref": "#/pictures/14", "parent": { - "$ref": "#/texts/249" + "$ref": "#/texts/252" }, "children": [], "content_layer": "body", @@ -7614,7 +7833,43 @@ "prov": [], "captions": [ { - "$ref": "#/texts/250" + "$ref": "#/texts/253" + } + ], + "references": [], + "footnotes": [], + "annotations": [] + }, + { + "self_ref": "#/pictures/15", + "parent": { + "$ref": "#/texts/260" + }, + "children": [], + "content_layer": "body", + "label": "picture", + "prov": [], + "captions": [ + { + "$ref": "#/texts/261" + } + ], + "references": [], + "footnotes": [], + "annotations": [] + }, + { + "self_ref": "#/pictures/16", + "parent": { + "$ref": "#/texts/263" + }, + "children": [], + "content_layer": "body", + "label": "picture", + "prov": [], + "captions": [ + { + "$ref": "#/texts/264" } ], "references": [], @@ -7624,7 +7879,7 @@ { "self_ref": "#/pictures/17", "parent": { - "$ref": "#/texts/341" + "$ref": "#/texts/355" }, "children": [], "content_layer": "body", @@ -7640,7 +7895,7 @@ { "self_ref": "#/tables/0", "parent": { - "$ref": "#/texts/39" + "$ref": "#/texts/43" }, "children": [], "content_layer": "body", @@ -8239,7 +8494,7 @@ { "self_ref": "#/tables/1", "parent": { - "$ref": "#/texts/341" + "$ref": "#/texts/355" }, "children": [], "content_layer": "body", diff --git a/tests/data/groundtruth/docling_v2/wiki_duck.html.md b/tests/data/groundtruth/docling_v2/wiki_duck.html.md index bd3f3c3d..26c42e26 100644 --- a/tests/data/groundtruth/docling_v2/wiki_duck.html.md +++ b/tests/data/groundtruth/docling_v2/wiki_duck.html.md @@ -1,3 +1,7 @@ +Main menu + +Navigation + - Main page - Contents - Current events @@ -5,6 +9,8 @@ - About Wikipedia - Contact us +Contribute + - Help - Learn to edit - Community portal @@ -22,6 +28,9 @@ - Log in - Create account - Log in + +Pages for logged out editors + - Contributions - Talk @@ -193,9 +202,17 @@ - Read - View source - View history + +Tools + +Actions + - Read - View source - View history + +General + - What links here - Related changes - Upload file @@ -206,13 +223,29 @@ - Get shortened URL - Download QR code - Wikidata item + +Print/export + - Download as PDF - Printable version + +In other projects + - Wikimedia Commons - Wikiquote +Appearance + +From Wikipedia, the free encyclopedia + +Common name for many species of bird + +This article is about the bird. For duck as a food, see . For other uses, see . + +"Duckling" redirects here. For other uses, see . + | Duck | Duck | |--------------------------------|--------------------------------| | | | @@ -482,10 +515,16 @@ The 1992 Disney film The Mighty Ducks, starring Emilio Estevez, chose the duck a +Retrieved from "" + +: + - Ducks - Game birds - Bird common names +Hidden categories: + - All accuracy disputes - Accuracy disputes from February 2020 - CS1 Finnish-language sources (fi) diff --git a/tests/data/html/example_06.html b/tests/data/html/example_06.html new file mode 100644 index 00000000..efafd278 --- /dev/null +++ b/tests/data/html/example_06.html @@ -0,0 +1,12 @@ + + + Sample HTML File + + +
This is a div with text.
+
This is another div with text.
+

This is a regular paragraph.

+
This is a third div
with a new line.
+

This is a fourth div with a bold paragraph.

+ + From c84b973959a254db22ac9a7dc8810628e4808a2d Mon Sep 17 00:00:00 2001 From: Panos Vagenas <35837085+vagenas@users.noreply.github.com> Date: Tue, 25 Feb 2025 13:07:38 +0100 Subject: [PATCH 02/13] docs: extend chunking docs, add FAQ on token limit (#1053) Signed-off-by: Panos Vagenas --- docs/concepts/chunking.md | 13 +++++++++++++ docs/faq.md | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/docs/concepts/chunking.md b/docs/concepts/chunking.md index 94ae387e..c552f3aa 100644 --- a/docs/concepts/chunking.md +++ b/docs/concepts/chunking.md @@ -1,5 +1,18 @@ ## Introduction +!!! note "Chunking approaches" + + Starting from a `DoclingDocument`, there are in principle two possible chunking + approaches: + + 1. exporting the `DoclingDocument` to Markdown (or similar format) and then + performing user-defined chunking as a post-processing step, or + 2. using native Docling chunkers, i.e. operating directly on the `DoclingDocument` + + This page is about the latter, i.e. using native Docling chunkers. + For an example of using approach (1) check out e.g. + [this recipe](../examples/rag_langchain.ipynb) looking at the Markdown export mode. + A *chunker* is a Docling abstraction that, given a [`DoclingDocument`](./docling_document.md), returns a stream of chunks, each of which captures some part of the document as a string accompanied by respective metadata. diff --git a/docs/faq.md b/docs/faq.md index 9daccae6..5f54d863 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -132,9 +132,45 @@ This is a collection of FAQ collected from the user questions on Token indices sequence length is longer than the specified maximum sequence length for this model (530 > 512). Running this sequence through the model will result in indexing errors + + This is a warning that is emitted by transformers, saying that actually *running this sequence through the model* will result in indexing errors, i.e. the problematic case is only if one indeed passes the particular sequence through the (embedding) model. + + In our case though, this occurs as a "false alarm", since what happens is the following: + + - the chunker invokes the tokenizer on a potentially long sequence (e.g. 530 tokens as mentioned in the warning) in order to count its tokens, i.e. to assess if it is short enough. At this point transformers already emits the warning above! + - whenever the sequence at hand is oversized, the chunker proceeds to split it (but the transformers warning has already been shown nonetheless) + + What is important is the actual token length of the produced chunks. + The snippet below can be used for getting the actual maximum chunk size (for users wanting to confirm that this does not exceed the model limit): + + ```python + max_len = 0 + for i, chunk in enumerate(chunks): + ser_txt = chunker.serialize(chunk=chunk) + ser_tokens = len(tokenizer.tokenize(ser_txt, max_len_length=None)) + if ser_tokens > max_len: + max_len = ser_tokens + print(f"{i}\t{ser_tokens}\t{repr(ser_txt[:100])}...") + print(f"{max_len=}") + ``` + + Source: Issue [docling-core#119](https://github.com/DS4SD/docling-core/issues/119) From e1972257399151503d60b4806976c8b9b6911aa8 Mon Sep 17 00:00:00 2001 From: Michele Dolfi <97102151+dolfim-ibm@users.noreply.github.com> Date: Wed, 26 Feb 2025 08:33:50 +0100 Subject: [PATCH 03/13] fix: vlm using artifacts path (#1057) * fix usage of artifacts path Signed-off-by: Michele Dolfi * add granite vision to the download utils Signed-off-by: Michele Dolfi --------- Signed-off-by: Michele Dolfi --- docling/cli/models.py | 13 ++++++++++++- docling/models/picture_description_vlm_model.py | 4 ++-- docling/utils/model_downloader.py | 17 +++++++++++++++-- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/docling/cli/models.py b/docling/cli/models.py index 3b62ad6b..50038adf 100644 --- a/docling/cli/models.py +++ b/docling/cli/models.py @@ -32,9 +32,19 @@ class _AvailableModels(str, Enum): CODE_FORMULA = "code_formula" PICTURE_CLASSIFIER = "picture_classifier" SMOLVLM = "smolvlm" + GRANITE_VISION = "granite_vision" EASYOCR = "easyocr" +_default_models = [ + _AvailableModels.LAYOUT, + _AvailableModels.TABLEFORMER, + _AvailableModels.CODE_FORMULA, + _AvailableModels.PICTURE_CLASSIFIER, + _AvailableModels.EASYOCR, +] + + @app.command("download") def download( output_dir: Annotated[ @@ -73,7 +83,7 @@ def download( datefmt="[%X]", handlers=[RichHandler(show_level=False, show_time=False, markup=True)], ) - to_download = models or [m for m in _AvailableModels] + to_download = models or _default_models output_dir = download_models( output_dir=output_dir, force=force, @@ -83,6 +93,7 @@ def download( with_code_formula=_AvailableModels.CODE_FORMULA in to_download, with_picture_classifier=_AvailableModels.PICTURE_CLASSIFIER in to_download, with_smolvlm=_AvailableModels.SMOLVLM in to_download, + with_granite_vision=_AvailableModels.GRANITE_VISION in to_download, with_easyocr=_AvailableModels.EASYOCR in to_download, ) diff --git a/docling/models/picture_description_vlm_model.py b/docling/models/picture_description_vlm_model.py index 9fa4826d..69d185b0 100644 --- a/docling/models/picture_description_vlm_model.py +++ b/docling/models/picture_description_vlm_model.py @@ -41,9 +41,9 @@ class PictureDescriptionVlmModel(PictureDescriptionBaseModel): ) # Initialize processor and model - self.processor = AutoProcessor.from_pretrained(self.options.repo_id) + self.processor = AutoProcessor.from_pretrained(artifacts_path) self.model = AutoModelForVision2Seq.from_pretrained( - self.options.repo_id, + artifacts_path, torch_dtype=torch.bfloat16, _attn_implementation=( "flash_attention_2" if self.device.startswith("cuda") else "eager" diff --git a/docling/utils/model_downloader.py b/docling/utils/model_downloader.py index 7d22b77b..694fe042 100644 --- a/docling/utils/model_downloader.py +++ b/docling/utils/model_downloader.py @@ -2,7 +2,10 @@ import logging from pathlib import Path from typing import Optional -from docling.datamodel.pipeline_options import smolvlm_picture_description +from docling.datamodel.pipeline_options import ( + granite_picture_description, + smolvlm_picture_description, +) from docling.datamodel.settings import settings from docling.models.code_formula_model import CodeFormulaModel from docling.models.document_picture_classifier import DocumentPictureClassifier @@ -23,7 +26,8 @@ def download_models( with_tableformer: bool = True, with_code_formula: bool = True, with_picture_classifier: bool = True, - with_smolvlm: bool = True, + with_smolvlm: bool = False, + with_granite_vision: bool = False, with_easyocr: bool = True, ): if output_dir is None: @@ -73,6 +77,15 @@ def download_models( progress=progress, ) + if with_granite_vision: + _log.info(f"Downloading Granite Vision model...") + PictureDescriptionVlmModel.download_models( + repo_id=granite_picture_description.repo_id, + local_dir=output_dir / granite_picture_description.repo_cache_folder, + force=force, + progress=progress, + ) + if with_easyocr: _log.info(f"Downloading easyocr models...") EasyOcrModel.download_models( From ab683e4fb6df4973d2efda04f00c269a2dc95f5b Mon Sep 17 00:00:00 2001 From: Panos Vagenas <35837085+vagenas@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:27:29 +0100 Subject: [PATCH 04/13] feat(cli): add option for downloading all models, refine help messages (#1061) * chore(cli): update download help messages Signed-off-by: Panos Vagenas <35837085+vagenas@users.noreply.github.com> * add `--all` flag to model download CLI Signed-off-by: Panos Vagenas --------- Signed-off-by: Panos Vagenas <35837085+vagenas@users.noreply.github.com> Signed-off-by: Panos Vagenas --- docling/cli/models.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/docling/cli/models.py b/docling/cli/models.py index 50038adf..cc4a43ac 100644 --- a/docling/cli/models.py +++ b/docling/cli/models.py @@ -53,18 +53,27 @@ def download( ..., "-o", "--output-dir", - help="The directory where all the models are downloaded.", + help="The directory where to download the models.", ), ] = (settings.cache_dir / "models"), force: Annotated[ - bool, typer.Option(..., help="If true, the download will be forced") + bool, typer.Option(..., help="If true, the download will be forced.") ] = False, models: Annotated[ Optional[list[_AvailableModels]], typer.Argument( - help=f"Models to download (default behavior: all will be downloaded)", + help=f"Models to download (default behavior: a predefined set of models will be downloaded).", ), ] = None, + all: Annotated[ + bool, + typer.Option( + ..., + "--all", + help="If true, all available models will be downloaded (mutually exclusive with passing specific models).", + show_default=True, + ), + ] = False, quiet: Annotated[ bool, typer.Option( @@ -75,6 +84,10 @@ def download( ), ] = False, ): + if models and all: + raise typer.BadParameter( + "Cannot simultaneously set 'all' parameter and specify models to download." + ) if not quiet: FORMAT = "%(message)s" logging.basicConfig( @@ -83,7 +96,7 @@ def download( datefmt="[%X]", handlers=[RichHandler(show_level=False, show_time=False, markup=True)], ) - to_download = models or _default_models + to_download = models or ([m for m in _AvailableModels] if all else _default_models) output_dir = download_models( output_dir=output_dir, force=force, From 3c9fe76b706b7714b25d49cb09050c42e3b8c849 Mon Sep 17 00:00:00 2001 From: Christoph Auer <60343111+cau-git@users.noreply.github.com> Date: Wed, 26 Feb 2025 14:43:26 +0100 Subject: [PATCH 05/13] feat: [Experimental] Introduce VLM pipeline using HF AutoModelForVision2Seq, featuring SmolDocling model (#1054) * Skeleton for SmolDocling model and VLM Pipeline Signed-off-by: Christoph Auer Signed-off-by: Maksym Lysak * wip smolDocling inference and vlm pipeline Signed-off-by: Maksym Lysak * WIP, first working code for inference of SmolDocling, and vlm pipeline assembly code, example included. Signed-off-by: Maksym Lysak * Fixes to preserve page image and demo export to html Signed-off-by: Maksym Lysak * Enabled figure support in vlm_pipeline Signed-off-by: Maksym Lysak * Fix for table span compute in vlm_pipeline Signed-off-by: Maksym Lysak * Properly propagating image data per page, together with predicted tags in VLM pipeline. This enables correct figure extraction and page numbers in provenances Signed-off-by: Maksym Lysak * Cleaned up logs, added pages to vlm_pipeline, basic timing per page measurement in smol_docling models Signed-off-by: Maksym Lysak * Replaced hardcoded otsl tokens with the ones from docling-core tokens.py enum Signed-off-by: Maksym Lysak * Added tokens/sec measurement, improved example Signed-off-by: Maksym Lysak * Added capability for vlm_pipeline to grab text from preconfigured backend Signed-off-by: Maksym Lysak * Exposed "force_backend_text" as pipeline parameter Signed-off-by: Maksym Lysak * Flipped keep_backend to True for vlm_pipeline assembly to work Signed-off-by: Maksym Lysak * Updated vlm pipeline assembly and smol docling model code to support updated doctags Signed-off-by: Maksym Lysak * Fixing doctags starting tag, that broke elements on first line during assembly Signed-off-by: Maksym Lysak * Introduced SmolDoclingOptions to configure model parameters (such as query and artifacts path) via client code, see example in minimal_smol_docling. Provisioning for other potential vlm all-in-one models. Signed-off-by: Maksym Lysak * Moved artifacts_path for SmolDocling into vlm_options instead of global pipeline option Signed-off-by: Maksym Lysak * New assembly code for latest model revision, updated prompt and parsing of doctags, updated logging Signed-off-by: Maksym Lysak * Updated example of Smol Docling usage Signed-off-by: Maksym Lysak * Added captions for the images for SmolDocling assembly code, improved provenance definition for all elements Signed-off-by: Maksym Lysak * Update minimal smoldocling example Signed-off-by: Christoph Auer * Fix repo id Signed-off-by: Christoph Auer * Cleaned up unnecessary logging Signed-off-by: Maksym Lysak * More elegant solution in removing the input prompt Signed-off-by: Maksym Lysak * removed minimal_smol_docling example from CI checks Signed-off-by: Maksym Lysak * Removed special html code wrapping when exporting to docling document, cleaned up comments Signed-off-by: Maksym Lysak * Addressing PR comments, added enabled property to SmolDocling, and related VLM pipeline option, few other minor things Signed-off-by: Maksym Lysak * Moved keep_backend = True to vlm pipeline Signed-off-by: Maksym Lysak * removed pipeline_options.generate_table_images from vlm_pipeline (deprecated in the pipelines) Signed-off-by: Maksym Lysak * Added example on how to get original predicted doctags in minimal_smol_docling Signed-off-by: Maksym Lysak * removing changes from base_pipeline Signed-off-by: Maksym Lysak * Replaced remaining strings to appropriate enums Signed-off-by: Maksym Lysak * Updated poetry.lock Signed-off-by: Maksym Lysak * re-built poetry.lock Signed-off-by: Maksym Lysak * Generalize and refactor VLM pipeline and models Signed-off-by: Christoph Auer * Rename example Signed-off-by: Christoph Auer * Move imports Signed-off-by: Christoph Auer * Expose control over using flash_attention_2 Signed-off-by: Christoph Auer * Fix VLM example exclusion in CI Signed-off-by: Christoph Auer * Add back device_map and accelerate Signed-off-by: Christoph Auer * Make drawing code resilient against bad bboxes Signed-off-by: Christoph Auer * chore: clean up code and comments Signed-off-by: Christoph Auer * chore: more cleanup Signed-off-by: Christoph Auer * chore: fix leftover .to(device) Signed-off-by: Christoph Auer * fix: add proper table provenance Signed-off-by: Christoph Auer --------- Signed-off-by: Christoph Auer Signed-off-by: Maksym Lysak Co-authored-by: Maksym Lysak --- .github/workflows/checks.yml | 2 +- docling/datamodel/base_models.py | 5 + docling/datamodel/pipeline_options.py | 63 ++- docling/models/hf_vlm_model.py | 180 +++++++ docling/pipeline/vlm_pipeline.py | 534 ++++++++++++++++++++ docling/utils/visualization.py | 5 + docs/examples/minimal_vlm_pipeline.py | 96 ++++ poetry.lock | 673 ++++++++++++++------------ pyproject.toml | 6 +- 9 files changed, 1248 insertions(+), 316 deletions(-) create mode 100644 docling/models/hf_vlm_model.py create mode 100644 docling/pipeline/vlm_pipeline.py create mode 100644 docs/examples/minimal_vlm_pipeline.py diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 89bcfd79..1c322d9a 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -28,7 +28,7 @@ jobs: run: | for file in docs/examples/*.py; do # Skip batch_convert.py - if [[ "$(basename "$file")" =~ ^(batch_convert|minimal|export_multimodal|custom_convert|develop_picture_enrichment|rapidocr_with_custom_models|offline_convert|pictures_description|pictures_description_api).py ]]; then + if [[ "$(basename "$file")" =~ ^(batch_convert|minimal_vlm_pipeline|minimal|export_multimodal|custom_convert|develop_picture_enrichment|rapidocr_with_custom_models|offline_convert|pictures_description|pictures_description_api).py ]]; then echo "Skipping $file" continue fi diff --git a/docling/datamodel/base_models.py b/docling/datamodel/base_models.py index da512aa1..3297c9a5 100644 --- a/docling/datamodel/base_models.py +++ b/docling/datamodel/base_models.py @@ -154,6 +154,10 @@ class LayoutPrediction(BaseModel): clusters: List[Cluster] = [] +class VlmPrediction(BaseModel): + text: str = "" + + class ContainerElement( BasePageElement ): # Used for Form and Key-Value-Regions, only for typing. @@ -197,6 +201,7 @@ class PagePredictions(BaseModel): tablestructure: Optional[TableStructurePrediction] = None figures_classification: Optional[FigureClassificationPrediction] = None equations_prediction: Optional[EquationPrediction] = None + vlm_response: Optional[VlmPrediction] = None PageElement = Union[TextElement, Table, FigureElement, ContainerElement] diff --git a/docling/datamodel/pipeline_options.py b/docling/datamodel/pipeline_options.py index d317e7d9..3a55ecfc 100644 --- a/docling/datamodel/pipeline_options.py +++ b/docling/datamodel/pipeline_options.py @@ -41,6 +41,7 @@ class AcceleratorOptions(BaseSettings): num_threads: int = 4 device: Union[str, AcceleratorDevice] = "auto" + cuda_use_flash_attention2: bool = False @field_validator("device") def validate_device(cls, value): @@ -254,6 +255,45 @@ granite_picture_description = PictureDescriptionVlmOptions( ) +class BaseVlmOptions(BaseModel): + kind: str + prompt: str + + +class ResponseFormat(str, Enum): + DOCTAGS = "doctags" + MARKDOWN = "markdown" + + +class HuggingFaceVlmOptions(BaseVlmOptions): + kind: Literal["hf_model_options"] = "hf_model_options" + + repo_id: str + load_in_8bit: bool = True + llm_int8_threshold: float = 6.0 + quantized: bool = False + + response_format: ResponseFormat + + @property + def repo_cache_folder(self) -> str: + return self.repo_id.replace("/", "--") + + +smoldocling_vlm_conversion_options = HuggingFaceVlmOptions( + repo_id="ds4sd/SmolDocling-256M-preview", + prompt="Convert this page to docling.", + response_format=ResponseFormat.DOCTAGS, +) + +granite_vision_vlm_conversion_options = HuggingFaceVlmOptions( + repo_id="ibm-granite/granite-vision-3.1-2b-preview", + # prompt="OCR the full page to markdown.", + prompt="OCR this image.", + response_format=ResponseFormat.MARKDOWN, +) + + # Define an enum for the backend options class PdfBackend(str, Enum): """Enum of valid PDF backends.""" @@ -285,7 +325,24 @@ class PipelineOptions(BaseModel): enable_remote_services: bool = False -class PdfPipelineOptions(PipelineOptions): +class PaginatedPipelineOptions(PipelineOptions): + images_scale: float = 1.0 + generate_page_images: bool = False + generate_picture_images: bool = False + + +class VlmPipelineOptions(PaginatedPipelineOptions): + artifacts_path: Optional[Union[Path, str]] = None + + generate_page_images: bool = True + force_backend_text: bool = ( + False # (To be used with vlms, or other generative models) + ) + # If True, text from backend will be used instead of generated text + vlm_options: Union[HuggingFaceVlmOptions] = smoldocling_vlm_conversion_options + + +class PdfPipelineOptions(PaginatedPipelineOptions): """Options for the PDF pipeline.""" artifacts_path: Optional[Union[Path, str]] = None @@ -295,6 +352,10 @@ class PdfPipelineOptions(PipelineOptions): do_formula_enrichment: bool = False # True: perform formula OCR, return Latex code do_picture_classification: bool = False # True: classify pictures in documents do_picture_description: bool = False # True: run describe pictures in documents + force_backend_text: bool = ( + False # (To be used with vlms, or other generative models) + ) + # If True, text from backend will be used instead of generated text table_structure_options: TableStructureOptions = TableStructureOptions() ocr_options: Union[ diff --git a/docling/models/hf_vlm_model.py b/docling/models/hf_vlm_model.py new file mode 100644 index 00000000..2acbe290 --- /dev/null +++ b/docling/models/hf_vlm_model.py @@ -0,0 +1,180 @@ +import logging +import time +from pathlib import Path +from typing import Iterable, List, Optional + +from docling.datamodel.base_models import Page, VlmPrediction +from docling.datamodel.document import ConversionResult +from docling.datamodel.pipeline_options import ( + AcceleratorDevice, + AcceleratorOptions, + HuggingFaceVlmOptions, +) +from docling.datamodel.settings import settings +from docling.models.base_model import BasePageModel +from docling.utils.accelerator_utils import decide_device +from docling.utils.profiling import TimeRecorder + +_log = logging.getLogger(__name__) + + +class HuggingFaceVlmModel(BasePageModel): + + def __init__( + self, + enabled: bool, + artifacts_path: Optional[Path], + accelerator_options: AcceleratorOptions, + vlm_options: HuggingFaceVlmOptions, + ): + self.enabled = enabled + + self.vlm_options = vlm_options + + if self.enabled: + import torch + from transformers import ( # type: ignore + AutoModelForVision2Seq, + AutoProcessor, + BitsAndBytesConfig, + ) + + device = decide_device(accelerator_options.device) + self.device = device + + _log.debug("Available device for HuggingFace VLM: {}".format(device)) + + repo_cache_folder = vlm_options.repo_id.replace("/", "--") + + # PARAMETERS: + if artifacts_path is None: + artifacts_path = self.download_models(self.vlm_options.repo_id) + elif (artifacts_path / repo_cache_folder).exists(): + artifacts_path = artifacts_path / repo_cache_folder + + self.param_question = vlm_options.prompt # "Perform Layout Analysis." + self.param_quantization_config = BitsAndBytesConfig( + load_in_8bit=vlm_options.load_in_8bit, # True, + llm_int8_threshold=vlm_options.llm_int8_threshold, # 6.0 + ) + self.param_quantized = vlm_options.quantized # False + + self.processor = AutoProcessor.from_pretrained(artifacts_path) + if not self.param_quantized: + self.vlm_model = AutoModelForVision2Seq.from_pretrained( + artifacts_path, + device_map=device, + torch_dtype=torch.bfloat16, + _attn_implementation=( + "flash_attention_2" + if self.device.startswith("cuda") + and accelerator_options.cuda_use_flash_attention2 + else "eager" + ), + ) # .to(self.device) + + else: + self.vlm_model = AutoModelForVision2Seq.from_pretrained( + artifacts_path, + device_map=device, + torch_dtype="auto", + quantization_config=self.param_quantization_config, + _attn_implementation=( + "flash_attention_2" + if self.device.startswith("cuda") + and accelerator_options.cuda_use_flash_attention2 + else "eager" + ), + ) # .to(self.device) + + @staticmethod + def download_models( + repo_id: str, + local_dir: Optional[Path] = None, + force: bool = False, + progress: bool = False, + ) -> Path: + from huggingface_hub import snapshot_download + from huggingface_hub.utils import disable_progress_bars + + if not progress: + disable_progress_bars() + download_path = snapshot_download( + repo_id=repo_id, + force_download=force, + local_dir=local_dir, + # revision="v0.0.1", + ) + + return Path(download_path) + + def __call__( + self, conv_res: ConversionResult, page_batch: Iterable[Page] + ) -> Iterable[Page]: + for page in page_batch: + assert page._backend is not None + if not page._backend.is_valid(): + yield page + else: + with TimeRecorder(conv_res, "vlm"): + assert page.size is not None + + hi_res_image = page.get_image(scale=2.0) # 144dpi + # hi_res_image = page.get_image(scale=1.0) # 72dpi + + if hi_res_image is not None: + im_width, im_height = hi_res_image.size + + # populate page_tags with predicted doc tags + page_tags = "" + + if hi_res_image: + if hi_res_image.mode != "RGB": + hi_res_image = hi_res_image.convert("RGB") + + messages = [ + { + "role": "user", + "content": [ + { + "type": "text", + "text": "This is a page from a document.", + }, + {"type": "image"}, + {"type": "text", "text": self.param_question}, + ], + } + ] + prompt = self.processor.apply_chat_template( + messages, add_generation_prompt=False + ) + inputs = self.processor( + text=prompt, images=[hi_res_image], return_tensors="pt" + ) + inputs = {k: v.to(self.device) for k, v in inputs.items()} + + start_time = time.time() + # Call model to generate: + generated_ids = self.vlm_model.generate( + **inputs, max_new_tokens=4096, use_cache=True + ) + + generation_time = time.time() - start_time + generated_texts = self.processor.batch_decode( + generated_ids[:, inputs["input_ids"].shape[1] :], + skip_special_tokens=False, + )[0] + + num_tokens = len(generated_ids[0]) + page_tags = generated_texts + + # inference_time = time.time() - start_time + # tokens_per_second = num_tokens / generation_time + # print("") + # print(f"Page Inference Time: {inference_time:.2f} seconds") + # print(f"Total tokens on page: {num_tokens:.2f}") + # print(f"Tokens/sec: {tokens_per_second:.2f}") + # print("") + page.predictions.vlm_response = VlmPrediction(text=page_tags) + + yield page diff --git a/docling/pipeline/vlm_pipeline.py b/docling/pipeline/vlm_pipeline.py new file mode 100644 index 00000000..c6920b65 --- /dev/null +++ b/docling/pipeline/vlm_pipeline.py @@ -0,0 +1,534 @@ +import itertools +import logging +import re +import warnings +from io import BytesIO + +# from io import BytesIO +from pathlib import Path +from typing import Optional + +from docling_core.types import DoclingDocument +from docling_core.types.doc import ( + BoundingBox, + DocItem, + DocItemLabel, + DoclingDocument, + GroupLabel, + ImageRef, + ImageRefMode, + PictureItem, + ProvenanceItem, + Size, + TableCell, + TableData, + TableItem, +) +from docling_core.types.doc.tokens import DocumentToken, TableToken + +from docling.backend.abstract_backend import AbstractDocumentBackend +from docling.backend.md_backend import MarkdownDocumentBackend +from docling.backend.pdf_backend import PdfDocumentBackend +from docling.datamodel.base_models import InputFormat, Page +from docling.datamodel.document import ConversionResult, InputDocument +from docling.datamodel.pipeline_options import ( + PdfPipelineOptions, + ResponseFormat, + VlmPipelineOptions, +) +from docling.datamodel.settings import settings +from docling.models.hf_vlm_model import HuggingFaceVlmModel +from docling.pipeline.base_pipeline import PaginatedPipeline +from docling.utils.profiling import ProfilingScope, TimeRecorder + +_log = logging.getLogger(__name__) + + +class VlmPipeline(PaginatedPipeline): + + def __init__(self, pipeline_options: VlmPipelineOptions): + super().__init__(pipeline_options) + self.keep_backend = True + + warnings.warn( + "The VlmPipeline is currently experimental and may change in upcoming versions without notice.", + category=UserWarning, + stacklevel=2, + ) + + self.pipeline_options: VlmPipelineOptions + + artifacts_path: Optional[Path] = None + if pipeline_options.artifacts_path is not None: + artifacts_path = Path(pipeline_options.artifacts_path).expanduser() + elif settings.artifacts_path is not None: + artifacts_path = Path(settings.artifacts_path).expanduser() + + if artifacts_path is not None and not artifacts_path.is_dir(): + raise RuntimeError( + f"The value of {artifacts_path=} is not valid. " + "When defined, it must point to a folder containing all models required by the pipeline." + ) + + # force_backend_text = False - use text that is coming from VLM response + # force_backend_text = True - get text from backend using bounding boxes predicted by SmolDocling doctags + self.force_backend_text = ( + pipeline_options.force_backend_text + and pipeline_options.vlm_options.response_format == ResponseFormat.DOCTAGS + ) + + self.keep_images = self.pipeline_options.generate_page_images + + self.build_pipe = [ + HuggingFaceVlmModel( + enabled=True, # must be always enabled for this pipeline to make sense. + artifacts_path=artifacts_path, + accelerator_options=pipeline_options.accelerator_options, + vlm_options=self.pipeline_options.vlm_options, + ), + ] + + self.enrichment_pipe = [ + # Other models working on `NodeItem` elements in the DoclingDocument + ] + + def initialize_page(self, conv_res: ConversionResult, page: Page) -> Page: + with TimeRecorder(conv_res, "page_init"): + page._backend = conv_res.input._backend.load_page(page.page_no) # type: ignore + if page._backend is not None and page._backend.is_valid(): + page.size = page._backend.get_size() + + return page + + def _assemble_document(self, conv_res: ConversionResult) -> ConversionResult: + with TimeRecorder(conv_res, "doc_assemble", scope=ProfilingScope.DOCUMENT): + + if ( + self.pipeline_options.vlm_options.response_format + == ResponseFormat.DOCTAGS + ): + conv_res.document = self._turn_tags_into_doc(conv_res.pages) + elif ( + self.pipeline_options.vlm_options.response_format + == ResponseFormat.MARKDOWN + ): + conv_res.document = self._turn_md_into_doc(conv_res) + + else: + raise RuntimeError( + f"Unsupported VLM response format {self.pipeline_options.vlm_options.response_format}" + ) + + # Generate images of the requested element types + if self.pipeline_options.generate_picture_images: + scale = self.pipeline_options.images_scale + for element, _level in conv_res.document.iterate_items(): + if not isinstance(element, DocItem) or len(element.prov) == 0: + continue + if ( + isinstance(element, PictureItem) + and self.pipeline_options.generate_picture_images + ): + page_ix = element.prov[0].page_no - 1 + page = conv_res.pages[page_ix] + assert page.size is not None + assert page.image is not None + + crop_bbox = ( + element.prov[0] + .bbox.scaled(scale=scale) + .to_top_left_origin(page_height=page.size.height * scale) + ) + + cropped_im = page.image.crop(crop_bbox.as_tuple()) + element.image = ImageRef.from_pil( + cropped_im, dpi=int(72 * scale) + ) + + return conv_res + + def _turn_md_into_doc(self, conv_res): + predicted_text = "" + for pg_idx, page in enumerate(conv_res.pages): + if page.predictions.vlm_response: + predicted_text += page.predictions.vlm_response.text + "\n\n" + response_bytes = BytesIO(predicted_text.encode("utf8")) + out_doc = InputDocument( + path_or_stream=response_bytes, + filename=conv_res.input.file.name, + format=InputFormat.MD, + backend=MarkdownDocumentBackend, + ) + backend = MarkdownDocumentBackend( + in_doc=out_doc, + path_or_stream=response_bytes, + ) + return backend.convert() + + def _turn_tags_into_doc(self, pages: list[Page]) -> DoclingDocument: + ############################################### + # Tag definitions and color mappings + ############################################### + + # Maps the recognized tag to a Docling label. + # Code items will be given DocItemLabel.CODE + tag_to_doclabel = { + "title": DocItemLabel.TITLE, + "document_index": DocItemLabel.DOCUMENT_INDEX, + "otsl": DocItemLabel.TABLE, + "section_header_level_1": DocItemLabel.SECTION_HEADER, + "checkbox_selected": DocItemLabel.CHECKBOX_SELECTED, + "checkbox_unselected": DocItemLabel.CHECKBOX_UNSELECTED, + "text": DocItemLabel.TEXT, + "page_header": DocItemLabel.PAGE_HEADER, + "page_footer": DocItemLabel.PAGE_FOOTER, + "formula": DocItemLabel.FORMULA, + "caption": DocItemLabel.CAPTION, + "picture": DocItemLabel.PICTURE, + "list_item": DocItemLabel.LIST_ITEM, + "footnote": DocItemLabel.FOOTNOTE, + "code": DocItemLabel.CODE, + } + + # Maps each tag to an associated bounding box color. + tag_to_color = { + "title": "blue", + "document_index": "darkblue", + "otsl": "green", + "section_header_level_1": "purple", + "checkbox_selected": "black", + "checkbox_unselected": "gray", + "text": "red", + "page_header": "orange", + "page_footer": "cyan", + "formula": "pink", + "caption": "magenta", + "picture": "yellow", + "list_item": "brown", + "footnote": "darkred", + "code": "lightblue", + } + + def extract_bounding_box(text_chunk: str) -> Optional[BoundingBox]: + """Extracts bounding box coords from the chunk, normalized by / 500.""" + coords = re.findall(r"", text_chunk) + if len(coords) == 4: + l, t, r, b = map(float, coords) + return BoundingBox(l=l / 500, t=t / 500, r=r / 500, b=b / 500) + return None + + def extract_inner_text(text_chunk: str) -> str: + """Strips all <...> tags inside the chunk to get the raw text content.""" + return re.sub(r"<.*?>", "", text_chunk, flags=re.DOTALL).strip() + + def extract_text_from_backend(page: Page, bbox: BoundingBox | None) -> str: + # Convert bounding box normalized to 0-100 into page coordinates for cropping + text = "" + if bbox: + if page.size: + bbox.l = bbox.l * page.size.width + bbox.t = bbox.t * page.size.height + bbox.r = bbox.r * page.size.width + bbox.b = bbox.b * page.size.height + if page._backend: + text = page._backend.get_text_in_rect(bbox) + return text + + def otsl_parse_texts(texts, tokens): + split_word = TableToken.OTSL_NL.value + split_row_tokens = [ + list(y) + for x, y in itertools.groupby(tokens, lambda z: z == split_word) + if not x + ] + table_cells = [] + r_idx = 0 + c_idx = 0 + + def count_right(tokens, c_idx, r_idx, which_tokens): + span = 0 + c_idx_iter = c_idx + while tokens[r_idx][c_idx_iter] in which_tokens: + c_idx_iter += 1 + span += 1 + if c_idx_iter >= len(tokens[r_idx]): + return span + return span + + def count_down(tokens, c_idx, r_idx, which_tokens): + span = 0 + r_idx_iter = r_idx + while tokens[r_idx_iter][c_idx] in which_tokens: + r_idx_iter += 1 + span += 1 + if r_idx_iter >= len(tokens): + return span + return span + + for i, text in enumerate(texts): + cell_text = "" + if text in [ + TableToken.OTSL_FCEL.value, + TableToken.OTSL_ECEL.value, + TableToken.OTSL_CHED.value, + TableToken.OTSL_RHED.value, + TableToken.OTSL_SROW.value, + ]: + row_span = 1 + col_span = 1 + right_offset = 1 + if text != TableToken.OTSL_ECEL.value: + cell_text = texts[i + 1] + right_offset = 2 + + # Check next element(s) for lcel / ucel / xcel, set properly row_span, col_span + next_right_cell = "" + if i + right_offset < len(texts): + next_right_cell = texts[i + right_offset] + + next_bottom_cell = "" + if r_idx + 1 < len(split_row_tokens): + if c_idx < len(split_row_tokens[r_idx + 1]): + next_bottom_cell = split_row_tokens[r_idx + 1][c_idx] + + if next_right_cell in [ + TableToken.OTSL_LCEL.value, + TableToken.OTSL_XCEL.value, + ]: + # we have horisontal spanning cell or 2d spanning cell + col_span += count_right( + split_row_tokens, + c_idx + 1, + r_idx, + [TableToken.OTSL_LCEL.value, TableToken.OTSL_XCEL.value], + ) + if next_bottom_cell in [ + TableToken.OTSL_UCEL.value, + TableToken.OTSL_XCEL.value, + ]: + # we have a vertical spanning cell or 2d spanning cell + row_span += count_down( + split_row_tokens, + c_idx, + r_idx + 1, + [TableToken.OTSL_UCEL.value, TableToken.OTSL_XCEL.value], + ) + + table_cells.append( + TableCell( + text=cell_text.strip(), + row_span=row_span, + col_span=col_span, + start_row_offset_idx=r_idx, + end_row_offset_idx=r_idx + row_span, + start_col_offset_idx=c_idx, + end_col_offset_idx=c_idx + col_span, + ) + ) + if text in [ + TableToken.OTSL_FCEL.value, + TableToken.OTSL_ECEL.value, + TableToken.OTSL_CHED.value, + TableToken.OTSL_RHED.value, + TableToken.OTSL_SROW.value, + TableToken.OTSL_LCEL.value, + TableToken.OTSL_UCEL.value, + TableToken.OTSL_XCEL.value, + ]: + c_idx += 1 + if text == TableToken.OTSL_NL.value: + r_idx += 1 + c_idx = 0 + return table_cells, split_row_tokens + + def otsl_extract_tokens_and_text(s: str): + # Pattern to match anything enclosed by < > (including the angle brackets themselves) + pattern = r"(<[^>]+>)" + # Find all tokens (e.g. "", "", etc.) + tokens = re.findall(pattern, s) + # Remove any tokens that start with "", + rf"", + ] + ) + ] + # Split the string by those tokens to get the in-between text + text_parts = re.split(pattern, s) + text_parts = [ + token + for token in text_parts + if not ( + token.startswith(rf"<{DocumentToken.LOC.value}") + or token + in [ + rf"<{DocumentToken.OTSL.value}>", + rf"", + ] + ) + ] + # Remove any empty or purely whitespace strings from text_parts + text_parts = [part for part in text_parts if part.strip()] + + return tokens, text_parts + + def parse_table_content(otsl_content: str) -> TableData: + tokens, mixed_texts = otsl_extract_tokens_and_text(otsl_content) + table_cells, split_row_tokens = otsl_parse_texts(mixed_texts, tokens) + + return TableData( + num_rows=len(split_row_tokens), + num_cols=( + max(len(row) for row in split_row_tokens) if split_row_tokens else 0 + ), + table_cells=table_cells, + ) + + doc = DoclingDocument(name="Document") + for pg_idx, page in enumerate(pages): + xml_content = "" + predicted_text = "" + if page.predictions.vlm_response: + predicted_text = page.predictions.vlm_response.text + image = page.image + + page_no = pg_idx + 1 + bounding_boxes = [] + + if page.size: + pg_width = page.size.width + pg_height = page.size.height + size = Size(width=pg_width, height=pg_height) + parent_page = doc.add_page(page_no=page_no, size=size) + + """ + 1. Finds all ... blocks in the entire string (multi-line friendly) in the order they appear. + 2. For each chunk, extracts bounding box (if any) and inner text. + 3. Adds the item to a DoclingDocument structure with the right label. + 4. Tracks bounding boxes + color in a separate list for later visualization. + """ + + # Regex for all recognized tags + tag_pattern = ( + rf"<(?P{DocItemLabel.TITLE}|{DocItemLabel.DOCUMENT_INDEX}|" + rf"{DocItemLabel.CHECKBOX_UNSELECTED}|{DocItemLabel.CHECKBOX_SELECTED}|" + rf"{DocItemLabel.TEXT}|{DocItemLabel.PAGE_HEADER}|" + rf"{DocItemLabel.PAGE_FOOTER}|{DocItemLabel.FORMULA}|" + rf"{DocItemLabel.CAPTION}|{DocItemLabel.PICTURE}|" + rf"{DocItemLabel.LIST_ITEM}|{DocItemLabel.FOOTNOTE}|{DocItemLabel.CODE}|" + rf"{DocItemLabel.SECTION_HEADER}_level_1|{DocumentToken.OTSL.value})>.*?" + ) + + # DocumentToken.OTSL + pattern = re.compile(tag_pattern, re.DOTALL) + + # Go through each match in order + for match in pattern.finditer(predicted_text): + full_chunk = match.group(0) + tag_name = match.group("tag") + + bbox = extract_bounding_box(full_chunk) + doc_label = tag_to_doclabel.get(tag_name, DocItemLabel.PARAGRAPH) + color = tag_to_color.get(tag_name, "white") + + # Store bounding box + color + if bbox: + bounding_boxes.append((bbox, color)) + + if tag_name == DocumentToken.OTSL.value: + table_data = parse_table_content(full_chunk) + bbox = extract_bounding_box(full_chunk) + + if bbox: + prov = ProvenanceItem( + bbox=bbox.resize_by_scale(pg_width, pg_height), + charspan=(0, 0), + page_no=page_no, + ) + doc.add_table(data=table_data, prov=prov) + else: + doc.add_table(data=table_data) + + elif tag_name == DocItemLabel.PICTURE: + text_caption_content = extract_inner_text(full_chunk) + if image: + if bbox: + im_width, im_height = image.size + + crop_box = ( + int(bbox.l * im_width), + int(bbox.t * im_height), + int(bbox.r * im_width), + int(bbox.b * im_height), + ) + cropped_image = image.crop(crop_box) + pic = doc.add_picture( + parent=None, + image=ImageRef.from_pil(image=cropped_image, dpi=72), + prov=( + ProvenanceItem( + bbox=bbox.resize_by_scale(pg_width, pg_height), + charspan=(0, 0), + page_no=page_no, + ) + ), + ) + # If there is a caption to an image, add it as well + if len(text_caption_content) > 0: + caption_item = doc.add_text( + label=DocItemLabel.CAPTION, + text=text_caption_content, + parent=None, + ) + pic.captions.append(caption_item.get_ref()) + else: + if bbox: + # In case we don't have access to an binary of an image + doc.add_picture( + parent=None, + prov=ProvenanceItem( + bbox=bbox, charspan=(0, 0), page_no=page_no + ), + ) + # If there is a caption to an image, add it as well + if len(text_caption_content) > 0: + caption_item = doc.add_text( + label=DocItemLabel.CAPTION, + text=text_caption_content, + parent=None, + ) + pic.captions.append(caption_item.get_ref()) + else: + # For everything else, treat as text + if self.force_backend_text: + text_content = extract_text_from_backend(page, bbox) + else: + text_content = extract_inner_text(full_chunk) + doc.add_text( + label=doc_label, + text=text_content, + prov=( + ProvenanceItem( + bbox=bbox.resize_by_scale(pg_width, pg_height), + charspan=(0, len(text_content)), + page_no=page_no, + ) + if bbox + else None + ), + ) + return doc + + @classmethod + def get_default_options(cls) -> VlmPipelineOptions: + return VlmPipelineOptions() + + @classmethod + def is_backend_supported(cls, backend: AbstractDocumentBackend): + return isinstance(backend, PdfDocumentBackend) diff --git a/docling/utils/visualization.py b/docling/utils/visualization.py index 465b7749..e7ea24a5 100644 --- a/docling/utils/visualization.py +++ b/docling/utils/visualization.py @@ -43,6 +43,11 @@ def draw_clusters( y0 *= scale_x y1 *= scale_y + if y1 <= y0: + y1, y0 = y0, y1 + if x1 <= x0: + x1, x0 = x0, x1 + cluster_fill_color = (*list(DocItemLabel.get_color(c.label)), 70) cluster_outline_color = ( *list(DocItemLabel.get_color(c.label)), diff --git a/docs/examples/minimal_vlm_pipeline.py b/docs/examples/minimal_vlm_pipeline.py new file mode 100644 index 00000000..948ecc64 --- /dev/null +++ b/docs/examples/minimal_vlm_pipeline.py @@ -0,0 +1,96 @@ +import json +import time +from pathlib import Path + +import yaml + +from docling.datamodel.base_models import InputFormat +from docling.datamodel.pipeline_options import ( + AcceleratorDevice, + VlmPipelineOptions, + granite_vision_vlm_conversion_options, + smoldocling_vlm_conversion_options, +) +from docling.datamodel.settings import settings +from docling.document_converter import DocumentConverter, PdfFormatOption +from docling.pipeline.vlm_pipeline import VlmPipeline + +sources = [ + "tests/data/2305.03393v1-pg9-img.png", +] + +## Use experimental VlmPipeline +pipeline_options = VlmPipelineOptions() +# If force_backend_text = True, text from backend will be used instead of generated text +pipeline_options.force_backend_text = False + +## On GPU systems, enable flash_attention_2 with CUDA: +# pipeline_options.accelerator_options.device = AcceleratorDevice.CUDA +# pipeline_options.accelerator_options.cuda_use_flash_attention2 = True + +## Pick a VLM model. We choose SmolDocling-256M by default +pipeline_options.vlm_options = smoldocling_vlm_conversion_options + +## Alternative VLM models: +# pipeline_options.vlm_options = granite_vision_vlm_conversion_options + +from docling_core.types.doc import DocItemLabel, ImageRefMode +from docling_core.types.doc.document import DEFAULT_EXPORT_LABELS + +## Set up pipeline for PDF or image inputs +converter = DocumentConverter( + format_options={ + InputFormat.PDF: PdfFormatOption( + pipeline_cls=VlmPipeline, + pipeline_options=pipeline_options, + ), + InputFormat.IMAGE: PdfFormatOption( + pipeline_cls=VlmPipeline, + pipeline_options=pipeline_options, + ), + } +) + +out_path = Path("scratch") +out_path.mkdir(parents=True, exist_ok=True) + +for source in sources: + start_time = time.time() + print("================================================") + print("Processing... {}".format(source)) + print("================================================") + print("") + + res = converter.convert(source) + + print("------------------------------------------------") + print("MD:") + print("------------------------------------------------") + print("") + print(res.document.export_to_markdown()) + + for page in res.pages: + print("") + print("Predicted page in DOCTAGS:") + print(page.predictions.vlm_response.text) + + res.document.save_as_html( + filename=Path("{}/{}.html".format(out_path, res.input.file.stem)), + image_mode=ImageRefMode.REFERENCED, + labels=[*DEFAULT_EXPORT_LABELS, DocItemLabel.FOOTNOTE], + ) + + with (out_path / f"{res.input.file.stem}.json").open("w") as fp: + fp.write(json.dumps(res.document.export_to_dict())) + + pg_num = res.document.num_pages() + + print("") + inference_time = time.time() - start_time + print( + f"Total document prediction time: {inference_time:.2f} seconds, pages: {pg_num}" + ) + +print("================================================") +print("done!") +print("================================================") diff --git a/poetry.lock b/poetry.lock index 1f35c6d7..374dfe0d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,35 @@ -# This file is automatically @generated by Poetry 1.8.5 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand. + +[[package]] +name = "accelerate" +version = "1.4.0" +description = "Accelerate" +optional = true +python-versions = ">=3.9.0" +files = [ + {file = "accelerate-1.4.0-py3-none-any.whl", hash = "sha256:f6e1e7dfaf9d799a20a1dc45efbf4b1546163eac133faa5acd0d89177c896e55"}, + {file = "accelerate-1.4.0.tar.gz", hash = "sha256:37d413e1b64cb8681ccd2908ae211cf73e13e6e636a2f598a96eccaa538773a5"}, +] + +[package.dependencies] +huggingface-hub = ">=0.21.0" +numpy = ">=1.17,<3.0.0" +packaging = ">=20.0" +psutil = "*" +pyyaml = "*" +safetensors = ">=0.4.3" +torch = ">=2.0.0" + +[package.extras] +deepspeed = ["deepspeed"] +dev = ["bitsandbytes", "black (>=23.1,<24.0)", "datasets", "diffusers", "evaluate", "hf-doc-builder (>=0.3.0)", "parameterized", "pytest (>=7.2.0,<=8.0.0)", "pytest-subtests", "pytest-xdist", "rich", "ruff (>=0.6.4,<0.7.0)", "scikit-learn", "scipy", "timm", "torchdata (>=0.8.0)", "torchpippy (>=0.2.0)", "tqdm", "transformers"] +quality = ["black (>=23.1,<24.0)", "hf-doc-builder (>=0.3.0)", "ruff (>=0.6.4,<0.7.0)"] +rich = ["rich"] +sagemaker = ["sagemaker"] +test-dev = ["bitsandbytes", "datasets", "diffusers", "evaluate", "scikit-learn", "scipy", "timm", "torchdata (>=0.8.0)", "torchpippy (>=0.2.0)", "tqdm", "transformers"] +test-prod = ["parameterized", "pytest (>=7.2.0,<=8.0.0)", "pytest-subtests", "pytest-xdist"] +test-trackers = ["comet-ml", "dvclive", "tensorboard", "wandb"] +testing = ["bitsandbytes", "datasets", "diffusers", "evaluate", "parameterized", "pytest (>=7.2.0,<=8.0.0)", "pytest-subtests", "pytest-xdist", "scikit-learn", "scipy", "timm", "torchdata (>=0.8.0)", "torchpippy (>=0.2.0)", "tqdm", "transformers"] [[package]] name = "aiohappyeyeballs" @@ -13,92 +44,92 @@ files = [ [[package]] name = "aiohttp" -version = "3.11.12" +version = "3.11.13" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.9" files = [ - {file = "aiohttp-3.11.12-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:aa8a8caca81c0a3e765f19c6953416c58e2f4cc1b84829af01dd1c771bb2f91f"}, - {file = "aiohttp-3.11.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:84ede78acde96ca57f6cf8ccb8a13fbaf569f6011b9a52f870c662d4dc8cd854"}, - {file = "aiohttp-3.11.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:584096938a001378484aa4ee54e05dc79c7b9dd933e271c744a97b3b6f644957"}, - {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:392432a2dde22b86f70dd4a0e9671a349446c93965f261dbaecfaf28813e5c42"}, - {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:88d385b8e7f3a870146bf5ea31786ef7463e99eb59e31db56e2315535d811f55"}, - {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b10a47e5390c4b30a0d58ee12581003be52eedd506862ab7f97da7a66805befb"}, - {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b5263dcede17b6b0c41ef0c3ccce847d82a7da98709e75cf7efde3e9e3b5cae"}, - {file = "aiohttp-3.11.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50c5c7b8aa5443304c55c262c5693b108c35a3b61ef961f1e782dd52a2f559c7"}, - {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d1c031a7572f62f66f1257db37ddab4cb98bfaf9b9434a3b4840bf3560f5e788"}, - {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:7e44eba534381dd2687be50cbd5f2daded21575242ecfdaf86bbeecbc38dae8e"}, - {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:145a73850926018ec1681e734cedcf2716d6a8697d90da11284043b745c286d5"}, - {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:2c311e2f63e42c1bf86361d11e2c4a59f25d9e7aabdbdf53dc38b885c5435cdb"}, - {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:ea756b5a7bac046d202a9a3889b9a92219f885481d78cd318db85b15cc0b7bcf"}, - {file = "aiohttp-3.11.12-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:526c900397f3bbc2db9cb360ce9c35134c908961cdd0ac25b1ae6ffcaa2507ff"}, - {file = "aiohttp-3.11.12-cp310-cp310-win32.whl", hash = "sha256:b8d3bb96c147b39c02d3db086899679f31958c5d81c494ef0fc9ef5bb1359b3d"}, - {file = "aiohttp-3.11.12-cp310-cp310-win_amd64.whl", hash = "sha256:7fe3d65279bfbee8de0fb4f8c17fc4e893eed2dba21b2f680e930cc2b09075c5"}, - {file = "aiohttp-3.11.12-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:87a2e00bf17da098d90d4145375f1d985a81605267e7f9377ff94e55c5d769eb"}, - {file = "aiohttp-3.11.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b34508f1cd928ce915ed09682d11307ba4b37d0708d1f28e5774c07a7674cac9"}, - {file = "aiohttp-3.11.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:936d8a4f0f7081327014742cd51d320296b56aa6d324461a13724ab05f4b2933"}, - {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2de1378f72def7dfb5dbd73d86c19eda0ea7b0a6873910cc37d57e80f10d64e1"}, - {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b9d45dbb3aaec05cf01525ee1a7ac72de46a8c425cb75c003acd29f76b1ffe94"}, - {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:930ffa1925393381e1e0a9b82137fa7b34c92a019b521cf9f41263976666a0d6"}, - {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8340def6737118f5429a5df4e88f440746b791f8f1c4ce4ad8a595f42c980bd5"}, - {file = "aiohttp-3.11.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4016e383f91f2814e48ed61e6bda7d24c4d7f2402c75dd28f7e1027ae44ea204"}, - {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3c0600bcc1adfaaac321422d615939ef300df81e165f6522ad096b73439c0f58"}, - {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:0450ada317a65383b7cce9576096150fdb97396dcfe559109b403c7242faffef"}, - {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:850ff6155371fd802a280f8d369d4e15d69434651b844bde566ce97ee2277420"}, - {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:8fd12d0f989c6099e7b0f30dc6e0d1e05499f3337461f0b2b0dadea6c64b89df"}, - {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:76719dd521c20a58a6c256d058547b3a9595d1d885b830013366e27011ffe804"}, - {file = "aiohttp-3.11.12-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:97fe431f2ed646a3b56142fc81d238abcbaff08548d6912acb0b19a0cadc146b"}, - {file = "aiohttp-3.11.12-cp311-cp311-win32.whl", hash = "sha256:e10c440d142fa8b32cfdb194caf60ceeceb3e49807072e0dc3a8887ea80e8c16"}, - {file = "aiohttp-3.11.12-cp311-cp311-win_amd64.whl", hash = "sha256:246067ba0cf5560cf42e775069c5d80a8989d14a7ded21af529a4e10e3e0f0e6"}, - {file = "aiohttp-3.11.12-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e392804a38353900c3fd8b7cacbea5132888f7129f8e241915e90b85f00e3250"}, - {file = "aiohttp-3.11.12-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8fa1510b96c08aaad49303ab11f8803787c99222288f310a62f493faf883ede1"}, - {file = "aiohttp-3.11.12-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dc065a4285307607df3f3686363e7f8bdd0d8ab35f12226362a847731516e42c"}, - {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cddb31f8474695cd61fc9455c644fc1606c164b93bff2490390d90464b4655df"}, - {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9dec0000d2d8621d8015c293e24589d46fa218637d820894cb7356c77eca3259"}, - {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e3552fe98e90fdf5918c04769f338a87fa4f00f3b28830ea9b78b1bdc6140e0d"}, - {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dfe7f984f28a8ae94ff3a7953cd9678550dbd2a1f9bda5dd9c5ae627744c78e"}, - {file = "aiohttp-3.11.12-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a481a574af914b6e84624412666cbfbe531a05667ca197804ecc19c97b8ab1b0"}, - {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1987770fb4887560363b0e1a9b75aa303e447433c41284d3af2840a2f226d6e0"}, - {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:a4ac6a0f0f6402854adca4e3259a623f5c82ec3f0c049374133bcb243132baf9"}, - {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c96a43822f1f9f69cc5c3706af33239489a6294be486a0447fb71380070d4d5f"}, - {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:a5e69046f83c0d3cb8f0d5bd9b8838271b1bc898e01562a04398e160953e8eb9"}, - {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:68d54234c8d76d8ef74744f9f9fc6324f1508129e23da8883771cdbb5818cbef"}, - {file = "aiohttp-3.11.12-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c9fd9dcf9c91affe71654ef77426f5cf8489305e1c66ed4816f5a21874b094b9"}, - {file = "aiohttp-3.11.12-cp312-cp312-win32.whl", hash = "sha256:0ed49efcd0dc1611378beadbd97beb5d9ca8fe48579fc04a6ed0844072261b6a"}, - {file = "aiohttp-3.11.12-cp312-cp312-win_amd64.whl", hash = "sha256:54775858c7f2f214476773ce785a19ee81d1294a6bedc5cc17225355aab74802"}, - {file = "aiohttp-3.11.12-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:413ad794dccb19453e2b97c2375f2ca3cdf34dc50d18cc2693bd5aed7d16f4b9"}, - {file = "aiohttp-3.11.12-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4a93d28ed4b4b39e6f46fd240896c29b686b75e39cc6992692e3922ff6982b4c"}, - {file = "aiohttp-3.11.12-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d589264dbba3b16e8951b6f145d1e6b883094075283dafcab4cdd564a9e353a0"}, - {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5148ca8955affdfeb864aca158ecae11030e952b25b3ae15d4e2b5ba299bad2"}, - {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:525410e0790aab036492eeea913858989c4cb070ff373ec3bc322d700bdf47c1"}, - {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bd8695be2c80b665ae3f05cb584093a1e59c35ecb7d794d1edd96e8cc9201d7"}, - {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0203433121484b32646a5f5ea93ae86f3d9559d7243f07e8c0eab5ff8e3f70e"}, - {file = "aiohttp-3.11.12-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40cd36749a1035c34ba8d8aaf221b91ca3d111532e5ccb5fa8c3703ab1b967ed"}, - {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a7442662afebbf7b4c6d28cb7aab9e9ce3a5df055fc4116cc7228192ad6cb484"}, - {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:8a2fb742ef378284a50766e985804bd6adb5adb5aa781100b09befdbfa757b65"}, - {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2cee3b117a8d13ab98b38d5b6bdcd040cfb4181068d05ce0c474ec9db5f3c5bb"}, - {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f6a19bcab7fbd8f8649d6595624856635159a6527861b9cdc3447af288a00c00"}, - {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:e4cecdb52aaa9994fbed6b81d4568427b6002f0a91c322697a4bfcc2b2363f5a"}, - {file = "aiohttp-3.11.12-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:30f546358dfa0953db92ba620101fefc81574f87b2346556b90b5f3ef16e55ce"}, - {file = "aiohttp-3.11.12-cp313-cp313-win32.whl", hash = "sha256:ce1bb21fc7d753b5f8a5d5a4bae99566386b15e716ebdb410154c16c91494d7f"}, - {file = "aiohttp-3.11.12-cp313-cp313-win_amd64.whl", hash = "sha256:f7914ab70d2ee8ab91c13e5402122edbc77821c66d2758abb53aabe87f013287"}, - {file = "aiohttp-3.11.12-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7c3623053b85b4296cd3925eeb725e386644fd5bc67250b3bb08b0f144803e7b"}, - {file = "aiohttp-3.11.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:67453e603cea8e85ed566b2700efa1f6916aefbc0c9fcb2e86aaffc08ec38e78"}, - {file = "aiohttp-3.11.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6130459189e61baac5a88c10019b21e1f0c6d00ebc770e9ce269475650ff7f73"}, - {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9060addfa4ff753b09392efe41e6af06ea5dd257829199747b9f15bfad819460"}, - {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:34245498eeb9ae54c687a07ad7f160053911b5745e186afe2d0c0f2898a1ab8a"}, - {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8dc0fba9a74b471c45ca1a3cb6e6913ebfae416678d90529d188886278e7f3f6"}, - {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a478aa11b328983c4444dacb947d4513cb371cd323f3845e53caeda6be5589d5"}, - {file = "aiohttp-3.11.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c160a04283c8c6f55b5bf6d4cad59bb9c5b9c9cd08903841b25f1f7109ef1259"}, - {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:edb69b9589324bdc40961cdf0657815df674f1743a8d5ad9ab56a99e4833cfdd"}, - {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:4ee84c2a22a809c4f868153b178fe59e71423e1f3d6a8cd416134bb231fbf6d3"}, - {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:bf4480a5438f80e0f1539e15a7eb8b5f97a26fe087e9828e2c0ec2be119a9f72"}, - {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:e6b2732ef3bafc759f653a98881b5b9cdef0716d98f013d376ee8dfd7285abf1"}, - {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:f752e80606b132140883bb262a457c475d219d7163d996dc9072434ffb0784c4"}, - {file = "aiohttp-3.11.12-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ab3247d58b393bda5b1c8f31c9edece7162fc13265334217785518dd770792b8"}, - {file = "aiohttp-3.11.12-cp39-cp39-win32.whl", hash = "sha256:0d5176f310a7fe6f65608213cc74f4228e4f4ce9fd10bcb2bb6da8fc66991462"}, - {file = "aiohttp-3.11.12-cp39-cp39-win_amd64.whl", hash = "sha256:74bd573dde27e58c760d9ca8615c41a57e719bff315c9adb6f2a4281a28e8798"}, - {file = "aiohttp-3.11.12.tar.gz", hash = "sha256:7603ca26d75b1b86160ce1bbe2787a0b706e592af5b2504e12caa88a217767b0"}, + {file = "aiohttp-3.11.13-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a4fe27dbbeec445e6e1291e61d61eb212ee9fed6e47998b27de71d70d3e8777d"}, + {file = "aiohttp-3.11.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9e64ca2dbea28807f8484c13f684a2f761e69ba2640ec49dacd342763cc265ef"}, + {file = "aiohttp-3.11.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9840be675de208d1f68f84d578eaa4d1a36eee70b16ae31ab933520c49ba1325"}, + {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28a772757c9067e2aee8a6b2b425d0efaa628c264d6416d283694c3d86da7689"}, + {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b88aca5adbf4625e11118df45acac29616b425833c3be7a05ef63a6a4017bfdb"}, + {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce10ddfbe26ed5856d6902162f71b8fe08545380570a885b4ab56aecfdcb07f4"}, + {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa48dac27f41b36735c807d1ab093a8386701bbf00eb6b89a0f69d9fa26b3671"}, + {file = "aiohttp-3.11.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:89ce611b1eac93ce2ade68f1470889e0173d606de20c85a012bfa24be96cf867"}, + {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:78e4dd9c34ec7b8b121854eb5342bac8b02aa03075ae8618b6210a06bbb8a115"}, + {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:66047eacbc73e6fe2462b77ce39fc170ab51235caf331e735eae91c95e6a11e4"}, + {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5ad8f1c19fe277eeb8bc45741c6d60ddd11d705c12a4d8ee17546acff98e0802"}, + {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:64815c6f02e8506b10113ddbc6b196f58dbef135751cc7c32136df27b736db09"}, + {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:967b93f21b426f23ca37329230d5bd122f25516ae2f24a9cea95a30023ff8283"}, + {file = "aiohttp-3.11.13-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cf1f31f83d16ec344136359001c5e871915c6ab685a3d8dee38e2961b4c81730"}, + {file = "aiohttp-3.11.13-cp310-cp310-win32.whl", hash = "sha256:00c8ac69e259c60976aa2edae3f13d9991cf079aaa4d3cd5a49168ae3748dee3"}, + {file = "aiohttp-3.11.13-cp310-cp310-win_amd64.whl", hash = "sha256:90d571c98d19a8b6e793b34aa4df4cee1e8fe2862d65cc49185a3a3d0a1a3996"}, + {file = "aiohttp-3.11.13-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b35aab22419ba45f8fc290d0010898de7a6ad131e468ffa3922b1b0b24e9d2e"}, + {file = "aiohttp-3.11.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f81cba651db8795f688c589dd11a4fbb834f2e59bbf9bb50908be36e416dc760"}, + {file = "aiohttp-3.11.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f55d0f242c2d1fcdf802c8fabcff25a9d85550a4cf3a9cf5f2a6b5742c992839"}, + {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4bea08a6aad9195ac9b1be6b0c7e8a702a9cec57ce6b713698b4a5afa9c2e33"}, + {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c6070bcf2173a7146bb9e4735b3c62b2accba459a6eae44deea0eb23e0035a23"}, + {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:718d5deb678bc4b9d575bfe83a59270861417da071ab44542d0fcb6faa686636"}, + {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0f6b2c5b4a4d22b8fb2c92ac98e0747f5f195e8e9448bfb7404cd77e7bfa243f"}, + {file = "aiohttp-3.11.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:747ec46290107a490d21fe1ff4183bef8022b848cf9516970cb31de6d9460088"}, + {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:01816f07c9cc9d80f858615b1365f8319d6a5fd079cd668cc58e15aafbc76a54"}, + {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:a08ad95fcbd595803e0c4280671d808eb170a64ca3f2980dd38e7a72ed8d1fea"}, + {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c97be90d70f7db3aa041d720bfb95f4869d6063fcdf2bb8333764d97e319b7d0"}, + {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ab915a57c65f7a29353c8014ac4be685c8e4a19e792a79fe133a8e101111438e"}, + {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:35cda4e07f5e058a723436c4d2b7ba2124ab4e0aa49e6325aed5896507a8a42e"}, + {file = "aiohttp-3.11.13-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:af55314407714fe77a68a9ccaab90fdb5deb57342585fd4a3a8102b6d4370080"}, + {file = "aiohttp-3.11.13-cp311-cp311-win32.whl", hash = "sha256:42d689a5c0a0c357018993e471893e939f555e302313d5c61dfc566c2cad6185"}, + {file = "aiohttp-3.11.13-cp311-cp311-win_amd64.whl", hash = "sha256:b73a2b139782a07658fbf170fe4bcdf70fc597fae5ffe75e5b67674c27434a9f"}, + {file = "aiohttp-3.11.13-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:2eabb269dc3852537d57589b36d7f7362e57d1ece308842ef44d9830d2dc3c90"}, + {file = "aiohttp-3.11.13-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7b77ee42addbb1c36d35aca55e8cc6d0958f8419e458bb70888d8c69a4ca833d"}, + {file = "aiohttp-3.11.13-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55789e93c5ed71832e7fac868167276beadf9877b85697020c46e9a75471f55f"}, + {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c929f9a7249a11e4aa5c157091cfad7f49cc6b13f4eecf9b747104befd9f56f2"}, + {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d33851d85537bbf0f6291ddc97926a754c8f041af759e0aa0230fe939168852b"}, + {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9229d8613bd8401182868fe95688f7581673e1c18ff78855671a4b8284f47bcb"}, + {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:669dd33f028e54fe4c96576f406ebb242ba534dd3a981ce009961bf49960f117"}, + {file = "aiohttp-3.11.13-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7c1b20a1ace54af7db1f95af85da530fe97407d9063b7aaf9ce6a32f44730778"}, + {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5724cc77f4e648362ebbb49bdecb9e2b86d9b172c68a295263fa072e679ee69d"}, + {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:aa36c35e94ecdb478246dd60db12aba57cfcd0abcad43c927a8876f25734d496"}, + {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9b5b37c863ad5b0892cc7a4ceb1e435e5e6acd3f2f8d3e11fa56f08d3c67b820"}, + {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:e06cf4852ce8c4442a59bae5a3ea01162b8fcb49ab438d8548b8dc79375dad8a"}, + {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:5194143927e494616e335d074e77a5dac7cd353a04755330c9adc984ac5a628e"}, + {file = "aiohttp-3.11.13-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:afcb6b275c2d2ba5d8418bf30a9654fa978b4f819c2e8db6311b3525c86fe637"}, + {file = "aiohttp-3.11.13-cp312-cp312-win32.whl", hash = "sha256:7104d5b3943c6351d1ad7027d90bdd0ea002903e9f610735ac99df3b81f102ee"}, + {file = "aiohttp-3.11.13-cp312-cp312-win_amd64.whl", hash = "sha256:47dc018b1b220c48089b5b9382fbab94db35bef2fa192995be22cbad3c5730c8"}, + {file = "aiohttp-3.11.13-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:9862d077b9ffa015dbe3ce6c081bdf35135948cb89116e26667dd183550833d1"}, + {file = "aiohttp-3.11.13-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fbfef0666ae9e07abfa2c54c212ac18a1f63e13e0760a769f70b5717742f3ece"}, + {file = "aiohttp-3.11.13-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:93a1f7d857c4fcf7cabb1178058182c789b30d85de379e04f64c15b7e88d66fb"}, + {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba40b7ae0f81c7029583a338853f6607b6d83a341a3dcde8bed1ea58a3af1df9"}, + {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b5b95787335c483cd5f29577f42bbe027a412c5431f2f80a749c80d040f7ca9f"}, + {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7d474c5c1f0b9405c1565fafdc4429fa7d986ccbec7ce55bc6a330f36409cad"}, + {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e83fb1991e9d8982b3b36aea1e7ad27ea0ce18c14d054c7a404d68b0319eebb"}, + {file = "aiohttp-3.11.13-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4586a68730bd2f2b04a83e83f79d271d8ed13763f64b75920f18a3a677b9a7f0"}, + {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fe4eb0e7f50cdb99b26250d9328faef30b1175a5dbcfd6d0578d18456bac567"}, + {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:2a8a6bc19818ac3e5596310ace5aa50d918e1ebdcc204dc96e2f4d505d51740c"}, + {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:7f27eec42f6c3c1df09cfc1f6786308f8b525b8efaaf6d6bd76c1f52c6511f6a"}, + {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:2a4a13dfbb23977a51853b419141cd0a9b9573ab8d3a1455c6e63561387b52ff"}, + {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:02876bf2f69b062584965507b07bc06903c2dc93c57a554b64e012d636952654"}, + {file = "aiohttp-3.11.13-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b992778d95b60a21c4d8d4a5f15aaab2bd3c3e16466a72d7f9bfd86e8cea0d4b"}, + {file = "aiohttp-3.11.13-cp313-cp313-win32.whl", hash = "sha256:507ab05d90586dacb4f26a001c3abf912eb719d05635cbfad930bdbeb469b36c"}, + {file = "aiohttp-3.11.13-cp313-cp313-win_amd64.whl", hash = "sha256:5ceb81a4db2decdfa087381b5fc5847aa448244f973e5da232610304e199e7b2"}, + {file = "aiohttp-3.11.13-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:51c3ff9c7a25f3cad5c09d9aacbc5aefb9267167c4652c1eb737989b554fe278"}, + {file = "aiohttp-3.11.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:e271beb2b1dabec5cd84eb488bdabf9758d22ad13471e9c356be07ad139b3012"}, + {file = "aiohttp-3.11.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0e9eb7e5764abcb49f0e2bd8f5731849b8728efbf26d0cac8e81384c95acec3f"}, + {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:baae005092e3f200de02699314ac8933ec20abf998ec0be39448f6605bce93df"}, + {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1982c98ac62c132d2b773d50e2fcc941eb0b8bad3ec078ce7e7877c4d5a2dce7"}, + {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2b25b2eeb35707113b2d570cadc7c612a57f1c5d3e7bb2b13870fe284e08fc0"}, + {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b27961d65639128336b7a7c3f0046dcc62a9443d5ef962e3c84170ac620cec47"}, + {file = "aiohttp-3.11.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a01fe9f1e05025eacdd97590895e2737b9f851d0eb2e017ae9574d9a4f0b6252"}, + {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fa1fb1b61881c8405829c50e9cc5c875bfdbf685edf57a76817dfb50643e4a1a"}, + {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:25de43bb3cf83ad83efc8295af7310219af6dbe4c543c2e74988d8e9c8a2a917"}, + {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:fe7065e2215e4bba63dc00db9ae654c1ba3950a5fff691475a32f511142fcddb"}, + {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:7836587eef675a17d835ec3d98a8c9acdbeb2c1d72b0556f0edf4e855a25e9c1"}, + {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:85fa0b18558eb1427090912bd456a01f71edab0872f4e0f9e4285571941e4090"}, + {file = "aiohttp-3.11.13-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a86dc177eb4c286c19d1823ac296299f59ed8106c9536d2b559f65836e0fb2c6"}, + {file = "aiohttp-3.11.13-cp39-cp39-win32.whl", hash = "sha256:684eea71ab6e8ade86b9021bb62af4bf0881f6be4e926b6b5455de74e420783a"}, + {file = "aiohttp-3.11.13-cp39-cp39-win_amd64.whl", hash = "sha256:82c249f2bfa5ecbe4a1a7902c81c0fba52ed9ebd0176ab3047395d02ad96cfcb"}, + {file = "aiohttp-3.11.13.tar.gz", hash = "sha256:8ce789231404ca8fff7f693cdce398abf6d90fd5dae2b1847477196c243b1fbb"}, ] [package.dependencies] @@ -773,13 +804,13 @@ files = [ [[package]] name = "decorator" -version = "5.1.1" +version = "5.2.1" description = "Decorators for Humans" optional = false -python-versions = ">=3.5" +python-versions = ">=3.8" files = [ - {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, - {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, + {file = "decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a"}, + {file = "decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360"}, ] [[package]] @@ -1499,13 +1530,13 @@ pyreadline3 = {version = "*", markers = "sys_platform == \"win32\" and python_ve [[package]] name = "identify" -version = "2.6.7" +version = "2.6.8" description = "File identification library for Python" optional = false python-versions = ">=3.9" files = [ - {file = "identify-2.6.7-py2.py3-none-any.whl", hash = "sha256:155931cb617a401807b09ecec6635d6c692d180090a1cedca8ef7d58ba5b6aa0"}, - {file = "identify-2.6.7.tar.gz", hash = "sha256:3fa266b42eba321ee0b2bb0936a6a6b9e36a1351cbb69055b3082f4193035684"}, + {file = "identify-2.6.8-py2.py3-none-any.whl", hash = "sha256:83657f0f766a3c8d0eaea16d4ef42494b39b34629a4b3192a9d020d349b3e255"}, + {file = "identify-2.6.8.tar.gz", hash = "sha256:61491417ea2c0c5c670484fd8abbb34de34cdae1e5f39a73ee65e48e4bb663fc"}, ] [package.extras] @@ -2617,13 +2648,13 @@ min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-imp [[package]] name = "mkdocs-autorefs" -version = "1.3.1" +version = "1.4.0" description = "Automatically link across pages in MkDocs." optional = false python-versions = ">=3.9" files = [ - {file = "mkdocs_autorefs-1.3.1-py3-none-any.whl", hash = "sha256:18c504ae4d3ee7f344369bb26cb31d4105569ee252aab7d75ec2734c2c8b0474"}, - {file = "mkdocs_autorefs-1.3.1.tar.gz", hash = "sha256:a6d30cbcccae336d622a66c2418a3c92a8196b69782774529ad441abb23c0902"}, + {file = "mkdocs_autorefs-1.4.0-py3-none-any.whl", hash = "sha256:bad19f69655878d20194acd0162e29a89c3f7e6365ffe54e72aa3fd1072f240d"}, + {file = "mkdocs_autorefs-1.4.0.tar.gz", hash = "sha256:a9c0aa9c90edbce302c09d050a3c4cb7c76f8b7b2c98f84a7a05f53d00392156"}, ] [package.dependencies] @@ -3144,35 +3175,35 @@ test = ["pytest (>=7.2)", "pytest-cov (>=4.0)"] [[package]] name = "nh3" -version = "0.2.20" +version = "0.2.21" description = "Python binding to Ammonia HTML sanitizer Rust crate" optional = false python-versions = ">=3.8" files = [ - {file = "nh3-0.2.20-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:e1061a4ab6681f6bdf72b110eea0c4e1379d57c9de937db3be4202f7ad6043db"}, - {file = "nh3-0.2.20-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb4254b1dac4a1ee49919a5b3f1caf9803ea8dada1816d9e8289e63d3cd0dd9a"}, - {file = "nh3-0.2.20-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ae9cbd713524cdb81e64663d0d6aae26f678db9f2cd9db0bf162606f1f9f20c"}, - {file = "nh3-0.2.20-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e1f7370b4e14cc03f5ae141ef30a1caf81fa5787711f80be9081418dd9eb79d2"}, - {file = "nh3-0.2.20-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:ac4d27dc836a476efffc6eb661994426b8b805c951b29c9cf2ff36bc9ad58bc5"}, - {file = "nh3-0.2.20-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:4fd2e9248725ebcedac3997a8d3da0d90a12a28c9179c6ba51f1658938ac30d0"}, - {file = "nh3-0.2.20-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f7d564871833ddbe54df3aa59053b1110729d3a800cb7628ae8f42adb3d75208"}, - {file = "nh3-0.2.20-cp313-cp313t-win32.whl", hash = "sha256:d2a176fd4306b6f0f178a3f67fac91bd97a3a8d8fafb771c9b9ef675ba5c8886"}, - {file = "nh3-0.2.20-cp313-cp313t-win_amd64.whl", hash = "sha256:6ed834c68452a600f517dd3e1534dbfaff1f67f98899fecf139a055a25d99150"}, - {file = "nh3-0.2.20-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:76e2f603b30c02ff6456b233a83fc377dedab6a50947b04e960a6b905637b776"}, - {file = "nh3-0.2.20-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:181063c581defe683bd4bb78188ac9936d208aebbc74c7f7c16b6a32ae2ebb38"}, - {file = "nh3-0.2.20-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:231addb7643c952cd6d71f1c8702d703f8fe34afcb20becb3efb319a501a12d7"}, - {file = "nh3-0.2.20-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1b9a8340a0aab991c68a5ca938d35ef4a8a3f4bf1b455da8855a40bee1fa0ace"}, - {file = "nh3-0.2.20-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10317cd96fe4bbd4eb6b95f3920b71c902157ad44fed103fdcde43e3b8ee8be6"}, - {file = "nh3-0.2.20-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8698db4c04b140800d1a1cd3067fda399e36e1e2b8fc1fe04292a907350a3e9b"}, - {file = "nh3-0.2.20-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3eb04b9c3deb13c3a375ea39fd4a3c00d1f92e8fb2349f25f1e3e4506751774b"}, - {file = "nh3-0.2.20-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92f3f1c4f47a2c6f3ca7317b1d5ced05bd29556a75d3a4e2715652ae9d15c05d"}, - {file = "nh3-0.2.20-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ddefa9fd6794a87e37d05827d299d4b53a3ec6f23258101907b96029bfef138a"}, - {file = "nh3-0.2.20-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:ce3731c8f217685d33d9268362e5b4f770914e922bba94d368ab244a59a6c397"}, - {file = "nh3-0.2.20-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:09f037c02fc2c43b211ff1523de32801dcfb0918648d8e651c36ef890f1731ec"}, - {file = "nh3-0.2.20-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:813f1c8012dd64c990514b795508abb90789334f76a561fa0fd4ca32d2275330"}, - {file = "nh3-0.2.20-cp38-abi3-win32.whl", hash = "sha256:47b2946c0e13057855209daeffb45dc910bd0c55daf10190bb0b4b60e2999784"}, - {file = "nh3-0.2.20-cp38-abi3-win_amd64.whl", hash = "sha256:da87573f03084edae8eb87cfe811ec338606288f81d333c07d2a9a0b9b976c0b"}, - {file = "nh3-0.2.20.tar.gz", hash = "sha256:9705c42d7ff88a0bea546c82d7fe5e59135e3d3f057e485394f491248a1f8ed5"}, + {file = "nh3-0.2.21-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:fcff321bd60c6c5c9cb4ddf2554e22772bb41ebd93ad88171bbbb6f271255286"}, + {file = "nh3-0.2.21-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31eedcd7d08b0eae28ba47f43fd33a653b4cdb271d64f1aeda47001618348fde"}, + {file = "nh3-0.2.21-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d426d7be1a2f3d896950fe263332ed1662f6c78525b4520c8e9861f8d7f0d243"}, + {file = "nh3-0.2.21-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9d67709bc0d7d1f5797b21db26e7a8b3d15d21c9c5f58ccfe48b5328483b685b"}, + {file = "nh3-0.2.21-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:55823c5ea1f6b267a4fad5de39bc0524d49a47783e1fe094bcf9c537a37df251"}, + {file = "nh3-0.2.21-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:818f2b6df3763e058efa9e69677b5a92f9bc0acff3295af5ed013da544250d5b"}, + {file = "nh3-0.2.21-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:b3b5c58161e08549904ac4abd450dacd94ff648916f7c376ae4b2c0652b98ff9"}, + {file = "nh3-0.2.21-cp313-cp313t-win32.whl", hash = "sha256:637d4a10c834e1b7d9548592c7aad760611415fcd5bd346f77fd8a064309ae6d"}, + {file = "nh3-0.2.21-cp313-cp313t-win_amd64.whl", hash = "sha256:713d16686596e556b65e7f8c58328c2df63f1a7abe1277d87625dcbbc012ef82"}, + {file = "nh3-0.2.21-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a772dec5b7b7325780922dd904709f0f5f3a79fbf756de5291c01370f6df0967"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d002b648592bf3033adfd875a48f09b8ecc000abd7f6a8769ed86b6ccc70c759"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2a5174551f95f2836f2ad6a8074560f261cf9740a48437d6151fd2d4d7d617ab"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b8d55ea1fc7ae3633d758a92aafa3505cd3cc5a6e40470c9164d54dff6f96d42"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6ae319f17cd8960d0612f0f0ddff5a90700fa71926ca800e9028e7851ce44a6f"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:63ca02ac6f27fc80f9894409eb61de2cb20ef0a23740c7e29f9ec827139fa578"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5f77e62aed5c4acad635239ac1290404c7e940c81abe561fd2af011ff59f585"}, + {file = "nh3-0.2.21-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:087ffadfdcd497658c3adc797258ce0f06be8a537786a7217649fc1c0c60c293"}, + {file = "nh3-0.2.21-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:ac7006c3abd097790e611fe4646ecb19a8d7f2184b882f6093293b8d9b887431"}, + {file = "nh3-0.2.21-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:6141caabe00bbddc869665b35fc56a478eb774a8c1dfd6fba9fe1dfdf29e6efa"}, + {file = "nh3-0.2.21-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:20979783526641c81d2f5bfa6ca5ccca3d1e4472474b162c6256745fbfe31cd1"}, + {file = "nh3-0.2.21-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a7ea28cd49293749d67e4fcf326c554c83ec912cd09cd94aa7ec3ab1921c8283"}, + {file = "nh3-0.2.21-cp38-abi3-win32.whl", hash = "sha256:6c9c30b8b0d291a7c5ab0967ab200598ba33208f754f2f4920e9343bdd88f79a"}, + {file = "nh3-0.2.21-cp38-abi3-win_amd64.whl", hash = "sha256:bb0014948f04d7976aabae43fcd4cb7f551f9f8ce785a4c9ef66e6c2590f8629"}, + {file = "nh3-0.2.21.tar.gz", hash = "sha256:4990e7ee6a55490dbf00d61a6f476c9a3258e31e711e13713b2ea7d6616f670e"}, ] [[package]] @@ -4282,93 +4313,109 @@ wcwidth = "*" [[package]] name = "propcache" -version = "0.2.1" +version = "0.3.0" description = "Accelerated property cache" optional = false python-versions = ">=3.9" files = [ - {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6"}, - {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2"}, - {file = "propcache-0.2.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634"}, - {file = "propcache-0.2.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034"}, - {file = "propcache-0.2.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b"}, - {file = "propcache-0.2.1-cp310-cp310-win32.whl", hash = "sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4"}, - {file = "propcache-0.2.1-cp310-cp310-win_amd64.whl", hash = "sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717"}, - {file = "propcache-0.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af"}, - {file = "propcache-0.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca"}, - {file = "propcache-0.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e"}, - {file = "propcache-0.2.1-cp311-cp311-win32.whl", hash = "sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034"}, - {file = "propcache-0.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0"}, - {file = "propcache-0.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24"}, - {file = "propcache-0.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6"}, - {file = "propcache-0.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518"}, - {file = "propcache-0.2.1-cp312-cp312-win32.whl", hash = "sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246"}, - {file = "propcache-0.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9"}, - {file = "propcache-0.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052"}, - {file = "propcache-0.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f"}, - {file = "propcache-0.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30"}, - {file = "propcache-0.2.1-cp313-cp313-win32.whl", hash = "sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6"}, - {file = "propcache-0.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1"}, - {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541"}, - {file = "propcache-0.2.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e"}, - {file = "propcache-0.2.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16"}, - {file = "propcache-0.2.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04"}, - {file = "propcache-0.2.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587"}, - {file = "propcache-0.2.1-cp39-cp39-win32.whl", hash = "sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb"}, - {file = "propcache-0.2.1-cp39-cp39-win_amd64.whl", hash = "sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1"}, - {file = "propcache-0.2.1-py3-none-any.whl", hash = "sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54"}, - {file = "propcache-0.2.1.tar.gz", hash = "sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64"}, + {file = "propcache-0.3.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:efa44f64c37cc30c9f05932c740a8b40ce359f51882c70883cc95feac842da4d"}, + {file = "propcache-0.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2383a17385d9800b6eb5855c2f05ee550f803878f344f58b6e194de08b96352c"}, + {file = "propcache-0.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d3e7420211f5a65a54675fd860ea04173cde60a7cc20ccfbafcccd155225f8bc"}, + {file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3302c5287e504d23bb0e64d2a921d1eb4a03fb93a0a0aa3b53de059f5a5d737d"}, + {file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7e2e068a83552ddf7a39a99488bcba05ac13454fb205c847674da0352602082f"}, + {file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2d913d36bdaf368637b4f88d554fb9cb9d53d6920b9c5563846555938d5450bf"}, + {file = "propcache-0.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ee1983728964d6070ab443399c476de93d5d741f71e8f6e7880a065f878e0b9"}, + {file = "propcache-0.3.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:36ca5e9a21822cc1746023e88f5c0af6fce3af3b85d4520efb1ce4221bed75cc"}, + {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9ecde3671e62eeb99e977f5221abcf40c208f69b5eb986b061ccec317c82ebd0"}, + {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:d383bf5e045d7f9d239b38e6acadd7b7fdf6c0087259a84ae3475d18e9a2ae8b"}, + {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8cb625bcb5add899cb8ba7bf716ec1d3e8f7cdea9b0713fa99eadf73b6d4986f"}, + {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:5fa159dcee5dba00c1def3231c249cf261185189205073bde13797e57dd7540a"}, + {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:a7080b0159ce05f179cfac592cda1a82898ca9cd097dacf8ea20ae33474fbb25"}, + {file = "propcache-0.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ed7161bccab7696a473fe7ddb619c1d75963732b37da4618ba12e60899fefe4f"}, + {file = "propcache-0.3.0-cp310-cp310-win32.whl", hash = "sha256:bf0d9a171908f32d54f651648c7290397b8792f4303821c42a74e7805bfb813c"}, + {file = "propcache-0.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:42924dc0c9d73e49908e35bbdec87adedd651ea24c53c29cac103ede0ea1d340"}, + {file = "propcache-0.3.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9ddd49258610499aab83b4f5b61b32e11fce873586282a0e972e5ab3bcadee51"}, + {file = "propcache-0.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2578541776769b500bada3f8a4eeaf944530516b6e90c089aa368266ed70c49e"}, + {file = "propcache-0.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d8074c5dd61c8a3e915fa8fc04754fa55cfa5978200d2daa1e2d4294c1f136aa"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b58229a844931bca61b3a20efd2be2a2acb4ad1622fc026504309a6883686fbf"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e45377d5d6fefe1677da2a2c07b024a6dac782088e37c0b1efea4cfe2b1be19b"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ec5060592d83454e8063e487696ac3783cc48c9a329498bafae0d972bc7816c9"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15010f29fbed80e711db272909a074dc79858c6d28e2915704cfc487a8ac89c6"}, + {file = "propcache-0.3.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a254537b9b696ede293bfdbc0a65200e8e4507bc9f37831e2a0318a9b333c85c"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2b975528998de037dfbc10144b8aed9b8dd5a99ec547f14d1cb7c5665a43f075"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:19d36bb351ad5554ff20f2ae75f88ce205b0748c38b146c75628577020351e3c"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6032231d4a5abd67c7f71168fd64a47b6b451fbcb91c8397c2f7610e67683810"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:6985a593417cdbc94c7f9c3403747335e450c1599da1647a5af76539672464d3"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:6a1948df1bb1d56b5e7b0553c0fa04fd0e320997ae99689488201f19fa90d2e7"}, + {file = "propcache-0.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8319293e85feadbbfe2150a5659dbc2ebc4afdeaf7d98936fb9a2f2ba0d4c35c"}, + {file = "propcache-0.3.0-cp311-cp311-win32.whl", hash = "sha256:63f26258a163c34542c24808f03d734b338da66ba91f410a703e505c8485791d"}, + {file = "propcache-0.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:cacea77ef7a2195f04f9279297684955e3d1ae4241092ff0cfcef532bb7a1c32"}, + {file = "propcache-0.3.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e53d19c2bf7d0d1e6998a7e693c7e87300dd971808e6618964621ccd0e01fe4e"}, + {file = "propcache-0.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a61a68d630e812b67b5bf097ab84e2cd79b48c792857dc10ba8a223f5b06a2af"}, + {file = "propcache-0.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fb91d20fa2d3b13deea98a690534697742029f4fb83673a3501ae6e3746508b5"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67054e47c01b7b349b94ed0840ccae075449503cf1fdd0a1fdd98ab5ddc2667b"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:997e7b8f173a391987df40f3b52c423e5850be6f6df0dcfb5376365440b56667"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d663fd71491dde7dfdfc899d13a067a94198e90695b4321084c6e450743b8c7"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8884ba1a0fe7210b775106b25850f5e5a9dc3c840d1ae9924ee6ea2eb3acbfe7"}, + {file = "propcache-0.3.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa806bbc13eac1ab6291ed21ecd2dd426063ca5417dd507e6be58de20e58dfcf"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6f4d7a7c0aff92e8354cceca6fe223973ddf08401047920df0fcb24be2bd5138"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:9be90eebc9842a93ef8335291f57b3b7488ac24f70df96a6034a13cb58e6ff86"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bf15fc0b45914d9d1b706f7c9c4f66f2b7b053e9517e40123e137e8ca8958b3d"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5a16167118677d94bb48bfcd91e420088854eb0737b76ec374b91498fb77a70e"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:41de3da5458edd5678b0f6ff66691507f9885f5fe6a0fb99a5d10d10c0fd2d64"}, + {file = "propcache-0.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:728af36011bb5d344c4fe4af79cfe186729efb649d2f8b395d1572fb088a996c"}, + {file = "propcache-0.3.0-cp312-cp312-win32.whl", hash = "sha256:6b5b7fd6ee7b54e01759f2044f936dcf7dea6e7585f35490f7ca0420fe723c0d"}, + {file = "propcache-0.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:2d15bc27163cd4df433e75f546b9ac31c1ba7b0b128bfb1b90df19082466ff57"}, + {file = "propcache-0.3.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a2b9bf8c79b660d0ca1ad95e587818c30ccdb11f787657458d6f26a1ea18c568"}, + {file = "propcache-0.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b0c1a133d42c6fc1f5fbcf5c91331657a1ff822e87989bf4a6e2e39b818d0ee9"}, + {file = "propcache-0.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bb2f144c6d98bb5cbc94adeb0447cfd4c0f991341baa68eee3f3b0c9c0e83767"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1323cd04d6e92150bcc79d0174ce347ed4b349d748b9358fd2e497b121e03c8"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3b812b3cb6caacd072276ac0492d249f210006c57726b6484a1e1805b3cfeea0"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:742840d1d0438eb7ea4280f3347598f507a199a35a08294afdcc560c3739989d"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7c6e7e4f9167fddc438cd653d826f2222222564daed4116a02a184b464d3ef05"}, + {file = "propcache-0.3.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a94ffc66738da99232ddffcf7910e0f69e2bbe3a0802e54426dbf0714e1c2ffe"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:3c6ec957025bf32b15cbc6b67afe233c65b30005e4c55fe5768e4bb518d712f1"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:549722908de62aa0b47a78b90531c022fa6e139f9166be634f667ff45632cc92"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5d62c4f6706bff5d8a52fd51fec6069bef69e7202ed481486c0bc3874912c787"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:24c04f8fbf60094c531667b8207acbae54146661657a1b1be6d3ca7773b7a545"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:7c5f5290799a3f6539cc5e6f474c3e5c5fbeba74a5e1e5be75587746a940d51e"}, + {file = "propcache-0.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4fa0e7c9c3cf7c276d4f6ab9af8adddc127d04e0fcabede315904d2ff76db626"}, + {file = "propcache-0.3.0-cp313-cp313-win32.whl", hash = "sha256:ee0bd3a7b2e184e88d25c9baa6a9dc609ba25b76daae942edfb14499ac7ec374"}, + {file = "propcache-0.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:1c8f7d896a16da9455f882870a507567d4f58c53504dc2d4b1e1d386dfe4588a"}, + {file = "propcache-0.3.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:e560fd75aaf3e5693b91bcaddd8b314f4d57e99aef8a6c6dc692f935cc1e6bbf"}, + {file = "propcache-0.3.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:65a37714b8ad9aba5780325228598a5b16c47ba0f8aeb3dc0514701e4413d7c0"}, + {file = "propcache-0.3.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:07700939b2cbd67bfb3b76a12e1412405d71019df00ca5697ce75e5ef789d829"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7c0fdbdf6983526e269e5a8d53b7ae3622dd6998468821d660d0daf72779aefa"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:794c3dd744fad478b6232289c866c25406ecdfc47e294618bdf1697e69bd64a6"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4544699674faf66fb6b4473a1518ae4999c1b614f0b8297b1cef96bac25381db"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fddb8870bdb83456a489ab67c6b3040a8d5a55069aa6f72f9d872235fbc52f54"}, + {file = "propcache-0.3.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f857034dc68d5ceb30fb60afb6ff2103087aea10a01b613985610e007053a121"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:02df07041e0820cacc8f739510078f2aadcfd3fc57eaeeb16d5ded85c872c89e"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:f47d52fd9b2ac418c4890aad2f6d21a6b96183c98021f0a48497a904199f006e"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9ff4e9ecb6e4b363430edf2c6e50173a63e0820e549918adef70515f87ced19a"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:ecc2920630283e0783c22e2ac94427f8cca29a04cfdf331467d4f661f4072dac"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:c441c841e82c5ba7a85ad25986014be8d7849c3cfbdb6004541873505929a74e"}, + {file = "propcache-0.3.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6c929916cbdb540d3407c66f19f73387f43e7c12fa318a66f64ac99da601bcdf"}, + {file = "propcache-0.3.0-cp313-cp313t-win32.whl", hash = "sha256:0c3e893c4464ebd751b44ae76c12c5f5c1e4f6cbd6fbf67e3783cd93ad221863"}, + {file = "propcache-0.3.0-cp313-cp313t-win_amd64.whl", hash = "sha256:75e872573220d1ee2305b35c9813626e620768248425f58798413e9c39741f46"}, + {file = "propcache-0.3.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:03c091bb752349402f23ee43bb2bff6bd80ccab7c9df6b88ad4322258d6960fc"}, + {file = "propcache-0.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:46ed02532cb66612d42ae5c3929b5e98ae330ea0f3900bc66ec5f4862069519b"}, + {file = "propcache-0.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:11ae6a8a01b8a4dc79093b5d3ca2c8a4436f5ee251a9840d7790dccbd96cb649"}, + {file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df03cd88f95b1b99052b52b1bb92173229d7a674df0ab06d2b25765ee8404bce"}, + {file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:03acd9ff19021bd0567582ac88f821b66883e158274183b9e5586f678984f8fe"}, + {file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd54895e4ae7d32f1e3dd91261df46ee7483a735017dc6f987904f194aa5fd14"}, + {file = "propcache-0.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26a67e5c04e3119594d8cfae517f4b9330c395df07ea65eab16f3d559b7068fe"}, + {file = "propcache-0.3.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ee25f1ac091def37c4b59d192bbe3a206298feeb89132a470325bf76ad122a1e"}, + {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:58e6d2a5a7cb3e5f166fd58e71e9a4ff504be9dc61b88167e75f835da5764d07"}, + {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_armv7l.whl", hash = "sha256:be90c94570840939fecedf99fa72839aed70b0ced449b415c85e01ae67422c90"}, + {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:49ea05212a529c2caffe411e25a59308b07d6e10bf2505d77da72891f9a05641"}, + {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:119e244ab40f70a98c91906d4c1f4c5f2e68bd0b14e7ab0a06922038fae8a20f"}, + {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:507c5357a8d8b4593b97fb669c50598f4e6cccbbf77e22fa9598aba78292b4d7"}, + {file = "propcache-0.3.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:8526b0941ec5a40220fc4dfde76aed58808e2b309c03e9fa8e2260083ef7157f"}, + {file = "propcache-0.3.0-cp39-cp39-win32.whl", hash = "sha256:7cedd25e5f678f7738da38037435b340694ab34d424938041aa630d8bac42663"}, + {file = "propcache-0.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:bf4298f366ca7e1ad1d21bbb58300a6985015909964077afd37559084590c929"}, + {file = "propcache-0.3.0-py3-none-any.whl", hash = "sha256:67dda3c7325691c2081510e92c561f465ba61b975f481735aefdfc845d2cd043"}, + {file = "propcache-0.3.0.tar.gz", hash = "sha256:a8fd93de4e1d278046345f49e2238cdb298589325849b2645d4a94c53faeffc5"}, ] [[package]] @@ -4708,13 +4755,13 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pydantic-settings" -version = "2.7.1" +version = "2.8.0" description = "Settings management using Pydantic" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_settings-2.7.1-py3-none-any.whl", hash = "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd"}, - {file = "pydantic_settings-2.7.1.tar.gz", hash = "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93"}, + {file = "pydantic_settings-2.8.0-py3-none-any.whl", hash = "sha256:c782c7dc3fb40e97b238e713c25d26f64314aece2e91abcff592fcac15f71820"}, + {file = "pydantic_settings-2.8.0.tar.gz", hash = "sha256:88e2ca28f6e68ea102c99c3c401d6c9078e68a5df600e97b43891c34e089500a"}, ] [package.dependencies] @@ -5719,114 +5766,114 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "rpds-py" -version = "0.22.3" +version = "0.23.1" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.9" files = [ - {file = "rpds_py-0.22.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:6c7b99ca52c2c1752b544e310101b98a659b720b21db00e65edca34483259967"}, - {file = "rpds_py-0.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:be2eb3f2495ba669d2a985f9b426c1797b7d48d6963899276d22f23e33d47e37"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70eb60b3ae9245ddea20f8a4190bd79c705a22f8028aaf8bbdebe4716c3fab24"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4041711832360a9b75cfb11b25a6a97c8fb49c07b8bd43d0d02b45d0b499a4ff"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64607d4cbf1b7e3c3c8a14948b99345eda0e161b852e122c6bb71aab6d1d798c"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e69b0a0e2537f26d73b4e43ad7bc8c8efb39621639b4434b76a3de50c6966e"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc27863442d388870c1809a87507727b799c8460573cfbb6dc0eeaef5a11b5ec"}, - {file = "rpds_py-0.22.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e79dd39f1e8c3504be0607e5fc6e86bb60fe3584bec8b782578c3b0fde8d932c"}, - {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e0fa2d4ec53dc51cf7d3bb22e0aa0143966119f42a0c3e4998293a3dd2856b09"}, - {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:fda7cb070f442bf80b642cd56483b5548e43d366fe3f39b98e67cce780cded00"}, - {file = "rpds_py-0.22.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cff63a0272fcd259dcc3be1657b07c929c466b067ceb1c20060e8d10af56f5bf"}, - {file = "rpds_py-0.22.3-cp310-cp310-win32.whl", hash = "sha256:9bd7228827ec7bb817089e2eb301d907c0d9827a9e558f22f762bb690b131652"}, - {file = "rpds_py-0.22.3-cp310-cp310-win_amd64.whl", hash = "sha256:9beeb01d8c190d7581a4d59522cd3d4b6887040dcfc744af99aa59fef3e041a8"}, - {file = "rpds_py-0.22.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f"}, - {file = "rpds_py-0.22.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1"}, - {file = "rpds_py-0.22.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d"}, - {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648"}, - {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74"}, - {file = "rpds_py-0.22.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a"}, - {file = "rpds_py-0.22.3-cp311-cp311-win32.whl", hash = "sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64"}, - {file = "rpds_py-0.22.3-cp311-cp311-win_amd64.whl", hash = "sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c"}, - {file = "rpds_py-0.22.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e"}, - {file = "rpds_py-0.22.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15"}, - {file = "rpds_py-0.22.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059"}, - {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e"}, - {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61"}, - {file = "rpds_py-0.22.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7"}, - {file = "rpds_py-0.22.3-cp312-cp312-win32.whl", hash = "sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627"}, - {file = "rpds_py-0.22.3-cp312-cp312-win_amd64.whl", hash = "sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4"}, - {file = "rpds_py-0.22.3-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84"}, - {file = "rpds_py-0.22.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518"}, - {file = "rpds_py-0.22.3-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd"}, - {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2"}, - {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16"}, - {file = "rpds_py-0.22.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f"}, - {file = "rpds_py-0.22.3-cp313-cp313-win32.whl", hash = "sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de"}, - {file = "rpds_py-0.22.3-cp313-cp313-win_amd64.whl", hash = "sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9"}, - {file = "rpds_py-0.22.3-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b"}, - {file = "rpds_py-0.22.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3"}, - {file = "rpds_py-0.22.3-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130"}, - {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c"}, - {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b"}, - {file = "rpds_py-0.22.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333"}, - {file = "rpds_py-0.22.3-cp313-cp313t-win32.whl", hash = "sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730"}, - {file = "rpds_py-0.22.3-cp313-cp313t-win_amd64.whl", hash = "sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf"}, - {file = "rpds_py-0.22.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:378753b4a4de2a7b34063d6f95ae81bfa7b15f2c1a04a9518e8644e81807ebea"}, - {file = "rpds_py-0.22.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3445e07bf2e8ecfeef6ef67ac83de670358abf2996916039b16a218e3d95e97e"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b2513ba235829860b13faa931f3b6846548021846ac808455301c23a101689d"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eaf16ae9ae519a0e237a0f528fd9f0197b9bb70f40263ee57ae53c2b8d48aeb3"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:583f6a1993ca3369e0f80ba99d796d8e6b1a3a2a442dd4e1a79e652116413091"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4617e1915a539a0d9a9567795023de41a87106522ff83fbfaf1f6baf8e85437e"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c150c7a61ed4a4f4955a96626574e9baf1adf772c2fb61ef6a5027e52803543"}, - {file = "rpds_py-0.22.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2fa4331c200c2521512595253f5bb70858b90f750d39b8cbfd67465f8d1b596d"}, - {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:214b7a953d73b5e87f0ebece4a32a5bd83c60a3ecc9d4ec8f1dca968a2d91e99"}, - {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f47ad3d5f3258bd7058d2d506852217865afefe6153a36eb4b6928758041d831"}, - {file = "rpds_py-0.22.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:f276b245347e6e36526cbd4a266a417796fc531ddf391e43574cf6466c492520"}, - {file = "rpds_py-0.22.3-cp39-cp39-win32.whl", hash = "sha256:bbb232860e3d03d544bc03ac57855cd82ddf19c7a07651a7c0fdb95e9efea8b9"}, - {file = "rpds_py-0.22.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfbc454a2880389dbb9b5b398e50d439e2e58669160f27b60e5eca11f68ae17c"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:d48424e39c2611ee1b84ad0f44fb3b2b53d473e65de061e3f460fc0be5f1939d"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:24e8abb5878e250f2eb0d7859a8e561846f98910326d06c0d51381fed59357bd"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b232061ca880db21fa14defe219840ad9b74b6158adb52ddf0e87bead9e8493"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac0a03221cdb5058ce0167ecc92a8c89e8d0decdc9e99a2ec23380793c4dcb96"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb0c341fa71df5a4595f9501df4ac5abfb5a09580081dffbd1ddd4654e6e9123"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bf9db5488121b596dbfc6718c76092fda77b703c1f7533a226a5a9f65248f8ad"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8db6b5b2d4491ad5b6bdc2bc7c017eec108acbf4e6785f42a9eb0ba234f4c9"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b3d504047aba448d70cf6fa22e06cb09f7cbd761939fdd47604f5e007675c24e"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e61b02c3f7a1e0b75e20c3978f7135fd13cb6cf551bf4a6d29b999a88830a338"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:e35ba67d65d49080e8e5a1dd40101fccdd9798adb9b050ff670b7d74fa41c566"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:26fd7cac7dd51011a245f29a2cc6489c4608b5a8ce8d75661bb4a1066c52dfbe"}, - {file = "rpds_py-0.22.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:177c7c0fce2855833819c98e43c262007f42ce86651ffbb84f37883308cb0e7d"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bb47271f60660803ad11f4c61b42242b8c1312a31c98c578f79ef9387bbde21c"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:70fb28128acbfd264eda9bf47015537ba3fe86e40d046eb2963d75024be4d055"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44d61b4b7d0c2c9ac019c314e52d7cbda0ae31078aabd0f22e583af3e0d79723"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f0e260eaf54380380ac3808aa4ebe2d8ca28b9087cf411649f96bad6900c728"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b25bc607423935079e05619d7de556c91fb6adeae9d5f80868dde3468657994b"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fb6116dfb8d1925cbdb52595560584db42a7f664617a1f7d7f6e32f138cdf37d"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a63cbdd98acef6570c62b92a1e43266f9e8b21e699c363c0fef13bd530799c11"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2b8f60e1b739a74bab7e01fcbe3dddd4657ec685caa04681df9d562ef15b625f"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:2e8b55d8517a2fda8d95cb45d62a5a8bbf9dd0ad39c5b25c8833efea07b880ca"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:2de29005e11637e7a2361fa151f780ff8eb2543a0da1413bb951e9f14b699ef3"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:666ecce376999bf619756a24ce15bb14c5bfaf04bf00abc7e663ce17c3f34fe7"}, - {file = "rpds_py-0.22.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:5246b14ca64a8675e0a7161f7af68fe3e910e6b90542b4bfb5439ba752191df6"}, - {file = "rpds_py-0.22.3.tar.gz", hash = "sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d"}, + {file = "rpds_py-0.23.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2a54027554ce9b129fc3d633c92fa33b30de9f08bc61b32c053dc9b537266fed"}, + {file = "rpds_py-0.23.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b5ef909a37e9738d146519657a1aab4584018746a18f71c692f2f22168ece40c"}, + {file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ee9d6f0b38efb22ad94c3b68ffebe4c47865cdf4b17f6806d6c674e1feb4246"}, + {file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f7356a6da0562190558c4fcc14f0281db191cdf4cb96e7604c06acfcee96df15"}, + {file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9441af1d25aed96901f97ad83d5c3e35e6cd21a25ca5e4916c82d7dd0490a4fa"}, + {file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d8abf7896a91fb97e7977d1aadfcc2c80415d6dc2f1d0fca5b8d0df247248f3"}, + {file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1b08027489ba8fedde72ddd233a5ea411b85a6ed78175f40285bd401bde7466d"}, + {file = "rpds_py-0.23.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fee513135b5a58f3bb6d89e48326cd5aa308e4bcdf2f7d59f67c861ada482bf8"}, + {file = "rpds_py-0.23.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:35d5631ce0af26318dba0ae0ac941c534453e42f569011585cb323b7774502a5"}, + {file = "rpds_py-0.23.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:a20cb698c4a59c534c6701b1c24a968ff2768b18ea2991f886bd8985ce17a89f"}, + {file = "rpds_py-0.23.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e9c206a1abc27e0588cf8b7c8246e51f1a16a103734f7750830a1ccb63f557a"}, + {file = "rpds_py-0.23.1-cp310-cp310-win32.whl", hash = "sha256:d9f75a06ecc68f159d5d7603b734e1ff6daa9497a929150f794013aa9f6e3f12"}, + {file = "rpds_py-0.23.1-cp310-cp310-win_amd64.whl", hash = "sha256:f35eff113ad430b5272bbfc18ba111c66ff525828f24898b4e146eb479a2cdda"}, + {file = "rpds_py-0.23.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b79f5ced71efd70414a9a80bbbfaa7160da307723166f09b69773153bf17c590"}, + {file = "rpds_py-0.23.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c9e799dac1ffbe7b10c1fd42fe4cd51371a549c6e108249bde9cd1200e8f59b4"}, + {file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:721f9c4011b443b6e84505fc00cc7aadc9d1743f1c988e4c89353e19c4a968ee"}, + {file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f88626e3f5e57432e6191cd0c5d6d6b319b635e70b40be2ffba713053e5147dd"}, + {file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:285019078537949cecd0190f3690a0b0125ff743d6a53dfeb7a4e6787af154f5"}, + {file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b92f5654157de1379c509b15acec9d12ecf6e3bc1996571b6cb82a4302060447"}, + {file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e768267cbe051dd8d1c5305ba690bb153204a09bf2e3de3ae530de955f5b5580"}, + {file = "rpds_py-0.23.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c5334a71f7dc1160382d45997e29f2637c02f8a26af41073189d79b95d3321f1"}, + {file = "rpds_py-0.23.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6adb81564af0cd428910f83fa7da46ce9ad47c56c0b22b50872bc4515d91966"}, + {file = "rpds_py-0.23.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:cafa48f2133d4daa028473ede7d81cd1b9f9e6925e9e4003ebdf77010ee02f35"}, + {file = "rpds_py-0.23.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0fced9fd4a07a1ded1bac7e961ddd9753dd5d8b755ba8e05acba54a21f5f1522"}, + {file = "rpds_py-0.23.1-cp311-cp311-win32.whl", hash = "sha256:243241c95174b5fb7204c04595852fe3943cc41f47aa14c3828bc18cd9d3b2d6"}, + {file = "rpds_py-0.23.1-cp311-cp311-win_amd64.whl", hash = "sha256:11dd60b2ffddba85715d8a66bb39b95ddbe389ad2cfcf42c833f1bcde0878eaf"}, + {file = "rpds_py-0.23.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3902df19540e9af4cc0c3ae75974c65d2c156b9257e91f5101a51f99136d834c"}, + {file = "rpds_py-0.23.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:66f8d2a17e5838dd6fb9be6baaba8e75ae2f5fa6b6b755d597184bfcd3cb0eba"}, + {file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:112b8774b0b4ee22368fec42749b94366bd9b536f8f74c3d4175d4395f5cbd31"}, + {file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e0df046f2266e8586cf09d00588302a32923eb6386ced0ca5c9deade6af9a149"}, + {file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0f3288930b947cbebe767f84cf618d2cbe0b13be476e749da0e6a009f986248c"}, + {file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ce473a2351c018b06dd8d30d5da8ab5a0831056cc53b2006e2a8028172c37ce5"}, + {file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d550d7e9e7d8676b183b37d65b5cd8de13676a738973d330b59dc8312df9c5dc"}, + {file = "rpds_py-0.23.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e14f86b871ea74c3fddc9a40e947d6a5d09def5adc2076ee61fb910a9014fb35"}, + {file = "rpds_py-0.23.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1bf5be5ba34e19be579ae873da515a2836a2166d8d7ee43be6ff909eda42b72b"}, + {file = "rpds_py-0.23.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d7031d493c4465dbc8d40bd6cafefef4bd472b17db0ab94c53e7909ee781b9ef"}, + {file = "rpds_py-0.23.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:55ff4151cfd4bc635e51cfb1c59ac9f7196b256b12e3a57deb9e5742e65941ad"}, + {file = "rpds_py-0.23.1-cp312-cp312-win32.whl", hash = "sha256:a9d3b728f5a5873d84cba997b9d617c6090ca5721caaa691f3b1a78c60adc057"}, + {file = "rpds_py-0.23.1-cp312-cp312-win_amd64.whl", hash = "sha256:b03a8d50b137ee758e4c73638b10747b7c39988eb8e6cd11abb7084266455165"}, + {file = "rpds_py-0.23.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:4caafd1a22e5eaa3732acb7672a497123354bef79a9d7ceed43387d25025e935"}, + {file = "rpds_py-0.23.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:178f8a60fc24511c0eb756af741c476b87b610dba83270fce1e5a430204566a4"}, + {file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c632419c3870507ca20a37c8f8f5352317aca097639e524ad129f58c125c61c6"}, + {file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:698a79d295626ee292d1730bc2ef6e70a3ab135b1d79ada8fde3ed0047b65a10"}, + {file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:271fa2184cf28bdded86bb6217c8e08d3a169fe0bbe9be5e8d96e8476b707122"}, + {file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b91cceb5add79ee563bd1f70b30896bd63bc5f78a11c1f00a1e931729ca4f1f4"}, + {file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a6cb95074777f1ecda2ca4fa7717caa9ee6e534f42b7575a8f0d4cb0c24013"}, + {file = "rpds_py-0.23.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:50fb62f8d8364978478b12d5f03bf028c6bc2af04082479299139dc26edf4c64"}, + {file = "rpds_py-0.23.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:c8f7e90b948dc9dcfff8003f1ea3af08b29c062f681c05fd798e36daa3f7e3e8"}, + {file = "rpds_py-0.23.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:5b98b6c953e5c2bda51ab4d5b4f172617d462eebc7f4bfdc7c7e6b423f6da957"}, + {file = "rpds_py-0.23.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2893d778d4671ee627bac4037a075168b2673c57186fb1a57e993465dbd79a93"}, + {file = "rpds_py-0.23.1-cp313-cp313-win32.whl", hash = "sha256:2cfa07c346a7ad07019c33fb9a63cf3acb1f5363c33bc73014e20d9fe8b01cdd"}, + {file = "rpds_py-0.23.1-cp313-cp313-win_amd64.whl", hash = "sha256:3aaf141d39f45322e44fc2c742e4b8b4098ead5317e5f884770c8df0c332da70"}, + {file = "rpds_py-0.23.1-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:759462b2d0aa5a04be5b3e37fb8183615f47014ae6b116e17036b131985cb731"}, + {file = "rpds_py-0.23.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:3e9212f52074fc9d72cf242a84063787ab8e21e0950d4d6709886fb62bcb91d5"}, + {file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e9f3a3ac919406bc0414bbbd76c6af99253c507150191ea79fab42fdb35982a"}, + {file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c04ca91dda8a61584165825907f5c967ca09e9c65fe8966ee753a3f2b019fe1e"}, + {file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4ab923167cfd945abb9b51a407407cf19f5bee35001221f2911dc85ffd35ff4f"}, + {file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ed6f011bedca8585787e5082cce081bac3d30f54520097b2411351b3574e1219"}, + {file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6959bb9928c5c999aba4a3f5a6799d571ddc2c59ff49917ecf55be2bbb4e3722"}, + {file = "rpds_py-0.23.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1ed7de3c86721b4e83ac440751329ec6a1102229aa18163f84c75b06b525ad7e"}, + {file = "rpds_py-0.23.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5fb89edee2fa237584e532fbf78f0ddd1e49a47c7c8cfa153ab4849dc72a35e6"}, + {file = "rpds_py-0.23.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:7e5413d2e2d86025e73f05510ad23dad5950ab8417b7fc6beaad99be8077138b"}, + {file = "rpds_py-0.23.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d31ed4987d72aabdf521eddfb6a72988703c091cfc0064330b9e5f8d6a042ff5"}, + {file = "rpds_py-0.23.1-cp313-cp313t-win32.whl", hash = "sha256:f3429fb8e15b20961efca8c8b21432623d85db2228cc73fe22756c6637aa39e7"}, + {file = "rpds_py-0.23.1-cp313-cp313t-win_amd64.whl", hash = "sha256:d6f6512a90bd5cd9030a6237f5346f046c6f0e40af98657568fa45695d4de59d"}, + {file = "rpds_py-0.23.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:09cd7dbcb673eb60518231e02874df66ec1296c01a4fcd733875755c02014b19"}, + {file = "rpds_py-0.23.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c6760211eee3a76316cf328f5a8bd695b47b1626d21c8a27fb3b2473a884d597"}, + {file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72e680c1518733b73c994361e4b06441b92e973ef7d9449feec72e8ee4f713da"}, + {file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ae28144c1daa61366205d32abd8c90372790ff79fc60c1a8ad7fd3c8553a600e"}, + {file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c698d123ce5d8f2d0cd17f73336615f6a2e3bdcedac07a1291bb4d8e7d82a05a"}, + {file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98b257ae1e83f81fb947a363a274c4eb66640212516becaff7bef09a5dceacaa"}, + {file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c9ff044eb07c8468594d12602291c635da292308c8c619244e30698e7fc455a"}, + {file = "rpds_py-0.23.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7938c7b0599a05246d704b3f5e01be91a93b411d0d6cc62275f025293b8a11ce"}, + {file = "rpds_py-0.23.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:e9cb79ecedfc156c0692257ac7ed415243b6c35dd969baa461a6888fc79f2f07"}, + {file = "rpds_py-0.23.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:7b77e07233925bd33fc0022b8537774423e4c6680b6436316c5075e79b6384f4"}, + {file = "rpds_py-0.23.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:a970bfaf130c29a679b1d0a6e0f867483cea455ab1535fb427566a475078f27f"}, + {file = "rpds_py-0.23.1-cp39-cp39-win32.whl", hash = "sha256:4233df01a250b3984465faed12ad472f035b7cd5240ea3f7c76b7a7016084495"}, + {file = "rpds_py-0.23.1-cp39-cp39-win_amd64.whl", hash = "sha256:c617d7453a80e29d9973b926983b1e700a9377dbe021faa36041c78537d7b08c"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:c1f8afa346ccd59e4e5630d5abb67aba6a9812fddf764fd7eb11f382a345f8cc"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fad784a31869747df4ac968a351e070c06ca377549e4ace94775aaa3ab33ee06"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5a96fcac2f18e5a0a23a75cd27ce2656c66c11c127b0318e508aab436b77428"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3e77febf227a1dc3220159355dba68faa13f8dca9335d97504abf428469fb18b"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26bb3e8de93443d55e2e748e9fd87deb5f8075ca7bc0502cfc8be8687d69a2ec"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db7707dde9143a67b8812c7e66aeb2d843fe33cc8e374170f4d2c50bd8f2472d"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eedaaccc9bb66581d4ae7c50e15856e335e57ef2734dbc5fd8ba3e2a4ab3cb6"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28358c54fffadf0ae893f6c1050e8f8853e45df22483b7fff2f6ab6152f5d8bf"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:633462ef7e61d839171bf206551d5ab42b30b71cac8f10a64a662536e057fdef"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a98f510d86f689fcb486dc59e6e363af04151e5260ad1bdddb5625c10f1e95f8"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:e0397dd0b3955c61ef9b22838144aa4bef6f0796ba5cc8edfc64d468b93798b4"}, + {file = "rpds_py-0.23.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:75307599f0d25bf6937248e5ac4e3bde5ea72ae6618623b86146ccc7845ed00b"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3614d280bf7aab0d3721b5ce0e73434acb90a2c993121b6e81a1c15c665298ac"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e5963ea87f88bddf7edd59644a35a0feecf75f8985430124c253612d4f7d27ae"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad76f44f70aac3a54ceb1813ca630c53415da3a24fd93c570b2dfb4856591017"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2c6ae11e6e93728d86aafc51ced98b1658a0080a7dd9417d24bfb955bb09c3c2"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc869af5cba24d45fb0399b0cfdbcefcf6910bf4dee5d74036a57cf5264b3ff4"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c76b32eb2ab650a29e423525e84eb197c45504b1c1e6e17b6cc91fcfeb1a4b1d"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4263320ed887ed843f85beba67f8b2d1483b5947f2dc73a8b068924558bfeace"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7f9682a8f71acdf59fd554b82b1c12f517118ee72c0f3944eda461606dfe7eb9"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:754fba3084b70162a6b91efceee8a3f06b19e43dac3f71841662053c0584209a"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:a1c66e71ecfd2a4acf0e4bd75e7a3605afa8f9b28a3b497e4ba962719df2be57"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:8d67beb6002441faef8251c45e24994de32c4c8686f7356a1f601ad7c466f7c3"}, + {file = "rpds_py-0.23.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a1e17d8dc8e57d8e0fd21f8f0f0a5211b3fa258b2e444c2053471ef93fe25a00"}, + {file = "rpds_py-0.23.1.tar.gz", hash = "sha256:7f3240dcfa14d198dba24b8b9cb3b108c06b68d45b7babd9eefc1038fdf7e707"}, ] [[package]] @@ -6166,13 +6213,13 @@ train = ["accelerate (>=0.20.3)", "datasets"] [[package]] name = "setuptools" -version = "75.8.0" +version = "75.8.1" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.9" files = [ - {file = "setuptools-75.8.0-py3-none-any.whl", hash = "sha256:e3982f444617239225d675215d51f6ba05f845d4eec313da4418fdbb56fb27e3"}, - {file = "setuptools-75.8.0.tar.gz", hash = "sha256:c5afc8f407c626b8313a86e10311dd3f661c6cd9c09d4bf8c15c0e11f9f2b0e6"}, + {file = "setuptools-75.8.1-py3-none-any.whl", hash = "sha256:3bc32c0b84c643299ca94e77f834730f126efd621de0cc1de64119e0e17dab1f"}, + {file = "setuptools-75.8.1.tar.gz", hash = "sha256:65fb779a8f28895242923582eadca2337285f0891c2c9e160754df917c3d2530"}, ] [package.extras] @@ -7781,9 +7828,9 @@ type = ["pytest-mypy"] ocrmac = ["ocrmac"] rapidocr = ["onnxruntime", "onnxruntime", "rapidocr-onnxruntime"] tesserocr = ["tesserocr"] -vlm = ["transformers", "transformers"] +vlm = ["accelerate", "transformers", "transformers"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "21c25b86d88aa138f7faa68fcba95af1d9a5edaa22550bd325997aed6eef44fe" +content-hash = "1d4718b694098b0676f1ad1606d769887e51fc29f604e5f4c83dd5e1c90557e7" diff --git a/pyproject.toml b/pyproject.toml index 7bf71c69..647d586f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,10 +58,14 @@ onnxruntime = [ { version = ">=1.7.0,<1.20.0", optional = true, markers = "python_version < '3.10'" }, { version = "^1.7.0", optional = true, markers = "python_version >= '3.10'" } ] + transformers = [ {markers = "sys_platform != 'darwin' or platform_machine != 'x86_64'", version = "^4.46.0", optional = true }, {markers = "sys_platform == 'darwin' and platform_machine == 'x86_64'", version = "~4.42.0", optional = true } ] +accelerate = [ + {markers = "sys_platform != 'darwin' or platform_machine != 'x86_64'", version = "^1.2.1", optional = true }, +] pillow = ">=10.0.0,<12.0.0" tqdm = "^4.65.0" @@ -124,7 +128,7 @@ torchvision = [ [tool.poetry.extras] tesserocr = ["tesserocr"] ocrmac = ["ocrmac"] -vlm = ["transformers"] +vlm = ["transformers", "accelerate"] rapidocr = ["rapidocr-onnxruntime", "onnxruntime"] [tool.poetry.scripts] From 37dd8c1cc7fc05095fe889eec78300647c946a42 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 26 Feb 2025 14:16:15 +0000 Subject: [PATCH 06/13] chore: bump version to 2.25.0 [skip ci] --- CHANGELOG.md | 16 ++++++++++++++++ pyproject.toml | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab946a87..500808ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,19 @@ +## [v2.25.0](https://github.com/DS4SD/docling/releases/tag/v2.25.0) - 2025-02-26 + +### Feature + +* [Experimental] Introduce VLM pipeline using HF AutoModelForVision2Seq, featuring SmolDocling model ([#1054](https://github.com/DS4SD/docling/issues/1054)) ([`3c9fe76`](https://github.com/DS4SD/docling/commit/3c9fe76b706b7714b25d49cb09050c42e3b8c849)) +* **cli:** Add option for downloading all models, refine help messages ([#1061](https://github.com/DS4SD/docling/issues/1061)) ([`ab683e4`](https://github.com/DS4SD/docling/commit/ab683e4fb6df4973d2efda04f00c269a2dc95f5b)) + +### Fix + +* Vlm using artifacts path ([#1057](https://github.com/DS4SD/docling/issues/1057)) ([`e197225`](https://github.com/DS4SD/docling/commit/e1972257399151503d60b4806976c8b9b6911aa8)) +* **html:** Parse text in div elements as TextItem ([#1041](https://github.com/DS4SD/docling/issues/1041)) ([`1b0ead6`](https://github.com/DS4SD/docling/commit/1b0ead69078030a0e4d25b51450ef2aa4a2e79fc)) + +### Documentation + +* Extend chunking docs, add FAQ on token limit ([#1053](https://github.com/DS4SD/docling/issues/1053)) ([`c84b973`](https://github.com/DS4SD/docling/commit/c84b973959a254db22ac9a7dc8810628e4808a2d)) + ## [v2.24.0](https://github.com/DS4SD/docling/releases/tag/v2.24.0) - 2025-02-20 ### Feature diff --git a/pyproject.toml b/pyproject.toml index 647d586f..afb98689 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "docling" -version = "2.24.0" # DO NOT EDIT, updated automatically +version = "2.25.0" # DO NOT EDIT, updated automatically description = "SDK and CLI for parsing PDF, DOCX, HTML, and more, to a unified document representation for powering downstream workflows such as gen AI applications." authors = ["Christoph Auer ", "Michele Dolfi ", "Maxim Lysak ", "Nikos Livathinos ", "Ahmed Nassar ", "Panos Vagenas ", "Peter Staar "] license = "MIT" From de7b963b09a34916f0a8d99649269aeb37db1408 Mon Sep 17 00:00:00 2001 From: Cesar Berrospi Ramis <75900930+ceberam@users.noreply.github.com> Date: Thu, 27 Feb 2025 09:46:57 +0100 Subject: [PATCH 07/13] fix(html): use 'start' attribute when parsing ordered lists from HTML docs (#1062) * fix(html): use 'start' attribute in ordered lists When parsing ordered lists in HTML, take into account the 'start' attribute if it exists. Signed-off-by: Cesar Berrospi Ramis <75900930+ceberam@users.noreply.github.com> * chore(html): reduce verbosity in HTML backend Signed-off-by: Cesar Berrospi Ramis <75900930+ceberam@users.noreply.github.com> --------- Signed-off-by: Cesar Berrospi Ramis <75900930+ceberam@users.noreply.github.com> --- docling/backend/html_backend.py | 24 +++++++++++--- tests/test_backend_html.py | 58 ++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/docling/backend/html_backend.py b/docling/backend/html_backend.py index 00ef05b4..f2320693 100644 --- a/docling/backend/html_backend.py +++ b/docling/backend/html_backend.py @@ -256,10 +256,16 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): parent=self.parents[self.level], name="list", label=GroupLabel.LIST ) elif element.name == "ol": + start_attr = element.get("start") + start: int = ( + int(start_attr) + if isinstance(start_attr, str) and start_attr.isnumeric() + else 1 + ) # create a list group self.parents[self.level + 1] = doc.add_group( parent=self.parents[self.level], - name="ordered list", + name="ordered list" + (f" start {start}" if start != 1 else ""), label=GroupLabel.ORDERED_LIST, ) self.level += 1 @@ -270,15 +276,23 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): self.level -= 1 def handle_list_item(self, element: Tag, doc: DoclingDocument) -> None: - """Handles listitem tags (li).""" + """Handles list item tags (li).""" nested_list = element.find(["ul", "ol"]) parent = self.parents[self.level] if parent is None: - _log.warning(f"list-item has no parent in DoclingDocument: {element}") + _log.debug(f"list-item has no parent in DoclingDocument: {element}") return parent_label: str = parent.label index_in_list = len(parent.children) + 1 + if ( + parent_label == GroupLabel.ORDERED_LIST + and isinstance(parent, GroupItem) + and parent.name + ): + start_in_list: str = parent.name.split(" ")[-1] + start: int = int(start_in_list) if start_in_list.isnumeric() else 1 + index_in_list += start - 1 if nested_list: # Text in list item can be hidden within hierarchy, hence @@ -324,13 +338,13 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): parent=parent, ) else: - _log.warning(f"list-item has no text: {element}") + _log.debug(f"list-item has no text: {element}") @staticmethod def parse_table_data(element: Tag) -> Optional[TableData]: nested_tables = element.find("table") if nested_tables is not None: - _log.warning("Skipping nested table.") + _log.debug("Skipping nested table.") return None # Count the number of rows (number of elements) diff --git a/tests/test_backend_html.py b/tests/test_backend_html.py index 6c1db062..a04ae219 100644 --- a/tests/test_backend_html.py +++ b/tests/test_backend_html.py @@ -1,4 +1,4 @@ -import os +from io import BytesIO from pathlib import Path from docling.backend.html_backend import HTMLDocumentBackend @@ -41,6 +41,62 @@ def test_heading_levels(): assert found_lvl_2 and found_lvl_3 +def test_ordered_lists(): + test_set: list[tuple[bytes, str]] = [] + + test_set.append( + ( + b"
  1. 1st item
  2. 2nd item
", + "1. 1st item\n2. 2nd item", + ) + ) + test_set.append( + ( + b'
  1. 1st item
  2. 2nd item
', + "1. 1st item\n2. 2nd item", + ) + ) + test_set.append( + ( + b'
  1. 1st item
  2. 2nd item
', + "2. 1st item\n3. 2nd item", + ) + ) + test_set.append( + ( + b'
  1. 1st item
  2. 2nd item
', + "0. 1st item\n1. 2nd item", + ) + ) + test_set.append( + ( + b'
  1. 1st item
  2. 2nd item
', + "1. 1st item\n2. 2nd item", + ) + ) + test_set.append( + ( + b'
  1. 1st item
  2. 2nd item
', + "1. 1st item\n2. 2nd item", + ) + ) + + for pair in test_set: + in_doc = InputDocument( + path_or_stream=BytesIO(pair[0]), + format=InputFormat.HTML, + backend=HTMLDocumentBackend, + filename="test", + ) + backend = HTMLDocumentBackend( + in_doc=in_doc, + path_or_stream=BytesIO(pair[0]), + ) + doc: DoclingDocument = backend.convert() + assert doc + assert doc.export_to_markdown() == pair[1] + + def get_html_paths(): # Define the directory you want to search From db3ceefd4ae6251a97e333bcb03051698b3fa71a Mon Sep 17 00:00:00 2001 From: Panos Vagenas <35837085+vagenas@users.noreply.github.com> Date: Fri, 28 Feb 2025 14:54:46 +0100 Subject: [PATCH 08/13] docs: improve docs on token limit warning triggered by HybridChunker (#1077) Signed-off-by: Panos Vagenas --- docs/examples/hybrid_chunking.ipynb | 21 ++++++++++++++++++--- docs/faq.md | 15 +++++++++------ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/docs/examples/hybrid_chunking.ipynb b/docs/examples/hybrid_chunking.ipynb index 2b7861aa..6a5f5882 100644 --- a/docs/examples/hybrid_chunking.ipynb +++ b/docs/examples/hybrid_chunking.ipynb @@ -83,7 +83,15 @@ "cell_type": "code", "execution_count": 3, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Token indices sequence length is longer than the specified maximum sequence length for this model (531 > 512). Running this sequence through the model will result in indexing errors\n" + ] + } + ], "source": [ "from docling.chunking import HybridChunker\n", "\n", @@ -91,6 +99,13 @@ "chunk_iter = chunker.chunk(dl_doc=doc)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "> 👉 **NOTE**: As you see above, using the `HybridChunker` can sometimes lead to a warning from the transformers library, however this is a \"false alarm\" — for details check [here](https://ds4sd.github.io/docling/faq/#hybridchunker-triggers-warning-token-indices-sequence-length-is-longer-than-the-specified-maximum-sequence-length-for-this-model)." + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -337,11 +352,11 @@ "source": [ "for i, chunk in enumerate(chunks):\n", " print(f\"=== {i} ===\")\n", - " txt_tokens = len(tokenizer.tokenize(chunk.text, max_length=None))\n", + " txt_tokens = len(tokenizer.tokenize(chunk.text))\n", " print(f\"chunk.text ({txt_tokens} tokens):\\n{repr(chunk.text)}\")\n", "\n", " ser_txt = chunker.serialize(chunk=chunk)\n", - " ser_tokens = len(tokenizer.tokenize(ser_txt, max_length=None))\n", + " ser_tokens = len(tokenizer.tokenize(ser_txt))\n", " print(f\"chunker.serialize(chunk) ({ser_tokens} tokens):\\n{repr(ser_txt)}\")\n", "\n", " print()" diff --git a/docs/faq.md b/docs/faq.md index 5f54d863..ae57446f 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -150,7 +150,7 @@ This is a collection of FAQ collected from the user questions on Token indices sequence length is longer than the specified maximum sequence length for this model (530 > 512). Running this sequence through the model will result in indexing errors + > Token indices sequence length is longer than the specified maximum sequence length for this model (531 > 512). Running this sequence through the model will result in indexing errors This is a warning that is emitted by transformers, saying that actually *running this sequence through the model* will result in indexing errors, i.e. the problematic case is only if one indeed passes the particular sequence through the (embedding) model. @@ -163,14 +163,17 @@ This is a collection of FAQ collected from the user questions on max_len: - max_len = ser_tokens + ser_tokens = len(tokenizer.tokenize(ser_txt)) + if ser_tokens > chunk_max_len: + chunk_max_len = ser_tokens print(f"{i}\t{ser_tokens}\t{repr(ser_txt[:100])}...") - print(f"{max_len=}") + print(f"Longest chunk yielded: {chunk_max_len} tokens") + print(f"Model max length: {tokenizer.model_max_length}") ``` + Also see [docling#725](https://github.com/DS4SD/docling/issues/725). + Source: Issue [docling-core#119](https://github.com/DS4SD/docling-core/issues/119) From e25d557c06afd77f1bb2c1ac4d2ece4dffcd52bd Mon Sep 17 00:00:00 2001 From: "Peter W. J. Staar" <91719829+PeterStaar-IBM@users.noreply.github.com> Date: Sun, 2 Mar 2025 10:37:53 -0500 Subject: [PATCH 09/13] refactor: add the contentlayer to html-backend (#1040) * added the contentlayer to html-backend Signed-off-by: Peter Staar * updated the handle_image function Signed-off-by: Peter Staar * reformatted code of html backend Signed-off-by: Peter Staar * test(html): add more info if a test case fails Signed-off-by: Cesar Berrospi Ramis <75900930+ceberam@users.noreply.github.com> * refactor(html): put parsed item in body if doc has no header In case an HTML does not have any header tag, all parsed items are placed in DoclingDocument's body content layer. HTML paragraphs ('p' tags) are parsed as text items with paragraph label. Update test ground truth accoring to the changes above. Signed-off-by: Cesar Berrospi Ramis <75900930+ceberam@users.noreply.github.com> * chore: set TextItem label to 'text' instead of 'paragraph' Signed-off-by: Cesar Berrospi Ramis <75900930+ceberam@users.noreply.github.com> --------- Signed-off-by: Peter Staar Signed-off-by: Cesar Berrospi Ramis <75900930+ceberam@users.noreply.github.com> Co-authored-by: Cesar Berrospi Ramis <75900930+ceberam@users.noreply.github.com> --- docling/backend/html_backend.py | 76 +- .../docling_v2/example_01.html.itxt | 4 +- .../docling_v2/example_01.html.json | 4 +- .../docling_v2/example_02.html.itxt | 4 +- .../docling_v2/example_02.html.json | 4 +- .../docling_v2/example_03.html.itxt | 4 +- .../docling_v2/example_03.html.json | 4 +- .../docling_v2/example_06.html.itxt | 10 +- .../docling_v2/example_06.html.json | 10 +- .../docling_v2/wiki_duck.html.itxt | 905 ++++++++---------- .../docling_v2/wiki_duck.html.json | 244 ++--- .../groundtruth/docling_v2/wiki_duck.html.md | 59 -- tests/test_backend_html.py | 4 +- 13 files changed, 623 insertions(+), 709 deletions(-) diff --git a/docling/backend/html_backend.py b/docling/backend/html_backend.py index f2320693..d14b422f 100644 --- a/docling/backend/html_backend.py +++ b/docling/backend/html_backend.py @@ -15,6 +15,7 @@ from docling_core.types.doc import ( TableCell, TableData, ) +from docling_core.types.doc.document import ContentLayer from typing_extensions import override from docling.backend.abstract_backend import DeclarativeDocumentBackend @@ -66,7 +67,8 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): self.soup = BeautifulSoup(html_content, "html.parser") except Exception as e: raise RuntimeError( - f"Could not initialize HTML backend for file with hash {self.document_hash}." + "Could not initialize HTML backend for file with " + f"hash {self.document_hash}." ) from e @override @@ -109,14 +111,21 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): # TODO: remove style to avoid losing text from tags like i, b, span, ... for br in content("br"): br.replace_with(NavigableString("\n")) + + headers = content.find(["h1", "h2", "h3", "h4", "h5", "h6"]) + self.content_layer = ( + ContentLayer.BODY if headers is None else ContentLayer.FURNITURE + ) self.walk(content, doc) else: raise RuntimeError( - f"Cannot convert doc with {self.document_hash} because the backend failed to init." + f"Cannot convert doc with {self.document_hash} because the backend " + "failed to init." ) return doc def walk(self, tag: Tag, doc: DoclingDocument) -> None: + # Iterate over elements in the body of the document text: str = "" for element in tag.children: @@ -143,8 +152,9 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): if text and tag.name in ["div"]: doc.add_text( parent=self.parents[self.level], - label=DocItemLabel.PARAGRAPH, + label=DocItemLabel.TEXT, text=text, + content_layer=self.content_layer, ) text = "" @@ -166,7 +176,7 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): elif tag.name == "figure": self.handle_figure(tag, doc) elif tag.name == "img": - self.handle_image(doc) + self.handle_image(tag, doc) else: self.walk(tag, doc) @@ -197,12 +207,17 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): text = element.text.strip() if hlevel == 1: + self.content_layer = ContentLayer.BODY + for key in self.parents.keys(): self.parents[key] = None self.level = 1 self.parents[self.level] = doc.add_text( - parent=self.parents[0], label=DocItemLabel.TITLE, text=text + parent=self.parents[0], + label=DocItemLabel.TITLE, + text=text, + content_layer=self.content_layer, ) else: if hlevel > self.level: @@ -213,6 +228,7 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): name=f"header-{i}", label=GroupLabel.SECTION, parent=self.parents[i - 1], + content_layer=self.content_layer, ) self.level = hlevel @@ -228,6 +244,7 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): parent=self.parents[hlevel - 1], text=text, level=hlevel, + content_layer=self.content_layer, ) def handle_code(self, element: Tag, doc: DoclingDocument) -> None: @@ -236,16 +253,24 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): return text = element.text.strip() if text: - doc.add_code(parent=self.parents[self.level], text=text) + doc.add_code( + parent=self.parents[self.level], + text=text, + content_layer=self.content_layer, + ) def handle_paragraph(self, element: Tag, doc: DoclingDocument) -> None: """Handles paragraph tags (p).""" if element.text is None: return text = element.text.strip() - label = DocItemLabel.PARAGRAPH if text: - doc.add_text(parent=self.parents[self.level], label=label, text=text) + doc.add_text( + parent=self.parents[self.level], + label=DocItemLabel.TEXT, + text=text, + content_layer=self.content_layer, + ) def handle_list(self, element: Tag, doc: DoclingDocument) -> None: """Handles list tags (ul, ol) and their list items.""" @@ -253,7 +278,10 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): if element.name == "ul": # create a list group self.parents[self.level + 1] = doc.add_group( - parent=self.parents[self.level], name="list", label=GroupLabel.LIST + parent=self.parents[self.level], + name="list", + label=GroupLabel.LIST, + content_layer=self.content_layer, ) elif element.name == "ol": start_attr = element.get("start") @@ -267,6 +295,7 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): parent=self.parents[self.level], name="ordered list" + (f" start {start}" if start != 1 else ""), label=GroupLabel.ORDERED_LIST, + content_layer=self.content_layer, ) self.level += 1 @@ -315,6 +344,7 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): enumerated=enumerated, marker=marker, parent=parent, + content_layer=self.content_layer, ) self.level += 1 @@ -336,6 +366,7 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): enumerated=enumerated, marker=marker, parent=parent, + content_layer=self.content_layer, ) else: _log.debug(f"list-item has no text: {element}") @@ -439,7 +470,11 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): table_data = HTMLDocumentBackend.parse_table_data(element) if table_data is not None: - doc.add_table(data=table_data, parent=self.parents[self.level]) + doc.add_table( + data=table_data, + parent=self.parents[self.level], + content_layer=self.content_layer, + ) def get_list_text(self, list_element: Tag, level: int = 0) -> list[str]: """Recursively extract text from
    or
      with proper indentation.""" @@ -479,20 +514,33 @@ class HTMLDocumentBackend(DeclarativeDocumentBackend): contains_captions = element.find(["figcaption"]) if not isinstance(contains_captions, Tag): - doc.add_picture(parent=self.parents[self.level], caption=None) + doc.add_picture( + parent=self.parents[self.level], + caption=None, + content_layer=self.content_layer, + ) else: texts = [] for item in contains_captions: texts.append(item.text) fig_caption = doc.add_text( - label=DocItemLabel.CAPTION, text=("".join(texts)).strip() + label=DocItemLabel.CAPTION, + text=("".join(texts)).strip(), + content_layer=self.content_layer, ) doc.add_picture( parent=self.parents[self.level], caption=fig_caption, + content_layer=self.content_layer, ) - def handle_image(self, doc: DoclingDocument) -> None: + def handle_image(self, element: Tag, doc: DoclingDocument) -> None: """Handles image tags (img).""" - doc.add_picture(parent=self.parents[self.level], caption=None) + _log.debug(f"ignoring tags at the moment: {element}") + + doc.add_picture( + parent=self.parents[self.level], + caption=None, + content_layer=self.content_layer, + ) diff --git a/tests/data/groundtruth/docling_v2/example_01.html.itxt b/tests/data/groundtruth/docling_v2/example_01.html.itxt index 9b2277a3..fbd75125 100644 --- a/tests/data/groundtruth/docling_v2/example_01.html.itxt +++ b/tests/data/groundtruth/docling_v2/example_01.html.itxt @@ -1,8 +1,8 @@ item-0 at level 0: unspecified: group _root_ item-1 at level 1: title: Introduction - item-2 at level 2: paragraph: This is the first paragraph of the introduction. + item-2 at level 2: text: This is the first paragraph of the introduction. item-3 at level 2: section_header: Background - item-4 at level 3: paragraph: Some background information here. + item-4 at level 3: text: Some background information here. item-5 at level 3: picture item-6 at level 3: list: group list item-7 at level 4: list_item: First item in unordered list diff --git a/tests/data/groundtruth/docling_v2/example_01.html.json b/tests/data/groundtruth/docling_v2/example_01.html.json index c1f3d644..d5617892 100644 --- a/tests/data/groundtruth/docling_v2/example_01.html.json +++ b/tests/data/groundtruth/docling_v2/example_01.html.json @@ -88,7 +88,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "This is the first paragraph of the introduction.", "text": "This is the first paragraph of the introduction." @@ -126,7 +126,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Some background information here.", "text": "Some background information here." diff --git a/tests/data/groundtruth/docling_v2/example_02.html.itxt b/tests/data/groundtruth/docling_v2/example_02.html.itxt index 93f0352e..49ea71e8 100644 --- a/tests/data/groundtruth/docling_v2/example_02.html.itxt +++ b/tests/data/groundtruth/docling_v2/example_02.html.itxt @@ -1,8 +1,8 @@ item-0 at level 0: unspecified: group _root_ item-1 at level 1: title: Introduction - item-2 at level 2: paragraph: This is the first paragraph of the introduction. + item-2 at level 2: text: This is the first paragraph of the introduction. item-3 at level 2: section_header: Background - item-4 at level 3: paragraph: Some background information here. + item-4 at level 3: text: Some background information here. item-5 at level 3: list: group list item-6 at level 4: list_item: First item in unordered list item-7 at level 4: list_item: Second item in unordered list diff --git a/tests/data/groundtruth/docling_v2/example_02.html.json b/tests/data/groundtruth/docling_v2/example_02.html.json index cbe9227a..ebd5fb63 100644 --- a/tests/data/groundtruth/docling_v2/example_02.html.json +++ b/tests/data/groundtruth/docling_v2/example_02.html.json @@ -88,7 +88,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "This is the first paragraph of the introduction.", "text": "This is the first paragraph of the introduction." @@ -123,7 +123,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Some background information here.", "text": "Some background information here." diff --git a/tests/data/groundtruth/docling_v2/example_03.html.itxt b/tests/data/groundtruth/docling_v2/example_03.html.itxt index 5fce9389..5b31bf82 100644 --- a/tests/data/groundtruth/docling_v2/example_03.html.itxt +++ b/tests/data/groundtruth/docling_v2/example_03.html.itxt @@ -1,9 +1,9 @@ item-0 at level 0: unspecified: group _root_ item-1 at level 1: title: Example Document item-2 at level 2: section_header: Introduction - item-3 at level 3: paragraph: This is the first paragraph of the introduction. + item-3 at level 3: text: This is the first paragraph of the introduction. item-4 at level 2: section_header: Background - item-5 at level 3: paragraph: Some background information here. + item-5 at level 3: text: Some background information here. item-6 at level 3: list: group list item-7 at level 4: list_item: First item in unordered list item-8 at level 5: list: group list diff --git a/tests/data/groundtruth/docling_v2/example_03.html.json b/tests/data/groundtruth/docling_v2/example_03.html.json index 3e74dbfe..74b2837e 100644 --- a/tests/data/groundtruth/docling_v2/example_03.html.json +++ b/tests/data/groundtruth/docling_v2/example_03.html.json @@ -142,7 +142,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "This is the first paragraph of the introduction.", "text": "This is the first paragraph of the introduction." @@ -177,7 +177,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Some background information here.", "text": "Some background information here." diff --git a/tests/data/groundtruth/docling_v2/example_06.html.itxt b/tests/data/groundtruth/docling_v2/example_06.html.itxt index 2ecad16f..0cbdcf4e 100644 --- a/tests/data/groundtruth/docling_v2/example_06.html.itxt +++ b/tests/data/groundtruth/docling_v2/example_06.html.itxt @@ -1,7 +1,7 @@ item-0 at level 0: unspecified: group _root_ - item-1 at level 1: paragraph: This is a div with text. - item-2 at level 1: paragraph: This is another div with text. - item-3 at level 1: paragraph: This is a regular paragraph. - item-4 at level 1: paragraph: This is a third div + item-1 at level 1: text: This is a div with text. + item-2 at level 1: text: This is another div with text. + item-3 at level 1: text: This is a regular paragraph. + item-4 at level 1: text: This is a third div with a new line. - item-5 at level 1: paragraph: This is a fourth div with a bold paragraph. \ No newline at end of file + item-5 at level 1: text: This is a fourth div with a bold paragraph. \ No newline at end of file diff --git a/tests/data/groundtruth/docling_v2/example_06.html.json b/tests/data/groundtruth/docling_v2/example_06.html.json index 03ce776b..5873774e 100644 --- a/tests/data/groundtruth/docling_v2/example_06.html.json +++ b/tests/data/groundtruth/docling_v2/example_06.html.json @@ -46,7 +46,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "This is a div with text.", "text": "This is a div with text." @@ -58,7 +58,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "This is another div with text.", "text": "This is another div with text." @@ -70,7 +70,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "This is a regular paragraph.", "text": "This is a regular paragraph." @@ -82,7 +82,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "This is a third div\nwith a new line.", "text": "This is a third div\nwith a new line." @@ -94,7 +94,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "This is a fourth div with a bold paragraph.", "text": "This is a fourth div with a bold paragraph." diff --git a/tests/data/groundtruth/docling_v2/wiki_duck.html.itxt b/tests/data/groundtruth/docling_v2/wiki_duck.html.itxt index 4e22c090..1ac0bf64 100644 --- a/tests/data/groundtruth/docling_v2/wiki_duck.html.itxt +++ b/tests/data/groundtruth/docling_v2/wiki_duck.html.itxt @@ -1,491 +1,416 @@ item-0 at level 0: unspecified: group _root_ - item-1 at level 1: paragraph: Main menu - item-2 at level 1: paragraph: Navigation - item-3 at level 1: list: group list - item-4 at level 2: list_item: Main page - item-5 at level 2: list_item: Contents - item-6 at level 2: list_item: Current events - item-7 at level 2: list_item: Random article - item-8 at level 2: list_item: About Wikipedia - item-9 at level 2: list_item: Contact us - item-10 at level 1: paragraph: Contribute - item-11 at level 1: list: group list - item-12 at level 2: list_item: Help - item-13 at level 2: list_item: Learn to edit - item-14 at level 2: list_item: Community portal - item-15 at level 2: list_item: Recent changes - item-16 at level 2: list_item: Upload file - item-17 at level 1: picture - item-18 at level 1: picture - item-19 at level 1: picture - item-20 at level 1: list: group list - item-21 at level 1: list: group list - item-22 at level 2: list_item: Donate - item-23 at level 1: list: group list - item-24 at level 1: list: group list - item-25 at level 2: list_item: Create account - item-26 at level 2: list_item: Log in - item-27 at level 1: list: group list - item-28 at level 2: list_item: Create account - item-29 at level 2: list_item: Log in - item-30 at level 1: paragraph: Pages for logged out editors - item-31 at level 1: list: group list - item-32 at level 2: list_item: Contributions - item-33 at level 2: list_item: Talk - item-34 at level 1: section: group header-1 - item-35 at level 2: section_header: Contents - item-36 at level 3: list: group list - item-37 at level 4: list_item: (Top) - item-38 at level 4: list_item: 1 Etymology - item-39 at level 5: list: group list - item-40 at level 4: list_item: 2 Taxonomy - item-41 at level 5: list: group list - item-42 at level 4: list_item: 3 Morphology - item-43 at level 5: list: group list - item-44 at level 4: list_item: 4 Distribution and habitat - item-45 at level 5: list: group list - item-46 at level 4: list_item: 5 Behaviour Toggle Behaviour subsection - item-47 at level 5: list: group list - item-48 at level 6: list_item: 5.1 Feeding - item-49 at level 7: list: group list - item-50 at level 6: list_item: 5.2 Breeding - item-51 at level 7: list: group list - item-52 at level 6: list_item: 5.3 Communication - item-53 at level 7: list: group list - item-54 at level 6: list_item: 5.4 Predators - item-55 at level 7: list: group list - item-56 at level 4: list_item: 6 Relationship with humans Toggle Relationship with humans subsection - item-57 at level 5: list: group list - item-58 at level 6: list_item: 6.1 Hunting - item-59 at level 7: list: group list - item-60 at level 6: list_item: 6.2 Domestication - item-61 at level 7: list: group list - item-62 at level 6: list_item: 6.3 Heraldry - item-63 at level 7: list: group list - item-64 at level 6: list_item: 6.4 Cultural references - item-65 at level 7: list: group list - item-66 at level 4: list_item: 7 See also - item-67 at level 5: list: group list - item-68 at level 4: list_item: 8 Notes Toggle Notes subsection - item-69 at level 5: list: group list - item-70 at level 6: list_item: 8.1 Citations - item-71 at level 7: list: group list - item-72 at level 6: list_item: 8.2 Sources - item-73 at level 7: list: group list - item-74 at level 4: list_item: 9 External links - item-75 at level 5: list: group list - item-76 at level 1: title: Duck - item-77 at level 2: list: group list - item-78 at level 3: list_item: Acèh - item-79 at level 3: list_item: Afrikaans - item-80 at level 3: list_item: Alemannisch - item-81 at level 3: list_item: አማርኛ - item-82 at level 3: list_item: Ænglisc - item-83 at level 3: list_item: العربية - item-84 at level 3: list_item: Aragonés - item-85 at level 3: list_item: ܐܪܡܝܐ - item-86 at level 3: list_item: Armãneashti - item-87 at level 3: list_item: Asturianu - item-88 at level 3: list_item: Atikamekw - item-89 at level 3: list_item: Авар - item-90 at level 3: list_item: Aymar aru - item-91 at level 3: list_item: تۆرکجه - item-92 at level 3: list_item: Basa Bali - item-93 at level 3: list_item: বাংলা - item-94 at level 3: list_item: 閩南語 / Bân-lâm-gú - item-95 at level 3: list_item: Беларуская - item-96 at level 3: list_item: Беларуская (тарашкевіца) - item-97 at level 3: list_item: Bikol Central - item-98 at level 3: list_item: Български - item-99 at level 3: list_item: Brezhoneg - item-100 at level 3: list_item: Буряад - item-101 at level 3: list_item: Català - item-102 at level 3: list_item: Чӑвашла - item-103 at level 3: list_item: Čeština - item-104 at level 3: list_item: ChiShona - item-105 at level 3: list_item: Cymraeg - item-106 at level 3: list_item: Dagbanli - item-107 at level 3: list_item: Dansk - item-108 at level 3: list_item: Deitsch - item-109 at level 3: list_item: Deutsch - item-110 at level 3: list_item: डोटेली - item-111 at level 3: list_item: Ελληνικά - item-112 at level 3: list_item: Emiliàn e rumagnòl - item-113 at level 3: list_item: Español - item-114 at level 3: list_item: Esperanto - item-115 at level 3: list_item: Euskara - item-116 at level 3: list_item: فارسی - item-117 at level 3: list_item: Français - item-118 at level 3: list_item: Gaeilge - item-119 at level 3: list_item: Galego - item-120 at level 3: list_item: ГӀалгӀай - item-121 at level 3: list_item: 贛語 - item-122 at level 3: list_item: گیلکی - item-123 at level 3: list_item: 𐌲𐌿𐍄𐌹𐍃𐌺 - item-124 at level 3: list_item: गोंयची कोंकणी / Gõychi Konknni - item-125 at level 3: list_item: 客家語 / Hak-kâ-ngî - item-126 at level 3: list_item: 한국어 - item-127 at level 3: list_item: Hausa - item-128 at level 3: list_item: Հայերեն - item-129 at level 3: list_item: हिन्दी - item-130 at level 3: list_item: Hrvatski - item-131 at level 3: list_item: Ido - item-132 at level 3: list_item: Bahasa Indonesia - item-133 at level 3: list_item: Iñupiatun - item-134 at level 3: list_item: Íslenska - item-135 at level 3: list_item: Italiano - item-136 at level 3: list_item: עברית - item-137 at level 3: list_item: Jawa - item-138 at level 3: list_item: ಕನ್ನಡ - item-139 at level 3: list_item: Kapampangan - item-140 at level 3: list_item: ქართული - item-141 at level 3: list_item: कॉशुर / کٲشُر - item-142 at level 3: list_item: Қазақша - item-143 at level 3: list_item: Ikirundi - item-144 at level 3: list_item: Kongo - item-145 at level 3: list_item: Kreyòl ayisyen - item-146 at level 3: list_item: Кырык мары - item-147 at level 3: list_item: ລາວ - item-148 at level 3: list_item: Latina - item-149 at level 3: list_item: Latviešu - item-150 at level 3: list_item: Lietuvių - item-151 at level 3: list_item: Li Niha - item-152 at level 3: list_item: Ligure - item-153 at level 3: list_item: Limburgs - item-154 at level 3: list_item: Lingála - item-155 at level 3: list_item: Malagasy - item-156 at level 3: list_item: മലയാളം - item-157 at level 3: list_item: मराठी - item-158 at level 3: list_item: مازِرونی - item-159 at level 3: list_item: Bahasa Melayu - item-160 at level 3: list_item: ꯃꯤꯇꯩ ꯂꯣꯟ - item-161 at level 3: list_item: 閩東語 / Mìng-dĕ̤ng-ngṳ̄ - item-162 at level 3: list_item: Мокшень - item-163 at level 3: list_item: Монгол - item-164 at level 3: list_item: မြန်မာဘာသာ - item-165 at level 3: list_item: Nederlands - item-166 at level 3: list_item: Nedersaksies - item-167 at level 3: list_item: नेपाली - item-168 at level 3: list_item: नेपाल भाषा - item-169 at level 3: list_item: 日本語 - item-170 at level 3: list_item: Нохчийн - item-171 at level 3: list_item: Norsk nynorsk - item-172 at level 3: list_item: Occitan - item-173 at level 3: list_item: Oromoo - item-174 at level 3: list_item: ਪੰਜਾਬੀ - item-175 at level 3: list_item: Picard - item-176 at level 3: list_item: Plattdüütsch - item-177 at level 3: list_item: Polski - item-178 at level 3: list_item: Português - item-179 at level 3: list_item: Qırımtatarca - item-180 at level 3: list_item: Română - item-181 at level 3: list_item: Русский - item-182 at level 3: list_item: Саха тыла - item-183 at level 3: list_item: ᱥᱟᱱᱛᱟᱲᱤ - item-184 at level 3: list_item: Sardu - item-185 at level 3: list_item: Scots - item-186 at level 3: list_item: Seeltersk - item-187 at level 3: list_item: Shqip - item-188 at level 3: list_item: Sicilianu - item-189 at level 3: list_item: සිංහල - item-190 at level 3: list_item: Simple English - item-191 at level 3: list_item: سنڌي - item-192 at level 3: list_item: کوردی - item-193 at level 3: list_item: Српски / srpski - item-194 at level 3: list_item: Srpskohrvatski / српскохрватски - item-195 at level 3: list_item: Sunda - item-196 at level 3: list_item: Svenska - item-197 at level 3: list_item: Tagalog - item-198 at level 3: list_item: தமிழ் - item-199 at level 3: list_item: Taqbaylit - item-200 at level 3: list_item: Татарча / tatarça - item-201 at level 3: list_item: ไทย - item-202 at level 3: list_item: Türkçe - item-203 at level 3: list_item: Українська - item-204 at level 3: list_item: ئۇيغۇرچە / Uyghurche - item-205 at level 3: list_item: Vahcuengh - item-206 at level 3: list_item: Tiếng Việt - item-207 at level 3: list_item: Walon - item-208 at level 3: list_item: 文言 - item-209 at level 3: list_item: Winaray - item-210 at level 3: list_item: 吴语 - item-211 at level 3: list_item: 粵語 - item-212 at level 3: list_item: Žemaitėška - item-213 at level 3: list_item: 中文 - item-214 at level 2: list: group list - item-215 at level 3: list_item: Article - item-216 at level 3: list_item: Talk - item-217 at level 2: list: group list - item-218 at level 2: list: group list - item-219 at level 3: list_item: Read - item-220 at level 3: list_item: View source - item-221 at level 3: list_item: View history - item-222 at level 2: paragraph: Tools - item-223 at level 2: paragraph: Actions - item-224 at level 2: list: group list - item-225 at level 3: list_item: Read - item-226 at level 3: list_item: View source - item-227 at level 3: list_item: View history - item-228 at level 2: paragraph: General - item-229 at level 2: list: group list - item-230 at level 3: list_item: What links here - item-231 at level 3: list_item: Related changes - item-232 at level 3: list_item: Upload file - item-233 at level 3: list_item: Special pages - item-234 at level 3: list_item: Permanent link - item-235 at level 3: list_item: Page information - item-236 at level 3: list_item: Cite this page - item-237 at level 3: list_item: Get shortened URL - item-238 at level 3: list_item: Download QR code - item-239 at level 3: list_item: Wikidata item - item-240 at level 2: paragraph: Print/export - item-241 at level 2: list: group list - item-242 at level 3: list_item: Download as PDF - item-243 at level 3: list_item: Printable version - item-244 at level 2: paragraph: In other projects - item-245 at level 2: list: group list - item-246 at level 3: list_item: Wikimedia Commons - item-247 at level 3: list_item: Wikiquote - item-248 at level 2: paragraph: Appearance - item-249 at level 2: picture - item-250 at level 2: paragraph: From Wikipedia, the free encyclopedia - item-251 at level 2: paragraph: Common name for many species of bird - item-252 at level 2: paragraph: This article is about the bird. ... as a food, see . For other uses, see . - item-253 at level 2: paragraph: "Duckling" redirects here. For other uses, see . - item-254 at level 2: table with [13x2] - item-255 at level 2: paragraph: Duck is the common name for nume ... und in both fresh water and sea water. - item-256 at level 2: paragraph: Ducks are sometimes confused wit ... divers, grebes, gallinules and coots. - item-257 at level 2: section_header: Etymology - item-258 at level 3: paragraph: The word duck comes from Old Eng ... h duiken and German tauchen 'to dive'. - item-259 at level 3: picture - item-259 at level 4: caption: Pacific black duck displaying the characteristic upending "duck" - item-260 at level 3: paragraph: This word replaced Old English e ... nskrit ātí 'water bird', among others. - item-261 at level 3: paragraph: A duckling is a young duck in do ... , is sometimes labelled as a duckling. - item-262 at level 3: paragraph: A male is called a drake and the ... a duck, or in ornithology a hen.[3][4] - item-263 at level 3: picture - item-263 at level 4: caption: Male mallard. - item-264 at level 3: picture - item-264 at level 4: caption: Wood ducks. - item-265 at level 2: section_header: Taxonomy - item-266 at level 3: paragraph: All ducks belong to the biologic ... ationships between various species.[9] - item-267 at level 3: picture - item-267 at level 4: caption: Mallard landing in approach - item-268 at level 3: paragraph: In most modern classifications, ... all size and stiff, upright tails.[14] - item-269 at level 3: paragraph: A number of other species called ... shelducks in the tribe Tadornini.[15] - item-270 at level 2: section_header: Morphology - item-271 at level 3: picture - item-271 at level 4: caption: Male Mandarin duck - item-272 at level 3: paragraph: The overall body plan of ducks i ... is moult typically precedes migration. - item-273 at level 3: paragraph: The drakes of northern species o ... rkscrew shaped vagina to prevent rape. - item-274 at level 2: section_header: Distribution and habitat - item-275 at level 3: picture - item-275 at level 4: caption: Flying steamer ducks in Ushuaia, Argentina - item-276 at level 3: paragraph: Ducks have a cosmopolitan distri ... endemic to such far-flung islands.[21] - item-277 at level 3: picture - item-277 at level 4: caption: Female mallard in Cornwall, England - item-278 at level 3: paragraph: Some duck species, mainly those ... t form after localised heavy rain.[23] - item-279 at level 2: section_header: Behaviour - item-280 at level 3: section_header: Feeding - item-281 at level 4: picture - item-281 at level 5: caption: Pecten along the bill - item-282 at level 4: picture - item-282 at level 5: caption: Mallard duckling preening - item-283 at level 4: paragraph: Ducks eat food sources such as g ... amphibians, worms, and small molluscs. - item-284 at level 4: paragraph: Dabbling ducks feed on the surfa ... thers and to hold slippery food items. - item-285 at level 4: paragraph: Diving ducks and sea ducks forag ... ave more difficulty taking off to fly. - item-286 at level 4: paragraph: A few specialized species such a ... apted to catch and swallow large fish. - item-287 at level 4: paragraph: The others have the characterist ... e nostrils come out through hard horn. - item-288 at level 4: paragraph: The Guardian published an articl ... the ducks and pollutes waterways.[25] - item-289 at level 3: section_header: Breeding - item-290 at level 4: picture - item-290 at level 5: caption: A Muscovy duckling - item-291 at level 4: paragraph: Ducks generally only have one pa ... st and led her ducklings to water.[28] - item-292 at level 3: section_header: Communication - item-293 at level 4: paragraph: Female mallard ducks (as well as ... laying calls or quieter contact calls. - item-294 at level 4: paragraph: A common urban legend claims tha ... annel television show MythBusters.[32] - item-295 at level 3: section_header: Predators - item-296 at level 4: picture - item-296 at level 5: caption: Ringed teal - item-297 at level 4: paragraph: Ducks have many predators. Duckl ... or large birds, such as hawks or owls. - item-298 at level 4: paragraph: Adult ducks are fast fliers, but ... its speed and strength to catch ducks. - item-299 at level 2: section_header: Relationship with humans - item-300 at level 3: section_header: Hunting - item-301 at level 4: paragraph: Humans have hunted ducks since p ... evidence of this is uncommon.[35][42] - item-302 at level 4: paragraph: In many areas, wild ducks (inclu ... inated by pollutants such as PCBs.[44] - item-303 at level 3: section_header: Domestication - item-304 at level 4: picture - item-304 at level 5: caption: Indian Runner ducks, a common breed of domestic ducks - item-305 at level 4: paragraph: Ducks have many economic uses, b ... it weighs less than 1 kg (2.2 lb).[48] - item-306 at level 3: section_header: Heraldry - item-307 at level 4: picture - item-307 at level 5: caption: Three black-colored ducks in the coat of arms of Maaninka[49] - item-308 at level 4: paragraph: Ducks appear on several coats of ... the coat of arms of Föglö (Åland).[51] - item-309 at level 3: section_header: Cultural references - item-310 at level 4: paragraph: In 2002, psychologist Richard Wi ... 54] and was made into a movie in 1986. - item-311 at level 4: paragraph: The 1992 Disney film The Mighty ... Ducks minor league baseball team.[55] - item-312 at level 2: section_header: See also - item-313 at level 3: list: group list - item-314 at level 4: list_item: Birds portal - item-315 at level 3: list: group list - item-316 at level 4: list_item: Domestic duck - item-317 at level 4: list_item: Duck as food - item-318 at level 4: list_item: Duck test - item-319 at level 4: list_item: Duck breeds - item-320 at level 4: list_item: Fictional ducks - item-321 at level 4: list_item: Rubber duck - item-322 at level 2: section_header: Notes - item-323 at level 3: section_header: Citations - item-324 at level 4: ordered_list: group ordered list - item-325 at level 5: list_item: ^ "Duckling". The American Herit ... n Company. 2006. Retrieved 2015-05-22. - item-326 at level 5: list_item: ^ "Duckling". Kernerman English ... Ltd. 2000–2006. Retrieved 2015-05-22. - item-327 at level 5: list_item: ^ Dohner, Janet Vorwald (2001). ... University Press. ISBN 978-0300138139. - item-328 at level 5: list_item: ^ Visca, Curt; Visca, Kelley (20 ... Publishing Group. ISBN 9780823961566. - item-329 at level 5: list_item: ^ a b c d Carboneras 1992, p. 536. - item-330 at level 5: list_item: ^ Livezey 1986, pp. 737–738. - item-331 at level 5: list_item: ^ Madsen, McHugh & de Kloet 1988, p. 452. - item-332 at level 5: list_item: ^ Donne-Goussé, Laudet & Hänni 2002, pp. 353–354. - item-333 at level 5: list_item: ^ a b c d e f Carboneras 1992, p. 540. - item-334 at level 5: list_item: ^ Elphick, Dunning & Sibley 2001, p. 191. - item-335 at level 5: list_item: ^ Kear 2005, p. 448. - item-336 at level 5: list_item: ^ Kear 2005, p. 622–623. - item-337 at level 5: list_item: ^ Kear 2005, p. 686. - item-338 at level 5: list_item: ^ Elphick, Dunning & Sibley 2001, p. 193. - item-339 at level 5: list_item: ^ a b c d e f g Carboneras 1992, p. 537. - item-340 at level 5: list_item: ^ American Ornithologists' Union 1998, p. xix. - item-341 at level 5: list_item: ^ American Ornithologists' Union 1998. - item-342 at level 5: list_item: ^ Carboneras 1992, p. 538. - item-343 at level 5: list_item: ^ Christidis & Boles 2008, p. 62. - item-344 at level 5: list_item: ^ Shirihai 2008, pp. 239, 245. - item-345 at level 5: list_item: ^ a b Pratt, Bruner & Berrett 1987, pp. 98–107. - item-346 at level 5: list_item: ^ Fitter, Fitter & Hosking 2000, pp. 52–3. - item-347 at level 5: list_item: ^ "Pacific Black Duck". www.wiresnr.org. Retrieved 2018-04-27. - item-348 at level 5: list_item: ^ Ogden, Evans. "Dabbling Ducks". CWE. Retrieved 2006-11-02. - item-349 at level 5: list_item: ^ Karl Mathiesen (16 March 2015) ... Guardian. Retrieved 13 November 2016. - item-350 at level 5: list_item: ^ Rohwer, Frank C.; Anderson, Mi ... 4615-6787-5_4. ISBN 978-1-4615-6789-9. - item-351 at level 5: list_item: ^ Smith, Cyndi M.; Cooke, Fred; ... 093/condor/102.1.201. hdl:10315/13797. - item-352 at level 5: list_item: ^ "If You Find An Orphaned Duckl ... l on 2018-09-23. Retrieved 2018-12-22. - item-353 at level 5: list_item: ^ Carver, Heather (2011). The Du ...  9780557901562.[self-published source] - item-354 at level 5: list_item: ^ Titlow, Budd (2013-09-03). Bir ... man & Littlefield. ISBN 9780762797707. - item-355 at level 5: list_item: ^ Amos, Jonathan (2003-09-08). " ... kers". BBC News. Retrieved 2006-11-02. - item-356 at level 5: list_item: ^ "Mythbusters Episode 8". 12 December 2003. - item-357 at level 5: list_item: ^ Erlandson 1994, p. 171. - item-358 at level 5: list_item: ^ Jeffries 2008, pp. 168, 243. - item-359 at level 5: list_item: ^ a b Sued-Badillo 2003, p. 65. - item-360 at level 5: list_item: ^ Thorpe 1996, p. 68. - item-361 at level 5: list_item: ^ Maisels 1999, p. 42. - item-362 at level 5: list_item: ^ Rau 1876, p. 133. - item-363 at level 5: list_item: ^ Higman 2012, p. 23. - item-364 at level 5: list_item: ^ Hume 2012, p. 53. - item-365 at level 5: list_item: ^ Hume 2012, p. 52. - item-366 at level 5: list_item: ^ Fieldhouse 2002, p. 167. - item-367 at level 5: list_item: ^ Livingston, A. D. (1998-01-01) ... Editions, Limited. ISBN 9781853263774. - item-368 at level 5: list_item: ^ "Study plan for waterfowl inju ... on 2022-10-09. Retrieved 2 July 2019. - item-369 at level 5: list_item: ^ "FAOSTAT". www.fao.org. Retrieved 2019-10-25. - item-370 at level 5: list_item: ^ "Anas platyrhynchos, Domestic ... . Digimorph.org. Retrieved 2012-12-23. - item-371 at level 5: list_item: ^ Sy Montgomery. "Mallard; Encyc ... Britannica.com. Retrieved 2012-12-23. - item-372 at level 5: list_item: ^ Glenday, Craig (2014). Guinnes ... ited. pp. 135. ISBN 978-1-908843-15-9. - item-373 at level 5: list_item: ^ Suomen kunnallisvaakunat (in F ... tto. 1982. p. 147. ISBN 951-773-085-3. - item-374 at level 5: list_item: ^ "Lubānas simbolika" (in Latvian). Retrieved September 9, 2021. - item-375 at level 5: list_item: ^ "Föglö" (in Swedish). Retrieved September 9, 2021. - item-376 at level 5: list_item: ^ Young, Emma. "World's funniest ... w Scientist. Retrieved 7 January 2019. - item-377 at level 5: list_item: ^ "Howard the Duck (character)". Grand Comics Database. - item-378 at level 5: list_item: ^ Sanderson, Peter; Gilbert, Lau ... luding this bad-tempered talking duck. - item-379 at level 5: list_item: ^ "The Duck". University of Oregon Athletics. Retrieved 2022-01-20. - item-380 at level 3: section_header: Sources - item-381 at level 4: list: group list - item-382 at level 5: list_item: American Ornithologists' Union ( ... (PDF) from the original on 2022-10-09. - item-383 at level 5: list_item: Carboneras, Carlos (1992). del H ... Lynx Edicions. ISBN 978-84-87334-10-8. - item-384 at level 5: list_item: Christidis, Les; Boles, Walter E ... ro Publishing. ISBN 978-0-643-06511-6. - item-385 at level 5: list_item: Donne-Goussé, Carole; Laudet, Vi ... /S1055-7903(02)00019-2. PMID 12099792. - item-386 at level 5: list_item: Elphick, Chris; Dunning, John B. ... istopher Helm. ISBN 978-0-7136-6250-4. - item-387 at level 5: list_item: Erlandson, Jon M. (1994). Early ... usiness Media. ISBN 978-1-4419-3231-0. - item-388 at level 5: list_item: Fieldhouse, Paul (2002). Food, F ... ara: ABC-CLIO. ISBN 978-1-61069-412-4. - item-389 at level 5: list_item: Fitter, Julian; Fitter, Daniel; ... versity Press. ISBN 978-0-691-10295-5. - item-390 at level 5: list_item: Higman, B. W. (2012). How Food M ... Wiley & Sons. ISBN 978-1-4051-8947-7. - item-391 at level 5: list_item: Hume, Julian H. (2012). Extinct ... istopher Helm. ISBN 978-1-4729-3744-5. - item-392 at level 5: list_item: Jeffries, Richard (2008). Holoce ... Alabama Press. ISBN 978-0-8173-1658-7. - item-393 at level 5: list_item: Kear, Janet, ed. (2005). Ducks, ... versity Press. ISBN 978-0-19-861009-0. - item-394 at level 5: list_item: Livezey, Bradley C. (October 198 ... (PDF) from the original on 2022-10-09. - item-395 at level 5: list_item: Madsen, Cort S.; McHugh, Kevin P ... (PDF) from the original on 2022-10-09. - item-396 at level 5: list_item: Maisels, Charles Keith (1999). E ... on: Routledge. ISBN 978-0-415-10975-8. - item-397 at level 5: list_item: Pratt, H. Douglas; Bruner, Phill ... University Press. ISBN 0-691-02399-9. - item-398 at level 5: list_item: Rau, Charles (1876). Early Man i ... ork: Harper & Brothers. LCCN 05040168. - item-399 at level 5: list_item: Shirihai, Hadoram (2008). A Comp ... versity Press. ISBN 978-0-691-13666-0. - item-400 at level 5: list_item: Sued-Badillo, Jalil (2003). Auto ... Paris: UNESCO. ISBN 978-92-3-103832-7. - item-401 at level 5: list_item: Thorpe, I. J. (1996). The Origin ... rk: Routledge. ISBN 978-0-415-08009-5. - item-402 at level 2: section_header: External links - item-403 at level 3: list: group list - item-404 at level 4: list_item: Definitions from Wiktionary - item-405 at level 4: list_item: Media from Commons - item-406 at level 4: list_item: Quotations from Wikiquote - item-407 at level 4: list_item: Recipes from Wikibooks - item-408 at level 4: list_item: Taxa from Wikispecies - item-409 at level 4: list_item: Data from Wikidata - item-410 at level 3: list: group list - item-411 at level 4: list_item: list of books (useful looking abstracts) - item-412 at level 4: list_item: Ducks on postage stamps Archived 2013-05-13 at the Wayback Machine - item-413 at level 4: list_item: Ducks at a Distance, by Rob Hine ... uide to identification of US waterfowl - item-414 at level 3: table with [3x2] - item-415 at level 3: picture - item-416 at level 3: paragraph: Retrieved from "" - item-417 at level 3: paragraph: : - item-418 at level 3: list: group list - item-419 at level 4: list_item: Ducks - item-420 at level 4: list_item: Game birds - item-421 at level 4: list_item: Bird common names - item-422 at level 3: paragraph: Hidden categories: - item-423 at level 3: list: group list - item-424 at level 4: list_item: All accuracy disputes - item-425 at level 4: list_item: Accuracy disputes from February 2020 - item-426 at level 4: list_item: CS1 Finnish-language sources (fi) - item-427 at level 4: list_item: CS1 Latvian-language sources (lv) - item-428 at level 4: list_item: CS1 Swedish-language sources (sv) - item-429 at level 4: list_item: Articles with short description - item-430 at level 4: list_item: Short description is different from Wikidata - item-431 at level 4: list_item: Wikipedia indefinitely move-protected pages - item-432 at level 4: list_item: Wikipedia indefinitely semi-protected pages - item-433 at level 4: list_item: Articles with 'species' microformats - item-434 at level 4: list_item: Articles containing Old English (ca. 450-1100)-language text - item-435 at level 4: list_item: Articles containing Dutch-language text - item-436 at level 4: list_item: Articles containing German-language text - item-437 at level 4: list_item: Articles containing Norwegian-language text - item-438 at level 4: list_item: Articles containing Lithuanian-language text - item-439 at level 4: list_item: Articles containing Ancient Greek (to 1453)-language text - item-440 at level 4: list_item: All articles with self-published sources - item-441 at level 4: list_item: Articles with self-published sources from February 2020 - item-442 at level 4: list_item: All articles with unsourced statements - item-443 at level 4: list_item: Articles with unsourced statements from January 2022 - item-444 at level 4: list_item: CS1: long volume value - item-445 at level 4: list_item: Pages using Sister project links with wikidata mismatch - item-446 at level 4: list_item: Pages using Sister project links with hidden wikidata - item-447 at level 4: list_item: Webarchive template wayback links - item-448 at level 4: list_item: Articles with Project Gutenberg links - item-449 at level 4: list_item: Articles containing video clips - item-450 at level 3: list: group list - item-451 at level 4: list_item: This page was last edited on 21 September 2024, at 12:11 (UTC). - item-452 at level 4: list_item: Text is available under the Crea ... tion, Inc., a non-profit organization. - item-453 at level 3: list: group list - item-454 at level 4: list_item: Privacy policy - item-455 at level 4: list_item: About Wikipedia - item-456 at level 4: list_item: Disclaimers - item-457 at level 4: list_item: Contact Wikipedia - item-458 at level 4: list_item: Code of Conduct - item-459 at level 4: list_item: Developers - item-460 at level 4: list_item: Statistics - item-461 at level 4: list_item: Cookie statement - item-462 at level 4: list_item: Mobile view - item-463 at level 3: list: group list - item-464 at level 3: list: group list - item-465 at level 1: caption: Pacific black duck displaying the characteristic upending "duck" - item-466 at level 1: caption: Male mallard. - item-467 at level 1: caption: Wood ducks. - item-468 at level 1: caption: Mallard landing in approach - item-469 at level 1: caption: Male Mandarin duck - item-470 at level 1: caption: Flying steamer ducks in Ushuaia, Argentina - item-471 at level 1: caption: Female mallard in Cornwall, England - item-472 at level 1: caption: Pecten along the bill - item-473 at level 1: caption: Mallard duckling preening - item-474 at level 1: caption: A Muscovy duckling - item-475 at level 1: caption: Ringed teal - item-476 at level 1: caption: Indian Runner ducks, a common breed of domestic ducks - item-477 at level 1: caption: Three black-colored ducks in the coat of arms of Maaninka[49] \ No newline at end of file + item-1 at level 1: title: Duck + item-2 at level 2: list: group list + item-3 at level 3: list_item: Acèh + item-4 at level 3: list_item: Afrikaans + item-5 at level 3: list_item: Alemannisch + item-6 at level 3: list_item: አማርኛ + item-7 at level 3: list_item: Ænglisc + item-8 at level 3: list_item: العربية + item-9 at level 3: list_item: Aragonés + item-10 at level 3: list_item: ܐܪܡܝܐ + item-11 at level 3: list_item: Armãneashti + item-12 at level 3: list_item: Asturianu + item-13 at level 3: list_item: Atikamekw + item-14 at level 3: list_item: Авар + item-15 at level 3: list_item: Aymar aru + item-16 at level 3: list_item: تۆرکجه + item-17 at level 3: list_item: Basa Bali + item-18 at level 3: list_item: বাংলা + item-19 at level 3: list_item: 閩南語 / Bân-lâm-gú + item-20 at level 3: list_item: Беларуская + item-21 at level 3: list_item: Беларуская (тарашкевіца) + item-22 at level 3: list_item: Bikol Central + item-23 at level 3: list_item: Български + item-24 at level 3: list_item: Brezhoneg + item-25 at level 3: list_item: Буряад + item-26 at level 3: list_item: Català + item-27 at level 3: list_item: Чӑвашла + item-28 at level 3: list_item: Čeština + item-29 at level 3: list_item: ChiShona + item-30 at level 3: list_item: Cymraeg + item-31 at level 3: list_item: Dagbanli + item-32 at level 3: list_item: Dansk + item-33 at level 3: list_item: Deitsch + item-34 at level 3: list_item: Deutsch + item-35 at level 3: list_item: डोटेली + item-36 at level 3: list_item: Ελληνικά + item-37 at level 3: list_item: Emiliàn e rumagnòl + item-38 at level 3: list_item: Español + item-39 at level 3: list_item: Esperanto + item-40 at level 3: list_item: Euskara + item-41 at level 3: list_item: فارسی + item-42 at level 3: list_item: Français + item-43 at level 3: list_item: Gaeilge + item-44 at level 3: list_item: Galego + item-45 at level 3: list_item: ГӀалгӀай + item-46 at level 3: list_item: 贛語 + item-47 at level 3: list_item: گیلکی + item-48 at level 3: list_item: 𐌲𐌿𐍄𐌹𐍃𐌺 + item-49 at level 3: list_item: गोंयची कोंकणी / Gõychi Konknni + item-50 at level 3: list_item: 客家語 / Hak-kâ-ngî + item-51 at level 3: list_item: 한국어 + item-52 at level 3: list_item: Hausa + item-53 at level 3: list_item: Հայերեն + item-54 at level 3: list_item: हिन्दी + item-55 at level 3: list_item: Hrvatski + item-56 at level 3: list_item: Ido + item-57 at level 3: list_item: Bahasa Indonesia + item-58 at level 3: list_item: Iñupiatun + item-59 at level 3: list_item: Íslenska + item-60 at level 3: list_item: Italiano + item-61 at level 3: list_item: עברית + item-62 at level 3: list_item: Jawa + item-63 at level 3: list_item: ಕನ್ನಡ + item-64 at level 3: list_item: Kapampangan + item-65 at level 3: list_item: ქართული + item-66 at level 3: list_item: कॉशुर / کٲشُر + item-67 at level 3: list_item: Қазақша + item-68 at level 3: list_item: Ikirundi + item-69 at level 3: list_item: Kongo + item-70 at level 3: list_item: Kreyòl ayisyen + item-71 at level 3: list_item: Кырык мары + item-72 at level 3: list_item: ລາວ + item-73 at level 3: list_item: Latina + item-74 at level 3: list_item: Latviešu + item-75 at level 3: list_item: Lietuvių + item-76 at level 3: list_item: Li Niha + item-77 at level 3: list_item: Ligure + item-78 at level 3: list_item: Limburgs + item-79 at level 3: list_item: Lingála + item-80 at level 3: list_item: Malagasy + item-81 at level 3: list_item: മലയാളം + item-82 at level 3: list_item: मराठी + item-83 at level 3: list_item: مازِرونی + item-84 at level 3: list_item: Bahasa Melayu + item-85 at level 3: list_item: ꯃꯤꯇꯩ ꯂꯣꯟ + item-86 at level 3: list_item: 閩東語 / Mìng-dĕ̤ng-ngṳ̄ + item-87 at level 3: list_item: Мокшень + item-88 at level 3: list_item: Монгол + item-89 at level 3: list_item: မြန်မာဘာသာ + item-90 at level 3: list_item: Nederlands + item-91 at level 3: list_item: Nedersaksies + item-92 at level 3: list_item: नेपाली + item-93 at level 3: list_item: नेपाल भाषा + item-94 at level 3: list_item: 日本語 + item-95 at level 3: list_item: Нохчийн + item-96 at level 3: list_item: Norsk nynorsk + item-97 at level 3: list_item: Occitan + item-98 at level 3: list_item: Oromoo + item-99 at level 3: list_item: ਪੰਜਾਬੀ + item-100 at level 3: list_item: Picard + item-101 at level 3: list_item: Plattdüütsch + item-102 at level 3: list_item: Polski + item-103 at level 3: list_item: Português + item-104 at level 3: list_item: Qırımtatarca + item-105 at level 3: list_item: Română + item-106 at level 3: list_item: Русский + item-107 at level 3: list_item: Саха тыла + item-108 at level 3: list_item: ᱥᱟᱱᱛᱟᱲᱤ + item-109 at level 3: list_item: Sardu + item-110 at level 3: list_item: Scots + item-111 at level 3: list_item: Seeltersk + item-112 at level 3: list_item: Shqip + item-113 at level 3: list_item: Sicilianu + item-114 at level 3: list_item: සිංහල + item-115 at level 3: list_item: Simple English + item-116 at level 3: list_item: سنڌي + item-117 at level 3: list_item: کوردی + item-118 at level 3: list_item: Српски / srpski + item-119 at level 3: list_item: Srpskohrvatski / српскохрватски + item-120 at level 3: list_item: Sunda + item-121 at level 3: list_item: Svenska + item-122 at level 3: list_item: Tagalog + item-123 at level 3: list_item: தமிழ் + item-124 at level 3: list_item: Taqbaylit + item-125 at level 3: list_item: Татарча / tatarça + item-126 at level 3: list_item: ไทย + item-127 at level 3: list_item: Türkçe + item-128 at level 3: list_item: Українська + item-129 at level 3: list_item: ئۇيغۇرچە / Uyghurche + item-130 at level 3: list_item: Vahcuengh + item-131 at level 3: list_item: Tiếng Việt + item-132 at level 3: list_item: Walon + item-133 at level 3: list_item: 文言 + item-134 at level 3: list_item: Winaray + item-135 at level 3: list_item: 吴语 + item-136 at level 3: list_item: 粵語 + item-137 at level 3: list_item: Žemaitėška + item-138 at level 3: list_item: 中文 + item-139 at level 2: list: group list + item-140 at level 3: list_item: Article + item-141 at level 3: list_item: Talk + item-142 at level 2: list: group list + item-143 at level 2: list: group list + item-144 at level 3: list_item: Read + item-145 at level 3: list_item: View source + item-146 at level 3: list_item: View history + item-147 at level 2: text: Tools + item-148 at level 2: text: Actions + item-149 at level 2: list: group list + item-150 at level 3: list_item: Read + item-151 at level 3: list_item: View source + item-152 at level 3: list_item: View history + item-153 at level 2: text: General + item-154 at level 2: list: group list + item-155 at level 3: list_item: What links here + item-156 at level 3: list_item: Related changes + item-157 at level 3: list_item: Upload file + item-158 at level 3: list_item: Special pages + item-159 at level 3: list_item: Permanent link + item-160 at level 3: list_item: Page information + item-161 at level 3: list_item: Cite this page + item-162 at level 3: list_item: Get shortened URL + item-163 at level 3: list_item: Download QR code + item-164 at level 3: list_item: Wikidata item + item-165 at level 2: text: Print/export + item-166 at level 2: list: group list + item-167 at level 3: list_item: Download as PDF + item-168 at level 3: list_item: Printable version + item-169 at level 2: text: In other projects + item-170 at level 2: list: group list + item-171 at level 3: list_item: Wikimedia Commons + item-172 at level 3: list_item: Wikiquote + item-173 at level 2: text: Appearance + item-174 at level 2: picture + item-175 at level 2: text: From Wikipedia, the free encyclopedia + item-176 at level 2: text: Common name for many species of bird + item-177 at level 2: text: This article is about the bird. ... as a food, see . For other uses, see . + item-178 at level 2: text: "Duckling" redirects here. For other uses, see . + item-179 at level 2: table with [13x2] + item-180 at level 2: text: Duck is the common name for nume ... und in both fresh water and sea water. + item-181 at level 2: text: Ducks are sometimes confused wit ... divers, grebes, gallinules and coots. + item-182 at level 2: section_header: Etymology + item-183 at level 3: text: The word duck comes from Old Eng ... h duiken and German tauchen 'to dive'. + item-184 at level 3: picture + item-184 at level 4: caption: Pacific black duck displaying the characteristic upending "duck" + item-185 at level 3: text: This word replaced Old English e ... nskrit ātí 'water bird', among others. + item-186 at level 3: text: A duckling is a young duck in do ... , is sometimes labelled as a duckling. + item-187 at level 3: text: A male is called a drake and the ... a duck, or in ornithology a hen.[3][4] + item-188 at level 3: picture + item-188 at level 4: caption: Male mallard. + item-189 at level 3: picture + item-189 at level 4: caption: Wood ducks. + item-190 at level 2: section_header: Taxonomy + item-191 at level 3: text: All ducks belong to the biologic ... ationships between various species.[9] + item-192 at level 3: picture + item-192 at level 4: caption: Mallard landing in approach + item-193 at level 3: text: In most modern classifications, ... all size and stiff, upright tails.[14] + item-194 at level 3: text: A number of other species called ... shelducks in the tribe Tadornini.[15] + item-195 at level 2: section_header: Morphology + item-196 at level 3: picture + item-196 at level 4: caption: Male Mandarin duck + item-197 at level 3: text: The overall body plan of ducks i ... is moult typically precedes migration. + item-198 at level 3: text: The drakes of northern species o ... rkscrew shaped vagina to prevent rape. + item-199 at level 2: section_header: Distribution and habitat + item-200 at level 3: picture + item-200 at level 4: caption: Flying steamer ducks in Ushuaia, Argentina + item-201 at level 3: text: Ducks have a cosmopolitan distri ... endemic to such far-flung islands.[21] + item-202 at level 3: picture + item-202 at level 4: caption: Female mallard in Cornwall, England + item-203 at level 3: text: Some duck species, mainly those ... t form after localised heavy rain.[23] + item-204 at level 2: section_header: Behaviour + item-205 at level 3: section_header: Feeding + item-206 at level 4: picture + item-206 at level 5: caption: Pecten along the bill + item-207 at level 4: picture + item-207 at level 5: caption: Mallard duckling preening + item-208 at level 4: text: Ducks eat food sources such as g ... amphibians, worms, and small molluscs. + item-209 at level 4: text: Dabbling ducks feed on the surfa ... thers and to hold slippery food items. + item-210 at level 4: text: Diving ducks and sea ducks forag ... ave more difficulty taking off to fly. + item-211 at level 4: text: A few specialized species such a ... apted to catch and swallow large fish. + item-212 at level 4: text: The others have the characterist ... e nostrils come out through hard horn. + item-213 at level 4: text: The Guardian published an articl ... the ducks and pollutes waterways.[25] + item-214 at level 3: section_header: Breeding + item-215 at level 4: picture + item-215 at level 5: caption: A Muscovy duckling + item-216 at level 4: text: Ducks generally only have one pa ... st and led her ducklings to water.[28] + item-217 at level 3: section_header: Communication + item-218 at level 4: text: Female mallard ducks (as well as ... laying calls or quieter contact calls. + item-219 at level 4: text: A common urban legend claims tha ... annel television show MythBusters.[32] + item-220 at level 3: section_header: Predators + item-221 at level 4: picture + item-221 at level 5: caption: Ringed teal + item-222 at level 4: text: Ducks have many predators. Duckl ... or large birds, such as hawks or owls. + item-223 at level 4: text: Adult ducks are fast fliers, but ... its speed and strength to catch ducks. + item-224 at level 2: section_header: Relationship with humans + item-225 at level 3: section_header: Hunting + item-226 at level 4: text: Humans have hunted ducks since p ... evidence of this is uncommon.[35][42] + item-227 at level 4: text: In many areas, wild ducks (inclu ... inated by pollutants such as PCBs.[44] + item-228 at level 3: section_header: Domestication + item-229 at level 4: picture + item-229 at level 5: caption: Indian Runner ducks, a common breed of domestic ducks + item-230 at level 4: text: Ducks have many economic uses, b ... it weighs less than 1 kg (2.2 lb).[48] + item-231 at level 3: section_header: Heraldry + item-232 at level 4: picture + item-232 at level 5: caption: Three black-colored ducks in the coat of arms of Maaninka[49] + item-233 at level 4: text: Ducks appear on several coats of ... the coat of arms of Föglö (Åland).[51] + item-234 at level 3: section_header: Cultural references + item-235 at level 4: text: In 2002, psychologist Richard Wi ... 54] and was made into a movie in 1986. + item-236 at level 4: text: The 1992 Disney film The Mighty ... Ducks minor league baseball team.[55] + item-237 at level 2: section_header: See also + item-238 at level 3: list: group list + item-239 at level 4: list_item: Birds portal + item-240 at level 3: list: group list + item-241 at level 4: list_item: Domestic duck + item-242 at level 4: list_item: Duck as food + item-243 at level 4: list_item: Duck test + item-244 at level 4: list_item: Duck breeds + item-245 at level 4: list_item: Fictional ducks + item-246 at level 4: list_item: Rubber duck + item-247 at level 2: section_header: Notes + item-248 at level 3: section_header: Citations + item-249 at level 4: ordered_list: group ordered list + item-250 at level 5: list_item: ^ "Duckling". The American Herit ... n Company. 2006. Retrieved 2015-05-22. + item-251 at level 5: list_item: ^ "Duckling". Kernerman English ... Ltd. 2000–2006. Retrieved 2015-05-22. + item-252 at level 5: list_item: ^ Dohner, Janet Vorwald (2001). ... University Press. ISBN 978-0300138139. + item-253 at level 5: list_item: ^ Visca, Curt; Visca, Kelley (20 ... Publishing Group. ISBN 9780823961566. + item-254 at level 5: list_item: ^ a b c d Carboneras 1992, p. 536. + item-255 at level 5: list_item: ^ Livezey 1986, pp. 737–738. + item-256 at level 5: list_item: ^ Madsen, McHugh & de Kloet 1988, p. 452. + item-257 at level 5: list_item: ^ Donne-Goussé, Laudet & Hänni 2002, pp. 353–354. + item-258 at level 5: list_item: ^ a b c d e f Carboneras 1992, p. 540. + item-259 at level 5: list_item: ^ Elphick, Dunning & Sibley 2001, p. 191. + item-260 at level 5: list_item: ^ Kear 2005, p. 448. + item-261 at level 5: list_item: ^ Kear 2005, p. 622–623. + item-262 at level 5: list_item: ^ Kear 2005, p. 686. + item-263 at level 5: list_item: ^ Elphick, Dunning & Sibley 2001, p. 193. + item-264 at level 5: list_item: ^ a b c d e f g Carboneras 1992, p. 537. + item-265 at level 5: list_item: ^ American Ornithologists' Union 1998, p. xix. + item-266 at level 5: list_item: ^ American Ornithologists' Union 1998. + item-267 at level 5: list_item: ^ Carboneras 1992, p. 538. + item-268 at level 5: list_item: ^ Christidis & Boles 2008, p. 62. + item-269 at level 5: list_item: ^ Shirihai 2008, pp. 239, 245. + item-270 at level 5: list_item: ^ a b Pratt, Bruner & Berrett 1987, pp. 98–107. + item-271 at level 5: list_item: ^ Fitter, Fitter & Hosking 2000, pp. 52–3. + item-272 at level 5: list_item: ^ "Pacific Black Duck". www.wiresnr.org. Retrieved 2018-04-27. + item-273 at level 5: list_item: ^ Ogden, Evans. "Dabbling Ducks". CWE. Retrieved 2006-11-02. + item-274 at level 5: list_item: ^ Karl Mathiesen (16 March 2015) ... Guardian. Retrieved 13 November 2016. + item-275 at level 5: list_item: ^ Rohwer, Frank C.; Anderson, Mi ... 4615-6787-5_4. ISBN 978-1-4615-6789-9. + item-276 at level 5: list_item: ^ Smith, Cyndi M.; Cooke, Fred; ... 093/condor/102.1.201. hdl:10315/13797. + item-277 at level 5: list_item: ^ "If You Find An Orphaned Duckl ... l on 2018-09-23. Retrieved 2018-12-22. + item-278 at level 5: list_item: ^ Carver, Heather (2011). The Du ...  9780557901562.[self-published source] + item-279 at level 5: list_item: ^ Titlow, Budd (2013-09-03). Bir ... man & Littlefield. ISBN 9780762797707. + item-280 at level 5: list_item: ^ Amos, Jonathan (2003-09-08). " ... kers". BBC News. Retrieved 2006-11-02. + item-281 at level 5: list_item: ^ "Mythbusters Episode 8". 12 December 2003. + item-282 at level 5: list_item: ^ Erlandson 1994, p. 171. + item-283 at level 5: list_item: ^ Jeffries 2008, pp. 168, 243. + item-284 at level 5: list_item: ^ a b Sued-Badillo 2003, p. 65. + item-285 at level 5: list_item: ^ Thorpe 1996, p. 68. + item-286 at level 5: list_item: ^ Maisels 1999, p. 42. + item-287 at level 5: list_item: ^ Rau 1876, p. 133. + item-288 at level 5: list_item: ^ Higman 2012, p. 23. + item-289 at level 5: list_item: ^ Hume 2012, p. 53. + item-290 at level 5: list_item: ^ Hume 2012, p. 52. + item-291 at level 5: list_item: ^ Fieldhouse 2002, p. 167. + item-292 at level 5: list_item: ^ Livingston, A. D. (1998-01-01) ... Editions, Limited. ISBN 9781853263774. + item-293 at level 5: list_item: ^ "Study plan for waterfowl inju ... on 2022-10-09. Retrieved 2 July 2019. + item-294 at level 5: list_item: ^ "FAOSTAT". www.fao.org. Retrieved 2019-10-25. + item-295 at level 5: list_item: ^ "Anas platyrhynchos, Domestic ... . Digimorph.org. Retrieved 2012-12-23. + item-296 at level 5: list_item: ^ Sy Montgomery. "Mallard; Encyc ... Britannica.com. Retrieved 2012-12-23. + item-297 at level 5: list_item: ^ Glenday, Craig (2014). Guinnes ... ited. pp. 135. ISBN 978-1-908843-15-9. + item-298 at level 5: list_item: ^ Suomen kunnallisvaakunat (in F ... tto. 1982. p. 147. ISBN 951-773-085-3. + item-299 at level 5: list_item: ^ "Lubānas simbolika" (in Latvian). Retrieved September 9, 2021. + item-300 at level 5: list_item: ^ "Föglö" (in Swedish). Retrieved September 9, 2021. + item-301 at level 5: list_item: ^ Young, Emma. "World's funniest ... w Scientist. Retrieved 7 January 2019. + item-302 at level 5: list_item: ^ "Howard the Duck (character)". Grand Comics Database. + item-303 at level 5: list_item: ^ Sanderson, Peter; Gilbert, Lau ... luding this bad-tempered talking duck. + item-304 at level 5: list_item: ^ "The Duck". University of Oregon Athletics. Retrieved 2022-01-20. + item-305 at level 3: section_header: Sources + item-306 at level 4: list: group list + item-307 at level 5: list_item: American Ornithologists' Union ( ... (PDF) from the original on 2022-10-09. + item-308 at level 5: list_item: Carboneras, Carlos (1992). del H ... Lynx Edicions. ISBN 978-84-87334-10-8. + item-309 at level 5: list_item: Christidis, Les; Boles, Walter E ... ro Publishing. ISBN 978-0-643-06511-6. + item-310 at level 5: list_item: Donne-Goussé, Carole; Laudet, Vi ... /S1055-7903(02)00019-2. PMID 12099792. + item-311 at level 5: list_item: Elphick, Chris; Dunning, John B. ... istopher Helm. ISBN 978-0-7136-6250-4. + item-312 at level 5: list_item: Erlandson, Jon M. (1994). Early ... usiness Media. ISBN 978-1-4419-3231-0. + item-313 at level 5: list_item: Fieldhouse, Paul (2002). Food, F ... ara: ABC-CLIO. ISBN 978-1-61069-412-4. + item-314 at level 5: list_item: Fitter, Julian; Fitter, Daniel; ... versity Press. ISBN 978-0-691-10295-5. + item-315 at level 5: list_item: Higman, B. W. (2012). How Food M ... Wiley & Sons. ISBN 978-1-4051-8947-7. + item-316 at level 5: list_item: Hume, Julian H. (2012). Extinct ... istopher Helm. ISBN 978-1-4729-3744-5. + item-317 at level 5: list_item: Jeffries, Richard (2008). Holoce ... Alabama Press. ISBN 978-0-8173-1658-7. + item-318 at level 5: list_item: Kear, Janet, ed. (2005). Ducks, ... versity Press. ISBN 978-0-19-861009-0. + item-319 at level 5: list_item: Livezey, Bradley C. (October 198 ... (PDF) from the original on 2022-10-09. + item-320 at level 5: list_item: Madsen, Cort S.; McHugh, Kevin P ... (PDF) from the original on 2022-10-09. + item-321 at level 5: list_item: Maisels, Charles Keith (1999). E ... on: Routledge. ISBN 978-0-415-10975-8. + item-322 at level 5: list_item: Pratt, H. Douglas; Bruner, Phill ... University Press. ISBN 0-691-02399-9. + item-323 at level 5: list_item: Rau, Charles (1876). Early Man i ... ork: Harper & Brothers. LCCN 05040168. + item-324 at level 5: list_item: Shirihai, Hadoram (2008). A Comp ... versity Press. ISBN 978-0-691-13666-0. + item-325 at level 5: list_item: Sued-Badillo, Jalil (2003). Auto ... Paris: UNESCO. ISBN 978-92-3-103832-7. + item-326 at level 5: list_item: Thorpe, I. J. (1996). The Origin ... rk: Routledge. ISBN 978-0-415-08009-5. + item-327 at level 2: section_header: External links + item-328 at level 3: list: group list + item-329 at level 4: list_item: Definitions from Wiktionary + item-330 at level 4: list_item: Media from Commons + item-331 at level 4: list_item: Quotations from Wikiquote + item-332 at level 4: list_item: Recipes from Wikibooks + item-333 at level 4: list_item: Taxa from Wikispecies + item-334 at level 4: list_item: Data from Wikidata + item-335 at level 3: list: group list + item-336 at level 4: list_item: list of books (useful looking abstracts) + item-337 at level 4: list_item: Ducks on postage stamps Archived 2013-05-13 at the Wayback Machine + item-338 at level 4: list_item: Ducks at a Distance, by Rob Hine ... uide to identification of US waterfowl + item-339 at level 3: table with [3x2] + item-340 at level 3: picture + item-341 at level 3: text: Retrieved from "" + item-342 at level 3: text: : + item-343 at level 3: list: group list + item-344 at level 4: list_item: Ducks + item-345 at level 4: list_item: Game birds + item-346 at level 4: list_item: Bird common names + item-347 at level 3: text: Hidden categories: + item-348 at level 3: list: group list + item-349 at level 4: list_item: All accuracy disputes + item-350 at level 4: list_item: Accuracy disputes from February 2020 + item-351 at level 4: list_item: CS1 Finnish-language sources (fi) + item-352 at level 4: list_item: CS1 Latvian-language sources (lv) + item-353 at level 4: list_item: CS1 Swedish-language sources (sv) + item-354 at level 4: list_item: Articles with short description + item-355 at level 4: list_item: Short description is different from Wikidata + item-356 at level 4: list_item: Wikipedia indefinitely move-protected pages + item-357 at level 4: list_item: Wikipedia indefinitely semi-protected pages + item-358 at level 4: list_item: Articles with 'species' microformats + item-359 at level 4: list_item: Articles containing Old English (ca. 450-1100)-language text + item-360 at level 4: list_item: Articles containing Dutch-language text + item-361 at level 4: list_item: Articles containing German-language text + item-362 at level 4: list_item: Articles containing Norwegian-language text + item-363 at level 4: list_item: Articles containing Lithuanian-language text + item-364 at level 4: list_item: Articles containing Ancient Greek (to 1453)-language text + item-365 at level 4: list_item: All articles with self-published sources + item-366 at level 4: list_item: Articles with self-published sources from February 2020 + item-367 at level 4: list_item: All articles with unsourced statements + item-368 at level 4: list_item: Articles with unsourced statements from January 2022 + item-369 at level 4: list_item: CS1: long volume value + item-370 at level 4: list_item: Pages using Sister project links with wikidata mismatch + item-371 at level 4: list_item: Pages using Sister project links with hidden wikidata + item-372 at level 4: list_item: Webarchive template wayback links + item-373 at level 4: list_item: Articles with Project Gutenberg links + item-374 at level 4: list_item: Articles containing video clips + item-375 at level 3: list: group list + item-376 at level 4: list_item: This page was last edited on 21 September 2024, at 12:11 (UTC). + item-377 at level 4: list_item: Text is available under the Crea ... tion, Inc., a non-profit organization. + item-378 at level 3: list: group list + item-379 at level 4: list_item: Privacy policy + item-380 at level 4: list_item: About Wikipedia + item-381 at level 4: list_item: Disclaimers + item-382 at level 4: list_item: Contact Wikipedia + item-383 at level 4: list_item: Code of Conduct + item-384 at level 4: list_item: Developers + item-385 at level 4: list_item: Statistics + item-386 at level 4: list_item: Cookie statement + item-387 at level 4: list_item: Mobile view + item-388 at level 3: list: group list + item-389 at level 3: list: group list + item-390 at level 1: caption: Pacific black duck displaying the characteristic upending "duck" + item-391 at level 1: caption: Male mallard. + item-392 at level 1: caption: Wood ducks. + item-393 at level 1: caption: Mallard landing in approach + item-394 at level 1: caption: Male Mandarin duck + item-395 at level 1: caption: Flying steamer ducks in Ushuaia, Argentina + item-396 at level 1: caption: Female mallard in Cornwall, England + item-397 at level 1: caption: Pecten along the bill + item-398 at level 1: caption: Mallard duckling preening + item-399 at level 1: caption: A Muscovy duckling + item-400 at level 1: caption: Ringed teal + item-401 at level 1: caption: Indian Runner ducks, a common breed of domestic ducks + item-402 at level 1: caption: Three black-colored ducks in the coat of arms of Maaninka[49] \ No newline at end of file diff --git a/tests/data/groundtruth/docling_v2/wiki_duck.html.json b/tests/data/groundtruth/docling_v2/wiki_duck.html.json index 3c61c1a5..32433514 100644 --- a/tests/data/groundtruth/docling_v2/wiki_duck.html.json +++ b/tests/data/groundtruth/docling_v2/wiki_duck.html.json @@ -138,7 +138,7 @@ "$ref": "#/texts/7" } ], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -164,7 +164,7 @@ "$ref": "#/texts/13" } ], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -174,7 +174,7 @@ "$ref": "#/body" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -188,7 +188,7 @@ "$ref": "#/texts/14" } ], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -198,7 +198,7 @@ "$ref": "#/body" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -215,7 +215,7 @@ "$ref": "#/texts/16" } ], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -232,7 +232,7 @@ "$ref": "#/texts/18" } ], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -249,7 +249,7 @@ "$ref": "#/texts/21" } ], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -263,7 +263,7 @@ "$ref": "#/texts/22" } ], - "content_layer": "body", + "content_layer": "furniture", "name": "header-1", "label": "section" }, @@ -304,7 +304,7 @@ "$ref": "#/texts/42" } ], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -314,7 +314,7 @@ "$ref": "#/texts/24" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -324,7 +324,7 @@ "$ref": "#/texts/25" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -334,7 +334,7 @@ "$ref": "#/texts/26" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -344,7 +344,7 @@ "$ref": "#/texts/27" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -367,7 +367,7 @@ "$ref": "#/texts/32" } ], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -377,7 +377,7 @@ "$ref": "#/texts/29" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -387,7 +387,7 @@ "$ref": "#/texts/30" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -397,7 +397,7 @@ "$ref": "#/texts/31" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -407,7 +407,7 @@ "$ref": "#/texts/32" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -430,7 +430,7 @@ "$ref": "#/texts/37" } ], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -440,7 +440,7 @@ "$ref": "#/texts/34" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -450,7 +450,7 @@ "$ref": "#/texts/35" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -460,7 +460,7 @@ "$ref": "#/texts/36" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -470,7 +470,7 @@ "$ref": "#/texts/37" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -480,7 +480,7 @@ "$ref": "#/texts/38" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -497,7 +497,7 @@ "$ref": "#/texts/41" } ], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -507,7 +507,7 @@ "$ref": "#/texts/40" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -517,7 +517,7 @@ "$ref": "#/texts/41" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -527,7 +527,7 @@ "$ref": "#/texts/42" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "name": "list", "label": "list" }, @@ -1623,8 +1623,8 @@ "$ref": "#/body" }, "children": [], - "content_layer": "body", - "label": "paragraph", + "content_layer": "furniture", + "label": "text", "prov": [], "orig": "Main menu", "text": "Main menu" @@ -1635,8 +1635,8 @@ "$ref": "#/body" }, "children": [], - "content_layer": "body", - "label": "paragraph", + "content_layer": "furniture", + "label": "text", "prov": [], "orig": "Navigation", "text": "Navigation" @@ -1647,7 +1647,7 @@ "$ref": "#/groups/0" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Main page", @@ -1661,7 +1661,7 @@ "$ref": "#/groups/0" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Contents", @@ -1675,7 +1675,7 @@ "$ref": "#/groups/0" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Current events", @@ -1689,7 +1689,7 @@ "$ref": "#/groups/0" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Random article", @@ -1703,7 +1703,7 @@ "$ref": "#/groups/0" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "About Wikipedia", @@ -1717,7 +1717,7 @@ "$ref": "#/groups/0" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Contact us", @@ -1731,8 +1731,8 @@ "$ref": "#/body" }, "children": [], - "content_layer": "body", - "label": "paragraph", + "content_layer": "furniture", + "label": "text", "prov": [], "orig": "Contribute", "text": "Contribute" @@ -1743,7 +1743,7 @@ "$ref": "#/groups/1" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Help", @@ -1757,7 +1757,7 @@ "$ref": "#/groups/1" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Learn to edit", @@ -1771,7 +1771,7 @@ "$ref": "#/groups/1" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Community portal", @@ -1785,7 +1785,7 @@ "$ref": "#/groups/1" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Recent changes", @@ -1799,7 +1799,7 @@ "$ref": "#/groups/1" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Upload file", @@ -1813,7 +1813,7 @@ "$ref": "#/groups/3" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Donate", @@ -1827,7 +1827,7 @@ "$ref": "#/groups/5" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Create account", @@ -1841,7 +1841,7 @@ "$ref": "#/groups/5" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Log in", @@ -1855,7 +1855,7 @@ "$ref": "#/groups/6" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Create account", @@ -1869,7 +1869,7 @@ "$ref": "#/groups/6" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Log in", @@ -1883,8 +1883,8 @@ "$ref": "#/body" }, "children": [], - "content_layer": "body", - "label": "paragraph", + "content_layer": "furniture", + "label": "text", "prov": [], "orig": "Pages for logged out editors", "text": "Pages for logged out editors" @@ -1895,7 +1895,7 @@ "$ref": "#/groups/7" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Contributions", @@ -1909,7 +1909,7 @@ "$ref": "#/groups/7" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "Talk", @@ -1927,7 +1927,7 @@ "$ref": "#/groups/9" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "section_header", "prov": [], "orig": "Contents", @@ -1940,7 +1940,7 @@ "$ref": "#/groups/9" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "(Top)", @@ -1958,7 +1958,7 @@ "$ref": "#/groups/10" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "1 Etymology", @@ -1976,7 +1976,7 @@ "$ref": "#/groups/11" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "2 Taxonomy", @@ -1994,7 +1994,7 @@ "$ref": "#/groups/12" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "3 Morphology", @@ -2012,7 +2012,7 @@ "$ref": "#/groups/13" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "4 Distribution and habitat", @@ -2030,7 +2030,7 @@ "$ref": "#/groups/14" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "5 Behaviour Toggle Behaviour subsection", @@ -2048,7 +2048,7 @@ "$ref": "#/groups/15" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "5.1 Feeding", @@ -2066,7 +2066,7 @@ "$ref": "#/groups/16" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "5.2 Breeding", @@ -2084,7 +2084,7 @@ "$ref": "#/groups/17" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "5.3 Communication", @@ -2102,7 +2102,7 @@ "$ref": "#/groups/18" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "5.4 Predators", @@ -2120,7 +2120,7 @@ "$ref": "#/groups/19" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "6 Relationship with humans Toggle Relationship with humans subsection", @@ -2138,7 +2138,7 @@ "$ref": "#/groups/20" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "6.1 Hunting", @@ -2156,7 +2156,7 @@ "$ref": "#/groups/21" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "6.2 Domestication", @@ -2174,7 +2174,7 @@ "$ref": "#/groups/22" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "6.3 Heraldry", @@ -2192,7 +2192,7 @@ "$ref": "#/groups/23" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "6.4 Cultural references", @@ -2210,7 +2210,7 @@ "$ref": "#/groups/24" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "7 See also", @@ -2228,7 +2228,7 @@ "$ref": "#/groups/25" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "8 Notes Toggle Notes subsection", @@ -2246,7 +2246,7 @@ "$ref": "#/groups/26" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "8.1 Citations", @@ -2264,7 +2264,7 @@ "$ref": "#/groups/27" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "8.2 Sources", @@ -2282,7 +2282,7 @@ "$ref": "#/groups/28" } ], - "content_layer": "body", + "content_layer": "furniture", "label": "list_item", "prov": [], "orig": "9 External links", @@ -4377,7 +4377,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Tools", "text": "Tools" @@ -4389,7 +4389,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Actions", "text": "Actions" @@ -4443,7 +4443,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "General", "text": "General" @@ -4595,7 +4595,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Print/export", "text": "Print/export" @@ -4635,7 +4635,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "In other projects", "text": "In other projects" @@ -4675,7 +4675,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Appearance", "text": "Appearance" @@ -4687,7 +4687,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "From Wikipedia, the free encyclopedia", "text": "From Wikipedia, the free encyclopedia" @@ -4699,7 +4699,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Common name for many species of bird", "text": "Common name for many species of bird" @@ -4711,7 +4711,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "This article is about the bird. For duck as a food, see . For other uses, see .", "text": "This article is about the bird. For duck as a food, see . For other uses, see ." @@ -4723,7 +4723,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "\"Duckling\" redirects here. For other uses, see .", "text": "\"Duckling\" redirects here. For other uses, see ." @@ -4735,7 +4735,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Duck is the common name for numerous species of waterfowl in the family Anatidae. Ducks are generally smaller and shorter-necked than swans and geese, which are members of the same family. Divided among several subfamilies, they are a form taxon; they do not represent a monophyletic group (the group of all descendants of a single common ancestral species), since swans and geese are not considered ducks. Ducks are mostly aquatic birds, and may be found in both fresh water and sea water.", "text": "Duck is the common name for numerous species of waterfowl in the family Anatidae. Ducks are generally smaller and shorter-necked than swans and geese, which are members of the same family. Divided among several subfamilies, they are a form taxon; they do not represent a monophyletic group (the group of all descendants of a single common ancestral species), since swans and geese are not considered ducks. Ducks are mostly aquatic birds, and may be found in both fresh water and sea water." @@ -4747,7 +4747,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Ducks are sometimes confused with several types of unrelated water birds with similar forms, such as loons or divers, grebes, gallinules and coots.", "text": "Ducks are sometimes confused with several types of unrelated water birds with similar forms, such as loons or divers, grebes, gallinules and coots." @@ -4794,7 +4794,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "The word duck comes from Old English d\u016bce 'diver', a derivative of the verb *d\u016bcan 'to duck, bend down low as if to get under something, or dive', because of the way many species in the dabbling duck group feed by upending; compare with Dutch duiken and German tauchen 'to dive'.", "text": "The word duck comes from Old English d\u016bce 'diver', a derivative of the verb *d\u016bcan 'to duck, bend down low as if to get under something, or dive', because of the way many species in the dabbling duck group feed by upending; compare with Dutch duiken and German tauchen 'to dive'." @@ -4818,7 +4818,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "This word replaced Old English ened /\u00e6nid 'duck', possibly to avoid confusion with other words, such as ende 'end' with similar forms. Other Germanic languages still have similar words for duck, for example, Dutch eend, German Ente and Norwegian and. The word ened /\u00e6nid was inherited from Proto-Indo-European; cf. Latin anas \"duck\", Lithuanian \u00e1ntis 'duck', Ancient Greek \u03bd\u1fc6\u03c3\u03c3\u03b1 /\u03bd\u1fc6\u03c4\u03c4\u03b1 (n\u0113ssa /n\u0113tta) 'duck', and Sanskrit \u0101t\u00ed 'water bird', among others.", "text": "This word replaced Old English ened /\u00e6nid 'duck', possibly to avoid confusion with other words, such as ende 'end' with similar forms. Other Germanic languages still have similar words for duck, for example, Dutch eend, German Ente and Norwegian and. The word ened /\u00e6nid was inherited from Proto-Indo-European; cf. Latin anas \"duck\", Lithuanian \u00e1ntis 'duck', Ancient Greek \u03bd\u1fc6\u03c3\u03c3\u03b1 /\u03bd\u1fc6\u03c4\u03c4\u03b1 (n\u0113ssa /n\u0113tta) 'duck', and Sanskrit \u0101t\u00ed 'water bird', among others." @@ -4830,7 +4830,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "A duckling is a young duck in downy plumage[1] or baby duck,[2] but in the food trade a young domestic duck which has just reached adult size and bulk and its meat is still fully tender, is sometimes labelled as a duckling.", "text": "A duckling is a young duck in downy plumage[1] or baby duck,[2] but in the food trade a young domestic duck which has just reached adult size and bulk and its meat is still fully tender, is sometimes labelled as a duckling." @@ -4842,7 +4842,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "A male is called a drake and the female is called a duck, or in ornithology a hen.[3][4]", "text": "A male is called a drake and the female is called a duck, or in ornithology a hen.[3][4]" @@ -4904,7 +4904,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "All ducks belong to the biological order Anseriformes, a group that contains the ducks, geese and swans, as well as the screamers, and the magpie goose.[5] All except the screamers belong to the biological family Anatidae.[5] Within the family, ducks are split into a variety of subfamilies and 'tribes'. The number and composition of these subfamilies and tribes is the cause of considerable disagreement among taxonomists.[5] Some base their decisions on morphological characteristics, others on shared behaviours or genetic studies.[6][7] The number of suggested subfamilies containing ducks ranges from two to five.[8][9] The significant level of hybridisation that occurs among wild ducks complicates efforts to tease apart the relationships between various species.[9]", "text": "All ducks belong to the biological order Anseriformes, a group that contains the ducks, geese and swans, as well as the screamers, and the magpie goose.[5] All except the screamers belong to the biological family Anatidae.[5] Within the family, ducks are split into a variety of subfamilies and 'tribes'. The number and composition of these subfamilies and tribes is the cause of considerable disagreement among taxonomists.[5] Some base their decisions on morphological characteristics, others on shared behaviours or genetic studies.[6][7] The number of suggested subfamilies containing ducks ranges from two to five.[8][9] The significant level of hybridisation that occurs among wild ducks complicates efforts to tease apart the relationships between various species.[9]" @@ -4928,7 +4928,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "In most modern classifications, the so-called 'true ducks' belong to the subfamily Anatinae, which is further split into a varying number of tribes.[10] The largest of these, the Anatini, contains the 'dabbling' or 'river' ducks \u2013 named for their method of feeding primarily at the surface of fresh water.[11] The 'diving ducks', also named for their primary feeding method, make up the tribe Aythyini.[12] The 'sea ducks' of the tribe Mergini are diving ducks which specialise on fish and shellfish and spend a majority of their lives in saltwater.[13] The tribe Oxyurini contains the 'stifftails', diving ducks notable for their small size and stiff, upright tails.[14]", "text": "In most modern classifications, the so-called 'true ducks' belong to the subfamily Anatinae, which is further split into a varying number of tribes.[10] The largest of these, the Anatini, contains the 'dabbling' or 'river' ducks \u2013 named for their method of feeding primarily at the surface of fresh water.[11] The 'diving ducks', also named for their primary feeding method, make up the tribe Aythyini.[12] The 'sea ducks' of the tribe Mergini are diving ducks which specialise on fish and shellfish and spend a majority of their lives in saltwater.[13] The tribe Oxyurini contains the 'stifftails', diving ducks notable for their small size and stiff, upright tails.[14]" @@ -4940,7 +4940,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "A number of other species called ducks are not considered to be 'true ducks', and are typically placed in other subfamilies or tribes. The whistling ducks are assigned either to a tribe (Dendrocygnini) in the subfamily Anatinae or the subfamily Anserinae,[15] or to their own subfamily (Dendrocygninae) or family (Dendrocyganidae).[9][16] The freckled duck of Australia is either the sole member of the tribe Stictonettini in the subfamily Anserinae,[15] or in its own family, the Stictonettinae.[9] The shelducks make up the tribe Tadornini in the family Anserinae in some classifications,[15] and their own subfamily, Tadorninae, in others,[17] while the steamer ducks are either placed in the family Anserinae in the tribe Tachyerini[15] or lumped with the shelducks in the tribe Tadorini.[9] The perching ducks make up in the tribe Cairinini in the subfamily Anserinae in some classifications, while that tribe is eliminated in other classifications and its members assigned to the tribe Anatini.[9] The torrent duck is generally included in the subfamily Anserinae in the monotypic tribe Merganettini,[15] but is sometimes included in the tribe Tadornini.[18] The pink-eared duck is sometimes included as a true duck either in the tribe Anatini[15] or the tribe Malacorhynchini,[19] and other times is included with the shelducks in the tribe Tadornini.[15]", "text": "A number of other species called ducks are not considered to be 'true ducks', and are typically placed in other subfamilies or tribes. The whistling ducks are assigned either to a tribe (Dendrocygnini) in the subfamily Anatinae or the subfamily Anserinae,[15] or to their own subfamily (Dendrocygninae) or family (Dendrocyganidae).[9][16] The freckled duck of Australia is either the sole member of the tribe Stictonettini in the subfamily Anserinae,[15] or in its own family, the Stictonettinae.[9] The shelducks make up the tribe Tadornini in the family Anserinae in some classifications,[15] and their own subfamily, Tadorninae, in others,[17] while the steamer ducks are either placed in the family Anserinae in the tribe Tachyerini[15] or lumped with the shelducks in the tribe Tadorini.[9] The perching ducks make up in the tribe Cairinini in the subfamily Anserinae in some classifications, while that tribe is eliminated in other classifications and its members assigned to the tribe Anatini.[9] The torrent duck is generally included in the subfamily Anserinae in the monotypic tribe Merganettini,[15] but is sometimes included in the tribe Tadornini.[18] The pink-eared duck is sometimes included as a true duck either in the tribe Anatini[15] or the tribe Malacorhynchini,[19] and other times is included with the shelducks in the tribe Tadornini.[15]" @@ -4987,7 +4987,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "The overall body plan of ducks is elongated and broad, and they are also relatively long-necked, albeit not as long-necked as the geese and swans. The body shape of diving ducks varies somewhat from this in being more rounded. The bill is usually broad and contains serrated pectens, which are particularly well defined in the filter-feeding species. In the case of some fishing species the bill is long and strongly serrated. The scaled legs are strong and well developed, and generally set far back on the body, more so in the highly aquatic species. The wings are very strong and are generally short and pointed, and the flight of ducks requires fast continuous strokes, requiring in turn strong wing muscles. Three species of steamer duck are almost flightless, however. Many species of duck are temporarily flightless while moulting; they seek out protected habitat with good food supplies during this period. This moult typically precedes migration.", "text": "The overall body plan of ducks is elongated and broad, and they are also relatively long-necked, albeit not as long-necked as the geese and swans. The body shape of diving ducks varies somewhat from this in being more rounded. The bill is usually broad and contains serrated pectens, which are particularly well defined in the filter-feeding species. In the case of some fishing species the bill is long and strongly serrated. The scaled legs are strong and well developed, and generally set far back on the body, more so in the highly aquatic species. The wings are very strong and are generally short and pointed, and the flight of ducks requires fast continuous strokes, requiring in turn strong wing muscles. Three species of steamer duck are almost flightless, however. Many species of duck are temporarily flightless while moulting; they seek out protected habitat with good food supplies during this period. This moult typically precedes migration." @@ -4999,7 +4999,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "The drakes of northern species often have extravagant plumage, but that is moulted in summer to give a more female-like appearance, the \"eclipse\" plumage. Southern resident species typically show less sexual dimorphism, although there are exceptions such as the paradise shelduck of New Zealand, which is both strikingly sexually dimorphic and in which the female's plumage is brighter than that of the male. The plumage of juvenile birds generally resembles that of the female. Female ducks have evolved to have a corkscrew shaped vagina to prevent rape.", "text": "The drakes of northern species often have extravagant plumage, but that is moulted in summer to give a more female-like appearance, the \"eclipse\" plumage. Southern resident species typically show less sexual dimorphism, although there are exceptions such as the paradise shelduck of New Zealand, which is both strikingly sexually dimorphic and in which the female's plumage is brighter than that of the male. The plumage of juvenile birds generally resembles that of the female. Female ducks have evolved to have a corkscrew shaped vagina to prevent rape." @@ -5049,7 +5049,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Ducks have a cosmopolitan distribution, and are found on every continent except Antarctica.[5] Several species manage to live on subantarctic islands, including South Georgia and the Auckland Islands.[20] Ducks have reached a number of isolated oceanic islands, including the Hawaiian Islands, Micronesia and the Gal\u00e1pagos Islands, where they are often vagrants and less often residents.[21][22] A handful are endemic to such far-flung islands.[21]", "text": "Ducks have a cosmopolitan distribution, and are found on every continent except Antarctica.[5] Several species manage to live on subantarctic islands, including South Georgia and the Auckland Islands.[20] Ducks have reached a number of isolated oceanic islands, including the Hawaiian Islands, Micronesia and the Gal\u00e1pagos Islands, where they are often vagrants and less often residents.[21][22] A handful are endemic to such far-flung islands.[21]" @@ -5073,7 +5073,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Some duck species, mainly those breeding in the temperate and Arctic Northern Hemisphere, are migratory; those in the tropics are generally not. Some ducks, particularly in Australia where rainfall is erratic, are nomadic, seeking out the temporary lakes and pools that form after localised heavy rain.[23]", "text": "Some duck species, mainly those breeding in the temperate and Arctic Northern Hemisphere, are migratory; those in the tropics are generally not. Some ducks, particularly in Australia where rainfall is erratic, are nomadic, seeking out the temporary lakes and pools that form after localised heavy rain.[23]" @@ -5173,7 +5173,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Ducks eat food sources such as grasses, aquatic plants, fish, insects, small amphibians, worms, and small molluscs.", "text": "Ducks eat food sources such as grasses, aquatic plants, fish, insects, small amphibians, worms, and small molluscs." @@ -5185,7 +5185,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Dabbling ducks feed on the surface of water or on land, or as deep as they can reach by up-ending without completely submerging.[24] Along the edge of the bill, there is a comb-like structure called a pecten. This strains the water squirting from the side of the bill and traps any food. The pecten is also used to preen feathers and to hold slippery food items.", "text": "Dabbling ducks feed on the surface of water or on land, or as deep as they can reach by up-ending without completely submerging.[24] Along the edge of the bill, there is a comb-like structure called a pecten. This strains the water squirting from the side of the bill and traps any food. The pecten is also used to preen feathers and to hold slippery food items." @@ -5197,7 +5197,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Diving ducks and sea ducks forage deep underwater. To be able to submerge more easily, the diving ducks are heavier than dabbling ducks, and therefore have more difficulty taking off to fly.", "text": "Diving ducks and sea ducks forage deep underwater. To be able to submerge more easily, the diving ducks are heavier than dabbling ducks, and therefore have more difficulty taking off to fly." @@ -5209,7 +5209,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "A few specialized species such as the mergansers are adapted to catch and swallow large fish.", "text": "A few specialized species such as the mergansers are adapted to catch and swallow large fish." @@ -5221,7 +5221,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "The others have the characteristic wide flat bill adapted to dredging-type jobs such as pulling up waterweed, pulling worms and small molluscs out of mud, searching for insect larvae, and bulk jobs such as dredging out, holding, turning head first, and swallowing a squirming frog. To avoid injury when digging into sediment it has no cere, but the nostrils come out through hard horn.", "text": "The others have the characteristic wide flat bill adapted to dredging-type jobs such as pulling up waterweed, pulling worms and small molluscs out of mud, searching for insect larvae, and bulk jobs such as dredging out, holding, turning head first, and swallowing a squirming frog. To avoid injury when digging into sediment it has no cere, but the nostrils come out through hard horn." @@ -5233,7 +5233,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "The Guardian published an article advising that ducks should not be fed with bread because it damages the health of the ducks and pollutes waterways.[25]", "text": "The Guardian published an article advising that ducks should not be fed with bread because it damages the health of the ducks and pollutes waterways.[25]" @@ -5277,7 +5277,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Ducks generally only have one partner at a time, although the partnership usually only lasts one year.[26] Larger species and the more sedentary species (like fast-river specialists) tend to have pair-bonds that last numerous years.[27] Most duck species breed once a year, choosing to do so in favourable conditions (spring/summer or wet seasons). Ducks also tend to make a nest before breeding, and, after hatching, lead their ducklings to water. Mother ducks are very caring and protective of their young, but may abandon some of their ducklings if they are physically stuck in an area they cannot get out of (such as nesting in an enclosed courtyard) or are not prospering due to genetic defects or sickness brought about by hypothermia, starvation, or disease. Ducklings can also be orphaned by inconsistent late hatching where a few eggs hatch after the mother has abandoned the nest and led her ducklings to water.[28]", "text": "Ducks generally only have one partner at a time, although the partnership usually only lasts one year.[26] Larger species and the more sedentary species (like fast-river specialists) tend to have pair-bonds that last numerous years.[27] Most duck species breed once a year, choosing to do so in favourable conditions (spring/summer or wet seasons). Ducks also tend to make a nest before breeding, and, after hatching, lead their ducklings to water. Mother ducks are very caring and protective of their young, but may abandon some of their ducklings if they are physically stuck in an area they cannot get out of (such as nesting in an enclosed courtyard) or are not prospering due to genetic defects or sickness brought about by hypothermia, starvation, or disease. Ducklings can also be orphaned by inconsistent late hatching where a few eggs hatch after the mother has abandoned the nest and led her ducklings to water.[28]" @@ -5309,7 +5309,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Female mallard ducks (as well as several other species in the genus Anas, such as the American and Pacific black ducks, spot-billed duck, northern pintail and common teal) make the classic \"quack\" sound while males make a similar but raspier sound that is sometimes written as \"breeeeze\",[29][self-published source?] but, despite widespread misconceptions, most species of duck do not \"quack\".[30] In general, ducks make a range of calls, including whistles, cooing, yodels and grunts. For example, the scaup \u2013 which are diving ducks \u2013 make a noise like \"scaup\" (hence their name). Calls may be loud displaying calls or quieter contact calls.", "text": "Female mallard ducks (as well as several other species in the genus Anas, such as the American and Pacific black ducks, spot-billed duck, northern pintail and common teal) make the classic \"quack\" sound while males make a similar but raspier sound that is sometimes written as \"breeeeze\",[29][self-published source?] but, despite widespread misconceptions, most species of duck do not \"quack\".[30] In general, ducks make a range of calls, including whistles, cooing, yodels and grunts. For example, the scaup \u2013 which are diving ducks \u2013 make a noise like \"scaup\" (hence their name). Calls may be loud displaying calls or quieter contact calls." @@ -5321,7 +5321,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "A common urban legend claims that duck quacks do not echo; however, this has been proven to be false. This myth was first debunked by the Acoustics Research Centre at the University of Salford in 2003 as part of the British Association's Festival of Science.[31] It was also debunked in one of the earlier episodes of the popular Discovery Channel television show MythBusters.[32]", "text": "A common urban legend claims that duck quacks do not echo; however, this has been proven to be false. This myth was first debunked by the Acoustics Research Centre at the University of Salford in 2003 as part of the British Association's Festival of Science.[31] It was also debunked in one of the earlier episodes of the popular Discovery Channel television show MythBusters.[32]" @@ -5368,7 +5368,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Ducks have many predators. Ducklings are particularly vulnerable, since their inability to fly makes them easy prey not only for predatory birds but also for large fish like pike, crocodilians, predatory testudines such as the alligator snapping turtle, and other aquatic hunters, including fish-eating birds such as herons. Ducks' nests are raided by land-based predators, and brooding females may be caught unaware on the nest by mammals, such as foxes, or large birds, such as hawks or owls.", "text": "Ducks have many predators. Ducklings are particularly vulnerable, since their inability to fly makes them easy prey not only for predatory birds but also for large fish like pike, crocodilians, predatory testudines such as the alligator snapping turtle, and other aquatic hunters, including fish-eating birds such as herons. Ducks' nests are raided by land-based predators, and brooding females may be caught unaware on the nest by mammals, such as foxes, or large birds, such as hawks or owls." @@ -5380,7 +5380,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Adult ducks are fast fliers, but may be caught on the water by large aquatic predators including big fish such as the North American muskie and the European pike. In flight, ducks are safe from all but a few predators such as humans and the peregrine falcon, which uses its speed and strength to catch ducks.", "text": "Adult ducks are fast fliers, but may be caught on the water by large aquatic predators including big fish such as the North American muskie and the European pike. In flight, ducks are safe from all but a few predators such as humans and the peregrine falcon, which uses its speed and strength to catch ducks." @@ -5438,7 +5438,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Humans have hunted ducks since prehistoric times. Excavations of middens in California dating to 7800 \u2013 6400 BP have turned up bones of ducks, including at least one now-extinct flightless species.[33] Ducks were captured in \"significant numbers\" by Holocene inhabitants of the lower Ohio River valley, suggesting they took advantage of the seasonal bounty provided by migrating waterfowl.[34] Neolithic hunters in locations as far apart as the Caribbean,[35] Scandinavia,[36] Egypt,[37] Switzerland,[38] and China relied on ducks as a source of protein for some or all of the year.[39] Archeological evidence shows that M\u0101ori people in New Zealand hunted the flightless Finsch's duck, possibly to extinction, though rat predation may also have contributed to its fate.[40] A similar end awaited the Chatham duck, a species with reduced flying capabilities which went extinct shortly after its island was colonised by Polynesian settlers.[41] It is probable that duck eggs were gathered by Neolithic hunter-gathers as well, though hard evidence of this is uncommon.[35][42]", "text": "Humans have hunted ducks since prehistoric times. Excavations of middens in California dating to 7800 \u2013 6400 BP have turned up bones of ducks, including at least one now-extinct flightless species.[33] Ducks were captured in \"significant numbers\" by Holocene inhabitants of the lower Ohio River valley, suggesting they took advantage of the seasonal bounty provided by migrating waterfowl.[34] Neolithic hunters in locations as far apart as the Caribbean,[35] Scandinavia,[36] Egypt,[37] Switzerland,[38] and China relied on ducks as a source of protein for some or all of the year.[39] Archeological evidence shows that M\u0101ori people in New Zealand hunted the flightless Finsch's duck, possibly to extinction, though rat predation may also have contributed to its fate.[40] A similar end awaited the Chatham duck, a species with reduced flying capabilities which went extinct shortly after its island was colonised by Polynesian settlers.[41] It is probable that duck eggs were gathered by Neolithic hunter-gathers as well, though hard evidence of this is uncommon.[35][42]" @@ -5450,7 +5450,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "In many areas, wild ducks (including ducks farmed and released into the wild) are hunted for food or sport,[43] by shooting, or by being trapped using duck decoys. Because an idle floating duck or a duck squatting on land cannot react to fly or move quickly, \"a sitting duck\" has come to mean \"an easy target\". These ducks may be contaminated by pollutants such as PCBs.[44]", "text": "In many areas, wild ducks (including ducks farmed and released into the wild) are hunted for food or sport,[43] by shooting, or by being trapped using duck decoys. Because an idle floating duck or a duck squatting on land cannot react to fly or move quickly, \"a sitting duck\" has come to mean \"an easy target\". These ducks may be contaminated by pollutants such as PCBs.[44]" @@ -5494,7 +5494,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Ducks have many economic uses, being farmed for their meat, eggs, and feathers (particularly their down). Approximately 3 billion ducks are slaughtered each year for meat worldwide.[45] They are also kept and bred by aviculturists and often displayed in zoos. Almost all the varieties of domestic ducks are descended from the mallard (Anas platyrhynchos), apart from the Muscovy duck (Cairina moschata).[46][47] The Call duck is another example of a domestic duck breed. Its name comes from its original use established by hunters, as a decoy to attract wild mallards from the sky, into traps set for them on the ground. The call duck is the world's smallest domestic duck breed, as it weighs less than 1\u00a0kg (2.2\u00a0lb).[48]", "text": "Ducks have many economic uses, being farmed for their meat, eggs, and feathers (particularly their down). Approximately 3 billion ducks are slaughtered each year for meat worldwide.[45] They are also kept and bred by aviculturists and often displayed in zoos. Almost all the varieties of domestic ducks are descended from the mallard (Anas platyrhynchos), apart from the Muscovy duck (Cairina moschata).[46][47] The Call duck is another example of a domestic duck breed. Its name comes from its original use established by hunters, as a decoy to attract wild mallards from the sky, into traps set for them on the ground. The call duck is the world's smallest domestic duck breed, as it weighs less than 1\u00a0kg (2.2\u00a0lb).[48]" @@ -5538,7 +5538,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Ducks appear on several coats of arms, including the coat of arms of Lub\u0101na (Latvia)[50] and the coat of arms of F\u00f6gl\u00f6 (\u00c5land).[51]", "text": "Ducks appear on several coats of arms, including the coat of arms of Lub\u0101na (Latvia)[50] and the coat of arms of F\u00f6gl\u00f6 (\u00c5land).[51]" @@ -5570,7 +5570,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "In 2002, psychologist Richard Wiseman and colleagues at the University of Hertfordshire, UK, finished a year-long LaughLab experiment, concluding that of all animals, ducks attract the most humor and silliness; he said, \"If you're going to tell a joke involving an animal, make it a duck.\"[52] The word \"duck\" may have become an inherently funny word in many languages, possibly because ducks are seen as silly in their looks or behavior. Of the many ducks in fiction, many are cartoon characters, such as Walt Disney's Donald Duck, and Warner Bros.' Daffy Duck. Howard the Duck started as a comic book character in 1973[53][54] and was made into a movie in 1986.", "text": "In 2002, psychologist Richard Wiseman and colleagues at the University of Hertfordshire, UK, finished a year-long LaughLab experiment, concluding that of all animals, ducks attract the most humor and silliness; he said, \"If you're going to tell a joke involving an animal, make it a duck.\"[52] The word \"duck\" may have become an inherently funny word in many languages, possibly because ducks are seen as silly in their looks or behavior. Of the many ducks in fiction, many are cartoon characters, such as Walt Disney's Donald Duck, and Warner Bros.' Daffy Duck. Howard the Duck started as a comic book character in 1973[53][54] and was made into a movie in 1986." @@ -5582,7 +5582,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "The 1992 Disney film The Mighty Ducks, starring Emilio Estevez, chose the duck as the mascot for the fictional youth hockey team who are protagonists of the movie, based on the duck being described as a fierce fighter. This led to the duck becoming the nickname and mascot for the eventual National Hockey League professional team of the Anaheim Ducks, who were founded with the name the Mighty Ducks of Anaheim.[citation needed] The duck is also the nickname of the University of Oregon sports teams as well as the Long Island Ducks minor league baseball team.[55]", "text": "The 1992 Disney film The Mighty Ducks, starring Emilio Estevez, chose the duck as the mascot for the fictional youth hockey team who are protagonists of the movie, based on the duck being described as a fierce fighter. This led to the duck becoming the nickname and mascot for the eventual National Hockey League professional team of the Anaheim Ducks, who were founded with the name the Mighty Ducks of Anaheim.[citation needed] The duck is also the nickname of the University of Oregon sports teams as well as the Long Island Ducks minor league baseball team.[55]" @@ -6995,7 +6995,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Retrieved from \"\"", "text": "Retrieved from \"\"" @@ -7007,7 +7007,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": ":", "text": ":" @@ -7061,7 +7061,7 @@ }, "children": [], "content_layer": "body", - "label": "paragraph", + "label": "text", "prov": [], "orig": "Hidden categories:", "text": "Hidden categories:" @@ -7592,7 +7592,7 @@ "$ref": "#/body" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "picture", "prov": [], "captions": [], @@ -7606,7 +7606,7 @@ "$ref": "#/body" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "picture", "prov": [], "captions": [], @@ -7620,7 +7620,7 @@ "$ref": "#/body" }, "children": [], - "content_layer": "body", + "content_layer": "furniture", "label": "picture", "prov": [], "captions": [], diff --git a/tests/data/groundtruth/docling_v2/wiki_duck.html.md b/tests/data/groundtruth/docling_v2/wiki_duck.html.md index 26c42e26..b08b31c6 100644 --- a/tests/data/groundtruth/docling_v2/wiki_duck.html.md +++ b/tests/data/groundtruth/docling_v2/wiki_duck.html.md @@ -1,62 +1,3 @@ -Main menu - -Navigation - -- Main page -- Contents -- Current events -- Random article -- About Wikipedia -- Contact us - -Contribute - -- Help -- Learn to edit -- Community portal -- Recent changes -- Upload file - - - - - - - - - Donate - - Create account - - Log in - - Create account - - Log in - -Pages for logged out editors - - - Contributions - - Talk - -## Contents - - - (Top) - - 1 Etymology - - 2 Taxonomy - - 3 Morphology - - 4 Distribution and habitat - - 5 Behaviour Toggle Behaviour subsection - - 5.1 Feeding - - 5.2 Breeding - - 5.3 Communication - - 5.4 Predators - - 6 Relationship with humans Toggle Relationship with humans subsection - - 6.1 Hunting - - 6.2 Domestication - - 6.3 Heraldry - - 6.4 Cultural references -- 7 See also -- 8 Notes Toggle Notes subsection - - 8.1 Citations - - 8.2 Sources -- 9 External links - # Duck - Acèh diff --git a/tests/test_backend_html.py b/tests/test_backend_html.py index a04ae219..29518682 100644 --- a/tests/test_backend_html.py +++ b/tests/test_backend_html.py @@ -81,7 +81,7 @@ def test_ordered_lists(): ) ) - for pair in test_set: + for idx, pair in enumerate(test_set): in_doc = InputDocument( path_or_stream=BytesIO(pair[0]), format=InputFormat.HTML, @@ -94,7 +94,7 @@ def test_ordered_lists(): ) doc: DoclingDocument = backend.convert() assert doc - assert doc.export_to_markdown() == pair[1] + assert doc.export_to_markdown() == pair[1], f"Error in case {idx}" def get_html_paths(): From 8dc0562542299cf972d14eeeb4393e50b589c8ad Mon Sep 17 00:00:00 2001 From: Michele Dolfi <97102151+dolfim-ibm@users.noreply.github.com> Date: Sun, 2 Mar 2025 20:06:44 +0100 Subject: [PATCH 10/13] fix: enable locks for threadsafe pdfium (#1052) * enable locks for threadsafe pdfium Signed-off-by: Michele Dolfi * fix deadlock in pypdfium2 backend Signed-off-by: Michele Dolfi --------- Signed-off-by: Michele Dolfi --- docling/backend/docling_parse_v2_backend.py | 68 +++++++------- docling/backend/pypdfium2_backend.py | 98 ++++++++++++--------- docling/utils/locks.py | 3 + 3 files changed, 98 insertions(+), 71 deletions(-) create mode 100644 docling/utils/locks.py diff --git a/docling/backend/docling_parse_v2_backend.py b/docling/backend/docling_parse_v2_backend.py index 27a368f9..9178883f 100644 --- a/docling/backend/docling_parse_v2_backend.py +++ b/docling/backend/docling_parse_v2_backend.py @@ -12,6 +12,7 @@ from pypdfium2 import PdfPage from docling.backend.pdf_backend import PdfDocumentBackend, PdfPageBackend from docling.datamodel.base_models import Cell, Size +from docling.utils.locks import pypdfium2_lock if TYPE_CHECKING: from docling.datamodel.document import InputDocument @@ -182,20 +183,24 @@ class DoclingParseV2PageBackend(PdfPageBackend): padbox.r = page_size.width - padbox.r padbox.t = page_size.height - padbox.t - image = ( - self._ppage.render( - scale=scale * 1.5, - rotation=0, # no additional rotation - crop=padbox.as_tuple(), - ) - .to_pil() - .resize(size=(round(cropbox.width * scale), round(cropbox.height * scale))) - ) # We resize the image from 1.5x the given scale to make it sharper. + with pypdfium2_lock: + image = ( + self._ppage.render( + scale=scale * 1.5, + rotation=0, # no additional rotation + crop=padbox.as_tuple(), + ) + .to_pil() + .resize( + size=(round(cropbox.width * scale), round(cropbox.height * scale)) + ) + ) # We resize the image from 1.5x the given scale to make it sharper. return image def get_size(self) -> Size: - return Size(width=self._ppage.get_width(), height=self._ppage.get_height()) + with pypdfium2_lock: + return Size(width=self._ppage.get_width(), height=self._ppage.get_height()) def unload(self): self._ppage = None @@ -206,23 +211,24 @@ class DoclingParseV2DocumentBackend(PdfDocumentBackend): def __init__(self, in_doc: "InputDocument", path_or_stream: Union[BytesIO, Path]): super().__init__(in_doc, path_or_stream) - self._pdoc = pdfium.PdfDocument(self.path_or_stream) - self.parser = pdf_parser_v2("fatal") + with pypdfium2_lock: + self._pdoc = pdfium.PdfDocument(self.path_or_stream) + self.parser = pdf_parser_v2("fatal") - success = False - if isinstance(self.path_or_stream, BytesIO): - success = self.parser.load_document_from_bytesio( - self.document_hash, self.path_or_stream - ) - elif isinstance(self.path_or_stream, Path): - success = self.parser.load_document( - self.document_hash, str(self.path_or_stream) - ) + success = False + if isinstance(self.path_or_stream, BytesIO): + success = self.parser.load_document_from_bytesio( + self.document_hash, self.path_or_stream + ) + elif isinstance(self.path_or_stream, Path): + success = self.parser.load_document( + self.document_hash, str(self.path_or_stream) + ) - if not success: - raise RuntimeError( - f"docling-parse v2 could not load document {self.document_hash}." - ) + if not success: + raise RuntimeError( + f"docling-parse v2 could not load document {self.document_hash}." + ) def page_count(self) -> int: # return len(self._pdoc) # To be replaced with docling-parse API @@ -236,9 +242,10 @@ class DoclingParseV2DocumentBackend(PdfDocumentBackend): return len_2 def load_page(self, page_no: int) -> DoclingParseV2PageBackend: - return DoclingParseV2PageBackend( - self.parser, self.document_hash, page_no, self._pdoc[page_no] - ) + with pypdfium2_lock: + return DoclingParseV2PageBackend( + self.parser, self.document_hash, page_no, self._pdoc[page_no] + ) def is_valid(self) -> bool: return self.page_count() > 0 @@ -246,5 +253,6 @@ class DoclingParseV2DocumentBackend(PdfDocumentBackend): def unload(self): super().unload() self.parser.unload_document(self.document_hash) - self._pdoc.close() - self._pdoc = None + with pypdfium2_lock: + self._pdoc.close() + self._pdoc = None diff --git a/docling/backend/pypdfium2_backend.py b/docling/backend/pypdfium2_backend.py index 5b627da7..b585e2d5 100644 --- a/docling/backend/pypdfium2_backend.py +++ b/docling/backend/pypdfium2_backend.py @@ -13,6 +13,7 @@ from pypdfium2._helpers.misc import PdfiumError from docling.backend.pdf_backend import PdfDocumentBackend, PdfPageBackend from docling.datamodel.base_models import Cell +from docling.utils.locks import pypdfium2_lock if TYPE_CHECKING: from docling.datamodel.document import InputDocument @@ -24,6 +25,7 @@ class PyPdfiumPageBackend(PdfPageBackend): def __init__( self, pdfium_doc: pdfium.PdfDocument, document_hash: str, page_no: int ): + # Note: lock applied by the caller self.valid = True # No better way to tell from pypdfium. try: self._ppage: pdfium.PdfPage = pdfium_doc[page_no] @@ -40,51 +42,57 @@ class PyPdfiumPageBackend(PdfPageBackend): def get_bitmap_rects(self, scale: float = 1) -> Iterable[BoundingBox]: AREA_THRESHOLD = 0 # 32 * 32 - for obj in self._ppage.get_objects(filter=[pdfium_c.FPDF_PAGEOBJ_IMAGE]): - pos = obj.get_pos() - cropbox = BoundingBox.from_tuple( - pos, origin=CoordOrigin.BOTTOMLEFT - ).to_top_left_origin(page_height=self.get_size().height) + page_size = self.get_size() + with pypdfium2_lock: + for obj in self._ppage.get_objects(filter=[pdfium_c.FPDF_PAGEOBJ_IMAGE]): + pos = obj.get_pos() + cropbox = BoundingBox.from_tuple( + pos, origin=CoordOrigin.BOTTOMLEFT + ).to_top_left_origin(page_height=page_size.height) - if cropbox.area() > AREA_THRESHOLD: - cropbox = cropbox.scaled(scale=scale) + if cropbox.area() > AREA_THRESHOLD: + cropbox = cropbox.scaled(scale=scale) - yield cropbox + yield cropbox def get_text_in_rect(self, bbox: BoundingBox) -> str: - if not self.text_page: - self.text_page = self._ppage.get_textpage() + with pypdfium2_lock: + if not self.text_page: + self.text_page = self._ppage.get_textpage() if bbox.coord_origin != CoordOrigin.BOTTOMLEFT: bbox = bbox.to_bottom_left_origin(self.get_size().height) - text_piece = self.text_page.get_text_bounded(*bbox.as_tuple()) + with pypdfium2_lock: + text_piece = self.text_page.get_text_bounded(*bbox.as_tuple()) return text_piece def get_text_cells(self) -> Iterable[Cell]: - if not self.text_page: - self.text_page = self._ppage.get_textpage() + with pypdfium2_lock: + if not self.text_page: + self.text_page = self._ppage.get_textpage() cells = [] cell_counter = 0 page_size = self.get_size() - for i in range(self.text_page.count_rects()): - rect = self.text_page.get_rect(i) - text_piece = self.text_page.get_text_bounded(*rect) - x0, y0, x1, y1 = rect - cells.append( - Cell( - id=cell_counter, - text=text_piece, - bbox=BoundingBox( - l=x0, b=y0, r=x1, t=y1, coord_origin=CoordOrigin.BOTTOMLEFT - ).to_top_left_origin(page_size.height), + with pypdfium2_lock: + for i in range(self.text_page.count_rects()): + rect = self.text_page.get_rect(i) + text_piece = self.text_page.get_text_bounded(*rect) + x0, y0, x1, y1 = rect + cells.append( + Cell( + id=cell_counter, + text=text_piece, + bbox=BoundingBox( + l=x0, b=y0, r=x1, t=y1, coord_origin=CoordOrigin.BOTTOMLEFT + ).to_top_left_origin(page_size.height), + ) ) - ) - cell_counter += 1 + cell_counter += 1 # PyPdfium2 produces very fragmented cells, with sub-word level boundaries, in many PDFs. # The cell merging code below is to clean this up. @@ -214,20 +222,24 @@ class PyPdfiumPageBackend(PdfPageBackend): padbox.r = page_size.width - padbox.r padbox.t = page_size.height - padbox.t - image = ( - self._ppage.render( - scale=scale * 1.5, - rotation=0, # no additional rotation - crop=padbox.as_tuple(), - ) - .to_pil() - .resize(size=(round(cropbox.width * scale), round(cropbox.height * scale))) - ) # We resize the image from 1.5x the given scale to make it sharper. + with pypdfium2_lock: + image = ( + self._ppage.render( + scale=scale * 1.5, + rotation=0, # no additional rotation + crop=padbox.as_tuple(), + ) + .to_pil() + .resize( + size=(round(cropbox.width * scale), round(cropbox.height * scale)) + ) + ) # We resize the image from 1.5x the given scale to make it sharper. return image def get_size(self) -> Size: - return Size(width=self._ppage.get_width(), height=self._ppage.get_height()) + with pypdfium2_lock: + return Size(width=self._ppage.get_width(), height=self._ppage.get_height()) def unload(self): self._ppage = None @@ -239,22 +251,26 @@ class PyPdfiumDocumentBackend(PdfDocumentBackend): super().__init__(in_doc, path_or_stream) try: - self._pdoc = pdfium.PdfDocument(self.path_or_stream) + with pypdfium2_lock: + self._pdoc = pdfium.PdfDocument(self.path_or_stream) except PdfiumError as e: raise RuntimeError( f"pypdfium could not load document with hash {self.document_hash}" ) from e def page_count(self) -> int: - return len(self._pdoc) + with pypdfium2_lock: + return len(self._pdoc) def load_page(self, page_no: int) -> PyPdfiumPageBackend: - return PyPdfiumPageBackend(self._pdoc, self.document_hash, page_no) + with pypdfium2_lock: + return PyPdfiumPageBackend(self._pdoc, self.document_hash, page_no) def is_valid(self) -> bool: return self.page_count() > 0 def unload(self): super().unload() - self._pdoc.close() - self._pdoc = None + with pypdfium2_lock: + self._pdoc.close() + self._pdoc = None diff --git a/docling/utils/locks.py b/docling/utils/locks.py new file mode 100644 index 00000000..558644da --- /dev/null +++ b/docling/utils/locks.py @@ -0,0 +1,3 @@ +import threading + +pypdfium2_lock = threading.Lock() From 0c1e9391de36c30a366505261edceca89931b561 Mon Sep 17 00:00:00 2001 From: Michele Dolfi <97102151+dolfim-ibm@users.noreply.github.com> Date: Mon, 3 Mar 2025 00:13:47 +0100 Subject: [PATCH 11/13] chore: use gh cache for huggingface models (#1096) * use gh cache for huggingface models Signed-off-by: Michele Dolfi * increase hf timeout Signed-off-by: Michele Dolfi * more timeout Signed-off-by: Michele Dolfi * use different cache key in each job Signed-off-by: Michele Dolfi --------- Signed-off-by: Michele Dolfi --- .github/workflows/checks.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 1c322d9a..b2a295dc 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -1,6 +1,10 @@ on: workflow_call: +env: + HF_HUB_DOWNLOAD_TIMEOUT: "60" + HF_HUB_ETAG_TIMEOUT: "60" + jobs: run-checks: runs-on: ubuntu-latest @@ -14,6 +18,11 @@ jobs: - name: Set TESSDATA_PREFIX run: | echo "TESSDATA_PREFIX=$(dpkg -L tesseract-ocr-eng | grep tessdata$)" >> "$GITHUB_ENV" + - name: Cache Hugging Face models + uses: actions/cache@v4 + with: + path: ~/.cache/huggingface + key: huggingface-cache-py${{ matrix.python-version }} - uses: ./.github/actions/setup-poetry with: python-version: ${{ matrix.python-version }} From b1e79cadc75bbfecc38965b96ae10d40e7b75efb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 3 Mar 2025 00:56:40 +0000 Subject: [PATCH 12/13] chore: bump version to 2.25.1 [skip ci] --- CHANGELOG.md | 11 +++++++++++ pyproject.toml | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 500808ba..917b3be0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +## [v2.25.1](https://github.com/DS4SD/docling/releases/tag/v2.25.1) - 2025-03-03 + +### Fix + +* Enable locks for threadsafe pdfium ([#1052](https://github.com/DS4SD/docling/issues/1052)) ([`8dc0562`](https://github.com/DS4SD/docling/commit/8dc0562542299cf972d14eeeb4393e50b589c8ad)) +* **html:** Use 'start' attribute when parsing ordered lists from HTML docs ([#1062](https://github.com/DS4SD/docling/issues/1062)) ([`de7b963`](https://github.com/DS4SD/docling/commit/de7b963b09a34916f0a8d99649269aeb37db1408)) + +### Documentation + +* Improve docs on token limit warning triggered by HybridChunker ([#1077](https://github.com/DS4SD/docling/issues/1077)) ([`db3ceef`](https://github.com/DS4SD/docling/commit/db3ceefd4ae6251a97e333bcb03051698b3fa71a)) + ## [v2.25.0](https://github.com/DS4SD/docling/releases/tag/v2.25.0) - 2025-02-26 ### Feature diff --git a/pyproject.toml b/pyproject.toml index afb98689..131e93ef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "docling" -version = "2.25.0" # DO NOT EDIT, updated automatically +version = "2.25.1" # DO NOT EDIT, updated automatically description = "SDK and CLI for parsing PDF, DOCX, HTML, and more, to a unified document representation for powering downstream workflows such as gen AI applications." authors = ["Christoph Auer ", "Michele Dolfi ", "Maxim Lysak ", "Nikos Livathinos ", "Ahmed Nassar ", "Panos Vagenas ", "Peter Staar "] license = "MIT" From 357d41cc47bcf69684643d193ed38f9baaf0d2f1 Mon Sep 17 00:00:00 2001 From: Michele Dolfi <97102151+dolfim-ibm@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:24:38 +0100 Subject: [PATCH 13/13] docs: Enrichment models (#1097) * warning for develop examples Signed-off-by: Michele Dolfi * add docs for enrichment models Signed-off-by: Michele Dolfi * minor reorg of top-level docs (#1098) * minor reorg of top-level docs Signed-off-by: Panos Vagenas * fix typo [no ci] Signed-off-by: Panos Vagenas <35837085+vagenas@users.noreply.github.com> --------- Signed-off-by: Panos Vagenas Signed-off-by: Panos Vagenas <35837085+vagenas@users.noreply.github.com> * trigger ci Signed-off-by: Michele Dolfi --------- Signed-off-by: Michele Dolfi Signed-off-by: Panos Vagenas Signed-off-by: Panos Vagenas <35837085+vagenas@users.noreply.github.com> Co-authored-by: Panos Vagenas <35837085+vagenas@users.noreply.github.com> --- README.md | 2 +- .../examples/develop_formula_understanding.py | 4 + docs/examples/develop_picture_enrichment.py | 4 + docs/{faq.md => faq/index.md} | 2 +- docs/index.md | 2 +- .../index.md} | 0 docs/usage/enrichments.md | 216 ++++++++++++++++++ docs/{usage.md => usage/index.md} | 14 +- docs/{ => usage}/supported_formats.md | 4 +- mkdocs.yml | 22 +- 10 files changed, 250 insertions(+), 20 deletions(-) rename docs/{faq.md => faq/index.md} (98%) rename docs/{installation.md => installation/index.md} (100%) create mode 100644 docs/usage/enrichments.md rename docs/{usage.md => usage/index.md} (93%) rename docs/{ => usage}/supported_formats.md (87%) diff --git a/README.md b/README.md index 5a957d60..842253e9 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,6 @@ For individual model usage, please refer to the model licenses found in the orig Docling has been brought to you by IBM. -[supported_formats]: https://ds4sd.github.io/docling/supported_formats/ +[supported_formats]: https://ds4sd.github.io/docling/usage/supported_formats/ [docling_document]: https://ds4sd.github.io/docling/concepts/docling_document/ [integrations]: https://ds4sd.github.io/docling/integrations/ diff --git a/docs/examples/develop_formula_understanding.py b/docs/examples/develop_formula_understanding.py index 2c631a8d..ca24d95d 100644 --- a/docs/examples/develop_formula_understanding.py +++ b/docs/examples/develop_formula_understanding.py @@ -1,3 +1,7 @@ +# WARNING +# This example demonstrates only how to develop a new enrichment model. +# It does not run the actual formula understanding model. + import logging from pathlib import Path from typing import Iterable diff --git a/docs/examples/develop_picture_enrichment.py b/docs/examples/develop_picture_enrichment.py index 86898889..9991afe9 100644 --- a/docs/examples/develop_picture_enrichment.py +++ b/docs/examples/develop_picture_enrichment.py @@ -1,3 +1,7 @@ +# WARNING +# This example demonstrates only how to develop a new enrichment model. +# It does not run the actual picture classifier model. + import logging from pathlib import Path from typing import Any, Iterable diff --git a/docs/faq.md b/docs/faq/index.md similarity index 98% rename from docs/faq.md rename to docs/faq/index.md index ae57446f..d1d05a8f 100644 --- a/docs/faq.md +++ b/docs/faq/index.md @@ -149,7 +149,7 @@ This is a collection of FAQ collected from the user questions on Token indices sequence length is longer than the specified maximum sequence length for this model (531 > 512). Running this sequence through the model will result in indexing errors This is a warning that is emitted by transformers, saying that actually *running this sequence through the model* will result in indexing errors, i.e. the problematic case is only if one indeed passes the particular sequence through the (embedding) model. diff --git a/docs/index.md b/docs/index.md index 18c12352..a0a1bb16 100644 --- a/docs/index.md +++ b/docs/index.md @@ -47,6 +47,6 @@ Docling simplifies document processing, parsing diverse formats — including ad Docling has been brought to you by IBM. -[supported_formats]: ./supported_formats.md +[supported_formats]: ./usage/supported_formats.md [docling_document]: ./concepts/docling_document.md [integrations]: ./integrations/index.md diff --git a/docs/installation.md b/docs/installation/index.md similarity index 100% rename from docs/installation.md rename to docs/installation/index.md diff --git a/docs/usage/enrichments.md b/docs/usage/enrichments.md new file mode 100644 index 00000000..96e10f16 --- /dev/null +++ b/docs/usage/enrichments.md @@ -0,0 +1,216 @@ +Docling allows to enrich the conversion pipeline with additional steps which process specific document components, +e.g. code blocks, pictures, etc. The extra steps usually require extra models executions which may increase +the processing time consistently. For this reason most enrichment models are disabled by default. + +The following table provides an overview of the default enrichment models available in Docling. + +| Feature | Parameter | Processed item | Description | +| ------- | --------- | ---------------| ----------- | +| Code understanding | `do_code_enrichment` | `CodeItem` | See [docs below](#code-understanding). | +| Formula understanding | `do_formula_enrichment` | `TextItem` with label `FORMULA` | See [docs below](#formula-understanding). | +| Picrure classification | `do_picture_classification` | `PictureItem` | See [docs below](#picture-classification). | +| Picture description | `do_picture_description` | `PictureItem` | See [docs below](#picture-description). | + + +## Enrichments details + +### Code understanding + +The code understanding step allows to use advance parsing for code blocks found in the document. +This enrichment model also set the `code_language` property of the `CodeItem`. + +Model specs: see the [`CodeFormula` model card](https://huggingface.co/ds4sd/CodeFormula). + +Example command line: + +```sh +docling --enrich-code FILE +``` + +Example code: + +```py +from docling.document_converter import DocumentConverter, PdfFormatOption +from docling.datamodel.pipeline_options import PdfPipelineOptions +from docling.datamodel.base_models import InputFormat + +pipeline_options = PdfPipelineOptions() +pipeline_options.do_code_enrichment = True + +converter = DocumentConverter(format_options={ + InputFormat.PDF: PdfFormatOption(pipeline_options=pipeline_options) +}) + +result = converter.convert("https://arxiv.org/pdf/2501.17887") +doc = result.document +``` + +### Formula understanding + +The formula understanding step will analize the equation formulas in documents and extract their LaTeX representation. +The HTML export functions in the DoclingDocument will leverage the formula and visualize the result using the mathml html syntax. + +Model specs: see the [`CodeFormula` model card](https://huggingface.co/ds4sd/CodeFormula). + +Example command line: + +```sh +docling --enrich-formula FILE +``` + +Example code: + +```py +from docling.document_converter import DocumentConverter, PdfFormatOption +from docling.datamodel.pipeline_options import PdfPipelineOptions +from docling.datamodel.base_models import InputFormat + +pipeline_options = PdfPipelineOptions() +pipeline_options.do_formula_enrichment = True + +converter = DocumentConverter(format_options={ + InputFormat.PDF: PdfFormatOption(pipeline_options=pipeline_options) +}) + +result = converter.convert("https://arxiv.org/pdf/2501.17887") +doc = result.document +``` + +### Picture classification + +The picture classification step classifies the `PictureItem` elements in the document with the `DocumentFigureClassifier` model. +This model is specialized to understand the classes of pictures found in documents, e.g. different chart types, flow diagrams, +logos, signatures, etc. + +Model specs: see the [`DocumentFigureClassifier` model card](https://huggingface.co/ds4sd/DocumentFigureClassifier). + +Example command line: + +```sh +docling --enrich-picture-classes FILE +``` + +Example code: + +```py +from docling.document_converter import DocumentConverter, PdfFormatOption +from docling.datamodel.pipeline_options import PdfPipelineOptions +from docling.datamodel.base_models import InputFormat + +pipeline_options = PdfPipelineOptions() +pipeline_options.generate_picture_images = True +pipeline_options.images_scale = 2 +pipeline_options.do_picture_classification = True + +converter = DocumentConverter(format_options={ + InputFormat.PDF: PdfFormatOption(pipeline_options=pipeline_options) +}) + +result = converter.convert("https://arxiv.org/pdf/2501.17887") +doc = result.document +``` + + +### Picture description + +The picture description step allows to annotate a picture with a vision model. This is also known as a "captioning" task. +The Docling pipeline allows to load and run models completely locally as well as connecting to remote API which support the chat template. +Below follow a few examples on how to use some common vision model and remote services. + + +```py +from docling.document_converter import DocumentConverter, PdfFormatOption +from docling.datamodel.pipeline_options import PdfPipelineOptions +from docling.datamodel.base_models import InputFormat + +pipeline_options = PdfPipelineOptions() +pipeline_options.do_picture_description = True + +converter = DocumentConverter(format_options={ + InputFormat.PDF: PdfFormatOption(pipeline_options=pipeline_options) +}) + +result = converter.convert("https://arxiv.org/pdf/2501.17887") +doc = result.document + +``` + +#### Granite Vision model + +Model specs: see the [`ibm-granite/granite-vision-3.1-2b-preview` model card](https://huggingface.co/ibm-granite/granite-vision-3.1-2b-preview). + +Usage in Docling: + +```py +from docling.datamodel.pipeline_options import granite_picture_description + +pipeline_options.picture_description_options = granite_picture_description +``` + +#### SmolVLM model + +Model specs: see the [`HuggingFaceTB/SmolVLM-256M-Instruct` model card](https://huggingface.co/HuggingFaceTB/SmolVLM-256M-Instruct). + +Usage in Docling: + +```py +from docling.datamodel.pipeline_options import smolvlm_picture_description + +pipeline_options.picture_description_options = smolvlm_picture_description +``` + +#### Other vision models + +The option class `PictureDescriptionVlmOptions` allows to use any another model from the Hugging Face Hub. + +```py +from docling.datamodel.pipeline_options import PictureDescriptionVlmOptions + +pipeline_options.picture_description_options = PictureDescriptionVlmOptions( + repo_id="", # <-- add here the Hugging Face repo_id of your favorite VLM + prompt="Describe the image in three sentences. Be consise and accurate.", +) +``` + +#### Remote vision model + +The option class `PictureDescriptionApiOptions` allows to use models hosted on remote platforms, e.g. +on local endpoints served by [VLLM](https://docs.vllm.ai), [Ollama](https://ollama.com/) and others, +or cloud providers like [IBM watsonx.ai](https://www.ibm.com/products/watsonx-ai), etc. + +_Note: in most cases this option will send your data to the remote service provider._ + +Usage in Docling: + +```py +from docling.datamodel.pipeline_options import PictureDescriptionApiOptions + +# Enable connections to remote services +pipeline_options.enable_remote_services=True # <-- this is required! + +# Example using a model running locally, e.g. via VLLM +# $ vllm serve MODEL_NAME +pipeline_options.picture_description_options = PictureDescriptionApiOptions( + url="http://localhost:8000/v1/chat/completions", + params=dict( + model="MODEL NAME", + seed=42, + max_completion_tokens=200, + ), + prompt="Describe the image in three sentences. Be consise and accurate.", + timeout=90, +) +``` + +End-to-end code snippets for cloud providers are available in the examples section: + +- [IBM watsonx.ai](../examples/pictures_description_api.py) + + +## Develop new enrichment models + +Beside looking at the implementation of all the models listed above, the Docling documentation has a few examples +dedicated to the implementation of enrichment models. + +- [Develop picture enrichment](../examples/develop_picture_enrichment.py) +- [Develop formula enrichment](../examples/develop_formula_understanding.py) diff --git a/docs/usage.md b/docs/usage/index.md similarity index 93% rename from docs/usage.md rename to docs/usage/index.md index 4b5e4ba1..033821b8 100644 --- a/docs/usage.md +++ b/docs/usage/index.md @@ -22,7 +22,7 @@ A simple example would look like this: docling https://arxiv.org/pdf/2206.01062 ``` -To see all available options (export formats etc.) run `docling --help`. More details in the [CLI reference page](./reference/cli.md). +To see all available options (export formats etc.) run `docling --help`. More details in the [CLI reference page](../reference/cli.md). ### Advanced options @@ -104,7 +104,7 @@ The options in this list require the explicit `enable_remote_services=True` when #### Adjust pipeline features -The example file [custom_convert.py](./examples/custom_convert.py) contains multiple ways +The example file [custom_convert.py](../examples/custom_convert.py) contains multiple ways one can adjust the conversion pipeline and features. ##### Control PDF table extraction options @@ -183,13 +183,13 @@ You can limit the CPU threads used by Docling by setting the environment variabl !!! note - This section discusses directly invoking a [backend](./concepts/architecture.md), + This section discusses directly invoking a [backend](../concepts/architecture.md), i.e. using a low-level API. This should only be done when necessary. For most cases, using a `DocumentConverter` (high-level API) as discussed in the sections above should suffice — and is the recommended way. -By default, Docling will try to identify the document format to apply the appropriate conversion backend (see the list of [supported formats](./supported_formats.md)). -You can restrict the `DocumentConverter` to a set of allowed document formats, as shown in the [Multi-format conversion](./examples/run_with_formats.py) example. +By default, Docling will try to identify the document format to apply the appropriate conversion backend (see the list of [supported formats](../supported_formats.md)). +You can restrict the `DocumentConverter` to a set of allowed document formats, as shown in the [Multi-format conversion](../examples/run_with_formats.py) example. Alternatively, you can also use the specific backend that matches your document content. For instance, you can use `HTMLDocumentBackend` for HTML pages: ```python @@ -214,9 +214,9 @@ print(dl_doc.export_to_markdown()) ## Chunking -You can chunk a Docling document using a [chunker](concepts/chunking.md), such as a +You can chunk a Docling document using a [chunker](../concepts/chunking.md), such as a `HybridChunker`, as shown below (for more details check out -[this example](examples/hybrid_chunking.ipynb)): +[this example](../examples/hybrid_chunking.ipynb)): ```python from docling.document_converter import DocumentConverter diff --git a/docs/supported_formats.md b/docs/usage/supported_formats.md similarity index 87% rename from docs/supported_formats.md rename to docs/usage/supported_formats.md index 0892ae1a..4d1ca4f9 100644 --- a/docs/supported_formats.md +++ b/docs/usage/supported_formats.md @@ -1,6 +1,6 @@ Docling can parse various documents formats into a unified representation (Docling Document), which it can export to different formats too — check out -[Architecture](./concepts/architecture.md) for more details. +[Architecture](../concepts/architecture.md) for more details. Below you can find a listing of all supported input and output formats. @@ -22,7 +22,7 @@ Schema-specific support: |--------|-------------| | USPTO XML | XML format followed by [USPTO](https://www.uspto.gov/patents) patents | | JATS XML | XML format followed by [JATS](https://jats.nlm.nih.gov/) articles | -| Docling JSON | JSON-serialized [Docling Document](./concepts/docling_document.md) | +| Docling JSON | JSON-serialized [Docling Document](../concepts/docling_document.md) | ## Supported output formats diff --git a/mkdocs.yml b/mkdocs.yml index 36bcacb5..b0c01c5e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -54,11 +54,14 @@ theme: nav: - Home: - "Docling": index.md - - Installation: installation.md - - Usage: usage.md - - Supported formats: supported_formats.md - - FAQ: faq.md - - Docling v2: v2.md + - Installation: + - Installation: installation/index.md + - Usage: + - Usage: usage/index.md + - Supported formats: usage/supported_formats.md + - Enrichment features: usage/enrichments.md + - FAQ: + - FAQ: faq/index.md - Concepts: - Concepts: concepts/index.md - Architecture: concepts/architecture.md @@ -72,11 +75,8 @@ nav: - "Batch conversion": examples/batch_convert.py - "Multi-format conversion": examples/run_with_formats.py - "Figure export": examples/export_figures.py - - "Figure enrichment": examples/develop_picture_enrichment.py - "Table export": examples/export_tables.py - "Multimodal export": examples/export_multimodal.py - - "Annotate picture with local vlm": examples/pictures_description.ipynb - - "Annotate picture with remote vlm": examples/pictures_description_api.py - "Force full page OCR": examples/full_page_ocr.py - "Automatic OCR language detection with tesseract": examples/tesseract_lang_detection.py - "RapidOCR with custom OCR models": examples/rapidocr_with_custom_models.py @@ -90,6 +90,12 @@ nav: - examples/rag_haystack.ipynb - examples/rag_langchain.ipynb - examples/rag_llamaindex.ipynb + - 🖼️ Picture annotation: + - "Annotate picture with local VLM": examples/pictures_description.ipynb + - "Annotate picture with remote VLM": examples/pictures_description_api.py + - ✨ Enrichment development: + - "Figure enrichment": examples/develop_picture_enrichment.py + - "Formula enrichment": examples/develop_formula_understanding.py - 🗂️ More examples: - examples/rag_weaviate.ipynb - RAG with Granite [↗]: https://github.com/ibm-granite-community/granite-snack-cookbook/blob/main/recipes/RAG/Granite_Docling_RAG.ipynb