Accept full meta HTML in Tags & Badges (name is label only).
Admins paste complete <meta> tags as the value; the name field is only a list label. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
68b985dee3
commit
eb9b8b9fa3
@@ -6,7 +6,7 @@ import { useT } from '../i18n/useT'
|
|||||||
import styles from './WebsiteMetaTagModal.module.css'
|
import styles from './WebsiteMetaTagModal.module.css'
|
||||||
|
|
||||||
const ANIMATION_MS = 220
|
const ANIMATION_MS = 220
|
||||||
const META_NAME_RE = /^[a-zA-Z0-9_.:-]{1,80}$/
|
const META_HTML_RE = /^<meta\b[^>]*>/i
|
||||||
|
|
||||||
interface WebsiteMetaTagModalProps {
|
interface WebsiteMetaTagModalProps {
|
||||||
open: boolean
|
open: boolean
|
||||||
@@ -65,11 +65,11 @@ export function WebsiteMetaTagModal({
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
const trimmedName = name.trim()
|
const trimmedName = name.trim()
|
||||||
const trimmedContent = content.trim()
|
const trimmedContent = content.trim()
|
||||||
if (!trimmedName || !META_NAME_RE.test(trimmedName)) {
|
if (!trimmedName) {
|
||||||
setFormError(t('website.badges.meta.nameInvalid'))
|
setFormError(t('website.badges.meta.nameInvalid'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!trimmedContent) {
|
if (!trimmedContent || !META_HTML_RE.test(trimmedContent)) {
|
||||||
setFormError(t('website.badges.meta.contentRequired'))
|
setFormError(t('website.badges.meta.contentRequired'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2435,7 +2435,7 @@ const en = {
|
|||||||
'website.badges.errorLoad': 'Unable to load tags & badges.',
|
'website.badges.errorLoad': 'Unable to load tags & badges.',
|
||||||
'website.badges.errorSave': 'Unable to save tags & badges.',
|
'website.badges.errorSave': 'Unable to save tags & badges.',
|
||||||
'website.badges.meta.title': 'Custom meta tags',
|
'website.badges.meta.title': 'Custom meta tags',
|
||||||
'website.badges.meta.desc': 'Each row is added to the website head as',
|
'website.badges.meta.desc': 'Name is only a label. Value is the full tag, e.g.',
|
||||||
'website.badges.meta.sample': '<meta name="…" content="…">',
|
'website.badges.meta.sample': '<meta name="…" content="…">',
|
||||||
'website.badges.meta.add': 'Add meta tag',
|
'website.badges.meta.add': 'Add meta tag',
|
||||||
'website.badges.meta.modalTitle': 'Add meta tag',
|
'website.badges.meta.modalTitle': 'Add meta tag',
|
||||||
@@ -2445,12 +2445,13 @@ const en = {
|
|||||||
'website.badges.meta.nameLabel': 'Name',
|
'website.badges.meta.nameLabel': 'Name',
|
||||||
'website.badges.meta.valueLabel': 'Value',
|
'website.badges.meta.valueLabel': 'Value',
|
||||||
'website.badges.meta.remove': 'Remove meta tag',
|
'website.badges.meta.remove': 'Remove meta tag',
|
||||||
'website.badges.meta.empty': 'No custom tags yet. Use + to add a name and value.',
|
'website.badges.meta.empty': 'No custom tags yet. Use + to paste a full meta tag.',
|
||||||
'website.badges.meta.namePlaceholder': 'name (e.g. google-site-verification)',
|
'website.badges.meta.namePlaceholder': 'Label (e.g. Google verification)',
|
||||||
'website.badges.meta.contentPlaceholder': 'value / content',
|
'website.badges.meta.contentPlaceholder':
|
||||||
'website.badges.meta.nameInvalid':
|
'<meta name="google-site-verification" content="…">',
|
||||||
'Meta tag names may only use letters, numbers, and _ . : -',
|
'website.badges.meta.nameInvalid': 'Enter a short label for this meta tag.',
|
||||||
'website.badges.meta.contentRequired': 'Each meta tag needs both a name and a value.',
|
'website.badges.meta.contentRequired':
|
||||||
|
'Value must be a full meta tag starting with <meta …>.',
|
||||||
'website.badges.enamad.title': 'eNamad',
|
'website.badges.enamad.title': 'eNamad',
|
||||||
'website.badges.enamad.desc':
|
'website.badges.enamad.desc':
|
||||||
'If you have received an eNamad badge for your website, enter its HTML code below to show it on the site.',
|
'If you have received an eNamad badge for your website, enter its HTML code below to show it on the site.',
|
||||||
@@ -5353,7 +5354,7 @@ const fa: Record<MessageKey, string> = {
|
|||||||
'website.badges.errorLoad': 'بارگذاری تگ و نشانها ممکن نشد.',
|
'website.badges.errorLoad': 'بارگذاری تگ و نشانها ممکن نشد.',
|
||||||
'website.badges.errorSave': 'ذخیره تگ و نشانها ممکن نشد.',
|
'website.badges.errorSave': 'ذخیره تگ و نشانها ممکن نشد.',
|
||||||
'website.badges.meta.title': 'تگهای متا سفارشی',
|
'website.badges.meta.title': 'تگهای متا سفارشی',
|
||||||
'website.badges.meta.desc': 'هر ردیف در هد وبسایت قرار میگیرد بهصورت',
|
'website.badges.meta.desc': 'نام فقط برچسب است. مقدار کل تگ است، مثلاً',
|
||||||
'website.badges.meta.sample': '<meta name="…" content="…">',
|
'website.badges.meta.sample': '<meta name="…" content="…">',
|
||||||
'website.badges.meta.add': 'افزودن تگ متا',
|
'website.badges.meta.add': 'افزودن تگ متا',
|
||||||
'website.badges.meta.modalTitle': 'افزودن تگ متا',
|
'website.badges.meta.modalTitle': 'افزودن تگ متا',
|
||||||
@@ -5363,12 +5364,13 @@ const fa: Record<MessageKey, string> = {
|
|||||||
'website.badges.meta.nameLabel': 'نام',
|
'website.badges.meta.nameLabel': 'نام',
|
||||||
'website.badges.meta.valueLabel': 'مقدار',
|
'website.badges.meta.valueLabel': 'مقدار',
|
||||||
'website.badges.meta.remove': 'حذف تگ متا',
|
'website.badges.meta.remove': 'حذف تگ متا',
|
||||||
'website.badges.meta.empty': 'هنوز تگ سفارشی ندارید. با + نام و مقدار اضافه کنید.',
|
'website.badges.meta.empty': 'هنوز تگ سفارشی ندارید. با + کل تگ متا را بچسبانید.',
|
||||||
'website.badges.meta.namePlaceholder': 'نام (مثلاً google-site-verification)',
|
'website.badges.meta.namePlaceholder': 'برچسب (مثلاً تأیید گوگل)',
|
||||||
'website.badges.meta.contentPlaceholder': 'مقدار / محتوا',
|
'website.badges.meta.contentPlaceholder':
|
||||||
'website.badges.meta.nameInvalid':
|
'<meta name="google-site-verification" content="…">',
|
||||||
'نام تگ فقط میتواند شامل حروف، اعداد و _ . : - باشد.',
|
'website.badges.meta.nameInvalid': 'یک برچسب کوتاه برای این تگ متا وارد کنید.',
|
||||||
'website.badges.meta.contentRequired': 'هر تگ متا باید هم نام و هم مقدار داشته باشد.',
|
'website.badges.meta.contentRequired':
|
||||||
|
'مقدار باید یک تگ متای کامل باشد که با <meta …> شروع شود.',
|
||||||
'website.badges.enamad.title': 'اینماد',
|
'website.badges.enamad.title': 'اینماد',
|
||||||
'website.badges.enamad.desc':
|
'website.badges.enamad.desc':
|
||||||
'در صورتی که نشان اینماد برای وبسایت خود دریافت کرده اید، کد HTML آن را در زیر وارد کنید تا در وبسایت نمایش داده شود.',
|
'در صورتی که نشان اینماد برای وبسایت خود دریافت کرده اید، کد HTML آن را در زیر وارد کنید تا در وبسایت نمایش داده شود.',
|
||||||
|
|||||||
@@ -27,14 +27,20 @@
|
|||||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
line-height: 1.4;
|
line-height: 1.4;
|
||||||
color: var(--text-primary);
|
color: #0f172a;
|
||||||
background: rgba(15, 23, 42, 0.55);
|
background: #f8fafc;
|
||||||
border: 1px solid rgba(148, 163, 184, 0.28);
|
border: 1px solid rgba(148, 163, 184, 0.5);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
unicode-bidi: isolate;
|
unicode-bidi: isolate;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(html[data-theme='dark']) .metaSample {
|
||||||
|
color: var(--text-primary);
|
||||||
|
background: rgba(15, 23, 42, 0.55);
|
||||||
|
border-color: rgba(148, 163, 184, 0.28);
|
||||||
|
}
|
||||||
|
|
||||||
.metaList {
|
.metaList {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -66,15 +72,21 @@
|
|||||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: var(--text-primary);
|
color: #0f172a;
|
||||||
background: rgba(15, 23, 42, 0.45);
|
background: #ffffff;
|
||||||
border: 1px solid rgba(148, 163, 184, 0.25);
|
border: 1px solid rgba(148, 163, 184, 0.5);
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:global(html[data-theme='dark']) .metaName {
|
||||||
|
color: var(--text-primary);
|
||||||
|
background: rgba(15, 23, 42, 0.45);
|
||||||
|
border-color: rgba(148, 163, 184, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
.metaValue {
|
.metaValue {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import sharedStyles from './ProductSettingsPage.module.css'
|
|||||||
import settingsStyles from './WebsiteSettingsPage.module.css'
|
import settingsStyles from './WebsiteSettingsPage.module.css'
|
||||||
import styles from './WebsiteBadgesPage.module.css'
|
import styles from './WebsiteBadgesPage.module.css'
|
||||||
|
|
||||||
const META_NAME_RE = /^[a-zA-Z0-9_.:-]{1,80}$/
|
const META_HTML_RE = /^<meta\b[^>]*>/i
|
||||||
const MAX_META_TAGS = 40
|
const MAX_META_TAGS = 40
|
||||||
|
|
||||||
type TrustKind = 'enamad' | 'samandehi'
|
type TrustKind = 'enamad' | 'samandehi'
|
||||||
@@ -152,11 +152,11 @@ export function WebsiteBadgesPage() {
|
|||||||
const name = tag.name.trim()
|
const name = tag.name.trim()
|
||||||
const content = tag.content.trim()
|
const content = tag.content.trim()
|
||||||
if (!name && !content) continue
|
if (!name && !content) continue
|
||||||
if (!name || !META_NAME_RE.test(name)) {
|
if (!name) {
|
||||||
setError(t('website.badges.meta.nameInvalid'))
|
setError(t('website.badges.meta.nameInvalid'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!content) {
|
if (!content || !META_HTML_RE.test(content)) {
|
||||||
setError(t('website.badges.meta.contentRequired'))
|
setError(t('website.badges.meta.contentRequired'))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ export interface WebsiteSchemaSettings {
|
|||||||
sameAs: string[]
|
sameAs: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** name = admin label; content = full `<meta …>` HTML */
|
||||||
export interface WebsiteMetaTag {
|
export interface WebsiteMetaTag {
|
||||||
id: string
|
id: string
|
||||||
name: string
|
name: string
|
||||||
|
|||||||
Reference in New Issue
Block a user