85 lines
3.0 KiB
TypeScript
85 lines
3.0 KiB
TypeScript
import { t } from '@/i18n'
|
|
import type { DescriptionSource } from '@/lib/seoPreview'
|
|
import type { SeoSuggestion, SuggestionCode, SuggestionField } from '@/lib/seoTypes'
|
|
|
|
function descriptionLength(params: Record<string, number>) {
|
|
return t('The description is {0} characters. About 70 to 160 reads best in results.', [
|
|
params.length,
|
|
])
|
|
}
|
|
|
|
const MESSAGES: Record<SuggestionCode, (params: Record<string, number>) => string> = {
|
|
title_long: (params) =>
|
|
t('The meta title is {0} characters. Search engines may cut it off after about {1}.', [
|
|
params.length,
|
|
params.max,
|
|
]),
|
|
title_empty: () => t('No meta title yet. The article title is used instead.'),
|
|
desc_short: descriptionLength,
|
|
desc_long: (params) =>
|
|
t('The description is {0} characters. Search engines may cut it off after about {1}.', [
|
|
params.length,
|
|
params.max,
|
|
]),
|
|
cover_alt: () => t('The cover image has no alt text. Add a short description of it.'),
|
|
cover_none: () => t("No cover image. The site's social image is used."),
|
|
slug_long: (params) =>
|
|
t('The slug is {0} characters. Shorter addresses are easier to share.', [params.length]),
|
|
no_au: () => t('This article has no authors, so the structured data has no author.'),
|
|
no_h: () => t('The body has no headings. H2 headings help readers scan the article.'),
|
|
body_alt: (params) =>
|
|
params.count === 1
|
|
? t('1 image in the body has no alt text.')
|
|
: t('{0} images in the body have no alt text.', [params.count]),
|
|
short: () => t('The article is under 300 words. That is fine for a short note.'),
|
|
}
|
|
|
|
const LINK_LABELS: Record<SuggestionField, () => string> = {
|
|
seo_title: () => t('Go to meta title'),
|
|
seo_description: () => t('Go to meta description'),
|
|
cover_image_alt: () => t('Go to cover image'),
|
|
cover_image_id: () => t('Go to cover image'),
|
|
slug: () => t('Go to URL slug'),
|
|
author_ids: () => t('Go to authors'),
|
|
body: () => t('Go to body'),
|
|
}
|
|
|
|
export function suggestionMessage(suggestion: SeoSuggestion) {
|
|
const message = MESSAGES[suggestion.code]
|
|
return message ? message(suggestion.params ?? {}) : suggestion.code
|
|
}
|
|
|
|
export function suggestionLinkLabel(field: SuggestionField) {
|
|
const label = LINK_LABELS[field]
|
|
return label ? label() : ''
|
|
}
|
|
|
|
const CHIPS = {
|
|
article_title: () => t('Using article title'),
|
|
body: () => t('Using first sentence of the body'),
|
|
excerpt: () => t('Using the excerpt'),
|
|
site_description: () => t('Using the site default description'),
|
|
cover_image: () => t('Using cover image'),
|
|
site_image: () => t('Using site social image'),
|
|
no_image: () => t('No image'),
|
|
canonical: () => t('Using site address and slug'),
|
|
meta_title: () => t('Using meta title'),
|
|
meta_description: () => t('Using meta description'),
|
|
}
|
|
|
|
export type ChipKey = keyof typeof CHIPS
|
|
|
|
export function chipLabel(key: ChipKey) {
|
|
return CHIPS[key]()
|
|
}
|
|
|
|
export function descriptionChip(source: DescriptionSource | string) {
|
|
const keys: Record<string, ChipKey> = {
|
|
excerpt: 'excerpt',
|
|
body: 'body',
|
|
site: 'site_description',
|
|
}
|
|
const key = keys[source]
|
|
return key ? chipLabel(key) : null
|
|
}
|