mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 14:43:46 +01:00
Merge pull request #32244 from overleaf/ab-labs-in-feature-flags
[web] Merge Labs programme into the Feature flags system GitOrigin-RevId: db75e07bf3272becc11ef1eeda3850098b3daa9d
This commit is contained in:
committed by
Copybot
parent
6f3e0963b8
commit
671df33da3
@@ -18,25 +18,21 @@ type LinkProps = {
|
||||
onMouseDown?: MouseEventHandler<HTMLAnchorElement>
|
||||
}
|
||||
|
||||
const defaultHref = '/beta/participate'
|
||||
|
||||
const BetaBadge: FC<{
|
||||
tooltip?: TooltipProps
|
||||
link?: LinkProps
|
||||
description?: ReactNode
|
||||
phase?: string
|
||||
}> = ({
|
||||
tooltip,
|
||||
link = { href: defaultHref },
|
||||
description,
|
||||
phase = 'beta',
|
||||
}) => {
|
||||
}> = ({ tooltip, link = {}, description, phase = 'beta' }) => {
|
||||
const { href, ...linkProps } = link
|
||||
|
||||
const linkedBadge = (
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href={href || defaultHref}
|
||||
href={
|
||||
href || (phase === 'labs' ? '/labs/participate' : '/beta/participate')
|
||||
}
|
||||
{...linkProps}
|
||||
>
|
||||
<span className="visually-hidden">{description || tooltip?.text}</span>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import { FC, useMemo } from 'react'
|
||||
import { micromark } from 'micromark'
|
||||
import DOMPurify from 'dompurify'
|
||||
|
||||
const PURIFY_CONFIG = {
|
||||
ALLOWED_TAGS: ['#text', 'p', 'em', 'strong', 'a'],
|
||||
ALLOWED_ATTR: ['href'],
|
||||
}
|
||||
|
||||
const LINK_REL = 'noreferrer noopener'
|
||||
const LINK_TARGET = '_BLANK'
|
||||
|
||||
function sanitizeDescription(description: string) {
|
||||
DOMPurify.addHook('afterSanitizeAttributes', node => {
|
||||
if (node.nodeName === 'A') {
|
||||
node.setAttribute('rel', LINK_REL)
|
||||
node.setAttribute('target', LINK_TARGET)
|
||||
}
|
||||
})
|
||||
|
||||
try {
|
||||
return DOMPurify.sanitize(micromark(description), PURIFY_CONFIG)
|
||||
} finally {
|
||||
DOMPurify.removeHook('afterSanitizeAttributes')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a labs experiment description from markdown to sanitized HTML.
|
||||
* Only bold, italic, and links are supported.
|
||||
*/
|
||||
export const LabsDescription: FC<{ description: string }> = ({
|
||||
description,
|
||||
}) => {
|
||||
const html = useMemo(() => sanitizeDescription(description), [description])
|
||||
|
||||
return <div dangerouslySetInnerHTML={{ __html: html }} />
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import React from 'react'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
|
||||
type LabsExperimentIconProps = {
|
||||
icon: string
|
||||
}
|
||||
|
||||
const LabsExperimentIcon: React.FC<LabsExperimentIconProps> = ({ icon }) => {
|
||||
if (!icon) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<MaterialIcon
|
||||
type={icon}
|
||||
className="rounded bg-primary-subtle labs-experiment-icon"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default LabsExperimentIcon
|
||||
@@ -73,14 +73,14 @@ export function LabsExperimentWidget({
|
||||
<h3 className="h4">{title}</h3>
|
||||
{optedIn && <OLBadge bg="info">{t('enabled')}</OLBadge>}
|
||||
</div>
|
||||
<p className="small">
|
||||
<div className="small">
|
||||
{optedIn && optedInDescription ? optedInDescription : description}{' '}
|
||||
{helpPath && (
|
||||
<a href={helpPath} target="_blank" rel="noreferrer">
|
||||
{t('learn_more')}
|
||||
</a>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{optedIn && feedbackLink && (
|
||||
|
||||
Reference in New Issue
Block a user