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

add PdfImageAsset #79

Merged
merged 6 commits into from
Feb 12, 2024
Merged

Conversation

ArielMejiaDev
Copy link
Contributor

What makes the PR

It adds a new class helper that encodes as base 64 images, no matter if the image path is relative or an absolute path, and also adds some prefix required for image assets in headers and footers to display images successfully by puppeteer.

The code would look like this

    public function __invoke(): PdfBuilder
    {
        return pdf('pdf.invoice', [
            'invoiceNumber' => '1234',
            'customerName' => 'Grumpy Cat',
        ])->footerView('components.footer', [
            'image' => PdfImageAsset::make('https://avatars.githubusercontent.com/u/7535935?s=200&v=4')
        ])->headerView('components.header', [
            'image' => PdfImageAsset::make(public_path('assets/spatie-logo.png')),
        ]);
    }

It would solve a lot of discussions and issues about how to add images to headers and footers.

like:

I add it as a support class as its concern is simple, I doubt adding the functionality as a trait to the PdfBuilder class but just makes more sense to handle it as a static helper.

Testing

It also adds its test `PdfImageAssetTest.

Docs

It also adds some suggested text for docs in headers and footers.

Demo about the issue

It solves the issue talked about in discussion #71

https://www.loom.com/share/8912fba845214a1d93aefc99fcf93b93?sid=c0389007-fcdf-4110-bee1-82317fc53c91

@freekmurze
Copy link
Member

Thanks for your work on this PR.

I like the functionality, but I think it could be make easier to use. Instead of letting users call PdfImageAsset::make in a controller, let's provide a Blade directive for them.

It could work like this in a Blade view

@inlidedImage($url)

This way, the controller doesn't have to know that images should be inlined.

Could you make this change? Thanks!

@RVP04
Copy link
Contributor

RVP04 commented Feb 9, 2024

@freekmurze appreciated for the suggestion @ArielMejiaDev welcoming to do it and waiting for the push

@ArielMejiaDev
Copy link
Contributor Author

Thanks for your work on this PR.

I like the functionality, but I think it could be make easier to use. Instead of letting users call PdfImageAsset::make in a controller, let's provide a Blade directive for them.

It could work like this in a Blade view

@inlidedImage($url)

This way, the controller doesn't have to know that images should be inlined.

Could you make this change? Thanks!

I am on it! thanks

@RVP04
Copy link
Contributor

RVP04 commented Feb 9, 2024

Eagerly waiting @ArielMejiaDev

@ArielMejiaDev
Copy link
Contributor Author

Hi @freekmurze there is a commit, if you can check this loom (I try to make it short & fun, sorry the audio) you would see the behavior now with a directive (looks lot more cleaner).

Demo

https://www.loom.com/share/e3a5fc63f7894b779371e4c5d13a6a0d?sid=80074810-3d33-4ac6-9293-9d7061afc2b4

I was not able to run all Pest tests that uses toContainText because I do not find how to install pdfToText package with Hombrew

expect()->extend('toContainText', function (string|array $expectedText) {
    $binPath = PHP_OS === 'Linux'
        ? '/usr/bin/pdftotext'
        : '/opt/homebrew/bin/pdftotext';

@RVP04
Copy link
Contributor

RVP04 commented Feb 9, 2024

@freekmurze waiting for you

@RVP04
Copy link
Contributor

RVP04 commented Feb 10, 2024

@freekmurze waiting please

@freekmurze
Copy link
Member

@RVP04 Thanks for your enthusiasm but please refrain from posting reminders here and on other social channels. That won't make me working faster.

Copy link
Member

@freekmurze freekmurze left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ArielMejiaDev Thanks for your work on this!

@@ -48,6 +48,16 @@ Inside the footer, you can use the following Blade directives:
- `@pageNumber`: The current page number
- `@totalPages`: The total number of pages

### Display Images in Headers and Footers

You can add an image using the blade directive `@inlidedImage`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be renamed to inlinedImage everywhere in this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @freekmurze , the directive name has been fixed, hopefully it helps and thanks for your efforts

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RVP04
Copy link
Contributor

RVP04 commented Feb 12, 2024

Because I am eagerly waiting for you

@freekmurze freekmurze merged commit ebe2e03 into spatie:main Feb 12, 2024
1 check passed
@freekmurze
Copy link
Member

Thanks!

@Professor93M
Copy link

How I can use PdfImageAsset with the pdf. because it's not found?
and I tried to add image to the header but it's not worked

@ArielMejiaDev
Copy link
Contributor Author

How I can use PdfImageAsset with the pdf. because it's not found? and I tried to add image to the header but it's not worked

@Professor93M

You can set images using the directive:

@imageInlined('your-image.png')

@Professor93M
Copy link

@ArielMejiaDev
Not work with me.
I tried all of these and nothing show:
@imageInline('images/logo.png')
<img src="{{ asset('images/logo.png') }}">
<img src="{{ public_path('images/logo.png') }}">

But when I used these lines of code:
@inlinedImage('images/logo.png')
<img src="data:image/png;base64,{{base64_encode(file_get_contents(public_path('images/logo.png')))}}">

the pages will not responding and show me This site can’t be reached and I have to stop the serve and re run it by php artisan serve

Please help me if you have any idea.

@RVP04
Copy link
Contributor

RVP04 commented Apr 8, 2024

You have to use

@imageInlined('your-image.png')

Check yours it is wrong @inlinedImage()

@ArielMejiaDev
Copy link
Contributor Author

Hi @Professor93M as @RVP04 says sorry the correct directive is @imageInlined(), so your current code should look like this:

@imageInlined('images/logo.png')

or using an object property

@imageInlined($model->image)

@Professor93M
Copy link

Do you mean like that:

<div dir="rtl" style="miargin: 20px auto; padding: 20px 70px; width: 100%;">
    <div style="display: flex; justify-content: space-between; align-items: center;">
        <h1 style="font-size: 16px; font-weight: 700; width: 150px; text-align: center;">Title</h1>
        @imageInlined('images/logo.png')
        <h1 style="font-size: 14px; font-weight: 700; width: 200px; text-align: center;">Title2</h1>
    </div>
    <hr style="border: 1px solid #DE9C55; width: 100%;">
</div>
return pdf('Print.pdf', compact('invoice', 'exchange'))
            ->footerView('Print.footer')
            ->headerView('Print.header')
            ->margins(30, 5, 15, 5)
            ->landscape()
            ->format(Format::A5);

I tried that but it show only the text like that: @imageInlined('images/logo.png')

@ArielMejiaDev
Copy link
Contributor Author

@Professor93M please check first that the file exists in your public directory, then you can follow this example https://github.com/ArielMejiaDev/laravel-pdf-demo/blob/main/resources/views/components/header.blade.php you can check the whole app to see controllers, public directory, resources/views to check blade files etc.

@Professor93M
Copy link

I used @imageInlined directive but it's not work with me.
I used this code I think it's work but there is problem with my server I think

<figure>
    @inlinedImage('images/logo.png')
</figure>

It show me this page even if I refresh it:
image

and I have to stop the server and restart it again.

@RVP04
Copy link
Contributor

RVP04 commented Apr 8, 2024

First check in view whether file is loading or not. Share your actual code controller and view properly to troubleshoot

Also try to clear cache, config and view

@Professor93M
Copy link

This my code:

Controller

public function invoice($id)
    {
        return pdf('Print.pdf')
            ->footerView('Print.footer')
            ->headerView('Print.header')
            ->margins(30, 5, 15, 5)
            ->landscape()
            ->format(Format::A5);
    }

pdf.blade.php (View)

<html>
    <head>
        <title>Invoice</title>
        <script src="https://cdn.tailwindcss.com"></script>
    </head>
    <body dir="rtl">
        <div class="flex mx-auto space-x-2 sm:space-x-4 font-['Almarai']">
            <div class="w-full px-10">
                <h1 class="text-xl text-center font-bold">Invoice</h1>
            </div>
        </div>
    </body>
</html>

header.blade.php

<div dir="rtl" style="miargin: 20px auto; padding: 20px 70px; width: 100%;">
    <div style="display: flex; justify-content: space-between; align-items: center;">
        <h1 style="font-size: 16px; font-weight: 700; width: 150px; text-align: center;">Title</h1>
        <figure>
            @inlinedImage('images/logo.png')
        </figure>
        <h1 style="font-size: 14px; font-weight: 700; width: 200px; text-align: center;">Title2</h1>
    </div>
    <hr style="border: 1px solid #DE9C55; width: 100%;">
</div>

I run php artisan optimize

same problem

@Professor93M
Copy link

Any comment gents?
Please need help

@RVP04
Copy link
Contributor

RVP04 commented Apr 11, 2024 via email

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.

4 participants