Renamed subtitle to excerpt (#20334)
no issue We've settled on using "excerpt" naming in place of "subtitle" to better reflect the underlying property name and tie in with themes and historical usage. - added migration to rename the `show_subtitle` newsletter setting to `show_excerpt` - renamed all places in the codebase that referenced subtitle
This commit is contained in:
parent
0470a4a431
commit
9ca1f3ce24
@ -21,7 +21,7 @@ export type Newsletter = {
|
||||
show_header_title: boolean;
|
||||
title_font_category: string;
|
||||
title_alignment: string;
|
||||
show_subtitle: boolean;
|
||||
show_excerpt: boolean;
|
||||
show_feature_image: boolean;
|
||||
body_font_category: string;
|
||||
footer_content: string | null;
|
||||
|
@ -19,7 +19,7 @@
|
||||
"show_header_title": true,
|
||||
"title_font_category": "serif",
|
||||
"title_alignment": "center",
|
||||
"show_subtitle": true,
|
||||
"show_excerpt": true,
|
||||
"show_feature_image": true,
|
||||
"body_font_category": "serif",
|
||||
"footer_content": "",
|
||||
|
@ -68,13 +68,13 @@ const features = [{
|
||||
description: '(Highly) Experimental support for ActivityPub.',
|
||||
flag: 'ActivityPub'
|
||||
},{
|
||||
title: 'Subtitle in editor',
|
||||
description: 'Using custom excerpt as subtitle in editor',
|
||||
flag: 'editorSubtitle'
|
||||
title: 'Show post excerpt inline',
|
||||
description: 'Adds the excerpt input below the post title in the editor',
|
||||
flag: 'editorExcerpt'
|
||||
},{
|
||||
title: 'Subtitle in newsletter',
|
||||
description: 'Showing subtitle in newsletter',
|
||||
flag: 'newsletterSubtitle'
|
||||
title: 'Excerpt in newsletter',
|
||||
description: 'Showing excerpt in newsletter',
|
||||
flag: 'newsletterExcerpt'
|
||||
}];
|
||||
|
||||
const AlphaFeatures: React.FC = () => {
|
||||
|
@ -103,8 +103,8 @@ const Sidebar: React.FC<{
|
||||
const {mutateAsync: uploadImage} = useUploadImage();
|
||||
const [selectedTab, setSelectedTab] = useState('generalSettings');
|
||||
const hasEmailCustomization = useFeatureFlag('emailCustomization');
|
||||
const hasNewsletterSubtitle = useFeatureFlag('newsletterSubtitle');
|
||||
const hasEditorSubtitle = useFeatureFlag('editorSubtitle');
|
||||
const hasNewsletterExcerpt = useFeatureFlag('newsletterExcerpt');
|
||||
const hasEditorSubtitle = useFeatureFlag('editorExcerpt');
|
||||
const {localSettings} = useSettingGroup();
|
||||
const [siteTitle] = getSettingValues(localSettings, ['title']) as string[];
|
||||
const handleError = useHandleError();
|
||||
@ -419,12 +419,12 @@ const Sidebar: React.FC<{
|
||||
onChange={color => updateNewsletter({title_color: color})}
|
||||
/>}
|
||||
<ToggleGroup gap='lg'>
|
||||
{(hasNewsletterSubtitle && newsletter.show_post_title_section) &&
|
||||
{(hasNewsletterExcerpt && newsletter.show_post_title_section) &&
|
||||
<Toggle
|
||||
checked={newsletter.show_subtitle}
|
||||
checked={newsletter.show_excerpt}
|
||||
direction="rtl"
|
||||
label={hasEditorSubtitle ? 'Subtitle' : 'Post excerpt'}
|
||||
onChange={e => updateNewsletter({show_subtitle: e.target.checked})}
|
||||
onChange={e => updateNewsletter({show_excerpt: e.target.checked})}
|
||||
/>
|
||||
}
|
||||
<Toggle
|
||||
|
@ -106,12 +106,12 @@ const NewsletterPreview: React.FC<{newsletter: Newsletter}> = ({newsletter}) =>
|
||||
senderReplyTo={renderReplyToEmail(newsletter, config, supportEmailAddress, defaultEmailAddress)}
|
||||
showBadge={newsletter.show_badge}
|
||||
showCommentCta={showCommentCta}
|
||||
showExcerpt={newsletter.show_excerpt}
|
||||
showFeatureImage={newsletter.show_feature_image}
|
||||
showFeedback={showFeedback}
|
||||
showLatestPosts={newsletter.show_latest_posts}
|
||||
showPostTitleSection={newsletter.show_post_title_section}
|
||||
showSubscriptionDetails={newsletter.show_subscription_details}
|
||||
showSubtitle={newsletter.show_subtitle}
|
||||
siteTitle={title}
|
||||
titleAlignment={newsletter.title_alignment}
|
||||
titleFontCategory={newsletter.title_font_category}
|
||||
|
@ -18,7 +18,7 @@ const NewsletterPreviewContent: React.FC<{
|
||||
headerTitle?: string | null;
|
||||
headerSubtitle?: string | null;
|
||||
showPostTitleSection: boolean;
|
||||
showSubtitle: boolean;
|
||||
showExcerpt: boolean;
|
||||
titleAlignment?: string;
|
||||
titleFontCategory?: string;
|
||||
bodyFontCategory?: string;
|
||||
@ -50,7 +50,7 @@ const NewsletterPreviewContent: React.FC<{
|
||||
headerTitle,
|
||||
headerSubtitle,
|
||||
showPostTitleSection,
|
||||
showSubtitle,
|
||||
showExcerpt,
|
||||
titleAlignment,
|
||||
titleFontCategory,
|
||||
bodyFontCategory,
|
||||
@ -77,7 +77,7 @@ const NewsletterPreviewContent: React.FC<{
|
||||
const showHeader = headerIcon || headerTitle;
|
||||
const {config} = useGlobalData();
|
||||
const hasNewEmailAddresses = useFeatureFlag('newEmailAddresses');
|
||||
const hasNewsletterSubtitle = useFeatureFlag('newsletterSubtitle');
|
||||
const hasNewsletterExcerpt = useFeatureFlag('newsletterExcerpt');
|
||||
|
||||
const currentDate = new Date().toLocaleDateString('default', {
|
||||
year: 'numeric',
|
||||
@ -101,16 +101,16 @@ const NewsletterPreviewContent: React.FC<{
|
||||
<p className="leading-normal"><span className="font-semibold text-grey-900">To:</span> Jamie Larson jamie@example.com</p></>;
|
||||
}
|
||||
|
||||
let subtitleClasses = 'mb-5 text-pretty leading-[1.7] text-black';
|
||||
let excerptClasses = 'mb-5 text-pretty leading-[1.7] text-black';
|
||||
|
||||
if (titleFontCategory === 'serif' && bodyFontCategory === 'serif') {
|
||||
subtitleClasses = clsx(subtitleClasses, 'font-serif text-[1.8rem]');
|
||||
excerptClasses = clsx(excerptClasses, 'font-serif text-[1.8rem]');
|
||||
} else if (titleFontCategory !== 'serif' && bodyFontCategory === 'serif') {
|
||||
subtitleClasses = clsx(subtitleClasses, 'text-[1.7rem] tracking-tight');
|
||||
excerptClasses = clsx(excerptClasses, 'text-[1.7rem] tracking-tight');
|
||||
} else if (titleFontCategory === 'serif' && bodyFontCategory !== 'serif') {
|
||||
subtitleClasses = clsx(subtitleClasses, 'font-serif text-[1.8rem]');
|
||||
excerptClasses = clsx(excerptClasses, 'font-serif text-[1.8rem]');
|
||||
} else {
|
||||
subtitleClasses = clsx(subtitleClasses, 'text-[1.7rem] tracking-tight');
|
||||
excerptClasses = clsx(excerptClasses, 'text-[1.7rem] tracking-tight');
|
||||
}
|
||||
|
||||
return (
|
||||
@ -146,8 +146,8 @@ const NewsletterPreviewContent: React.FC<{
|
||||
)} style={{color: titleColor}}>
|
||||
Your email newsletter
|
||||
</h2>
|
||||
{(hasNewsletterSubtitle && showSubtitle) && (
|
||||
<p className={subtitleClasses}>A subtitle to highlight key points and engage your readers</p>
|
||||
{(hasNewsletterExcerpt && showExcerpt) && (
|
||||
<p className={excerptClasses}>A subtitle to highlight key points and engage your readers</p>
|
||||
)}
|
||||
<div className={clsx(
|
||||
'flex w-full justify-between text-center text-md leading-none text-grey-700',
|
||||
|
@ -57,11 +57,11 @@
|
||||
data-test-editor-title-input={{true}}
|
||||
/>
|
||||
|
||||
{{#if (feature 'editorSubtitle')}}
|
||||
{{#if (feature 'editorExcerpt')}}
|
||||
<div class="relative">
|
||||
<GhTextarea
|
||||
@class={{concat "gh-editor-subtitle " (if @excerptErrorMessage "red")}}
|
||||
@placeholder="Add a subtitle"
|
||||
@class={{concat "gh-editor-excerpt " (if @excerptErrorMessage "red")}}
|
||||
@placeholder="Add an excerpt"
|
||||
@shouldFocus={{false}}
|
||||
@tabindex="1"
|
||||
@autoExpand=".gh-koenig-editor"
|
||||
@ -69,12 +69,12 @@
|
||||
@input={{this.onExcerptInput}}
|
||||
@keyDown={{this.onExcerptKeydown}}
|
||||
@didCreateTextarea={{this.registerSubtitleElement}}
|
||||
data-test-textarea="subtitle"
|
||||
data-test-textarea="excerpt"
|
||||
/>
|
||||
{{#if @excerptHasTk}}
|
||||
<div
|
||||
class="tk-indicator tk-indicator-subtitle"
|
||||
data-testid="tk-indicator-subtitle"
|
||||
class="tk-indicator tk-indicator-excerpt"
|
||||
data-testid="tk-indicator-excerpt"
|
||||
{{on "click" this.focusSubtitle}}
|
||||
>
|
||||
TK
|
||||
@ -82,7 +82,7 @@
|
||||
{{/if}}
|
||||
<hr class="gh-editor-title-divider {{if @excerptErrorMessage "gh-editor-title-divider-error" ""}}">
|
||||
{{#if @excerptErrorMessage}}
|
||||
<div class="gh-editor-subtitle-error" data-test-error="subtitle">
|
||||
<div class="gh-editor-excerpt-error" data-test-error="excerpt">
|
||||
{{@excerptErrorMessage}}
|
||||
</div>
|
||||
{{/if}}
|
||||
@ -96,7 +96,7 @@
|
||||
@cardConfig={{@cardOptions}}
|
||||
@onChange={{@onBodyChange}}
|
||||
@registerAPI={{this.registerEditorAPI}}
|
||||
@cursorDidExitAtTop={{if this.feature.editorSubtitle this.focusSubtitle this.focusTitle}}
|
||||
@cursorDidExitAtTop={{if this.feature.editorExcerpt this.focusSubtitle this.focusTitle}}
|
||||
@updateWordCount={{@updateWordCount}}
|
||||
@updatePostTkCount={{@updatePostTkCount}}
|
||||
/>
|
||||
|
@ -10,7 +10,7 @@ export default class GhKoenigEditorReactComponent extends Component {
|
||||
|
||||
containerElement = null;
|
||||
titleElement = null;
|
||||
subtitleElement = null;
|
||||
excerptElement = null;
|
||||
mousedownY = 0;
|
||||
uploadUrl = `${ghostPaths().apiRoot}/images/upload/`;
|
||||
|
||||
@ -114,8 +114,8 @@ export default class GhKoenigEditorReactComponent extends Component {
|
||||
|
||||
@action
|
||||
onTitleKeydown(event) {
|
||||
if (this.feature.get('editorSubtitle')) {
|
||||
// move cursor to the subtitle on
|
||||
if (this.feature.get('editorExcerpt')) {
|
||||
// move cursor to the excerpt on
|
||||
// - Tab (handled by browser)
|
||||
// - Arrow Down/Right when input is empty or caret at end of input
|
||||
// - Enter
|
||||
@ -124,7 +124,7 @@ export default class GhKoenigEditorReactComponent extends Component {
|
||||
|
||||
if (key === 'Enter') {
|
||||
event.preventDefault();
|
||||
this.subtitleElement?.focus();
|
||||
this.excerptElement?.focus();
|
||||
}
|
||||
|
||||
if ((key === 'ArrowDown' || key === 'ArrowRight') && !event.shiftKey) {
|
||||
@ -132,7 +132,7 @@ export default class GhKoenigEditorReactComponent extends Component {
|
||||
|
||||
if (couldLeaveTitle) {
|
||||
event.preventDefault();
|
||||
this.subtitleElement?.focus();
|
||||
this.excerptElement?.focus();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -167,17 +167,17 @@ export default class GhKoenigEditorReactComponent extends Component {
|
||||
// Subtitle ("excerpt") Actions -------------------------------------------
|
||||
|
||||
@action
|
||||
registerSubtitleElement(element) {
|
||||
this.subtitleElement = element;
|
||||
excerptSubtitleElement(element) {
|
||||
this.excerptElement = element;
|
||||
}
|
||||
|
||||
@action
|
||||
focusSubtitle() {
|
||||
this.subtitleElement?.focus();
|
||||
this.excerptElement?.focus();
|
||||
|
||||
// timeout ensures this occurs after the keyboard events
|
||||
setTimeout(() => {
|
||||
this.subtitleElement?.setSelectionRange(-1, -1);
|
||||
this.excerptElement?.setSelectionRange(-1, -1);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#unless (feature 'editorSubtitle')}}
|
||||
{{#unless (feature 'editorExcerpt')}}
|
||||
<GhFormGroup @errors={{this.post.errors}} @hasValidated={{this.post.hasValidated}} @property="customExcerpt">
|
||||
<label for="custom-excerpt">Excerpt</label>
|
||||
<GhTextarea
|
||||
|
@ -23,8 +23,8 @@
|
||||
<div class="gh-editor-title" data-test-post-history-preview-title>
|
||||
{{this.currentTitle}}
|
||||
</div>
|
||||
{{#if (feature "editorSubtitle")}}
|
||||
<div class="gh-editor-subtitle" data-test-post-history-preview-subtitle>
|
||||
{{#if (feature "editorExcerpt")}}
|
||||
<div class="gh-editor-excerpt" data-test-post-history-preview-excerpt>
|
||||
{{this.selectedRevision.custom_excerpt}}
|
||||
</div>
|
||||
<hr class="gh-editor-title-divider">
|
||||
|
@ -39,7 +39,7 @@ export default class RestoreRevisionModal extends Component {
|
||||
post.featureImageAlt = revision.feature_image_alt;
|
||||
post.featureImageCaption = revision.feature_image_caption;
|
||||
|
||||
if (this.feature.editorSubtitle) {
|
||||
if (this.feature.editorExcerpt) {
|
||||
post.customExcerpt = revision.custom_excerpt;
|
||||
}
|
||||
|
||||
|
@ -272,7 +272,7 @@ export default class LexicalEditorController extends Controller {
|
||||
|
||||
@computed('post.customExcerpt')
|
||||
get excerptHasTk() {
|
||||
if (!this.feature.editorSubtitle) {
|
||||
if (!this.feature.editorExcerpt) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -282,7 +282,7 @@ export default class LexicalEditorController extends Controller {
|
||||
@computed('titleHasTk', 'excerptHasTk', 'postTkCount', 'featureImageTkCount')
|
||||
get tkCount() {
|
||||
const titleTk = this.titleHasTk ? 1 : 0;
|
||||
const excerptTk = (this.feature.editorSubtitle && this.excerptHasTk) ? 1 : 0;
|
||||
const excerptTk = (this.feature.editorExcerpt && this.excerptHasTk) ? 1 : 0;
|
||||
return titleTk + excerptTk + this.postTkCount + this.featureImageTkCount;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ export default class Newsletter extends Model.extend(ValidationEngine) {
|
||||
@attr({defaultValue: true}) showHeaderTitle;
|
||||
@attr({defaultValue: true}) showHeaderName;
|
||||
@attr({defaultValue: true}) showPostTitleSection;
|
||||
@attr({defaultValue: false}) showSubtitle;
|
||||
@attr({defaultValue: false}) showExcerpt;
|
||||
@attr({defaultValue: true}) showCommentCta;
|
||||
@attr({defaultValue: false}) showSubscriptionDetails;
|
||||
@attr({defaultValue: false}) showLatestPosts;
|
||||
|
@ -84,8 +84,8 @@ export default class FeatureService extends Service {
|
||||
@feature('ActivityPub') ActivityPub;
|
||||
@feature('internalLinking') internalLinking;
|
||||
@feature('internalLinkingAtLinks') internalLinkingAtLinks;
|
||||
@feature('editorSubtitle') editorSubtitle;
|
||||
@feature('newsletterSubtitle') newsletterSubtitle;
|
||||
@feature('editorExcerpt') editorExcerpt;
|
||||
@feature('newsletterExcerpt') newsletterExcerpt;
|
||||
|
||||
_user = null;
|
||||
|
||||
|
@ -745,7 +745,7 @@ input:focus,
|
||||
/* Editor */
|
||||
|
||||
.gh-editor-title,
|
||||
.gh-editor-subtitle {
|
||||
.gh-editor-excerpt {
|
||||
background: var(--white);
|
||||
}
|
||||
|
||||
@ -1435,4 +1435,4 @@ Onboarding checklist: Share publication modal */
|
||||
|
||||
.gh-sidebar-banner.gh-error-banner {
|
||||
background: var(--lightgrey-d1);
|
||||
}
|
||||
}
|
||||
|
@ -788,7 +788,7 @@ body[data-user-is-dragging] .gh-editor-feature-image-dropzone {
|
||||
height: 2.4rem;
|
||||
}
|
||||
|
||||
.gh-editor-subtitle {
|
||||
.gh-editor-excerpt {
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: unset;
|
||||
@ -807,12 +807,12 @@ body[data-user-is-dragging] .gh-editor-feature-image-dropzone {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.gh-editor-subtitle:focus {
|
||||
.gh-editor-excerpt:focus {
|
||||
box-shadow: none !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.gh-editor-subtitle-error {
|
||||
.gh-editor-excerpt-error {
|
||||
margin-top: .8rem;
|
||||
margin-bottom: 4.8rem;
|
||||
color: var(--red-d1);
|
||||
@ -840,7 +840,7 @@ body[data-user-is-dragging] .gh-editor-feature-image-dropzone {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.gh-editor .tk-indicator-subtitle {
|
||||
.gh-editor .tk-indicator-excerpt {
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
|
@ -62,8 +62,8 @@ export default BaseValidator.create({
|
||||
|
||||
customExcerpt(model) {
|
||||
if (!validator.isLength(model.customExcerpt || '', 0, 300)) {
|
||||
if (model.feature.editorSubtitle) {
|
||||
model.errors.add('customExcerpt', 'Subtitle cannot be longer than 300 characters.');
|
||||
if (model.feature.editorExcerpt) {
|
||||
model.errors.add('customExcerpt', 'Excerpt cannot be longer than 300 characters.');
|
||||
} else {
|
||||
model.errors.add('customExcerpt', 'Excerpt cannot be longer than 300 characters.');
|
||||
}
|
||||
|
@ -492,19 +492,19 @@ describe('Acceptance: Editor', function () {
|
||||
});
|
||||
|
||||
it('handles in-editor excerpt update and validation', async function () {
|
||||
enableLabsFlag(this.server, 'editorSubtitle');
|
||||
enableLabsFlag(this.server, 'editorExcerpt');
|
||||
|
||||
let post = this.server.create('post', {authors: [author], customExcerpt: 'Existing excerpt'});
|
||||
|
||||
await visit(`/editor/post/${post.id}`);
|
||||
|
||||
expect(find('[data-test-textarea="subtitle"]'), 'initial textarea').to.be.visible;
|
||||
expect(find('[data-test-textarea="subtitle"]'), 'initial textarea').to.have.value('Existing excerpt');
|
||||
expect(find('[data-test-textarea="excerpt"]'), 'initial textarea').to.be.visible;
|
||||
expect(find('[data-test-textarea="excerpt"]'), 'initial textarea').to.have.value('Existing excerpt');
|
||||
|
||||
await fillIn('[data-test-textarea="subtitle"]', 'New excerpt');
|
||||
expect(find('[data-test-textarea="subtitle"]'), 'updated textarea').to.have.value('New excerpt');
|
||||
await fillIn('[data-test-textarea="excerpt"]', 'New excerpt');
|
||||
expect(find('[data-test-textarea="excerpt"]'), 'updated textarea').to.have.value('New excerpt');
|
||||
|
||||
await triggerEvent('[data-test-textarea="subtitle"]', 'keydown', {
|
||||
await triggerEvent('[data-test-textarea="excerpt"]', 'keydown', {
|
||||
key: 's',
|
||||
keyCode: 83, // s
|
||||
metaKey: ctrlOrCmd === 'command',
|
||||
@ -513,14 +513,14 @@ describe('Acceptance: Editor', function () {
|
||||
|
||||
expect(post.customExcerpt, 'saved excerpt').to.equal('New excerpt');
|
||||
|
||||
await fillIn('[data-test-textarea="subtitle"]', Array(302).join('a'));
|
||||
await fillIn('[data-test-textarea="excerpt"]', Array(302).join('a'));
|
||||
|
||||
expect(find('[data-test-error="subtitle"]'), 'subtitle error').to.exist;
|
||||
expect(find('[data-test-error="subtitle"]')).to.have.trimmed.text('Subtitle cannot be longer than 300 characters.');
|
||||
expect(find('[data-test-error="excerpt"]'), 'excerpt error').to.exist;
|
||||
expect(find('[data-test-error="excerpt"]')).to.have.trimmed.text('Excerpt cannot be longer than 300 characters.');
|
||||
|
||||
await fillIn('[data-test-textarea="subtitle"]', Array(300).join('a'));
|
||||
await fillIn('[data-test-textarea="excerpt"]', Array(300).join('a'));
|
||||
|
||||
expect(find('[data-test-error="subtitle"]'), 'subtitle error').to.not.exist;
|
||||
expect(find('[data-test-error="excerpt"]'), 'excerpt error').to.not.exist;
|
||||
});
|
||||
|
||||
// https://github.com/TryGhost/Ghost/issues/11786
|
||||
@ -636,28 +636,28 @@ describe('Acceptance: Editor', function () {
|
||||
).to.exist;
|
||||
});
|
||||
|
||||
it('handles TKs in subtitle', async function () {
|
||||
enableLabsFlag(this.server, 'editorSubtitle');
|
||||
it('handles TKs in excerpt', async function () {
|
||||
enableLabsFlag(this.server, 'editorExcerpt');
|
||||
|
||||
const post = this.server.create('post', {authors: [author]});
|
||||
|
||||
await visit(`/editor/post/${post.id}`);
|
||||
|
||||
expect(
|
||||
find('[data-test-textarea="subtitle"]').value,
|
||||
'initial subtitle'
|
||||
find('[data-test-textarea="excerpt"]').value,
|
||||
'initial excerpt'
|
||||
).to.equal('');
|
||||
|
||||
await fillIn('[data-test-textarea="subtitle"]', 'Test TK subtitle');
|
||||
await fillIn('[data-test-textarea="excerpt"]', 'Test TK excerpt');
|
||||
|
||||
expect(
|
||||
find('[data-test-textarea="subtitle"]').value,
|
||||
'subtitle after typing'
|
||||
).to.equal('Test TK subtitle');
|
||||
find('[data-test-textarea="excerpt"]').value,
|
||||
'excerpt after typing'
|
||||
).to.equal('Test TK excerpt');
|
||||
|
||||
// check for TK indicator
|
||||
expect(
|
||||
find('[data-testid="tk-indicator-subtitle"]'),
|
||||
find('[data-testid="tk-indicator-excerpt"]'),
|
||||
'TK indicator text'
|
||||
).to.exist;
|
||||
|
||||
|
@ -26,7 +26,7 @@ describe('Acceptance: Post revisions', function () {
|
||||
this.server.create('post-revision', {
|
||||
post,
|
||||
title: post.title,
|
||||
customExcerpt: 'New subtitle',
|
||||
customExcerpt: 'New excerpt',
|
||||
featureImage: 'https://example.com/new-image.jpg',
|
||||
featureImageAlt: 'New feature alt text',
|
||||
featureImageCaption: 'New feature caption',
|
||||
@ -38,7 +38,7 @@ describe('Acceptance: Post revisions', function () {
|
||||
this.server.create('post-revision', {
|
||||
post,
|
||||
title: 'Old Title',
|
||||
customExcerpt: 'Old subtitle',
|
||||
customExcerpt: 'Old excerpt',
|
||||
featureImage: 'https://example.com/old-image.jpg',
|
||||
featureImageAlt: 'Old feature alt text',
|
||||
featureImageCaption: 'Old feature caption',
|
||||
@ -70,8 +70,8 @@ describe('Acceptance: Post revisions', function () {
|
||||
expect(find('[data-test-post-history-preview-feature-image]')).to.have.attribute('alt', 'New feature alt text');
|
||||
expect(find('[data-test-post-history-preview-feature-image-caption]')).to.have.trimmed.text('New feature caption');
|
||||
|
||||
// subtitle is not visible (needs feature flag)
|
||||
expect(find('[data-test-post-history-preview-subtitle]')).to.not.exist;
|
||||
// excerpt is not visible (needs feature flag)
|
||||
expect(find('[data-test-post-history-preview-excerpt]')).to.not.exist;
|
||||
|
||||
// previous post can be previewed
|
||||
await click('[data-test-revision-item="1"] [data-test-button="preview-revision"]');
|
||||
@ -90,22 +90,22 @@ describe('Acceptance: Post revisions', function () {
|
||||
expect(post.attrs.featureImageAlt).to.equal('Old feature alt text');
|
||||
expect(post.attrs.featureImageCaption).to.equal('Old feature caption');
|
||||
|
||||
// subtitle (customExcerpt) is not restored (needs feature flag)
|
||||
// excerpt (customExcerpt) is not restored (needs feature flag)
|
||||
expect(post.attrs.customExcerpt).to.equal('Current excerpt');
|
||||
});
|
||||
|
||||
it('can preview and restore subtitle (with editorSubtitle feature flag)', async function () {
|
||||
enableLabsFlag(this.server, 'editorSubtitle');
|
||||
it('can preview and restore excerpt (with editorExcerpt feature flag)', async function () {
|
||||
enableLabsFlag(this.server, 'editorExcerpt');
|
||||
|
||||
const post = this.server.create('post', {
|
||||
title: 'Current Title',
|
||||
customExcerpt: 'Current subtitle',
|
||||
customExcerpt: 'Current excerpt',
|
||||
status: 'draft'
|
||||
});
|
||||
this.server.create('post-revision', {
|
||||
post,
|
||||
title: post.title,
|
||||
customExcerpt: 'New subtitle',
|
||||
customExcerpt: 'New excerpt',
|
||||
postStatus: 'draft',
|
||||
author: post.authors.models[0],
|
||||
createdAt: moment(post.updatedAt).subtract(1, 'hour'),
|
||||
@ -114,7 +114,7 @@ describe('Acceptance: Post revisions', function () {
|
||||
this.server.create('post-revision', {
|
||||
post,
|
||||
title: 'Old Title',
|
||||
customExcerpt: 'Old subtitle',
|
||||
customExcerpt: 'Old excerpt',
|
||||
postStatus: 'draft',
|
||||
author: post.authors.models[0],
|
||||
createdAt: moment(post.updatedAt).subtract(1, 'day'),
|
||||
@ -127,19 +127,19 @@ describe('Acceptance: Post revisions', function () {
|
||||
await click('[data-test-psm-trigger]');
|
||||
await click('[data-test-toggle="post-history"]');
|
||||
|
||||
// subtitle is visible
|
||||
expect(find('[data-test-post-history-preview-subtitle]')).to.exist;
|
||||
expect(find('[data-test-post-history-preview-subtitle]')).to.have.trimmed.text('New subtitle');
|
||||
// excerpt is visible
|
||||
expect(find('[data-test-post-history-preview-excerpt]')).to.exist;
|
||||
expect(find('[data-test-post-history-preview-excerpt]')).to.have.trimmed.text('New excerpt');
|
||||
|
||||
// previous post can be previewed
|
||||
await click('[data-test-revision-item="1"] [data-test-button="preview-revision"]');
|
||||
expect(find('[data-test-post-history-preview-subtitle]')).to.have.trimmed.text('Old subtitle');
|
||||
expect(find('[data-test-post-history-preview-excerpt]')).to.have.trimmed.text('Old excerpt');
|
||||
|
||||
// previous post can be restored
|
||||
await click('[data-test-revision-item="1"] [data-test-button="restore-revision"]');
|
||||
await click('[data-test-modal="restore-revision"] [data-test-button="restore"]');
|
||||
|
||||
// post has been saved with correct data
|
||||
expect(post.attrs.customExcerpt).to.equal('Old subtitle');
|
||||
expect(post.attrs.customExcerpt).to.equal('Old excerpt');
|
||||
});
|
||||
});
|
||||
|
@ -0,0 +1,3 @@
|
||||
const {createRenameColumnMigration} = require('../../utils');
|
||||
|
||||
module.exports = createRenameColumnMigration('newsletters', 'show_subtitle', 'show_excerpt');
|
@ -30,7 +30,7 @@ module.exports = {
|
||||
header_image: {type: 'string', maxlength: 2000, nullable: true},
|
||||
show_header_icon: {type: 'boolean', nullable: false, defaultTo: true},
|
||||
show_header_title: {type: 'boolean', nullable: false, defaultTo: true},
|
||||
show_subtitle: {type: 'boolean', nullable: false, defaultTo: false},
|
||||
show_excerpt: {type: 'boolean', nullable: false, defaultTo: false},
|
||||
title_font_category: {type: 'string', maxlength: 191, nullable: false, defaultTo: 'sans_serif', validations: {isIn: [['serif', 'sans_serif']]}},
|
||||
title_alignment: {type: 'string', maxlength: 191, nullable: false, defaultTo: 'center', validations: {isIn: [['center', 'left']]}},
|
||||
show_feature_image: {type: 'boolean', nullable: false, defaultTo: true},
|
||||
|
@ -30,7 +30,7 @@ const Newsletter = ghostBookshelf.Model.extend({
|
||||
border_color: null,
|
||||
title_color: null,
|
||||
feedback_enabled: false,
|
||||
show_subtitle: false
|
||||
show_excerpt: false
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -52,8 +52,8 @@ const ALPHA_FEATURES = [
|
||||
'importMemberTier',
|
||||
'lexicalIndicators',
|
||||
'adminXDemo',
|
||||
'editorSubtitle',
|
||||
'newsletterSubtitle',
|
||||
'editorExcerpt',
|
||||
'newsletterExcerpt',
|
||||
'internalLinkingAtLinks'
|
||||
];
|
||||
|
||||
|
@ -5351,7 +5351,7 @@ exports[`Members API Can subscribe to a newsletter 5: [headers] 1`] = `
|
||||
Object {
|
||||
"access-control-allow-origin": "http://127.0.0.1:2369",
|
||||
"cache-control": "no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0",
|
||||
"content-length": "4604",
|
||||
"content-length": "4601",
|
||||
"content-type": "application/json; charset=utf-8",
|
||||
"content-version": StringMatching /v\\\\d\\+\\\\\\.\\\\d\\+/,
|
||||
"etag": StringMatching /\\(\\?:W\\\\/\\)\\?"\\(\\?:\\[ !#-\\\\x7E\\\\x80-\\\\xFF\\]\\*\\|\\\\r\\\\n\\[\\\\t \\]\\|\\\\\\\\\\.\\)\\*"/,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -35,7 +35,7 @@ const validateRouteSettings = require('../../../../../core/server/services/route
|
||||
*/
|
||||
describe('DB version integrity', function () {
|
||||
// Only these variables should need updating
|
||||
const currentSchemaHash = 'e6fff125e9a6cd6167acaf9983a21319';
|
||||
const currentSchemaHash = '7ad5a5720c29fab6b8cebb19da496935';
|
||||
const currentFixturesHash = 'a489d615989eab1023d4b8af0ecee7fd';
|
||||
const currentSettingsHash = '5c957ceb48c4878767d7d3db484c592d';
|
||||
const currentRoutesHash = '3d180d52c663d173a6be791ef411ed01';
|
||||
|
@ -1017,14 +1017,14 @@ class EmailRenderer {
|
||||
}
|
||||
}
|
||||
|
||||
let subtitleFontClass = '';
|
||||
let excerptFontClass = '';
|
||||
const bodyFont = newsletter.get('body_font_category');
|
||||
const titleFont = newsletter.get('title_font_category');
|
||||
|
||||
if (titleFont === 'serif' && bodyFont === 'serif') {
|
||||
subtitleFontClass = 'post-subtitle-serif-serif';
|
||||
excerptFontClass = 'post-excerpt-serif-serif';
|
||||
} else if (titleFont === 'serif' && bodyFont !== 'serif') {
|
||||
subtitleFontClass = 'post-subtitle-serif-sans';
|
||||
excerptFontClass = 'post-excerpt-serif-sans';
|
||||
}
|
||||
|
||||
const data = {
|
||||
@ -1056,7 +1056,7 @@ class EmailRenderer {
|
||||
newsletter: {
|
||||
name: newsletter.get('name'),
|
||||
showPostTitleSection: newsletter.get('show_post_title_section'),
|
||||
showSubtitle: newsletter.get('show_subtitle'),
|
||||
showExcerpt: newsletter.get('show_excerpt'),
|
||||
showCommentCta: newsletter.get('show_comment_cta') && this.#settingsCache.get('comments_enabled') !== 'off' && !hasEmailOnlyFlag,
|
||||
showSubscriptionDetails: newsletter.get('show_subscription_details')
|
||||
},
|
||||
@ -1090,7 +1090,7 @@ class EmailRenderer {
|
||||
classes: {
|
||||
title: 'post-title' + (newsletter.get('title_font_category') === 'serif' ? ` post-title-serif` : ``) + (newsletter.get('title_alignment') === 'left' ? ` post-title-left` : ``),
|
||||
titleLink: 'post-title-link' + (newsletter.get('title_alignment') === 'left' ? ` post-title-link-left` : ``),
|
||||
subtitle: 'post-subtitle' + ` ` + subtitleFontClass + (newsletter.get('title_alignment') === 'left' ? ` post-subtitle-left` : ``),
|
||||
excerpt: 'post-excerpt' + ` ` + excerptFontClass + (newsletter.get('title_alignment') === 'left' ? ` post-excerpt-left` : ``),
|
||||
meta: 'post-meta' + (newsletter.get('title_alignment') === 'left' ? ` post-meta-left` : ` post-meta-center`),
|
||||
body: newsletter.get('body_font_category') === 'sans_serif' ? `post-content-sans-serif` : `post-content`
|
||||
},
|
||||
|
@ -377,12 +377,12 @@ figure blockquote p {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.post-subtitle-wrapper {
|
||||
.post-excerpt-wrapper {
|
||||
width: 100%;
|
||||
max-width: 600px !important;
|
||||
}
|
||||
|
||||
.post-subtitle {
|
||||
.post-excerpt {
|
||||
margin: 0;
|
||||
padding-bottom: 20px;
|
||||
color: #15212A;
|
||||
@ -391,17 +391,17 @@ figure blockquote p {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.post-subtitle-serif-serif {
|
||||
.post-excerpt-serif-serif {
|
||||
font-family: Georgia, serif;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.post-subtitle-serif-sans {
|
||||
.post-excerpt-serif-sans {
|
||||
font-size: 18px;
|
||||
font-family: Georgia, serif;
|
||||
}
|
||||
|
||||
.post-subtitle-left {
|
||||
.post-excerpt-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@ -1313,7 +1313,7 @@ a[data-flickr-embed] img {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
table.body .post-subtitle {
|
||||
table.body .post-excerpt {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
|
@ -79,11 +79,11 @@
|
||||
<a href="{{post.url}}" class="{{classes.titleLink}}">{{post.title}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{#hasFeature 'newsletterSubtitle'}}
|
||||
{{#if (and newsletter.showSubtitle post.customExcerpt)}}
|
||||
{{#hasFeature 'newsletterExcerpt'}}
|
||||
{{#if (and newsletter.showExcerpt post.customExcerpt)}}
|
||||
<tr>
|
||||
<td class="post-subtitle-wrapper" style="width: 100%">
|
||||
<p class="{{classes.subtitle}}">{{post.customExcerpt}}</p>
|
||||
<td class="post-excerpt-wrapper" style="width: 100%">
|
||||
<p class="{{classes.excerpt}}">{{post.customExcerpt}}</p>
|
||||
</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
|
@ -1769,18 +1769,18 @@ describe('Email renderer', function () {
|
||||
assert.equal(response.html.includes('width="auto" height="auto"'), false, 'Should not replace img height and width with auto from css');
|
||||
});
|
||||
|
||||
describe('show subtitle', function () {
|
||||
describe('show excerpt', function () {
|
||||
beforeEach(function () {
|
||||
labsEnabled = {
|
||||
newsletterSubtitle: true
|
||||
newsletterExcerpt: true
|
||||
};
|
||||
});
|
||||
|
||||
it('is rendered when enabled and customExcerpt is present', async function () {
|
||||
const post = createModel(Object.assign({}, basePost, {custom_excerpt: 'This is a subtitle'}));
|
||||
const post = createModel(Object.assign({}, basePost, {custom_excerpt: 'This is an excerpt'}));
|
||||
const newsletter = createModel({
|
||||
show_post_title_section: true,
|
||||
show_subtitle: true
|
||||
show_excerpt: true
|
||||
});
|
||||
const segment = null;
|
||||
const options = {};
|
||||
@ -1794,14 +1794,14 @@ describe('Email renderer', function () {
|
||||
|
||||
await validateHtml(response.html);
|
||||
|
||||
assert.equal(response.html.match(/This is a subtitle/g).length, 2, 'Subtitle should appear twice (preheader and subtitle section)');
|
||||
assert.equal(response.html.match(/This is an excerpt/g).length, 2, 'Excerpt should appear twice (preheader and excerpt section)');
|
||||
});
|
||||
|
||||
it('is not rendered when disabled and customExcerpt is present', async function () {
|
||||
const post = createModel(Object.assign({}, basePost, {custom_excerpt: 'This is a subtitle'}));
|
||||
const post = createModel(Object.assign({}, basePost, {custom_excerpt: 'This is an excerpt'}));
|
||||
const newsletter = createModel({
|
||||
show_post_title_section: true,
|
||||
show_subtitle: false
|
||||
show_excerpt: false
|
||||
});
|
||||
const segment = null;
|
||||
const options = {};
|
||||
@ -1815,15 +1815,15 @@ describe('Email renderer', function () {
|
||||
|
||||
await validateHtml(response.html);
|
||||
|
||||
assert.equal(response.html.match(/This is a subtitle/g).length, 1, 'Subtitle should only appear once (preheader, subtitle section skipped)');
|
||||
response.html.should.not.containEql('post-subtitle-wrapper');
|
||||
assert.equal(response.html.match(/This is an excerpt/g).length, 1, 'Subtitle should only appear once (preheader, excerpt section skipped)');
|
||||
response.html.should.not.containEql('post-excerpt-wrapper');
|
||||
});
|
||||
|
||||
it('does not render when enabled and customExcerpt is not present', async function () {
|
||||
const post = createModel(Object.assign({}, basePost, {custom_excerpt: null}));
|
||||
const newsletter = createModel({
|
||||
show_post_title_section: true,
|
||||
show_subtitle: true
|
||||
show_excerpt: true
|
||||
});
|
||||
const segment = null;
|
||||
const options = {};
|
||||
@ -1837,7 +1837,7 @@ describe('Email renderer', function () {
|
||||
|
||||
await validateHtml(response.html);
|
||||
|
||||
response.html.should.not.containEql('post-subtitle-wrapper');
|
||||
response.html.should.not.containEql('post-excerpt-wrapper');
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -2073,12 +2073,12 @@ describe('Email renderer', function () {
|
||||
title: 'post-title post-title-serif post-title-left',
|
||||
titleLink: 'post-title-link post-title-link-left',
|
||||
meta: 'post-meta post-meta-left',
|
||||
subtitle: 'post-subtitle post-subtitle-serif-sans post-subtitle-left',
|
||||
excerpt: 'post-excerpt post-excerpt-serif-sans post-excerpt-left',
|
||||
body: 'post-content-sans-serif'
|
||||
});
|
||||
});
|
||||
|
||||
it('has correct subtitle classes for serif title+body', async function () {
|
||||
it('has correct excerpt classes for serif title+body', async function () {
|
||||
const html = '';
|
||||
const post = createModel({
|
||||
posts_meta: createModel({}),
|
||||
@ -2089,10 +2089,10 @@ describe('Email renderer', function () {
|
||||
title_font_category: 'serif',
|
||||
title_alignment: 'left',
|
||||
body_font_category: 'serif',
|
||||
show_subtitle: true
|
||||
show_excerpt: true
|
||||
});
|
||||
const data = await emailRenderer.getTemplateData({post, newsletter, html, addPaywall: false});
|
||||
assert.equal(data.classes.subtitle, 'post-subtitle post-subtitle-serif-serif post-subtitle-left');
|
||||
assert.equal(data.classes.excerpt, 'post-excerpt post-excerpt-serif-serif post-excerpt-left');
|
||||
});
|
||||
|
||||
it('show comment CTA is enabled if labs disabled', async function () {
|
||||
|
Loading…
Reference in New Issue
Block a user