Ghost icon indicating copy to clipboard operation
Ghost copied to clipboard

Lexical kg-cards missing on website after ghost update with zip

Open ASAMedia opened this issue 1 year ago • 7 comments

Issue Summary

I updated my custom Ghost to version 5.71.2. It runs fine in development via yarn dev, but upgrading the 5.70 docker with an .tgz file from yarn archive brings up some problems. When editing existing posts (mobiledoc) and saving them with the new editor (lexical) ALL images and other kg-cards will not show up anymore on the website of this post. There is not a single error in webconsole or docker-compose logs -f during/saving editing or while upgrading ghost. When running the original 5.71 docker image or yarn dev everything runs fine without this issue.

~Looking into the sqlite database, I'll found that the lexical code is complete with the image.~

So it seems like an update problem, that I cant narrow down without some help. Any idea how to fix this?

Steps to Reproduce

  1. create the following DOCKERFILE
FROM ghost:5.71.0-alpine
WORKDIR /var/lib/ghost
COPY ./ghost-5.71.2.tgz /var/lib
RUN apk add --no-cache git
USER node
RUN yarn --version
RUN yarn cache clean
RUN rm -rf node_modules
RUN yarn
RUN chmod -R 00775 /var/lib/ghost/content &&\
    ghost update --force --zip /var/lib/ghost-5.71.2.tgz
RUN chmod -R 00775 /var/lib/ghost/content
  1. create the docker-compose.yml
version: '3.1'

services:

  lfg-ghost:
    build: .
    container_name: lfg-ghost
    restart: always
    ports:
      - 2368:2368
    volumes:
      -  ./content:/var/lib/ghost/content
      -  ./.env:/var/lib/ghost/.env
    environment:
      NODE_ENV: development
      database__client: sqlite3
      database__connection__filename: /var/lib/ghost/content/data/ghost.db
      url: 
      mail__transport: SMTP
      mail__from: 
      mail__options__service: SMTP
      mail__options__host: 
      mail__options__port: 587
      mail__options__auth__user: 
      mail__options__auth__pass: 
  1. Download the release file from here
  2. run sudo docker-compose build, sudo docker-compose up -d

Ghost Version

5.71.2

Node.js Version

18

How did you install Ghost?

docker-compose

Database type

SQLite3

Browser & OS version

Win 11/Ubuntu 20/Chrome/Firefox/Edge

Relevant log / error output

No response

Code of Conduct

  • [X] I agree to be friendly and polite to people in this repository

ASAMedia avatar Nov 12 '23 01:11 ASAMedia

An example from the website I'm running (lyonel-feininger-gymnasium.de): It looks like this in the editor grafik

and like this on the website grafik

As you can see, the snow picture is nowhere to be seen.

ASAMedia avatar Nov 12 '23 01:11 ASAMedia

Ok, I've got some more information: I looked into the db and found that the images are against my previous claims in fact are NOT present in the lexical field of the post

Here is the code snippet from the working original docker version

 receive emails when new content is publishrfed!</p><figure class="kg-card kg-image-card kg-width-wide"><img src="__GHOST_URL__/content/images/2023/11/IMG_2658.jpeg" class="kg-image" alt="" loading="lazy" width="2000" height="1500" srcset="__GHOST_URL__/content/images/size/w600/2023/11/IMG_2658.jpeg 600w, __GHOST_URL__/content/images/size/w1000/2023/11/IMG_2658.jpeg 1000w, __GHOST_URL__/content/images/size/w1600/2023/11/IMG_2658.jpeg 1600w, __GHOST_URL__/content/images/2023/11/IMG_2658.jpeg 2000w" sizes="(min-width: 1200px) 1200px"></figure><figure class="kg-card kg-image-card"><img src="__GHOST_URL__/content/images/2023/11/Screenshot-2023-11-11-at-18-42-13-Studienfahrt-nach-Gillingham--Kent-GB--der-9.-Klassen.png" class="kg-image" alt="" loading="lazy" width="1920" height="673" srcset="__GHOST_URL__/content/images/size/w600/2023/11/Screenshot-2023-11-11-at-18-42-13-Studienfahrt-nach-Gillingham--Kent-GB--der-9.-Klassen.png 600w, __GHOST_URL__/content/images/size/w1000/2023/11/Screenshot-2023-11-11-at-18-42-13-Studienfahrt-nach-Gillingham--Kent-GB--der-9.-Klassen.png 1000w, __GHOST_URL__/content/images/size/w1600/2023/11/Screenshot-2023-11-11-at-18-42-13-Studienfahrt-nach-Gillingham--Kent-GB--der-9.-Klassen.png 1600w, __GHOST_URL__/content/images/2023/11/Screenshot-2023-11-11-at-18-42-13-Studienfahrt-nach-Gillingham--Kent-GB--der-9.-Klassen.png 1920w" sizes="(min-width: 720px) 720px"></figure><hr>

