├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── mathview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── zanvent │ │ └── mathview │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── mathscribe │ │ │ ├── function.js │ │ │ ├── jqmath-0.4.3.css │ │ │ ├── jqmath-0.4.6.js │ │ │ ├── jqmath-etc-0.4.6.min.js │ │ │ ├── jquery-1.4.3.js │ │ │ ├── jquery-1.4.3.min.js │ │ │ ├── jscurry-0.4.5.js │ │ │ ├── jscurry-0.4.5.min.js │ │ │ ├── jscurry-documentation.txt │ │ │ └── view.html │ └── java │ │ └── com │ │ └── zanvent │ │ └── mathview │ │ ├── MathView.java │ │ └── Util.java │ └── test │ └── java │ └── com │ └── zanvent │ └── mathview │ └── ExampleUnitTest.java ├── screenshots ├── screenshot.png └── screenshot2.png └── settings.gradle /.gitattributes: -------------------------------------------------------------------------------- 1 | * linguist-vendored 2 | *.java linguist-vendored=false -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | /app 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2018 Farhan Farooqui 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![](https://jitpack.io/v/frhnfrq/MathView.svg)](https://jitpack.io/#frhnfrq/MathView) 2 | 3 | # MathView 4 | 5 | `MathView` is a library to render Math equations in Android. It uses [jqMath](https://mathscribe.com/author/jqmath.html) to render math equations. 6 | 7 | ## Setup 8 | 9 | Add it in your **root** build.gradle at the end of repositories: 10 | 11 | ```groovy 12 | allprojects { 13 | repositories { 14 | ... 15 | maven { url 'https://jitpack.io' } 16 | } 17 | } 18 | ``` 19 | 20 | Add `implementation 'com.github.frhnfrq:MathView:1.2'` into **dependencies** section of your **module** build.gradle file. For example: 21 | 22 | ```groovy 23 | dependencies { 24 | implementation 'com.github.frhnfrq:MathView:1.2' 25 | } 26 | ``` 27 | ## Usage 28 | 29 | #### Add `MathView` in your layout 30 | 31 | ```xml 32 | 36 | ``` 37 | 38 | #### Get an instance of it in your code 39 | ```java 40 | MathView mathview = findViewById(R.id.mathview); 41 | mathview.setText("If $ax^2+bx+c=0$ with $a≠0$, then: $$x={-b±√{b^2-4ac}}/{2a}$$"); 42 | mathview.setPixelScaleType(Scale.SCALE_DP); 43 | mathview.setTextSize(16); 44 | mathview.setTextColor("#111111"); 45 | ``` 46 | 47 | ## Screenshot 48 | 49 | 50 | ## How to 51 | 52 | To learn how to write math equations in it, please have a look at [jqMath](https://mathscribe.com/author/jqmath.html). 53 | 54 | ## Advantages 55 | 56 | 1. Faster than MathJax. 57 | 2. Change text size and color easily. 58 | 3. Supports HTML outside of the equation. Example 59 | ```java 60 | mathview.setText("This is a straight line, $\ax + \by = \c$"); 61 | ``` 62 | 63 | 64 | ## Disadvantages 65 | 66 | 1. Special symbols are typed manually. Example: √ ∑ ∫ ← → + > 67 | 2. Some parts of the MathML standard are not yet implemented in jqMath, such as elementary school mathematics (e.g. “long division”), and “Content MathML.” 68 | 69 | 70 | 71 | 72 | License 73 | ======= 74 | 75 | Copyright 2018 Farhan Farooqui 76 | 77 | Licensed under the Apache License, Version 2.0 (the "License"); 78 | you may not use this file except in compliance with the License. 79 | You may obtain a copy of the License at 80 | 81 | http://www.apache.org/licenses/LICENSE-2.0 82 | 83 | Unless required by applicable law or agreed to in writing, software 84 | distributed under the License is distributed on an "AS IS" BASIS, 85 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 86 | See the License for the specific language governing permissions and 87 | limitations under the License. 88 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | mavenCentral() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:7.3.1' 11 | 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | mavenCentral() 22 | maven { url 'https://jitpack.io' } 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | android.enableJetifier=true 10 | android.useAndroidX=true 11 | org.gradle.jvmargs=-Xmx1536m 12 | # When configured, Gradle will run in incubating parallel mode. 13 | # This option should only be used with decoupled projects. More details, visit 14 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 15 | # org.gradle.parallel=true 16 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frhnfrq/MathView/468eabd9645218286a3fd8841fbfefffb9bb8dc4/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Nov 29 08:13:06 MSK 2022 2 | distributionBase=GRADLE_USER_HOME 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /mathview/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /mathview/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | namespace = "com.zanvert.mathview" 5 | 6 | compileSdkVersion 33 7 | 8 | defaultConfig { 9 | minSdkVersion 16 10 | targetSdkVersion 33 11 | versionCode 1 12 | versionName "1.2" 13 | 14 | testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' 15 | 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | 25 | } 26 | 27 | dependencies { 28 | implementation fileTree(dir: 'libs', include: ['*.jar']) 29 | implementation 'androidx.appcompat:appcompat:1.5.1' 30 | testImplementation 'junit:junit:4.13.2' 31 | androidTestImplementation 'androidx.test.ext:junit:1.1.4' 32 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0' 33 | } 34 | -------------------------------------------------------------------------------- /mathview/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /mathview/src/androidTest/java/com/zanvent/mathview/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.zanvent.mathview; 2 | 3 | import android.content.Context; 4 | import androidx.test.platform.app.InstrumentationRegistry; 5 | import androidx.test.ext.junit.runners.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); 23 | 24 | assertEquals("com.zanvent.mathview.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /mathview/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /mathview/src/main/assets/mathscribe/function.js: -------------------------------------------------------------------------------- 1 | function setText(text) { 2 | $("#text").html(text); 3 | var script = document.createElement('script'); 4 | script.src = 'jqmath-etc-0.4.6.min.js'; 5 | document.head.appendChild(script); 6 | } 7 | 8 | function setTextSize(fontSize) { 9 | $("#text").css("font-size", fontSize + "px"); 10 | } 11 | 12 | function setTextColor(colorCode) { 13 | $("#text").css("color", colorCode); 14 | } -------------------------------------------------------------------------------- /mathview/src/main/assets/mathscribe/jqmath-0.4.3.css: -------------------------------------------------------------------------------- 1 | /* "fm" classes are mostly for imitating MathML in browsers without it; we try to roughly mimic 2 | Firefox's MathML layout, which seems better than http://www.w3.org/TR/mathml-for-css/ */ 3 | 4 | /* Cambria [Math]'s line height currently (2/11) is large in most non-Microsoft browsers: */ 5 | fmath, .fm-math { font-family: STIXGeneral, 'DejaVu Serif', 'DejaVu Sans', 6 | /* Cambria, 'Cambria Math', */ Times, 'Lucida Sans Unicode', 7 | OpenSymbol, 'Standard Symbols L', serif; line-height: 1.2 } 8 | fmath mtext, .fm-math mtext 9 | { line-height: normal } 10 | fmath mo, .fm-mo, .ma-sans-serif, fmath mi[mathvariant*=sans-serif], 11 | fmath mn[mathvariant*=sans-serif], fmath mtext[mathvariant*=sans-serif], 12 | fmath ms[mathvariant*=sans-serif] 13 | /* some (crossbrowsertesting/browsershots) IE7s require no line break before 14 | 'Lucida Sans Unicode': */ 15 | { font-family: STIXGeneral, 'DejaVu Sans', 'DejaVu Serif', /* Cambria, 'Cambria Math', */ 'Lucida Sans Unicode', 16 | 'Arial Unicode MS', 'Lucida Grande', Times, 17 | OpenSymbol, 'Standard Symbols L', sans-serif } 18 | .fm-mo-Luc /* avoid extra space at character tops, especially when stretched */ 19 | { font-family: STIXGeneral, 'DejaVu Sans', 'DejaVu Serif', /* Cambria, 'Cambria Math', */ 'Lucida Sans Unicode', 20 | 'Lucida Grande', 'Arial Unicode MS', Times, 21 | OpenSymbol, 'Standard Symbols L', sans-serif } 22 | * html fmath, * html .fm-math, * html fmath mo, * html .fm-mo, * html .IE6-LSU 23 | { font-family: 'Lucida Sans Unicode' !important } /* IE <=6 only */ 24 | mo.fm-radic { font-family: 'Lucida Sans Unicode', 'Lucida Grande', 25 | Verdana, sans-serif !important } 26 | .ma-script, fmath mi[mathvariant*=script], fmath mo[mathvariant*=script], 27 | fmath mn[mathvariant*=script], fmath mtext[mathvariant*=script], fmath ms[mathvariant*=script] 28 | { font-family: 29 | 'England Hand DB', 'Embassy BT', 'Amazone BT', 'Bank Script D', 30 | 'URW Chancery L', 'Lucida Calligraphy', 'Apple Chancery', 31 | 'Monotype Corsiva', Corsiva, 32 | 'Vivaldi D', Gabriola, 'Segoe Script', cursive } 33 | .ma-fraktur, fmath mi[mathvariant*=fraktur], fmath mo[mathvariant*=fraktur], 34 | fmath mn[mathvariant*=fraktur], fmath mtext[mathvariant*=fraktur], 35 | fmath ms[mathvariant*=fraktur] 36 | { font-family: UnifrakturMaguntia, Impact, fantasy } 37 | fmath mi[mathvariant*=monospace], fmath mo[mathvariant*=monospace], 38 | fmath mn[mathvariant*=monospace], fmath mtext[mathvariant*=monospace], 39 | fmath ms[mathvariant*=monospace] 40 | { font-family: monospace } 41 | /* .ma-double-struck currently ignored */ 42 | 43 | .fm-mi-length-1 { font-style: italic } 44 | fmath mi[mathvariant] { font-style: normal } 45 | 46 | .ma-bold, fmath mi[mathvariant*=bold], fmath mo[mathvariant*=bold], 47 | fmath mn[mathvariant*=bold], fmath mtext[mathvariant*=bold], fmath ms[mathvariant*=bold] 48 | { font-weight: bold } 49 | .ma-nonbold { font-weight: normal } 50 | .ma-upright { font-style: normal !important } 51 | .ma-italic, fmath mi[mathvariant*=italic], fmath mo[mathvariant*=italic], 52 | fmath mn[mathvariant*=italic], fmath mtext[mathvariant*=italic], fmath ms[mathvariant*=italic] 53 | { font-style: italic } 54 | 55 | fmath.ma-block { display: block; text-align: center; text-indent: 0; 56 | page-break-inside: avoid } 57 | 58 | /* note an operator might be 'mo' or "embellished": */ 59 | .fm-separator { padding: 0 0.56ex 0 0 } 60 | .fm-infix-loose { padding: 0 0.56ex } /* typically a relation */ 61 | .fm-infix { padding: 0 0.44ex } 62 | .fm-prefix { padding: 0 0.33ex 0 0 } 63 | .fm-postfix { padding: 0 0 0 0.33ex } 64 | .fm-prefix-tight { padding: 0 0.11ex 0 0 } 65 | .fm-postfix-tight { padding: 0 0 0 0.11ex } 66 | .fm-quantifier { padding: 0 0.11ex 0 0.22ex } /* to match MathML */ 67 | /* fences should have no padding */ 68 | .ma-non-marking { display: none } 69 | 70 | .fm-large-op { font-size: 1.3em } 71 | .fm-inline .fm-large-op { font-size: 1em } 72 | 73 | fmath mrow { white-space: nowrap } 74 | 75 | .fm-vert { display: inline-block; vertical-align: middle } 76 | 77 | fmath table, fmath tbody, fmath tr, fmath td /* reset to default(?) styles */ 78 | { border: 0 !important; padding: 0 !important; margin: 0 !important; 79 | outline: 0 !important } 80 | 81 | fmath table { border-collapse: collapse !important; text-align: center !important; 82 | table-layout: auto !important; float: none !important } 83 | 84 | .fm-frac { padding: 0 1px !important } 85 | td.fm-den-frac { border-top: solid thin !important } 86 | 87 | .fm-root { font-size: 0.6em } 88 | .fm-radicand { padding: 0 1px 0 0; border-top: solid; margin-top: 0.1em } 89 | 90 | .fm-script { font-size: 0.71em } 91 | .fm-script .fm-script .fm-script { font-size: 1em } 92 | 93 | td.fm-underover-base { line-height: 1 !important } 94 | 95 | td.fm-mtd { padding: 0.5ex 0.4em !important; vertical-align: baseline !important } 96 | 97 | fmath mphantom { visibility: hidden } 98 | fmath menclose, menclose.fm-menclose 99 | { display: inline-block } 100 | fmath menclose[notation=top], menclose.fm-menclose[notation=top] 101 | { border-top: solid thin } 102 | fmath menclose[notation=right], menclose.fm-menclose[notation=right] 103 | { border-right: solid thin } 104 | fmath menclose[notation=bottom], menclose.fm-menclose[notation=bottom] 105 | { border-bottom: solid thin } 106 | fmath menclose[notation=left], menclose.fm-menclose[notation=left] 107 | { border-left: solid thin } 108 | fmath menclose[notation=box], menclose.fm-menclose[notation=box] 109 | { border: solid thin } 110 | fmath none { display: none } /* probably unnecessary */ 111 | 112 | mtd.middle, fmath td.middle { vertical-align: middle !important } 113 | 114 | fmath table[columnalign=left], fmath tr[columnalign=left], fmath td[columnalign=left] 115 | { text-align: left !important } 116 | fmath table[columnalign=right], fmath tr[columnalign=right], fmath td[columnalign=right] 117 | { text-align: right !important } 118 | fmath td[rowalign=top] 119 | { vertical-align: top !important } 120 | fmath td[rowalign=bottom] 121 | { vertical-align: bottom !important } 122 | fmath td[rowalign=center] 123 | { vertical-align: middle !important } 124 | 125 | mtable.ma-join-align > mtr > mtd:first-child, 126 | fmath span.ma-join-align > table > tbody > tr > td:first-child 127 | { text-align: right; padding-right: 0 !important } 128 | mtable.ma-join-align > mtr > mtd:first-child + mtd, 129 | fmath span.ma-join-align > table > tbody > tr > td:first-child + td 130 | { text-align: left; padding-left: 0 !important } 131 | mtable.ma-join1-align > mtr > mtd:first-child, /* e.g. for cases after a stretched { */ 132 | fmath span.ma-join1-align > table > tbody > tr > td:first-child 133 | { text-align: left; padding-left: 0 !important } 134 | 135 | mtable.ma-binom > mtr > mtd, fmath span.ma-binom > table > tbody > tr > td 136 | { padding: 0 !important } 137 | mtable.ma-binom > mtr:first-child > mtd, 138 | fmath span.ma-binom > table > tbody > tr:first-child > td 139 | { padding: 0 0 0.18em 0 !important } 140 | -------------------------------------------------------------------------------- /mathview/src/main/assets/mathscribe/jqmath-0.4.6.js: -------------------------------------------------------------------------------- 1 | /* jqmath.js: a JavaScript module for symbolic expressions, e.g. formatted mathematical 2 | formulas. This file uses charset UTF-8, and requires jQuery 1.0+, jsCurry, and jqmath.css. 3 | By default, we use Presentation MathML when available, else simple HTML and CSS. 4 | Expressions may be constructed programmatically, or using a simple TeX-like syntax. 5 | 6 | To use symbolic expressions in a web page or problem domain, one must choose a set of 7 | symbols, ensure they can be viewed by users, and specify precedences for the operator 8 | symbols. We use Unicode character numbers for encoding, and fonts for display. Normally 9 | standard characters and fonts suffice, but "private use" character numbers and custom fonts 10 | can be used when necessary. By default, this module currently uses standard MathML 3 11 | precedences for operator symbols, except we omit "multiple character operator"s like && or 12 | <=, and choose a single precedence for each of |, ^, and _. 13 | 14 | The algorithm to detect MathML only works after some document.body is defined and available. 15 | Thus it should probably not be used during document loading. 16 | 17 | See http://mathscribe.com/author/jqmath.html for usage documentation and examples, and 18 | jscurry.js for some coding conventions and goals. */ 19 | 20 | /* Copyright 2017, Mathscribe, Inc. Released under the MIT license (same as jQuery). 21 | See e.g. http://jquery.org/license for an explanation of this license. */ 22 | 23 | 24 | "use strict"; 25 | 26 | 27 | var jqMath = function() { 28 | var $ = jQuery, F = jsCurry; 29 | 30 | if (! Math.sign) 31 | Math.sign = function(x) { 32 | x = Number(x); 33 | return x > 0 ? 1 : x < 0 ? -1 : x /* +0, -0, or NaN */; 34 | }; 35 | if (! Math.trunc) 36 | Math.trunc = function(x) { return (x < 0 ? Math.ceil : Math.floor)(x); }; 37 | 38 | function M(x, y, z) /* any number of arguments */ { 39 | if (typeof x == 'number') x = String(x); // e.g. for small integers 40 | if (typeof x == 'string' || Array.isArray(x)) return M.sToMathE(x, y, z); 41 | if (x.nodeType == 1 /* Element */ && x.tagName.toLowerCase() == 'math') 42 | return M.eToMathE(x); 43 | F.err(err_M_); 44 | } 45 | 46 | M.toArray1 = function(g) { return Array.isArray(g) ? g : [g]; }; 47 | 48 | M.getSpecAttrP = function(e, attrName) { 49 | var attrP = e.getAttributeNode(attrName); 50 | return attrP && /* for IE6-7: */ attrP.specified !== false ? attrP.value : undefined; 51 | }; 52 | M.objToAttrs = function(obj) { 53 | var res = []; 54 | for (var p in obj) res.push({ name: p, value: obj[p] }); 55 | return res; 56 | }; 57 | M.setAttrs = function(e, attrsP) /* uses attr.name/value/[specified for IE6-7] */ { 58 | if (attrsP && attrsP.length == null) attrsP = M.objToAttrs(attrsP); 59 | 60 | F.iter(function(attr) { 61 | if (attr.specified !== false /* for IE6-7 */) 62 | e.setAttribute(attr.name, attr.value); 63 | }, attrsP || []); 64 | return e; 65 | }; 66 | 67 | M.replaceNode = function(newNode, oldNode) /* returns newNode (unlike node.replaceChild) */ 68 | { 69 | oldNode.parentNode.replaceChild(newNode, oldNode); 70 | return newNode; 71 | }; 72 | 73 | M.addClass = function(e, ws) { 74 | // $(e).addClass(ws) doesn't seem to work for XML elements 75 | if (typeof e.className != 'undefined') { // needed for old IE, works for non-XML 76 | var classes = e.className; 77 | e.className = (classes ? classes+' ' : '')+ws; 78 | } else { // needed for XML, would work for non-IE 79 | var classes = e.getAttribute('class'); 80 | e.setAttribute('class', (classes ? classes+' ' : '')+ws); 81 | } 82 | return e; 83 | }; 84 | M.eToClassesS = function(e) { 85 | var sP = typeof e.className != 'undefined' ? e.className : e.getAttribute('class'); 86 | return sP || ''; 87 | }; 88 | M.hasClass = function(e, w) { // works for HTML or XML elements, unlike jQuery e.g. 1.4.3 89 | return (' '+M.eToClassesS(e)+' ').replace(/[\n\t]/g, ' ').indexOf(' '+w+' ') != -1; 90 | // we replace /[\n\t]/g to be consistent with jQuery 91 | }; 92 | 93 | M.inlineBlock = function(/* ... */) /* each argument is a DOM elt, jQuery object, or HTML 94 | string */ { 95 | var res$ = $('
').css('display', 'inline-block'); 96 | if (arguments.length) res$.append.apply(res$, arguments); 97 | return res$[0]; 98 | }; 99 | 100 | M.tr$ = function(/* ... */) /* each argument is a DOM elt, jQuery object, HTML string, or 101 | Array of them; each argument produces one */ { 102 | var appendMF = $.fn.append; 103 | function td$(g) { return appendMF.apply($(''), M.toArray1(g)); } 104 | return appendMF.apply($(''), F.map(td$, arguments)); 105 | }; 106 | 107 | M.mathmlNS = "http://www.w3.org/1998/Math/MathML"; // MathML namespace 108 | 109 | function appendMeArgs(e, args /* null/undefined, string, node, or array-like of nodes incl. 110 | live NodeList */, attrsP) { 111 | if (args == null) ; 112 | else if (typeof args == 'string') 113 | e.appendChild(e.ownerDocument.createTextNode(args)); 114 | else if (args.nodeType) e.appendChild(args); 115 | else { 116 | if (args.constructor != Array) args = F.slice(args); // for live NodeList 117 | F.iter(function(x) { e.appendChild(x); }, args); 118 | } 119 | return M.setAttrs(e, attrsP); 120 | } 121 | 122 | var fixMathMLQ_ = false; 123 | (function() { // M.webkitVersion, M.operaVersion, M.msieVersion, M.mozillaVersion 124 | var ua = navigator.userAgent.toLowerCase(), match = ua.match(/webkit[ \/](\d+)\.(\d+)/); 125 | if (match) { 126 | M.webkitVersion = [Number(match[1]), Number(match[2])]; 127 | fixMathMLQ_ = M.webkitVersion[0] <= 540 /*@@*/; 128 | } else { 129 | match = ua.match(/(opera)(?:.*version)?[ \/]([\w.]+)/) || 130 | ua.match(/(msie) ([\w.]+)/) || 131 | ua.indexOf("compatible") < 0 && ua.match(/(mozilla)(?:.*? rv:([\w.]+))?/); 132 | if (match) M[match[1]+'Version'] = match[2] || "0"; 133 | } 134 | })(); 135 | if (M.msieVersion) 136 | document.write( 137 | '', 138 | ''); 139 | // M.MathPlayer controls whether the IE plugin MathPlayer can be used. 140 | function checkMathMLAttrs(e) { 141 | if (M.MathML && ! fixMathMLQ_) return e; 142 | 143 | var tagName = e.tagName.toLowerCase(), doc = e.ownerDocument; 144 | function new1(k) { return doc.createElementNS(M.mathmlNS, k); } 145 | if (tagName == 'mi') { 146 | if (! e.getAttribute('mathvariant') && e.firstChild 147 | && e.firstChild.nodeType == 3 /* Text */) 148 | e.setAttribute('mathvariant', 149 | e.firstChild.data.length == 1 ? 'italic' : 'normal'); 150 | } else if (tagName == 'mo') { 151 | if (e.childNodes.length == 1 && e.firstChild.nodeType == 3 /* Text */) { 152 | var s = e.firstChild.data; 153 | if (/^[\u2061-\u2064]$/.test(s)) M.addClass(e, 'ma-non-marking'); 154 | /*@@ move parse_mxP_tokP fm- operator spacing here!? */ 155 | } 156 | } else if (tagName == 'mspace') { //@@ combine with M.newMe 'mspace' clause 157 | if (M.webkitVersion && M.MathML) { 158 | e.style.display = 'inline-block'; 159 | e.style.minWidth = e.getAttribute('width') || '0px'; 160 | } 161 | } else if (tagName == 'menclose') { 162 | if (M.webkitVersion && M.MathML) M.addClass(e, 'fm-menclose'); 163 | } else if (tagName == 'mmultiscripts') { 164 | if (M.webkitVersion) { 165 | var a = F.slice(e.childNodes); // partly because e.childNodes is dynamic 166 | if (a.length == 0) throw 'Wrong number of arguments: 0'; 167 | var rowA = [a[0]]; 168 | for (var i = 1; i < a.length; i++) { 169 | if (a[i].tagName == 'mprescripts') { 170 | rowA.unshift(new1('none')); 171 | continue; 172 | } 173 | if (i + 1 == a.length) throw 'Missing argument in '; 174 | var a3 = [rowA[0], a[i], a[i + 1]]; 175 | i++; 176 | rowA[0] = new1('msubsup'); 177 | F.iter(function(arg) { rowA[0].appendChild(arg); }, a3); 178 | } 179 | var oldE = e; 180 | e = appendMeArgs(new1('mrow'), rowA, e.attributes); 181 | if (oldE.parentNode) oldE.parentNode.replaceChild(e, oldE); 182 | } 183 | } 184 | 185 | var colorOpt = e.getAttribute('mathcolor'), hrefOpt = e.getAttribute('href'); 186 | if (colorOpt && e.style) e.style.color = colorOpt; 187 | if (hrefOpt && (! M.MathML || M.webkitVersion)) { 188 | var aE = doc.createElement('A'), parentP = e.parentNode, nextP = e.nextSibling; 189 | aE.appendChild(e); 190 | aE.href = hrefOpt; 191 | e = aE; 192 | if (parentP) parentP.insertBefore(e, nextP); 193 | } 194 | return e; 195 | } 196 | function newMeNS(tagName, argsP /* for appendMeArgs() */, attrsP, doc) 197 | /* tries to use the MathML namespace, perhaps with prefix 'm' */ { 198 | if (! doc) doc = document; 199 | 200 | var e = M.MathPlayer ? doc.createElement('m:'+tagName) : 201 | doc.createElementNS(M.mathmlNS, tagName); 202 | return checkMathMLAttrs(appendMeArgs(e, argsP, attrsP)); 203 | } 204 | // M.MathML controls whether MathML is used. 205 | (function() { 206 | if (self.location) { 207 | var match = location.search.match(/[?&;]mathml=(?:(off|false)|(on|true))\b/i); 208 | if (match) M.MathML = ! match[1]; 209 | else if (M.webkitVersion && F.cmpLex(F.cmpX, M.webkitVersion, [537, 17]) < 0 210 | || M.operaVersion) 211 | M.MathML = false; 212 | } 213 | })(); 214 | M.canMathML = function() /* requires document.body */ { 215 | if (M.msieVersion && ! M.MathPlayer) 216 | try { 217 | new ActiveXObject("MathPlayer.Factory.1"); 218 | if (M.MathPlayer == null) M.MathPlayer = true; 219 | else if (! M.MathPlayer) return false; // for Carlisle's MathPlayer 3 220 | } catch(exc) { 221 | M.MathPlayer = false; 222 | } 223 | if (! M.MathPlayer && typeof document.createElementNS == 'undefined') return false; 224 | 225 | function mathMeToE(mathMe) { 226 | mathMe.setAttribute('display', 'block'); 227 | return $('
').append(mathMe)[0]; 228 | } 229 | var e1 = newMeNS('math', newMeNS('mn', '1')), 230 | e2 = newMeNS('math', newMeNS('mfrac', [newMeNS('mn', '1'), newMeNS('mn', '2')])), 231 | es$ = $(F.map(mathMeToE, [e1, e2])); 232 | es$.css('visibility', 'hidden').appendTo(document.body); 233 | var res = $(es$[1]).height() > $(es$[0]).height() + 2; 234 | es$.remove(); 235 | return res; 236 | }; 237 | 238 | // fmUp is mid-x to outer top, fmDn is mid-x to outer bottom, both approx. & in parent ems 239 | function checkVertStretch(up, dn, g, doP) /* non-MathML */ { 240 | if (g.nodeName.toLowerCase() == 'mo' && g.childNodes.length == 1) { 241 | var c = g.firstChild, s = c.data; 242 | if (c.nodeType == 3 /* Text */ && (up > 0.9 || dn > 0.9) 243 | && (M.prefix_[s] < 25 || M.postfix_[s] < 25 244 | || '|\u2016\u221A' /* ‖ √ */.indexOf(s) != -1 || doP)) { 245 | var r = (up + dn) / 1.2, radicQ = s == '\u221A', 246 | v = (radicQ ? 0.26 : 0.35) + ((radicQ ? 0.15 : 0.25) - dn) / r; 247 | g.style.fontSize = r.toFixed(3)+'em'; 248 | g.style.verticalAlign = v.toFixed(3)+'em'; 249 | g.fmUp = up; 250 | g.fmDn = dn; 251 | g.style.display = 'inline-block'; 252 | g.style.transform = g.style.msTransform = g.style.MozTransform = 253 | g.style.WebkitTransform = 'scaleX(0.5)'; 254 | } 255 | } 256 | } 257 | function vertAlignE$(up, dn, fmVert) /* non-MathML */ { 258 | var e$ = $('').append(fmVert); 259 | e$[0].fmUp = up; 260 | e$[0].fmDn = dn; 261 | e$[0].style.verticalAlign = (0.5 * (up - dn)).toFixed(3)+'em'; 262 | return e$; 263 | } 264 | M.mtagName = function(e) /* returns 'fmath' for non-MathML 'math' */ { 265 | if (e.tagName == 'A' && e.childNodes.length == 1) e = e.firstChild; 266 | return e.getAttribute('mtagname') || e.tagName.toLowerCase().replace(/^m:/, ''); 267 | }; 268 | M.mchilds = function(e) { 269 | if (e.tagName == 'A' && e.childNodes.length == 1) e = e.firstChild; 270 | var mSP = e.getAttribute('mtagname'); 271 | while (e.tagName == 'SPAN') e = e.firstChild; 272 | function span0(g) { g.tagName == 'SPAN' || F.err(err_span0_); return g.firstChild; } 273 | if (e.tagName == 'TABLE') { 274 | e = e.firstChild; 275 | e.tagName == 'TBODY' || F.err(err_mchilds_tbody_); 276 | if (mSP == 'mtable') return e.childNodes; 277 | var a = e.childNodes; // s for mfrac munder mover munderover 278 | if (mSP == 'mover') a = [a[1], a[0]]; 279 | else if (mSP == 'munderover') a = [a[1], a[2], a[0]]; 280 | return F.map(function(tr) { return tr.firstChild.firstChild; }, a); 281 | } else if (e.tagName == 'MROW' && mSP) { 282 | var a = e.childNodes; 283 | if (mSP == 'msqrt') return [span0(span0(a[1]))]; 284 | if (mSP == 'mroot') return [span0(span0(a[2])), span0(a[0])]; 285 | mSP == 'mmultiscripts' || F.err(err_mchilds_mrow_); 286 | var nPrescripts = Number(e.getAttribute('nprescripts')); 287 | 0 <= nPrescripts && nPrescripts < a.length && nPrescripts % 2 == 0 || 288 | F.err(err_mchilds_mmultiscripts_); 289 | var res = [a[nPrescripts]]; 290 | for (var i = nPrescripts + 1; i < a.length; i++) res.push(span0(a[i])); 291 | if (nPrescripts) { 292 | res.push(e.ownerDocument.createElement('mprescripts')); 293 | for (var i = 0; i < nPrescripts; i++) res.push(span0(a[i])); 294 | } 295 | return res; 296 | } else if (F.elem(e.tagName, ['MSUB', 'MSUP', 'MSUBSUP'])) 297 | return F.map(function(c, i) { return i ? span0(c) : c; }, e.childNodes); 298 | else if (e.tagName == 'MSPACE') return []; 299 | else return e.childNodes; 300 | }; 301 | var mtokens_ = ['mn', 'mi', 'mo', 'mtext', 'mspace', 'ms'], 302 | impMRows_ = 303 | ['fmath', 'msqrt', 'mtd', 'mstyle', 'merror', 'mpadded', 'mphantom', 'menclose'], 304 | accentDsByS_ = { // top and bottom space in ems 305 | '\xAF' /* ¯ macron */: [0, 0.85], '\u203E' /* ‾ overline */: [0, 0.85], 306 | '\u02D9' /* ˙ dot above */: [0, 0.75], '\u02C7' /* ˇ caron */: [0, 0.7], 307 | '^': [0, 0.5], '~': [0, 0.4], '\u2192' /* → rightwards arrow */: [0.25, 0.25], 308 | '_': [0.7, 0], 309 | // not accents in MathML 3 operator dictionary: 310 | '\u2212' /* − */: [0.25, 0.45], '.': [0.6, 0.1] 311 | }; 312 | M.newMe = function(tagName, argsP /* for appendMeArgs() */, attrsP, docP) { 313 | if (! docP) { 314 | if (attrsP && attrsP.nodeType == 9 /* Document */) { 315 | docP = attrsP; 316 | attrsP = undefined; 317 | } else docP = document; 318 | } 319 | M.MathML != null || F.err(err_newMe_MathML_); 320 | 321 | if (M.MathML) return newMeNS(tagName, argsP, attrsP, docP); 322 | 323 | if (tagName == 'math') tagName = 'fmath'; 324 | var e$ = $(appendMeArgs(docP.createElement(tagName.toUpperCase()), argsP)), 325 | a = F.slice(e$[0].childNodes); // partly because e$[0].childNodes is dynamic 326 | if (F.elem(tagName, impMRows_) && a.length != 1) { 327 | a = [M.newMe('mrow', a, undefined, docP)]; 328 | e$[0].childNodes.length == 0 || F.err(err_newMe_imp_mrow_); 329 | e$.append(a[0]); 330 | } 331 | var ups = F.map(function(g) { return Number(g.fmUp || 0.6); }, a), 332 | dns = F.map(function(g) { return Number(g.fmDn || 0.6); }, a); 333 | 334 | if (tagName == 'fmath' || tagName == 'mn' || tagName == 'mtext' 335 | || tagName == 'mprescripts' || tagName == 'none') 336 | ; 337 | else if (tagName == 'mstyle' || tagName == 'merror' || tagName == 'mpadded' 338 | || tagName == 'mphantom' || tagName == 'menclose') { 339 | if (a[0].fmUp) e$[0].fmUp = a[0].fmUp; 340 | if (a[0].fmDn) e$[0].fmDn = a[0].fmDn; 341 | } else if (tagName == 'mi') { 342 | var c = a.length == 1 ? a[0] : {}; 343 | if (c.nodeType == 3 /* Text */ && c.data.length == 1) { 344 | e$.addClass('fm-mi-length-1'); 345 | if (c.data == 'f') e$.css('padding-right', '0.44ex'); 346 | // e.g. on a Mac, unnec. on netrenderer.com 12/20/16 347 | } 348 | } else if (tagName == 'mo') { 349 | var c = a.length == 1 ? a[0] : {}; 350 | if (c.nodeType == 3 /* Text */ && /[\]|([{‖)}]/.test(c.data)) 351 | e$.addClass('fm-mo-Luc'); 352 | } else if (tagName == 'mspace') { 353 | var e = M.setAttrs(e$[0], attrsP); 354 | attrsP = undefined; 355 | e.style.marginRight = e.getAttribute('width') || '0px'; // may be negative 356 | e.style.paddingRight = '0.001em'; // Firefox work-around 357 | e$.append('\u200C' /* ‌ */); // for Safari/Chrome 358 | e$.css('visibility', 'hidden'); // e.g. for iPad Mobile Safari 4.0.4 359 | } else if (tagName == 'mrow') { 360 | var up = F.applyF(Math.max, ups), dn = F.applyF(Math.max, dns); 361 | if (up > 0.65 || dn > 0.65) { 362 | e$[0].fmUp = up; 363 | e$[0].fmDn = dn; 364 | F.iter(F([up, dn, F._, undefined], checkVertStretch), a); 365 | } 366 | } else if (tagName == 'mfrac') { 367 | if (a.length != 2) throw 'Wrong number of arguments: '+a.length; 368 | var num$ = $('', docP).append(a[0]), 369 | den$ = $('', docP).append(a[1]); 370 | e$ = vertAlignE$(ups[0] + dns[0] + 0.03, ups[1] + dns[1] + 0.03, 371 | $('', docP). 372 | // partly for IE6-7, see www.quirksmode.org/css/display.html 373 | append($('', docP). 374 | append($('', docP). 375 | append($('', docP).append(num$)). 376 | append($('', docP).append(den$))))). 377 | attr('mtagname', tagName); 378 | } else if (tagName == 'msqrt' || tagName == 'mroot') { 379 | if (a.length != (tagName == 'msqrt' ? 1 : 2)) 380 | throw 'Wrong number of <'+tagName+'> arguments: '+a.length; 381 | e$ = $('', docP).attr('mtagname', tagName); 382 | var t = 0.06*(ups[0] + dns[0]), up = ups[0] + t + 0.1, dn = dns[0]; 383 | if (tagName == 'mroot') { 384 | var ht = 0.6 * (ups[1] + dns[1]), d = 0.25/0.6 - 0.25; 385 | if (up > ht) d += up/0.6 - ups[1]; 386 | else { 387 | d += dns[1]; 388 | up = ht; 389 | } 390 | e$.append($('', docP).append(a[1]). 391 | css('verticalAlign', d.toFixed(2)+'em')); 392 | } 393 | var mo$ = $('', docP).addClass('fm-radic').append('\u221A' /* √ */), 394 | // IE8 doesn't like $('').append(...) 395 | y$ = vertAlignE$(up, dn, 396 | $('', docP).append(a[0]). 397 | css('borderTopWidth', t.toFixed(3)+'em')); 398 | checkVertStretch(up, dn, mo$[0]); 399 | e$.append(mo$).append(y$); 400 | e$[0].fmUp = up; 401 | e$[0].fmDn = dn; 402 | } else if (tagName == 'msub' || tagName == 'msup' || tagName == 'msubsup' 403 | || tagName == 'mmultiscripts') { 404 | if (tagName != 'mmultiscripts' && a.length != (tagName == 'msubsup' ? 3 : 2)) 405 | throw 'Wrong number of <'+tagName+'> arguments: '+a.length; 406 | var up = ups[0], dn = dns[0], oddQ = tagName == 'msup', 407 | dUp = up/0.71 - 0.6, dDn = dn/0.71 - 0.6; 408 | for (var i = 1; i < a.length; i++) { 409 | if (tagName == 'mmultiscripts') { 410 | var w = M.mtagName(a[i]); 411 | if (w == 'none') continue; 412 | if (w == 'mprescripts') { 413 | if (oddQ) throw 'Repeated "mprescripts"'; 414 | oddQ = true; 415 | continue; 416 | } 417 | } 418 | if (i % 2 == (oddQ ? 0 : 1)) dDn = Math.max(dDn, ups[i]); 419 | else dUp = Math.max(dUp, dns[i]); 420 | } 421 | var preAP = undefined, postA = [], nPrescripts = 0; 422 | for (var i = 1; i < a.length; i++) { 423 | if (tagName == 'mmultiscripts') { 424 | var w = M.mtagName(a[i]); 425 | if (w == 'mprescripts') { 426 | preAP = []; 427 | nPrescripts = a.length - i - 1; 428 | continue; 429 | } 430 | } 431 | var d = 0.25/0.71 - 0.25; 432 | if (i % 2 == (preAP ? 0 : 1) && tagName != 'msup') { 433 | d -= dDn; 434 | dn = Math.max(dn, 0.71*(dDn + dns[i])); 435 | } else { 436 | d += dUp; 437 | up = Math.max(up, 0.71*(dUp + ups[i])); 438 | } 439 | $(a[i]).wrap('').parent(). 440 | css('verticalAlign', d.toFixed(2)+'em'); 441 | if (M.msieVersion && (document.documentMode || M.msieVersion) < 8) 442 | a[i].style.zoom = 1; // to set hasLayout 443 | if (tagName == 'mmultiscripts') (preAP || postA).push(a[i].parentNode); 444 | } 445 | if (tagName == 'mmultiscripts') 446 | e$ = $(''). // $('') fails in IE8 447 | append($((preAP || []).concat(a[0], postA))). 448 | attr({ mtagname: 'mmultiscripts', nprescripts: nPrescripts }); 449 | e$[0].fmUp = up; 450 | e$[0].fmDn = dn; 451 | } else if (tagName == 'munder' || tagName == 'mover' || tagName == 'munderover') { 452 | if (a.length != (tagName == 'munderover' ? 3 : 2)) 453 | throw 'Wrong number of <'+tagName+'> arguments: '+a.length; 454 | var tbody$ = $('', docP), td$, up = 0.85 * ups[0], dn = 0.85 * dns[0]; 455 | if (tagName != 'munder') { 456 | var overE = a[a.length - 1], accentDsP = undefined; 457 | td$ = $('', docP).append(td$)); 472 | } 473 | if (a[0].nodeName == 'MI' && a[0].childNodes.length == 1) { 474 | var c = a[0].firstChild, s = c.data; 475 | if (c.nodeType == 3 /* Text */ && s.length == 1) { 476 | var d = 'acegmnopqrsuvwxyz'.indexOf(s) != -1 ? 0.25 : s == 't' ? 0.15 : 0; 477 | if (d) { 478 | a[0].style.display = 'block'; 479 | a[0].style.marginTop = (- d).toFixed(2) + 'em'; 480 | up -= d; 481 | } 482 | } 483 | } 484 | td$ = $('', docP).append(a[0]); 485 | tbody$.append($('', docP).append(td$)); 486 | if (tagName != 'mover') { 487 | td$ = $('', docP).append(a[1]); 488 | tbody$.append($('', docP).append(td$)); 489 | dn += 0.71 * (ups[1] + dns[1]); 490 | } 491 | e$ = vertAlignE$(up, dn, $('', docP). 492 | append($('
', docP).append(overE); 458 | if (overE.nodeName == 'MO' && overE.childNodes.length == 1) { 459 | var c = overE.firstChild; 460 | if (c.nodeType == 3 /* Text */) accentDsP = accentDsByS_[c.data]; 461 | } 462 | if (accentDsP) { 463 | overE.style.display = 'block'; 464 | overE.style.marginTop = (- accentDsP[0]).toFixed(2) + 'em'; 465 | overE.style.marginBottom = (- accentDsP[1]).toFixed(2) + 'em'; 466 | up += 1.2 - F.sum(accentDsP); 467 | } else { 468 | td$.addClass("fm-script fm-inline"); 469 | up += 0.71 * (ups[a.length - 1] + dns[a.length - 1]); 470 | } 471 | tbody$.append($('
', docP).append(tbody$))). 493 | attr('mtagname', tagName); 494 | } else if (tagName == 'mtable') { 495 | var tbody$ = $('', docP).append($(a)); 496 | e$ = $('', docP) 497 | .append($('
', docP).append(tbody$)); 498 | var r = F.sum(ups) + F.sum(dns); 499 | e$[0].fmUp = e$[0].fmDn = 0.5 * r; // binomScan() may modify 500 | } else if (tagName == 'mtr') { 501 | e$ = $('', docP).append($(a)); 502 | var up = 0.6, dn = 0.6; 503 | F.iter(function(e, i) { 504 | if ((e.getAttribute(M.MathML ? 'rowspan' : 'rowSpan') || 1) == 1) { 505 | up = Math.max(up, ups[i]); 506 | dn = Math.max(dn, dns[i]); 507 | } 508 | }, a); 509 | e$[0].fmUp = up + 0.25; 510 | e$[0].fmDn = dn + 0.25; 511 | } else if (tagName == 'mtd') { // return ', docP).append($(a)); 513 | if (ups[0] > 0.65) e$[0].fmUp = ups[0]; 514 | if (dns[0] > 0.65) e$[0].fmDn = dns[0]; 515 | var e = M.setAttrs(e$[0], attrsP); 516 | attrsP = undefined; 517 | var rowspan = e.getAttribute('rowspan'), colspan = e.getAttribute('columnspan'); 518 | if (rowspan) { 519 | e.setAttribute('rowSpan', rowspan); // for IE6-7 520 | if (! M.hasClass(e, 'middle')) M.addClass(e, 'middle'); 521 | } 522 | if (colspan) e.setAttribute('colSpan', colspan); 523 | } else if (tagName == 'mfenced') { 524 | var e = M.setAttrs(e$[0], attrsP); 525 | return M.newMe('mrow', M.mfencedToMRowArgs(e), attrsP, docP); 526 | } else throw 'Unrecognized or unimplemented MathML tagName: '+tagName; 527 | 528 | return checkMathMLAttrs(M.setAttrs(e$[0], attrsP)); 529 | }; 530 | M.mfencedToMRowArgs = function(e) { 531 | e.tagName.toLowerCase() == 'mfenced' || F.err(err_mfencedToMRowArgs_); 532 | var doc = e.ownerDocument; 533 | function newMo(s) { return M.newMe('mo', s, undefined, doc); } 534 | var res = [newMo(F.defOr(M.getSpecAttrP(e, 'open'), '(')), 535 | newMo(F.defOr(M.getSpecAttrP(e, 'close'), ')'))], 536 | es = F.slice(e.childNodes); 537 | if (es.length == 0) return res; 538 | var inner; 539 | if (es.length == 1) inner = es[0]; 540 | else { 541 | var sepsP = F.defOr(M.getSpecAttrP(e, 'separators'), ',').match(/\S/g), 542 | n = sepsP ? es.length - 1 : 0; 543 | for (var i = 0; i < n; i++) 544 | es.splice(2*i + 1, 0, newMo(sepsP[Math.min(i, sepsP.length - 1)])); 545 | inner = M.newMe('mrow', es, undefined, doc); 546 | } 547 | res.splice(1, 0, inner); 548 | return res; 549 | }; 550 | M.spaceMe = function(widthS, docP) /* incl. avoid bad font support for \u2009   */ 551 | /* E.g. in Firefox 3.6.12, the DOM/jQuery don't like '' as a // child, 552 | and also padding doesn't seem to work on e.g. // elements; 553 | also any kind of unicode space inside an might be stripped by the browser: */ 554 | { return M.newMe('mspace', undefined, { width: widthS }, docP); }; 555 | M.fenceMe = function(me1, leftP, rightP, docP) 556 | { return M.newMe('mrow', 557 | [M.newMe('mo', F.defOr(leftP, '('), docP), me1, 558 | M.newMe('mo', F.defOr(rightP, ')'), docP)], 559 | docP); }; 560 | F.iter(function(tagName) { M[tagName] = F(M.newMe, tagName); }, 561 | ['mn', 'mi', 'mo', 'mtext', 'mspace', 'mrow', 'mfenced', 'mfrac', 'msqrt', 'mroot', 562 | 'msub', 'msup', 'msubsup', 'mmultiscripts', 'mprescripts', 'none', 563 | 'munder', 'mover', 'munderover', 'mtable', 'mtr', 'mtd', 564 | 'mstyle', 'merror', 'mpadded', 'mphantom', 'menclose']); 565 | M.setMathBlockQ = function(e, blockQ) { 566 | if (blockQ) { 567 | e.setAttribute('display', 'block'); 568 | M.addClass(e, 'ma-block'); 569 | } else if (! M.MathML) $(e).addClass('fm-inline'); 570 | return e; 571 | }; 572 | M.math = function(argsP /* for appendMeArgs() */, blockQ, docP) 573 | { return M.setMathBlockQ(M.newMe('math', argsP, docP), blockQ); }; 574 | 575 | M.eToMathE = function(mathE) /* 'mathE' has been parsed from MathML syntax */ { 576 | if (M.MathML == null || mathE.tagName.toLowerCase() != 'math') F.err(err_eToMathE_); 577 | function fixMathMLDeep(nod) { 578 | if (nod.nodeType != 1 /* Element */) return nod; 579 | if (! F.elem(nod.tagName, mtokens_)) F.iter(fixMathMLDeep, nod.childNodes); 580 | return checkMathMLAttrs(nod); 581 | } 582 | if (M.MathML && mathE.tagName == 'math') 583 | return fixMathMLQ_ ? fixMathMLDeep(mathE) : mathE; 584 | var doc = mathE.ownerDocument; 585 | function newMeDeep(me) { 586 | var tagName = me.tagName.toLowerCase(), args = me.childNodes; 587 | function nodeToMes(nod) { 588 | if (nod.nodeType == 3 /* Text */) 589 | return /^\s*$/.test(nod.data) ? [] : [M.mtext(nod.data, doc)]; 590 | if (nod.nodeType == 8 /* Comment */) return []; 591 | me.nodeType == 1 /* Element */ || F.err(err_newMeDeep_); 592 | return [newMeDeep(nod)]; 593 | } 594 | if (F.elem(tagName, mtokens_)) { 595 | if (tagName == 'mo' && args.length == 1 && args[0].nodeType == 3 /* Text */ 596 | && args[0].data == '-') args = M['-']; 597 | } else args = F.concatMap(nodeToMes, args); 598 | var res = M.newMe(tagName, args, me.attributes, doc); 599 | if (tagName == 'math') M.setMathBlockQ(res, me.getAttribute('display') == 'block'); 600 | return res; 601 | } 602 | return newMeDeep(mathE); 603 | }; 604 | 605 | M['-'] = '\u2212'; // − − 606 | M.trimNumS = function(s) /* trims trailing 0s after decimal point, trailing ., -0 */ { 607 | return s.replace(/(\d\.\d*?)0+(?!\d)/g, '$1').replace(/(\d)\.(?!\d)/g, '$1'). 608 | replace(/[-\u2212]0(?![.\d])/g, '0'); 609 | }; 610 | M.numS = function(s, trimQ) /* converts a numeric string to jqMath notation */ { 611 | if (trimQ) s = M.trimNumS(s); 612 | return s.replace(/Infinity/ig, '\u221E' /* ∞ */).replace(/NaN/ig, '{?}'). 613 | replace(/e(-\d+)/ig, '\xB710^{$1}').replace(/e\+?(\d+)/ig, '\xB710^$1'). 614 | replace(/-/g, M['-']); // \xB7 is · 615 | }; 616 | 617 | /* Like TeX, we use ^ for superscripts, _ for subscripts, {} for grouping, and \ (or `) as 618 | an escape character. Spaces and newline characters are ignored. We also use ↖ (\u2196) 619 | and ↙ (\u2199) to put limits above and below an operator or expression. You can 620 | $.extend() or even replace M.infix_, M.prefix_, M.postfix_, M.macros_, M.macro1s_, and 621 | M.alias_ as needed. */ 622 | M.combiningChar_ = '[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]'; 623 | M.surrPair_ = '[\uD800-\uDBFF][\uDC00-\uDFFF]'; 624 | var decComma_, escPat_ = '[\\\\`]([A-Za-z]+|.)'; 625 | M.decimalComma = function(qP) /* whether to allow decimal commas */ { 626 | if (qP != null) { 627 | decComma_ = qP; 628 | var numPat = (qP ? '\\d*,\\d+|' : '') + '\\d+\\.?\\d*|\\.\\d+'; 629 | M.re_ /* .lastIndex set during use */ = RegExp( 630 | '('+numPat+')|'+escPat_+'|'+M.surrPair_+'|\\S'+M.combiningChar_+'*', 'g'); 631 | } 632 | return decComma_; 633 | }; 634 | var commaLangs = 'af|an|ar|av|az|ba|be|bg|bs|ca|ce|co|cs|cu|cv|da|de|el|es|et|eu|fi|fo|fr|'+ 635 | 'gl|hr|hu|hy|id|is|it|jv|kk|kl|kv|lb|lt|lv|mk|mn|mo|nl|no|os|pl|pt|ro|ru|sc|sk|sq|sr|'+ 636 | 'su|sv|tr|tt|ug|uk|vi|yi'; 637 | M.decimalComma(RegExp('^('+commaLangs+')\\b', 'i').test(document.documentElement.lang)); 638 | M.infix_ = { // operator precedences, see http://www.w3.org/TR/MathML3/appendixc.html 639 | '⊂⃒': 240, '⊃⃒': 240, 640 | '≪̸': 260, '≫̸': 260, '⪯̸': 260, '⪰̸': 260, 641 | '∽̱': 265, '≂̸': 265, '≎̸': 265, '≏̸': 265, '≦̸': 265, '≿̸': 265, '⊏̸': 265, '⊐̸': 265, '⧏̸': 265, 642 | '⧐̸': 265, '⩽̸': 265, '⩾̸': 265, '⪡̸': 265, '⪢̸': 265, 643 | 644 | // if non-MathML and precedence <= 270, then class is 'fm-infix-loose' not 'fm-infix' 645 | 646 | /* '-' is converted to '\u2212' − − */ 647 | '\u2009' /*   ' ', currently generates an */: 390, 648 | 649 | '' /* no is generated */: 500 /* not 390 or 850 */ 650 | 651 | /* \^ or `^ 880 not 780, \_ or `_ 880 not 900 */ 652 | 653 | // unescaped ^ _ ↖ (\u2196) ↙ (\u2199) have precedence 999 654 | }; 655 | // If an infix op is also prefix or postfix, it must use the same precedence in each form. 656 | // Also, we omit "multiple character operator"s like && or <=. 657 | M.prefix_ = {}; 658 | // prefix precedence < 25 => thin space not inserted between multi-letter and it; 659 | // (prefix or postfix precedence < 25) and non-MathML => stretchy; 660 | // precedence < 25 => can be a fence 661 | 662 | // can use {|...|} for absolute value 663 | 664 | // + - % and other infix ops can automatically be used as prefix and postfix ops 665 | 666 | // if non-MathML and prefix and 290 <= precedence <= 350, then 'fm-large-op' 667 | M.postfix_ = { 668 | // (unquoted) ' is converted to '\u2032' ′ ′ 669 | }; 670 | function setPrecs(precs, precCharsA) { 671 | F.iter(function(prec_chars) { 672 | var prec = prec_chars[0]; 673 | F.iter(function(c) { precs[c] = prec; }, prec_chars[1].split('')); 674 | }, precCharsA); 675 | } 676 | setPrecs(M.infix_, [ 677 | [21, '|'], // | not 20 or 270 678 | [30, ';'], 679 | [40, ',\u2063'], 680 | [70, '∴∵'], 681 | [100, ':'], 682 | [110, '϶'], 683 | [150, '…⋮⋯⋱'], 684 | [160, '∋'], 685 | [170, '⊢⊣⊤⊨⊩⊬⊭⊮⊯'], 686 | [190, '∨'], 687 | [200, '∧'], 688 | [240, '∁∈∉∌⊂⊃⊄⊅⊆⊇⊈⊉⊊⊋'], 689 | [241, '≤'], 690 | [242, '≥'], 691 | [243, '>'], 692 | [244, '≯'], 693 | [245, '<'], 694 | [246, '≮'], 695 | [247, '≈'], 696 | [250, '∼≉'], 697 | [252, '≢'], 698 | [255, '≠'], 699 | [260, '=∝∤∥∦≁≃≄≅≆≇≍≔≗≙≚≜≟≡≨≩≪≫≭≰≱≺≻≼≽⊀⊁⊥⊴⊵⋉⋊⋋⋌⋔⋖⋗⋘⋙⋪⋫⋬⋭■□▪▫▭▮▯▰▱△▴▵▶▷▸▹▼▽▾▿◀◁◂◃'+ 700 | '◄◅◆◇◈◉◌◍◎●◖◗◦⧀⧁⧣⧤⧥⧦⧳⪇⪈⪯⪰'], 701 | [265, '⁄∆∊∍∎∕∗∘∙∟∣∶∷∸∹∺∻∽∾∿≂≊≋≌≎≏≐≑≒≓≕≖≘≝≞≣≦≧≬≲≳≴≵≶≷≸≹≾≿⊌⊍⊎⊏⊐⊑⊒⊓⊔⊚⊛⊜⊝⊦⊧⊪⊫⊰⊱⊲⊳⊶⊷⊹⊺⊻⊼⊽⊾⊿⋄⋆⋇'+ 702 | '⋈⋍⋎⋏⋐⋑⋒⋓⋕⋚⋛⋜⋝⋞⋟⋠⋡⋢⋣⋤⋥⋦⋧⋨⋩⋰⋲⋳⋴⋵⋶⋷⋸⋹⋺⋻⋼⋽⋾⋿▲❘⦁⦂⦠⦡⦢⦣⦤⦥⦦⦧⦨⦩⦪⦫⦬⦭⦮⦯⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧂⧃⧄'+ 703 | '⧅⧆⧇⧈⧉⧊⧋⧌⧍⧎⧏⧐⧑⧒⧓⧔⧕⧖⧗⧘⧙⧛⧜⧝⧞⧠⧡⧢⧧⧨⧩⧪⧫⧬⧭⧮⧰⧱⧲⧵⧶⧷⧸⧹⧺⧻⧾⧿⨝⨞⨟⨠⨡⨢⨣⨤⨥⨦⨧⨨⨩⨪⨫⨬⨭⨮⨰⨱⨲⨳⨴⨵⨶⨷⨸⨹'+ 704 | '⨺⨻⨼⨽⨾⩀⩁⩂⩃⩄⩅⩆⩇⩈⩉⩊⩋⩌⩍⩎⩏⩐⩑⩒⩓⩔⩕⩖⩗⩘⩙⩚⩛⩜⩝⩞⩟⩠⩡⩢⩣⩤⩥⩦⩧⩨⩩⩪⩫⩬⩭⩮⩯⩰⩱⩲⩳⩴⩵⩶⩷⩸⩹⩺⩻⩼⩽⩾⩿⪀⪁⪂⪃⪄⪅⪆⪉⪊⪋⪌⪍⪎⪏'+ 705 | '⪐⪑⪒⪓⪔⪕⪖⪗⪘⪙⪚⪛⪜⪝⪞⪟⪠⪡⪢⪣⪤⪥⪦⪧⪨⪩⪪⪫⪬⪭⪮⪱⪲⪳⪴⪵⪶⪷⪸⪹⪺⪻⪼⪽⪾⪿⫀⫁⫂⫃⫄⫅⫆⫇⫈⫉⫊⫋⫌⫍⫎⫏⫐⫑⫒⫓⫔⫕⫖⫗⫘⫙⫚⫛⫝⫝⫞⫟⫠⫡⫢⫣⫤⫥⫦'+ 706 | '⫧⫨⫩⫪⫫⫬⫭⫮⫯⫰⫱⫲⫳⫴⫵⫶⫷⫸⫹⫺⫻⫽⫾'], 707 | [270, '←↑→↓↔↕↖↗↘↙↚↛↜↝↞↟↠↡↢↣↤↥↦↧↨↩↪↫↬↭↮↯↰↱↲↳↴↵↶↷↸↹↺↻↼↽↾↿⇀⇁⇂⇃⇄⇅⇆⇇⇈⇉⇊⇋⇌⇍⇎⇏⇐⇑'+ 708 | '⇒⇓⇔⇕⇖⇗⇘⇙⇚⇛⇜⇝⇞⇟⇠⇡⇢⇣⇤⇥⇦⇧⇨⇩⇪⇫⇬⇭⇮⇯⇰⇱⇲⇳⇴⇵⇶⇷⇸⇹⇺⇻⇼⇽⇾⇿⊸⟰⟱⟵⟶⟷⟸⟹⟺⟻⟼⟽⟾⟿⤀⤁⤂⤃⤄'+ 709 | '⤅⤆⤇⤈⤉⤊⤋⤌⤍⤎⤏⤐⤑⤒⤓⤔⤕⤖⤗⤘⤙⤚⤛⤜⤝⤞⤟⤠⤡⤢⤣⤤⤥⤦⤧⤨⤩⤪⤫⤬⤭⤮⤯⤰⤱⤲⤳⤴⤵⤶⤷⤸⤹⤺⤻⤼⤽⤾⤿⥀⥁⥂⥃⥄⥅⥆⥇⥈⥉⥊⥋⥌⥍⥎⥏⥐⥑⥒'+ 710 | '⥓⥔⥕⥖⥗⥘⥙⥚⥛⥜⥝⥞⥟⥠⥡⥢⥣⥤⥥⥦⥧⥨⥩⥪⥫⥬⥭⥮⥯⥰⥱⥲⥳⥴⥵⥶⥷⥸⥹⥺⥻⥼⥽⥾⥿⦙⦚⦛⦜⦝⦞⦟⧟⧯⧴⭅⭆'], 711 | [275, '+-±−∓∔⊞⊟'], 712 | [300, '⊕⊖⊘'], 713 | [340, '≀'], 714 | [350, '∩∪'], 715 | [390, '*.ו\u2062⊠⊡⋅⨯⨿'], 716 | [400, '·'], 717 | [410, '⊗'], 718 | [640, '%'], 719 | [650, '\\∖'], 720 | [660, '/÷'], 721 | [710, '⊙'], 722 | [825, '@'], 723 | [835, '?'], 724 | [850, '\u2061'], 725 | [880, '^_\u2064']]); 726 | setPrecs(M.prefix_, [ 727 | [10, '‘“'], 728 | [20, '([{‖⌈⌊❲⟦⟨⟪⟬⟮⦀⦃⦅⦇⦉⦋⦍⦏⦑⦓⦕⦗⧼'], 729 | [230, '∀∃∄'], 730 | [290, '∑⨊⨋'], 731 | [300, '∬∭⨁'], 732 | [310, '∫∮∯∰∱∲∳⨌⨍⨎⨏⨐⨑⨒⨓⨔⨕⨖⨗⨘⨙⨚⨛⨜'], 733 | [320, '⋃⨃⨄'], 734 | [330, '⋀⋁⋂⨀⨂⨅⨆⨇⨈⨉⫼⫿'], 735 | [350, '∏∐'], 736 | [670, '∠∡∢'], 737 | [680, '¬'], 738 | [740, '∂∇'], 739 | [845, 'ⅅⅆ√∛∜']]); 740 | setPrecs(M.postfix_, [ 741 | [10, '’”'], 742 | [20, ')]}‖⌉⌋❳⟧⟩⟫⟭⟯⦀⦄⦆⦈⦊⦌⦎⦐⦒⦔⦖⦘⧽'], 743 | [800, '′♭♮♯'], 744 | [810, '!'], 745 | [880, '&\'`~¨¯°´¸ˆˇˉˊˋˍ˘˙˚˜˝˷\u0302\u0311‾\u20db\u20dc⎴⎵⏜⏝⏞⏟⏠⏡']]); 746 | 747 | var s_, s_or_mx_a_, s_or_mx_i_, docP_, precAdj_; 748 | /* A "tok" (scanner token or similar) here is an [meP, opSP], with at least one != null. 749 | The meP may be non-atomic. Thus a tok is either an me, possibly with a precedence given 750 | by an operator, or else either a meta-operator or "macro1" for building an me. */ 751 | 752 | function newMe_(tagName, argsP, attrsP) { return M.newMe(tagName, argsP, attrsP, docP_); } 753 | function emptyMe_() { return newMe_('mspace' /* or 'mrow'? */); } 754 | 755 | function scanWord(descP) /* use scanString() instead if any quotes should be stripped */ { 756 | var re = /\s*([-\w.]*)/g; //+ could allow all unicode alphabetics 757 | re.lastIndex = M.re_.lastIndex; 758 | var match = re.exec(s_); 759 | if (! match[1]) throw 'Missing '+(descP || 'word'); 760 | M.re_.lastIndex = re.lastIndex; 761 | return match[1]; 762 | } 763 | function scanString(descP) /* scans a word or quoted string */ { 764 | var re = /\s*(?:(["'])|([-\w.]*))/g; 765 | re.lastIndex = M.re_.lastIndex; 766 | var match = re.exec(s_); 767 | if (match[2]) { 768 | M.re_.lastIndex = re.lastIndex; 769 | return match[2]; 770 | } 771 | if (! match[1]) throw 'Missing '+(descP || 'string'); 772 | var c = match[1], re2 = RegExp('[^\\`'+c+']+|[\\`](.|\n)|('+c+')', 'g'), res = ''; 773 | re2.lastIndex = re.lastIndex; 774 | while (true) { 775 | match = re2.exec(s_); 776 | if (! match) throw 'Missing closing '+c; 777 | if (match[2]) break; 778 | res += match[1] || match[0]; 779 | } 780 | M.re_.lastIndex = re2.lastIndex; 781 | return res; 782 | } 783 | function scanMeTok(afterP) { 784 | var tokP = scanTokP(); 785 | if (! tokP || ! tokP[0]) 786 | throw 'Missing expression argument'+(afterP ? ' after '+afterP : '')+ 787 | ', before position '+M.re_.lastIndex; 788 | return tokP; 789 | } 790 | 791 | function mtokenScan(tagName /* 'mn', 'mi', 'mo', or 'mtext' */) { 792 | var s = scanString(tagName == 'mtext' ? 'text' : tagName); 793 | return [newMe_(tagName, s), tagName == 'mo' ? s : null]; 794 | } 795 | function htmlScan() { 796 | if (! M.trustHtml) throw '\\html use requires M.trustHtml'; 797 | var h = scanString('html'), 798 | e = $('
', docP_ || document).css('display', 'inline-block').html(h)[0]; 799 | if (e.childNodes.length == 1) e = e.childNodes[0]; 800 | return [newMe_('mtext', e), null]; 801 | } 802 | function spScan() { 803 | var widthS = scanString('\\sp width'); 804 | return [M.spaceMe(widthS, docP_), 805 | /^[^-]*[1-9]/.test(widthS) ? '\u2009' /*   */ : null]; 806 | } 807 | function braceScan() { 808 | var tokP = scanTokP(); 809 | if (tokP && tokP[1] == '↖' && ! tokP[0]) { // grouped op 810 | var meTokP_tokP = parseEmbel(); 811 | tokP = meTokP_tokP[1] || scanTokP(); 812 | if (! (meTokP_tokP[0] && tokP && tokP[1] == '}' && ! tokP[0])) 813 | throw 'Expected an embellished operator and "}" after "{↖", before position '+ 814 | M.re_.lastIndex; 815 | return meTokP_tokP[0]; 816 | } 817 | var mxP_tokP = parse_mxP_tokP(0, tokP); 818 | tokP = mxP_tokP[1]; 819 | // if (! tokP) throw 'Missing "}"'; 820 | ! tokP || tokP[1] == '}' && ! tokP[0] || F.err(err_braceScan_); 821 | return [mxP_tokP[0] || emptyMe_(), null]; 822 | } 823 | function attrScan(nameP, mmlOnlyQ) { // note usually doesn't affect non-MathML rendering 824 | if (! nameP) nameP = scanWord('attribute name'); 825 | var v = scanString(nameP+' attribute'), tok = scanMeTok(nameP); 826 | if (! mmlOnlyQ || M.MathML) tok[0].setAttribute(nameP, v); 827 | return tok; 828 | } 829 | function clScan() { // note currently ignored by MathPlayer 830 | var desc = 'CSS class name(s)', ws = scanString(desc), tok = scanMeTok(desc); 831 | M.addClass(tok[0], ws); 832 | return tok; 833 | } 834 | // see http://www.w3.org/TR/MathML3/chapter3.html#presm.commatt for mathvariant attr 835 | function mvScan(sP) { 836 | var s = sP || scanString('mathvariant'), tok = scanMeTok(s), me = tok[0]; 837 | if (! F.elem(M.mtagName(me), ['mi', 'mn', 'mo', 'mtext', 'mspace', 'ms'])) 838 | throw 'Can only apply a mathvariant to a MathML token (atomic) element, at '+ 839 | 'position '+M.re_.lastIndex; 840 | 841 | me.setAttribute('mathvariant', s); 842 | 843 | if (/bold/.test(s)) M.addClass(me, 'ma-bold'); 844 | else if (s == 'normal' || s == 'italic') M.addClass(me, 'ma-nonbold'); 845 | 846 | M.addClass(me, /italic/.test(s) ? 'ma-italic' : 'ma-upright'); 847 | 848 | if (/double-struck/.test(s)) M.addClass(me, 'ma-double-struck'); 849 | else if (/fraktur/.test(s)) M.addClass(me, 'ma-fraktur'); 850 | else if (/script/.test(s)) M.addClass(me, 'ma-script'); 851 | else if (/sans-serif/.test(s)) M.addClass(me, 'ma-sans-serif'); 852 | 853 | // (monospace, initial, tailed, looped, stretched) currently don't add classes 854 | 855 | return tok; 856 | } 857 | function meScan(tagNameP) { 858 | if (! tagNameP) tagNameP = scanWord('tagName'); 859 | var tok = scanMeTok({ menclose: 'enclose' }[tagNameP] || tagNameP); 860 | return [newMe_(tagNameP, tok[0]), 861 | F.elem(tagNameP, ['mstyle', 'mpadded']) ? tok[1] : null]; 862 | } 863 | function phantomScan(macroS) { 864 | var tok = scanMeTok(macroS); 865 | F.iter(function(e) { e.disabled = true; }, $('input', tok[0])); 866 | if (macroS == 'vphantom') 867 | tok[0] = newMe_('mpadded', tok[0], 868 | { width: '0', style: 'display: inline-block; width: 0' }); 869 | return [newMe_('mphantom', tok[0]), tok[1]]; 870 | } 871 | function ovScan() /* overbar */ { 872 | return [M.menclose(scanMeTok('\\ov')[0], { notation: 'top' }, docP_), null]; 873 | } 874 | function minsizeScan() { 875 | var s = scanString('minsize'), tok = scanMeTok('minsize'), me = tok[0]; 876 | if (M.mtagName(me) != 'mo') 877 | throw 'Can only stretch an operator symbol, before position '+M.re_.lastIndex; 878 | if (M.MathML) me.setAttribute('minsize', s); 879 | else { 880 | var match = /^(.+)em$/.exec(s); 881 | if (match) s = match[1]; 882 | var r = Number(s); // may be NaN, 0, etc. 883 | if (r > 1) checkVertStretch(0.6*r, 0.6*r, me, true); 884 | else if (! r) me.style.fontSize = s; 885 | } 886 | return tok; 887 | } 888 | function mrow1Scan() { return [newMe_('mrow', scanMeTok('\\mrowOne')[0]), null]; } 889 | function binomScan() { 890 | function mtr1(e) { return newMe_('mtr', newMe_('mtd', e)); } 891 | var xMe = scanMeTok('\\binom')[0], yMe = scanMeTok('\\binom')[0], 892 | zMe = newMe_('mtable', F.map(mtr1, [xMe, yMe])); 893 | M.addClass(zMe, 'ma-binom'); 894 | if (! M.MathML) { 895 | zMe.fmUp -= 0.41; 896 | zMe.fmDn -= 0.41; 897 | } 898 | return [newMe_('mrow', [newMe_('mo', '('), zMe, newMe_('mo', ')')]), null]; 899 | } 900 | M.macros_ /* each returns a tokP */ = { 901 | mn: F(mtokenScan, 'mn'), mi: F(mtokenScan, 'mi'), mo: F(mtokenScan, 'mo'), 902 | text: F(mtokenScan, 'mtext'), html: htmlScan, sp: spScan, 903 | attr: attrScan, attrMML: F(attrScan, null, true), 904 | id: F(attrScan, 'id'), dir: F(attrScan, 'dir'), cl: clScan, mv: mvScan, 905 | bo: F(mvScan, 'bold'), it: F(mvScan, 'italic'), bi: F(mvScan, 'bold-italic'), 906 | sc: F(mvScan, 'script'), bs: F(mvScan, 'bold-script'), fr: F(mvScan, 'fraktur'), 907 | ds: F(mvScan, 'double-struck'), bf: F(mvScan, 'bold-fraktur'), 908 | mstyle: F(meScan, 'mstyle'), merror: F(meScan, 'merror'), mpadded: F(meScan, 'mpadded'), 909 | phantom: F(phantomScan, 'phantom'), vphantom: F(phantomScan, 'vphantom'), 910 | enclose: F(meScan, 'menclose'), 911 | ov: ovScan, minsize: minsizeScan, mrowOne: mrow1Scan, binom: binomScan 912 | }; 913 | 914 | M.alias_ = { '-': M['-'], '\'': '\u2032' /* ′ */, 915 | '\u212D': ['C', 'fraktur'], '\u210C': ['H', 'fraktur'], '\u2111': ['I', 'fraktur'], 916 | '\u211C': ['R', 'fraktur'], '\u2128': ['Z', 'fraktur'], 917 | '\u212C': ['B', 'script'], '\u2130': ['E', 'script'], '\u2131': ['F', 'script'], 918 | '\u210B': ['H', 'script'], '\u2110': ['I', 'script'], '\u2112': ['L', 'script'], 919 | '\u2133': ['M', 'script'], '\u211B': ['R', 'script'], '\u212F': ['e', 'script'], 920 | '\u210A': ['g', 'script'], /* '\u2113': ['l', 'script'], */ '\u2134': ['o', 'script'] 921 | }; 922 | var spaces_ = { ',': '.17em', ':': '.22em', ';': '.28em', '!': '-.17em' }; 923 | function scanTokP() { 924 | var match = M.re_.exec(s_); 925 | while (! match) { 926 | M.re_.lastIndex = s_.length; 927 | if (s_or_mx_i_ == s_or_mx_a_.length) return null; 928 | var g = s_or_mx_a_[s_or_mx_i_++]; 929 | if (typeof g == 'string') { 930 | M.re_.lastIndex = 0; 931 | s_ = g; 932 | match = M.re_.exec(s_); 933 | } else if (g.nodeType == 1 /* Element */) return [g, null]; 934 | else F.err(err_scanTokP_); 935 | } 936 | var s1 = match[2] || match[0], mvP = null; 937 | if (/^[_^}\u2196\u2199]$/.test(match[0]) || match[2] && M.macro1s_[s1]) 938 | return [null, s1]; 939 | if (match[0] == '{') return braceScan(); 940 | if (match[2] && M.macros_[s1]) return M.macros_[s1](); 941 | if (match[1]) return [M.newMe('mn', s1, docP_), null]; 942 | if (/^[,:;!]$/.test(match[2])) s1 = '\u2009' /*   */; 943 | /* else if (match[2] == '&') { 944 | if (M.mozillaVersion && M.MathML && false /* not supported yet * /) 945 | return [M.newMe('maligngroup', undefined, docP_), null]; 946 | s1 = ','; 947 | } */ else if (match[2] == '/') s1 = '\u2215' /* ∕ */; 948 | else if (M.alias_[s1] && ! match[2]) { 949 | var t = M.alias_[s1]; 950 | if (typeof t == 'string') s1 = t; 951 | else { 952 | s1 = t[0]; 953 | mvP = t[1]; // 'double-struck', 'fraktur', or 'script' 954 | } 955 | } 956 | var opSP = M.infix_[s1] || M.prefix_[s1] || M.postfix_[s1] ? s1 : null, e; 957 | if (s1 == '\u2009' /*   */) // incl. avoid bad font support, incl. in MathML 958 | e = M.spaceMe(spaces_[match[2] || ','], docP_); 959 | else if (opSP) { 960 | if (/^[∛∜]$/.test(s1) && ! match[2]) { 961 | e = newMe_('mn', s1 == '∛' ? '3' : '4'); 962 | return [newMe_('msup', [newMe_('mo', '√'), e]), '√']; 963 | } 964 | e = M.newMe('mo', s1, docP_); 965 | if (/^[∀∃∄∂∇]$/.test(s1)) { // Firefox work-arounds 966 | e.setAttribute('lspace', '.11em'); 967 | e.setAttribute('rspace', '.06em'); 968 | } else if (s1 == '!') { 969 | e.setAttribute('lspace', '.06em'); 970 | e.setAttribute('rspace', '0'); 971 | } else if (s1 == '×' /* '\u00D7' */) { 972 | e.setAttribute('lspace', '.22em'); 973 | e.setAttribute('rspace', '.22em'); 974 | } 975 | } else { 976 | e = M.newMe('mi', s1, docP_); 977 | if (match[2] && s1.length == 1) { 978 | e.setAttribute('mathvariant', 'normal'); 979 | M.addClass(e, 'ma-upright'); 980 | if (! M.MathML) e.style.paddingRight = '0'; 981 | } else if (mvP) { 982 | e.setAttribute('mathvariant', mvP); 983 | M.addClass(e, 'ma-upright'); 984 | M.addClass(e, 'ma-'+mvP); 985 | } 986 | if (/\w\w/.test(s1)) M.addClass(e, 'ma-repel-adj'); 987 | } 988 | return [e, opSP]; 989 | } 990 | 991 | function parse_mtd_tokP(optQ /* => mtd can be null or an mtr */) { 992 | var mxP_tokP = parse_mxP_tokP(M.infix_[',']), tokP = mxP_tokP[1] || scanTokP(), 993 | mxP = mxP_tokP[0]; 994 | if (! mxP) { 995 | if (optQ && ! (tokP && tokP[1] == ',')) return [null, tokP]; 996 | mxP = emptyMe_(); 997 | } 998 | var w = M.mtagName(mxP); 999 | if (w != 'mtd' && ! (w == 'mtr' && optQ)) mxP = M.newMe('mtd', mxP, docP_); 1000 | return [mxP, tokP]; 1001 | } 1002 | function parse_rowspan_tokP() { 1003 | var v = scanString('rowspan'), mtd_tokP = parse_mtd_tokP(), mtd = mtd_tokP[0]; 1004 | mtd.setAttribute(M.MathML ? 'rowspan' : 'rowSpan' /* for IE6-7 */, v); 1005 | if (! M.hasClass(mtd, 'middle')) M.addClass(mtd, 'middle'); 1006 | return mtd_tokP; 1007 | } 1008 | function parse_colspan_tokP() { 1009 | var v = scanString('colspan'), mtd_tokP = parse_mtd_tokP(); 1010 | mtd_tokP[0].setAttribute(M.MathML ? 'columnspan' : 'colSpan', v); 1011 | return mtd_tokP; 1012 | } 1013 | function parse_mtr_tokP(optQ /* => mtr can be null */) { 1014 | var mtds = []; 1015 | while (true) { 1016 | var mtdP_tokP = parse_mtd_tokP(mtds.length == 0), mtdP = mtdP_tokP[0], 1017 | tokP = mtdP_tokP[1] || scanTokP(); 1018 | if (mtdP) { 1019 | if (M.mtagName(mtdP) == 'mtr') return [mtdP, tokP]; 1020 | mtds.push(mtdP); 1021 | } 1022 | if (! (tokP && tokP[1] == ',')) 1023 | return [mtds.length || ! optQ || tokP && tokP[1] == ';' ? 1024 | M.newMe('mtr', mtds, docP_) : null, tokP]; 1025 | } 1026 | } 1027 | M.dtableQ = false; // whether \table defaults to \dtable 1028 | function parse_table_tokP(dtableQ) { 1029 | if (dtableQ === undefined) dtableQ = M.dtableQ; 1030 | 1031 | var mtrs = []; 1032 | while (true) { 1033 | var mtrP_tokP = parse_mtr_tokP(mtrs.length == 0), mtrP = mtrP_tokP[0], 1034 | tokP = mtrP_tokP[1] || scanTokP(); 1035 | if (mtrP) mtrs.push(mtrP); 1036 | if (! (tokP && tokP[1] == ';')) 1037 | return [newMe_('mtable', mtrs, dtableQ ? { displaystyle: true } : undefined), 1038 | tokP]; 1039 | } 1040 | } 1041 | function parse_math_tokP() { 1042 | var mxP_tokP = parse_mxP_tokP(0); 1043 | mxP_tokP[0] = M.newMe('math', mxP_tokP[0], docP_); 1044 | return mxP_tokP; 1045 | } 1046 | /* An "mx" is an "me" ("eXpression") with no operator precedence (binding power), or one 1047 | whose precedence can be ignored. */ 1048 | M.macro1s_ /* each returns mxP_tokP, so can do precedence-based look-ahead */ = { 1049 | mtd: parse_mtd_tokP, rowspan: parse_rowspan_tokP, colspan: parse_colspan_tokP, 1050 | mtr: parse_mtr_tokP, dtable: F(parse_table_tokP, true), 1051 | ttable: F(parse_table_tokP, false), table: F(parse_table_tokP, undefined), 1052 | math: parse_math_tokP 1053 | }; 1054 | 1055 | var embelWs_ = { '_': 'sub', '^': 'sup', '\u2199': 'under', '\u2196': 'over' }; 1056 | function embelKP(op) { 1057 | var wP = embelWs_[op]; 1058 | return wP && (wP.length < 4 ? 'ss' : 'uo'); 1059 | } 1060 | function parseEmbel(meTokP, tokP) /* checks sub/sup/under/over; returns [meTokP, tokP] */ { 1061 | while (true) { 1062 | if (! tokP) tokP = scanTokP(); 1063 | if (! tokP || tokP[0] || ! embelWs_[tokP[1]]) { 1064 | if (tokP && ! meTokP) { 1065 | meTokP = tokP; 1066 | tokP = null; 1067 | continue; 1068 | } 1069 | return [meTokP, tokP]; 1070 | } 1071 | var k = embelKP(tokP[1]), 1072 | parseMxs = function() /* returns 0-2 mxs of kind 'k', by op; sets tokP */ { 1073 | var mxs = {}, doneQs = {}; 1074 | while (true) { 1075 | if (! tokP) tokP = scanTokP(); 1076 | if (! tokP || tokP[0]) break; 1077 | var op = tokP[1]; 1078 | if (embelKP(op) != k || doneQs[op]) break; 1079 | doneQs[op] = true; 1080 | tokP = scanTokP(); 1081 | if (tokP && embelKP(tokP[1]) == k && ! tokP[0]) continue; 1082 | var mxP_tokP = parse_mxP_tokP(999, tokP); 1083 | mxs[op] = mxP_tokP[0]; // null ok 1084 | tokP = mxP_tokP[1]; 1085 | } 1086 | return mxs; 1087 | }, mxs = parseMxs(); 1088 | if (k == 'uo' || ! tokP || (tokP[0] ? meTokP : embelKP(tokP[1]) != 'ss')) { 1089 | if (! meTokP) meTokP = [emptyMe_(), null]; 1090 | var w = 'm', a = [meTokP[0]]; 1091 | F.iter(function(op) { 1092 | if (mxs[op]) { 1093 | w += embelWs_[op]; 1094 | a.push(mxs[op]); 1095 | } 1096 | }, ['_', '^', '↙', '↖']); 1097 | if (a.length > 1) meTokP = [M.newMe(w, a, docP_), meTokP[1]]; 1098 | } else { 1099 | var mxsPA = [mxs]; 1100 | while (tokP && ! tokP[0] && embelKP(tokP[1]) == 'ss') mxsPA.push(parseMxs()); 1101 | if (! meTokP) { 1102 | if (! tokP || ! tokP[0]) meTokP = [emptyMe_(), null]; 1103 | else { 1104 | meTokP = tokP; 1105 | tokP = scanTokP(); 1106 | var postA = []; 1107 | while (tokP && ! tokP[0] && embelKP(tokP[1]) == 'ss') 1108 | postA.push(parseMxs()); 1109 | mxsPA = postA.concat(null, mxsPA); 1110 | } 1111 | } 1112 | var a = [meTokP[0]]; 1113 | F.iter(function(mxsP) { 1114 | if (! mxsP) a.push(M.newMe('mprescripts', undefined, docP_)); 1115 | else 1116 | a.push(mxsP['_'] || M.newMe('none', undefined, docP_), 1117 | mxsP['^'] || M.newMe('none', undefined, docP_)); 1118 | }, mxsPA); 1119 | meTokP = [M.newMe('mmultiscripts', a, docP_), meTokP[1]]; 1120 | } 1121 | } 1122 | } 1123 | function parse_mxP_tokP(prec, tokP) /* tokP may be non-atomic */ { 1124 | var mx0p = null; 1125 | while (true) { 1126 | if (! tokP) { 1127 | tokP = scanTokP(); 1128 | if (! tokP) break; 1129 | } 1130 | var op = tokP[1]; // may be null/undefined 1131 | if (! op 1132 | || mx0p && (tokP[0] ? ! (M.infix_[op] || M.postfix_[op]) : M.macro1s_[op])) { 1133 | if (! mx0p) { 1134 | mx0p = tokP[0]; 1135 | tokP = null; 1136 | } else { 1137 | if (prec >= precAdj_) break; 1138 | var mxP_tokP = parse_mxP_tokP(precAdj_, tokP), mx1 = mxP_tokP[0]; 1139 | mx1 || F.err(err_parse_mxP_tokP_1_); 1140 | var e = M.newMe('mrow', [mx0p, mx1], docP_); 1141 | if (M.hasClass(mx0p, 'ma-repel-adj') || M.hasClass(mx1, 'ma-repel-adj')) { 1142 | /* setting padding on mx0p or mx1 doesn't work on e.g. or 1143 | elements in Firefox 3.6.12 */ 1144 | if (! (op && tokP[0] && M.prefix_[op] < 25)) 1145 | $(mx0p).after(M.spaceMe('.17em', docP_)); 1146 | M.addClass(e, 'ma-repel-adj'); 1147 | } 1148 | mx0p = e; 1149 | tokP = mxP_tokP[1]; 1150 | } 1151 | } else { 1152 | var moP = tokP[0]; // could be an embellished in {↖ } 1153 | if (moP) { 1154 | var precL = M.infix_[op] || M.postfix_[op]; 1155 | if (precL && prec >= precL) break; 1156 | var precROpt = M.infix_[op] || ! (mx0p && M.postfix_[op]) && M.prefix_[op]; 1157 | if (! M.MathML && ! mx0p && 290 <= precROpt && precROpt <= 350) { 1158 | $(moP).addClass('fm-large-op'); 1159 | //+ omit if fm-inline: 1160 | moP.fmUp = 0.85*1.3 - 0.25; 1161 | moP.fmDn = 0.35*1.3 + 0.25; 1162 | } 1163 | var meTok_tokP = parseEmbel(tokP), a = []; 1164 | meTok_tokP[0] || F.err(err_parse_mxP_tokP_embel_); 1165 | var extOp = meTok_tokP[0][0]; 1166 | tokP = meTok_tokP[1]; 1167 | if (mx0p) a.push(mx0p); 1168 | a.push(extOp); 1169 | if (precROpt) { 1170 | var mxP_tokP = parse_mxP_tokP(precROpt, tokP); 1171 | if (mxP_tokP[0]) a.push(mxP_tokP[0]); 1172 | tokP = mxP_tokP[1]; 1173 | if (precROpt < 25 && ! mx0p) { // check for fences 1174 | if (! tokP) tokP = scanTokP(); 1175 | if (tokP && tokP[1] && tokP[0] 1176 | && (M.postfix_[tokP[1]] || M.infix_[tokP[1]]) == precROpt) { 1177 | // don't parseEmbel() here [after fences] 1178 | a.push(tokP[0]); 1179 | tokP = null; 1180 | } 1181 | } 1182 | } 1183 | if (a.length == 1) mx0p = a[0]; 1184 | else if (op == '/' && mx0p && a.length == 3 1185 | || op == '\u221A' /* √ */ && ! mx0p && a.length == 2) { 1186 | if (op == '\u221A' && M.mtagName(a[0]) == 'msup') 1187 | mx0p = M.newMe('mroot', [a[1], M.mchilds(a[0])[1]], docP_); 1188 | else { 1189 | a.splice(a.length - 2, 1); 1190 | mx0p = M.newMe(op == '/' ? 'mfrac' : 'msqrt', a, docP_); 1191 | } 1192 | } else { 1193 | var e = M.newMe('mrow', a, docP_); 1194 | if (op == '\u2009' /*   */ || (precL || precROpt) >= precAdj_) 1195 | ; 1196 | else { 1197 | var k = ''; 1198 | if (op == '=') k = 'infix-loose'; 1199 | else if (a.length == 2) { 1200 | k = mx0p ? 'postfix' : 'prefix'; 1201 | if (M.infix_[op]) k += '-tight'; 1202 | else { 1203 | if (/^[∀∃∄∂∇]$/.test(op)) k = 'quantifier'; 1204 | M.addClass(e, 'ma-repel-adj'); 1205 | } 1206 | } else if (mx0p) { // a.length == 3 && not fences 1207 | k = op == ',' || op == ';' ? 'separator' : 1208 | precL <= 270 ? 'infix-loose' : 'infix'; 1209 | if (op == '|' && M.MathML && moP.tagName == 'mo') { 1210 | // Firefox work-around 1211 | moP.setAttribute('lspace', '.11em'); 1212 | moP.setAttribute('rspace', '.11em'); 1213 | } 1214 | } 1215 | if (! M.MathML && k && ! moP.style.fontSize) 1216 | $(extOp).addClass('fm-'+k); 1217 | } 1218 | mx0p = e; 1219 | } 1220 | } else if (op == '}') break; 1221 | else if (M.macro1s_[op]) { 1222 | ! mx0p || F.err(err_parse_mxP_tokP_macro_); 1223 | var mxP_tokP = M.macro1s_[op](); 1224 | mx0p = mxP_tokP[0]; 1225 | tokP = mxP_tokP[1]; 1226 | } else { 1227 | embelWs_[op] || F.err(err_parse_mxP_tokP_script_); 1228 | if (prec >= 999) break; 1229 | var meTok_tokP = parseEmbel(mx0p && [mx0p, null], tokP), 1230 | meTok = meTok_tokP[0]; 1231 | meTok || F.err(err_parse_mxP_tokP_embel_2_); 1232 | tokP = meTok_tokP[1]; 1233 | var a = [meTok[0]], opP = meTok[1]; 1234 | if (opP) { 1235 | var precROpt = M.infix_[opP] || M.prefix_[opP]; 1236 | if (precROpt) { 1237 | var mxP_tokP = parse_mxP_tokP(precROpt, tokP); 1238 | if (mxP_tokP[0]) a.push(mxP_tokP[0]); 1239 | tokP = mxP_tokP[1]; 1240 | } 1241 | } 1242 | mx0p = a.length == 1 ? a[0] : M.newMe('mrow', a, docP_); 1243 | } 1244 | } 1245 | } 1246 | return [mx0p, tokP]; 1247 | } 1248 | M.sMxAToMe = function(g /* string, mx, or array of strings and mxs */, docP) { 1249 | if (! docP) docP = document; 1250 | M.infix_[''] && M.infix_[','] || F.err(err_sToMe_1_); 1251 | 1252 | if (M.MathML === undefined) M.MathML = M.canMathML(); 1253 | M.re_.lastIndex = 0; 1254 | s_ = ''; 1255 | s_or_mx_a_ = Array.isArray(g) ? g : [g]; 1256 | s_or_mx_i_ = 0; 1257 | docP_ = docP; 1258 | precAdj_ = M.infix_['']; 1259 | 1260 | var mxP_tokP = parse_mxP_tokP(0); 1261 | if (mxP_tokP[1]) 1262 | throw 'Extra input: ' + mxP_tokP[1][1] + s_.substring(M.re_.lastIndex) + 1263 | (s_or_mx_i_ < s_or_mx_a_.length ? '...' : ''); 1264 | if (M.re_.lastIndex < s_.length || s_or_mx_i_ < s_or_mx_a_.length) F.err(err_sToMe_2_); 1265 | return mxP_tokP[0] || emptyMe_(); 1266 | }; 1267 | M.sToMathE = function(g, blockQ, docP) /* parses strings and includes MathML subexpression 1268 | elements into an XML 'math' or HTML 'fmath' element */ { 1269 | var res = M.sMxAToMe(g, docP); 1270 | if (! F.elem(M.mtagName(res), ['math', 'fmath'])) res = M.newMe('math', res, docP); 1271 | if (typeof g == 'string') res.setAttribute('alttext', g); 1272 | return M.setMathBlockQ(res, blockQ); 1273 | }; 1274 | 1275 | /* Like TeX, we use $ or \( \), and $$ or \[ \], to delimit inline and block ("display") 1276 | mathematics, respectively. Use \$ for an actual $ instead, or \\ for \ if necessary. 1277 | */ 1278 | M.$mathQ = true; // whether $ acts as an (inline) math delimiter 1279 | M.inline$$Q = false; /* whether $$ $$ or \[ \] in a

or should be wrapped in an 1280 | inline-block */ 1281 | M.parseMath = function(nod) { 1282 | if (nod.nodeType == 1 /* Element */ && nod.tagName != 'SCRIPT') { 1283 | if (nod.tagName.toUpperCase() == 'MATH') { 1284 | var newE = M.eToMathE(nod); 1285 | if (newE != nod) nod.parentNode.replaceChild(newE, nod); 1286 | } else 1287 | for (var p = nod.firstChild; p; ) { 1288 | var restP = p.nextSibling; // do before splitting 'p' 1289 | M.parseMath(p); 1290 | p = restP; 1291 | } 1292 | } else if (nod.nodeType == 3 /* Text */ && /[$\\]/.test(nod.data) /* for speed */) { 1293 | var doc = nod.ownerDocument, s = nod.data, a = [], t = '', 1294 | re = /\\([$\\])|\$\$?|\\[([]/g; 1295 | while (true) { 1296 | var j = re.lastIndex, m = re.exec(s), k = m ? m.index : s.length; 1297 | if (j < k) t += s.substring(j, k); 1298 | if (m && m[1]) t += m[1]; 1299 | else { 1300 | var i = -1, z; 1301 | if (m) { 1302 | z = m[0] == '\\(' ? '\\)' : m[0] == '\\[' ? '\\]' : m[0]; 1303 | if (re.lastIndex < s.length && (m[0] != '$' || M.$mathQ)) { 1304 | i = s.indexOf(z, re.lastIndex); 1305 | while (i != -1 && s.charAt(i - 1) == '\\') i = s.indexOf(z, i + 1); 1306 | } 1307 | if (i == -1) { 1308 | t += m[0]; 1309 | continue; 1310 | } 1311 | } 1312 | if (t) { 1313 | a.push(doc.createTextNode(t)); 1314 | t = ''; 1315 | } 1316 | if (! m) break; 1317 | var blockQ = m[0] == '$$' || m[0] == '\\[', 1318 | e = M.sToMathE(s.substring(re.lastIndex, i), blockQ, doc); 1319 | if (blockQ && M.inline$$Q && F.elem(nod.parentNode.nodeName, ['P', 'SPAN'])) 1320 | { 1321 | var wrap$ = $('

', doc).css('display', 'inline-block').append(e); 1322 | wrap$ = $('', doc).css('white-space', 'nowrap').append(wrap$); 1323 | // so Firefox won't line-break between e and a period/comma/etc. 1324 | e = wrap$[0]; 1325 | } 1326 | a.push(e); 1327 | re.lastIndex = i + z.length; 1328 | } 1329 | } 1330 | F.iter(function(x) { nod.parentNode.insertBefore(x, nod); }, a); 1331 | nod.parentNode.removeChild(nod); 1332 | } 1333 | }; 1334 | M.parseMathQ = true; 1335 | $(function() { 1336 | if (M.MathML === undefined) M.MathML = M.canMathML(); 1337 | if (M.parseMathQ) 1338 | try { 1339 | M.parseMath(document.body); 1340 | } catch(exc) { 1341 | alert(exc); 1342 | } 1343 | }); 1344 | 1345 | if ($.fn.parseMath == null) 1346 | $.fn.parseMath = function() { F.iter(M.parseMath, this); return this; }; 1347 | 1348 | return M; 1349 | }(); 1350 | var M; if (M === undefined) M = jqMath; 1351 | -------------------------------------------------------------------------------- /mathview/src/main/assets/mathscribe/jqmath-etc-0.4.6.min.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2016, Mathscribe, Inc. Released under the MIT license (same as jQuery). 2 | See e.g. http://jquery.org/license for an explanation of this license. */ 3 | "use strict";var jsCurry=function(){function e(t){if("function"==typeof t)return e.curry.apply(void 0,arguments);if(2==arguments.length){var r=arguments[1];if("string"==typeof t)return r[t].bind(r);if("function"==typeof r)return("number"==typeof t?e.aritize:e.partial)(t,r)}return 1==arguments.length||e.err(err_F_1_),"number"==typeof t||"string"==typeof t?e.pToF(t):1==t.nodeType?jQuery.data(t):t&&"object"==typeof t?e.aToF(t):void e.err(err_F_2_)}var t=Array.prototype.slice;return Function.prototype.bind||(Function.prototype.bind=function(e){var r=this,n=t.call(arguments,1);return function(){return r.apply(e,n.concat(t.call(arguments,0)))}}),String.prototype.trim||(String.prototype.trim=function(){return String(this).replace(/^\s+|\s+$/g,"")}),Array.isArray||(Array.isArray=function(e){return"object"==typeof e&&null!==e&&"[object Array]"===Object.prototype.toString.call(e)}),Object.keys||(Object.keys=function(e){var t=[];for(var r in e)e.hasOwnProperty(r)&&t.push(r);return t}),Date.now||(Date.now=function(){return(new Date).getTime()}),e.err=function(){throw e.debug,Error("Assertion failed")},e.id=function(e){return e},e.constant=function(e){return function(){return e}},e.applyF=function(e,t){return e.apply(void 0,t)},e.curry=function(e){var t=e;return arguments[0]=void 0,t.bind.apply(t,arguments)},e._={},e.partial=function(r,n){var a=r.length;return function(){for(var i=t.call(arguments,0),s=0;a>s;s++)r[s]!==e._?i.splice(s,0,r[s]):i.length==s&&i.push(void 0);return n.apply(this,i)}},e.uncurry=function(e){return function(t,r){return e(t)(r)}},e.o=function(){var e=arguments;return function(){for(var t=e.length,r=e[--t].apply(void 0,arguments);t>0;)r=e[--t](r);return r}},e.oMap=function(t,r){return function(){return e.applyF(t,e.map(r,arguments))}},e.flip=function(e){return function(t,r){return e(r,t)}},e.seqF=function(){var e=arguments,t=e.length;return function(){for(var r,n=0;t>n;n++)r=e[n].apply(void 0,arguments);return r}},e.cor=function(){var t=arguments;return function(){return e.any(e([e._,arguments],e.applyF),t)}},e.aritize=function(r,n){return function(){return e.applyF(n,t.call(arguments,0,r))}},e.not=function(e){return!e},e.defOr=function(e,t){return void 0!==e?e:t},e.cmpX=function(e,t){return e-t},e.cmpJS=function(e,t){return t>e?-1:e==t?0:1},e.cmpLex=function(t,r,n){return e.any(function(e,r){return r==n.length?1:t(e,n[r])},r)||r.length-n.length},e.eqTo=function(t,r){return r||(r=function(e,t){return e!==t}),e.o(e.not,e(r,t))},e.pToF=function(e){return function(t){return t[e]}},e.aToF=function(e){return function(t){return e[t]}},e.fToA=function(e,t){for(var r=new Array(t),n=0;t>n;n++)r[n]=e(n);return r},e.memoF=function(e,t){return t||(t={}),function(r){return t.hasOwnProperty(r)?t[r]:t[r]=e(r)}},e.replicate=function(t,r){return e.fToA(e.constant(r),t)},e.setF=function(e,t,r){e[t]=r},e.obj1=function(e,t){var r={};return r[e]=t,r},e.slice=function(e,t,r){if(null==t&&(t=0),Array.isArray(e))return e.slice(t,r);var n=e.length;t=0>t?Math.max(0,n+t):Math.min(n,t),r=void 0===r?n:0>r?Math.max(0,n+r):Math.min(n,r);for(var a=[];r>t;)a.push(e[t++]);return a},e.array=function(){return t.call(arguments,0)},e.concatArgs=e.oMap(e("concat",[]),function(t){return Array.isArray(t)?t:e.slice(t)}),e.concatMap=function(t,r){return e.applyF(e.concatArgs,e.map(t,r))},e.reverseCopy=function(t){return e.slice(t).reverse()},e.findIndex=function(e,t){for(var r=t.length,n=0;r>n;n++)if(e(t[n],n,t))return n;return-1},e.findLastIndex=function(e,t){for(var r=t.length;--r>=0;)if(e(t[r],r,t))return r;return-1},e.find=function(t,r){var n=e.findIndex(t,r);return-1==n?void 0:r[n]},e.elemIndex=function(t,r,n){return r.indexOf&&!n&&Array.isArray(r)?r.indexOf(t):e.findIndex(e.eqTo(t,n),r)},e.elemLastIndex=function(t,r,n){return r.lastIndexOf&&!n&&Array.isArray(r)?r.lastIndexOf(t):e.findLastIndex(e.eqTo(t,n),r)},e.elem=function(t,r,n){return-1!=e.elemIndex(t,r,n)},e.all=function(e,t){if(t.every&&Array.isArray(t))return t.every(e);for(var r=t.length,n=0;r>n;n++)if(!e(t[n],n,t))return!1;return!0},e.any=function(e,t){for(var r=t.length,n=!1,a=0;r>a;a++)if(n=e(t[a],a,t))return n;return n},e.iter=function(r,n){if(2==arguments.length){if(n.forEach&&Array.isArray(n))return n.forEach(r);for(var a=n.length,i=0;a>i;i++)r(n[i],i,n)}else{arguments.length>2||e.err(err_iter_);for(var s=t.call(arguments,1),a=e.applyF(Math.min,e.map(e("length"),s)),i=0;a>i;i++)e.applyF(r,e.map(e(i),s).concat(i,s))}},e.map=function(e,t){if(t.map&&Array.isArray(t))return t.map(e);for(var r=t.length,n=new Array(r),a=0;r>a;a++)n[a]=e(t[a],a,t);return n},e.map1=function(t,r){return e.map(e(1,t),r)},e.zipWith=function(t){arguments.length>1||e.err(err_zipWith_);for(var r=[],n=0;;n++){for(var a=[],i=1;ii;i++)n=t(n,r[i],i,r);return n},e.foldR=function(t,r,n){if(r.reduceRight&&Array.isArray(r))return arguments.length<3?r.reduceRight(t):r.reduceRight(t,n);var a=r.length;for(arguments.length<3&&(n=a?r[--a]:e.err(err_foldR_));--a>=0;)n=t(n,r[a],a,r);return n},e.sum=function(e){for(var t=e.length,r=0,n=0;t>n;n++)r+=e[n];return r},e.test=function(t){if((0===t||""===t)&&(t=typeof t),"string"==typeof t)return function(e){return typeof e==t};if(t===Array||t===Date||t===RegExp)return function(e){return null!=e&&e.constructor==t};if(null===t)return e.eqTo(null);if(t.constructor==RegExp)return e("test",t);if("function"==typeof t)return t;if(Array.isArray(t))return 1==t.length?(t=e.test(t[0]),function(r){return Array.isArray(r)&&e.all(t,r)}):(t=e.map(e.test,t),function(r){return e.any(function(e){return e(r)},t)});if("object"==typeof t){var r=Object.keys(t),n=e.map(e.o(e.test,e(t)),r);return function(t){return null!=t&&e.all(function(e,r){return n[r](t[e])},r)}}e.err(err_test_)},e.translations_={},e.s=function(t){return e.translations_[t]||t},e}(),F;void 0===F&&(F=jsCurry),"object"==typeof module&&(module.exports=jsCurry);var jqMath=function(){function e(t,r,n){return"number"==typeof t&&(t=String(t)),"string"==typeof t||Array.isArray(t)?e.sToMathE(t,r,n):1==t.nodeType&&"math"==t.tagName.toLowerCase()?e.eToMathE(t):void O.err(err_M_)}function t(t,r,n){return null==r||("string"==typeof r?t.appendChild(t.ownerDocument.createTextNode(r)):r.nodeType?t.appendChild(r):(r.constructor!=Array&&(r=O.slice(r)),O.iter(function(e){t.appendChild(e)},r))),e.setAttrs(t,n)}function r(r){function n(t){return i.createElementNS(e.mathmlNS,t)}if(e.MathML&&!E)return r;var a=r.tagName.toLowerCase(),i=r.ownerDocument;if("mi"==a)!r.getAttribute("mathvariant")&&r.firstChild&&3==r.firstChild.nodeType&&r.setAttribute("mathvariant",1==r.firstChild.data.length?"italic":"normal");else if("mo"==a){if(1==r.childNodes.length&&3==r.firstChild.nodeType){var s=r.firstChild.data;/^[\u2061-\u2064]$/.test(s)&&e.addClass(r,"ma-non-marking")}}else if("mspace"==a)e.webkitVersion&&e.MathML&&(r.style.display="inline-block",r.style.minWidth=r.getAttribute("width")||"0px");else if("menclose"==a)e.webkitVersion&&e.MathML&&e.addClass(r,"fm-menclose");else if("mmultiscripts"==a&&e.webkitVersion){var o=O.slice(r.childNodes);if(0==o.length)throw"Wrong number of arguments: 0";for(var u=[o[0]],l=1;l";var m=[u[0],o[l],o[l+1]];l++,u[0]=n("msubsup"),O.iter(function(e){u[0].appendChild(e)},m)}else u.unshift(n("none"));var f=r;r=t(n("mrow"),u,r.attributes),f.parentNode&&f.parentNode.replaceChild(r,f)}var c=r.getAttribute("mathcolor"),p=r.getAttribute("href");if(c&&r.style&&(r.style.color=c),p&&(!e.MathML||e.webkitVersion)){var d=i.createElement("A"),h=r.parentNode,g=r.nextSibling;d.appendChild(r),d.href=p,r=d,h&&h.insertBefore(r,g)}return r}function n(n,a,i,s){s||(s=document);var o=e.MathPlayer?s.createElement("m:"+n):s.createElementNS(e.mathmlNS,n);return r(t(o,a,i))}function a(t,r,n,a){if("mo"==n.nodeName.toLowerCase()&&1==n.childNodes.length){var i=n.firstChild,s=i.data;if(3==i.nodeType&&(t>.9||r>.9)&&(e.prefix_[s]<25||e.postfix_[s]<25||-1!="|‖√".indexOf(s)||a)){var o=(t+r)/1.2,u="√"==s,l=(u?.26:.35)+((u?.15:.25)-r)/o;n.style.fontSize=o.toFixed(3)+"em",n.style.verticalAlign=l.toFixed(3)+"em",n.fmUp=t,n.fmDn=r,n.style.display="inline-block",n.style.transform=n.style.msTransform=n.style.MozTransform=n.style.WebkitTransform="scaleX(0.5)"}}}function i(e,t,r){var n=D("").append(r);return n[0].fmUp=e,n[0].fmDn=t,n[0].style.verticalAlign=(.5*(e-t)).toFixed(3)+"em",n}function s(e,t){O.iter(function(t){var r=t[0];O.iter(function(t){e[t]=r},t[1].split(""))},t)}function o(t,r,n){return e.newMe(t,r,n,H)}function u(){return o("mspace")}function l(t){var r=/\s*([-\w.]*)/g;r.lastIndex=e.re_.lastIndex;var n=r.exec(Q);if(!n[1])throw"Missing "+(t||"word");return e.re_.lastIndex=r.lastIndex,n[1]}function m(t){var r=/\s*(?:(["'])|([-\w.]*))/g;r.lastIndex=e.re_.lastIndex;var n=r.exec(Q);if(n[2])return e.re_.lastIndex=r.lastIndex,n[2];if(!n[1])throw"Missing "+(t||"string");var a=n[1],i=RegExp("[^\\`"+a+"]+|[\\`](.|\n)|("+a+")","g"),s="";for(i.lastIndex=r.lastIndex;;){if(n=i.exec(Q),!n)throw"Missing closing "+a;if(n[2])break;s+=n[1]||n[0]}return e.re_.lastIndex=i.lastIndex,s}function f(t){var r=N();if(!r||!r[0])throw"Missing expression argument"+(t?" after "+t:"")+", before position "+e.re_.lastIndex;return r}function c(e){var t=m("mtext"==e?"text":e);return[o(e,t),"mo"==e?t:null]}function p(){if(!e.trustHtml)throw"\\html use requires M.trustHtml";var t=m("html"),r=D("
",H||document).css("display","inline-block").html(t)[0];return 1==r.childNodes.length&&(r=r.childNodes[0]),[o("mtext",r),null]}function d(){var t=m("\\sp width");return[e.spaceMe(t,H),/^[^-]*[1-9]/.test(t)?" ":null]}function h(){var t=N();if(t&&"↖"==t[1]&&!t[0]){var r=P();if(t=r[1]||N(),!r[0]||!t||"}"!=t[1]||t[0])throw'Expected an embellished operator and "}" after "{↖", before position '+e.re_.lastIndex;return r[0]}var n=j(0,t);return t=n[1],!t||"}"==t[1]&&!t[0]||O.err(err_braceScan_),[n[0]||u(),null]}function g(t,r){t||(t=l("attribute name"));var n=m(t+" attribute"),a=f(t);return(!r||e.MathML)&&a[0].setAttribute(t,n),a}function v(){var t="CSS class name(s)",r=m(t),n=f(t);return e.addClass(n[0],r),n}function y(t){var r=t||m("mathvariant"),n=f(r),a=n[0];if(!O.elem(e.mtagName(a),["mi","mn","mo","mtext","mspace","ms"]))throw"Can only apply a mathvariant to a MathML token (atomic) element, at position "+e.re_.lastIndex;return a.setAttribute("mathvariant",r),/bold/.test(r)?e.addClass(a,"ma-bold"):("normal"==r||"italic"==r)&&e.addClass(a,"ma-nonbold"),e.addClass(a,/italic/.test(r)?"ma-italic":"ma-upright"),/double-struck/.test(r)?e.addClass(a,"ma-double-struck"):/fraktur/.test(r)?e.addClass(a,"ma-fraktur"):/script/.test(r)?e.addClass(a,"ma-script"):/sans-serif/.test(r)&&e.addClass(a,"ma-sans-serif"),n}function M(e){e||(e=l("tagName"));var t=f({menclose:"enclose"}[e]||e);return[o(e,t[0]),O.elem(e,["mstyle","mpadded"])?t[1]:null]}function b(e){var t=f(e);return O.iter(function(e){e.disabled=!0},D("input",t[0])),"vphantom"==e&&(t[0]=o("mpadded",t[0],{width:"0",style:"display: inline-block; width: 0"})),[o("mphantom",t[0]),t[1]]}function _(){return[e.menclose(f("\\ov")[0],{notation:"top"},H),null]}function x(){var t=m("minsize"),r=f("minsize"),n=r[0];if("mo"!=e.mtagName(n))throw"Can only stretch an operator symbol, before position "+e.re_.lastIndex;if(e.MathML)n.setAttribute("minsize",t);else{var i=/^(.+)em$/.exec(t);i&&(t=i[1]);var s=Number(t);s>1?a(.6*s,.6*s,n,!0):s||(n.style.fontSize=t)}return r}function w(){return[o("mrow",f("\\mrowOne")[0]),null]}function A(){function t(e){return o("mtr",o("mtd",e))}var r=f("\\binom")[0],n=f("\\binom")[0],a=o("mtable",O.map(t,[r,n]));return e.addClass(a,"ma-binom"),e.MathML||(a.fmUp-=.41,a.fmDn-=.41),[o("mrow",[o("mo","("),a,o("mo",")")]),null]}function N(){for(var t=e.re_.exec(Q);!t;){if(e.re_.lastIndex=Q.length,W==V.length)return null;var r=V[W++];if("string"==typeof r)e.re_.lastIndex=0,Q=r,t=e.re_.exec(Q);else{if(1==r.nodeType)return[r,null];O.err(err_scanTokP_)}}var n=t[2]||t[0],a=null;if(/^[_^}\u2196\u2199]$/.test(t[0])||t[2]&&e.macro1s_[n])return[null,n];if("{"==t[0])return h();if(t[2]&&e.macros_[n])return e.macros_[n]();if(t[1])return[e.newMe("mn",n,H),null];if(/^[,:;!]$/.test(t[2]))n=" ";else if("/"==t[2])n="∕";else if(e.alias_[n]&&!t[2]){var i=e.alias_[n];"string"==typeof i?n=i:(n=i[0],a=i[1])}var s,u=e.infix_[n]||e.prefix_[n]||e.postfix_[n]?n:null;if(" "==n)s=e.spaceMe(Z[t[2]||","],H);else if(u){if(/^[∛∜]$/.test(n)&&!t[2])return s=o("mn","∛"==n?"3":"4"),[o("msup",[o("mo","√"),s]),"√"];s=e.newMe("mo",n,H),/^[∀∃∄∂∇]$/.test(n)?(s.setAttribute("lspace",".11em"),s.setAttribute("rspace",".06em")):"!"==n?(s.setAttribute("lspace",".06em"),s.setAttribute("rspace","0")):"×"==n&&(s.setAttribute("lspace",".22em"),s.setAttribute("rspace",".22em"))}else s=e.newMe("mi",n,H),t[2]&&1==n.length?(s.setAttribute("mathvariant","normal"),e.addClass(s,"ma-upright"),e.MathML||(s.style.paddingRight="0")):a&&(s.setAttribute("mathvariant",a),e.addClass(s,"ma-upright"),e.addClass(s,"ma-"+a)),/\w\w/.test(n)&&e.addClass(s,"ma-repel-adj");return[s,u]}function C(t){var r=j(e.infix_[","]),n=r[1]||N(),a=r[0];if(!a){if(t&&(!n||","!=n[1]))return[null,n];a=u()}var i=e.mtagName(a);return"mtd"==i||"mtr"==i&&t||(a=e.newMe("mtd",a,H)),[a,n]}function k(){var t=m("rowspan"),r=C(),n=r[0];return n.setAttribute(e.MathML?"rowspan":"rowSpan",t),e.hasClass(n,"middle")||e.addClass(n,"middle"),r}function T(){var t=m("colspan"),r=C();return r[0].setAttribute(e.MathML?"columnspan":"colSpan",t),r}function L(t){for(var r=[];;){var n=C(0==r.length),a=n[0],i=n[1]||N();if(a){if("mtr"==e.mtagName(a))return[a,i];r.push(a)}if(!i||","!=i[1])return[r.length||!t||i&&";"==i[1]?e.newMe("mtr",r,H):null,i]}}function S(t){void 0===t&&(t=e.dtableQ);for(var r=[];;){var n=L(0==r.length),a=n[0],i=n[1]||N();if(a&&r.push(a),!i||";"!=i[1])return[o("mtable",r,t?{displaystyle:!0}:void 0),i]}}function I(){var t=j(0);return t[0]=e.newMe("math",t[0],H),t}function F(e){var t=J[e];return t&&(t.length<4?"ss":"uo")}function P(t,r){for(;;){if(r||(r=N()),!r||r[0]||!J[r[1]]){if(r&&!t){t=r,r=null;continue}return[t,r]}var n=F(r[1]),a=function(){for(var e={},t={};;){if(r||(r=N()),!r||r[0])break;var a=r[1];if(F(a)!=n||t[a])break;if(t[a]=!0,r=N(),!r||F(r[1])!=n||r[0]){var i=j(999,r);e[a]=i[0],r=i[1]}}return e},i=a();if("uo"==n||!r||(r[0]?t:"ss"!=F(r[1]))){t||(t=[u(),null]);var s="m",o=[t[0]];O.iter(function(e){i[e]&&(s+=J[e],o.push(i[e]))},["_","^","↙","↖"]),o.length>1&&(t=[e.newMe(s,o,H),t[1]])}else{for(var l=[i];r&&!r[0]&&"ss"==F(r[1]);)l.push(a());if(!t)if(r&&r[0]){t=r,r=N();for(var m=[];r&&!r[0]&&"ss"==F(r[1]);)m.push(a());l=m.concat(null,l)}else t=[u(),null];var o=[t[0]];O.iter(function(t){t?o.push(t._||e.newMe("none",void 0,H),t["^"]||e.newMe("none",void 0,H)):o.push(e.newMe("mprescripts",void 0,H))},l),t=[e.newMe("mmultiscripts",o,H),t[1]]}}}function j(t,r){for(var n=null;;){if(!r&&(r=N(),!r))break;var a=r[1];if(!a||n&&(r[0]?!(e.infix_[a]||e.postfix_[a]):e.macro1s_[a]))if(n){if(t>=X)break;var i=j(X,r),s=i[0];s||O.err(err_parse_mxP_tokP_1_);var o=e.newMe("mrow",[n,s],H);(e.hasClass(n,"ma-repel-adj")||e.hasClass(s,"ma-repel-adj"))&&(a&&r[0]&&e.prefix_[a]<25||D(n).after(e.spaceMe(".17em",H)),e.addClass(o,"ma-repel-adj")),n=o,r=i[1]}else n=r[0],r=null;else{var u=r[0];if(u){var l=e.infix_[a]||e.postfix_[a];if(l&&t>=l)break;var m=e.infix_[a]||!(n&&e.postfix_[a])&&e.prefix_[a];!e.MathML&&!n&&m>=290&&350>=m&&(D(u).addClass("fm-large-op"),u.fmUp=.855,u.fmDn=.705);var f=P(r),c=[];f[0]||O.err(err_parse_mxP_tokP_embel_);var p=f[0][0];if(r=f[1],n&&c.push(n),c.push(p),m){var i=j(m,r);i[0]&&c.push(i[0]),r=i[1],25>m&&!n&&(r||(r=N()),r&&r[1]&&r[0]&&(e.postfix_[r[1]]||e.infix_[r[1]])==m&&(c.push(r[0]),r=null))}if(1==c.length)n=c[0];else if("/"==a&&n&&3==c.length||"√"==a&&!n&&2==c.length)"√"==a&&"msup"==e.mtagName(c[0])?n=e.newMe("mroot",[c[1],e.mchilds(c[0])[1]],H):(c.splice(c.length-2,1),n=e.newMe("/"==a?"mfrac":"msqrt",c,H));else{var o=e.newMe("mrow",c,H);if(" "==a||(l||m)>=X);else{var d="";"="==a?d="infix-loose":2==c.length?(d=n?"postfix":"prefix",e.infix_[a]?d+="-tight":(/^[∀∃∄∂∇]$/.test(a)&&(d="quantifier"),e.addClass(o,"ma-repel-adj"))):n&&(d=","==a||";"==a?"separator":270>=l?"infix-loose":"infix","|"==a&&e.MathML&&"mo"==u.tagName&&(u.setAttribute("lspace",".11em"),u.setAttribute("rspace",".11em"))),e.MathML||!d||u.style.fontSize||D(p).addClass("fm-"+d)}n=o}}else{if("}"==a)break;if(e.macro1s_[a]){!n||O.err(err_parse_mxP_tokP_macro_);var i=e.macro1s_[a]();n=i[0],r=i[1]}else{if(J[a]||O.err(err_parse_mxP_tokP_script_),t>=999)break;var f=P(n&&[n,null],r),h=f[0];h||O.err(err_parse_mxP_tokP_embel_2_),r=f[1];var c=[h[0]],g=h[1];if(g){var m=e.infix_[g]||e.prefix_[g];if(m){var i=j(m,r);i[0]&&c.push(i[0]),r=i[1]}}n=1==c.length?c[0]:e.newMe("mrow",c,H)}}}}return[n,r]}var D=jQuery,O=jsCurry;Math.sign||(Math.sign=function(e){return e=Number(e),e>0?1:0>e?-1:e}),Math.trunc||(Math.trunc=function(e){return(0>e?Math.ceil:Math.floor)(e)}),e.toArray1=function(e){return Array.isArray(e)?e:[e]},e.getSpecAttrP=function(e,t){var r=e.getAttributeNode(t);return r&&r.specified!==!1?r.value:void 0},e.objToAttrs=function(e){var t=[];for(var r in e)t.push({name:r,value:e[r]});return t},e.setAttrs=function(t,r){return r&&null==r.length&&(r=e.objToAttrs(r)),O.iter(function(e){e.specified!==!1&&t.setAttribute(e.name,e.value)},r||[]),t},e.replaceNode=function(e,t){return t.parentNode.replaceChild(e,t),e},e.addClass=function(e,t){if("undefined"!=typeof e.className){var r=e.className;e.className=(r?r+" ":"")+t}else{var r=e.getAttribute("class");e.setAttribute("class",(r?r+" ":"")+t)}return e},e.eToClassesS=function(e){var t="undefined"!=typeof e.className?e.className:e.getAttribute("class");return t||""},e.hasClass=function(t,r){return-1!=(" "+e.eToClassesS(t)+" ").replace(/[\n\t]/g," ").indexOf(" "+r+" ")},e.inlineBlock=function(){var e=D("
").css("display","inline-block");return arguments.length&&e.append.apply(e,arguments),e[0]},e.tr$=function(){function t(t){return r.apply(D("
"),O.map(t,arguments))},e.mathmlNS="http://www.w3.org/1998/Math/MathML";var E=!1;!function(){var t=navigator.userAgent.toLowerCase(),r=t.match(/webkit[ \/](\d+)\.(\d+)/);r?(e.webkitVersion=[Number(r[1]),Number(r[2])],E=e.webkitVersion[0]<=540):(r=t.match(/(opera)(?:.*version)?[ \/]([\w.]+)/)||t.match(/(msie) ([\w.]+)/)||t.indexOf("compatible")<0&&t.match(/(mozilla)(?:.*? rv:([\w.]+))?/),r&&(e[r[1]+"Version"]=r[2]||"0"))}(),e.msieVersion&&document.write('',''),function(){if(self.location){var t=location.search.match(/[?&;]mathml=(?:(off|false)|(on|true))\b/i);t?e.MathML=!t[1]:(e.webkitVersion&&O.cmpLex(O.cmpX,e.webkitVersion,[537,17])<0||e.operaVersion)&&(e.MathML=!1)}}(),e.canMathML=function(){function t(e){return e.setAttribute("display","block"),D("
").append(e)[0]}if(e.msieVersion&&!e.MathPlayer)try{if(new ActiveXObject("MathPlayer.Factory.1"),null==e.MathPlayer)e.MathPlayer=!0;else if(!e.MathPlayer)return!1}catch(r){e.MathPlayer=!1}if(!e.MathPlayer&&"undefined"==typeof document.createElementNS)return!1;var a=n("math",n("mn","1")),i=n("math",n("mfrac",[n("mn","1"),n("mn","2")])),s=D(O.map(t,[a,i]));s.css("visibility","hidden").appendTo(document.body);var o=D(s[1]).height()>D(s[0]).height()+2;return s.remove(),o},e.mtagName=function(e){return"A"==e.tagName&&1==e.childNodes.length&&(e=e.firstChild),e.getAttribute("mtagname")||e.tagName.toLowerCase().replace(/^m:/,"")},e.mchilds=function(e){function t(e){return"SPAN"==e.tagName||O.err(err_span0_),e.firstChild}"A"==e.tagName&&1==e.childNodes.length&&(e=e.firstChild);for(var r=e.getAttribute("mtagname");"SPAN"==e.tagName;)e=e.firstChild;if("TABLE"==e.tagName){if(e=e.firstChild,"TBODY"==e.tagName||O.err(err_mchilds_tbody_),"mtable"==r)return e.childNodes;var n=e.childNodes;return"mover"==r?n=[n[1],n[0]]:"munderover"==r&&(n=[n[1],n[2],n[0]]),O.map(function(e){return e.firstChild.firstChild},n)}if("MROW"==e.tagName&&r){var n=e.childNodes;if("msqrt"==r)return[t(t(n[1]))];if("mroot"==r)return[t(t(n[2])),t(n[0])];"mmultiscripts"==r||O.err(err_mchilds_mrow_);var a=Number(e.getAttribute("nprescripts"));a>=0&&as;s++)i.push(t(n[s]))}return i}return O.elem(e.tagName,["MSUB","MSUP","MSUBSUP"])?O.map(function(e,r){return r?t(e):e},e.childNodes):"MSPACE"==e.tagName?[]:e.childNodes};var $=["mn","mi","mo","mtext","mspace","ms"],z=["fmath","msqrt","mtd","mstyle","merror","mpadded","mphantom","menclose"],R={"¯":[0,.85],"‾":[0,.85],"˙":[0,.75],"ˇ":[0,.7],"^":[0,.5],"~":[0,.4],"→":[.25,.25],_:[.7,0],"−":[.25,.45],".":[.6,.1]};e.newMe=function(s,o,u,l){if(l||(u&&9==u.nodeType?(l=u,u=void 0):l=document),null!=e.MathML||O.err(err_newMe_MathML_),e.MathML)return n(s,o,u,l);"math"==s&&(s="fmath");var m=D(t(l.createElement(s.toUpperCase()),o)),f=O.slice(m[0].childNodes);O.elem(s,z)&&1!=f.length&&(f=[e.newMe("mrow",f,void 0,l)],0==m[0].childNodes.length||O.err(err_newMe_imp_mrow_),m.append(f[0]));var c=O.map(function(e){return Number(e.fmUp||.6)},f),p=O.map(function(e){return Number(e.fmDn||.6)},f);if("fmath"==s||"mn"==s||"mtext"==s||"mprescripts"==s||"none"==s);else if("mstyle"==s||"merror"==s||"mpadded"==s||"mphantom"==s||"menclose"==s)f[0].fmUp&&(m[0].fmUp=f[0].fmUp),f[0].fmDn&&(m[0].fmDn=f[0].fmDn);else if("mi"==s){var d=1==f.length?f[0]:{};3==d.nodeType&&1==d.data.length&&(m.addClass("fm-mi-length-1"),"f"==d.data&&m.css("padding-right","0.44ex"))}else if("mo"==s){var d=1==f.length?f[0]:{};3==d.nodeType&&/[\]|([{‖)}]/.test(d.data)&&m.addClass("fm-mo-Luc")}else if("mspace"==s){var h=e.setAttrs(m[0],u);u=void 0,h.style.marginRight=h.getAttribute("width")||"0px",h.style.paddingRight="0.001em",m.append("‌"),m.css("visibility","hidden")}else if("mrow"==s){var g=O.applyF(Math.max,c),v=O.applyF(Math.max,p);(g>.65||v>.65)&&(m[0].fmUp=g,m[0].fmDn=v,O.iter(O([g,v,O._,void 0],a),f))}else if("mfrac"==s){if(2!=f.length)throw"Wrong number of arguments: "+f.length;var y=D('
',l).append(f[0]),M=D('',l).append(f[1]);m=i(c[0]+p[0]+.03,c[1]+p[1]+.03,D('',l).append(D("
partly so rowspan/colspan work 512 | e$ = $('"),e.toArray1(t))}var r=D.fn.append;return r.apply(D("
",l).append(D("",l).append(D("",l).append(y)).append(D("",l).append(M))))).attr("mtagname",s)}else if("msqrt"==s||"mroot"==s){if(f.length!=("msqrt"==s?1:2))throw"Wrong number of <"+s+"> arguments: "+f.length;m=D("",l).attr("mtagname",s);var b=.06*(c[0]+p[0]),g=c[0]+b+.1,v=p[0];if("mroot"==s){var _=.6*(c[1]+p[1]),x=.25/.6-.25;g>_?x+=g/.6-c[1]:(x+=p[1],g=_),m.append(D('',l).append(f[1]).css("verticalAlign",x.toFixed(2)+"em"))}var w=D("",l).addClass("fm-radic").append("√"),A=i(g,v,D('',l).append(f[0]).css("borderTopWidth",b.toFixed(3)+"em"));a(g,v,w[0]),m.append(w).append(A),m[0].fmUp=g,m[0].fmDn=v}else if("msub"==s||"msup"==s||"msubsup"==s||"mmultiscripts"==s){if("mmultiscripts"!=s&&f.length!=("msubsup"==s?3:2))throw"Wrong number of <"+s+"> arguments: "+f.length;for(var g=c[0],v=p[0],N="msup"==s,C=g/.71-.6,k=v/.71-.6,T=1;T').parent().css("verticalAlign",x.toFixed(2)+"em"),e.msieVersion&&(document.documentMode||e.msieVersion)<8&&(f[T].style.zoom=1),"mmultiscripts"==s&&(S||I).push(f[T].parentNode)}"mmultiscripts"==s&&(m=D("").append(D((S||[]).concat(f[0],I))).attr({mtagname:"mmultiscripts",nprescripts:F})),m[0].fmUp=g,m[0].fmDn=v}else if("munder"==s||"mover"==s||"munderover"==s){if(f.length!=("munderover"==s?3:2))throw"Wrong number of <"+s+"> arguments: "+f.length;var P,j=D("",l),g=.85*c[0],v=.85*p[0];if("munder"!=s){var E=f[f.length-1],$=void 0;if(P=D("",l).append(P))}if("MI"==f[0].nodeName&&1==f[0].childNodes.length){var d=f[0].firstChild,U=d.data;if(3==d.nodeType&&1==U.length){var x=-1!="acegmnopqrsuvwxyz".indexOf(U)?.25:"t"==U?.15:0;x&&(f[0].style.display="block",f[0].style.marginTop=(-x).toFixed(2)+"em",g-=x)}}P=D('',l).append(f[0]),j.append(D("",l).append(P)),"mover"!=s&&(P=D('',l).append(f[1]),j.append(D("",l).append(P)),v+=.71*(c[1]+p[1])),m=i(g,v,D('',l).append(D("
",l).append(E),"MO"==E.nodeName&&1==E.childNodes.length){var d=E.firstChild;3==d.nodeType&&($=R[d.data])}$?(E.style.display="block",E.style.marginTop=(-$[0]).toFixed(2)+"em",E.style.marginBottom=(-$[1]).toFixed(2)+"em",g+=1.2-O.sum($)):(P.addClass("fm-script fm-inline"),g+=.71*(c[f.length-1]+p[f.length-1])),j.append(D("
",l).append(j))).attr("mtagname",s)}else if("mtable"==s){var j=D("",l).append(D(f));m=D('',l).append(D("
",l).append(j));var q=O.sum(c)+O.sum(p);m[0].fmUp=m[0].fmDn=.5*q}else if("mtr"==s){m=D('',l).append(D(f));var g=.6,v=.6;O.iter(function(t,r){1==(t.getAttribute(e.MathML?"rowspan":"rowSpan")||1)&&(g=Math.max(g,c[r]),v=Math.max(v,p[r]))},f),m[0].fmUp=g+.25,m[0].fmDn=v+.25}else{if("mtd"!=s){if("mfenced"==s){var h=e.setAttrs(m[0],u);return e.newMe("mrow",e.mfencedToMRowArgs(h),u,l)}throw"Unrecognized or unimplemented MathML tagName: "+s}m=D('',l).append(D(f)),c[0]>.65&&(m[0].fmUp=c[0]),p[0]>.65&&(m[0].fmDn=p[0]);var h=e.setAttrs(m[0],u);u=void 0;var B=h.getAttribute("rowspan"),Q=h.getAttribute("columnspan");B&&(h.setAttribute("rowSpan",B),e.hasClass(h,"middle")||e.addClass(h,"middle")),Q&&h.setAttribute("colSpan",Q)}return r(e.setAttrs(m[0],u))},e.mfencedToMRowArgs=function(t){function r(t){return e.newMe("mo",t,void 0,n)}"mfenced"==t.tagName.toLowerCase()||O.err(err_mfencedToMRowArgs_);var n=t.ownerDocument,a=[r(O.defOr(e.getSpecAttrP(t,"open"),"(")),r(O.defOr(e.getSpecAttrP(t,"close"),")"))],i=O.slice(t.childNodes);if(0==i.length)return a;var s;if(1==i.length)s=i[0];else{for(var o=O.defOr(e.getSpecAttrP(t,"separators"),",").match(/\S/g),u=o?i.length-1:0,l=0;u>l;l++)i.splice(2*l+1,0,r(o[Math.min(l,o.length-1)]));s=e.newMe("mrow",i,void 0,n)}return a.splice(1,0,s),a},e.spaceMe=function(t,r){return e.newMe("mspace",void 0,{width:t},r)},e.fenceMe=function(t,r,n,a){return e.newMe("mrow",[e.newMe("mo",O.defOr(r,"("),a),t,e.newMe("mo",O.defOr(n,")"),a)],a)},O.iter(function(t){e[t]=O(e.newMe,t)},["mn","mi","mo","mtext","mspace","mrow","mfenced","mfrac","msqrt","mroot","msub","msup","msubsup","mmultiscripts","mprescripts","none","munder","mover","munderover","mtable","mtr","mtd","mstyle","merror","mpadded","mphantom","menclose"]),e.setMathBlockQ=function(t,r){return r?(t.setAttribute("display","block"),e.addClass(t,"ma-block")):e.MathML||D(t).addClass("fm-inline"),t},e.math=function(t,r,n){return e.setMathBlockQ(e.newMe("math",t,n),r)},e.eToMathE=function(t){function n(e){return 1!=e.nodeType?e:(O.elem(e.tagName,$)||O.iter(n,e.childNodes),r(e))}function a(t){function r(r){return 3==r.nodeType?/^\s*$/.test(r.data)?[]:[e.mtext(r.data,i)]:8==r.nodeType?[]:(1==t.nodeType||O.err(err_newMeDeep_),[a(r)])}var n=t.tagName.toLowerCase(),s=t.childNodes;O.elem(n,$)?"mo"==n&&1==s.length&&3==s[0].nodeType&&"-"==s[0].data&&(s=e["-"]):s=O.concatMap(r,s);var o=e.newMe(n,s,t.attributes,i);return"math"==n&&e.setMathBlockQ(o,"block"==t.getAttribute("display")),o}if((null==e.MathML||"math"!=t.tagName.toLowerCase())&&O.err(err_eToMathE_),e.MathML&&"math"==t.tagName)return E?n(t):t;var i=t.ownerDocument;return a(t)},e["-"]="−",e.trimNumS=function(e){return e.replace(/(\d\.\d*?)0+(?!\d)/g,"$1").replace(/(\d)\.(?!\d)/g,"$1").replace(/[-\u2212]0(?![.\d])/g,"0")},e.numS=function(t,r){return r&&(t=e.trimNumS(t)),t.replace(/Infinity/gi,"∞").replace(/NaN/gi,"{?}").replace(/e(-\d+)/gi,"·10^{$1}").replace(/e\+?(\d+)/gi,"·10^$1").replace(/-/g,e["-"])},e.combiningChar_="[̀-ͯ᷀-᷿⃐-⃿︠-︯]",e.surrPair_="[�-�][�-�]";var U,q="[\\\\`]([A-Za-z]+|.)";e.decimalComma=function(t){if(null!=t){U=t;var r=(t?"\\d*,\\d+|":"")+"\\d+\\.?\\d*|\\.\\d+";e.re_=RegExp("("+r+")|"+q+"|"+e.surrPair_+"|\\S"+e.combiningChar_+"*","g")}return U};var B="af|an|ar|av|az|ba|be|bg|bs|ca|ce|co|cs|cu|cv|da|de|el|es|et|eu|fi|fo|fr|gl|hr|hu|hy|id|is|it|jv|kk|kl|kv|lb|lt|lv|mk|mn|mo|nl|no|os|pl|pt|ro|ru|sc|sk|sq|sr|su|sv|tr|tt|ug|uk|vi|yi";e.decimalComma(RegExp("^("+B+")\\b","i").test(document.documentElement.lang)),e.infix_={"⊂⃒":240,"⊃⃒":240,"≪̸":260,"≫̸":260,"⪯̸":260,"⪰̸":260,"∽̱":265,"≂̸":265,"≎̸":265,"≏̸":265,"≦̸":265,"≿̸":265,"⊏̸":265,"⊐̸":265,"⧏̸":265,"⧐̸":265,"⩽̸":265,"⩾̸":265,"⪡̸":265,"⪢̸":265," ":390,"":500},e.prefix_={},e.postfix_={},s(e.infix_,[[21,"|"],[30,";"],[40,",⁣"],[70,"∴∵"],[100,":"],[110,"϶"],[150,"…⋮⋯⋱"],[160,"∋"],[170,"⊢⊣⊤⊨⊩⊬⊭⊮⊯"],[190,"∨"],[200,"∧"],[240,"∁∈∉∌⊂⊃⊄⊅⊆⊇⊈⊉⊊⊋"],[241,"≤"],[242,"≥"],[243,">"],[244,"≯"],[245,"<"],[246,"≮"],[247,"≈"],[250,"∼≉"],[252,"≢"],[255,"≠"],[260,"=∝∤∥∦≁≃≄≅≆≇≍≔≗≙≚≜≟≡≨≩≪≫≭≰≱≺≻≼≽⊀⊁⊥⊴⊵⋉⋊⋋⋌⋔⋖⋗⋘⋙⋪⋫⋬⋭■□▪▫▭▮▯▰▱△▴▵▶▷▸▹▼▽▾▿◀◁◂◃◄◅◆◇◈◉◌◍◎●◖◗◦⧀⧁⧣⧤⧥⧦⧳⪇⪈⪯⪰"],[265,"⁄∆∊∍∎∕∗∘∙∟∣∶∷∸∹∺∻∽∾∿≂≊≋≌≎≏≐≑≒≓≕≖≘≝≞≣≦≧≬≲≳≴≵≶≷≸≹≾≿⊌⊍⊎⊏⊐⊑⊒⊓⊔⊚⊛⊜⊝⊦⊧⊪⊫⊰⊱⊲⊳⊶⊷⊹⊺⊻⊼⊽⊾⊿⋄⋆⋇⋈⋍⋎⋏⋐⋑⋒⋓⋕⋚⋛⋜⋝⋞⋟⋠⋡⋢⋣⋤⋥⋦⋧⋨⋩⋰⋲⋳⋴⋵⋶⋷⋸⋹⋺⋻⋼⋽⋾⋿▲❘⦁⦂⦠⦡⦢⦣⦤⦥⦦⦧⦨⦩⦪⦫⦬⦭⦮⦯⦰⦱⦲⦳⦴⦵⦶⦷⦸⦹⦺⦻⦼⦽⦾⦿⧂⧃⧄⧅⧆⧇⧈⧉⧊⧋⧌⧍⧎⧏⧐⧑⧒⧓⧔⧕⧖⧗⧘⧙⧛⧜⧝⧞⧠⧡⧢⧧⧨⧩⧪⧫⧬⧭⧮⧰⧱⧲⧵⧶⧷⧸⧹⧺⧻⧾⧿⨝⨞⨟⨠⨡⨢⨣⨤⨥⨦⨧⨨⨩⨪⨫⨬⨭⨮⨰⨱⨲⨳⨴⨵⨶⨷⨸⨹⨺⨻⨼⨽⨾⩀⩁⩂⩃⩄⩅⩆⩇⩈⩉⩊⩋⩌⩍⩎⩏⩐⩑⩒⩓⩔⩕⩖⩗⩘⩙⩚⩛⩜⩝⩞⩟⩠⩡⩢⩣⩤⩥⩦⩧⩨⩩⩪⩫⩬⩭⩮⩯⩰⩱⩲⩳⩴⩵⩶⩷⩸⩹⩺⩻⩼⩽⩾⩿⪀⪁⪂⪃⪄⪅⪆⪉⪊⪋⪌⪍⪎⪏⪐⪑⪒⪓⪔⪕⪖⪗⪘⪙⪚⪛⪜⪝⪞⪟⪠⪡⪢⪣⪤⪥⪦⪧⪨⪩⪪⪫⪬⪭⪮⪱⪲⪳⪴⪵⪶⪷⪸⪹⪺⪻⪼⪽⪾⪿⫀⫁⫂⫃⫄⫅⫆⫇⫈⫉⫊⫋⫌⫍⫎⫏⫐⫑⫒⫓⫔⫕⫖⫗⫘⫙⫚⫛⫝⫝⫞⫟⫠⫡⫢⫣⫤⫥⫦⫧⫨⫩⫪⫫⫬⫭⫮⫯⫰⫱⫲⫳⫴⫵⫶⫷⫸⫹⫺⫻⫽⫾"],[270,"←↑→↓↔↕↖↗↘↙↚↛↜↝↞↟↠↡↢↣↤↥↦↧↨↩↪↫↬↭↮↯↰↱↲↳↴↵↶↷↸↹↺↻↼↽↾↿⇀⇁⇂⇃⇄⇅⇆⇇⇈⇉⇊⇋⇌⇍⇎⇏⇐⇑⇒⇓⇔⇕⇖⇗⇘⇙⇚⇛⇜⇝⇞⇟⇠⇡⇢⇣⇤⇥⇦⇧⇨⇩⇪⇫⇬⇭⇮⇯⇰⇱⇲⇳⇴⇵⇶⇷⇸⇹⇺⇻⇼⇽⇾⇿⊸⟰⟱⟵⟶⟷⟸⟹⟺⟻⟼⟽⟾⟿⤀⤁⤂⤃⤄⤅⤆⤇⤈⤉⤊⤋⤌⤍⤎⤏⤐⤑⤒⤓⤔⤕⤖⤗⤘⤙⤚⤛⤜⤝⤞⤟⤠⤡⤢⤣⤤⤥⤦⤧⤨⤩⤪⤫⤬⤭⤮⤯⤰⤱⤲⤳⤴⤵⤶⤷⤸⤹⤺⤻⤼⤽⤾⤿⥀⥁⥂⥃⥄⥅⥆⥇⥈⥉⥊⥋⥌⥍⥎⥏⥐⥑⥒⥓⥔⥕⥖⥗⥘⥙⥚⥛⥜⥝⥞⥟⥠⥡⥢⥣⥤⥥⥦⥧⥨⥩⥪⥫⥬⥭⥮⥯⥰⥱⥲⥳⥴⥵⥶⥷⥸⥹⥺⥻⥼⥽⥾⥿⦙⦚⦛⦜⦝⦞⦟⧟⧯⧴⭅⭆"],[275,"+-±−∓∔⊞⊟"],[300,"⊕⊖⊘"],[340,"≀"],[350,"∩∪"],[390,"*.ו⁢⊠⊡⋅⨯⨿"],[400,"·"],[410,"⊗"],[640,"%"],[650,"\\∖"],[660,"/÷"],[710,"⊙"],[825,"@"],[835,"?"],[850,"⁡"],[880,"^_⁤"]]),s(e.prefix_,[[10,"‘“"],[20,"([{‖⌈⌊❲⟦⟨⟪⟬⟮⦀⦃⦅⦇⦉⦋⦍⦏⦑⦓⦕⦗⧼"],[230,"∀∃∄"],[290,"∑⨊⨋"],[300,"∬∭⨁"],[310,"∫∮∯∰∱∲∳⨌⨍⨎⨏⨐⨑⨒⨓⨔⨕⨖⨗⨘⨙⨚⨛⨜"],[320,"⋃⨃⨄"],[330,"⋀⋁⋂⨀⨂⨅⨆⨇⨈⨉⫼⫿"],[350,"∏∐"],[670,"∠∡∢"],[680,"¬"],[740,"∂∇"],[845,"ⅅⅆ√∛∜"]]),s(e.postfix_,[[10,"’”"],[20,")]}‖⌉⌋❳⟧⟩⟫⟭⟯⦀⦄⦆⦈⦊⦌⦎⦐⦒⦔⦖⦘⧽"],[800,"′♭♮♯"],[810,"!"],[880,"&'`~¨¯°´¸ˆˇˉˊˋˍ˘˙˚˜˝˷̂̑‾⃛⃜⎴⎵⏜⏝⏞⏟⏠⏡"]]);var Q,V,W,H,X;e.macros_={mn:O(c,"mn"),mi:O(c,"mi"),mo:O(c,"mo"),text:O(c,"mtext"),html:p,sp:d,attr:g,attrMML:O(g,null,!0),id:O(g,"id"),dir:O(g,"dir"),cl:v,mv:y,bo:O(y,"bold"),it:O(y,"italic"),bi:O(y,"bold-italic"),sc:O(y,"script"),bs:O(y,"bold-script"),fr:O(y,"fraktur"),ds:O(y,"double-struck"),bf:O(y,"bold-fraktur"),mstyle:O(M,"mstyle"),merror:O(M,"merror"),mpadded:O(M,"mpadded"),phantom:O(b,"phantom"),vphantom:O(b,"vphantom"),enclose:O(M,"menclose"),ov:_,minsize:x,mrowOne:w,binom:A},e.alias_={"-":e["-"],"'":"′","ℭ":["C","fraktur"],"ℌ":["H","fraktur"],"ℑ":["I","fraktur"],"ℜ":["R","fraktur"],"ℨ":["Z","fraktur"], 4 | "ℬ":["B","script"],"ℰ":["E","script"],"ℱ":["F","script"],"ℋ":["H","script"],"ℐ":["I","script"],"ℒ":["L","script"],"ℳ":["M","script"],"ℛ":["R","script"],"ℯ":["e","script"],"ℊ":["g","script"],"ℴ":["o","script"]};var Z={",":".17em",":":".22em",";":".28em","!":"-.17em"};e.dtableQ=!1,e.macro1s_={mtd:C,rowspan:k,colspan:T,mtr:L,dtable:O(S,!0),ttable:O(S,!1),table:O(S,void 0),math:I};var J={_:"sub","^":"sup","↙":"under","↖":"over"};return e.sMxAToMe=function(t,r){r||(r=document),e.infix_[""]&&e.infix_[","]||O.err(err_sToMe_1_),void 0===e.MathML&&(e.MathML=e.canMathML()),e.re_.lastIndex=0,Q="",V=Array.isArray(t)?t:[t],W=0,H=r,X=e.infix_[""];var n=j(0);if(n[1])throw"Extra input: "+n[1][1]+Q.substring(e.re_.lastIndex)+(Wm&&(u+=s.substring(m,c)),f&&f[1])u+=f[1];else{var p,d=-1;if(f){if(p="\\("==f[0]?"\\)":"\\["==f[0]?"\\]":f[0],l.lastIndex",i).css("display","inline-block").append(g);v=D("",i).css("white-space","nowrap").append(v),g=v[0]}o.push(g),l.lastIndex=d+p.length}}O.iter(function(e){t.parentNode.insertBefore(e,t)},o),t.parentNode.removeChild(t)}},e.parseMathQ=!0,D(function(){if(void 0===e.MathML&&(e.MathML=e.canMathML()),e.parseMathQ)try{e.parseMath(document.body)}catch(t){alert(t)}}),null==D.fn.parseMath&&(D.fn.parseMath=function(){return O.iter(e.parseMath,this),this}),e}(),M;void 0===M&&(M=jqMath); -------------------------------------------------------------------------------- /mathview/src/main/assets/mathscribe/jscurry-0.4.5.js: -------------------------------------------------------------------------------- 1 | /* jscurry.js: a JavaScript module for functional programming; requires ECMAScript 3. These 2 | definitions are based on Haskell's, but allow side effects, and do not use automatic lazy 3 | evaluation, compile-time type checking, or automatic Currying. 4 | 5 | We believe that "member functions" are the wrong technique in general for implementing 6 | function closures or passing functions to polymorphic algorithms. 7 | 8 | Variable suffixes (in this and other modules): 9 | F: function 10 | P ("Possible" or "Pointer"): undefined and maybe null treated specially 11 | Q ("Question"): value effectively converted to a boolean when used 12 | S: string 13 | _: a (usually non-constant) variable with a large scope 14 | $: a jQuery() result or "wrapped set" 15 | 16 | These library modules aim to be small, efficient, compatible with standards, and hopefully 17 | elegant. */ 18 | 19 | /* Copyright 2016, Mathscribe, Inc. Released under the MIT license (same as jQuery). 20 | See e.g. http://jquery.org/license for an explanation of this license. */ 21 | 22 | 23 | "use strict"; 24 | 25 | 26 | var jsCurry = function() { 27 | var sliceMF = Array.prototype.slice; // slice "Member Function" 28 | 29 | // provide a few basic ECMAScript 5 functions if they are missing: 30 | if (! Function.prototype.bind) 31 | Function.prototype.bind = function(thisArg /* , ... */) { 32 | var f = this, args0 = sliceMF.call(arguments, 1); 33 | return function(/* ... */) { 34 | return f.apply(thisArg, args0.concat(sliceMF.call(arguments, 0))); 35 | }; 36 | }; 37 | if (! String.prototype.trim) 38 | String.prototype.trim = function() { return String(this).replace(/^\s+|\s+$/g, ''); }; 39 | if (! Array.isArray) 40 | Array.isArray = function(x) { 41 | return typeof x == 'object' && x !== null && 42 | Object.prototype.toString.call(x) === '[object Array]'; 43 | }; 44 | if (! Object.keys) 45 | Object.keys = function(obj) { 46 | var res = []; 47 | for (var p in obj) if (obj.hasOwnProperty(p)) res.push(p); 48 | return res; 49 | }; 50 | if (! Date.now) Date.now = function() { return (new Date()).getTime(); }; 51 | 52 | function F(x /* , ... */) { // F() shorthand notation for some basic operations 53 | if (typeof x == 'function') return F.curry.apply(undefined, arguments); 54 | if (arguments.length == 2) { 55 | var y = arguments[1]; 56 | if (typeof x == 'string') return y[x].bind(y); 57 | if (typeof y == 'function') 58 | return (typeof x == 'number' ? F.aritize : F.partial)(x, y); 59 | } 60 | arguments.length == 1 || F.err(err_F_1_); 61 | if (typeof x == 'number' || typeof x == 'string') return F.pToF(x); 62 | if (x.nodeType == 1 /* Element */) // requires jQuery 1.4+; e.g. for widget ops 63 | return jQuery.data(x); 64 | if (x && typeof x == 'object') return F.aToF(x); 65 | F.err(err_F_2_); 66 | } 67 | 68 | F.err = function() { if (F.debug) debugger; throw Error('Assertion failed'); }; 69 | // usually argument evaluation intentionally fails, to report its line number 70 | 71 | F.id = function(x) { return x; }; 72 | F.constant = function(x) { return function(/* ... */) { return x; }; }; 73 | // "const" is a reserved word in ECMAScript 3 74 | F.applyF = function(f, args) { return f.apply(undefined, args); } 75 | F.curry = function(f /* , ... */) 76 | { var g = f; arguments[0] = undefined; return g.bind.apply(g, arguments); }; 77 | F._ = {}; // needed since e.g. (0 in [ , 3]) is apparently wrong in e.g. Firefox 3.0 78 | F.partial = function(a, f) { // 'a' supplies some arguments to 'f' 79 | var n = a.length; 80 | return function(/* ... */) { 81 | var args = sliceMF.call(arguments, 0); 82 | for (var i = 0; i < n; i++) 83 | if (a[i] !== F._) args.splice(i, 0, a[i]); 84 | else if (args.length == i) args.push(undefined); 85 | return f.apply(this, args); 86 | }; 87 | }; 88 | F.uncurry = function(f) { return function(x, y) { return f(x)(y); }; }; 89 | F.o = function(/* ... */) { // composition of 1 or more functions 90 | var fs = arguments; 91 | return function(/* ... */) { 92 | var n = fs.length, res = fs[--n].apply(undefined, arguments); 93 | while (n > 0) res = fs[--n](res); 94 | return res; 95 | }; 96 | }; 97 | F.oMap = function(f, g) // composition, using F.map(g, ) 98 | { return function(/* ... */) { return F.applyF(f, F.map(g, arguments)); }; }; 99 | F.flip = function(f) { return function(x, y) { return f(y, x); }; }; 100 | F.seqF = function(/* ... */) { 101 | var fs = arguments, n = fs.length; 102 | return function(/* ... */) { 103 | var y; 104 | for (var i = 0; i < n; i++) y = fs[i].apply(undefined, arguments); 105 | return y; // returns undefined if n == 0 106 | }; 107 | }; 108 | F.cor = function(/* ... */) { // conditional or 109 | var fs = arguments; 110 | return function(/* ... */) { return F.any(F([F._, arguments], F.applyF), fs); }; 111 | }; 112 | F.aritize = function(n, f) // for discarding optional trailing arguments 113 | { return function(/* ... */) { return F.applyF(f, sliceMF.call(arguments, 0, n)); }; }; 114 | 115 | F.not = function(x) { return ! x; }; 116 | F.defOr = function(xP, y) { return xP !== undefined ? xP : y; }; 117 | 118 | /* The following functions that act on arrays also work on "array-like" objects (with a 119 | 'length' property), including array-like host objects. The functions may or may not 120 | skip missing elements. */ 121 | 122 | // A "cmp" function returns 0, < 0, or > 0 for ==, <, or > respectively. 123 | F.cmpX = function(x, y) { return x - y; }; // for finite numbers, or Dates 124 | F.cmpJS = function(s, t) { return s < t ? -1 : s == t ? 0 : 1; }; 125 | // JavaScript built-in comparison; for numbers, strings, or Dates; NaN => != 126 | F.cmpLex = function(cmpE, v, w) // "lexicographic order"; cmpE need not return a number 127 | { return F.any(function(e, i) { return i == w.length ? 1 : cmpE(e, w[i]); }, v) || 128 | v.length - w.length; }; 129 | F.eqTo = function(x, cmpP) { 130 | if (! cmpP) cmpP = function(y, z) { return y !== z; }; 131 | return F.o(F.not, F(cmpP, x)); 132 | }; 133 | 134 | F.pToF = function(p) { return function(obj) { return obj[p]; }; }; 135 | F.aToF = function(obj) { return function(p) { return obj[p]; }; }; 136 | F.fToA = function(f, n) { 137 | var a = new Array(n); 138 | for (var i = 0; i < n; i++) a[i] = f(i); 139 | return a; 140 | }; 141 | F.memoF = function(f, memo) { 142 | if (! memo) memo = {}; 143 | return function(p) { return memo.hasOwnProperty(p) ? memo[p] : (memo[p] = f(p)); }; 144 | }; 145 | F.replicate = function(n, e) { return F.fToA(F.constant(e), n); }; 146 | F.setF = function(obj, p, v) { obj[p] = v; }; 147 | F.obj1 = function(p, v) { var res = {}; res[p] = v; return res; }; 148 | 149 | F.slice = function(a, startP, endP) { 150 | if (startP == null) startP = 0; 151 | if (Array.isArray(a)) return a.slice(startP, endP); 152 | var n = a.length; 153 | startP = startP < 0 ? Math.max(0, n + startP) : Math.min(n, startP); 154 | endP = endP === undefined ? n : endP < 0 ? Math.max(0, n + endP) : Math.min(n, endP); 155 | var res = []; 156 | while (startP < endP) res.push(a[startP++]); 157 | return res; 158 | }; 159 | F.array = function(/* ... */) { return sliceMF.call(arguments, 0); }; 160 | F.concatArgs = F.oMap(F('concat', []), 161 | function(a) { return Array.isArray(a) ? a : F.slice(a); }); 162 | F.concatMap = function(f, a) { return F.applyF(F.concatArgs, F.map(f, a)); }; 163 | F.reverseCopy = function(a) { return F.slice(a).reverse(); }; 164 | 165 | F.findIndex = function(qF, a) { 166 | var n = a.length; 167 | for (var i = 0; i < n; i++) if (qF(a[i], i, a)) return i; 168 | return -1; 169 | }; 170 | F.findLastIndex = function(qF, a) { 171 | for (var i = a.length; --i >= 0; ) if (qF(a[i], i, a)) return i; 172 | return -1; 173 | }; 174 | F.find = function(qF, a) { 175 | var j = F.findIndex(qF, a); 176 | return j == -1 ? undefined : a[j]; 177 | }; 178 | F.elemIndex = function(e, a, cmpP) { 179 | if (a.indexOf && ! cmpP && Array.isArray(a)) return a.indexOf(e); 180 | return F.findIndex(F.eqTo(e, cmpP), a); 181 | }; 182 | F.elemLastIndex = function(e, a, cmpP) { 183 | if (a.lastIndexOf && ! cmpP && Array.isArray(a)) return a.lastIndexOf(e); 184 | return F.findLastIndex(F.eqTo(e, cmpP), a); 185 | }; 186 | F.elem = function(e, a, cmpP) { return F.elemIndex(e, a, cmpP) != -1; }; 187 | F.all = function(qF, a) { 188 | if (a.every && Array.isArray(a)) return a.every(qF); 189 | var n = a.length; 190 | for (var i = 0; i < n; i++) if (! qF(a[i], i, a)) return false; 191 | return true; 192 | }; 193 | F.any = function(f, a) /* note result may be non-boolean */ { 194 | var n = a.length, y = false /* in case n == 0 */; 195 | for (var i = 0; i < n; i++) { 196 | y = f(a[i], i, a); 197 | if (y) return y; 198 | } 199 | return y; 200 | }; 201 | F.iter = function(f, a /* , ... */) { 202 | if (arguments.length == 2) { // for speed 203 | if (a.forEach && Array.isArray(a)) return a.forEach(f); 204 | var n = a.length; 205 | for (var i = 0; i < n; i++) f(a[i], i, a); 206 | } else { 207 | arguments.length > 2 || F.err(err_iter_); 208 | var args = sliceMF.call(arguments, 1), 209 | n = F.applyF(Math.min, F.map(F('length'), args)); 210 | for (var i = 0; i < n; i++) F.applyF(f, F.map(F(i), args).concat(i, args)); 211 | } 212 | }; 213 | F.map = function(f, a) { 214 | if (a.map && Array.isArray(a)) return a.map(f); 215 | var n = a.length, res = new Array(n); 216 | for (var i = 0; i < n; i++) res[i] = f(a[i], i, a); 217 | return res; 218 | }; 219 | F.map1 = function(f, a) { return F.map(F(1, f), a); }; 220 | F.zipWith = function(f /* , ... */) { 221 | arguments.length > 1 || F.err(err_zipWith_); 222 | var res = []; 223 | for (var i = 0; ; i++) { 224 | var args = []; 225 | for (var j = 1; j < arguments.length; j++) { 226 | var a = arguments[j]; 227 | if (i < a.length) args.push(a[i]); 228 | else return res; 229 | } 230 | res.push(F.applyF(f, args)); 231 | } 232 | return res; 233 | }; 234 | F.zip = F(F.zipWith, F.array); 235 | F.unzip = // matrix transpose, similar to Haskell unzip/unzip3/unzip4/... 236 | function(zs) { return zs.length ? F.applyF(F.zip, zs) : []; }; 237 | F.filter = function(qF, a) { 238 | if (a.filter && Array.isArray(a)) return a.filter(qF); 239 | return F.fold(function(y, e, i, a) { if (qF(e, i, a)) y.push(e); return y; }, a, []); 240 | }; 241 | F.fold = function(op, a, xOpt) { 242 | if (a.reduce && Array.isArray(a)) 243 | return arguments.length < 3 ? a.reduce(op) : a.reduce(op, xOpt); 244 | var n = a.length, i = 0; 245 | if (arguments.length < 3) xOpt = n ? a[i++] : F.err(err_fold_); 246 | for ( ; i < n; i++) xOpt = op(xOpt, a[i], i, a); 247 | return xOpt; 248 | }; 249 | F.foldR = function(op, a, xOpt) { // similar to Haskell (foldr (flip op) xOpt a) 250 | if (a.reduceRight && Array.isArray(a)) 251 | return arguments.length < 3 ? a.reduceRight(op) : a.reduceRight(op, xOpt); 252 | var n = a.length; 253 | if (arguments.length < 3) xOpt = n ? a[--n] : F.err(err_foldR_); 254 | while (--n >= 0) xOpt = op(xOpt, a[n], n, a); 255 | return xOpt; 256 | }; 257 | 258 | F.sum = function(a) { 259 | var n = a.length, res = 0; 260 | for (var i = 0; i < n; i++) res += a[i]; 261 | return res; 262 | }; 263 | 264 | F.test = function(t) { // e.g. for dynamic type checking when appropriate 265 | if (t === 0 || t === '') t = typeof t; 266 | if (typeof t == 'string') return function(x) { return typeof x == t; }; 267 | if (t === Array || t === Date || t === RegExp) // assumes same frame 268 | return function(x) { return x != null && x.constructor == t; }; 269 | if (t === null) return F.eqTo(null); 270 | if (t.constructor == RegExp) return F('test', t); // assumes same frame 271 | if (typeof t == 'function') return t; 272 | if (Array.isArray(t)) { 273 | if (t.length == 1) { 274 | t = F.test(t[0]); 275 | return function(x) { return Array.isArray(x) && F.all(t, x); }; 276 | } else { // "or" of tests 277 | t = F.map(F.test, t); 278 | return function(x) { return F.any(function(qF) { return qF(x); }, t); }; 279 | } 280 | } 281 | if (typeof t == 'object') { 282 | var ks = Object.keys(t), fs = F.map(F.o(F.test, F(t)), ks); 283 | return function(x) 284 | { return x != null && F.all(function(k, i) { return fs[i](x[k]); }, ks); }; 285 | } 286 | F.err(err_test_); 287 | }; 288 | 289 | F.translations_ = {}; // can override, e.g. in language translation files 290 | F.s = function(s) { return F.translations_[s] || s; }; 291 | 292 | return F; 293 | }(); 294 | var F; if (F === undefined) F = jsCurry; 295 | if (typeof module == 'object') module.exports = jsCurry; 296 | -------------------------------------------------------------------------------- /mathview/src/main/assets/mathscribe/jscurry-0.4.5.min.js: -------------------------------------------------------------------------------- 1 | /* Copyright 2016, Mathscribe, Inc. Released under the MIT license (same as jQuery). 2 | See e.g. http://jquery.org/license for an explanation of this license. */ 3 | "use strict";var jsCurry=function(){function r(n){if("function"==typeof n)return r.curry.apply(void 0,arguments);if(2==arguments.length){var t=arguments[1];if("string"==typeof n)return t[n].bind(t);if("function"==typeof t)return("number"==typeof n?r.aritize:r.partial)(n,t)}return 1==arguments.length||r.err(err_F_1_),"number"==typeof n||"string"==typeof n?r.pToF(n):1==n.nodeType?jQuery.data(n):n&&"object"==typeof n?r.aToF(n):void r.err(err_F_2_)}var n=Array.prototype.slice;return Function.prototype.bind||(Function.prototype.bind=function(r){var t=this,e=n.call(arguments,1);return function(){return t.apply(r,e.concat(n.call(arguments,0)))}}),String.prototype.trim||(String.prototype.trim=function(){return String(this).replace(/^\s+|\s+$/g,"")}),Array.isArray||(Array.isArray=function(r){return"object"==typeof r&&null!==r&&"[object Array]"===Object.prototype.toString.call(r)}),Object.keys||(Object.keys=function(r){var n=[];for(var t in r)r.hasOwnProperty(t)&&n.push(t);return n}),Date.now||(Date.now=function(){return(new Date).getTime()}),r.err=function(){throw r.debug,Error("Assertion failed")},r.id=function(r){return r},r.constant=function(r){return function(){return r}},r.applyF=function(r,n){return r.apply(void 0,n)},r.curry=function(r){var n=r;return arguments[0]=void 0,n.bind.apply(n,arguments)},r._={},r.partial=function(t,e){var u=t.length;return function(){for(var i=n.call(arguments,0),o=0;u>o;o++)t[o]!==r._?i.splice(o,0,t[o]):i.length==o&&i.push(void 0);return e.apply(this,i)}},r.uncurry=function(r){return function(n,t){return r(n)(t)}},r.o=function(){var r=arguments;return function(){for(var n=r.length,t=r[--n].apply(void 0,arguments);n>0;)t=r[--n](t);return t}},r.oMap=function(n,t){return function(){return r.applyF(n,r.map(t,arguments))}},r.flip=function(r){return function(n,t){return r(t,n)}},r.seqF=function(){var r=arguments,n=r.length;return function(){for(var t,e=0;n>e;e++)t=r[e].apply(void 0,arguments);return t}},r.cor=function(){var n=arguments;return function(){return r.any(r([r._,arguments],r.applyF),n)}},r.aritize=function(t,e){return function(){return r.applyF(e,n.call(arguments,0,t))}},r.not=function(r){return!r},r.defOr=function(r,n){return void 0!==r?r:n},r.cmpX=function(r,n){return r-n},r.cmpJS=function(r,n){return n>r?-1:r==n?0:1},r.cmpLex=function(n,t,e){return r.any(function(r,t){return t==e.length?1:n(r,e[t])},t)||t.length-e.length},r.eqTo=function(n,t){return t||(t=function(r,n){return r!==n}),r.o(r.not,r(t,n))},r.pToF=function(r){return function(n){return n[r]}},r.aToF=function(r){return function(n){return r[n]}},r.fToA=function(r,n){for(var t=new Array(n),e=0;n>e;e++)t[e]=r(e);return t},r.memoF=function(r,n){return n||(n={}),function(t){return n.hasOwnProperty(t)?n[t]:n[t]=r(t)}},r.replicate=function(n,t){return r.fToA(r.constant(t),n)},r.setF=function(r,n,t){r[n]=t},r.obj1=function(r,n){var t={};return t[r]=n,t},r.slice=function(r,n,t){if(null==n&&(n=0),Array.isArray(r))return r.slice(n,t);var e=r.length;n=0>n?Math.max(0,e+n):Math.min(e,n),t=void 0===t?e:0>t?Math.max(0,e+t):Math.min(e,t);for(var u=[];t>n;)u.push(r[n++]);return u},r.array=function(){return n.call(arguments,0)},r.concatArgs=r.oMap(r("concat",[]),function(n){return Array.isArray(n)?n:r.slice(n)}),r.concatMap=function(n,t){return r.applyF(r.concatArgs,r.map(n,t))},r.reverseCopy=function(n){return r.slice(n).reverse()},r.findIndex=function(r,n){for(var t=n.length,e=0;t>e;e++)if(r(n[e],e,n))return e;return-1},r.findLastIndex=function(r,n){for(var t=n.length;--t>=0;)if(r(n[t],t,n))return t;return-1},r.find=function(n,t){var e=r.findIndex(n,t);return-1==e?void 0:t[e]},r.elemIndex=function(n,t,e){return t.indexOf&&!e&&Array.isArray(t)?t.indexOf(n):r.findIndex(r.eqTo(n,e),t)},r.elemLastIndex=function(n,t,e){return t.lastIndexOf&&!e&&Array.isArray(t)?t.lastIndexOf(n):r.findLastIndex(r.eqTo(n,e),t)},r.elem=function(n,t,e){return-1!=r.elemIndex(n,t,e)},r.all=function(r,n){if(n.every&&Array.isArray(n))return n.every(r);for(var t=n.length,e=0;t>e;e++)if(!r(n[e],e,n))return!1;return!0},r.any=function(r,n){for(var t=n.length,e=!1,u=0;t>u;u++)if(e=r(n[u],u,n))return e;return e},r.iter=function(t,e){if(2==arguments.length){if(e.forEach&&Array.isArray(e))return e.forEach(t);for(var u=e.length,i=0;u>i;i++)t(e[i],i,e)}else{arguments.length>2||r.err(err_iter_);for(var o=n.call(arguments,1),u=r.applyF(Math.min,r.map(r("length"),o)),i=0;u>i;i++)r.applyF(t,r.map(r(i),o).concat(i,o))}},r.map=function(r,n){if(n.map&&Array.isArray(n))return n.map(r);for(var t=n.length,e=new Array(t),u=0;t>u;u++)e[u]=r(n[u],u,n);return e},r.map1=function(n,t){return r.map(r(1,n),t)},r.zipWith=function(n){arguments.length>1||r.err(err_zipWith_);for(var t=[],e=0;;e++){for(var u=[],i=1;ii;i++)e=n(e,t[i],i,t);return e},r.foldR=function(n,t,e){if(t.reduceRight&&Array.isArray(t))return arguments.length<3?t.reduceRight(n):t.reduceRight(n,e);var u=t.length;for(arguments.length<3&&(e=u?t[--u]:r.err(err_foldR_));--u>=0;)e=n(e,t[u],u,t);return e},r.sum=function(r){for(var n=r.length,t=0,e=0;n>e;e++)t+=r[e];return t},r.test=function(n){if((0===n||""===n)&&(n=typeof n),"string"==typeof n)return function(r){return typeof r==n};if(n===Array||n===Date||n===RegExp)return function(r){return null!=r&&r.constructor==n};if(null===n)return r.eqTo(null);if(n.constructor==RegExp)return r("test",n);if("function"==typeof n)return n;if(Array.isArray(n))return 1==n.length?(n=r.test(n[0]),function(t){return Array.isArray(t)&&r.all(n,t)}):(n=r.map(r.test,n),function(t){return r.any(function(r){return r(t)},n)});if("object"==typeof n){var t=Object.keys(n),e=r.map(r.o(r.test,r(n)),t);return function(n){return null!=n&&r.all(function(r,t){return e[t](n[r])},t)}}r.err(err_test_)},r.translations_={},r.s=function(n){return r.translations_[n]||n},r}(),F;void 0===F&&(F=jsCurry),"object"==typeof module&&(module.exports=jsCurry); -------------------------------------------------------------------------------- /mathview/src/main/assets/mathscribe/jscurry-documentation.txt: -------------------------------------------------------------------------------- 1 | jscurry-0.4.5.js Usage Documentation 2 | by Micah Smukler 3 | 4 | Type conventions: 5 | 6 | x,y,z are arbitrary objects or values. 7 | f,g,h are functions. 8 | a,b,c are arrays or array-like objects. 9 | m,n are integers. 10 | s,t are strings. 11 | p,q are either integers or strings when used as array indices/object property names. 12 | 13 | F(): Several different behaviors depending on the types of its arguments. 14 | 15 | F(f, ...): Equivalent to F.curry(f, ...) (see below). 16 | 17 | F(s, x): Returns the method of x with name s. 18 | 19 | Example: If a is an array, F('concat', a) is a function which returns an array consisting of 20 | a followed by its arguments; F('push', a) is a function with the side-effect of appending 21 | its arguments to a. 22 | 23 | F(n, f): Equivalent to F.aritize(n, f) (see below). 24 | 25 | F(a, f): Equivalent to F.partial(a, f) (see below). 26 | 27 | F(p): Equivalent to F.pToF(p). (see below) 28 | 29 | F(x): If x is an HTML element, returns the jQuery data associated to that element. 30 | In all other cases (not covered above), equivalent to F.aToF(x). (see below) 31 | 32 | F.id(x): Identity function; returns x. 33 | 34 | F.constant(x): Builds a constant function; returns the function whose value is constantly x. 35 | 36 | F.applyF(f, a): Evaluates f using the elements of a as arguments. 37 | 38 | Example: F.applyF(f, [x, y, z]) is equivalent to f(x, y, z). 39 | 40 | F.curry(f, ...): Returns the function given by partially evaluating f on the remaining 41 | arguments. 42 | 43 | Example: g = F.curry(f, x) is a function with g(y, z, ...) = f(x, y, z, ...). 44 | 45 | F.partial(a, f): Returns the function given by partially evaluating f on the elements of a. 46 | 47 | Example: g = F.partial([x, y], f) is a function with g(z, ...) = f(x, y, z, ...). 48 | 49 | If any of the elements of a is F._, the function returned will "fill in" the corresponding 50 | argument in f before moving on to further-right arguments. 51 | 52 | Example: g = F.partial([x, F._, y], f) is a function with g(z, ...) = f(x, z, y, ...). 53 | 54 | F.uncurry(f): f should be a one-argument function that returns another one-argument function. 55 | Then g = F.uncurry(f) is a function with g(x, y) = f(x)(y). 56 | 57 | F.o(f, g, h, ...): Returns the function composition f o g o h o ... 58 | 59 | Example: F.o(f, g, h)(x) = f(g(h(x))). 60 | 61 | F.oMap(f, g): returns a function which evaluates g on each of its arguments, then uses them as 62 | an argument list for f. 63 | 64 | Example: If g is a one-argument function, h = F.oMap(f, g) is a function with 65 | h(x, y, z, ...) = f(g(x), g(y), g(z), ...) 66 | 67 | F.oMap() passes the index of each argument as a second argument to g. 68 | 69 | Example: If g is a two-argument function, h = F.oMap(f, g) is a function 70 | with h(x, y, z, ...) = f(g(x, 0), g(y, 1), g(z, 2), ...) 71 | 72 | As a third argument to g, F.oMap() passes its full Argument object. 73 | 74 | Example: If g is a function with at least 3 arguments, h = F.oMap(f, g) is a function with 75 | h(x, y, z) = f(g(x, 0, [x, y, z, ...]), g(y, 0, [x, y, z, ...]), g(z, 0, [x, y, z]), ...), 76 | except that the "arrays" are actually all array-like Argument objects. 77 | 78 | F.flip(f): f should be a two-argument function. F.flip(f) is the two argument function which 79 | is identical to f but with the arguments reversed: F.flip(f)(x, y) = f(y, x). 80 | 81 | F.seqF(f, g, h, ...): The arguments should be functions with side-effects. F.seqF returns a 82 | function which calls each of f, g, h, ... in turn, using its arguments as the arguments of each 83 | of them. 84 | 85 | Example: If h = F.seqF(f, g), then calling h(x, y, z, ...) is equivalent to calling 86 | f(x, y, z, ...) and then calling g(x, y, z, ...). 87 | 88 | F.cor(f, g, h, ...): The arguments should be functions. F.cor returns a function which calls 89 | each of f, g, h until one returns a truthy value, and then returns that value. 90 | 91 | Example: F.cor(F.eqTo(0), F.eqTo(1), F.eqTo(2)) returns a boolean-valued function which 92 | returns true iff x is either 0, 1, or 2. (see below for F.eqTo) 93 | 94 | F.aritize(n, f): Returns a function that is equivalent to f except that it ignores any arguments 95 | past the first n. 96 | 97 | Example: If g = F.aritize(2, f), then g(x, y) and g(x, y, z) are both equivalent to f(x, y). 98 | 99 | F.not(x): Returns ! x. 100 | 101 | F.defOr(x, y): Returns x if x !== undefined, else y. Beware: y is evaluated in either case. 102 | 103 | F.cmpX(x, y): Comparison for numbers or Dates; returns x - y (so negative if x < y, positive if 104 | x > y, 0 if x == y). 105 | 106 | F.cmpJS(x, y): Default JavaScript comparison for numbers, Dates, or strings; returns -1 107 | if x < y, 1 if x > 1, 0 otherwise. 108 | 109 | F.cmpLex(f, a, b) -- Compares a and b using "lexicographic order"; returns the first 110 | f(a[i], b[i]) which is truthy, or if none then just compares their lengths. 111 | 112 | F.eqTo(x): Returns a function of one argument that checks whether x is equal (===) to that 113 | argument. 114 | 115 | Example: If g = F.eqTo(5), g(x) returns true when x === 5 and false otherwise. 116 | 117 | F.eqTo(x, f): As above, but f is a comparison function (such as the three above). The function 118 | returned by F.eqTo will use f to check whether its argument is equal to x or not. 119 | 120 | Example: If g = F.eqTo(5, f) and f returns a number, then g(x) returns true when 121 | f(5, x) == 0 and false otherwise. 122 | 123 | F.pToF(p): Converts a property name or subscript to a function; returns the function that looks 124 | at its argument and returns the value indexed by p. 125 | 126 | Example: F.pToF(0) is a one-argument function that picks out the zeroth element in arrays. 127 | F.pToF('baseHeightA') is a one-argument function that picks out the value of the baseHeightA 128 | property in objects. 129 | 130 | F.aToF(a): "array to function": Returns the function f with f(i) = a[i]. (Despite the suggestive 131 | name, works on arbitrary objects.) 132 | 133 | Example: f = F.aToF([0, 1, 1]) is a function with f(0) = 0, f(1) = f(2) = 1, and f(x) 134 | undefined for any other x. 135 | 136 | g = F.aToF({ x: 1, y: 'fnord' }) is a function with g('x') = 1, g('y') = 'fnord', and g(z) 137 | undefined for any other z. 138 | 139 | F.fToA(f, n): "function to array": Returns an n-element array a with a[i] = f(i). 140 | 141 | F.memoF(f, x): returns a memoized version of f, storing all previously computed values of f in 142 | x. Can be called as a one-argument function in which case x will be automatically created and 143 | inaccessible. 144 | 145 | F.replicate(n, x): Returns an array whose n elements are all x. 146 | 147 | F.setF(x, p, y): A function whose side-effect is to set x[p] = y. Good for feeding to F to build 148 | other functions. 149 | 150 | F.obj1(p, x): Returns an object whose sole property p has value x. 151 | 152 | F.slice(a): Returns an array which is a shallow copy of the array-like object a. 153 | 154 | F.slice(a, n): Returns an array consisting of all the elements of a starting with a[n] if n is 155 | non-negative, or the element -n from the end if n is negative. Analogous to the array method of 156 | the same name, but also works on array-like objects. 157 | 158 | F.slice(a, n, m): Returns an array consisting of the elements of a starting with a[n] and 159 | going up to but not including a[m]; treats negative arguments modulo a.length as the 160 | two-argument version does. Can be called with n == null to start from the beginning of the 161 | array, like n == 0. 162 | 163 | F.array(x, y, z, ...): Returns its arguments in an array (not an array-like Argument object). 164 | 165 | Example: F.array(x, y, z, ...) returns [x, y, z, ...]. 166 | 167 | F.concatArgs(a, b, c, ...): Returns an array consisting of the elements of the array-like 168 | objects a, b, c, .... 169 | 170 | Example: F.concatArgs([x, y], [1, 2], [z]) returns [x, y, 1, 2, z]. 171 | 172 | F.concatMap(f, a): f should be a function that returns an array-like object. Returns an array 173 | obtained by applying f to each element of a in turn and then concatenating the resulting arrays. 174 | 175 | Example: If f(n) returns [n^2, 2n, 1], F.concatMap(f, [0, 1, 5, 100]) returns 176 | [0, 0, 1, 1, 2, 1, 25, 10, 1, 10000, 200, 1]. 177 | 178 | F.reverseCopy(a): Returns an array which is the reverse of a shallow copy of the array-like 179 | object a. 180 | 181 | F.findIndex(f, a): Returns the smallest i where f(a[i]) is truthy. If f has a second argument, 182 | it is taken to be the index i; a third argument is taken to be the entire array a. If no such i 183 | exists, returns -1. 184 | 185 | Example: F.findIndex(function(x) { return x == 3; }, [0, 1, 2, 3, 4, 3]) returns 3. 186 | F.findIndex(function(x) { return x == 3; }, [0, 1, 2]) returns -1. 187 | 188 | F.findLastIndex(f, a): As findIndex, except that it returns the largest i where f(a[i]) is 189 | truthy. 190 | 191 | Example: F.findLastIndex(function(x) { return x == 3; }, [0, 1, 2, 3, 4, 3]) returns 5. 192 | 193 | F.find(f, a): Returns the first a[i] with f(a[i]) truthy, or undefined if there is no such a[i]. 194 | 195 | Example: F.find(function(x) { return x > 3; }, [0, 4, 2]) returns 4. 196 | 197 | F.elemIndex(x, a, f): Returns the smallest i where a[i] == x, using f as a comparison function 198 | for equality if given (i.e., it finds i where f(x, a[i]) is falsy). 199 | 200 | F.elemLastIndex(x, a, f): As F.elemIndex, except that it returns the largest such i. 201 | 202 | F.elem(x, a, f): Returns true if x can be found in a and false otherwise, using f as a 203 | comparison function if given. 204 | 205 | F.all(f, a): Returns true if f(a[i], i, a) returns a truthy value for all i, and false 206 | otherwise. 207 | 208 | F.any(f, a): Returns the smallest-index f(a[i], i, a) which is truthy, or the last such value if 209 | none are truthy, or false if a is empty. 210 | 211 | F.iter(f, a, b, c, ...): f should be a function with side-effects. Calls f with arguments 212 | a[0], b[0], c[0], ...; then with arguments a[1], b[1], c[1], ...; and so on. If the arrays 213 | differ in length, ignores all remaining elements in longer arrays once the shortest array has 214 | run out. If f wants more arguments than there are arrays, the first additional argument is the 215 | index and each subsequent additional argument is an entire array a, b, c, ... . 216 | 217 | Example: F.iter(f, [x0, x1, x2], [y0, y1, y2]) is equivalent to calling: 218 | f(x0, y0); f(x1, y1); f(x2; y2); if f is a function of at most 2 arguments 219 | f(x0, y0, 0); f(x1, y1, 1); f(x2, y2, 2); if f is a function of 3 arguments 220 | f(x0, y0, 0, [x0, x1, x2], [y0, y1, y2]); ... in general. 221 | 222 | F.map(f, a): Returns the array whose ith element is f(a[i], i, a). 223 | 224 | F.map1(f, a): Returns the array whose ith element is f(a[i]) (even if f is capable of being 225 | passed more than one argument). 226 | 227 | F.zipWith(f, a, b, c, ...): Returns the array whose ith element is f(a[i], b[i], c[i], ...). If 228 | a, b, c, ... are not all the same length, ignores remaining elements in the longer ones once the 229 | shortest one has run out. 230 | 231 | F.zip(a, b, c, ...): Returns the array [[a[0], b[0], c[0], ...], [a[1], b[1], c[1], ...], ...]. 232 | 233 | F.unzip(a): a should be a *matrix* -- an array of arrays, where each row array has the same 234 | length (or elements beyond the shortest length are ignored). Returns the matrix transpose of a. 235 | 236 | Example: F.unzip([[1,2,3], [4,5,6], [7,8,9]]) returns [[1,4,7], [2,5,8], [3,6,9]]. 237 | 238 | F.filter(f, a): returns an array consisting of all those a[i] where f(a[i], i, a) is truthy, in 239 | their original order. 240 | 241 | Example: F.filter(eqTo(4), [1,2,3,4,5,4]) returns [4,4]. 242 | F.filter(F.not, [0, 1, null, 2, undefined, 3]) returns [0, null, undefined]. 243 | 244 | F.fold(f, a, x): Calls f(x, a[0]), then calls f on the result and a[1], and so on until the 245 | array is exhausted, and returns the result. If x is omitted, start the process with 246 | f(a[0], a[1]). Equivalent to the reduce method for genuine arrays. Also passes i and a to f. 247 | 248 | Example: If plus is a function that returns x + y, F.fold(plus, [0, 1, 2], ' ') returns the 249 | string ' 012'. 250 | 251 | F.foldR(f, a, x): The same as to F.fold except that it begins at the end of a (so it starts by 252 | calling f(x, a[a.length - 1])). Equivalent to the reduceRight method for genuine arrays. 253 | 254 | Example: If plus is a function that returns x + y, F.foldR(plus, [0, 1, 2], ' ') returns the 255 | string ' 210'. 256 | 257 | F.sum(a): Returns the sum of the elements of a. 258 | 259 | F.test(x): Returns a boolean function of one argument which checks that argument in some way 260 | determined by x -- usually some form of type-checking. 261 | 262 | To check whether: 263 | Something is a number Use F.test(0) (or F.test('number') -- see below) 264 | Something is a string Use F.test('') (or F.test('string') -- see below) 265 | Something has a type readable Use F.test(s) where s is a string returnable by the typeof 266 | by the typeof operator operator. 267 | (undefined, object, boolean, 268 | number, string, function) 269 | Something is an array, Date Use F.test(Array), F.test(Date), and F.test(RegExp) 270 | object, or Javascript regular respectively. 271 | expression, constructed in 272 | the same window frame 273 | Something is null Use F.test(null) 274 | 275 | If r is a regular expression, F.test(r) is equivalent to r.test (it returns true if its argument 276 | contains a match for r). 277 | 278 | If f is a function, F.test(f) returns f (allowing you to feed arbitrary test functions into the 279 | following recursive cases). 280 | 281 | F.test([x]) checks to see if its argument is an array, all of whose elements satisfy F.test(x). 282 | 283 | For arrays of more than one element, F.test(a) checks to see if its argument satisfies 284 | F.test(a[i]) for any i. 285 | 286 | For generic objects that don’t match any of the above, F.test(x) looks at some other object y 287 | and returns true if: 288 | -y is non-null, and 289 | -for every property p of x, y[p] passes the test F.test(x[p]). 290 | 291 | F.translations_: An object mapping user visible strings to their translations in the current 292 | language. 293 | 294 | F.s(s): Returns the translation of s if one exists, else s. 295 | -------------------------------------------------------------------------------- /mathview/src/main/assets/mathscribe/view.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 41 | 42 | 43 |
44 |
45 |

46 |
47 |
48 | 49 | 50 | -------------------------------------------------------------------------------- /mathview/src/main/java/com/zanvent/mathview/MathView.java: -------------------------------------------------------------------------------- 1 | package com.zanvent.mathview; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.util.AttributeSet; 6 | import android.view.MotionEvent; 7 | import android.webkit.WebSettings; 8 | import android.webkit.WebView; 9 | import android.webkit.WebViewClient; 10 | 11 | public class MathView extends WebView { 12 | private String text; 13 | private String textColor; 14 | private float textSize; 15 | private Scale pixelScaleType; 16 | private volatile boolean pageLoaded; 17 | private OnLoadListener onLoadListener; 18 | private static final String textColorDefault = "#000000"; 19 | private static final int textSizeDefault = 16; 20 | 21 | public enum Scale { 22 | SCALE_DP, 23 | SCALE_SP 24 | } 25 | 26 | public MathView(Context context) { 27 | super(context); 28 | init(); 29 | } 30 | 31 | public MathView(Context context, AttributeSet attrs) { 32 | super(context, attrs); 33 | init(); 34 | } 35 | 36 | 37 | private void init() { 38 | setBackgroundColor(Color.TRANSPARENT); 39 | this.pageLoaded = false; 40 | pixelScaleType = Scale.SCALE_DP; 41 | setText(""); 42 | setTextSize(textSizeDefault); 43 | setTextColor(textColorDefault); 44 | // enable javascript 45 | getSettings().setLoadWithOverviewMode(true); 46 | getSettings().setJavaScriptEnabled(true); 47 | 48 | getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); 49 | 50 | // disable click 51 | setClickable(false); 52 | setLongClickable(false); 53 | getSettings().setUseWideViewPort(true); 54 | loadUrl("file:///android_asset/mathscribe/view.html"); 55 | setWebViewClient(new WebViewClient() { 56 | @Override 57 | public void onPageFinished(WebView view, String url) { 58 | super.onPageFinished(view, url); 59 | pageLoaded = true; 60 | updateText(); 61 | updateTextColor(); 62 | updateTextSize(); 63 | if (onLoadListener != null) 64 | onLoadListener.onLoad(); 65 | } 66 | }); 67 | setVerticalScrollBarEnabled(false); 68 | setHorizontalScrollBarEnabled(false); 69 | } 70 | 71 | public void setText(String text) { 72 | this.text = text; 73 | updateText(); 74 | } 75 | 76 | public void setTextColor(String textColor) { 77 | if (textColor != null && !textColor.trim().isEmpty()) { 78 | this.textColor = textColor; 79 | updateTextColor(); 80 | } else { 81 | setTextColor(textColorDefault); 82 | } 83 | } 84 | 85 | public void setTextSize(int textSize) { 86 | if (textSize > 0) { 87 | if (pixelScaleType == Scale.SCALE_DP) { 88 | this.textSize = Util.convertDpToPixels(getContext(), textSize); 89 | } else if (pixelScaleType == Scale.SCALE_SP) { 90 | this.textSize = Util.convertSpToPixels(getContext(), textSize); 91 | } 92 | updateTextSize(); 93 | } else { 94 | setTextSize(textSizeDefault); 95 | } 96 | } 97 | 98 | private void updateText() { 99 | if (pageLoaded) { 100 | loadUrl("javascript:setText(\"" + getText() + "\" )"); 101 | } 102 | } 103 | 104 | private void updateTextSize() { 105 | if (pageLoaded) { 106 | loadUrl("javascript:setTextSize(" + getTextSize() + ")"); 107 | } 108 | } 109 | 110 | private void updateTextColor() { 111 | if (pageLoaded) { 112 | loadUrl("javascript:setTextColor(\"" + getTextColor() + "\" )"); 113 | } 114 | } 115 | 116 | public String getText() { 117 | return text; 118 | } 119 | 120 | public String getTextColor() { 121 | return textColor; 122 | } 123 | 124 | public float getTextSize() { 125 | return textSize; 126 | } 127 | 128 | public Scale getPixelScaleType() { 129 | return pixelScaleType; 130 | } 131 | 132 | public void setPixelScaleType(Scale pixelScaleType) { 133 | this.pixelScaleType = pixelScaleType; 134 | } 135 | 136 | public interface OnLoadListener { 137 | void onLoad(); 138 | } 139 | 140 | public OnLoadListener getOnLoadListener() { 141 | return onLoadListener; 142 | } 143 | 144 | public void setOnLoadListener(OnLoadListener onLoadListener) { 145 | this.onLoadListener = onLoadListener; 146 | } 147 | 148 | 149 | /** 150 | * Max allowed duration for a "click", in milliseconds. 151 | */ 152 | private static final int MAX_CLICK_DURATION = 1000; 153 | 154 | /** 155 | * Max allowed distance to move during a "click", in DP. 156 | */ 157 | private static final int MAX_CLICK_DISTANCE = 15; 158 | 159 | private long pressStartTime; 160 | private float pressedX; 161 | private float pressedY; 162 | private boolean stayedWithinClickDistance; 163 | 164 | @Override 165 | public boolean onTouchEvent(MotionEvent event) { 166 | switch (event.getAction()) { 167 | case MotionEvent.ACTION_DOWN: { 168 | pressStartTime = System.currentTimeMillis(); 169 | pressedX = event.getX(); 170 | pressedY = event.getY(); 171 | stayedWithinClickDistance = true; 172 | break; 173 | } 174 | case MotionEvent.ACTION_MOVE: { 175 | if (stayedWithinClickDistance && distance(pressedX, pressedY, event.getX(), event.getY()) > MAX_CLICK_DISTANCE) { 176 | stayedWithinClickDistance = false; 177 | } 178 | break; 179 | } 180 | case MotionEvent.ACTION_UP: { 181 | long pressDuration = System.currentTimeMillis() - pressStartTime; 182 | if (pressDuration < MAX_CLICK_DURATION && stayedWithinClickDistance) { 183 | performClick(); 184 | } 185 | } 186 | } 187 | return true; 188 | } 189 | 190 | private float distance(float x1, float y1, float x2, float y2) { 191 | float dx = x1 - x2; 192 | float dy = y1 - y2; 193 | float distanceInPx = (float) Math.sqrt(dx * dx + dy * dy); 194 | return Util.convertPixelsToDp(distanceInPx, getContext()); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /mathview/src/main/java/com/zanvent/mathview/Util.java: -------------------------------------------------------------------------------- 1 | package com.zanvent.mathview; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.util.DisplayMetrics; 6 | import android.util.TypedValue; 7 | 8 | 9 | public class Util { 10 | /** 11 | * This method converts dp unit to equivalent pixels, depending on device density. 12 | * 13 | * @param dp A value in dp (density independent pixels) unit. Which we need to convert into pixels 14 | * @param context Context to get resources and device specific display metrics 15 | * @return A float value to represent px equivalent to dp depending on device density 16 | */ 17 | public static float convertDpToPixels(Context context, float dp) { 18 | Resources resources = context.getResources(); 19 | DisplayMetrics metrics = resources.getDisplayMetrics(); 20 | return dp * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT); 21 | } 22 | 23 | /** 24 | * This method converts device specific pixels to density independent pixels. 25 | * 26 | * @param px A value in px (pixels) unit. Which we need to convert into db 27 | * @param context Context to get resources and device specific display metrics 28 | * @return A float value to represent dp equivalent to px value 29 | */ 30 | public static float convertPixelsToDp(float px, Context context) { 31 | Resources resources = context.getResources(); 32 | DisplayMetrics metrics = resources.getDisplayMetrics(); 33 | return px / ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT); 34 | } 35 | 36 | public static float convertSpToPixels(Context context, float sp) { 37 | return (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp, context.getResources().getDisplayMetrics())); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /mathview/src/test/java/com/zanvent/mathview/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.zanvent.mathview; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /screenshots/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frhnfrq/MathView/468eabd9645218286a3fd8841fbfefffb9bb8dc4/screenshots/screenshot.png -------------------------------------------------------------------------------- /screenshots/screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/frhnfrq/MathView/468eabd9645218286a3fd8841fbfefffb9bb8dc4/screenshots/screenshot2.png -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':mathview' 2 | --------------------------------------------------------------------------------