Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include radio buttons when processing forms #2143

Merged
merged 12 commits into from May 14, 2024
Merged

Conversation

okkays
Copy link
Contributor

@okkays okkays commented May 1, 2024

Hello!

Resolves #1831

This aims to make radio buttons work in forms.

  • 🌎 Currently, inputs are collected and rendered individually.
  • ⛔ This means that groups of elements, such as radio buttons which may only have one value checked at once, don't have a way to identify other elements in the group.
  • ✅ This PR keeps a concept of "forms" in between "page" and "inputs", and uses those forms to build groups of radio buttons.

This is my first time reading the PDF specification (such fun!) so appreciate any scrutiny of the dictionaries I have it making.

Added a few unit tests as well, but here's a working example:

example.pdf

example

Created with:

import weasyprint

html = '''
<!DOCTYPE html><html><body>
<form><h2>Form 1</h2>
<p>Radio 1:</p>
    <label>Option One <input type="radio" name="radio1" value="1"/></label>
    <label>Option Two <input type="radio" name="radio1" value="2"/></label>
<p>Radio 2:</p>
    <label>Option One <input type="radio" name="radio2" value="1"/></label>
    <label>Option Two <input type="radio" name="radio2" value="2"/></label>
</form>

<form id="two">
<h2>Form 2</h2>
<p>Radio 1:</p>
    <label>Option One <input type="radio" name="radio1" value="1"/></label>
    <label>Option Two <input type="radio" name="radio1" value="2"/></label>
<p>Radio 2:</p>
    <label>Option One <input type="radio" name="radio2" value="1"/></label>
    <label>Option Two <input type="radio" name="radio2" value="2"/></label>
</form>
</body></html>
'''

weasyprint.HTML(string=html).write_pdf('output.pdf', pdf_forms=True)

Thanks for taking a look. Happy to change / reformat as needed!

- 🌎 Currently, inputs are collected and rendered individually.
- ⛔ This means that groups of elements, such as radio buttons which may only have one value checked at once, don't have a way to identify other elements in the group.
- ✅ This commit keeps a concept of "forms" in between "page" and "inputs", and uses those forms to build groups of radio buttons.
@liZe liZe added this to the 63.0 milestone May 12, 2024
@liZe
Copy link
Member

liZe commented May 13, 2024

Thanks a lot for your pull request!

I’ve added some commits to fix the problems I’ve found. The generated PDF files are now valid according to some PDF validators, but they’re still broken with GhostScript. I’ll fix that as soon as I find the reason why.

I’ve tried different PDF viewers, including Adobe Reader and browsers, it seems to work with most of them (Evince being the one that doesn’t, but it was already kind of broken with checkboxes…).

@alenards
Copy link
Contributor

@liZe - I tried to Adobe Reader last week and didn't make it over here to post/mention the messages.

Is there anything I can assist with on testing/verifying?

This way works with many PDF readers and validators.
@liZe
Copy link
Member

liZe commented May 13, 2024

Is there anything I can assist with on testing/verifying?

I’ve tested the current code, it seems to work with Ghostscript, Adobe Reader, Pdf.js, Okular, Foxit, and a PDF validator. Evince is a bit broken, it was with checkboxes too, but Okular (that is also based on Poppler) works well, so I suppose it’s a bug in Evince.

If you could test with different HTML files on the different PDF readers you have on your computer, that would be wonderful! 💜

(As always with PDF forms, the specification is not perfect and different implementations have different undocumented requirements. That’s why the code can be strange sometimes.)

@alenards
Copy link
Contributor

alenards commented May 14, 2024

I realized one interesting test case is the "Lesson Forms" from https://print-css.rocks/lesson/lesson-forms

example__print_css_lesson_forms.pdf

All fields are editable, code used to write pdf is same as PR description.

📝 The submit button input isn't clickable, doesn't render the text "Save" in it.

Tested on macOS:

  • Preview.app
  • Adobe Reader
  • Google Chrome rendering via file:///
  • Safari rendering via file:///
Screenshots

Edit, Save, View

✅ Google Chrome
✅ Safari
✅ Preview.app (macOS only)

Adobe Reader

❌ saving in Adobe Reader seems to be mangled the styling:

example__print_css_lesson_forms_adobe.pdf

That might be a known Adobe Reader issue though.

Adobe Reader Version info


"View" Examples (All macOS)

Using the following apps, can open and view the PDF as expected.

Version: macOS 14.4.1

Safari

Screenshot 2024-05-13 at 5 06 31 PM

Preview.app (macOS)

Screenshot 2024-05-13 at 5 08 29 PM

Adobe Reader

