Swapped feature image caption input from mobiledoc to lexical

closes https://github.com/TryGhost/Product/issues/4015

Swapped `<KoenigBasicHtmlInput>` for `<KoenigLexicalEditorInput>`

- added support for passing `class` through to the container `<div>`
- updated caption handler to clean HTML and strip/add surrounding `<p>` as necessary
- added passthrough for `onFocus` prop
- updated styles to force font style inheritance within Koeing's `.kg-prose` class
This commit is contained in:
Kevin Ansfield 2023-10-10 18:30:47 +01:00
parent 9e51a8be88
commit 0ffe4dd144
5 changed files with 47 additions and 14 deletions

View File

@ -71,12 +71,11 @@
aria-label="Alt text for feature image"
>
{{else}}
<KoenigBasicHtmlInput
@html={{@caption}}
@placeholder={{if this.captionInputFocused "" "Add a caption to the feature image"}}
@class="gh-editor-feature-image-caption {{if (and @isHidden (not this.captionInputFocused)) "faded"}}"
@name="caption"
@onChange={{@updateCaption}}
<KoenigLexicalEditorInput
class="gh-editor-feature-image-caption {{if (and @isHidden (not this.captionInputFocused)) "faded"}}"
@html={{this.caption}}
@onChangeHtml={{this.setCaption}}
@placeholderText={{if this.captionInputFocused "" "Add a caption to the feature image"}}
@onFocus={{fn (mut this.captionInputFocused) true}}
@onBlur={{fn (mut this.captionInputFocused) false}}
/>

View File

@ -1,8 +1,16 @@
import Component from '@glimmer/component';
import cleanBasicHtml from '@tryghost/kg-clean-basic-html';
import {action} from '@ember/object';
import {inject as service} from '@ember/service';
import {tracked} from '@glimmer/tracking';
function hasParagraphWrapper(html) {
const domParser = new DOMParser();
const doc = domParser.parseFromString(html, 'text/html');
return doc.body?.firstElementChild?.tagName === 'P';
}
export default class GhEditorFeatureImageComponent extends Component {
@service settings;
@ -16,6 +24,21 @@ export default class GhEditorFeatureImageComponent extends Component {
return !this.canDrop && !this.isHovered && !this.args.forceButtonDisplay;
}
get caption() {
const content = this.args.caption;
if (!content) {
return null;
}
// wrap in a paragraph, so it gets parsed correctly
return hasParagraphWrapper(content) ? content : `<p>${content}</p>`;
}
@action
setCaption(html) {
const cleanedHtml = cleanBasicHtml(html || '', {firstChildInnerContent: true});
this.args.updateCaption(cleanedHtml);
}
@action
setUploadedImage(results) {
if (results[0]) {

View File

@ -1,7 +1,10 @@
<div {{react-render this.ReactComponent props=(hash
placeholderText=@placeholderText
html=@html
onChangeHtml=@onChangeHtml
onBlur=@onBlur
)
}}></div>
<div
{{react-render this.ReactComponent props=(hash
placeholderText=@placeholderText
html=@html
onChangeHtml=@onChangeHtml
onBlur=@onBlur
onFocus=@onFocus
)}}
...attributes
></div>

View File

@ -81,6 +81,7 @@ export default class KoenigLexicalEditorInput extends Component {
darkMode={this.feature.nightShift}
onChange={props.onChange}
onBlur={props.onBlur}
onFocus={props.onFocus}
isSnippetsEnabled={false}
singleParagraph={true}
className="koenig-lexical-editor-input"

View File

@ -641,6 +641,13 @@ body[data-user-is-dragging] .gh-editor-feature-image-dropzone {
opacity: 1 !important;
}
.gh-editor-feature-image-caption :is(.koenig-lexical *) {
font-size: inherit !important;
font-family: inherit !important;
line-height: inherit !important;
letter-spacing: inherit !important;
}
.gh-editor-feature-image-caption p {
margin: 0;
}
@ -1269,4 +1276,4 @@ figure {
.gh-editor-hidden-indicator svg {
height: 2.4rem;
}
}