penpot/penpot

bug: Creating a text using the external penpot library (lib-penpot) to import from Figma does not work as expected

Cenadros opened this issue · 8 comments

Steps To Reproduce

We're currently working in the penpot-exporter plugin and we've encountered an issue when trying to export text from Figma and import it to Penpot. The steps to reproduce the behavior are as follow:

  1. Call the createText method on the penpot library.
  2. Based on how TextShape is created:
  • If we create the text shape with position-data we're unable to import the text correctly into Penpot because position-data requires a position, width and height for every piece of text, and Figma does not provide this information in the API.
  • If we create the text shape without position-data the import does not work because the foreign-object is not being rendered in the svg. This is caused because the flag is-component? is false as taken from the context in https://github.com/penpot/penpot/blob/staging/frontend/src/app/main/ui/shapes/text.cljs
(mf/defc text-shape
  {::mf/wrap-props false}
  [props]
  (let [{:keys [position-data content] :as shape} (obj/get props "shape")
        is-component? (mf/use-ctx ctx/is-component?)]

    (mf/with-memo [content]
      (load-fonts! content))

    ;; Old components can have texts without position data that must be rendered via foreign key
    (cond
      (some? position-data) [:> svg/text-shape props]
      is-component?             [:> fo/text-shape props])))

More code here: penpot/penpot-exporter-figma-plugin#61

The code can be executed in a simple Figma file:

  1. Compile with npm run build (node 20)
  2. Import plugin in Figma
  3. Create a simple document with a text with several words
  4. Try to export and import into Penpot.

Expected behavior

On previous versions of the penpot library the flag checking position-data was different, allowing to use foreign-object and thus allowing the export from Figma and import to Penpot work:

(if (some? position-data)
      [:> svg/text-shape props]
      [:> fo/text-shape props])))

This was changed here: #3000

Seeing that foreign-object is something you apparently want to remove, is there any way we can use position-data without having to define each word position and dimension? If not is there any way we can force to use foreign-object?

Actual behavior

When the .zip is created and imported to penpot the text is not positioned correctly. When exported with position-data we're unable to set position/dimension for every word. When exported without position-data the foreign-object is not created and the imported text is always at position (0,0) with height/width 0.

Screenshots or video

  1. With position-data: https://www.loom.com/share/133a189d72ec47fc81190adfc767eb6c?sid=d9ccc933-be7a-4d67-a41a-af0609a4d773
  2. Without position-data: https://www.loom.com/share/eb2ac3e48d4c45f1afbd6dcf289d837d?sid=a23ba319-dcf2-4dba-ab12-d388ed74879a

Desktop (please complete the following information)

No response

Smartphone (please complete the following information)

No response

Environment (please complete the following information)

No response

Frontend Stack Trace

No response

Backend Stack Trace

No response

Additional context

No response

@Cenadros Can you upload both zip files generated? (or other examples)

position-data in theory is not "mandatory" once the file is open should be re-calculated.

The thing with text in SVG is that it's pretty complex issue, SVG doesn't have any paragraph layout information. In order to calculate the correct text position in the workspace we have a process that renders the text in html and then fills the attribute "position-data" with the real positions. Foreign objects are really not well implememented on most web browsers and also they have less functionality (ie: you cannot create masks, or set gradients, etc...).

On the exporter I think you need to export the attribute content. Once the info it's in Penpot, the process will calculate the position-data. This will mean that the SVG you export won't show the text well, but the import process should work fine. Maybe there is a bug and that's why I need to see the generated exported files.

Thanks!

@Cenadros I've cloned the exporter repo and reproduced the error. I don't need the files anymore. I'll let you know when I have a fix.

To give more information, we have detected that the text shape without position-data lacks the information about x, y, width and height (even though the information is a basic property for the text shape it is not present anywhere in the final export).

Example without position-data:

    <g id="shape-8d3796ab-e6ca-809f-8004-40729550c6b5"
       style="opacity:1">
        <penpot:shape penpot:name="a text"
                      penpot:blocked="false"
                      penpot:hidden="false"
                      penpot:type="text"
                      penpot:transform="matrix(1.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000)"
                      penpot:transform-inverse="matrix(1.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000)"
                      penpot:proportion-lock="false"
                      penpot:rotation="0"
                      penpot:center-x="130"
                      penpot:center-y="4.5"
                      penpot:grow-type="fixed"
                      penpot:content="{&quot;type&quot;:&quot;root&quot;,&quot;vertical-align&quot;:&quot;top&quot;,&quot;children&quot;:[{&quot;type&quot;:&quot;paragraph-set&quot;,&quot;children&quot;:[{&quot;line-height&quot;:1.2,&quot;font-style&quot;:&quot;Regular&quot;,&quot;children&quot;:[{&quot;line-height&quot;:1.2,&quot;font-style&quot;:&quot;Regular&quot;,&quot;text-transform&quot;:&quot;none&quot;,&quot;text-align&quot;:&quot;left&quot;,&quot;font-id&quot;:&quot;gfont-inter&quot;,&quot;font-size&quot;:&quot;12&quot;,&quot;font-weight&quot;:&quot;400&quot;,&quot;font-variant-id&quot;:&quot;regular&quot;,&quot;text-decoration&quot;:&quot;none&quot;,&quot;letter-spacing&quot;:0,&quot;fills&quot;:[{&quot;fill-color&quot;:&quot;#000000&quot;,&quot;fill-opacity&quot;:1}],&quot;font-family&quot;:&quot;Inter&quot;,&quot;text&quot;:&quot;a text&quot;}],&quot;text-transform&quot;:&quot;none&quot;,&quot;text-align&quot;:&quot;left&quot;,&quot;font-id&quot;:&quot;gfont-inter&quot;,&quot;font-size&quot;:&quot;12&quot;,&quot;font-weight&quot;:&quot;400&quot;,&quot;type&quot;:&quot;paragraph&quot;,&quot;font-variant-id&quot;:&quot;regular&quot;,&quot;text-decoration&quot;:&quot;none&quot;,&quot;letter-spacing&quot;:0,&quot;fills&quot;:[{&quot;fill-color&quot;:&quot;#000000&quot;,&quot;fill-opacity&quot;:1}],&quot;font-family&quot;:&quot;Inter&quot;}]}]}">
            <penpot:svg-import />
        </penpot:shape>
        <defs />
    </g>

Yes, I know what's happening. I'm in the process of fixing it. 👍

Hi there @Alotor, working on this issue we noticed as well that letter-spacing is being imported into penpot but is not being applied until you modify it in the text settings in penpot. I don't know if it's related but just wanted to let you know. In any case if this is a different issue we'll report it as such.

Hi @Cenadros

I've just merged to develop the @Alotor PR, could you please check if it fixes the problem?

Hi @superalex

I've just tested it and now it works correctly. We still have the issue with the letter-spacing being imported but not rendered, but I think it's better if we manage it in another issue that we'll open if you agree with that.

Great!, thank you very much @Cenadros and @Alotor <3 <3 <3