Screenshot 2024-05-13 at 5 07 53 PM

Google Chrome

Screenshot 2024-05-13 at 5 07 24 PM

python repl to generate pdf

I used the HTML input from here https://print-css.rocks/lesson/lesson-forms

No stylesheet to begin with.

I have the okkays:kk/radio-buttons branch local.

macOS 14.4.1, Python 3.9.9, ghostscript & pango installed from brew.

python                                                                                                   lenards@Andrews-MBP
Python 3.9.9 (main, Feb 20 2024, 15:40:24)
[Clang 15.0.0 (clang-1500.1.0.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import weasyprint
>>> html = '''
... <html>
...     <head>
...         <link rel="stylesheet" type="text/css" href="styles.css" />
...     </head>
...     <body>
...         <form method="POST">
...             <fieldset>
...                 <legend>Test form</legend>
...
...                 <div class="row">
...                     First name:
...                     <input type="text" name="firstname" value="" placeholder="Firstname"/>
...                 </div>
...                 <div class="row">
...                     Last name:
...                     <input type="text" name="lastname" value="" placeholder="Lastname"/>
...                 </div>
...                 <div class="row">
...                     <input type="checkbox"> Married?
...                 </div>
...                 <div class="row">
...                     Gender:
...                     <br/>
...                     <input type="radio" name="gender" value="male">Male
...                     <br/>
...                     <input type="radio" name="gender" value="female">Female
...                     <br/>
...                     <input type="radio" name="gender" value="diverse">Diverse
...                 </div>
...                 <div class="row">
...                     Gender 2:
...                     <select name="testdata">
...                         <option value="male">Male</option>
...                         <option value="female">Female</option>
...                         <option value="diverse">Diverse3</option>
...                     </select>
...                 </div>
...                 <div class="row">
...                     Comment
...                     <br/>
...                     <textarea rows="5" cols="60"></textarea>
...                 </div>
...                 <div class="row">
...                     <input type="submit" value="Save"/>
...                 </div>
...             </fieldset>
...         </form>
...     </body>
... </html>
... '''
>>> weasyprint.HTML(string=html).write_pdf('output.pdf', pdf_forms=True)
>>>

📝 I'll post viewing the attached PDF from Windows PDF views later today

@liZe
Copy link
Member

liZe commented May 14, 2024

Thanks for your feedback.

saving in Adobe Reader seems to be mangled the styling

I’ll try to see if there’s anything to do about this. If the bug is already there in stable releases, we can merge the pull request as it doesn’t break anything. If it’s introduced by the bug report, then we have to fix it before merging.

The submit button input isn't clickable, doesn't render the text "Save" in it.

That’s because button and submit inputs are not supported. It’s also not possible to send forms to websites. Interested in opening a new PR for this? 😄

@liZe
Copy link
Member

liZe commented May 14, 2024

saving in Adobe Reader seems to be mangled the styling

I tried to edit the form and save the document with Adobe Acrobat Reader on Windows, it worked for me. I have version 2024.002.20736, maybe that’s why. (And a new 20759 version has even been released today.)

If it’s OK for you, I think that we can merge this PR

@alenards
Copy link
Contributor

If it’s OK for you, I think that we can merge this PR

I think that would fantastic! Most excellent - thank you! 🙌

😮‍💨 I had issues w/ my Windows 10 laptop last night, so I'm glad you were able to get in testing on that platform.

@alenards
Copy link
Contributor

The submit button input isn't clickable, doesn't render the text "Save" in it.

That’s because button and submit inputs are not supported. It’s also not possible to send forms to websites. Interested in opening a new PR for this? 😄

Sure @liZe - I'd be up to take a look into getting the text to render in a separate PR.

I'll to look at the spec; I'm puzzled what clicking on "Save" would do.

@liZe
Copy link
Member

liZe commented May 14, 2024

I'd be up to take a look into getting the text to render in a separate PR.

🚀

I'll to look at the spec; I'm puzzled what clicking on "Save" would do.

No idea. There’s probably a lot of work to store data in a way that makes PDF readers send the right HTTP requests…

@liZe liZe merged commit 6518579 into Kozea:main May 14, 2024
6 checks passed
@alenards
Copy link
Contributor

🙌 🎉 🎊

Awesome work @okkays! Thank you @liZe!!!

@alenards
Copy link
Contributor

I forgot to mention that if you structure the HTML to prefill information for the radio buttons (and checkbox, textfields, etc), you get what you'd expect! 🎉

example_form_pre_fill.pdf

On macOS, Preview.app ...

Screenshot 2024-05-15 at 11 31 17 AM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support for editable forms lacks support for radio buttons
3 participants