hugo icon indicating copy to clipboard operation
hugo copied to clipboard

Support CJK in images.Text, add width and height as optional args

Open naa0yama opened this issue 1 year ago • 7 comments

When I started using Hugo, I was really drawn to the "images.Text" feature. I'm trying to use this to generate images for the Open Graph Protocol.

Since it does not support CJK, it is in a state where it is not wrapped as shown below.

{{- $font := resources.Get "/fonts/NotoSansJP-Bold.ttf" -}}
{{- $img_base := resources.Get "/img/ogp.png" -}}
{{- $img_base = $img_base.Filter (images.Text "あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみぬめもあいうえおかきくけこさしすせそたちつてとなにぬねの" (
        dict
            "color" "#ffffff"
            "size" 60
            "linespacing" 2
            "x" 130
            "y" 220
            "font" $font
        )
    )
-}}

ogp_hufdd91d49eff6d1dff05547c7d4a76f06_74228_59b8087107427e41d2c791161541b873

Workaround

As a workaround, it can be handled by separating with spaces at moderate intervals, but I thought it would be easier to use if you could define a text area like a CSS margin. Could you consider adding it as a feature?

  • Avoidance example
{{- $img_base = $img_base.Filter (images.Text "あいうえおかきくけこさしすせそ たちつてとなにぬねのはひふへほ まみぬめもあいうえおかきくけ こさしすせそたちつてとなにぬねの" (
        dict
            "color" "#ffffff"
            "size" 60
            "linespacing" 2
            "x" 130
            "y" 220
            "font" $font
        )
    )
-}}

ogp_hufdd91d49eff6d1dff05547c7d4a76f06_74228_490208ae06a351d5c4cd8b1ac2e294fb

naa0yama avatar Aug 17 '23 04:08 naa0yama

Could you consider adding it as a feature?

Yes, I can see how that would be useful (even for non CJK languages), but I'm not totally sure how the API would look like.

  • I guess a width (of text block, in pixels) would make sense.
  • But how do we break words?

bep avatar Aug 17 '23 08:08 bep

Thank you for having interest.

  • I guess a width (of text block, in pixels) would make sense.

My first thought was to fit the page title in the blue border of the image. Therefore, I decided to output a character string in Font size (size: 60), check the number of characters that fit, and insert a space there to make a line break. In order to make this mechanical, I thought that if the margins on the four sides could be defined, it would be possible to calculate from the font size, which is the reason why I made the proposal.

  • But how do we break words?

Japanese is very difficult, so even Japanese people have different opinions on where to cut phrases and words (laughs). I don't think it's worth the cost to do it with Hugo, so I think the following is fine.

  • Allow setting margins on "images.Text"
    • Calculate whether it exceeds the margin size and break a line.
      • CJK: Line break before 1 character exceeding margin.
      • Not CJK: line break before the word.
    • Option: Support for newline characters, etc., so that users can break lines. Example: \n, etc.

The projects below may be helpful. I initially thought about using it, but it seemed incompatible with the environment I was using, so I wanted to use Hugo's functions. Ladicle/tcardgen: Generate a TwitterCard(OGP) image for your Hugo posts.

In the case of CJK, this project seems to be output as follows, and it seems that Japanese clauses are not conscious

naa0yama avatar Aug 17 '23 09:08 naa0yama

In order to make this mechanical, I thought that if the margins on the four sides could be defined, it would be possible to calculate from the font size, which is the reason why I made the proposal.

Yea, we could do something like that.

I guess the left/top margin is somehow covered by the current x/y parameters.

What if we make it top, right bottom, left?

And retire/alias x/y.

bep avatar Aug 21 '23 12:08 bep

Plan1

I thought about several patterns, but I felt that the optimum was different depending on the person. If you want to think about the design and put it there like me, you can substitute "x,y" of "images.Text" for the upper left specification. And if you can define the lower right coordinates, it seems that you can define the square (gray part) of the text box. I'm excited that I can write like this when writing in config.yaml

# config.yaml
params:
  opengraph:
    x: 120 # images.Text x
    y: 240 # images.Text y
    bottom_right:
      x: 1160
      y: 590

ogp

Plan2

On the other hand, while drawing a diagram, I thought that it might be easier to use if the width and height were input. The reason for calculating and using the lower right coordinate is that the size of the image you want to use "images.Text" must be the same. In this case, simply control the width so that the characters do not exceed the x-coordinate, and the height is the same. I felt that it was intuitive and easy to understand even if it became an option of "images.Text".

{{- $img_base = $img_base.Filter (images.Text "あいうえおかき…" (
        dict
            "color" "#ffffff"
            "size" 60
            "linespacing" 2
            "x" 120
            "y" 240
            "width" 1040
            "height" 350
            "font" $font
        )
    )
-}}

Therefore, I personally think that Plan2 may be more beneficial for those who want to use it in the future, so how about this?

naa0yama avatar Aug 21 '23 14:08 naa0yama

I like plan 2, easy to understand.

bep avatar Aug 22 '23 06:08 bep

It will be nice, if letterspacing option can be introduced.

If introduced, the modified plan 2 will look like this:

{{- $img_base = $img_base.Filter (images.Text "あいうえおかき…" (
        dict
            "color" "#ffffff"
            "size" 60
            "linespacing" 2
            "letterspacing" 1
            "x" 120
            "y" 240
            "width" 1040
            "height" 350
            "font" $font
        )
    )
-}}

hugo-sid avatar Sep 23 '23 11:09 hugo-sid

letter-spacing is a nice feature. I did not know this CSS property.

It might be useful if some users want to have equally spaced letters in width and height boxes.

naa0yama avatar Sep 23 '23 16:09 naa0yama