And here the one I'm getting with my updated version inside docker

 receive emails when new content is publishrfed!</p>

Now the question where does this go wrong?

ASAMedia avatar Nov 12 '23 14:11 ASAMedia

Another Update: I downloaded the original source files from 5.71.2 build them to an archive with yarn archive and used the resulting ghost-5.71.2.tgz.zip to update the ghost 5.71.0-alpine docker.

Result: The problem is still occuring the same way as before :(

So it seems like in the build or update process the reference to the js for the kg-cards/nodes goes missing. I will attach some log info below, where the missing functions/attr are named when clicking the save/update button in the lexical-editor:

log output
lfg-ghost | CodeBlockNode must implement static "getType" method lfg-ghost | CodeBlockNode must implement static "clone" method lfg-ghost | CodeBlockNode must implement "decorate" method lfg-ghost | CodeBlockNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | CodeBlockNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | ImageNode must implement static "getType" method lfg-ghost | ImageNode must implement static "clone" method lfg-ghost | ImageNode must implement "decorate" method lfg-ghost | ImageNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | MarkdownNode must implement static "getType" method lfg-ghost | MarkdownNode must implement static "clone" method lfg-ghost | MarkdownNode must implement "decorate" method lfg-ghost | MarkdownNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | MarkdownNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | VideoNode must implement static "getType" method lfg-ghost | VideoNode must implement static "clone" method lfg-ghost | VideoNode must implement "decorate" method lfg-ghost | VideoNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | AudioNode must implement static "getType" method lfg-ghost | AudioNode must implement static "clone" method lfg-ghost | AudioNode must implement "decorate" method lfg-ghost | AudioNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | AudioNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | CalloutNode must implement static "getType" method lfg-ghost | CalloutNode must implement static "clone" method lfg-ghost | CalloutNode must implement "decorate" method lfg-ghost | CalloutNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | CalloutNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | HorizontalRuleNode must implement static "getType" method lfg-ghost | HorizontalRuleNode must implement static "clone" method lfg-ghost | HorizontalRuleNode must implement "decorate" method lfg-ghost | HorizontalRuleNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | HorizontalRuleNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | HtmlNode must implement static "getType" method lfg-ghost | HtmlNode must implement static "clone" method lfg-ghost | HtmlNode must implement "decorate" method lfg-ghost | HtmlNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | HtmlNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | FileNode must implement static "getType" method lfg-ghost | FileNode must implement static "clone" method lfg-ghost | FileNode must implement "decorate" method lfg-ghost | FileNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | ToggleNode must implement static "getType" method lfg-ghost | ToggleNode must implement static "clone" method lfg-ghost | ToggleNode must implement "decorate" method lfg-ghost | ToggleNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | ToggleNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | ButtonNode must implement static "getType" method lfg-ghost | ButtonNode must implement static "clone" method lfg-ghost | ButtonNode must implement "decorate" method lfg-ghost | ButtonNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | ButtonNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | HeaderNode must implement static "getType" method lfg-ghost | HeaderNode must implement static "clone" method lfg-ghost | HeaderNode must implement "decorate" method lfg-ghost | HeaderNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | HeaderNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | BookmarkNode must implement static "getType" method lfg-ghost | BookmarkNode must implement static "clone" method lfg-ghost | BookmarkNode must implement "decorate" method lfg-ghost | PaywallNode must implement static "getType" method lfg-ghost | PaywallNode must implement static "clone" method lfg-ghost | PaywallNode must implement "decorate" method lfg-ghost | PaywallNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | PaywallNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | ProductNode must implement static "getType" method lfg-ghost | ProductNode must implement static "clone" method lfg-ghost | ProductNode must implement "decorate" method lfg-ghost | ProductNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | EmbedNode must implement static "getType" method lfg-ghost | EmbedNode must implement static "clone" method lfg-ghost | EmbedNode must implement "decorate" method lfg-ghost | EmbedNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | EmbedNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | EmailNode must implement static "getType" method lfg-ghost | EmailNode must implement static "clone" method lfg-ghost | EmailNode must implement "decorate" method lfg-ghost | EmailNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | EmailNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | GalleryNode must implement static "getType" method lfg-ghost | GalleryNode must implement static "clone" method lfg-ghost | GalleryNode must implement "decorate" method lfg-ghost | GalleryNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | GalleryNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | EmailCtaNode must implement static "getType" method lfg-ghost | EmailCtaNode must implement static "clone" method lfg-ghost | EmailCtaNode must implement "decorate" method lfg-ghost | EmailCtaNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | EmailCtaNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | SignupNode must implement static "getType" method lfg-ghost | SignupNode must implement static "clone" method lfg-ghost | SignupNode must implement "decorate" method lfg-ghost | SignupNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | SignupNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | CollectionNode must implement static "getType" method lfg-ghost | CollectionNode must implement static "clone" method lfg-ghost | CollectionNode must implement "decorate" method lfg-ghost | CollectionNode should implement "importJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | CollectionNode should implement "exportJSON" method to ensure JSON and default HTML serialization works as expected lfg-ghost | [2023-11-12 21:53:13] INFO Adding one-off job to queue with current length = 0 called 'sendWebmentions' lfg-ghost | [2023-11-12 21:53:13] INFO "PUT /ghost/api/admin/posts/654ff84b2fecd90001949776/?formats=mobiledoc%2Clexical&save_revision=1&include=tags%2Cauthors%2Cauthors.roles%2Cemail%2Ctiers%2Cnewsletter%2Ccount.clicks%2Cpost_revisions%2Cpost_revisions.author" 200 133ms

ASAMedia avatar Nov 12 '23 21:11 ASAMedia

Something in the build system is broken. I build my docker instance similar to how you do it, and since 5.71.0, at least, I get two kg-default-nodes modules, one in ghost/node_modules/@tryghost and one in ghost/ghost/core/node_modules/@tryghost. Removing ghost/ghost/core/node_modules fixes the issue.

The duplicate module import creates two definitions of KoenigDecoratorNode. This causes the instanceof test in $isKoenigCard to fail, which causes exportTopLevelElementOrDecorator to fail on elements where $isKoenigCard should return true but returns false (Images and Cards, at least).

I know very little about Ghost's build system, but someone with more knowledge than me should be able to fix this fairly quickly.

The official images do not exhibit this problem. They may be building ghost differently.

sergiosgc avatar Nov 28 '23 18:11 sergiosgc

Wow great! Thanks @sergiosgc That will solve the issue till a fix is implemented.

Looks like kg-default-nodes is imported here "@tryghost/kg-default-nodes": "0.2.9", in the ghost/core/package.json and here const {DEFAULT_NODES} = require('@tryghost/kg-default-nodes'); in the ghost/core/core/server/lib/lexical.js

When I delete the line in the package.json and build, everything works as expected.

Maybe this could be a valid fix?

ASAMedia avatar Nov 29 '23 16:11 ASAMedia

This problem seems to impact Ghost(Pro) subscribers as well. I have a JavaScript code that uses the Admin API JavaScript Client that updates the content of one post. It used to work but now isn't working. I am seeing no errors. The post history shows that it is being updated but the content isn't changing. If I recall correctly, the source for the blog post used to show that it uses a markdown card. Now, I don't see a markdown class in the post's source.

I tried troubleshooting the code for several hours with the help of Bing AI to no avail. I agree, partially, with its observation:

The issue affects the mobiledoc format for posts, which is used by the Ghost API. The mobiledoc format is a JSON document that defines the structure and content of a post using cards, atoms, and markups. The problem is that the Ghost API is not creating the cards correctly, resulting in empty or corrupted posts.

I think the problem is that the API isn't creating the cards, so my post's history shows it is being updated but the Markdown card inside the post isn't changing.

hsarji avatar Dec 17 '23 15:12 hsarji

Our bot has automatically marked this issue as stale because there has not been any activity here in some time.

The issue will be closed soon if there are no further updates, however we ask that you do not post comments to keep the issue open if you are not actively working on a PR.

We keep the issue list minimal so we can keep focus on the most pressing issues. Closed issues can always be reopened if a new contributor is found. Thank you for understanding 🙂

github-actions[bot] avatar Apr 15 '24 16:04 github-actions[bot]

This should be fixed now!

daniellockyer avatar May 21 '24 13:05 daniellockyer