Ghost
Ghost copied to clipboard
Lexical kg-cards missing on website after ghost update with zip
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
- 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
- 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:
- Download the release file from here
- 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
An example from the website I'm running (lyonel-feininger-gymnasium.de):
It looks like this in the editor
and like this on the website
As you can see, the snow picture is nowhere to be seen.
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?
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
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.
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?
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.
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 🙂
This should be fixed now!