@khanacademy/perseus-editor 28.6.5 → 28.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/article-editor.d.ts +9 -1
- package/dist/es/index.js +38 -38
- package/dist/es/index.js.map +1 -1
- package/dist/index.js +39 -39
- package/dist/index.js.map +1 -1
- package/dist/messages.d.ts +1 -1
- package/package.json +4 -4
package/dist/es/index.js
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
import { addLibraryVersionToPerseusDebug } from '@khanacademy/perseus-utils';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import React__default, { useId, createElement,
|
|
4
|
-
import { Widgets, excludeDenylistKeys, ApiOptions,
|
|
3
|
+
import React__default, { useState, useId, createElement, useRef, useEffect } from 'react';
|
|
4
|
+
import { PerseusMarkdown, Util, Widgets, excludeDenylistKeys, ApiOptions, preprocessTex, Log, components, Dependencies, iconTrash, ClassNames, usePerseusI18n, UserInputManager, Renderer, Categorizer as Categorizer$1, Changeable, EditorJsonify, Expression, interactiveSizes, GrapherWidget, GrapherUtil, containerSizeClass, getInteractiveBoxFromSizeClass, iconChevronDown, KhanColors, mathOnlyParser, getAngleCoords, getPolygonCoords, getPointCoords, getQuadraticCoords, getSinusoidCoords, getCircleCoords, getLinearSystemCoords, getSegmentCoords, getLineCoords, InteractiveGraphWidget, bodyXsmallBold, MatrixWidget, makeSafeUrl, PlotterWidget, TableWidget, widgets } from '@khanacademy/perseus';
|
|
5
5
|
export { widgets } from '@khanacademy/perseus';
|
|
6
|
-
import { isFeatureOn, CoreWidgetRegistry, applyDefaultsToWidget, PerseusError, Errors,
|
|
6
|
+
import { generateImageWidget, generateImageOptions, isFeatureOn, CoreWidgetRegistry, applyDefaultsToWidget, PerseusError, Errors, ItemExtras, categorizerLogic, csProgramLogic, definitionLogic, dropdownLogic, explanationLogic, expressionLogic, deriveExtraKeys, PerseusExpressionAnswerFormConsidered, freeResponseLogic, gradedGroupLogic, gradedGroupSetLogic, grapherLogic, GrapherUtil as GrapherUtil$1, groupLogic, iframeLogic, imageLogic, inputNumberLogic, interactionLogic, lockedFigureColors, lockedFigureFillStyles, interactiveGraphLogic, labelImageLogic, matcherLogic, matrixLogic, getMatrixSize, measurerLogic, numberLineLogic, numericInputLogic, ordererLogic, passageLogic, passageRefLogic, passageRefTargetLogic, phetSimulationLogic, plotterLogic, plotterPlotTypes, pythonProgramLogic, radioLogic, deriveNumCorrect, sorterLogic, tableLogic, videoLogic } from '@khanacademy/perseus-core';
|
|
7
|
+
import * as PerseusLinter from '@khanacademy/perseus-linter';
|
|
7
8
|
import Button from '@khanacademy/wonder-blocks-button';
|
|
8
9
|
import arrowCircleDownIcon from '@phosphor-icons/core/bold/arrow-circle-down-bold.svg';
|
|
9
10
|
import arrowCircleUpIcon from '@phosphor-icons/core/bold/arrow-circle-up-bold.svg';
|
|
10
11
|
import plusIcon from '@phosphor-icons/core/bold/plus-bold.svg';
|
|
11
12
|
import trashIcon from '@phosphor-icons/core/bold/trash-bold.svg';
|
|
12
13
|
import _ from 'underscore';
|
|
13
|
-
import
|
|
14
|
+
import { View, addStyle, Id } from '@khanacademy/wonder-blocks-core';
|
|
15
|
+
import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
|
|
16
|
+
import { sizing, spacing, semanticColor, color, font, border } from '@khanacademy/wonder-blocks-tokens';
|
|
17
|
+
import iconPass from '@phosphor-icons/core/fill/check-circle-fill.svg';
|
|
18
|
+
import iconWarning from '@phosphor-icons/core/fill/warning-fill.svg';
|
|
19
|
+
import { LabelSmall, LabelLarge, LabelMedium, HeadingSmall, HeadingXSmall, Caption, LabelXSmall, BodyMonospace, Footnote } from '@khanacademy/wonder-blocks-typography';
|
|
20
|
+
import { AccordionSection } from '@khanacademy/wonder-blocks-accordion';
|
|
14
21
|
import { StyleSheet, css } from 'aphrodite';
|
|
22
|
+
import caretRight from '@phosphor-icons/core/bold/caret-right-bold.svg';
|
|
23
|
+
import IconButton from '@khanacademy/wonder-blocks-icon-button';
|
|
15
24
|
import $ from 'jquery';
|
|
16
25
|
import katex from 'katex';
|
|
17
|
-
import { View, addStyle, Id } from '@khanacademy/wonder-blocks-core';
|
|
18
26
|
import { Strut, Spring } from '@khanacademy/wonder-blocks-layout';
|
|
19
27
|
import Switch from '@khanacademy/wonder-blocks-switch';
|
|
20
|
-
import { spacing, sizing, semanticColor, color, font, border } from '@khanacademy/wonder-blocks-tokens';
|
|
21
|
-
import { PhosphorIcon } from '@khanacademy/wonder-blocks-icon';
|
|
22
|
-
import caretRight from '@phosphor-icons/core/bold/caret-right-bold.svg';
|
|
23
28
|
import PropTypes from 'prop-types';
|
|
24
29
|
import classNames from 'classnames';
|
|
25
|
-
import * as PerseusLinter from '@khanacademy/perseus-linter';
|
|
26
|
-
import iconPass from '@phosphor-icons/core/fill/check-circle-fill.svg';
|
|
27
|
-
import iconWarning from '@phosphor-icons/core/fill/warning-fill.svg';
|
|
28
|
-
import { LabelSmall, LabelLarge, LabelMedium, HeadingSmall, HeadingXSmall, Caption, LabelXSmall, BodyMonospace, Footnote } from '@khanacademy/wonder-blocks-typography';
|
|
29
|
-
import { AccordionSection } from '@khanacademy/wonder-blocks-accordion';
|
|
30
30
|
import { Checkbox as Checkbox$1, TextField, LabeledTextField, TextArea } from '@khanacademy/wonder-blocks-form';
|
|
31
31
|
import { StatefulKeypadContextProvider, KeypadContext } from '@khanacademy/keypad-context';
|
|
32
32
|
import { MobileKeypad, useMathInputI18n, createMathField } from '@khanacademy/math-input';
|
|
@@ -63,7 +63,7 @@ import xIcon from '@phosphor-icons/core/regular/x.svg';
|
|
|
63
63
|
import checkIcon from '@phosphor-icons/core/bold/check-bold.svg';
|
|
64
64
|
import minusCircleIcon from '@phosphor-icons/core/bold/minus-circle-bold.svg';
|
|
65
65
|
|
|
66
|
-
const libName="@khanacademy/perseus-editor";const libVersion="28.
|
|
66
|
+
const libName="@khanacademy/perseus-editor";const libVersion="28.7.0";addLibraryVersionToPerseusDebug(libName,libVersion);
|
|
67
67
|
|
|
68
68
|
var jsxRuntime = {exports: {}};
|
|
69
69
|
|
|
@@ -1413,9 +1413,23 @@ const devices={PHONE:"phone",TABLET:"tablet",DESKTOP:"desktop"};const lintGutter
|
|
|
1413
1413
|
|
|
1414
1414
|
const SCREEN_SIZES={phone:{width:320,height:480,framedWidth:320},tablet:{width:750,height:920,framedWidth:525},desktop:{width:688,height:600,framedWidth:688}};const DeviceFramer=({children,deviceType="phone",nochrome})=>{const scale=React.useMemo(()=>SCREEN_SIZES[deviceType].framedWidth/SCREEN_SIZES[deviceType].width,[deviceType]);const withChromeStyle=React.useMemo(()=>({backgroundColor:"white",overflow:"scroll",color:"black",textAlign:"left",width:SCREEN_SIZES[deviceType].width,height:SCREEN_SIZES[deviceType].height,border:"solid 1px #CCC",margin:8,zoom:scale}),[deviceType,scale]);if(nochrome){return jsxRuntimeExports.jsx("div",{style:{overflow:"scroll",width:SCREEN_SIZES[deviceType].framedWidth+2*perseusFrameBorderWidth+lintGutterWidth},children:jsxRuntimeExports.jsx("div",{children:children})},"screen")}return jsxRuntimeExports.jsx("div",{className:"screen",style:{...withChromeStyle,textAlign:"start"},children:children},"screen")};
|
|
1415
1415
|
|
|
1416
|
+
const IMAGE_MARKDOWN_REGEX=/!\[[^\]]*\]\([^)]+\)/g;function getFirstAvailableWidgetIndex(widgetType,widgets){const widgetNames=Object.keys(widgets);for(let i=1;i<=widgetNames.length+1;i++){if(!widgetNames.includes(`${widgetType} ${i}`)){return i}}return 1}async function convertImageMarkdownToImageWidget(question,onEditorChange){const{content,widgets}=question;const newWidgets={...widgets};const matches=Array.from(content.matchAll(IMAGE_MARKDOWN_REGEX));if(matches.length===0){return}const replacements=[];for(const match of matches){const imageIndex=getFirstAvailableWidgetIndex("image",newWidgets);const imageNode=PerseusMarkdown.parse(match[0],{});const imageUrl=imageNode[0].content[0].target;const imageAlt=imageNode[0].content[0].alt;const imageSize=await Util.getImageSizeModern(imageUrl);const[width,height]=imageSize;newWidgets[`image ${imageIndex}`]=generateImageWidget({options:generateImageOptions({backgroundImage:{url:imageUrl,width,height},alt:imageAlt})});replacements.push({original:match[0],replacement:`[[☃ image ${imageIndex}]]`});}let newContent=content;for(const{original,replacement}of replacements){newContent=newContent.replace(original,replacement);}onEditorChange({content:newContent,widgets:newWidgets});}function getCtaForIssueId(issueId,question,onEditorChange){switch(issueId){case "image-markdown":return {label:"Convert all image markdown to widget",onClick:()=>convertImageMarkdownToImageWidget(question,onEditorChange)};default:return null}}
|
|
1417
|
+
|
|
1418
|
+
const defaultItemEditorContext={question:{content:"",widgets:{},images:{}},onEditorChange:()=>{}};const ItemEditorContext=React.createContext(defaultItemEditorContext);function useItemEditorContext(){return React.useContext(ItemEditorContext)}
|
|
1419
|
+
|
|
1420
|
+
const IssueCta=({issue})=>{const{question,onEditorChange}=useItemEditorContext();const cta=getCtaForIssueId(issue.id,question,onEditorChange);if(!cta){return null}return jsxRuntimeExports.jsx(Button,{size:"small",onClick:cta.onClick,style:styles$V.button,children:cta.label},issue.id)};const styles$V={button:{marginTop:sizing.size_080,marginBottom:sizing.size_080}};
|
|
1421
|
+
|
|
1422
|
+
const PerseusEditorAccordion=props=>{const{animated,children,header,expanded,containerStyle,panelStyle,headerStyle,onToggle}=props;return jsxRuntimeExports.jsx(View,{className:"perseus-editor-accordion",children:jsxRuntimeExports.jsx(AccordionSection,{animated:animated,expanded:expanded,onToggle:onToggle,style:[styles$U.container,containerStyle],headerStyle:[styles$U.accordionHeader,headerStyle],header:header,children:jsxRuntimeExports.jsx(View,{style:[styles$U.accordionPanel,panelStyle],children:children})})})};const styles$U=StyleSheet.create({container:{backgroundColor:semanticColor.core.background.instructive.subtle,marginTop:spacing.xSmall_8},accordionHeader:{padding:spacing.small_12,paddingInlineEnd:0,height:spacing.xxLarge_48},accordionPanel:{paddingTop:spacing.xxSmall_6,paddingBottom:spacing.xxxSmall_4,paddingLeft:spacing.small_12,paddingRight:spacing.small_12}});
|
|
1423
|
+
|
|
1424
|
+
const impactStringMap={high:"Error",medium:"Warning",low:"Guideline"};const IssueDetails=({apiOptions,issue})=>{const[expanded,setExpanded]=React.useState(false);const toggleVisibility=()=>setExpanded(!expanded);const imageUpgradeFF=isFeatureOn({apiOptions},"image-widget-upgrade");return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{animated:true,expanded:expanded,onToggle:toggleVisibility,containerStyle:{backgroundColor:issue.impact==="high"?semanticColor.feedback.critical.subtle.background:semanticColor.feedback.warning.subtle.background},panelStyle:{backgroundColor:"white"},header:jsxRuntimeExports.jsx(LabelLarge,{style:{textOverflow:"ellipsis",maxWidth:"100%",overflow:"hidden",whiteSpace:"nowrap"},children:`${impactStringMap[issue.impact]}: ${issue.id}`}),children:[jsxRuntimeExports.jsx(LabelSmall,{style:{fontWeight:"bold"},children:"Description:"}),jsxRuntimeExports.jsx("span",{children:issue.description}),jsxRuntimeExports.jsx("a",{href:issue.helpUrl,target:"_blank",rel:"noreferrer",children:issue.help}),jsxRuntimeExports.jsx(LabelSmall,{style:{marginTop:"1em",fontWeight:"bold"},children:"Impact:"}),jsxRuntimeExports.jsxs("span",{style:{fontWeight:"initial"},children:[" ",issue.impact]}),jsxRuntimeExports.jsx(LabelSmall,{style:{marginTop:"1em",fontWeight:"bold"},children:"Issue:"}),jsxRuntimeExports.jsx("span",{style:{whiteSpace:"pre-line",color:semanticColor.core.foreground.critical.subtle},children:issue.message}),imageUpgradeFF&&jsxRuntimeExports.jsx(IssueCta,{issue:issue})]})};
|
|
1425
|
+
|
|
1426
|
+
function ToggleableCaret(props){const iconStyle=props.isExpanded?styles$T.expanded:styles$T.collapsed;return jsxRuntimeExports.jsx(PhosphorIcon,{icon:caretRight,style:iconStyle})}const styles$T=StyleSheet.create({collapsed:{transition:".15s"},expanded:{transform:"rotate(90deg)",transition:".15s"}});
|
|
1427
|
+
|
|
1428
|
+
const IssuesPanel=({apiOptions,issues=[]})=>{const[showPanel,setShowPanel]=useState(false);const hasWarnings=issues.length>0;const issuesCount=`${issues.length} issue${issues.length===1?"":"s"}`;const icon=hasWarnings?iconWarning:iconPass;const iconColor=hasWarnings?color.gold:color.green;return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-title",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-title-id",children:jsxRuntimeExports.jsxs(View,{style:{display:"flex",flexDirection:"row",alignItems:"center",gap:"0.25em"},onClick:()=>setShowPanel(!showPanel),children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:showPanel}),jsxRuntimeExports.jsx("span",{children:"Issues"})]})}),jsxRuntimeExports.jsx(PhosphorIcon,{icon:icon,size:"medium",color:iconColor,testId:`issues-icon-${icon}`,style:{marginRight:"0.25em"}}),issuesCount]}),showPanel&&jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-panel",children:jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-content",children:[issues.map(issue=>jsxRuntimeExports.jsx(IssueDetails,{apiOptions:apiOptions,issue:issue},issue.id)),issues.length===0&&jsxRuntimeExports.jsx("div",{children:"No issues found"})]})})]})};
|
|
1429
|
+
|
|
1416
1430
|
class JsonEditor extends React.Component{getInitialState(){return {currentValue:JSON.stringify(this.props.value,null,4),valid:true}}UNSAFE_componentWillReceiveProps(nextProps){const shouldReplaceContent=!this.state.valid||!_.isEqual(nextProps.value,JSON.parse(this.state.currentValue?this.state.currentValue:""));if(shouldReplaceContent){this.setState(this.getInitialState());}}handleKeyDown(e){if(e.key==="Tab"){const cursorPos=e.target.selectionStart;const v=e.target.value;const textBefore=v.substring(0,cursorPos);const textAfter=v.substring(cursorPos,v.length);e.target.value=textBefore+" "+textAfter;e.target.selectionStart=textBefore.length+4;e.target.selectionEnd=textBefore.length+4;e.preventDefault();this.handleChange(e);}}handleChange(e){const nextString=e.target.value;try{let json=JSON.parse(nextString);if(_.isString(json)){json=JSON.parse(json);}this.setState({currentValue:nextString,valid:true},function(){this.props.onChange(json);});}catch{this.setState({currentValue:nextString,valid:false});}}handleBlur(e){const nextString=e.target.value;try{let json=JSON.parse(nextString);if(_.isString(json)){json=JSON.parse(json);}this.setState({currentValue:JSON.stringify(json,null,4),valid:true},function(){this.props.onChange(json);});}catch{this.setState({currentValue:JSON.stringify(this.props.value,null,4),valid:true});}}render(){const classes="perseus-json-editor "+(this.state.valid?"valid":"invalid");return jsxRuntimeExports.jsx("textarea",{className:classes,value:this.state.currentValue,onChange:this.handleChange,onKeyDown:this.handleKeyDown,onBlur:this.handleBlur,disabled:this.props.editingDisabled})}constructor(props){super(props);this.state=this.getInitialState();this.handleBlur=this.handleBlur.bind(this);this.handleChange=this.handleChange.bind(this);this.handleKeyDown=this.handleKeyDown.bind(this);}}JsonEditor.defaultProps={value:{}};
|
|
1417
1431
|
|
|
1418
|
-
const SectionControlButton=({icon,onClick,title,disabled})=>{return jsxRuntimeExports.jsx(IconButton,{icon:icon,disabled:disabled,"aria-label":title,style:styles$
|
|
1432
|
+
const SectionControlButton=({icon,onClick,title,disabled})=>{return jsxRuntimeExports.jsx(IconButton,{icon:icon,disabled:disabled,"aria-label":title,style:styles$S.button,size:"xsmall",onClick:onClick})};const styles$S=StyleSheet.create({button:{marginLeft:5}});
|
|
1419
1433
|
|
|
1420
1434
|
const chemParse=function(tokens,stateMachine){let str="";let expectedLoc=tokens[tokens.length-1].loc.start;for(let i=tokens.length-1;i>=0;i--){if(tokens[i].loc.start>expectedLoc){str+=" ";expectedLoc=tokens[i].loc.start;}str+=tokens[i].text;expectedLoc+=tokens[i].text.length;}const tex=texify.go(mhchemParser.go(str,stateMachine));return tex};var mhchemParser={go:function(input,stateMachine){if(!input){return []}if(stateMachine===undefined){stateMachine="ce";}let state="0";const buffer={};buffer["parenthesisLevel"]=0;input=input.replace(/\n/g," ");input=input.replace(/[\u2212\u2013\u2014\u2010]/g,"-");input=input.replace(/[\u2026]/g,"...");let lastInput;let watchdog=10;const output=[];while(true){if(lastInput!==input){watchdog=10;lastInput=input;}else {watchdog--;}const machine=mhchemParser.stateMachines[stateMachine];const t=machine.transitions[state]||machine.transitions["*"];iterateTransitions:for(let i=0;i<t.length;i++){const matches=mhchemParser.patterns.match_(t[i].pattern,input);if(matches){const task=t[i].task;for(let iA=0;iA<task.action_.length;iA++){var o;if(machine.actions[task.action_[iA].type_]){o=machine.actions[task.action_[iA].type_](buffer,matches.match_,task.action_[iA].option);}else if(mhchemParser.actions[task.action_[iA].type_]){o=mhchemParser.actions[task.action_[iA].type_](buffer,matches.match_,task.action_[iA].option);}else {throw ["MhchemBugA","mhchem bug A. Please report. ("+task.action_[iA].type_+")"]}mhchemParser.concatArray(output,o);}state=task.nextState||state;if(input.length>0){if(!task.revisit){input=matches.remainder;}if(!task.toContinue){break iterateTransitions}}else {return output}}}if(watchdog<=0){throw ["MhchemBugU","mhchem bug U. Please report."]}}},concatArray:function(a,b){if(b){if(Array.isArray(b)){for(let iB=0;iB<b.length;iB++){a.push(b[iB]);}}else {a.push(b);}}},patterns:{patterns:{empty:/^$/,else:/^./,else2:/^./,space:/^\s/,"space A":/^\s(?=[A-Z\\$])/,space$:/^\s$/,"a-z":/^[a-z]/,x:/^x/,x$:/^x$/,i$:/^i$/,letters:/^(?:[a-zA-Z\u03B1-\u03C9\u0391-\u03A9?@]|(?:\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))))+/,"\\greek":/^\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega|Gamma|Delta|Theta|Lambda|Xi|Pi|Sigma|Upsilon|Phi|Psi|Omega)(?:\s+|\{\}|(?![a-zA-Z]))/,"one lowercase latin letter $":/^(?:([a-z])(?:$|[^a-zA-Z]))$/,"$one lowercase latin letter$ $":/^\$(?:([a-z])(?:$|[^a-zA-Z]))\$$/,"one lowercase greek letter $":/^(?:\$?[\u03B1-\u03C9]\$?|\$?\\(?:alpha|beta|gamma|delta|epsilon|zeta|eta|theta|iota|kappa|lambda|mu|nu|xi|omicron|pi|rho|sigma|tau|upsilon|phi|chi|psi|omega)\s*\$?)(?:\s+|\{\}|(?![a-zA-Z]))$/,digits:/^[0-9]+/,"-9.,9":/^[+\-]?(?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))/,"-9.,9 no missing 0":/^[+\-]?[0-9]+(?:[.,][0-9]+)?/,"(-)(9.,9)(e)(99)":function(input){const m=input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))?(\((?:[0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+))\))?(?:([eE]|\s*(\*|x|\\times|\u00D7)\s*10\^)([+\-]?[0-9]+|\{[+\-]?[0-9]+\}))?/);if(m&&m[0]){return {match_:m.splice(1),remainder:input.substr(m[0].length)}}return null},"(-)(9)^(-9)":function(input){const m=input.match(/^(\+\-|\+\/\-|\+|\-|\\pm\s?)?([0-9]+(?:[,.][0-9]+)?|[0-9]*(?:\.[0-9]+)?)\^([+\-]?[0-9]+|\{[+\-]?[0-9]+\})/);if(m&&m[0]){return {match_:m.splice(1),remainder:input.substr(m[0].length)}}return null},"state of aggregation $":function(input){const a=mhchemParser.patterns.findObserveGroups(input,"",/^\([a-z]{1,3}(?=[\),])/,")","");if(a&&a.remainder.match(/^($|[\s,;\)\]\}])/)){return a}const m=input.match(/^(?:\((?:\\ca\s?)?\$[amothc]\$\))/);if(m){return {match_:m[0],remainder:input.substr(m[0].length)}}return null},"_{(state of aggregation)}$":/^_\{(\([a-z]{1,3}\))\}/,"{[(":/^(?:\\\{|\[|\()/,")]}":/^(?:\)|\]|\\\})/,", ":/^[,;]\s*/,",":/^[,;]/,".":/^[.]/,". ":/^([.\u22C5\u00B7\u2022])\s*/,"...":/^\.\.\.(?=$|[^.])/,"* ":/^([*])\s*/,"^{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"^{","","","}")},"^($...$)":function(input){return mhchemParser.patterns.findObserveGroups(input,"^","$","$","")},"^a":/^\^([0-9]+|[^\\_])/,"^\\x{}{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"^",/^\\[a-zA-Z]+\{/,"}","","","{","}","",true)},"^\\x{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"^",/^\\[a-zA-Z]+\{/,"}","")},"^\\x":/^\^(\\[a-zA-Z]+)\s*/,"^(-1)":/^\^(-?\d+)/,"'":/^'/,"_{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"_{","","","}")},"_($...$)":function(input){return mhchemParser.patterns.findObserveGroups(input,"_","$","$","")},_9:/^_([+\-]?[0-9]+|[^\\])/,"_\\x{}{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"_",/^\\[a-zA-Z]+\{/,"}","","","{","}","",true)},"_\\x{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"_",/^\\[a-zA-Z]+\{/,"}","")},"_\\x":/^_(\\[a-zA-Z]+)\s*/,"^_":/^(?:\^(?=_)|\_(?=\^)|[\^_]$)/,"{}":/^\{\}/,"{...}":function(input){return mhchemParser.patterns.findObserveGroups(input,"","{","}","")},"{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"{","","","}")},"$...$":function(input){return mhchemParser.patterns.findObserveGroups(input,"","$","$","")},"${(...)}$":function(input){return mhchemParser.patterns.findObserveGroups(input,"${","","","}$")},"$(...)$":function(input){return mhchemParser.patterns.findObserveGroups(input,"$","","","$")},"=<>":/^[=<>]/,"#":/^[#\u2261]/,"+":/^\+/,"-$":/^-(?=[\s_},;\]/]|$|\([a-z]+\))/,"-9":/^-(?=[0-9])/,"- orbital overlap":/^-(?=(?:[spd]|sp)(?:$|[\s,;\)\]\}]))/,"-":/^-/,"pm-operator":/^(?:\\pm|\$\\pm\$|\+-|\+\/-)/,operator:/^(?:\+|(?:[\-=<>]|<<|>>|\\approx|\$\\approx\$)(?=\s|$|-?[0-9]))/,arrowUpDown:/^(?:v|\(v\)|\^|\(\^\))(?=$|[\s,;\)\]\}])/,"\\bond{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\bond{","","","}")},"->":/^(?:<->|<-->|->|<-|<=>>|<<=>|<=>|[\u2192\u27F6\u21CC])/,CMT:/^[CMT](?=\[)/,"[(...)]":function(input){return mhchemParser.patterns.findObserveGroups(input,"[","","","]")},"1st-level escape":/^(&|\\\\|\\hline)\s*/,"\\,":/^(?:\\[,\ ;:])/,"\\x{}{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"",/^\\[a-zA-Z]+\{/,"}","","","{","}","",true)},"\\x{}":function(input){return mhchemParser.patterns.findObserveGroups(input,"",/^\\[a-zA-Z]+\{/,"}","")},"\\ca":/^\\ca(?:\s+|(?![a-zA-Z]))/,"\\x":/^(?:\\[a-zA-Z]+\s*|\\[_&{}%])/,orbital:/^(?:[0-9]{1,2}[spdfgh]|[0-9]{0,2}sp)(?=$|[^a-zA-Z])/,others:/^[\/~|]/,"\\frac{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\frac{","","","}","{","","","}")},"\\overset{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\overset{","","","}","{","","","}")},"\\underset{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\underset{","","","}","{","","","}")},"\\underbrace{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\underbrace{","","","}_","{","","","}")},"\\color{(...)}0":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\color{","","","}")},"\\color{(...)}{(...)}1":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\color{","","","}","{","","","}")},"\\color(...){(...)}2":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\color","\\","",/^(?=\{)/,"{","","","}")},"\\ce{(...)}":function(input){return mhchemParser.patterns.findObserveGroups(input,"\\ce{","","","}")},oxidation$:/^(?:[+-][IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,"d-oxidation$":/^(?:[+-]?\s?[IVX]+|\\pm\s*0|\$\\pm\$\s*0)$/,"roman numeral":/^[IVX]+/,"1/2$":/^[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+(?:\$[a-z]\$|[a-z])?$/,amount:function(input){let match;match=input.match(/^(?:(?:(?:\([+\-]?[0-9]+\/[0-9]+\)|[+\-]?(?:[0-9]+|\$[a-z]\$|[a-z])\/[0-9]+|[+\-]?[0-9]+[.,][0-9]+|[+\-]?\.[0-9]+|[+\-]?[0-9]+)(?:[a-z](?=\s*[A-Z]))?)|[+\-]?[a-z](?=\s*[A-Z])|\+(?!\s))/);if(match){return {match_:match[0],remainder:input.substr(match[0].length)}}const a=mhchemParser.patterns.findObserveGroups(input,"","$","$","");if(a){match=a.match_.match(/^\$(?:\(?[+\-]?(?:[0-9]*[a-z]?[+\-])?[0-9]*[a-z](?:[+\-][0-9]*[a-z]?)?\)?|\+|-)\$$/);if(match){return {match_:match[0],remainder:input.substr(match[0].length)}}}return null},amount2:function(input){return this["amount"](input)},"(KV letters),":/^(?:[A-Z][a-z]{0,2}|i)(?=,)/,formula$:function(input){if(input.match(/^\([a-z]+\)$/)){return null}const match=input.match(/^(?:[a-z]|(?:[0-9\ \+\-\,\.\(\)]+[a-z])+[0-9\ \+\-\,\.\(\)]*|(?:[a-z][0-9\ \+\-\,\.\(\)]+)+[a-z]?)$/);if(match){return {match_:match[0],remainder:input.substr(match[0].length)}}return null},uprightEntities:/^(?:pH|pOH|pC|pK|iPr|iBu)(?=$|[^a-zA-Z])/,"/":/^\s*(\/)\s*/,"//":/^\s*(\/\/)\s*/,"*":/^\s*[*.]\s*/},findObserveGroups:function(input,begExcl,begIncl,endIncl,endExcl,beg2Excl,beg2Incl,end2Incl,end2Excl,combine){const _match=function(input,pattern){if(typeof pattern==="string"){if(input.indexOf(pattern)!==0){return null}return pattern}const match=input.match(pattern);if(!match){return null}return match[0]};const _findObserveGroups=function(input,i,endChars){let braces=0;while(i<input.length){const a=input.charAt(i);const match=_match(input.substr(i),endChars);if(match!==null&&braces===0){return {endMatchBegin:i,endMatchEnd:i+match.length}}if(a==="{"){braces++;}else if(a==="}"){if(braces===0){throw ["ExtraCloseMissingOpen","Extra close brace or missing open brace"]}else {braces--;}}i++;}if(braces>0){return null}return null};let match=_match(input,begExcl);if(match===null){return null}input=input.substr(match.length);match=_match(input,begIncl);if(match===null){return null}const e=_findObserveGroups(input,match.length,endIncl||endExcl);if(e===null){return null}const match1=input.substring(0,endIncl?e.endMatchEnd:e.endMatchBegin);if(!(beg2Excl||beg2Incl)){return {match_:match1,remainder:input.substr(e.endMatchEnd)}}const group2=this.findObserveGroups(input.substr(e.endMatchEnd),beg2Excl,beg2Incl,end2Incl,end2Excl);if(group2===null){return null}const matchRet=[match1,group2.match_];return {match_:combine?matchRet.join(""):matchRet,remainder:group2.remainder}},match_:function(m,input){const pattern=mhchemParser.patterns.patterns[m];if(pattern===undefined){throw ["MhchemBugP","mhchem bug P. Please report. ("+m+")"]}else if(typeof pattern==="function"){return mhchemParser.patterns.patterns[m](input)}else {const match=input.match(pattern);if(match){let mm;if(match[2]){mm=[match[1],match[2]];}else if(match[1]){mm=match[1];}else {mm=match[0];}return {match_:mm,remainder:input.substr(match[0].length)}}return null}}},actions:{"a=":function(buffer,m){buffer.a=(buffer.a||"")+m;},"b=":function(buffer,m){buffer.b=(buffer.b||"")+m;},"p=":function(buffer,m){buffer.p=(buffer.p||"")+m;},"o=":function(buffer,m){buffer.o=(buffer.o||"")+m;},"q=":function(buffer,m){buffer.q=(buffer.q||"")+m;},"d=":function(buffer,m){buffer.d=(buffer.d||"")+m;},"rm=":function(buffer,m){buffer.rm=(buffer.rm||"")+m;},"text=":function(buffer,m){buffer.text_=(buffer.text_||"")+m;},insert:function(buffer,m,a){return {type_:a}},"insert+p1":function(buffer,m,a){return {type_:a,p1:m}},"insert+p1+p2":function(buffer,m,a){return {type_:a,p1:m[0],p2:m[1]}},copy:function(buffer,m){return m},rm:function(buffer,m){return {type_:"rm",p1:m||""}},text:function(buffer,m){return mhchemParser.go(m,"text")},"{text}":function(buffer,m){const ret=["{"];mhchemParser.concatArray(ret,mhchemParser.go(m,"text"));ret.push("}");return ret},"tex-math":function(buffer,m){return mhchemParser.go(m,"tex-math")},"tex-math tight":function(buffer,m){return mhchemParser.go(m,"tex-math tight")},bond:function(buffer,m,k){return {type_:"bond",kind_:k||m}},"color0-output":function(buffer,m){return {type_:"color0",color:m[0]}},ce:function(buffer,m){return mhchemParser.go(m)},"1/2":function(buffer,m){const ret=[];if(m.match(/^[+\-]/)){ret.push(m.substr(0,1));m=m.substr(1);}const n=m.match(/^([0-9]+|\$[a-z]\$|[a-z])\/([0-9]+)(\$[a-z]\$|[a-z])?$/);n[1]=n[1].replace(/\$/g,"");ret.push({type_:"frac",p1:n[1],p2:n[2]});if(n[3]){n[3]=n[3].replace(/\$/g,"");ret.push({type_:"tex-math",p1:n[3]});}return ret},"9,9":function(buffer,m){return mhchemParser.go(m,"9,9")}},createTransitions:function(o){let pattern;let state;let stateArray;let i;const transitions={};for(pattern in o){for(state in o[pattern]){stateArray=state.split("|");o[pattern][state].stateArray=stateArray;for(i=0;i<stateArray.length;i++){transitions[stateArray[i]]=[];}}}for(pattern in o){for(state in o[pattern]){stateArray=o[pattern][state].stateArray||[];for(i=0;i<stateArray.length;i++){const p=o[pattern][state];if(p.action_){p.action_=[].concat(p.action_);for(let k=0;k<p.action_.length;k++){if(typeof p.action_[k]==="string"){p.action_[k]={type_:p.action_[k]};}}}else {p.action_=[];}const patternArray=pattern.split("|");for(let j=0;j<patternArray.length;j++){if(stateArray[i]==="*"){for(const t in transitions){transitions[t].push({pattern:patternArray[j],task:p});}}else {transitions[stateArray[i]].push({pattern:patternArray[j],task:p});}}}}}return transitions},stateMachines:{}};mhchemParser.stateMachines={ce:{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},else:{"0|1|2":{action_:"beginsWithBond=false",revisit:true,toContinue:true}},oxidation$:{0:{action_:"oxidation-output"}},CMT:{r:{action_:"rdt=",nextState:"rt"},rd:{action_:"rqt=",nextState:"rdt"}},arrowUpDown:{"0|1|2|as":{action_:["sb=false","output","operator"],nextState:"1"}},uprightEntities:{"0|1|2":{action_:["o=","output"],nextState:"1"}},orbital:{"0|1|2|3":{action_:"o=",nextState:"o"}},"->":{"0|1|2|3":{action_:"r=",nextState:"r"},"a|as":{action_:["output","r="],nextState:"r"},"*":{action_:["output","r="],nextState:"r"}},"+":{o:{action_:"d= kv",nextState:"d"},"d|D":{action_:"d=",nextState:"d"},q:{action_:"d=",nextState:"qd"},"qd|qD":{action_:"d=",nextState:"qd"},dq:{action_:["output","d="],nextState:"d"},3:{action_:["sb=false","output","operator"],nextState:"0"}},amount:{"0|2":{action_:"a=",nextState:"a"}},"pm-operator":{"0|1|2|a|as":{action_:["sb=false","output",{type_:"operator",option:"\\pm"}],nextState:"0"}},operator:{"0|1|2|a|as":{action_:["sb=false","output","operator"],nextState:"0"}},"-$":{"o|q":{action_:["charge or bond","output"],nextState:"qd"},d:{action_:"d=",nextState:"d"},D:{action_:["output",{type_:"bond",option:"-"}],nextState:"3"},q:{action_:"d=",nextState:"qd"},qd:{action_:"d=",nextState:"qd"},"qD|dq":{action_:["output",{type_:"bond",option:"-"}],nextState:"3"}},"-9":{"3|o":{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"3"}},"- orbital overlap":{o:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"},d:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"}},"-":{"0|1|2":{action_:[{type_:"output",option:1},"beginsWithBond=true",{type_:"bond",option:"-"}],nextState:"3"},3:{action_:{type_:"bond",option:"-"}},a:{action_:["output",{type_:"insert",option:"hyphen"}],nextState:"2"},as:{action_:[{type_:"output",option:2},{type_:"bond",option:"-"}],nextState:"3"},b:{action_:"b="},o:{action_:{type_:"- after o/d",option:false},nextState:"2"},q:{action_:{type_:"- after o/d",option:false},nextState:"2"},"d|qd|dq":{action_:{type_:"- after o/d",option:true},nextState:"2"},"D|qD|p":{action_:["output",{type_:"bond",option:"-"}],nextState:"3"}},amount2:{"1|3":{action_:"a=",nextState:"a"}},letters:{"0|1|2|3|a|as|b|p|bp|o":{action_:"o=",nextState:"o"},"q|dq":{action_:["output","o="],nextState:"o"},"d|D|qd|qD":{action_:"o after d",nextState:"o"}},digits:{o:{action_:"q=",nextState:"q"},"d|D":{action_:"q=",nextState:"dq"},q:{action_:["output","o="],nextState:"o"},a:{action_:"o=",nextState:"o"}},"space A":{"b|p|bp":{}},space:{a:{nextState:"as"},0:{action_:"sb=false"},"1|2":{action_:"sb=true"},"r|rt|rd|rdt|rdq":{action_:"output",nextState:"0"},"*":{action_:["output","sb=true"],nextState:"1"}},"1st-level escape":{"1|2":{action_:["output",{type_:"insert+p1",option:"1st-level escape"}]},"*":{action_:["output",{type_:"insert+p1",option:"1st-level escape"}],nextState:"0"}},"[(...)]":{"r|rt":{action_:"rd=",nextState:"rd"},"rd|rdt":{action_:"rq=",nextState:"rdq"}},"...":{"o|d|D|dq|qd|qD":{action_:["output",{type_:"bond",option:"..."}],nextState:"3"},"*":{action_:[{type_:"output",option:1},{type_:"insert",option:"ellipsis"}],nextState:"1"}},". |* ":{"*":{action_:["output",{type_:"insert",option:"addition compound"}],nextState:"1"}},"state of aggregation $":{"*":{action_:["output","state of aggregation"],nextState:"1"}},"{[(":{"a|as|o":{action_:["o=","output","parenthesisLevel++"],nextState:"2"},"0|1|2|3":{action_:["o=","output","parenthesisLevel++"],nextState:"2"},"*":{action_:["output","o=","output","parenthesisLevel++"],nextState:"2"}},")]}":{"0|1|2|3|b|p|bp|o":{action_:["o=","parenthesisLevel--"],nextState:"o"},"a|as|d|D|q|qd|qD|dq":{action_:["output","o=","parenthesisLevel--"],nextState:"o"}},", ":{"*":{action_:["output","comma"],nextState:"0"}},"^_":{"*":{}},"^{(...)}|^($...$)":{"0|1|2|as":{action_:"b=",nextState:"b"},p:{action_:"b=",nextState:"bp"},"3|o":{action_:"d= kv",nextState:"D"},q:{action_:"d=",nextState:"qD"},"d|D|qd|qD|dq":{action_:["output","d="],nextState:"D"}},"^a|^\\x{}{}|^\\x{}|^\\x|'":{"0|1|2|as":{action_:"b=",nextState:"b"},p:{action_:"b=",nextState:"bp"},"3|o":{action_:"d= kv",nextState:"d"},q:{action_:"d=",nextState:"qd"},"d|qd|D|qD":{action_:"d="},dq:{action_:["output","d="],nextState:"d"}},"_{(state of aggregation)}$":{"d|D|q|qd|qD|dq":{action_:["output","q="],nextState:"q"}},"_{(...)}|_($...$)|_9|_\\x{}{}|_\\x{}|_\\x":{"0|1|2|as":{action_:"p=",nextState:"p"},b:{action_:"p=",nextState:"bp"},"3|o":{action_:"q=",nextState:"q"},"d|D":{action_:"q=",nextState:"dq"},"q|qd|qD|dq":{action_:["output","q="],nextState:"q"}},"=<>":{"0|1|2|3|a|as|o|q|d|D|qd|qD|dq":{action_:[{type_:"output",option:2},"bond"],nextState:"3"}},"#":{"0|1|2|3|a|as|o":{action_:[{type_:"output",option:2},{type_:"bond",option:"#"}],nextState:"3"}},"{}":{"*":{action_:{type_:"output",option:1},nextState:"1"}},"{...}":{"0|1|2|3|a|as|b|p|bp":{action_:"o=",nextState:"o"},"o|d|D|q|qd|qD|dq":{action_:["output","o="],nextState:"o"}},"$...$":{a:{action_:"a="},"0|1|2|3|as|b|p|bp|o":{action_:"o=",nextState:"o"},"as|o":{action_:"o="},"q|d|D|qd|qD|dq":{action_:["output","o="],nextState:"o"}},"\\bond{(...)}":{"*":{action_:[{type_:"output",option:2},"bond"],nextState:"3"}},"\\frac{(...)}":{"*":{action_:[{type_:"output",option:1},"frac-output"],nextState:"3"}},"\\overset{(...)}":{"*":{action_:[{type_:"output",option:2},"overset-output"],nextState:"3"}},"\\underset{(...)}":{"*":{action_:[{type_:"output",option:2},"underset-output"],nextState:"3"}},"\\underbrace{(...)}":{"*":{action_:[{type_:"output",option:2},"underbrace-output"],nextState:"3"}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:[{type_:"output",option:2},"color-output"],nextState:"3"}},"\\color{(...)}0":{"*":{action_:[{type_:"output",option:2},"color0-output"]}},"\\ce{(...)}":{"*":{action_:[{type_:"output",option:2},"ce"],nextState:"3"}},"\\,":{"*":{action_:[{type_:"output",option:1},"copy"],nextState:"1"}},"\\x{}{}|\\x{}|\\x":{"0|1|2|3|a|as|b|p|bp|o|c0":{action_:["o=","output"],nextState:"3"},"*":{action_:["output","o=","output"],nextState:"3"}},others:{"*":{action_:[{type_:"output",option:1},"copy"],nextState:"3"}},else2:{a:{action_:"a to o",nextState:"o",revisit:true},as:{action_:["output","sb=true"],nextState:"1",revisit:true},"r|rt|rd|rdt|rdq":{action_:["output"],nextState:"0",revisit:true},"*":{action_:["output","copy"],nextState:"3"}}}),actions:{"o after d":function(buffer,m){let ret;if((buffer.d||"").match(/^[0-9]+$/)){const tmp=buffer.d;buffer.d=undefined;ret=this["output"](buffer);buffer.b=tmp;}else {ret=this["output"](buffer);}mhchemParser.actions["o="](buffer,m);return ret},"d= kv":function(buffer,m){buffer.d=m;buffer.dType="kv";},"charge or bond":function(buffer,m){if(buffer["beginsWithBond"]){const ret=[];mhchemParser.concatArray(ret,this["output"](buffer));mhchemParser.concatArray(ret,mhchemParser.actions["bond"](buffer,m,"-"));return ret}buffer.d=m;},"- after o/d":function(buffer,m,isAfterD){let c1=mhchemParser.patterns.match_("orbital",buffer.o||"");const c2=mhchemParser.patterns.match_("one lowercase greek letter $",buffer.o||"");const c3=mhchemParser.patterns.match_("one lowercase latin letter $",buffer.o||"");const c4=mhchemParser.patterns.match_("$one lowercase latin letter$ $",buffer.o||"");const hyphenFollows=m==="-"&&(c1&&c1.remainder===""||c2||c3||c4);if(hyphenFollows&&!buffer.a&&!buffer.b&&!buffer.p&&!buffer.d&&!buffer.q&&!c1&&c3){buffer.o="$"+buffer.o+"$";}const ret=[];if(hyphenFollows){mhchemParser.concatArray(ret,this["output"](buffer));ret.push({type_:"hyphen"});}else {c1=mhchemParser.patterns.match_("digits",buffer.d||"");if(isAfterD&&c1&&c1.remainder===""){mhchemParser.concatArray(ret,mhchemParser.actions["d="](buffer,m));mhchemParser.concatArray(ret,this["output"](buffer));}else {mhchemParser.concatArray(ret,this["output"](buffer));mhchemParser.concatArray(ret,mhchemParser.actions["bond"](buffer,m,"-"));}}return ret},"a to o":function(buffer){buffer.o=buffer.a;buffer.a=undefined;},"sb=true":function(buffer){buffer.sb=true;},"sb=false":function(buffer){buffer.sb=false;},"beginsWithBond=true":function(buffer){buffer["beginsWithBond"]=true;},"beginsWithBond=false":function(buffer){buffer["beginsWithBond"]=false;},"parenthesisLevel++":function(buffer){buffer["parenthesisLevel"]++;},"parenthesisLevel--":function(buffer){buffer["parenthesisLevel"]--;},"state of aggregation":function(buffer,m){return {type_:"state of aggregation",p1:mhchemParser.go(m,"o")}},comma:function(buffer,m){const a=m.replace(/\s*$/,"");const withSpace=a!==m;if(withSpace&&buffer["parenthesisLevel"]===0){return {type_:"comma enumeration L",p1:a}}return {type_:"comma enumeration M",p1:a}},output:function(buffer,m,entityFollows){let ret;if(!buffer.r){ret=[];if(!buffer.a&&!buffer.b&&!buffer.p&&!buffer.o&&!buffer.q&&!buffer.d&&!entityFollows);else {if(buffer.sb){ret.push({type_:"entitySkip"});}if(!buffer.o&&!buffer.q&&!buffer.d&&!buffer.b&&!buffer.p&&entityFollows!==2){buffer.o=buffer.a;buffer.a=undefined;}else if(!buffer.o&&!buffer.q&&!buffer.d&&(buffer.b||buffer.p)){buffer.o=buffer.a;buffer.d=buffer.b;buffer.q=buffer.p;buffer.a=buffer.b=buffer.p=undefined;}else {if(buffer.o&&buffer.dType==="kv"&&mhchemParser.patterns.match_("d-oxidation$",buffer.d||"")){buffer.dType="oxidation";}else if(buffer.o&&buffer.dType==="kv"&&!buffer.q){buffer.dType=undefined;}}ret.push({type_:"chemfive",a:mhchemParser.go(buffer.a,"a"),b:mhchemParser.go(buffer.b,"bd"),p:mhchemParser.go(buffer.p,"pq"),o:mhchemParser.go(buffer.o,"o"),q:mhchemParser.go(buffer.q,"pq"),d:mhchemParser.go(buffer.d,buffer.dType==="oxidation"?"oxidation":"bd"),dType:buffer.dType});}}else {let rd;if(buffer.rdt==="M"){rd=mhchemParser.go(buffer.rd,"tex-math");}else if(buffer.rdt==="T"){rd=[{type_:"text",p1:buffer.rd||""}];}else {rd=mhchemParser.go(buffer.rd);}let rq;if(buffer.rqt==="M"){rq=mhchemParser.go(buffer.rq,"tex-math");}else if(buffer.rqt==="T"){rq=[{type_:"text",p1:buffer.rq||""}];}else {rq=mhchemParser.go(buffer.rq);}ret={type_:"arrow",r:buffer.r,rd:rd,rq:rq};}for(const p in buffer){if(p!=="parenthesisLevel"&&p!=="beginsWithBond"){delete buffer[p];}}return ret},"oxidation-output":function(buffer,m){const ret=["{"];mhchemParser.concatArray(ret,mhchemParser.go(m,"oxidation"));ret.push("}");return ret},"frac-output":function(buffer,m){return {type_:"frac-ce",p1:mhchemParser.go(m[0]),p2:mhchemParser.go(m[1])}},"overset-output":function(buffer,m){return {type_:"overset",p1:mhchemParser.go(m[0]),p2:mhchemParser.go(m[1])}},"underset-output":function(buffer,m){return {type_:"underset",p1:mhchemParser.go(m[0]),p2:mhchemParser.go(m[1])}},"underbrace-output":function(buffer,m){return {type_:"underbrace",p1:mhchemParser.go(m[0]),p2:mhchemParser.go(m[1])}},"color-output":function(buffer,m){return {type_:"color",color1:m[0],color2:mhchemParser.go(m[1])}},"r=":function(buffer,m){buffer.r=m;},"rdt=":function(buffer,m){buffer.rdt=m;},"rd=":function(buffer,m){buffer.rd=m;},"rqt=":function(buffer,m){buffer.rqt=m;},"rq=":function(buffer,m){buffer.rq=m;},operator:function(buffer,m,p1){return {type_:"operator",kind_:p1||m}}}},a:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"1",revisit:true}},"$(...)$":{"*":{action_:"tex-math tight",nextState:"1"}},",":{"*":{action_:{type_:"insert",option:"commaDecimal"}}},else2:{"*":{action_:"copy"}}}),actions:{}},o:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"1",revisit:true}},letters:{"*":{action_:"rm"}},"\\ca":{"*":{action_:{type_:"insert",option:"circa"}}},"\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"{text}"}},else2:{"*":{action_:"copy"}}}),actions:{}},text:{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"{...}":{"*":{action_:"text="}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"\\greek":{"*":{action_:["output","rm"]}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:["output","copy"]}},else:{"*":{action_:"text="}}}),actions:{output:function(buffer){if(buffer.text_){const ret={type_:"text",p1:buffer.text_};for(const p in buffer){delete buffer[p];}return ret}}}},pq:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"state of aggregation $":{"*":{action_:"state of aggregation"}},i$:{0:{nextState:"!f",revisit:true}},"(KV letters),":{0:{action_:"rm",nextState:"0"}},formula$:{0:{nextState:"f",revisit:true}},"1/2$":{0:{action_:"1/2"}},else:{0:{nextState:"!f",revisit:true}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"text"}},"a-z":{f:{action_:"tex-math"}},letters:{"*":{action_:"rm"}},"-9.,9":{"*":{action_:"9,9"}},",":{"*":{action_:{type_:"insert+p1",option:"comma enumeration S"}}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:"color-output"}},"\\color{(...)}0":{"*":{action_:"color0-output"}},"\\ce{(...)}":{"*":{action_:"ce"}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},else2:{"*":{action_:"copy"}}}),actions:{"state of aggregation":function(buffer,m){return {type_:"state of aggregation subscript",p1:mhchemParser.go(m,"o")}},"color-output":function(buffer,m){return {type_:"color",color1:m[0],color2:mhchemParser.go(m[1],"pq")}}}},bd:{transitions:mhchemParser.createTransitions({empty:{"*":{}},x$:{0:{nextState:"!f",revisit:true}},formula$:{0:{nextState:"f",revisit:true}},else:{0:{nextState:"!f",revisit:true}},"-9.,9 no missing 0":{"*":{action_:"9,9"}},".":{"*":{action_:{type_:"insert",option:"electron dot"}}},"a-z":{f:{action_:"tex-math"}},x:{"*":{action_:{type_:"insert",option:"KV x"}}},letters:{"*":{action_:"rm"}},"'":{"*":{action_:{type_:"insert",option:"prime"}}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},"{(...)}":{"*":{action_:"text"}},"\\color{(...)}{(...)}1|\\color(...){(...)}2":{"*":{action_:"color-output"}},"\\color{(...)}0":{"*":{action_:"color0-output"}},"\\ce{(...)}":{"*":{action_:"ce"}},"\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"copy"}},else2:{"*":{action_:"copy"}}}),actions:{"color-output":function(buffer,m){return {type_:"color",color1:m[0],color2:mhchemParser.go(m[1],"bd")}}}},oxidation:{transitions:mhchemParser.createTransitions({empty:{"*":{}},"roman numeral":{"*":{action_:"roman-numeral"}},"${(...)}$|$(...)$":{"*":{action_:"tex-math"}},else:{"*":{action_:"copy"}}}),actions:{"roman-numeral":function(buffer,m){return {type_:"roman numeral",p1:m||""}}}},"tex-math":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"\\ce{(...)}":{"*":{action_:["output","ce"]}},"{...}|\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"o="}},else:{"*":{action_:"o="}}}),actions:{output:function(buffer){if(buffer.o){const ret={type_:"tex-math",p1:buffer.o};for(const p in buffer){delete buffer[p];}return ret}}}},"tex-math tight":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"\\ce{(...)}":{"*":{action_:["output","ce"]}},"{...}|\\,|\\x{}{}|\\x{}|\\x":{"*":{action_:"o="}},"-|+":{"*":{action_:"tight operator"}},else:{"*":{action_:"o="}}}),actions:{"tight operator":function(buffer,m){buffer.o=(buffer.o||"")+"{"+m+"}";},output:function(buffer){if(buffer.o){const ret={type_:"tex-math",p1:buffer.o};for(const p in buffer){delete buffer[p];}return ret}}}},"9,9":{transitions:mhchemParser.createTransitions({empty:{"*":{}},",":{"*":{action_:"comma"}},else:{"*":{action_:"copy"}}}),actions:{comma:function(){return {type_:"commaDecimal"}}}},pu:{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},space$:{"*":{action_:["output","space"]}},"{[(|)]}":{"0|a":{action_:"copy"}},"(-)(9)^(-9)":{0:{action_:"number^",nextState:"a"}},"(-)(9.,9)(e)(99)":{0:{action_:"enumber",nextState:"a"}},space:{"0|a":{}},"pm-operator":{"0|a":{action_:{type_:"operator",option:"\\pm"},nextState:"0"}},operator:{"0|a":{action_:"copy",nextState:"0"}},"//":{d:{action_:"o=",nextState:"/"}},"/":{d:{action_:"o=",nextState:"/"}},"{...}|else":{"0|d":{action_:"d=",nextState:"d"},a:{action_:["space","d="],nextState:"d"},"/|q":{action_:"q=",nextState:"q"}}}),actions:{enumber:function(buffer,m){const ret=[];if(m[0]==="+-"||m[0]==="+/-"){ret.push("\\pm ");}else if(m[0]){ret.push(m[0]);}if(m[1]){mhchemParser.concatArray(ret,mhchemParser.go(m[1],"pu-9,9"));if(m[2]){if(m[2].match(/[,.]/)){mhchemParser.concatArray(ret,mhchemParser.go(m[2],"pu-9,9"));}else {ret.push(m[2]);}}m[3]=m[4]||m[3];if(m[3]){m[3]=m[3].trim();if(m[3]==="e"||m[3].substr(0,1)==="*"){ret.push({type_:"cdot"});}else {ret.push({type_:"times"});}}}if(m[3]){ret.push("10^{"+m[5]+"}");}return ret},"number^":function(buffer,m){const ret=[];if(m[0]==="+-"||m[0]==="+/-"){ret.push("\\pm ");}else if(m[0]){ret.push(m[0]);}mhchemParser.concatArray(ret,mhchemParser.go(m[1],"pu-9,9"));ret.push("^{"+m[2]+"}");return ret},operator:function(buffer,m,p1){return {type_:"operator",kind_:p1||m}},space:function(){return {type_:"pu-space-1"}},output:function(buffer){let ret;const md=mhchemParser.patterns.match_("{(...)}",buffer.d||"");if(md&&md.remainder===""){buffer.d=md.match_;}const mq=mhchemParser.patterns.match_("{(...)}",buffer.q||"");if(mq&&mq.remainder===""){buffer.q=mq.match_;}if(buffer.d){buffer.d=buffer.d.replace(/\u00B0C|\^oC|\^{o}C/g,"{}^{\\circ}C");buffer.d=buffer.d.replace(/\u00B0F|\^oF|\^{o}F/g,"{}^{\\circ}F");}if(buffer.q){buffer.q=buffer.q.replace(/\u00B0C|\^oC|\^{o}C/g,"{}^{\\circ}C");buffer.q=buffer.q.replace(/\u00B0F|\^oF|\^{o}F/g,"{}^{\\circ}F");const b5={d:mhchemParser.go(buffer.d,"pu"),q:mhchemParser.go(buffer.q,"pu")};if(buffer.o==="//"){ret={type_:"pu-frac",p1:b5.d,p2:b5.q};}else {ret=b5.d;if(b5.d.length>1||b5.q.length>1){ret.push({type_:" / "});}else {ret.push({type_:"/"});}mhchemParser.concatArray(ret,b5.q);}}else {ret=mhchemParser.go(buffer.d,"pu-2");}for(const p in buffer){delete buffer[p];}return ret}}},"pu-2":{transitions:mhchemParser.createTransitions({empty:{"*":{action_:"output"}},"*":{"*":{action_:["output","cdot"],nextState:"0"}},"\\x":{"*":{action_:"rm="}},space:{"*":{action_:["output","space"],nextState:"0"}},"^{(...)}|^(-1)":{1:{action_:"^(-1)"}},"-9.,9":{0:{action_:"rm=",nextState:"0"},1:{action_:"^(-1)",nextState:"0"}},"{...}|else":{"*":{action_:"rm=",nextState:"1"}}}),actions:{cdot:function(){return {type_:"tight cdot"}},"^(-1)":function(buffer,m){buffer.rm+="^{"+m+"}";},space:function(){return {type_:"pu-space-2"}},output:function(buffer){let ret=[];if(buffer.rm){const mrm=mhchemParser.patterns.match_("{(...)}",buffer.rm||"");if(mrm&&mrm.remainder===""){ret=mhchemParser.go(mrm.match_,"pu");}else {ret={type_:"rm",p1:buffer.rm};}}for(const p in buffer){delete buffer[p];}return ret}}},"pu-9,9":{transitions:mhchemParser.createTransitions({empty:{0:{action_:"output-0"},o:{action_:"output-o"}},",":{0:{action_:["output-0","comma"],nextState:"o"}},".":{0:{action_:["output-0","copy"],nextState:"o"}},else:{"*":{action_:"text="}}}),actions:{comma:function(){return {type_:"commaDecimal"}},"output-0":function(buffer){const ret=[];buffer.text_=buffer.text_||"";if(buffer.text_.length>4){let a=buffer.text_.length%3;if(a===0){a=3;}for(let i=buffer.text_.length-3;i>0;i-=3){ret.push(buffer.text_.substr(i,3));ret.push({type_:"1000 separator"});}ret.push(buffer.text_.substr(0,a));ret.reverse();}else {ret.push(buffer.text_);}for(const p in buffer){delete buffer[p];}return ret},"output-o":function(buffer){const ret=[];buffer.text_=buffer.text_||"";if(buffer.text_.length>4){const a=buffer.text_.length-3;for(var i=0;i<a;i+=3){ret.push(buffer.text_.substr(i,3));ret.push({type_:"1000 separator"});}ret.push(buffer.text_.substr(i));}else {ret.push(buffer.text_);}for(const p in buffer){delete buffer[p];}return ret}}}};var texify={go:function(input,isInner){if(!input){return ""}let res="";let cee=false;for(let i=0;i<input.length;i++){const inputi=input[i];if(typeof inputi==="string"){res+=inputi;}else {res+=texify._go2(inputi);if(inputi.type_==="1st-level escape"){cee=true;}}}if(!isInner&&!cee&&res){res="{"+res+"}";}return res},_goInner:function(input){if(!input){return input}return texify.go(input,true)},_go2:function(buf){let res;switch(buf.type_){case "chemfive":res="";var b5={a:texify._goInner(buf.a),b:texify._goInner(buf.b),p:texify._goInner(buf.p),o:texify._goInner(buf.o),q:texify._goInner(buf.q),d:texify._goInner(buf.d)};if(b5.a){if(b5.a.match(/^[+\-]/)){b5.a="{"+b5.a+"}";}res+=b5.a+"\\,";}if(b5.b||b5.p){res+="{\\vphantom{X}}";res+="^{\\hphantom{"+(b5.b||"")+"}}_{\\hphantom{"+(b5.p||"")+"}}";res+="{\\vphantom{X}}";res+="^{\\smash[t]{\\vphantom{2}}\\mathllap{"+(b5.b||"")+"}}";res+="_{\\vphantom{2}\\mathllap{\\smash[t]{"+(b5.p||"")+"}}}";}if(b5.o){if(b5.o.match(/^[+\-]/)){b5.o="{"+b5.o+"}";}res+=b5.o;}if(buf.dType==="kv"){if(b5.d||b5.q){res+="{\\vphantom{X}}";}if(b5.d){res+="^{"+b5.d+"}";}if(b5.q){res+="_{\\smash[t]{"+b5.q+"}}";}}else if(buf.dType==="oxidation"){if(b5.d){res+="{\\vphantom{X}}";res+="^{"+b5.d+"}";}if(b5.q){res+="{\\vphantom{X}}";res+="_{\\smash[t]{"+b5.q+"}}";}}else {if(b5.q){res+="{\\vphantom{X}}";res+="_{\\smash[t]{"+b5.q+"}}";}if(b5.d){res+="{\\vphantom{X}}";res+="^{"+b5.d+"}";}}break;case "rm":res="\\mathrm{"+buf.p1+"}";break;case "text":if(buf.p1.match(/[\^_]/)){buf.p1=buf.p1.replace(" ","~").replace("-","\\text{-}");res="\\mathrm{"+buf.p1+"}";}else {res="\\text{"+buf.p1+"}";}break;case "roman numeral":res="\\mathrm{"+buf.p1+"}";break;case "state of aggregation":res="\\mskip2mu "+texify._goInner(buf.p1);break;case "state of aggregation subscript":res="\\mskip1mu "+texify._goInner(buf.p1);break;case "bond":res=texify._getBond(buf.kind_);if(!res){throw ["MhchemErrorBond","mhchem Error. Unknown bond type ("+buf.kind_+")"]}break;case "frac":var c="\\frac{"+buf.p1+"}{"+buf.p2+"}";res="\\mathchoice{\\textstyle"+c+"}{"+c+"}{"+c+"}{"+c+"}";break;case "pu-frac":var d="\\frac{"+texify._goInner(buf.p1)+"}{"+texify._goInner(buf.p2)+"}";res="\\mathchoice{\\textstyle"+d+"}{"+d+"}{"+d+"}{"+d+"}";break;case "tex-math":res=buf.p1+" ";break;case "frac-ce":res="\\frac{"+texify._goInner(buf.p1)+"}{"+texify._goInner(buf.p2)+"}";break;case "overset":res="\\overset{"+texify._goInner(buf.p1)+"}{"+texify._goInner(buf.p2)+"}";break;case "underset":res="\\underset{"+texify._goInner(buf.p1)+"}{"+texify._goInner(buf.p2)+"}";break;case "underbrace":res="\\underbrace{"+texify._goInner(buf.p1)+"}_{"+texify._goInner(buf.p2)+"}";break;case "color":res="{\\color{"+buf.color1+"}{"+texify._goInner(buf.color2)+"}}";break;case "color0":res="\\color{"+buf.color+"}";break;case "arrow":var b6={rd:texify._goInner(buf.rd),rq:texify._goInner(buf.rq)};var arrow="\\x"+texify._getArrow(buf.r);if(b6.rq){arrow+="[{"+b6.rq+"}]";}if(b6.rd){arrow+="{"+b6.rd+"}";}else {arrow+="{}";}res=arrow;break;case "operator":res=texify._getOperator(buf.kind_);break;case "1st-level escape":res=buf.p1+" ";break;case "space":res=" ";break;case "entitySkip":res="~";break;case "pu-space-1":res="~";break;case "pu-space-2":res="\\mkern3mu ";break;case "1000 separator":res="\\mkern2mu ";break;case "commaDecimal":res="{,}";break;case "comma enumeration L":res="{"+buf.p1+"}\\mkern6mu ";break;case "comma enumeration M":res="{"+buf.p1+"}\\mkern3mu ";break;case "comma enumeration S":res="{"+buf.p1+"}\\mkern1mu ";break;case "hyphen":res="\\text{-}";break;case "addition compound":res="\\,{\\cdot}\\,";break;case "electron dot":res="\\mkern1mu \\bullet\\mkern1mu ";break;case "KV x":res="{\\times}";break;case "prime":res="\\prime ";break;case "cdot":res="\\cdot ";break;case "tight cdot":res="\\mkern1mu{\\cdot}\\mkern1mu ";break;case "times":res="\\times ";break;case "circa":res="{\\sim}";break;case "^":res="uparrow";break;case "v":res="downarrow";break;case "ellipsis":res="\\ldots ";break;case "/":res="/";break;case " / ":res="\\,/\\,";break;default:throw ["MhchemBugT","mhchem bug T. Please report."]}return res},_getArrow:function(a){switch(a){case "->":return "rightarrow";case "→":return "rightarrow";case "⟶":return "rightarrow";case "<-":return "leftarrow";case "<->":return "leftrightarrow";case "<-->":return "rightleftarrows";case "<=>":return "rightleftharpoons";case "⇌":return "rightleftharpoons";case "<=>>":return "rightequilibrium";case "<<=>":return "leftequilibrium";default:throw ["MhchemBugT","mhchem bug T. Please report."]}},_getBond:function(a){switch(a){case "-":return "{-}";case "1":return "{-}";case "=":return "{=}";case "2":return "{=}";case "#":return "{\\equiv}";case "3":return "{\\equiv}";case "~":return "{\\tripledash}";case "~-":return "{\\mathrlap{\\raisebox{-.1em}{$-$}}\\raisebox{.1em}{$\\tripledash$}}";case "~=":return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";case "~--":return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$\\tripledash$}}-}";case "-~-":return "{\\mathrlap{\\raisebox{-.2em}{$-$}}\\mathrlap{\\raisebox{.2em}{$-$}}\\tripledash}";case "...":return "{{\\cdot}{\\cdot}{\\cdot}}";case "....":return "{{\\cdot}{\\cdot}{\\cdot}{\\cdot}}";case "->":return "{\\rightarrow}";case "<-":return "{\\leftarrow}";case "<":return "{<}";case ">":return "{>}";default:throw ["MhchemBugT","mhchem bug T. Please report."]}},_getOperator:function(a){switch(a){case "+":return " {}+{} ";case "-":return " {}-{} ";case "=":return " {}={} ";case "<":return " {}<{} ";case ">":return " {}>{} ";case "<<":return " {}\\ll{} ";case ">>":return " {}\\gg{} ";case "\\pm":return " {}\\pm{} ";case "\\approx":return " {}\\approx{} ";case "$\\approx$":return " {}\\approx{} ";case "v":return " \\downarrow{} ";case "(v)":return " \\downarrow{} ";case "^":return " \\uparrow{} ";case "(^)":return " \\uparrow{} ";default:throw ["MhchemBugT","mhchem bug T. Please report."]}}};
|
|
1421
1435
|
|
|
@@ -1423,19 +1437,19 @@ katex.__defineMacro("\\ce",function(context){return chemParse(context.consumeArg
|
|
|
1423
1437
|
|
|
1424
1438
|
class DragTarget extends React.Component{handleDrop(e){e.stopPropagation();e.preventDefault();this.setState({dragHover:false});this.props.onDrop(e);}handleDragEnd(){this.setState({dragHover:false});}handleDragOver(e){e.preventDefault();}handleDragLeave(){this.setState({dragHover:false});}handleDragEnter(e){this.setState({dragHover:this.props.shouldDragHighlight(e)});}render(){const opacity=this.state.dragHover?{opacity:.3}:{};const{component:Component,shouldDragHighlight,...forwardProps}=this.props;return jsxRuntimeExports.jsx(Component,{...forwardProps,style:Object.assign({},this.props.style,opacity),onDrop:this.handleDrop,onDragEnd:this.handleDragEnd,onDragOver:this.handleDragOver,onDragEnter:this.handleDragEnter,onDragLeave:this.handleDragLeave})}constructor(props){super(props);this.state={dragHover:false};this.handleDrop=this.handleDrop.bind(this);this.handleDragEnd=this.handleDragEnd.bind(this);this.handleDragOver=this.handleDragOver.bind(this);this.handleDragLeave=this.handleDragLeave.bind(this);this.handleDragEnter=this.handleDragEnter.bind(this);}}DragTarget.defaultProps={component:"div",shouldDragHighlight:()=>true};
|
|
1425
1439
|
|
|
1426
|
-
function ToggleableCaret(props){const iconStyle=props.isExpanded?styles$U.expanded:styles$U.collapsed;return jsxRuntimeExports.jsx(PhosphorIcon,{icon:caretRight,style:iconStyle})}const styles$U=StyleSheet.create({collapsed:{transition:".15s"},expanded:{transform:"rotate(90deg)",transition:".15s"}});
|
|
1427
|
-
|
|
1428
1440
|
const _upgradeWidgetInfo=props=>{const filteredProps=excludeDenylistKeys(props);return applyDefaultsToWidget(filteredProps)};class WidgetEditor extends React.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState({widgetInfo:_upgradeWidgetInfo(nextProps)});if(nextProps.widgetIsOpen!=null&&nextProps.widgetIsOpen!==this.props.widgetIsOpen){this.setState({showWidget:nextProps.widgetIsOpen});}}render(){const widgetInfo=this.state.widgetInfo;const isEditingDisabled=this.props.apiOptions.editingDisabled??false;const Ed=Widgets.getEditor(widgetInfo.type);let supportedAlignments;const imageUpgradeFF=isFeatureOn(this.props,"image-widget-upgrade");if(widgetInfo.type==="image"&&!imageUpgradeFF){supportedAlignments=["block","full-width"];}else if(this.props.apiOptions.showAlignmentOptions){supportedAlignments=CoreWidgetRegistry.getSupportedAlignments(widgetInfo.type);}else {supportedAlignments=["default"];}const supportsStaticMode=Widgets.supportsStaticMode(widgetInfo.type);return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-title "+(this.state.showWidget?"open":"closed"),children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-title-id",children:jsxRuntimeExports.jsxs(View,{style:{display:"flex",flexDirection:"row",alignItems:"center",gap:"0.25em"},onClick:this._toggleWidget,children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:this.state.showWidget}),jsxRuntimeExports.jsx("span",{children:this.props.id})]})}),supportsStaticMode&&jsxRuntimeExports.jsx(LabeledSwitch$1,{label:"Static",checked:!!widgetInfo.static,disabled:isEditingDisabled,onChange:this._setStatic}),supportedAlignments.length>1&&jsxRuntimeExports.jsx("select",{className:"alignment",value:widgetInfo.alignment,disabled:isEditingDisabled,onChange:this._handleAlignmentChange,children:supportedAlignments.map(alignment=>jsxRuntimeExports.jsx("option",{children:alignment},alignment))}),jsxRuntimeExports.jsx(SectionControlButton,{icon:trashIcon,disabled:isEditingDisabled,onClick:()=>{this.props.onRemove();},title:"Remove image widget"})]}),jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-content "+(this.state.showWidget?"enter":"leave"),children:Ed&&jsxRuntimeExports.jsx(Ed,{ref:this.widget,onChange:this._handleWidgetChange,static:widgetInfo.static,apiOptions:this.props.apiOptions,...widgetInfo.options})})]})}constructor(props){super(props),this._toggleWidget=e=>{e.preventDefault();this.setState({showWidget:!this.state.showWidget});},this._handleWidgetChange=(newProps,cb,silent)=>{const newWidgetInfo={...this.state.widgetInfo,options:{...this.state.widgetInfo.options,...this.widget.current?.serialize()??{},...newProps}};this.props.onChange(newWidgetInfo,cb,silent);},this._setStatic=value=>{const newWidgetInfo={...this.state.widgetInfo,static:value};this.props.onChange(newWidgetInfo);},this._handleAlignmentChange=e=>{const newAlignment=e.currentTarget.value;const newWidgetInfo=Object.assign({},this.state.widgetInfo);newWidgetInfo.alignment=newAlignment;this.props.onChange(newWidgetInfo);},this.getSaveWarnings=()=>{const issuesFunc=this.widget.current?.getSaveWarnings;return issuesFunc?issuesFunc():[]},this.serialize=()=>{const widgetInfo=this.state.widgetInfo;return {type:widgetInfo.type,alignment:widgetInfo.alignment,static:widgetInfo.static,graded:widgetInfo.graded,options:this.widget.current.serialize(),version:widgetInfo.version}};this.state={showWidget:props.widgetIsOpen??true,widgetInfo:_upgradeWidgetInfo(props)};this.widget=React.createRef();}}function LabeledSwitch$1(props){const{label,disabled,...switchProps}=props;const id=useId();return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx("label",{htmlFor:id,children:label}),jsxRuntimeExports.jsx(Strut,{size:spacing.xxSmall_6}),jsxRuntimeExports.jsx(Switch,{id:id,...switchProps,disabled:disabled})]})}
|
|
1429
1441
|
|
|
1430
1442
|
class WidgetSelect extends React.Component{shouldComponentUpdate(){return false}render(){const widgets=Widgets.getPublicWidgets();const orderedWidgetNames=_.sortBy(_.keys(widgets),name=>{return widgets[name].displayName});const addWidgetString="Add a widget…";return jsxRuntimeExports.jsxs("select",{value:"",onChange:this.handleChange,"data-testid":"editor__widget-select",children:[jsxRuntimeExports.jsx("option",{value:"",children:addWidgetString}),jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),orderedWidgetNames.map(name=>{return jsxRuntimeExports.jsx("option",{value:name,children:widgets[name].displayName},name)})]})}constructor(...args){super(...args),this.handleChange=e=>{const widgetType=e.currentTarget.value;if(widgetType===""){return}if(this.props.onChange){this.props.onChange(widgetType);}};}}
|
|
1431
1443
|
|
|
1432
|
-
class TexErrorView extends React.Component{render(){const{errorList}=this.props;const{showErrors}=this.state;return jsxRuntimeExports.jsxs(View,{style:styles$
|
|
1444
|
+
class TexErrorView extends React.Component{render(){const{errorList}=this.props;const{showErrors}=this.state;return jsxRuntimeExports.jsxs(View,{style:styles$R.errorContainer,children:[jsxRuntimeExports.jsxs(View,{style:styles$R.title,onClick:this.handleToggleTexErrors,children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:showErrors})," TeX Errors (",errorList.length,")"]}),showErrors&&jsxRuntimeExports.jsx(View,{style:styles$R.errorExplanation,children:"If your math doesn't display correctly, these errors might help you troubleshoot. Message #content-kitchen for help."}),showErrors&&errorList.map((e,index)=>jsxRuntimeExports.jsxs(View,{style:styles$R.error,children:[jsxRuntimeExports.jsx(View,{style:{color:"red"},children:e.math}),jsxRuntimeExports.jsx(View,{children:e.message})]},index))]})}constructor(...args){super(...args),this.state={showErrors:false},this.handleToggleTexErrors=e=>{this.setState({showErrors:!this.state.showErrors});};}}const styles$R=StyleSheet.create({title:{backgroundColor:"#eee",fontSize:"1.25em",padding:"4px 10px",cursor:"pointer",display:"flex",flexDirection:"row",alignItems:"center"},errorContainer:{border:"1px solid #ddd",borderTop:"none"},errorExplanation:{padding:"4px 10px",backgroundColor:"pink"},error:{padding:"4px 10px"}});
|
|
1433
1445
|
|
|
1434
1446
|
const widgetPlaceholder="[[☃ {id}]]";const widgetRegExp="(\\[\\[☃ {id}\\]\\])";const rWidgetSplit=new RegExp(widgetRegExp.replace("{id}","[a-z-]+ [0-9]+"),"g");const shortcutRegexp=/^\[\[([a-z-]+)$/;const ENDS_WITH_A_PARAGRAPH=/(?:\n{2,}|^\n*)$/;const TRAILING_NEWLINES=/(\n*)$/;const LEADING_NEWLINES=/^(\n*)/;const commafyInteger=n=>{let str=n.toString();if(str.length>=5){str=str.replace(/(\d)(?=(\d{3})+$)/g,"$1{,}");}return str};const makeEndWithAParagraphIfNecessary=content=>{if(!ENDS_WITH_A_PARAGRAPH.test(content)){const match=TRAILING_NEWLINES.exec(content);if(match){const newlines=match[1];return content+"\n\n".slice(0,2-newlines.length)}}return content};const makeStartWithAParagraphAlways=content=>{const match=LEADING_NEWLINES.exec(content);if(!match){return content}const newlines=match[1];return "\n\n".slice(0,2-newlines.length)+content};const IMAGE_REGEX$1=/!\[[^\]]*\]\(([^\s)]+)[^)]*\)/g;const allMatches=function(regex,str){const result=[];while(true){const match=regex.exec(str);if(!match){break}result.push(match);}return result};const imageUrlsFromContent=function(content){return allMatches(IMAGE_REGEX$1,content).map(capture=>capture[1])};class Editor extends React.Component{componentDidMount(){this.lastUserValue=null;this._sizeImages(this.props);$(this.textarea.current).on("copy cut",this._maybeCopyWidgets).on("paste",this._maybePasteWidgets);}UNSAFE_componentWillReceiveProps(nextProps){if(this.props.content!==nextProps.content){this.setState({textAreaValue:nextProps.content});}}componentDidUpdate(prevProps){const textarea=this.textarea.current;if(this.lastUserValue!=null&&textarea){textarea.focus();textarea.value=this.lastUserValue;textarea.selectionStart=0;textarea.setSelectionRange(0,prevProps.content.length);if(document.execCommand("insertText",false,this.props.content)===false){textarea.value=this.props.content;}this.lastUserValue=null;}if(this.props.content!==prevProps.content){this._sizeImages(this.props);}}componentWillUnmount(){clearTimeout(this.deferredChange);}getWidgetEditor(id,type){if(!Widgets.getEditor(type)){return}return createElement(WidgetEditor,{...this.props.widgets[id],ref:id,id:id,key:id,onChange:this._handleWidgetEditorChange.bind(this,id),onRemove:this._handleWidgetEditorRemove.bind(this,id),apiOptions:this.props.apiOptions,widgetIsOpen:this.props.widgetIsOpen})}render(){let pieces;let widgets;let underlayPieces;let widgetsDropDown;let templatesDropDown;let widgetsAndTemplates;let wordCountDisplay;const katexErrorList=[];if(this.props.showWordCount){const numChars=PerseusMarkdown.characterCount(this.props.content);const numWords=Math.floor(numChars/6);wordCountDisplay=jsxRuntimeExports.jsx("span",{className:"perseus-editor-word-count",title:"~"+commafyInteger(numWords)+" words ("+commafyInteger(numChars)+" characters)",children:commafyInteger(numWords)});}if(this.props.widgetEnabled){pieces=this.props.content.split(rWidgetSplit);widgets={};underlayPieces=[];for(let i=0;i<pieces.length;i++){if(i%2===0){underlayPieces.push(pieces[i]);const ast=PerseusMarkdown.parse(pieces[i]);PerseusMarkdown.traverseContent(ast,node=>{if(node.type==="math"||node.type==="blockMath"){const content=preprocessTex(node.content);try{katex.renderToString(content,{colorIsTextColor:true});}catch(e){katexErrorList.push({math:content,message:e.message});}}});}else {const match=Util.rWidgetParts.exec(pieces[i]);if(match!=null){const id=match[1];const type=match[2];const duplicate=id in widgets;widgets[id]=this.getWidgetEditor(id,type);const classes=(duplicate||!widgets[id]?"error ":"")+("");const key=duplicate?i:id;underlayPieces.push(jsxRuntimeExports.jsx("b",{className:classes,children:pieces[i]},key));}}}this.widgetIds=_.keys(widgets);widgetsDropDown=jsxRuntimeExports.jsx(WidgetSelect,{onChange:this._addWidget});const insertTemplateString="Insert template…";templatesDropDown=jsxRuntimeExports.jsxs("select",{onChange:this.addTemplate,"data-testid":"editor__template-select",children:[jsxRuntimeExports.jsx("option",{value:"",children:insertTemplateString}),jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),jsxRuntimeExports.jsx("option",{value:"table",children:"Table"}),jsxRuntimeExports.jsx("option",{value:"titledTable",children:"Titled table"}),jsxRuntimeExports.jsx("option",{value:"alignment",children:"Aligned equations"}),jsxRuntimeExports.jsx("option",{value:"piecewise",children:"Piecewise function"}),Object.keys(this.props.additionalTemplates).length>0&&jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),Object.entries(this.props.additionalTemplates).map(([key])=>jsxRuntimeExports.jsx("option",{value:key,children:key},key)),jsxRuntimeExports.jsx("option",{disabled:true,children:"--"}),jsxRuntimeExports.jsx("option",{value:"allWidgets",children:"All widgets (for testing)"})]});if(!this.props.immutableWidgets){const widgetNodes=Object.values(widgets);widgetsAndTemplates=jsxRuntimeExports.jsxs("div",{className:"perseus-editor-widgets",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-widgets-selectors",children:[widgetsDropDown,templatesDropDown,wordCountDisplay]}),widgetNodes]});wordCountDisplay=null;}}else {underlayPieces=[this.props.content];}underlayPieces.push(jsxRuntimeExports.jsx("br",{},"end"));const completeTextarea=[jsxRuntimeExports.jsx("div",{className:"perseus-textarea-underlay",ref:this.underlay,children:underlayPieces},"underlay"),jsxRuntimeExports.jsx("textarea",{ref:this.textarea,onChange:this.handleChange,onKeyDown:this._handleKeyDown,placeholder:this.props.placeholder,disabled:this.props.disabled,value:this.state.textAreaValue},"textarea")];let textareaWrapper;if(this.props.imageUploader){textareaWrapper=jsxRuntimeExports.jsx(DragTarget,{onDrop:this.handleDrop,className:"perseus-textarea-pair",children:completeTextarea});}else {textareaWrapper=jsxRuntimeExports.jsx("div",{className:"perseus-textarea-pair",children:completeTextarea});}const contentWithoutWidgets=this.props.content.replace(/\[\[\u2603 (([a-z-]+) ([0-9]+))\]\]/g,"");const noPrompt=contentWithoutWidgets.trim().length===0;const noWidgets=!/\[\[\u2603 (([a-z-]+) ([0-9]+))\]\]/g.test(this.props.content);const warningStyle={borderTop:"none",padding:4,backgroundColor:"pink"};const editingDisabled=this.props.apiOptions.editingDisabled;return jsxRuntimeExports.jsxs("div",{"data-testid":"perseus-single-editor",className:"perseus-single-editor "+(this.props.className||"")+(editingDisabled?" perseus-editor-disabled":""),children:[textareaWrapper,katexErrorList.length>0&&jsxRuntimeExports.jsx(TexErrorView,{errorList:katexErrorList}),this.props.warnNoPrompt&&noPrompt&&jsxRuntimeExports.jsx("div",{style:warningStyle,children:"Graded Groups should contain a prompt"}),this.props.warnNoWidgets&&noWidgets&&jsxRuntimeExports.jsx("div",{style:warningStyle,children:"Graded Groups should contain at least one widget"}),wordCountDisplay,widgetsAndTemplates]})}constructor(...args){super(...args),this.underlay=React.createRef(),this.textarea=React.createRef(),this.state={textAreaValue:this.props.content},this._handleWidgetEditorChange=(id,newWidgetInfo,cb,silent)=>{const widgets=Object.assign({},this.props.widgets);widgets[id]=Object.assign({},widgets[id],newWidgetInfo);this.props.onChange({widgets},cb,silent);},this._handleWidgetEditorRemove=id=>{if(!confirm("Are you sure you want to delete this item?")){return}const textarea=this.textarea.current;const re=new RegExp(widgetRegExp.replace("{id}",id),"gm");this.props.onChange({content:textarea?.value.replace(re,"")});},this._sizeImages=props=>{const imageUrls=imageUrlsFromContent(props.content);const images=_.pick(props.images,imageUrls);const newImageUrls=_.filter(imageUrls,url=>!images[url]);_.each(newImageUrls,url=>{Util.getImageSize(url,(width,height)=>{images[url]={width:width,height:height};props.onChange({images:_.clone(images)},null,true);});});},this.handleDrop=e=>{const{imageUploader}=this.props;let content=this.state.textAreaValue||"";const dataTransfer=e.dataTransfer;if(!dataTransfer||!imageUploader){return}const files=dataTransfer.files;if(files.length===0){const imageUrl=dataTransfer.getData("URL");if(imageUrl){const newContent=content+"\n\n";this.lastUserValue=this.props.content;this.props.onChange({content:newContent});}return}const origContent=this.state.textAreaValue;_(files).chain().map(function(file){if(!file.type.match("image.*")){return null}const sentinel="☃ "+_.uniqueId("image_");content+="\n\n";return {file:file,sentinel:sentinel}}).reject(_.isNull).tap(()=>{this.lastUserValue=origContent;this.props.onChange({content:content});}).each(fileAndSentinel=>{imageUploader(fileAndSentinel.file,url=>{this.lastUserValue=origContent;this.props.onChange({content:this.state.textAreaValue.replace(fileAndSentinel.sentinel,url)});});});},this.handleChange=e=>{clearTimeout(this.deferredChange);this.setState({textAreaValue:e.currentTarget.value});this.deferredChange=setTimeout(()=>{if(this.state.textAreaValue!==this.props.content){this.props.onChange({content:this.state.textAreaValue});}},this.props.apiOptions.editorChangeDelay);},this._handleKeyDown=e=>{e.stopPropagation();if(e.key==="Tab"){const textarea=this.textarea.current;const word=Util.textarea.getWordBeforeCursor(textarea);const matches=word.string.toLowerCase().match(shortcutRegexp);if(matches!=null){const text=matches[1];const widgets=Widgets.getAllWidgetTypes();const matchingWidgets=widgets.filter(name=>{return name.substring(0,text.length)===text});if(matchingWidgets.length===1){const widgetType=matchingWidgets[0];this._addWidgetToContent(this.props.content,[word.pos.start,word.pos.end+1],widgetType);}e.preventDefault();}}},this._maybeCopyWidgets=e=>{const textarea=e.currentTarget;const selectedText=textarea.value.substring(textarea.selectionStart,textarea.selectionEnd);const widgetNames=_.map(selectedText.match(rWidgetSplit),syntax=>{return Util.rWidgetParts.exec(syntax)[1]});const widgetData=_.pick(this.serialize().widgets,widgetNames);localStorage.perseusLastCopiedText=selectedText;localStorage.perseusLastCopiedWidgets=JSON.stringify(widgetData);Log.log(`Widgets copied: ${localStorage.perseusLastCopiedWidgets}`);},this._maybePasteWidgets=e=>{const widgetJSON=localStorage.perseusLastCopiedWidgets;const lastCopiedText=localStorage.perseusLastCopiedText;const textToBePasted=e.originalEvent.clipboardData.getData("text");if(widgetJSON&&lastCopiedText===textToBePasted){e.preventDefault();const widgetData=JSON.parse(widgetJSON);const safeWidgetMapping=this._safeWidgetNameMapping(widgetData);const safeWidgetData={};for(const[key,data]of Object.entries(widgetData)){safeWidgetData[safeWidgetMapping[key]]=data;}const newWidgets=_.extend(safeWidgetData,this.props.widgets);const safeText=lastCopiedText.replace(rWidgetSplit,syntax=>{const match=Util.rWidgetParts.exec(syntax);const completeWidget=match[0];const widget=match[1];return completeWidget.replace(widget,safeWidgetMapping[widget])});const textarea=e.currentTarget;const selectionStart=textarea.selectionStart;const newContent=this.state.textAreaValue.substr(0,selectionStart)+safeText+this.state.textAreaValue.substr(textarea.selectionEnd);this.lastUserValue=this.state.textAreaValue;this.props.onChange({content:newContent,widgets:newWidgets},()=>{const expectedCursorPosition=selectionStart+safeText.length;Util.textarea.moveCursor(textarea,expectedCursorPosition);});}},this._safeWidgetNameMapping=widgetData=>{const widgets=_.keys(widgetData).map(name=>name.split(" "));const widgetTypes=_.uniq(widgets.map(widget=>widget[0]));const existingWidgets=_.keys(this.props.widgets).map(name=>name.split(" "));const safeWidgetNums={};_.each(widgetTypes,type=>{safeWidgetNums[type]=_.chain(existingWidgets).filter(existingWidget=>existingWidget[0]===type).map(existingWidget=>+existingWidget[1]+1).max().value();safeWidgetNums[type]=Math.max(safeWidgetNums[type],1);});const safeWidgetMapping={};_.each(widgets,widget=>{const widgetName=widget.join(" ");const widgetType=widget[0];safeWidgetMapping[widgetName]=`${widgetType} ${safeWidgetNums[widgetType]}`;safeWidgetNums[widgetType]++;});return safeWidgetMapping},this._addWidgetToContent=(oldContent,cursorRange,widgetType)=>{const allWidgetIds=_.map(oldContent.match(rWidgetSplit),syntax=>{const match=Util.rWidgetParts.exec(syntax);const type=match[2];const num=+match[3];return [type,num]});const widgetNum=_.reduce(allWidgetIds,(currentNum,otherId)=>{const[otherType,otherNum]=otherId;if(otherType===widgetType){return Math.max(otherNum+1,currentNum)}return currentNum},1);const id=widgetType+" "+widgetNum;const widgetContent=widgetPlaceholder.replace("{id}",id);const isBlock=CoreWidgetRegistry.getDefaultAlignment(widgetType)==="block";const prelude=oldContent.slice(0,cursorRange[0]);const postlude=oldContent.slice(cursorRange[1]);const newPrelude=isBlock?makeEndWithAParagraphIfNecessary(prelude):prelude;const newPostlude=isBlock?makeStartWithAParagraphAlways(postlude):postlude;const newContent=newPrelude+widgetContent+newPostlude;const newWidgets={...this.props.widgets};newWidgets[id]={options:Widgets.getEditor(widgetType)?.defaultProps,type:widgetType,version:Widgets.getVersion(widgetType)};this.lastUserValue=this.props.content;this.props.onChange({content:newContent,widgets:newWidgets},()=>{if(!this.textarea.current){return}Util.textarea.moveCursor(this.textarea.current,newContent.length-postlude.length);});},this._addWidget=widgetType=>{const textarea=this.textarea.current;if(!textarea){return}this._addWidgetToContent(this.props.content,[textarea.selectionStart,textarea.selectionEnd],widgetType);textarea.focus();},this.addTemplate=e=>{const templateType=e.currentTarget.value;if(templateType===""){return}e.currentTarget.value="";let oldContent=this.props.content;oldContent=oldContent.replace(/\n*$/,"\n\n");let template;if(templateType==="table"){template="header 1 | header 2 | header 3\n"+"- | - | -\n"+"data 1 | data 2 | data 3\n"+"data 4 | data 5 | data 6\n"+"data 7 | data 8 | data 9";}else if(templateType==="titledTable"){template="|| **Table title** ||\n"+"header 1 | header 2 | header 3\n"+"- | - | -\n"+"data 1 | data 2 | data 3\n"+"data 4 | data 5 | data 6\n"+"data 7 | data 8 | data 9";}else if(templateType==="alignment"){template="$\\begin{align} \n"+"\\\\\\\\\n"+"\\end{align}$";}else if(templateType==="piecewise"){template="$f(x) = \\begin{cases}\n"+"7 & \\text{if }x=1 \\\\\n"+"f(x-1)+5 & \\text{if }x > 1\n"+"\\end{cases}$";}else if(templateType==="allWidgets"){template=Widgets.getAllWidgetTypes().map(type=>`[[${Util.snowman} ${type} 1]]`).join("\n\n");}else if(templateType in this.props.additionalTemplates){template=this.props.additionalTemplates[templateType];}else {throw new PerseusError("Invalid template type: "+templateType,Errors.InvalidInput,{metadata:{templateType}})}const newContent=oldContent+template;this.lastUserValue=this.props.content;this.props.onChange({content:newContent},this.focusAndMoveToEnd);},this.getSaveWarnings=()=>{const widgetIds=_.intersection(this.widgetIds,_.keys(this.refs));const warnings=_(widgetIds).chain().map(id=>{const issuesFunc=this.refs[id].getSaveWarnings;const issues=issuesFunc?issuesFunc():[];return _.map(issues,issue=>id+": "+issue)}).flatten(true).value();return warnings},this.focus=()=>{const textarea=this.textarea.current;if(textarea){textarea.focus();}},this.focusAndMoveToEnd=()=>{this.focus();const textarea=this.textarea.current;if(textarea){textarea.selectionStart=textarea.value.length;textarea.selectionEnd=textarea.value.length;}},this.serialize=options=>{const widgets={};const widgetIds=_.intersection(this.widgetIds,_.keys(this.refs));_.each(widgetIds,id=>{widgets[id]=this.refs[id].serialize();});if(options&&options.keepDeletedWidgets){_.chain(this.props.widgets).keys().reject(id=>_.contains(widgetIds,id)).each(id=>{widgets[id]=this.props.widgets[id];});}return {replace:this.props.replace,content:this.props.content,images:this.props.images,widgets:widgets}};}}Editor.defaultProps={content:"",placeholder:"",widgets:{},images:{},disabled:false,widgetEnabled:true,immutableWidgets:false,showWordCount:false,warnNoPrompt:false,warnNoWidgets:false,additionalTemplates:{},apiOptions:ApiOptions.defaults};
|
|
1435
1447
|
|
|
1436
1448
|
let nextIframeID=0;const requestIframeData={};const updateIframeHeight={};window.iframeDataStore={};window.addEventListener("message",event=>{if(typeof event.data==="string"){const callback=requestIframeData[event.data];if(callback){callback();}}else if(event.data.id){if(event.data.height!==undefined){updateIframeHeight[event.data.id](event.data.height);}else if(event.data.lintWarnings){Log.log("LINTER REPORT",{lintWarnings:JSON.stringify(event.data.lintWarnings)});}}});class IframeContentRenderer extends React.Component{componentDidMount(){this._isMounted=true;this.iframeID=nextIframeID;nextIframeID++;this._prepareFrame();requestIframeData[this.iframeID]=()=>{this.sendNewData(this._lastData);};updateIframeHeight[this.iframeID]=height=>{this._lastHeight=height;if(this._isMounted&&this.props.seamless&&this.container.current){this.container.current.style.height=height+"px";}};}shouldComponentUpdate(nextProps){return nextProps.datasetValue!==this.props.datasetValue||nextProps.seamless!==this.props.seamless}componentDidUpdate(prevProps){if(this.container.current){if(!this.props.seamless){this.container.current.style.height="100%";}else {this.container.current.style.height=this._lastHeight+"px";}}if(prevProps.datasetValue!==this.props.datasetValue){this._prepareFrame();}}componentWillUnmount(){requestIframeData[this.iframeID]=null;updateIframeHeight[this.iframeID]=null;this._isMounted=false;}_prepareFrame(){if(this._frame){this.container.current?.removeChild(this._frame);}const frame=document.createElement("iframe");frame.style.width="100%";frame.style.height="100%";frame.src=this.props.url;if(this.props.datasetKey){frame.dataset[this.props.datasetKey]=this.props.datasetValue;}frame.dataset.id=String(this.iframeID);if(this.props.seamless){frame.dataset.lintGutter="true";}this.container.current?.appendChild(frame);this._frame=frame;}sendNewData(data){const frame=this._frame;if(this._isMounted&&data&&frame?.contentWindow){this._lastData=data;window.iframeDataStore[this.iframeID]=data;frame.contentWindow.postMessage(this.iframeID,"*");}}render(){return jsxRuntimeExports.jsx("div",{ref:this.container,style:{width:"100%",height:"100%"}})}constructor(...args){super(...args),this.container=React.createRef();}}
|
|
1437
1449
|
|
|
1438
|
-
const
|
|
1450
|
+
const SEVERITY_ERROR=1;const SEVERITY_WARNING=2;const SEVERITY_GUIDELINE=3;const SEVERITY_MAP={[SEVERITY_ERROR]:"high",[SEVERITY_WARNING]:"medium",[SEVERITY_GUIDELINE]:"low"};const WARNINGS={inaccessibleWidget:(widgetType,widgetId)=>({id:`${widgetId} inaccessible`,description:`This ${widgetType} widget (${widgetId}) is inaccessible. Consider using an alternative to support all learners. Please check out the following documentation on compliant widget options.`,helpUrl:"https://khanacademy.atlassian.net/wiki/spaces/LC/pages/1909489691/Widget+Fundamentals",help:"Widget Fundamentals",impact:"medium",message:"Selecting inaccessible widgets for a practice item will result in this exercise being hidden from users with 'Hide visually dependant content' setting set to true. Please select another widget or create an alternative practice item."}),genericLinterWarning:(rule,message,severity)=>({id:rule,description:message,help:"Learn more about best practices for authoring items",helpUrl:"https://docs.google.com/document/d/1N13f4sY-7EXWDwQ04ivA9vJBVvPPd60qjBT73B4NHuM/edit?tab=t.0",impact:SEVERITY_MAP[severity??SEVERITY_GUIDELINE],message:message})};
|
|
1451
|
+
|
|
1452
|
+
const{HUD: HUD$1}=components;class ArticleEditor extends React.Component{componentDidMount(){this._updateIssues();this._updatePreviewFrames();}componentDidUpdate(prevProps){if(prevProps.json!==this.props.json||prevProps.issues!==this.props.issues){this._updateIssues();}this._updatePreviewFrames();}_updateIssues(){const sections=this.props.json instanceof Array?this.props.json:[this.props.json];const allLinterIssues=[];sections.forEach(section=>{const parsed=PerseusMarkdown.parse(section.content??"",{});const linterContext={content:section.content,widgets:section.widgets,stack:[]};const sectionIssues=PerseusLinter.runLinter(parsed,linterContext,false)?.map(linterWarning=>{if(linterWarning.rule==="inaccessible-widget"){return WARNINGS.inaccessibleWidget(linterWarning.metadata?.widgetType??"unknown",linterWarning.metadata?.widgetId??"unknown")}return WARNINGS.genericLinterWarning(linterWarning.rule,linterWarning.message,linterWarning.severity)})??[];allLinterIssues.push(...sectionIssues);});this.setState({issues:[...this.props.issues??[],...allLinterIssues]});}_updatePreviewFrames(){if(this.props.mode==="preview"){this.refs["frame-all"].sendNewData({type:"article-all",data:this._sections().map((section,i)=>{return this._apiOptionsForSection(section,i)})});}else if(this.props.mode==="edit"){this._sections().forEach((section,i)=>{this.refs["frame-"+i].sendNewData({type:"article",data:this._apiOptionsForSection(section,i)});});}}_apiOptionsForSection(section,sectionIndex){const editor=this.refs[`editor${sectionIndex}`];return {apiOptions:{...ApiOptions.defaults,...this.props.apiOptions,showAlignmentOptions:true,isArticle:true},json:section,useNewStyles:this.props.useNewStyles,linterContext:{contentType:"article",highlightLint:this.state.highlightLint,paths:this.props.contentPaths},legacyPerseusLint:editor?editor.getSaveWarnings():[]}}_sections(){const json=this.props.json;return json instanceof Array?json:[json]}_renderEditor(){const{imageUploader,sectionImageUploadGenerator}=this.props;const apiOptions={...ApiOptions.defaults,...this.props.apiOptions,showAlignmentOptions:true,isArticle:true};const sections=this._sections();const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsxs("div",{className:"perseus-editor-table",children:[sections.map((section,i)=>{return [jsxRuntimeExports.jsx("div",{className:"perseus-editor-row",children:jsxRuntimeExports.jsxs("fieldset",{disabled:editingDisabled,children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-left-cell",children:[jsxRuntimeExports.jsx(IssuesPanel,{apiOptions:this.props.apiOptions,issues:this.state.issues}),jsxRuntimeExports.jsxs("div",{className:"pod-title",children:["Section ",i+1,jsxRuntimeExports.jsxs("div",{style:{display:"inline-block",float:"right"},children:[sectionImageUploadGenerator(i),jsxRuntimeExports.jsx(SectionControlButton,{icon:plusIcon,disabled:editingDisabled,onClick:()=>{this._handleAddSectionAfter(i);},title:"Add a new section after this one"}),i+1<sections.length&&jsxRuntimeExports.jsx(SectionControlButton,{icon:arrowCircleDownIcon,disabled:editingDisabled,onClick:()=>{this._handleMoveSectionLater(i);},title:"Move this section down"}),i>0&&jsxRuntimeExports.jsx(SectionControlButton,{icon:arrowCircleUpIcon,disabled:editingDisabled,onClick:()=>{this._handleMoveSectionEarlier(i);},title:"Move this section up"}),jsxRuntimeExports.jsx(SectionControlButton,{icon:trashIcon,disabled:editingDisabled,onClick:()=>{const msg="Are you sure you "+"want to delete section "+(i+1)+"?";if(confirm(msg)){this._handleRemoveSection(i);}},title:"Delete this section"})]})]}),jsxRuntimeExports.jsx(Editor,{...section,apiOptions:apiOptions,imageUploader:imageUploader,onChange:newProps=>this._handleEditorChange(i,newProps),placeholder:"Type your section text here...",ref:"editor"+i})]}),jsxRuntimeExports.jsx("div",{className:"editor-preview",children:this._renderIframePreview(i,true)})]})},i)]}),this._renderAddSection(editingDisabled),this._renderLinterHUD()]})}_renderAddSection(editingDisabled){return jsxRuntimeExports.jsx("div",{className:"perseus-editor-row",children:jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsx(Button,{startIcon:plusIcon,disabled:editingDisabled,kind:"tertiary","aria-label":"Add a section",onClick:()=>{this._handleAddSectionAfter(this._sections().length-1);},children:"Add a section"})})})}_renderLinterHUD(){return jsxRuntimeExports.jsx(HUD$1,{message:"Style warnings",enabled:this.state.highlightLint,onClick:()=>{this.setState({highlightLint:!this.state.highlightLint});}})}_renderIframePreview(i,nochrome){const isMobile=this.props.screen==="phone"||this.props.screen==="tablet";return jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.screen,nochrome:nochrome,children:jsxRuntimeExports.jsx(IframeContentRenderer,{ref:"frame-"+i,datasetKey:"mobile",datasetValue:isMobile,seamless:nochrome,url:this.props.previewURL},this.props.screen)})}_renderPreviewMode(){return jsxRuntimeExports.jsx("div",{className:"standalone-preview",children:this._renderIframePreview("all",false)})}_handleMoveSectionEarlier(i){if(i===0){return}const sections=[...this._sections()];const section=sections[i];sections.splice(i,1);sections.splice(i-1,0,section);this.props.onChange({json:sections});}_handleMoveSectionLater(i){const sections=[...this._sections()];if(i+1===sections.length){return}const section=sections[i];sections.splice(i,1);sections.splice(i+1,0,section);this.props.onChange({json:sections});}_handleAddSectionAfter(i){const sections=_.clone(this.serialize());const newSection=i>=0?{widgets:sections[i].widgets}:{};sections.splice(i+1,0,newSection);this.props.onChange({json:sections});}_handleRemoveSection(i){const sections=[...this._sections()];sections.splice(i,1);this.props.onChange({json:sections});}serialize(){if(this.props.mode==="edit"){return this._sections().map((section,i)=>{return this.refs["editor"+i].serialize()})}if(this.props.mode==="preview"||this.props.mode==="json"){return this.props.json}throw new PerseusError("Could not serialize; mode "+this.props.mode+" not found",Errors.Internal)}getSaveWarnings(){if(this.props.mode!=="edit"){throw new PerseusError("Can only get save warnings in edit mode.",Errors.NotAllowed)}return this._sections().map((section,i)=>{return this.refs["editor"+i].getSaveWarnings()})}render(){const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsx(Dependencies.DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsxs("div",{className:"framework-perseus perseus-article-editor",children:[this.props.mode==="edit"&&this._renderEditor(),this.props.mode==="preview"&&this._renderPreviewMode(),this.props.mode==="json"&&jsxRuntimeExports.jsxs("div",{className:"json-editor",children:[jsxRuntimeExports.jsx("div",{className:"json-editor-warning",children:jsxRuntimeExports.jsx("span",{children:"Warning: Editing in this mode can lead to broken articles!"})}),jsxRuntimeExports.jsx(JsonEditor,{multiLine:true,onChange:this._handleJsonChange,value:this.props.json,editingDisabled:editingDisabled})]})]})})}constructor(...args){super(...args),this.state={highlightLint:true,issues:[]},this._handleJsonChange=newJson=>{this.props.onChange({json:newJson});},this._handleEditorChange=(i,newProps)=>{const sections=[...this._sections()];sections[i]={...sections[i],...newProps};this.props.onChange({json:sections});};}}ArticleEditor.defaultProps={contentPaths:[],json:[{}],mode:"edit",screen:"desktop",sectionImageUploadGenerator:()=>jsxRuntimeExports.jsx("span",{}),useNewStyles:false};
|
|
1439
1453
|
|
|
1440
1454
|
const iconChevronRight={path:"M62.808 49.728q0 3.36-2.352 5.88l-41.72 41.664q-2.352 2.408-5.768 2.408t-5.768-2.408l-4.872-4.76q-2.352-2.52-2.352-5.88t2.352-5.712l31.08-31.136-31.08-31.024q-2.352-2.52-2.352-5.88t2.352-5.712l4.872-4.76q2.296-2.408 5.768-2.408t5.768 2.408l41.72 41.664q2.352 2.296 2.352 5.656z",width:63.034,height:100};const iconCircleArrowDown={path:"M50.046 83.676q1.767 0 2.907-1.14l29.526-29.526q1.197-1.197 1.197-2.907t-1.197-2.964l-5.928-5.928q-1.197-1.14-2.964-1.14t-2.907 1.14l-12.312 12.312l0-32.661q0-1.71-1.254-2.964t-2.907-1.254l-8.322 0q-1.71 0-2.964 1.254t-1.254 2.964l0 32.661l-12.312-12.312q-1.197-1.254-2.907-1.254t-2.907 1.254l-5.928 5.928q-1.197 1.197-1.197 2.964t1.197 2.907l29.469 29.526q1.197 1.14 2.964 1.14zm49.989-33.63q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",width:100,height:100};const iconCircleArrowUp={path:"M54.207 83.391q1.653 0 2.907-1.254t1.254-2.907l0-32.718l12.312 12.312q1.254 1.254 2.964 1.254t2.907-1.254l5.928-5.928q1.197-1.197 1.14-2.964 0-1.767-1.14-2.907l-29.526-29.526q-1.197-1.14-2.907-1.14t-2.964 1.14l-29.469 29.526q-1.197 1.254-1.197 2.964t1.197 2.907l5.928 5.928q1.197 1.197 2.907 1.197t2.907-1.197l12.312-12.312l0 32.718q0 1.653 1.254 2.907t2.964 1.254l8.322 0zm45.828-33.345q.057 13.623-6.669 25.137t-18.24 18.183-25.08 6.669-25.137-6.726q-11.514-6.726-18.183-18.183-6.726-11.571-6.726-25.137t6.726-25.08 18.24-18.24 25.08-6.669q13.566 0 25.08 6.726 11.514 6.669 18.24 18.183t6.669 25.137z",width:100,height:100};const iconDesktop={path:"M94.208 52.119l0-43.746q0-.69-.506-1.15t-1.196-.506l-84.088 0q-.69 0-1.196.506t-.506 1.15l0 43.746q0 .69.506 1.196t1.196.506l84.088 0q.69 0 1.196-.506t.506-1.196zm6.716-43.746l0 57.224q0 3.45-2.484 5.934t-5.934 2.484l-28.566 0q0 3.128 2.53 7.774.828 1.61.828 2.622t-1.012 2.07q-1.012 1.012-2.346.966l-26.91 0q-1.38 0-2.392-1.012t-1.012-2.024q0-1.058 1.656-4.14t1.748-6.256l-28.612 0q-3.45 0-5.934-2.484t-2.484-5.934l0-57.224q0-3.45 2.484-5.934t5.934-2.438l84.088 0q3.45 0 5.98 2.438 2.438 2.484 2.438 5.934z",width:100,height:86.648};const iconMobilePhone={path:"M36.04 89.557q0-2.584-1.836-4.42t-4.42-1.836-4.352 1.836q-1.836 1.836-1.836 4.42t1.836 4.352 4.42 1.836q2.652-.068 4.42-1.836t1.768-4.352zm16.184-12.444l0-54.74q0-1.088-.748-1.768t-1.768-.68l-39.78 0q-1.088 0-1.768.748t-.68 1.7l0 54.74q0 1.02.748 1.768t1.7.68l39.78 0q1.02-.068 1.768-.748t.748-1.7zm-14.892-65.892q0-1.224-1.292-1.292l-12.444 0q-1.224.068-1.224 1.292t1.224 1.224l12.444 0q1.292 0 1.292-1.224zm22.372-1.292l0 79.628q0 3.944-2.992 6.936t-7.004 2.992l-39.78 0q-4.012 0-7.004-2.924-2.924-2.924-2.924-7.004l0-79.628q0-4.012 2.924-6.936t7.004-2.992l39.78 0q4.012-.068 7.004 2.924t2.992 7.004z",width:60.013,height:100};const iconPlus={path:"M99.758 43.09l0 13.578q0 2.852-1.984 4.836t-4.836 1.984l-29.45 0l0 29.45q0 2.852-1.984 4.836t-4.836 1.984l-13.578 0q-2.852 0-4.836-1.984t-1.984-4.836l0-29.45l-29.45 0q-2.852 0-4.836-1.984t-1.984-4.836l0-13.578q0-2.852 1.984-4.836t4.836-1.984l29.45 0l0-29.45q0-2.852 1.984-4.836t4.836-1.984l13.578 0q2.852 0 4.836 1.984t1.984 4.836l0 29.45l29.45 0q2.852 0 4.836 1.984t1.984 4.836z",width:100,height:100};const iconTablet={path:"M45.322 90.706q0-1.86-1.302-3.224-1.364-1.364-3.224-1.364t-3.224 1.364-1.302 3.224q0 1.86 1.364 3.224 1.302 1.364 3.162 1.302 1.86.062 3.224-1.302t1.302-3.224zm27.218-11.346l0-68.014q0-.93-.682-1.612t-1.55-.682l-58.962 0q-.93 0-1.612.682t-.682 1.612l0 68.014q0 .93.682 1.612t1.612.62l58.962 0q.992-.062 1.612-.682t.62-1.55zm9.114-68.014l0 77.066q0 4.65-3.348 7.998t-7.998 3.348l-58.962 0q-4.65 0-7.998-3.348t-3.348-7.998l0-77.066q0-4.65 3.348-7.998t7.998-3.348l58.962 0q4.65 0 7.998 3.348t3.348 7.998z",width:81.852,height:100};
|
|
1441
1455
|
|
|
@@ -1447,11 +1461,11 @@ const splitDiff=function(diffEntries){const lines=[];let currentLine=[];_.each(d
|
|
|
1447
1461
|
|
|
1448
1462
|
const statusFor=function(chunk){if(chunk.added){return "added"}if(chunk.removed){return "removed"}return "unchanged"};const splitUpChunk=chunk=>_.map(chunk.value,value=>{return {value:value,status:statusFor(chunk)}});const mapcat=function(lst,fn){return _.flatten(_.map(lst,fn),true)};const ArrayDiff=new JSDiff.Diff;ArrayDiff.tokenize=array=>_.map(array,elem=>[elem]);ArrayDiff.join=(a,b)=>a.concat(b);ArrayDiff.equals=_.isEqual;const flattenChunks=chunks=>mapcat(chunks,splitUpChunk);const stringArrayDiff=function(a,b){const diffResult=ArrayDiff.diff(a,b);const flattened=flattenChunks(diffResult);return {before:_.filter(flattened,entry=>entry.status!=="added"),after:_.filter(flattened,entry=>entry.status!=="removed")}};
|
|
1449
1463
|
|
|
1450
|
-
const{SvgImage: SvgImage$3}=components;const BEFORE$1="before";const AFTER$1="after";const IMAGE_REGEX=/http.*?\.png|web\+graphie[^)]*/g;const imagesInString=function(str){return str.match(IMAGE_REGEX)||[]};const classFor=function(entry,ifAdded,ifRemoved){if(entry.added){return ifAdded}if(entry.removed){return ifRemoved}return ""};class ImageDiffSide extends React.Component{render(){return jsxRuntimeExports.jsx("div",{children:_.map(this.props.images,(entry,index)=>{const className=classNames({image:true,"image-unchanged":entry.status==="unchanged","image-added":entry.status==="added","image-removed":entry.status==="removed"});return jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsx("div",{className:className,children:jsxRuntimeExports.jsx(SvgImage$3,{src:entry.value,title:entry.value})})},index)})})}}ImageDiffSide.propTypes={images:PropTypes.arrayOf(PropTypes.shape({})).isRequired};class TextDiff extends React.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState({collapsed:nextProps.before===nextProps.after});}render(){const diffed=JSDiff.diffWords(this.props.before,this.props.after);const lines=splitDiff(diffed);const beforeImages=imagesInString(this.props.before);const afterImages=imagesInString(this.props.after);const images=stringArrayDiff(beforeImages,afterImages);const renderedLines=_.map(lines,line=>{const contents={};contents.before=_(line).map(function(entry,i){return jsxRuntimeExports.jsx("span",{className:classFor(entry,"not-present","removed dark"),children:entry.value},i)});contents.after=_(line).map(function(entry,i){return jsxRuntimeExports.jsx("span",{className:classFor(entry,"added dark","not-present"),children:entry.value},i)});return contents});const className=classNames({"diff-row":true,collapsed:this.state.collapsed});return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:"diff-header",children:this.props.title}),jsxRuntimeExports.jsx("div",{className:"diff-header",children:this.props.title}),jsxRuntimeExports.jsx("div",{className:"diff-body ui-helper-clearfix",children:_.map([BEFORE$1,AFTER$1],(side,index)=>{return jsxRuntimeExports.jsxs("div",{className:"diff-row "+side,children:[!this.state.collapsed&&_.map(renderedLines,(line,lineNum)=>{const changed=line[side].length>1;const lineClass=classNames({"diff-line":true,added:side===AFTER$1&&changed,removed:side===BEFORE$1&&changed});return jsxRuntimeExports.jsx("div",{className:lineClass,children:line[side]},lineNum)}),!this.state.collapsed&&jsxRuntimeExports.jsx(ImageDiffSide,{images:images[side]})]},index)})}),_.map([BEFORE$1,AFTER$1],(side,index)=>{return jsxRuntimeExports.jsx("div",{className:className+" "+side,onClick:this.handleExpand,children:this.state.collapsed&&jsxRuntimeExports.jsx("span",{children:jsxRuntimeExports.jsxs("span",{className:"expand-button",children:[" ","[ show unmodified ]"," "]})})},index)})]})}constructor(...args){super(...args),this.state={collapsed:this.props.before===this.props.after},this.handleExpand=()=>{this.setState({collapsed:false});};}}TextDiff.propTypes={after:PropTypes.string,before:PropTypes.string,title:PropTypes.string.isRequired};TextDiff.defaultProps={after:"",before:""};
|
|
1464
|
+
const{SvgImage: SvgImage$3}=components;const BEFORE$1="before";const AFTER$1="after";const IMAGE_REGEX=/http.*?\.png|web\+graphie[^)]*/g;const imagesInString=function(str){return str.match(IMAGE_REGEX)||[]};const classFor=function(entry,ifAdded,ifRemoved){if(entry.added){return ifAdded}if(entry.removed){return ifRemoved}return ""};class ImageDiffSide extends React.Component{render(){return jsxRuntimeExports.jsx("div",{children:_.map(this.props.images,(entry,index)=>{const className=classNames({image:true,"image-unchanged":entry.status==="unchanged","image-added":entry.status==="added","image-removed":entry.status==="removed"});return jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsx("div",{className:className,children:jsxRuntimeExports.jsx(SvgImage$3,{src:entry.value,title:entry.value,allowZoom:false})})},index)})})}}ImageDiffSide.propTypes={images:PropTypes.arrayOf(PropTypes.shape({})).isRequired};class TextDiff extends React.Component{UNSAFE_componentWillReceiveProps(nextProps){this.setState({collapsed:nextProps.before===nextProps.after});}render(){const diffed=JSDiff.diffWords(this.props.before,this.props.after);const lines=splitDiff(diffed);const beforeImages=imagesInString(this.props.before);const afterImages=imagesInString(this.props.after);const images=stringArrayDiff(beforeImages,afterImages);const renderedLines=_.map(lines,line=>{const contents={};contents.before=_(line).map(function(entry,i){return jsxRuntimeExports.jsx("span",{className:classFor(entry,"not-present","removed dark"),children:entry.value},i)});contents.after=_(line).map(function(entry,i){return jsxRuntimeExports.jsx("span",{className:classFor(entry,"added dark","not-present"),children:entry.value},i)});return contents});const className=classNames({"diff-row":true,collapsed:this.state.collapsed});return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:"diff-header",children:this.props.title}),jsxRuntimeExports.jsx("div",{className:"diff-header",children:this.props.title}),jsxRuntimeExports.jsx("div",{className:"diff-body ui-helper-clearfix",children:_.map([BEFORE$1,AFTER$1],(side,index)=>{return jsxRuntimeExports.jsxs("div",{className:"diff-row "+side,children:[!this.state.collapsed&&_.map(renderedLines,(line,lineNum)=>{const changed=line[side].length>1;const lineClass=classNames({"diff-line":true,added:side===AFTER$1&&changed,removed:side===BEFORE$1&&changed});return jsxRuntimeExports.jsx("div",{className:lineClass,children:line[side]},lineNum)}),!this.state.collapsed&&jsxRuntimeExports.jsx(ImageDiffSide,{images:images[side]})]},index)})}),_.map([BEFORE$1,AFTER$1],(side,index)=>{return jsxRuntimeExports.jsx("div",{className:className+" "+side,onClick:this.handleExpand,children:this.state.collapsed&&jsxRuntimeExports.jsx("span",{children:jsxRuntimeExports.jsxs("span",{className:"expand-button",children:[" ","[ show unmodified ]"," "]})})},index)})]})}constructor(...args){super(...args),this.state={collapsed:this.props.before===this.props.after},this.handleExpand=()=>{this.setState({collapsed:false});};}}TextDiff.propTypes={after:PropTypes.string,before:PropTypes.string,title:PropTypes.string.isRequired};TextDiff.defaultProps={after:"",before:""};
|
|
1451
1465
|
|
|
1452
1466
|
const UNCHANGED$1="unchanged";const CHANGED="changed";const ADDED="added";const REMOVED="removed";const valueEntry=function(before,after,key){let status;if(before===after){status=UNCHANGED$1;}else if(before===undefined){status=ADDED;}else if(after===undefined){status=REMOVED;}else {status=CHANGED;}return {after:JSON.stringify(after),before:JSON.stringify(before),children:[],key:key,status:status}};const objectEntry=function(before,after,key){const beforeKeys=_.isObject(before)?_(before).keys():[];const afterKeys=_.isObject(after)?_(after).keys():[];const keys=_.union(beforeKeys,afterKeys);const children=_.map(keys,function(key){return performDiff((before||{})[key],(after||{})[key],key)});let status;if(before===undefined){status=ADDED;}else if(after===undefined){status=REMOVED;}else {const changed=_.any(children,function(child){return child.status!==UNCHANGED$1});status=changed?CHANGED:UNCHANGED$1;}return {after:"",before:"",children:children,key:key,status:status}};const performDiff=function(before,after,key){if(typeof before==="object"||typeof after==="object"){return objectEntry(before,after,key)}return valueEntry(before,after,key)};
|
|
1453
1467
|
|
|
1454
|
-
const{SvgImage: SvgImage$2}=components;const indentationFromDepth=function(depth){return (depth-1)*20};const BEFORE="before";const AFTER="after";const UNCHANGED="unchanged";class DiffSide extends React.Component{render(){const className=classNames(this.props.className,{"diff-row":true,before:this.props.side===BEFORE,after:this.props.side===AFTER});return jsxRuntimeExports.jsx("div",{className:className,children:jsxRuntimeExports.jsxs("div",{style:{paddingLeft:indentationFromDepth(this.props.depth)},children:[this.props.showKey&&this.props.propKey+": ",jsxRuntimeExports.jsx("span",{className:"inner-value dark "+this.props.className,children:this.props.value})]})})}}DiffSide.propTypes={className:PropTypes.string.isRequired,depth:PropTypes.number.isRequired,propKey:PropTypes.string.isRequired,showKey:PropTypes.bool.isRequired,side:PropTypes.oneOf([BEFORE,AFTER]).isRequired,value:PropTypes.string};class CollapsedRow extends React.Component{render(){const self=this;return jsxRuntimeExports.jsx("div",{onClick:self.props.onClick,style:{clear:"both"},children:_.map([BEFORE,AFTER],function(side){return jsxRuntimeExports.jsx("div",{className:"diff-row collapsed "+side,children:jsxRuntimeExports.jsx("div",{style:{paddingLeft:indentationFromDepth(self.props.depth)},children:jsxRuntimeExports.jsx("span",{children:" [ show unmodified ] "})})},side)})})}}CollapsedRow.propTypes={depth:PropTypes.number,onClick:PropTypes.func.isRequired};CollapsedRow.defaultProps={depth:0};class DiffEntry extends React.Component{render(){const entry=this.props.entry;const propertyDeleted=entry.status==="removed";const propertyAdded=entry.status==="added";const propertyChanged=entry.status==="changed";const hasChildren=entry.children.length>0;const leftClass=classNames({removed:propertyDeleted||propertyChanged&&!hasChildren,dark:propertyDeleted,"blank-space":propertyAdded});const rightClass=classNames({added:propertyAdded||propertyChanged&&!hasChildren,dark:propertyAdded,"blank-space":propertyDeleted});let shownChildren;if(this.state.expanded){shownChildren=entry.children;}else {shownChildren=_(entry.children).select(function(child){return child.status!==UNCHANGED});}let collapsed=shownChildren.length<entry.children.length;if(entry.children.length===shownChildren.length+1){shownChildren=entry.children;collapsed=false;}const self=this;return jsxRuntimeExports.jsxs("div",{children:[entry.key&&jsxRuntimeExports.jsxs("div",{style:{clear:"both"},children:[jsxRuntimeExports.jsx(DiffSide,{side:BEFORE,className:leftClass,depth:this.props.depth,propKey:entry.key,showKey:!propertyAdded,value:entry.before}),jsxRuntimeExports.jsx(DiffSide,{side:AFTER,className:rightClass,depth:this.props.depth,propKey:entry.key,showKey:!propertyDeleted,value:entry.after})]}),_.map(shownChildren,function(child){return jsxRuntimeExports.jsx(DiffEntry,{depth:self.props.depth+1,entry:child,expanded:self.state.expanded},child.key)}),collapsed&&jsxRuntimeExports.jsx(CollapsedRow,{depth:this.props.depth+1,onClick:this.expand})]})}constructor(...args){super(...args),this.state={expanded:this.props.expanded},this.expand=()=>{this.setState({expanded:true});};}}DiffEntry.propTypes={depth:PropTypes.number,entry:PropTypes.shape({after:PropTypes.string,before:PropTypes.string,children:PropTypes.arrayOf(PropTypes.any),key:PropTypes.string}),expanded:PropTypes.bool};DiffEntry.defaultProps={depth:0};class ImageWidgetDiff extends React.Component{render(){const{before,after}=this.props;const beforeSrc=before.options&&before.options.backgroundImage?before.options.backgroundImage.url:"";const afterSrc=after.options&&after.options.backgroundImage?after.options.backgroundImage.url:"";return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:"diff-row before",children:beforeSrc&&jsxRuntimeExports.jsx("div",{className:classNames({image:true,"image-unchanged":beforeSrc===afterSrc,"image-removed":beforeSrc!==afterSrc}),children:jsxRuntimeExports.jsx(SvgImage$2,{src:beforeSrc,title:beforeSrc})})}),jsxRuntimeExports.jsx("div",{className:"diff-row after",children:afterSrc&&jsxRuntimeExports.jsx("div",{className:classNames({image:true,"image-unchanged":beforeSrc===afterSrc,"image-added":beforeSrc!==afterSrc}),children:jsxRuntimeExports.jsx(SvgImage$2,{src:afterSrc,title:afterSrc})})})]})}}ImageWidgetDiff.propTypes={after:PropTypes.shape({options:PropTypes.objectOf(PropTypes.any)}).isRequired,before:PropTypes.shape({options:PropTypes.objectOf(PropTypes.any)}).isRequired};class WidgetDiff extends React.Component{render(){const{after,before,title,type}=this.props;const diff=performDiff(before,after);return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:"diff-header",children:title}),jsxRuntimeExports.jsx("div",{className:"diff-header",children:title}),jsxRuntimeExports.jsxs("div",{className:"diff-body ui-helper-clearfix",children:[type==="image"&&jsxRuntimeExports.jsx(ImageWidgetDiff,{before:before,after:after}),jsxRuntimeExports.jsx(DiffEntry,{entry:diff})]})]})}}WidgetDiff.propTypes={after:PropTypes.shape({options:PropTypes.objectOf(PropTypes.any)}),before:PropTypes.shape({options:PropTypes.objectOf(PropTypes.any)}),title:PropTypes.string.isRequired,type:PropTypes.string};WidgetDiff.defaultProps={after:{},before:{},type:""};
|
|
1468
|
+
const{SvgImage: SvgImage$2}=components;const indentationFromDepth=function(depth){return (depth-1)*20};const BEFORE="before";const AFTER="after";const UNCHANGED="unchanged";class DiffSide extends React.Component{render(){const className=classNames(this.props.className,{"diff-row":true,before:this.props.side===BEFORE,after:this.props.side===AFTER});return jsxRuntimeExports.jsx("div",{className:className,children:jsxRuntimeExports.jsxs("div",{style:{paddingLeft:indentationFromDepth(this.props.depth)},children:[this.props.showKey&&this.props.propKey+": ",jsxRuntimeExports.jsx("span",{className:"inner-value dark "+this.props.className,children:this.props.value})]})})}}DiffSide.propTypes={className:PropTypes.string.isRequired,depth:PropTypes.number.isRequired,propKey:PropTypes.string.isRequired,showKey:PropTypes.bool.isRequired,side:PropTypes.oneOf([BEFORE,AFTER]).isRequired,value:PropTypes.string};class CollapsedRow extends React.Component{render(){const self=this;return jsxRuntimeExports.jsx("div",{onClick:self.props.onClick,style:{clear:"both"},children:_.map([BEFORE,AFTER],function(side){return jsxRuntimeExports.jsx("div",{className:"diff-row collapsed "+side,children:jsxRuntimeExports.jsx("div",{style:{paddingLeft:indentationFromDepth(self.props.depth)},children:jsxRuntimeExports.jsx("span",{children:" [ show unmodified ] "})})},side)})})}}CollapsedRow.propTypes={depth:PropTypes.number,onClick:PropTypes.func.isRequired};CollapsedRow.defaultProps={depth:0};class DiffEntry extends React.Component{render(){const entry=this.props.entry;const propertyDeleted=entry.status==="removed";const propertyAdded=entry.status==="added";const propertyChanged=entry.status==="changed";const hasChildren=entry.children.length>0;const leftClass=classNames({removed:propertyDeleted||propertyChanged&&!hasChildren,dark:propertyDeleted,"blank-space":propertyAdded});const rightClass=classNames({added:propertyAdded||propertyChanged&&!hasChildren,dark:propertyAdded,"blank-space":propertyDeleted});let shownChildren;if(this.state.expanded){shownChildren=entry.children;}else {shownChildren=_(entry.children).select(function(child){return child.status!==UNCHANGED});}let collapsed=shownChildren.length<entry.children.length;if(entry.children.length===shownChildren.length+1){shownChildren=entry.children;collapsed=false;}const self=this;return jsxRuntimeExports.jsxs("div",{children:[entry.key&&jsxRuntimeExports.jsxs("div",{style:{clear:"both"},children:[jsxRuntimeExports.jsx(DiffSide,{side:BEFORE,className:leftClass,depth:this.props.depth,propKey:entry.key,showKey:!propertyAdded,value:entry.before}),jsxRuntimeExports.jsx(DiffSide,{side:AFTER,className:rightClass,depth:this.props.depth,propKey:entry.key,showKey:!propertyDeleted,value:entry.after})]}),_.map(shownChildren,function(child){return jsxRuntimeExports.jsx(DiffEntry,{depth:self.props.depth+1,entry:child,expanded:self.state.expanded},child.key)}),collapsed&&jsxRuntimeExports.jsx(CollapsedRow,{depth:this.props.depth+1,onClick:this.expand})]})}constructor(...args){super(...args),this.state={expanded:this.props.expanded},this.expand=()=>{this.setState({expanded:true});};}}DiffEntry.propTypes={depth:PropTypes.number,entry:PropTypes.shape({after:PropTypes.string,before:PropTypes.string,children:PropTypes.arrayOf(PropTypes.any),key:PropTypes.string}),expanded:PropTypes.bool};DiffEntry.defaultProps={depth:0};class ImageWidgetDiff extends React.Component{render(){const{before,after}=this.props;const beforeSrc=before.options&&before.options.backgroundImage?before.options.backgroundImage.url:"";const afterSrc=after.options&&after.options.backgroundImage?after.options.backgroundImage.url:"";return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:"diff-row before",children:beforeSrc&&jsxRuntimeExports.jsx("div",{className:classNames({image:true,"image-unchanged":beforeSrc===afterSrc,"image-removed":beforeSrc!==afterSrc}),children:jsxRuntimeExports.jsx(SvgImage$2,{src:beforeSrc,title:beforeSrc,allowZoom:false})})}),jsxRuntimeExports.jsx("div",{className:"diff-row after",children:afterSrc&&jsxRuntimeExports.jsx("div",{className:classNames({image:true,"image-unchanged":beforeSrc===afterSrc,"image-added":beforeSrc!==afterSrc}),children:jsxRuntimeExports.jsx(SvgImage$2,{src:afterSrc,title:afterSrc,allowZoom:false})})})]})}}ImageWidgetDiff.propTypes={after:PropTypes.shape({options:PropTypes.objectOf(PropTypes.any)}).isRequired,before:PropTypes.shape({options:PropTypes.objectOf(PropTypes.any)}).isRequired};class WidgetDiff extends React.Component{render(){const{after,before,title,type}=this.props;const diff=performDiff(before,after);return jsxRuntimeExports.jsxs("div",{children:[jsxRuntimeExports.jsx("div",{className:"diff-header",children:title}),jsxRuntimeExports.jsx("div",{className:"diff-header",children:title}),jsxRuntimeExports.jsxs("div",{className:"diff-body ui-helper-clearfix",children:[type==="image"&&jsxRuntimeExports.jsx(ImageWidgetDiff,{before:before,after:after}),jsxRuntimeExports.jsx(DiffEntry,{entry:diff})]})]})}}WidgetDiff.propTypes={after:PropTypes.shape({options:PropTypes.objectOf(PropTypes.any)}),before:PropTypes.shape({options:PropTypes.objectOf(PropTypes.any)}),title:PropTypes.string.isRequired,type:PropTypes.string};WidgetDiff.defaultProps={after:{},before:{},type:""};
|
|
1455
1469
|
|
|
1456
1470
|
const filterWidgetInfo=function(widgetInfo,showAlignmentOptions){const{alignment,graded,options,type}=widgetInfo||{};const filteredWidgetInfo={options};if(showAlignmentOptions&&CoreWidgetRegistry.getSupportedAlignments(type).length>1){filteredWidgetInfo.alignment=alignment;}if(type==="transformer"){filteredWidgetInfo.graded=graded;}if(Widgets.supportsStaticMode(type)){filteredWidgetInfo.static=widgetInfo?.static??undefined;}return filteredWidgetInfo};class RendererDiff extends React.Component{render(){const{after,before,showAlignmentOptions,showSeparator,title}=this.props;let textDiff;let widgetsDiff;if(before.content||after.content){textDiff=jsxRuntimeExports.jsx(TextDiff,{before:before.content,after:after.content,title:title});}const beforeWidgets=Object.keys(before.widgets??{}).filter(widget=>before.content.includes(widget));const afterWidgets=Object.keys(after.widgets??{}).filter(widget=>after.content.includes(widget));if(beforeWidgets.length||afterWidgets.length){const widgets=_.union(beforeWidgets,afterWidgets);widgetsDiff=widgets.map(widget=>jsxRuntimeExports.jsx(WidgetDiff,{before:filterWidgetInfo(before.widgets?.[widget],showAlignmentOptions),after:filterWidgetInfo(after.widgets?.[widget],showAlignmentOptions),title:widget,type:(before.widgets?.[widget]??{}).type||(after.widgets?.[widget]??{}).type},widget));}return jsxRuntimeExports.jsxs("div",{children:[textDiff,widgetsDiff,showSeparator&&jsxRuntimeExports.jsx("div",{className:"diff-separator"})]})}}RendererDiff.defaultProps={after:{content:"",images:{},widgets:{}},before:{content:"",images:{},widgets:{}},showAlignmentOptions:false,showSeparator:false};
|
|
1457
1471
|
|
|
@@ -1461,23 +1475,9 @@ const itemProps=PropTypes.shape({question:PropTypes.shape({}).isRequired,answerA
|
|
|
1461
1475
|
|
|
1462
1476
|
const{InfoTip: InfoTip$q,InlineIcon: InlineIcon$2}=components;class HintEditor extends React.Component{render(){return jsxRuntimeExports.jsxs("div",{className:"perseus-hint-editor "+this.props.className,children:[this.props.showTitle&&jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Hint"}),jsxRuntimeExports.jsx(Editor,{ref:this.editor,apiOptions:this.props.apiOptions,widgets:this.props.widgets||undefined,content:this.props.content||undefined,images:this.props.images,replace:this.props.replace,placeholder:"Type your hint here...",imageUploader:this.props.imageUploader,onChange:this.props.onChange,widgetIsOpen:this.props.widgetIsOpen},this.props.itemId),jsxRuntimeExports.jsxs("div",{className:"hint-controls-container clearfix",children:[this.props.showMoveButtons&&jsxRuntimeExports.jsxs("span",{className:"reorder-hints",children:[jsxRuntimeExports.jsx("button",{type:"button",className:this.props.isLast?"hidden":"",onClick:_.partial(this.props.onMove,1),children:jsxRuntimeExports.jsx(InlineIcon$2,{...iconCircleArrowDown})})," ",jsxRuntimeExports.jsx("button",{type:"button",className:this.props.isFirst?"hidden":"",onClick:_.partial(this.props.onMove,-1),children:jsxRuntimeExports.jsx(InlineIcon$2,{...iconCircleArrowUp})})," ",this.props.isLast&&jsxRuntimeExports.jsx(InfoTip$q,{children:jsxRuntimeExports.jsx("p",{children:"The last hint is automatically bolded."})})]}),jsxRuntimeExports.jsx("input",{type:"checkbox",checked:this.props.replace,onChange:this.handleChange}),"Replace previous hint",this.props.showRemoveButton&&jsxRuntimeExports.jsxs("button",{type:"button",className:"remove-hint simple-button orange",onClick:this.props.onRemove,children:[jsxRuntimeExports.jsx(InlineIcon$2,{...iconTrash}),"Remove this hint"," "]})]})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.handleChange=e=>{this.props.onChange({replace:e.target.checked});},this.focus=()=>{this.editor.current?.focus();},this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()},this.serialize=options=>{return this.editor.current?.serialize(options)};}}HintEditor.defaultProps={className:"",content:"",replace:false,showMoveButtons:true,showTitle:true,showRemoveButton:true};class CombinedHintEditor extends React.Component{componentDidMount(){this.updatePreview();}componentDidUpdate(){this.updatePreview();}render(){const isMobile=this.props.deviceType==="phone"||this.props.deviceType==="tablet";return jsxRuntimeExports.jsxs("div",{className:"perseus-combined-hint-editor "+"perseus-editor-row",children:[jsxRuntimeExports.jsx("div",{className:"perseus-editor-left-cell",children:jsxRuntimeExports.jsx(HintEditor,{ref:this.editor,itemId:this.props.itemId,isFirst:this.props.isFirst,isLast:this.props.isLast,widgets:this.props.hint.widgets,content:this.props.hint.content,images:this.props.hint.images,replace:this.props.hint.replace,imageUploader:this.props.imageUploader,onChange:this.props.onChange,onRemove:this.props.onRemove,onMove:this.props.onMove,apiOptions:this.props.apiOptions,widgetIsOpen:this.props.widgetIsOpen})}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell",children:jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.deviceType,nochrome:true,children:jsxRuntimeExports.jsx(IframeContentRenderer,{ref:this.frame,datasetKey:"mobile",datasetValue:isMobile,seamless:true,url:this.props.previewURL})})})]})}constructor(...args){super(...args),this.editor=React.createRef(),this.frame=React.createRef(),this.updatePreview=()=>{const shouldBold=this.props.isLast&&!/\*\*/.test(this.props.hint.content);this.frame.current?.sendNewData({type:"hint",data:{hint:this.props.hint,bold:shouldBold,pos:this.props.pos,apiOptions:this.props.apiOptions,linterContext:{contentType:"hint",highlightLint:this.props.highlightLint,paths:this.props.contentPaths}}});},this.getSaveWarnings=()=>{return this.editor.current?.getSaveWarnings()},this.serialize=options=>{return this.editor.current?.serialize(options)},this.focus=()=>{this.editor.current?.focus();};}}CombinedHintEditor.defaultProps={highlightLint:false};class CombinedHintsEditor extends React.Component{render(){const{itemId,hints}=this.props;const editingDisabled=this.props.apiOptions?.editingDisabled??false;const hintElems=_.map(hints,function(hint,i){return jsxRuntimeExports.jsx("fieldset",{disabled:editingDisabled,children:jsxRuntimeExports.jsx(CombinedHintEditor,{ref:"hintEditor"+i,isFirst:i===0,isLast:i+1===hints.length,itemId:itemId,hint:hint,pos:i,imageUploader:this.props.imageUploader,onChange:this.handleHintChange.bind(this,i),onRemove:this.handleHintRemove.bind(this,i),onMove:this.handleHintMove.bind(this,i),deviceType:this.props.deviceType,apiOptions:this.props.apiOptions,highlightLint:this.props.highlightLint,previewURL:this.props.previewURL,contentPaths:[],widgetIsOpen:this.props.widgetIsOpen})},"hintEditor"+i)},this);return jsxRuntimeExports.jsxs("div",{className:"perseus-hints-editor perseus-editor-table",children:[hintElems,jsxRuntimeExports.jsx("div",{className:"perseus-editor-row",children:jsxRuntimeExports.jsx("div",{className:"add-hint-container perseus-editor-left-cell",children:jsxRuntimeExports.jsxs("button",{type:"button",className:"add-hint simple-button orange",disabled:editingDisabled,onClick:this.addHint,children:[jsxRuntimeExports.jsx(InlineIcon$2,{...iconPlus})," Add a hint"]})})})]})}constructor(...args){super(...args),this.handleHintChange=(i,newProps,cb,silent)=>{const hints=[...this.props.hints];hints[i]=_.extend({},this.serializeHint(i,{keepDeletedWidgets:true}),newProps);this.props.onChange({hints:hints},cb,silent);},this.handleHintRemove=i=>{if(!confirm("Are you sure you want to delete this hint?")){return}const hints=[...this.props.hints];hints.splice(i,1);this.props.onChange({hints:hints});},this.handleHintMove=(i,dir)=>{const hints=[...this.props.hints];const hint=hints.splice(i,1)[0];hints.splice(i+dir,0,hint);this.props.onChange({hints:hints},()=>{this.refs["hintEditor"+(i+dir)].focus();});},this.addHint=()=>{const hint={content:"",images:{},widgets:{}};const hints=[...this.props.hints,hint];this.props.onChange({hints:hints},()=>{const i=hints.length-1;this.refs["hintEditor"+i].focus();});},this.getSaveWarnings=()=>{return _.chain(this.props.hints).map((hint,i)=>{return _.map(this.refs["hintEditor"+i].getSaveWarnings(),issue=>"Hint "+(i+1)+": "+issue)}).flatten(true).value()},this.serialize=options=>{return this.props.hints.map((hint,i)=>{return this.serializeHint(i,options)})},this.serializeHint=(index,options)=>{return this.refs["hintEditor"+index].serialize(options)};}}CombinedHintsEditor.HintEditor=HintEditor;CombinedHintsEditor.defaultProps={onChange:()=>{},hints:[],highlightLint:false};
|
|
1463
1477
|
|
|
1464
|
-
const IMAGE_MARKDOWN_REGEX=/!\[[^\]]*\]\([^)]+\)/g;function getFirstAvailableWidgetIndex(widgetType,widgets){const widgetNames=Object.keys(widgets);for(let i=1;i<=widgetNames.length+1;i++){if(!widgetNames.includes(`${widgetType} ${i}`)){return i}}return 1}async function convertImageMarkdownToImageWidget(question,onEditorChange){const{content,widgets}=question;const newWidgets={...widgets};const matches=Array.from(content.matchAll(IMAGE_MARKDOWN_REGEX));if(matches.length===0){return}const replacements=[];for(const match of matches){const imageIndex=getFirstAvailableWidgetIndex("image",newWidgets);const imageNode=PerseusMarkdown.parse(match[0],{});const imageUrl=imageNode[0].content[0].target;const imageAlt=imageNode[0].content[0].alt;const imageSize=await Util.getImageSizeModern(imageUrl);const[width,height]=imageSize;newWidgets[`image ${imageIndex}`]=generateImageWidget({options:generateImageOptions({backgroundImage:{url:imageUrl,width,height},alt:imageAlt})});replacements.push({original:match[0],replacement:`[[☃ image ${imageIndex}]]`});}let newContent=content;for(const{original,replacement}of replacements){newContent=newContent.replace(original,replacement);}onEditorChange({content:newContent,widgets:newWidgets});}function getCtaForIssueId(issueId,question,onEditorChange){switch(issueId){case "image-markdown":return {label:"Convert all image markdown to widget",onClick:()=>convertImageMarkdownToImageWidget(question,onEditorChange)};default:return null}}
|
|
1465
|
-
|
|
1466
|
-
const defaultItemEditorContext={question:{content:"",widgets:{},images:{}},onEditorChange:()=>{}};const ItemEditorContext=React.createContext(defaultItemEditorContext);function useItemEditorContext(){return React.useContext(ItemEditorContext)}
|
|
1467
|
-
|
|
1468
|
-
const IssueCta=({issue})=>{const{question,onEditorChange}=useItemEditorContext();const cta=getCtaForIssueId(issue.id,question,onEditorChange);if(!cta){return null}return jsxRuntimeExports.jsx(Button,{size:"small",onClick:cta.onClick,style:styles$S.button,children:cta.label},issue.id)};const styles$S={button:{marginTop:sizing.size_080,marginBottom:sizing.size_080}};
|
|
1469
|
-
|
|
1470
|
-
const PerseusEditorAccordion=props=>{const{animated,children,header,expanded,containerStyle,panelStyle,headerStyle,onToggle}=props;return jsxRuntimeExports.jsx(View,{className:"perseus-editor-accordion",children:jsxRuntimeExports.jsx(AccordionSection,{animated:animated,expanded:expanded,onToggle:onToggle,style:[styles$R.container,containerStyle],headerStyle:[styles$R.accordionHeader,headerStyle],header:header,children:jsxRuntimeExports.jsx(View,{style:[styles$R.accordionPanel,panelStyle],children:children})})})};const styles$R=StyleSheet.create({container:{backgroundColor:semanticColor.core.background.instructive.subtle,marginTop:spacing.xSmall_8},accordionHeader:{padding:spacing.small_12,paddingInlineEnd:0,height:spacing.xxLarge_48},accordionPanel:{paddingTop:spacing.xxSmall_6,paddingBottom:spacing.xxxSmall_4,paddingLeft:spacing.small_12,paddingRight:spacing.small_12}});
|
|
1471
|
-
|
|
1472
|
-
const IssueDetails=({apiOptions,issue})=>{const[expanded,setExpanded]=React.useState(false);const toggleVisibility=()=>setExpanded(!expanded);const imageUpgradeFF=isFeatureOn({apiOptions},"image-widget-upgrade");return jsxRuntimeExports.jsxs(PerseusEditorAccordion,{animated:true,expanded:expanded,onToggle:toggleVisibility,containerStyle:{backgroundColor:color.fadedGold8},panelStyle:{backgroundColor:"white"},header:jsxRuntimeExports.jsx(LabelLarge,{style:{textOverflow:"ellipsis",maxWidth:"100%",overflow:"hidden",whiteSpace:"nowrap"},children:`Warning: ${issue.id}`}),children:[jsxRuntimeExports.jsx(LabelSmall,{style:{fontWeight:"bold"},children:"Description:"}),jsxRuntimeExports.jsx("span",{children:issue.description}),jsxRuntimeExports.jsx("a",{href:issue.helpUrl,target:"_blank",rel:"noreferrer",children:issue.help}),jsxRuntimeExports.jsx(LabelSmall,{style:{marginTop:"1em",fontWeight:"bold"},children:"Impact:"}),jsxRuntimeExports.jsxs("span",{style:{fontWeight:"initial"},children:[" ",issue.impact]}),jsxRuntimeExports.jsx(LabelSmall,{style:{marginTop:"1em",fontWeight:"bold"},children:"Issue:"}),jsxRuntimeExports.jsx("span",{children:issue.message}),imageUpgradeFF&&jsxRuntimeExports.jsx(IssueCta,{issue:issue})]})};
|
|
1473
|
-
|
|
1474
|
-
const IssuesPanel=({apiOptions,issues=[]})=>{const[showPanel,setShowPanel]=useState(false);const hasWarnings=issues.length>0;const issuesCount=`${issues.length} issue${issues.length===1?"":"s"}`;const icon=hasWarnings?iconWarning:iconPass;const iconColor=hasWarnings?color.gold:color.green;const togglePanel=()=>{if(hasWarnings){setShowPanel(!showPanel);}};return jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-widget-editor-title",children:[jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-title-id",children:jsxRuntimeExports.jsxs(View,{style:{display:"flex",flexDirection:"row",alignItems:"center",gap:"0.25em"},onClick:togglePanel,children:[jsxRuntimeExports.jsx(ToggleableCaret,{isExpanded:showPanel}),jsxRuntimeExports.jsx("span",{children:"Issues"})]})}),jsxRuntimeExports.jsx(PhosphorIcon,{icon:icon,size:"medium",color:iconColor,testId:`issues-icon-${icon}`,style:{marginRight:"0.25em"}}),issuesCount]}),showPanel&&jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-panel",children:jsxRuntimeExports.jsx("div",{className:"perseus-widget-editor-content",children:issues.map(issue=>jsxRuntimeExports.jsx(IssueDetails,{apiOptions:apiOptions,issue:issue},issue.id))})})]})};
|
|
1475
|
-
|
|
1476
1478
|
const{InfoTip: InfoTip$p}=components;class ItemExtrasEditor extends React.Component{shouldShowFinancialCalculatorOptions(){return this.props.financialCalculatorMonthlyPayment||this.props.financialCalculatorTotalAmount||this.props.financialCalculatorTimeToPayOff}render(){const{editingDisabled}=this.props;return jsxRuntimeExports.jsx("div",{className:"perseus-answer-editor",children:jsxRuntimeExports.jsxs("div",{className:"perseus-answer-options",children:[jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show calculator",disabled:editingDisabled,infoTip:"Use the calculator when completing difficult calculations is NOT the intent of the question. DON’T use the calculator when testing the student’s ability to complete different types of computations.",checked:this.props.calculator,onChange:newCheckedState=>{this.props.onChange({calculator:newCheckedState});}}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show financial calculator",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a financial calculator, e.g., for answering financial questions. Once checked, requires at least one of the three options below to be checked.",checked:this.shouldShowFinancialCalculatorOptions(),onChange:newCheckedState=>{this.props.onChange({financialCalculatorMonthlyPayment:newCheckedState,financialCalculatorTotalAmount:newCheckedState,financialCalculatorTimeToPayOff:newCheckedState});}}),this.shouldShowFinancialCalculatorOptions()&&jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include monthly payment",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a monthly payment calculator; e.g., given a loan amount, interest rate, and term, what is the monthly payment?",checked:this.props.financialCalculatorMonthlyPayment,onChange:newCheckedState=>{this.props.onChange({financialCalculatorMonthlyPayment:newCheckedState});},indent:true}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include total amount",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a total amount calculator; e.g., given a monthly payment, interest rate, and term, what is the total amount to be paid?",checked:this.props.financialCalculatorTotalAmount,onChange:newCheckedState=>{this.props.onChange({financialCalculatorTotalAmount:newCheckedState});},indent:true}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include time-to-pay-off",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a time to pay off calculator; e.g., given a loan amount, interest rate, and monthly payment, how long will it take to pay off the loan?",checked:this.props.financialCalculatorTimeToPayOff,onChange:newCheckedState=>{this.props.onChange({financialCalculatorTimeToPayOff:newCheckedState});},indent:true})]}),jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Show periodic table",disabled:editingDisabled,infoTip:"This provides the student with the ability to view a periodic table of the elements, e.g., for answering chemistry questions.",checked:this.props.periodicTable,onChange:newCheckedState=>{this.props.onChange({periodicTable:newCheckedState,periodicTableWithKey:false});}}),this.props.periodicTable&&jsxRuntimeExports.jsx(ItemExtraCheckbox,{label:"Include key/legend with periodic table",disabled:editingDisabled,infoTip:"Include a key for HS courses; omit for AP chemistry.",checked:this.props.periodicTableWithKey,onChange:newCheckedState=>{this.props.onChange({periodicTableWithKey:newCheckedState});},indent:true})]})})}constructor(...args){super(...args),this.serialize=()=>{const data={...ItemExtrasEditor.defaultProps};for(const key of ItemExtras){data[key]=!!this.props[key];}return data};}}ItemExtrasEditor.defaultProps={calculator:false,financialCalculatorMonthlyPayment:false,financialCalculatorTotalAmount:false,financialCalculatorTimeToPayOff:false,periodicTable:false,periodicTableWithKey:false};const ItemExtraCheckbox=props=>jsxRuntimeExports.jsx(View,{style:[styles$Q.checkbox,props.indent?styles$Q.indented:undefined],children:jsxRuntimeExports.jsx(Checkbox$1,{disabled:props.disabled,label:jsxRuntimeExports.jsxs(View,{style:{flexDirection:"row"},children:[props.label," ",jsxRuntimeExports.jsx(InfoTip$p,{children:props.infoTip})]}),checked:props.checked,onChange:newCheckedState=>props.onChange(newCheckedState)})});const styles$Q=StyleSheet.create({indented:{marginInlineStart:spacing.large_24}});
|
|
1477
1479
|
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
class ItemEditor extends React.Component{static getDerivedStateFromProps(props){if(props.question?.content===ItemEditor.prevContent&&props.question?.widgets===ItemEditor.prevWidgets){return null}ItemEditor.prevContent=props.question?.content;ItemEditor.prevWidgets=props.question?.widgets;const parsed=PerseusMarkdown.parse(props.question?.content??"",{});const linterContext={content:props.question?.content,widgets:props.question?.widgets,stack:[]};return {issues:[...props.issues??[],...PerseusLinter.runLinter(parsed,linterContext,false)?.map(linterWarning=>{if(linterWarning.rule==="inaccessible-widget"){return WARNINGS.inaccessibleWidget(linterWarning.metadata?.widgetType??"unknown",linterWarning.metadata?.widgetId??"unknown")}return WARNINGS.genericLinterWarning(linterWarning.rule,linterWarning.message)})??[]]}}render(){const isMobile=this.props.deviceType==="phone"||this.props.deviceType==="tablet";const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsx(ItemEditorContext.Provider,{value:{question:this.props.question,onEditorChange:this.handleEditorChange},children:jsxRuntimeExports.jsxs("div",{className:"perseus-editor-table",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row perseus-question-container",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-left-cell",children:[jsxRuntimeExports.jsx(IssuesPanel,{apiOptions:this.props.apiOptions,issues:this.state.issues}),jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Question"}),jsxRuntimeExports.jsx("fieldset",{disabled:editingDisabled,children:jsxRuntimeExports.jsx(Editor,{ref:this.questionEditor,placeholder:"Type your question here...",className:"perseus-question-editor",imageUploader:this.props.imageUploader,onChange:this.handleEditorChange,apiOptions:this.props.apiOptions,showWordCount:true,widgetIsOpen:this.props.widgetIsOpen,additionalTemplates:this.props.additionalTemplates,...this.props.question},this.props.itemId)})]}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell",children:jsxRuntimeExports.jsxs("div",{id:"problemarea",children:[jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.deviceType,nochrome:true,children:jsxRuntimeExports.jsx(IframeContentRenderer,{ref:this.frame,datasetKey:"mobile",datasetValue:isMobile,seamless:true,url:this.props.previewURL},this.props.deviceType)}),jsxRuntimeExports.jsx("div",{id:"hintsarea",className:"hintsarea",style:{display:"none"}})]})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row perseus-answer-container",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-left-cell",children:[jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Question extras"}),jsxRuntimeExports.jsx(ItemExtrasEditor,{ref:this.itemExtrasEditor,onChange:this.handleItemExtrasChange,editingDisabled:editingDisabled,...this.props.answerArea})]}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell"})]})]})})}constructor(...args){super(...args),this.frame=React.createRef(),this.questionEditor=React.createRef(),this.itemExtrasEditor=React.createRef(),this.state={issues:[]},this.updateProps=(newProps,cb,silent)=>{const props=_(this.props).pick("question","answerArea");this.props.onChange(_(props).extend(newProps),cb,silent);},this.triggerPreviewUpdate=newData=>{this.frame.current?.sendNewData(newData);},this.handleEditorChange=(newProps,cb,silent)=>{const question=_.extend({},this.props.question,newProps);this.updateProps({question},cb,silent);},this.handleItemExtrasChange=newProps=>{const answerArea=_.extend({},this.props.answerArea,newProps);this.updateProps({answerArea},()=>{},true);},this.getSaveWarnings=()=>{return this.questionEditor.current?.getSaveWarnings()},this.serialize=options=>{return {question:this.questionEditor.current?.serialize(options),answerArea:this.itemExtrasEditor.current?.serialize()}};}}ItemEditor.defaultProps={onChange:()=>{},question:{},answerArea:{}};
|
|
1480
|
+
class ItemEditor extends React.Component{static getDerivedStateFromProps(props){if(props.question?.content===ItemEditor.prevContent&&props.question?.widgets===ItemEditor.prevWidgets){return null}ItemEditor.prevContent=props.question?.content;ItemEditor.prevWidgets=props.question?.widgets;const parsed=PerseusMarkdown.parse(props.question?.content??"",{});const linterContext={content:props.question?.content,widgets:props.question?.widgets,stack:[]};return {issues:[...props.issues??[],...PerseusLinter.runLinter(parsed,linterContext,false)?.map(linterWarning=>{if(linterWarning.rule==="inaccessible-widget"){return WARNINGS.inaccessibleWidget(linterWarning.metadata?.widgetType??"unknown",linterWarning.metadata?.widgetId??"unknown")}return WARNINGS.genericLinterWarning(linterWarning.rule,linterWarning.message,linterWarning.severity)})??[]]}}render(){const isMobile=this.props.deviceType==="phone"||this.props.deviceType==="tablet";const editingDisabled=this.props.apiOptions?.editingDisabled??false;return jsxRuntimeExports.jsx(ItemEditorContext.Provider,{value:{question:this.props.question,onEditorChange:this.handleEditorChange},children:jsxRuntimeExports.jsxs("div",{className:"perseus-editor-table",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row perseus-question-container",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-left-cell",children:[jsxRuntimeExports.jsx(IssuesPanel,{apiOptions:this.props.apiOptions,issues:this.state.issues}),jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Question"}),jsxRuntimeExports.jsx("fieldset",{disabled:editingDisabled,children:jsxRuntimeExports.jsx(Editor,{ref:this.questionEditor,placeholder:"Type your question here...",className:"perseus-question-editor",imageUploader:this.props.imageUploader,onChange:this.handleEditorChange,apiOptions:this.props.apiOptions,showWordCount:true,widgetIsOpen:this.props.widgetIsOpen,additionalTemplates:this.props.additionalTemplates,...this.props.question},this.props.itemId)})]}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell",children:jsxRuntimeExports.jsxs("div",{id:"problemarea",children:[jsxRuntimeExports.jsx(DeviceFramer,{deviceType:this.props.deviceType,nochrome:true,children:jsxRuntimeExports.jsx(IframeContentRenderer,{ref:this.frame,datasetKey:"mobile",datasetValue:isMobile,seamless:true,url:this.props.previewURL},this.props.deviceType)}),jsxRuntimeExports.jsx("div",{id:"hintsarea",className:"hintsarea",style:{display:"none"}})]})})]}),jsxRuntimeExports.jsxs("div",{className:"perseus-editor-row perseus-answer-container",children:[jsxRuntimeExports.jsxs("div",{className:"perseus-editor-left-cell",children:[jsxRuntimeExports.jsx("div",{className:"pod-title",children:"Question extras"}),jsxRuntimeExports.jsx(ItemExtrasEditor,{ref:this.itemExtrasEditor,onChange:this.handleItemExtrasChange,editingDisabled:editingDisabled,...this.props.answerArea})]}),jsxRuntimeExports.jsx("div",{className:"perseus-editor-right-cell"})]})]})})}constructor(...args){super(...args),this.frame=React.createRef(),this.questionEditor=React.createRef(),this.itemExtrasEditor=React.createRef(),this.state={issues:[]},this.updateProps=(newProps,cb,silent)=>{const props=_(this.props).pick("question","answerArea");this.props.onChange(_(props).extend(newProps),cb,silent);},this.triggerPreviewUpdate=newData=>{this.frame.current?.sendNewData(newData);},this.handleEditorChange=(newProps,cb,silent)=>{const question=_.extend({},this.props.question,newProps);this.updateProps({question},cb,silent);},this.handleItemExtrasChange=newProps=>{const answerArea=_.extend({},this.props.answerArea,newProps);this.updateProps({answerArea},()=>{},true);},this.getSaveWarnings=()=>{return this.questionEditor.current?.getSaveWarnings()},this.serialize=options=>{return {question:this.questionEditor.current?.serialize(options),answerArea:this.itemExtrasEditor.current?.serialize()}};}}ItemEditor.defaultProps={onChange:()=>{},question:{},answerArea:{}};
|
|
1481
1481
|
|
|
1482
1482
|
const{HUD}=components;class EditorPage extends React.Component{componentDidMount(){this._isMounted=true;this.updateRenderer();}componentDidUpdate(){setTimeout(()=>{this.updateRenderer();});}componentWillUnmount(){this._isMounted=false;}updateRenderer(){const hasEditor=!this.props.developerMode||!this.props.jsonMode;if(!this._isMounted||!hasEditor){return}const touch=this.props.previewDevice==="phone"||this.props.previewDevice==="tablet";const deviceBasedApiOptions={...this.getApiOptions(),customKeypad:touch,isMobile:touch};this.itemEditor.current?.triggerPreviewUpdate({type:"question",data:_({item:this.serialize(),apiOptions:deviceBasedApiOptions,initialHintsVisible:0,device:this.props.previewDevice,linterContext:{contentType:"exercise",highlightLint:this.state.highlightLint,paths:this.props.contentPaths||[]},reviewMode:true,legacyPerseusLint:this.itemEditor.current?.getSaveWarnings()}).extend(_(this.props).pick("problemNum"))});}getApiOptions(){return {...ApiOptions.defaults,...this.props.apiOptions}}getSaveWarnings(){const issues1=this.itemEditor.current?.getSaveWarnings();const issues2=this.hintsEditor.current?.getSaveWarnings();return issues1.concat(issues2)}serialize(options){if(this.props.jsonMode){return this.state.json}return _.extend(this.itemEditor.current?.serialize(options),{hints:this.hintsEditor.current?.serialize(options)})}render(){let className="framework-perseus";const editingDisabled=this.props.apiOptions?.editingDisabled??false;const touch=this.props.previewDevice==="phone"||this.props.previewDevice==="tablet";const deviceBasedApiOptions={...this.getApiOptions(),customKeypad:touch,isMobile:touch};if(deviceBasedApiOptions.isMobile){className+=" "+ClassNames.MOBILE;}return jsxRuntimeExports.jsx(Dependencies.DependenciesContext.Provider,{value:this.props.dependencies,children:jsxRuntimeExports.jsxs("div",{id:"perseus",className:className,children:[jsxRuntimeExports.jsxs("div",{style:{marginBottom:10},children:[this.props.developerMode&&jsxRuntimeExports.jsxs("span",{children:[jsxRuntimeExports.jsxs("label",{children:[" ","Developer JSON Mode:"," ",jsxRuntimeExports.jsx("input",{type:"checkbox",checked:this.props.jsonMode,disabled:this.props.apiOptions?.editingDisabled,onChange:this.toggleJsonMode})]})," "]}),!this.props.jsonMode&&jsxRuntimeExports.jsx(ViewportResizer,{deviceType:this.props.previewDevice,onViewportSizeChanged:this.props.onPreviewDeviceChange}),!this.props.jsonMode&&jsxRuntimeExports.jsx(HUD,{message:"Style warnings",enabled:this.state.highlightLint,onClick:()=>{this.setState({highlightLint:!this.state.highlightLint});}})]}),this.props.developerMode&&this.props.jsonMode&&jsxRuntimeExports.jsx("div",{children:jsxRuntimeExports.jsx(JsonEditor,{multiLine:true,value:this.state.json,onChange:this.changeJSON,editingDisabled:editingDisabled})}),(!this.props.developerMode||!this.props.jsonMode)&&jsxRuntimeExports.jsx(ItemEditor,{ref:this.itemEditor,itemId:this.props.itemId,question:this.props.question,answerArea:this.props.answerArea,imageUploader:this.props.imageUploader,onChange:this.handleChange,deviceType:this.props.previewDevice,widgetIsOpen:this.state.widgetsAreOpen,apiOptions:deviceBasedApiOptions,previewURL:this.props.previewURL,issues:this.props.issues,additionalTemplates:this.props.additionalTemplates}),(!this.props.developerMode||!this.props.jsonMode)&&jsxRuntimeExports.jsx(CombinedHintsEditor,{ref:this.hintsEditor,itemId:this.props.itemId,hints:this.props.hints,imageUploader:this.props.imageUploader,onChange:this.handleChange,deviceType:this.props.previewDevice,apiOptions:deviceBasedApiOptions,previewURL:this.props.previewURL,highlightLint:this.state.highlightLint,widgetIsOpen:this.state.widgetsAreOpen})]})})}constructor(props){super(props),this.itemEditor=React.createRef(),this.hintsEditor=React.createRef(),this.toggleJsonMode=()=>{this.setState({json:this.serialize({keepDeletedWidgets:true})},()=>{this.props.onChange({jsonMode:!this.props.jsonMode});});},this.handleChange=(toChange,cb,silent)=>{const newProps=_(this.props).pick("question","hints","answerArea");_(newProps).extend(toChange);this.props.onChange(newProps,cb,silent);},this.changeJSON=newJson=>{this.setState({json:newJson});this.props.onChange(newJson);};this.state={json:_.pick(this.props,"question","answerArea","hints"),gradeMessage:"",wasAnswered:false,highlightLint:true,widgetsAreOpen:this.props.widgetsAreOpen??true};this._isMounted=false;}}EditorPage.defaultProps={developerMode:false,jsonMode:false,onChange:()=>{}};
|
|
1483
1483
|
|
|
@@ -1530,7 +1530,7 @@ var styles$J = {"dimensionsContainer":"perseus_4qo24hC2","dimensionsFieldContain
|
|
|
1530
1530
|
|
|
1531
1531
|
function ImageDimensionsInput({backgroundImage,onChange}){function handleWidthChange(newWidth){const newHeight=getOtherSideLengthWithPreservedAspectRatio(backgroundImage.width,backgroundImage.height,Number(newWidth));if(isNaN(newHeight)){return}onChange({backgroundImage:{...backgroundImage,width:Number(newWidth),height:newHeight}});}function handleHeightChange(newHeight){const newWidth=getOtherSideLengthWithPreservedAspectRatio(backgroundImage.height,backgroundImage.width,Number(newHeight));if(isNaN(newWidth)){return}onChange({backgroundImage:{...backgroundImage,height:Number(newHeight),width:newWidth}});}async function handleResetToOriginalSize(){const naturalSize=await Util.getImageSizeModern(backgroundImage.url);const[naturalWidth,naturalHeight]=naturalSize;if(naturalWidth===backgroundImage.width&&naturalHeight===backgroundImage.height){return}onChange({backgroundImage:{...backgroundImage,width:naturalWidth,height:naturalHeight}});}return jsxRuntimeExports.jsxs("div",{className:styles$J.dimensionsContainer,children:[jsxRuntimeExports.jsxs("div",{className:styles$J.dimensionsFieldContainer,children:[jsxRuntimeExports.jsx(LabeledField,{label:"Width",field:jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:backgroundImage.width?.toString()??"",onChange:handleWidthChange}),styles:wbFieldStyles}),jsxRuntimeExports.jsx("span",{className:styles$J.xSpan,children:"x"}),jsxRuntimeExports.jsx(LabeledField,{label:"Height",field:jsxRuntimeExports.jsx(ScrolllessNumberTextField,{value:backgroundImage.height?.toString()??"",onChange:handleHeightChange}),styles:wbFieldStyles})]}),jsxRuntimeExports.jsx(Button,{kind:"tertiary",size:"small",startIcon:arrowCounterClockwise,onClick:handleResetToOriginalSize,children:"Reset to original size"})]})}
|
|
1532
1532
|
|
|
1533
|
-
const{SvgImage: SvgImage$1}=components;const MIN_ALT_TEXT_LENGTH=8;const MAX_ALT_TEXT_LENGTH=150;const altTextTooLongError="Alt text should not exceed 150 characters. Please pair your alt with a long description below if you need significantly more text to sufficiently describe the image.";const altTextTooShortError="Add more detail to describe your image. While alt text should be brief, it must also describe the image well.";function ImageSettings({alt,backgroundImage,apiOptions,caption,decorative,longDescription,title,onChange}){const imageUpgradeFF=isFeatureOn({apiOptions},"image-widget-upgrade");const[altFieldError,setAltFieldError]=React.useState(null);if(!backgroundImage.url||!backgroundImage.width||!backgroundImage.height){return null}const hasPopulatedFields=Boolean(alt||caption||title||longDescription);function handleAltFieldChange(value){if(value.length===0){setAltFieldError(null);}else if(imageUpgradeFF&&value.length>MAX_ALT_TEXT_LENGTH){setAltFieldError(altTextTooLongError);}else if(value.length>=MIN_ALT_TEXT_LENGTH){setAltFieldError(null);}onChange({alt:value});}function handleAltFieldBlur(value){if(value.length>0&&value.length<MIN_ALT_TEXT_LENGTH){setAltFieldError(altTextTooShortError);}}return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(LabeledField,{label:"Preview",field:jsxRuntimeExports.jsx(SvgImage$1,{src:backgroundImage.url,alt:`Preview: ${alt||"No alt text"}
|
|
1533
|
+
const{SvgImage: SvgImage$1}=components;const MIN_ALT_TEXT_LENGTH=8;const MAX_ALT_TEXT_LENGTH=150;const altTextTooLongError="Alt text should not exceed 150 characters. Please pair your alt with a long description below if you need significantly more text to sufficiently describe the image.";const altTextTooShortError="Add more detail to describe your image. While alt text should be brief, it must also describe the image well.";function ImageSettings({alt,backgroundImage,apiOptions,caption,decorative,longDescription,title,onChange}){const imageUpgradeFF=isFeatureOn({apiOptions},"image-widget-upgrade");const[altFieldError,setAltFieldError]=React.useState(null);if(!backgroundImage.url||!backgroundImage.width||!backgroundImage.height){return null}const hasPopulatedFields=Boolean(alt||caption||title||longDescription);function handleAltFieldChange(value){if(value.length===0){setAltFieldError(null);}else if(imageUpgradeFF&&value.length>MAX_ALT_TEXT_LENGTH){setAltFieldError(altTextTooLongError);}else if(value.length>=MIN_ALT_TEXT_LENGTH){setAltFieldError(null);}onChange({alt:value});}function handleAltFieldBlur(value){if(value.length>0&&value.length<MIN_ALT_TEXT_LENGTH){setAltFieldError(altTextTooShortError);}}return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(LabeledField,{label:"Preview",field:jsxRuntimeExports.jsx(SvgImage$1,{src:backgroundImage.url,alt:`Preview: ${alt||"No alt text"}`,allowZoom:false}),styles:wbFieldStyles}),jsxRuntimeExports.jsx(ImageDimensionsInput,{backgroundImage:backgroundImage,onChange:onChange}),imageUpgradeFF&&jsxRuntimeExports.jsx(DecorativeToggle,{decorative:decorative,hasPopulatedFields:hasPopulatedFields,onChange:onChange}),jsxRuntimeExports.jsx(LabeledField,{label:"Title",field:jsxRuntimeExports.jsx(AutoResizingTextArea,{value:title??"",onChange:value=>onChange({title:value}),disabled:decorative}),styles:wbFieldStyles}),jsxRuntimeExports.jsx(LabeledField,{label:"Alt text",description:"Summarize the image using up to 150 characters.",field:jsxRuntimeExports.jsx(AutoResizingTextArea,{value:alt??"",onBlur:e=>handleAltFieldBlur(e.target.value),onChange:handleAltFieldChange,disabled:decorative}),errorMessage:altFieldError,styles:wbFieldStylesWithDescription}),imageUpgradeFF&&jsxRuntimeExports.jsx(LabeledField,{label:"Long description",field:jsxRuntimeExports.jsx(AutoResizingTextArea,{value:longDescription??"",onChange:value=>onChange({longDescription:value}),disabled:decorative}),styles:wbFieldStyles}),jsxRuntimeExports.jsx(LabeledField,{label:"Caption",field:jsxRuntimeExports.jsx(AutoResizingTextArea,{value:caption??"",onChange:value=>onChange({caption:value}),disabled:decorative}),styles:wbFieldStyles})]})}
|
|
1534
1534
|
|
|
1535
1535
|
const INTERNALLY_HOSTED_DOMAINS="("+"ka-.*.s3.amazonaws.com|"+"(fastly|cdn).kastatic.org|"+"khanacademy.org|"+"kasandbox.org"+")";const INTERNALLY_HOSTED_URL_RE=new RegExp("^(https?|web\\+graphie)://[^/]*"+INTERNALLY_HOSTED_DOMAINS);function ImageUrlInput({backgroundImage,onChange}){const uniqueId=React__default.useId();const urlId=`${uniqueId}-url`;const[urlFieldValue,setUrlFieldValue]=React__default.useState(backgroundImage.url||"");const[backgroundImageError,setBackgroundImageError]=React__default.useState(null);function setUrl(url,width,height){const image={...backgroundImage};image.url=url;image.width=width;image.height=height;const box=[image.width,image.height];onChange({backgroundImage:image,box:box});}async function onUrlChange(url){if(!url){setBackgroundImageError(null);setUrl(url,0,0);return}if(url&&!INTERNALLY_HOSTED_URL_RE.test(url)){setBackgroundImageError("Images must be from sites hosted by Khan Academy. "+"Please input a Khan Academy-owned address, or use the "+"Add Image tool to rehost an existing image");return}setBackgroundImageError(null);try{const size=await Util.getImageSizeModern(url);setUrl(url,size[0],size[1]);}catch(error){setBackgroundImageError(`There was an error loading the image URL: ${JSON.stringify(error,null,2)}`);}}return jsxRuntimeExports.jsx(LabeledField,{label:"Image URL",description:"Paste an image or graphie image URL.",field:jsxRuntimeExports.jsx(TextField,{id:urlId,value:urlFieldValue,onBlur:e=>onUrlChange(e.target.value),onChange:value=>setUrlFieldValue(value)}),errorMessage:backgroundImageError,styles:wbFieldStylesWithDescription})}
|
|
1536
1536
|
|
|
@@ -1729,7 +1729,7 @@ function RadioImageEditor({initialImageUrl,initialImageAltText,containerClassNam
|
|
|
1729
1729
|
function getMovedChoices(choices,hasNoneOfTheAbove,choiceIndex,movement){const newChoices=[...choices];const[removedChoice]=newChoices.splice(choiceIndex,1);switch(movement){case "top":if(choiceIndex===0){return choices}newChoices.unshift(removedChoice);break;case "up":if(choiceIndex===0){return choices}newChoices.splice(choiceIndex-1,0,removedChoice);break;case "down":if(choiceIndex===choices.length-1){return choices}if(choiceIndex===choices.length-2&&hasNoneOfTheAbove){return choices}newChoices.splice(choiceIndex+1,0,removedChoice);break;case "bottom":if(choiceIndex===choices.length-1){return choices}if(hasNoneOfTheAbove){const removedNoneOfTheAbove=newChoices.pop();newChoices.push(removedChoice);if(removedNoneOfTheAbove){newChoices.push(removedNoneOfTheAbove);}}else {newChoices.push(removedChoice);}break}return newChoices}function setImageProxyFromMarkdownContent(markdownContent){const images=[];const parsedMarkdown=PerseusMarkdown.parse(markdownContent,{});PerseusMarkdown.traverseContent(parsedMarkdown,node=>{if(node.type==="image"){images.push({url:node.target||"",altText:node.alt||""});}});let proxiedContent=markdownContent;images.forEach((image,index)=>{const originalPattern=``;const replacement=`![Image ${index+1}]`;const patternIndex=proxiedContent.indexOf(originalPattern);if(patternIndex!==-1){proxiedContent=proxiedContent.substring(0,patternIndex)+replacement+proxiedContent.substring(patternIndex+originalPattern.length);}});return [proxiedContent,images]}function setMarkdownContentFromImageProxy(proxiedContent,images){let markdownContent=proxiedContent;for(let i=0;i<images.length;i++){const image=images[i];markdownContent=markdownContent.replace(`![Image ${i+1}]`,``);}return markdownContent}
|
|
1730
1730
|
|
|
1731
1731
|
const{SvgImage}=components;const RadioOptionContentAndImageEditor=props=>{const{content,choiceIndex,onContentChange,isNoneOfTheAbove}=props;const uniqueId=React.useId();const contentTextAreaId=`${uniqueId}-content-textarea`;const[proxiedContent,setProxiedContent]=React.useState("");const[images,setImages]=React.useState([]);const[addingImage,setAddingImage]=React.useState(false);React.useEffect(()=>{const[proxiedContent,images]=setImageProxyFromMarkdownContent(content??"");setProxiedContent(proxiedContent);setImages(images);},[content]);const handleAddImage=(choiceIndex,imageUrl,imageAltText)=>{const newContent=`${content}
|
|
1732
|
-
`;onContentChange(choiceIndex,newContent);};const handleDeleteImage=imageIndex=>{const substr=`![Image ${imageIndex+1}]`;const newProxiedContent=proxiedContent.replace(substr,"");setProxiedContent(newProxiedContent);const newContent=setMarkdownContentFromImageProxy(newProxiedContent,images);onContentChange(choiceIndex,newContent);};const handleUpdateImage=(imageIndex,url,altText)=>{const newImages=[...images];newImages[imageIndex]={url,altText};setImages(newImages);const newContent=setMarkdownContentFromImageProxy(proxiedContent,newImages);onContentChange(choiceIndex,newContent);};const handleContentChange=(choiceIndex,newProxiedContent)=>{setProxiedContent(newProxiedContent);const newContent=setMarkdownContentFromImageProxy(newProxiedContent,images);onContentChange(choiceIndex,newContent);};const handlePaste=e=>{const imageURL=e.clipboardData.getData("text");if(imageURL.includes("cdn.kastatic.org")||imageURL.includes("graphie")){e.preventDefault();handleAddImage(choiceIndex,imageURL,"");}};const handleDeleteImageConfirmation=imageIndex=>{if(window.confirm("Are you sure you want to delete this image?")){handleDeleteImage(imageIndex);}};if(isNoneOfTheAbove){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(HeadingXSmall,{tag:"label",htmlFor:contentTextAreaId,children:"Content"}),jsxRuntimeExports.jsx(AutoResizingTextArea,{id:contentTextAreaId,value:"None of the above",disabled:true,onChange:()=>{}})]})}return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(HeadingXSmall,{tag:"label",htmlFor:contentTextAreaId,style:{marginBlockEnd:sizing.size_040},children:"Content"}),jsxRuntimeExports.jsx(AutoResizingTextArea,{id:contentTextAreaId,value:proxiedContent,placeholder:"Type a choice here...",onChange:value=>{handleContentChange(choiceIndex,value);},onPaste:handlePaste}),!addingImage&&jsxRuntimeExports.jsx(Button,{startIcon:plusIcon,size:"small",kind:"tertiary",style:{alignSelf:"flex-start"},onClick:()=>{setAddingImage(true);},children:"Add image"}),addingImage&&jsxRuntimeExports.jsx(RadioImageEditor,{initialImageUrl:"",initialImageAltText:"",containerClassName:styles.imageEditorContainer,onSave:(imageUrl,imageAltText)=>{handleAddImage(choiceIndex,imageUrl,imageAltText);},onClose:()=>{setAddingImage(false);}}),images?.map((image,imageIndex)=>jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:`Image ${imageIndex+1}`,expanded:true,containerStyle:{backgroundColor:semanticColor.core.background.base.default,marginBlockStart:sizing.size_040,marginBlockEnd:sizing.size_040},panelStyle:{paddingBlockEnd:sizing.size_120},children:[jsxRuntimeExports.jsx(SvgImage,{src:image.url,alt:`Preview: ${image.altText??"No alt text"}
|
|
1732
|
+
`;onContentChange(choiceIndex,newContent);};const handleDeleteImage=imageIndex=>{const substr=`![Image ${imageIndex+1}]`;const newProxiedContent=proxiedContent.replace(substr,"");setProxiedContent(newProxiedContent);const newContent=setMarkdownContentFromImageProxy(newProxiedContent,images);onContentChange(choiceIndex,newContent);};const handleUpdateImage=(imageIndex,url,altText)=>{const newImages=[...images];newImages[imageIndex]={url,altText};setImages(newImages);const newContent=setMarkdownContentFromImageProxy(proxiedContent,newImages);onContentChange(choiceIndex,newContent);};const handleContentChange=(choiceIndex,newProxiedContent)=>{setProxiedContent(newProxiedContent);const newContent=setMarkdownContentFromImageProxy(newProxiedContent,images);onContentChange(choiceIndex,newContent);};const handlePaste=e=>{const imageURL=e.clipboardData.getData("text");if(imageURL.includes("cdn.kastatic.org")||imageURL.includes("graphie")){e.preventDefault();handleAddImage(choiceIndex,imageURL,"");}};const handleDeleteImageConfirmation=imageIndex=>{if(window.confirm("Are you sure you want to delete this image?")){handleDeleteImage(imageIndex);}};if(isNoneOfTheAbove){return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(HeadingXSmall,{tag:"label",htmlFor:contentTextAreaId,children:"Content"}),jsxRuntimeExports.jsx(AutoResizingTextArea,{id:contentTextAreaId,value:"None of the above",disabled:true,onChange:()=>{}})]})}return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment,{children:[jsxRuntimeExports.jsx(HeadingXSmall,{tag:"label",htmlFor:contentTextAreaId,style:{marginBlockEnd:sizing.size_040},children:"Content"}),jsxRuntimeExports.jsx(AutoResizingTextArea,{id:contentTextAreaId,value:proxiedContent,placeholder:"Type a choice here...",onChange:value=>{handleContentChange(choiceIndex,value);},onPaste:handlePaste}),!addingImage&&jsxRuntimeExports.jsx(Button,{startIcon:plusIcon,size:"small",kind:"tertiary",style:{alignSelf:"flex-start"},onClick:()=>{setAddingImage(true);},children:"Add image"}),addingImage&&jsxRuntimeExports.jsx(RadioImageEditor,{initialImageUrl:"",initialImageAltText:"",containerClassName:styles.imageEditorContainer,onSave:(imageUrl,imageAltText)=>{handleAddImage(choiceIndex,imageUrl,imageAltText);},onClose:()=>{setAddingImage(false);}}),images?.map((image,imageIndex)=>jsxRuntimeExports.jsxs(PerseusEditorAccordion,{header:`Image ${imageIndex+1}`,expanded:true,containerStyle:{backgroundColor:semanticColor.core.background.base.default,marginBlockStart:sizing.size_040,marginBlockEnd:sizing.size_040},panelStyle:{paddingBlockEnd:sizing.size_120},children:[jsxRuntimeExports.jsx(SvgImage,{src:image.url,alt:`Preview: ${image.altText??"No alt text"}`,allowZoom:false}),jsxRuntimeExports.jsx(RadioImageEditor,{initialImageUrl:image.url,initialImageAltText:image.altText,onSave:(imageUrl,imageAltText)=>{handleUpdateImage(imageIndex,imageUrl,imageAltText);},onDelete:()=>{handleDeleteImageConfirmation(imageIndex);}})]},image.url))??null]})};
|
|
1733
1733
|
|
|
1734
1734
|
function RadioOptionSettingsActions({content,showDelete,showMove,onDelete,onMove}){return jsxRuntimeExports.jsxs("div",{className:styles.radioOptionActionsContainer,children:[showDelete&&jsxRuntimeExports.jsx(Button,{size:"small",kind:"tertiary",startIcon:trashIcon,onClick:()=>{if(window.confirm(`Are you sure you want to remove this choice?
|
|
1735
1735
|
|