diff --git a/src/blueink/bundle_helper.py b/src/blueink/bundle_helper.py index 0e720c2..697fa9c 100644 --- a/src/blueink/bundle_helper.py +++ b/src/blueink/bundle_helper.py @@ -114,6 +114,20 @@ def add_document_by_file(self, file: io.FileIO, **additional_data) -> str: return self.add_document_by_b64(filename, b64str, **additional_data) + def add_document_by_html(self, html_content: str, **additional_data) -> str: + """Add a document using an HTML string for HTML-to-PDF conversion. + + Args: + html_content: HTML content string + additional_data: Optional additional kwargs (e.g., filename, html_fields_mode) + + Returns: + Document Key + """ + document = Document.create(file_html=html_content, **additional_data) + self._documents[document.key] = document + return document.key + def add_document_by_b64(self, filename: str, b64str: str, **additional_data): """Add a file using a b64 string; utf-8 encoded @@ -212,6 +226,8 @@ def add_field( v_pattern: str = None, v_min: int = None, v_max: int = None, + v_regex: str = None, + v_regex_msg: str = None, v_attachment_types: List[str] = None, key=None, **additional_data, @@ -230,6 +246,8 @@ def add_field( v_pattern: Optional v_min: Optional v_max: Optional + v_regex: Optional regular expression for field validation + v_regex_msg: Optional error message shown when v_regex validation fails v_attachment_types: Optional list of allowed attachment file extensions (only for kind='att') editors: Optional key: Optional @@ -252,6 +270,8 @@ def add_field( v_pattern=v_pattern, v_min=v_min, v_max=v_max, + v_regex=v_regex, + v_regex_msg=v_regex_msg, v_attachment_types=v_attachment_types, key=key, **additional_data, diff --git a/src/blueink/model/bundles.py b/src/blueink/model/bundles.py index 9a11659..ff2fe30 100644 --- a/src/blueink/model/bundles.py +++ b/src/blueink/model/bundles.py @@ -94,6 +94,8 @@ class Field(BaseModel): v_pattern: Optional[int] v_min: Optional[int] v_max: Optional[int] + v_regex: Optional[str] + v_regex_msg: Optional[str] editors: Optional[List[str]] v_attachment_types: Optional[List[str]] @@ -248,9 +250,11 @@ class Document(BaseModel): file_url: Optional[str] filename: Optional[str] file_b64: Optional[str] + file_html: Optional[str] file_index: Optional[int] fields: Optional[List[Field]] auto_placements: Optional[List[AutoPlacement]] + html_fields_mode: Optional[str] class Config: extra = "allow" diff --git a/src/blueink/tests/test_bundle_helper.py b/src/blueink/tests/test_bundle_helper.py index c5d6700..3437289 100644 --- a/src/blueink/tests/test_bundle_helper.py +++ b/src/blueink/tests/test_bundle_helper.py @@ -370,3 +370,78 @@ def test_field_with_attachment_types(self): self.assert_equal(field["kind"], "att") self.assert_equal(field["v_attachment_types"], ["pdf", "docx"]) + + def test_adding_document_via_html(self): + """Test adding a document using HTML content""" + input_data = copy.deepcopy(self.BUNDLE_INIT_DATA) + html_content = "
Test document
" + + bh = BundleHelper(**input_data) + doc_key = bh.add_document_by_html(html_content) + + compiled_bundle = bh.as_data() + + self.assert_in("documents", compiled_bundle) + self.assert_len(compiled_bundle["documents"], 1) + + doc = compiled_bundle["documents"][0] + self.assert_in("file_html", doc) + self.assert_equal(doc["file_html"], html_content) + self.assert_equal(doc["key"], doc_key) + + def test_adding_document_via_html_with_filename(self): + """Test adding an HTML document with a custom filename""" + input_data = copy.deepcopy(self.BUNDLE_INIT_DATA) + html_content = "Test document
" + + bh = BundleHelper(**input_data) + bh.add_document_by_html(html_content, filename="my_doc.pdf") + + compiled_bundle = bh.as_data() + doc = compiled_bundle["documents"][0] + + self.assert_equal(doc["file_html"], html_content) + self.assert_equal(doc["filename"], "my_doc.pdf") + + def test_adding_document_via_html_with_fields_mode(self): + """Test adding an HTML document with html_fields_mode""" + input_data = copy.deepcopy(self.BUNDLE_INIT_DATA) + html_content = "Test document
" + + bh = BundleHelper(**input_data) + bh.add_document_by_html(html_content, html_fields_mode="blueink") + + compiled_bundle = bh.as_data() + doc = compiled_bundle["documents"][0] + + self.assert_equal(doc["file_html"], html_content) + self.assert_equal(doc["html_fields_mode"], "blueink") + + def test_field_with_v_regex(self): + """Test adding a field with v_regex and v_regex_msg""" + input_data = copy.deepcopy(self.BUNDLE_INIT_DATA) + url01 = self.DOCUMENT_01_URL + signer01_data = copy.deepcopy(self.SIGNER_01_DATA) + + bh = BundleHelper(**input_data) + doc01_key = bh.add_document_by_url(url01) + signer01_key = bh.add_signer(**signer01_data) + + bh.add_field( + document_key=doc01_key, + x=10, + y=20, + w=30, + h=10, + p=1, + kind="inp", + editors=[signer01_key], + v_regex="^[A-Z]+$", + v_regex_msg="Uppercase letters only", + ) + + compiled_bundle = bh.as_data() + field = compiled_bundle["documents"][0]["fields"][0] + + self.assert_equal(field["v_regex"], "^[A-Z]+$") + self.assert_equal(field["v_regex_msg"], "Uppercase letters only")