import { Atom , ToLatexOptions } from '../core/atom-class' ; import { addSVGOverlay , Box } from '../core/box' ; import { Context } from '../core/context' ; import { convertToDimension } from '../core/parser' ; import { convertDimensionToEm } from '../core/registers-utils' ; import { Style } from '../public/core' ; export type EncloseAtomOptions = { shadow ? : string ; strokeWidth ? : string ; strokeStyle ? : string ; svgStrokeStyle ? : string ; strokeColor ? : string ; borderStyle ? : string ; padding ? : string ; backgroundcolor ? : string ; style : Style ; } ; export type Notations = { downdiagonalstrike ? : boolean ; updiagonalstrike ? : boolean ; verticalstrike ? : boolean ; horizontalstrike ? : boolean ; updiagonalarrow ? : boolean ; right ? : boolean ; bottom ? : boolean ; left ? : boolean ; top ? : boolean ; circle ? : boolean ; roundedbox ? : boolean ; madruwb ? : boolean ; actuarial ? : boolean ; box ? : boolean ; } ; export class EncloseAtom extends Atom { backgroundcolor ? : string ; border : string ; private readonly notation : Notations ; private readonly shadow ? : string ; private readonly strokeWidth ? : string ; private readonly strokeStyle ? : string ; private readonly svgStrokeStyle ? : string ; private readonly strokeColor ? : string ; private readonly borderStyle ? : string ; private readonly padding ? : string ; constructor ( command , body , notation , options ) { super ( 'enclose' , { command , style : options . style } ) ; this . body = body ; this . backgroundcolor = options . backgroundcolor ; if ( notation . updiagonalarrow ) { notation . updiagonalstrike = false ; } if ( notation . box ) { notation . left = false ; notation . right = false ; notation . bottom = false ; notation . top = false ; } this . notation = notation ; this . shadow = options . shadow ; this . strokeWidth = options . strokeWidth ; this . strokeStyle = options . strokeStyle ; this . svgStrokeStyle = options . svgStrokeStyle ; this . strokeColor = options . strokeColor ; this . borderStyle = options . borderStyle ; this . padding = options . padding ; this . captureSelection = true ; } serialize ( options ) { let result = this . command ?? '' ; if ( this . command === '\\enclose' ) { result += '{' + Object . keys ( this . notation ) . join ( ' ' ) + '}' ; let style = '' ; let sep = '' ; if ( this . backgroundcolor && this . backgroundcolor !== 'transparent' ) { style += sep + 'mathbackground="' + this . backgroundcolor + '"' ; sep = ',' ; } if ( this . shadow && this . shadow !== 'auto' ) { style += sep + 'shadow="' + this . shadow + '"' ; sep = ',' ; } if ( this . strokeWidth || this . strokeStyle !== 'solid' ) { style += sep + this . borderStyle ; sep = ',' ; } else if ( this . strokeColor && this . strokeColor !== 'currentColor' ) { style += sep + 'mathcolor="' + this . strokeColor + '"' ; sep = ',' ; } if ( style ) { result += `[${ style }]` ; } } result += `{${ this . bodyToLatex ( options ) }}` ; return result ; } render ( parentContext ) { const context = new Context ( parentContext , this . style ) ; const base = Atom . createBox ( context , this . body ) ; if ( ! base ) return null ; const padding = convertDimensionToEm ( this . padding && this . padding !== 'auto' ? convertToDimension ( this . padding , parentContext . registers ) : context . getRegisterAsDimension ( 'fboxsep' ) ) ?? 0 ; const notation = new Box ( null , { classes : 'ML__notation' } ) ; notation . setStyle ( 'position' , 'absolute' ) ; notation . setStyle ( 'height' , base . height + base . depth + 2 * padding , 'em' ) ; notation . height = base . height + padding ; notation . depth = base . depth + padding ; if ( padding !== 0 ) { notation . setStyle ( 'width' , `calc(100% + ${ 2 * padding }em)` ) ; } else { notation . setStyle ( 'width' , '100%' ) ; } notation . setStyle ( 'top' , - base . height + 2 * padding , 'em' ) ; notation . setStyle ( 'left' , - padding , 'em' ) ; notation . setStyle ( 'z-index' , '-1' ) ; notation . setStyle ( 'box-sizing' , 'border-box' ) ; if ( this . backgroundcolor ) { notation . setStyle ( 'background-color' , this . backgroundcolor ) ; } if ( this . notation . box ) notation . setStyle ( 'border' , this . borderStyle ) ; if ( this . notation . actuarial ) { notation . setStyle ( 'border-top' , this . borderStyle ) ; notation . setStyle ( 'border-right' , this . borderStyle ) ; } if ( this . notation . madruwb ) { notation . setStyle ( 'border-bottom' , this . borderStyle ) ; notation . setStyle ( 'border-right' , this . borderStyle ) ; } if ( this . notation . roundedbox ) { notation . setStyle ( 'border-radius' , ( base . height + base . depth ) / 2 , 'em' ) ; notation . setStyle ( 'border' , this . borderStyle ) ; } if ( this . notation . circle ) { notation . setStyle ( 'border-radius' , '50%' ) ; notation . setStyle ( 'border' , this . borderStyle ) ; } if ( this . notation . top ) { notation . setStyle ( 'border-top' , this . borderStyle ) ; } if ( this . notation . left ) { notation . setStyle ( 'border-left' , this . borderStyle ) ; } if ( this . notation . right ) { notation . setStyle ( 'border-right' , this . borderStyle ) ; } if ( this . notation . bottom ) { notation . setStyle ( 'border-bottom' , this . borderStyle ) ; } let svg = '' ; if ( this . notation . horizontalstrike ) { svg += '<line x1="3%"  y1="50%" x2="97%" y2="50%"' ; svg += ` stroke-width="${ this . strokeWidth }" stroke="${ this . strokeColor }"` ; svg += ' stroke-linecap="round"' ; if ( this . svgStrokeStyle ) { svg += ` stroke-dasharray="${ this . svgStrokeStyle }"` ; } svg += '/>' ; } if ( this . notation . verticalstrike ) { svg += '<line x1="50%"  y1="3%" x2="50%" y2="97%"' ; svg += ` stroke-width="${ this . strokeWidth }" stroke="${ this . strokeColor }"` ; svg += ' stroke-linecap="round"' ; if ( this . svgStrokeStyle ) { svg += ` stroke-dasharray="${ this . svgStrokeStyle }"` ; } svg += '/>' ; } if ( this . notation . updiagonalstrike ) { svg += '<line x1="3%"  y1="97%" x2="97%" y2="3%"' ; svg += ` stroke-width="${ this . strokeWidth }" stroke="${ this . strokeColor }"` ; svg += ' stroke-linecap="round"' ; if ( this . svgStrokeStyle ) { svg += ` stroke-dasharray="${ this . svgStrokeStyle }"` ; } svg += '/>' ; } if ( this . notation . downdiagonalstrike ) { svg += '<line x1="3%"  y1="3%" x2="97%" y2="97%"' ; svg += ` stroke-width="${ this . strokeWidth }" stroke="${ this . strokeColor }"` ; svg += ' stroke-linecap="round"' ; if ( this . svgStrokeStyle ) { svg += ` stroke-dasharray="${ this . svgStrokeStyle }"` ; } svg += '/>' ; } if ( svg ) { let svgStyle ; if ( this . shadow !== 'none' ) { svgStyle = this . shadow === 'auto' ? 'filter: drop-shadow(0 0 .5px rgba(255, 255, 255, .7)) drop-shadow(1px 1px 2px #333)' : 'filter: drop-shadow(' + this . shadow + ')' ; } addSVGOverlay ( notation , svg , svgStyle ) ; } const result = new Box ( [ notation , base ] ) ; result . setStyle ( 'position' , 'relative' ) ; result . setStyle ( 'display' , 'inline' ) ; result . height = base . height + padding ; result . depth = base . depth + padding ; result . left = padding ; result . right = padding ; if ( this . caret ) result . caret = this . caret ; return result . wrap ( context ) ; } }