Added TK indicator support to post title (#19231)

closes TryGhost/Product#4208
- added TK indicator to post title
- added to TK count in confirmation flow
This commit is contained in:
Steve Larson 2023-12-05 09:41:54 -06:00 committed by GitHub
parent 960fde80db
commit 96320d378a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 7 deletions

View File

@ -28,6 +28,15 @@
</span>
{{/if}}
{{#if (and (feature "tkReminders") @titleHasTk)}}
<div
class="tk-indicator" data-testid="tk-indicator"
{{on "click" this.focusTitle}}
>
TK
</div>
{{/if}}
<GhTextarea
@class="gh-editor-title {{if (and (not @cardOptions.post.showTitleAndFeatureImage) (not this.titleIsFocused)) "faded"}}"
@placeholder={{@titlePlaceholder}}
@ -56,7 +65,7 @@
@registerAPI={{this.registerEditorAPI}}
@cursorDidExitAtTop={{this.focusTitle}}
@updateWordCount={{@updateWordCount}}
@updateTkCount={{@updateTkCount}}
@updatePostTkCount={{@updatePostTkCount}}
/>
</div>
</div>

View File

@ -536,7 +536,7 @@ export default class KoenigLexicalEditor extends Component {
registerAPI={this.args.registerAPI}
/>
<WordCountPlugin editorResource={this.editorResource} onChange={this.args.updateWordCount} />
{this.feature.tkReminders && <TKPlugin editorResource={this.editorResource} onCountChange={this.args.updateTkCount} />}
{this.feature.tkReminders && <TKPlugin editorResource={this.editorResource} onCountChange={this.args.updatePostTkCount} />}
</KoenigComposer>
</Suspense>
</ErrorHandler>

View File

@ -35,6 +35,9 @@ const AUTOSAVE_TIMEOUT = 3000;
// time in ms to force a save if the user is continuously typing
const TIMEDSAVE_TIMEOUT = 60000;
const TK_REGEX = new RegExp(/(^|.)([^\p{L}\p{N}\s]*(TK)+[^\p{L}\p{N}\s]*)(.)?/u);
const WORD_CHAR_REGEX = new RegExp(/\p{L}|\p{N}/u);
// this array will hold properties we need to watch for this.hasDirtyAttributes
let watchedProps = [
'post.lexicalScratch',
@ -127,7 +130,7 @@ export default class LexicalEditorController extends Controller {
// koenig related properties
wordCount = 0;
tkCount = 0;
postTkCount = 0;
/* private properties ----------------------------------------------------*/
@ -215,6 +218,55 @@ export default class LexicalEditorController extends Controller {
return config.environment !== 'test' && this.get('post.isDraft');
}
TK_REGEX = new RegExp(/(^|.)([^\p{L}\p{N}\s]*(TK)+[^\p{L}\p{N}\s]*)(.)?/u);
WORD_CHAR_REGEX = new RegExp(/\p{L}|\p{N}/u);
@computed('post.titleScratch')
get titleHasTk() {
let text = this.post.titleScratch;
let matchArr = TK_REGEX.exec(text);
if (matchArr === null) {
return false;
}
function isValidMatch(match) {
// negative lookbehind isn't supported before Safari 16.4
// so we capture the preceding char and test it here
if (match[1] && match[1].trim() && WORD_CHAR_REGEX.test(match[1])) {
return false;
}
// we also check any following char in code to avoid an overly
// complex regex when looking for word-chars following the optional
// trailing symbol char
if (match[4] && match[4].trim() && WORD_CHAR_REGEX.test(match[4])) {
return false;
}
return true;
}
// our regex will match invalid TKs because we can't use negative lookbehind
// so we need to loop through the matches discarding any that are invalid
// and moving on to any subsequent matches
while (matchArr !== null && !isValidMatch(matchArr)) {
text = text.slice(matchArr.index + matchArr[0].length - 1);
matchArr = TK_REGEX.exec(text);
}
if (matchArr === null) {
return false;
}
return true;
}
@computed('titleHasTk', 'postTkCount')
get tkCount() {
return (this.titleHasTk ? 1 : 0) + this.postTkCount;
}
@action
updateScratch(lexical) {
this.set('post.lexicalScratch', JSON.stringify(lexical));
@ -312,8 +364,8 @@ export default class LexicalEditorController extends Controller {
}
@action
updateTkCount(count) {
this.set('tkCount', count);
updatePostTkCount(count) {
this.set('postTkCount', count);
}
@action
@ -1082,7 +1134,7 @@ export default class LexicalEditorController extends Controller {
this.set('shouldFocusTitle', false);
this.set('showSettingsMenu', false);
this.set('wordCount', 0);
this.set('tkCount', 0);
this.set('postTkCount', 0);
// remove the onbeforeunload handler as it's only relevant whilst on
// the editor route

View File

@ -683,6 +683,17 @@ body[data-user-is-dragging] .gh-editor-feature-image-dropzone {
opacity: .5;
}
.gh-editor-title-container .tk-indicator {
position: absolute;
top: 15px;
right: -5.6rem;
padding: .4rem;
color: #95A1AD;
font-size: 1.2rem;
font-weight: 500;
cursor: default;
}
.gh-editor-back-button {
height: 34px;
margin-right: 8px;

View File

@ -67,6 +67,7 @@
@title={{readonly this.post.titleScratch}}
@titleAutofocus={{this.shouldFocusTitle}}
@titlePlaceholder={{concat (capitalize this.post.displayName) " title"}}
@titleHasTk={{this.titleHasTk}}
@onTitleChange={{this.updateTitleScratch}}
@onTitleBlur={{perform this.saveTitleTask}}
@body={{readonly this.post.lexicalScratch}}
@ -77,7 +78,7 @@
@scrollOffsetBottomSelector=".gh-mobile-nav-bar"
@onEditorCreated={{this.setKoenigEditor}}
@updateWordCount={{this.updateWordCount}}
@updateTkCount={{this.updateTkCount}}
@updatePostTkCount={{this.updatePostTkCount}}
@featureImage={{this.post.featureImage}}
@featureImageAlt={{this.post.featureImageAlt}}
@featureImageCaption={{this.post.featureImageCaption}}