New Upstream Snapshot - owasp-java-html-sanitizer
Ready changes
Summary
Merged new upstream version: 20220608.1+git20220608.1.3756979 (was: 20191001.1).
Resulting package
Built on 2022-10-21T11:14 (took 5m59s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-snapshots libowasp-java-html-sanitizer-java
Diff
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
index 59bfbdd..0ea7293 100644
--- a/.github/ISSUE_TEMPLATE.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -14,6 +14,8 @@ For bugs, please include
If you're having trouble putting HTML in markdown, try using
an HTML [code block](https://help.github.com/articles/creating-and-highlighting-code-blocks/):
+````md
```html
HTML goes here
```
+````
diff --git a/README.md b/README.md
index e11f93b..e624995 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,7 @@
-# OWASP Java HTML Sanitizer [<img src="https://travis-ci.org/OWASP/java-html-sanitizer.svg">](https://travis-ci.org/OWASP/java-html-sanitizer) [![Coverage Status](https://coveralls.io/repos/github/OWASP/java-html-sanitizer/badge.svg?branch=master)](https://coveralls.io/github/OWASP/java-html-sanitizer?branch=master) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2602/badge)](https://bestpractices.coreinfrastructure.org/projects/2602)
+# OWASP Java HTML Sanitizer
+
+[<img src="https://travis-ci.org/OWASP/java-html-sanitizer.svg">](https://travis-ci.org/OWASP/java-html-sanitizer) [![Coverage Status](https://coveralls.io/repos/github/OWASP/java-html-sanitizer/badge.svg?branch=main)](https://coveralls.io/github/OWASP/java-html-sanitizer?branch=main) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/2602/badge)](https://bestpractices.coreinfrastructure.org/projects/2602) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/badge.png?style=plastic)](https://search.maven.org/artifact/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer)
+
A fast and easy to configure HTML Sanitizer written in Java which lets
you include HTML authored by third-parties in your web application while
@@ -32,7 +35,7 @@ how to get started with or without Maven.
## Prepackaged Policies
You can use
-[prepackaged policies](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20191001.1/org/owasp/html/Sanitizers.html):
+[prepackaged policies](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20220608.1/org/owasp/html/Sanitizers.html):
```Java
PolicyFactory policy = Sanitizers.FORMATTING.and(Sanitizers.LINKS);
@@ -42,9 +45,9 @@ String safeHTML = policy.sanitize(untrustedHTML);
## Crafting a policy
The
-[tests](https://github.com/OWASP/java-html-sanitizer/blob/master/src/test/java/org/owasp/html/HtmlPolicyBuilderTest.java)
+[tests](https://github.com/OWASP/java-html-sanitizer/blob/main/src/test/java/org/owasp/html/HtmlPolicyBuilderTest.java)
show how to configure your own
-[policy](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20191001.1/org/owasp/html/HtmlPolicyBuilder.html):
+[policy](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20220608.1/org/owasp/html/HtmlPolicyBuilder.html):
```Java
PolicyFactory policy = new HtmlPolicyBuilder()
@@ -59,7 +62,7 @@ String safeHTML = policy.sanitize(untrustedHTML);
## Custom Policies
You can write
-[custom policies](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20191001.1/org/owasp/html/ElementPolicy.html)
+[custom policies](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20220608.1/org/owasp/html/ElementPolicy.html)
to do things like changing `h1`s to `div`s with a certain class:
```Java
@@ -82,7 +85,7 @@ need to be explicitly whitelisted using the `allowWithoutAttributes()`
method if you want them to be allowed through the filter when these
elements do not include any attributes.
-[Attribute policies](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20191001.1/org/owasp/html/AttributePolicy.html) allow running custom code too. Adding an attribute policy will not water down any default policy like `style` or URL attribute checks.
+[Attribute policies](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20220608.1/org/owasp/html/AttributePolicy.html) allow running custom code too. Adding an attribute policy will not water down any default policy like `style` or URL attribute checks.
```Java
new HtmlPolicyBuilder = new HtmlPolicyBuilder()
@@ -150,7 +153,7 @@ of the output.
## Telemetry
-When a policy rejects an element or attribute it notifies an [HtmlChangeListener](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20191001.1/org/owasp/html/HtmlChangeListener.html).
+When a policy rejects an element or attribute it notifies an [HtmlChangeListener](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20220608.1/org/owasp/html/HtmlChangeListener.html).
You can use this to keep track of policy violation trends and find out when someone
is making an effort to breach your security.
@@ -184,7 +187,7 @@ used HTML parsers will agree on the meaning of, but the absence of
notifications does not mean that the input is in such a sub-set,
only that it does not contain elements or attributes that were removed.
-See ["Why sanitize when you can validate"](https://github.com/OWASP/java-html-sanitizer/blob/master/docs/html-validation.md) for more on this topic.
+See ["Why sanitize when you can validate"](https://github.com/OWASP/java-html-sanitizer/blob/main/docs/html-validation.md) for more on this topic.
## Questions?
@@ -203,7 +206,7 @@ We welcome [issue reports](https://github.com/OWASP/java-html-sanitizer/issues)
PRs that change behavior or that add functionality should include both positive and
[negative tests](https://www.guru99.com/negative-testing.html).
-Please be aware that contributions fall under the [Apache 2.0 License](https://github.com/OWASP/java-html-sanitizer/blob/master/COPYING).
+Please be aware that contributions fall under the [Apache 2.0 License](https://github.com/OWASP/java-html-sanitizer/blob/main/COPYING).
## Credits
diff --git a/RELEASE-checklist.sh b/RELEASE-checklist.sh
index 9315800..57e611b 100644
--- a/RELEASE-checklist.sh
+++ b/RELEASE-checklist.sh
@@ -16,7 +16,7 @@ mvn org.sonatype.ossindex.maven:ossindex-maven-plugin:audit -f aggregate
echo
echo Browse to
echo "file://$PWD/target/site"
-echo and check the findbugs and jacoco reports.
+echo and check the spotbugs and jacoco reports.
echo
echo Check https://central.sonatype.org/pages/apache-maven.html#nexus-staging-maven-plugin-for-deployment-and-release
@@ -92,7 +92,7 @@ find . -name pom.xml \
git commit -am "Bumped dev version"
-git push origin master --tags
+git push origin main --tags
# Now Release
echo '1. Go to oss.sonatype.org'
diff --git a/aggregate/pom.xml b/aggregate/pom.xml
index f7ef3ab..1fc1a84 100644
--- a/aggregate/pom.xml
+++ b/aggregate/pom.xml
@@ -3,12 +3,12 @@
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
<artifactId>aggregate</artifactId>
<packaging>pom</packaging>
- <version>20191001.1</version>
+ <version>20220608.2-SNAPSHOT</version>
<parent>
<relativePath>../parent</relativePath>
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
<artifactId>parent</artifactId>
- <version>20191001.1</version>
+ <version>20220608.2-SNAPSHOT</version>
</parent>
<modules>
diff --git a/change_log.md b/change_log.md
index f5efd94..04324a4 100644
--- a/change_log.md
+++ b/change_log.md
@@ -1,6 +1,30 @@
# OWASP Java HTML Sanitizer Change Log
Most recent at top.
+ * Release 20220608.1
+ * Fix bugs in CSS tokenization
+ * Fix deocding of HTML character references that lack semicolons
+ like `¶` in HTML attribute values that affected
+ URL query parameters.
+ * Release 20211018.2
+ * Tweak how we address CVE-2021-42575 to be more tailored and to
+ interfere less with `<style>` element content in general. We
+ still advise not allowing attacker controlled `<style>` content.
+ * Release 20211018.1
+ * Fix [CVE-2021-42575](https://docs.google.com/document/d/11SoX296sMS0XoQiQbpxc5pNxSdbJKDJkm5BDv0zrX50/edit#)
+ * Changes rendering of `<style>` elements by wrapping text content
+ in HTML comments and CDATA section tags so that even when
+ content is not treated as CDATA, it will not be treated as
+ active content.
+ * Release 20200713.1
+ * Do not lower-case SVG/MathML names.
+ This shouldn't cause problems since it was hard to write policies for
+ SBG, but be aware that SVG's `<textArea>` is now distinct from HTML's `<textarea>`.
+ * Release 20200615.1
+ * Change `.and` when combining two policies to respect explicit `skipIfEmpty` decisions.
+ * HTML entity decoding now follows HTML standard rules about when a semicolon is optional.
+ [Fixes #193](https://github.com/OWASP/java-html-sanitizer/issues/193)
+ * Fix table formatting [#137](https://github.com/OWASP/java-html-sanitizer/issues/137)
* Release 20191001.1
* Package as an OSGI bundle
* Release 20190610.1
diff --git a/debian/changelog b/debian/changelog
index 4194397..d8c818e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+owasp-java-html-sanitizer (20220608.1+git20220608.1.3756979-1) UNRELEASED; urgency=low
+
+ * New upstream snapshot.
+
+ -- Debian Janitor <janitor@jelmer.uk> Fri, 21 Oct 2022 11:10:45 -0000
+
owasp-java-html-sanitizer (20191001.1-1) unstable; urgency=medium
* Team upload.
diff --git a/docs/credits.md b/docs/credits.md
index 20b1d42..cad3b04 100644
--- a/docs/credits.md
+++ b/docs/credits.md
@@ -4,12 +4,18 @@
* agustin.lucchetti
* andy-h-chen
* augustd
+ * benapple
* chuckdumont
* gazheyes
+ * jacobrshields
+ * kylesimmons
* lichtenberger.johannes
* nikhilmarathe
* rfamilya
* robinhouston
+ * sneha patil
+ * tomanthony
* vytah
* willikins_bear
+ * yangbongsoo
* yokotaso
diff --git a/docs/cve202142575.md b/docs/cve202142575.md
new file mode 100644
index 0000000..241c518
--- /dev/null
+++ b/docs/cve202142575.md
@@ -0,0 +1,5 @@
+# CVE-2021-42575
+
+Policies that allow `<style>` tags inside `<option>` elements are vulnerable to RCE
+
+See https://docs.google.com/document/d/11SoX296sMS0XoQiQbpxc5pNxSdbJKDJkm5BDv0zrX50/edit?usp=sharing for mitigations.
diff --git a/docs/getting_started.md b/docs/getting_started.md
index a46f254..44de7fe 100644
--- a/docs/getting_started.md
+++ b/docs/getting_started.md
@@ -23,23 +23,23 @@ to one of your project's `.java` files and compile it.
## Using the APIs
The
-[examples](https://github.com/OWASP/java-html-sanitizer/tree/master/src/main/java/org/owasp/html/examples)
+[examples](https://github.com/OWASP/java-html-sanitizer/tree/main/src/main/java/org/owasp/html/examples)
include source code which defines a sanitization policy, and applies
it to HTML.
The
[javadoc](http://javadoc.io/doc/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/)
covers more detailed topics, including
-[customization](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20191001.1/org/owasp/html/HtmlPolicyBuilder.html).
+[customization](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20220608.1/org/owasp/html/HtmlPolicyBuilder.html).
Important classes are:
- * [Sanitizers](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20191001.1/org/owasp/html/Sanitizers.html) contains combinable pre-packaged policies.
- * [HtmlPolicyBuilder](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20191001.1/org/owasp/html/HtmlPolicyBuilder.html) lets you easily build custom policies.
+ * [Sanitizers](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20220608.1/org/owasp/html/Sanitizers.html) contains combinable pre-packaged policies.
+ * [HtmlPolicyBuilder](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20220608.1/org/owasp/html/HtmlPolicyBuilder.html) lets you easily build custom policies.
For advanced use, see:
- * [AttributePolicy](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20191001.1/org/owasp/html/AttributePolicy.html) and [ElementPolicy](http://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20180219.1/org/owasp/html/ElementPolicy.html) allow complex customization.
- * [HtmlStreamEventReceiver](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20191001.1/org/owasp/html/HtmlStreamEventReceiver.html) if you don't just want a `String` as output.
+ * [AttributePolicy](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20220608.1/org/owasp/html/AttributePolicy.html) and [ElementPolicy](http://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20180219.1/org/owasp/html/ElementPolicy.html) allow complex customization.
+ * [HtmlStreamEventReceiver](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20220608.1/org/owasp/html/HtmlStreamEventReceiver.html) if you don't just want a `String` as output.
## Asking Questions
diff --git a/docs/maven.md b/docs/maven.md
index 4f2ad1b..c24a046 100644
--- a/docs/maven.md
+++ b/docs/maven.md
@@ -23,7 +23,7 @@ Bigger numbers are more recent and the [change log](../change_log.md)
can shed light on the salient differences.
You should be able to build with the HTML sanitizer. You can read the
-[javadoc](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20191001.1/index.html),
+[javadoc](https://static.javadoc.io/com.googlecode.owasp-java-html-sanitizer/owasp-java-html-sanitizer/20220608.1/index.html),
and if you have questions that aren't answered by these wiki pages,
you can ask on the
[mailing list](http://groups.google.com/group/owasp-java-html-sanitizer-support).
diff --git a/docs/vulnerabilities.md b/docs/vulnerabilities.md
index 67b3464..844ef85 100644
--- a/docs/vulnerabilities.md
+++ b/docs/vulnerabilities.md
@@ -1,3 +1,4 @@
-# Known & public vulnerabilities in this project
+# Known & public vulnerabilities in this project
+ * [CVE-2021-42575](cve202142575.md) - 18 Oct. 2021 - Recommend upgrade to v20211018.1 or later.
* [CVE-2011-4457](cve20114457.md) - 17 Nov. 2011 - Recommend upgrade to r88 or later.
diff --git a/empiricism/pom.xml b/empiricism/pom.xml
index 0358773..2a5d1c8 100644
--- a/empiricism/pom.xml
+++ b/empiricism/pom.xml
@@ -2,13 +2,13 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
<artifactId>html-types</artifactId>
- <version>20191001.1</version>
+ <version>20220608.2-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<relativePath>../parent</relativePath>
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
<artifactId>parent</artifactId>
- <version>20191001.1</version>
+ <version>20220608.2-SNAPSHOT</version>
</parent>
<name>empiricism</name>
diff --git a/html-types/pom.xml b/html-types/pom.xml
index 0812a65..97f9eb1 100644
--- a/html-types/pom.xml
+++ b/html-types/pom.xml
@@ -2,13 +2,13 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
<artifactId>html-types</artifactId>
- <version>20191001.1</version>
+ <version>20220608.2-SNAPSHOT</version>
<packaging>bundle</packaging>
<parent>
<relativePath>../parent</relativePath>
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
<artifactId>parent</artifactId>
- <version>20191001.1</version>
+ <version>20220608.2-SNAPSHOT</version>
</parent>
<name>OWASP Java HTML Sanitizer Safe HTML Compatibility</name>
diff --git a/html-types/src/main/java/org/owasp/html/htmltypes/SafeHtmlMint.java b/html-types/src/main/java/org/owasp/html/htmltypes/SafeHtmlMint.java
index 1027da0..cfba285 100644
--- a/html-types/src/main/java/org/owasp/html/htmltypes/SafeHtmlMint.java
+++ b/html-types/src/main/java/org/owasp/html/htmltypes/SafeHtmlMint.java
@@ -45,7 +45,7 @@ import org.owasp.html.PolicyFactory;
* This class is safe when the policy factories passed to it are safe.
* <a href="https://github.com/mikesamuel/fences-maven-enforcer-rule">Fences</a>
* can be used to control access to {@link SafeHtmlMint#fromPolicyFactory}
- * as needed, and <a href="https://github.com/mikesamuel/fences-maven-enforcer-rule/blob/master/src/site/markdown/caveats.md">the plausible deniability</a>
+ * as needed, and <a href="https://github.com/mikesamuel/fences-maven-enforcer-rule/blob/main/src/site/markdown/caveats.md">the plausible deniability</a>
* standard can be extended to writing policies that white-list known-unsafe
* content.
*/
diff --git a/html-types/src/main/java/org/owasp/html/htmltypes/package-info.java b/html-types/src/main/java/org/owasp/html/htmltypes/package-info.java
index 3fc3408..452e79c 100644
--- a/html-types/src/main/java/org/owasp/html/htmltypes/package-info.java
+++ b/html-types/src/main/java/org/owasp/html/htmltypes/package-info.java
@@ -28,9 +28,9 @@
/**
* Wraps HTML policy builders to produce
- * <a href="https://github.com/google/safe-html-types/blob/master/doc/safehtml-types.md">Safe HTML</a>.
+ * <a href="https://github.com/google/safe-html-types/blob/main/doc/safehtml-types.md">Safe HTML</a>.
* <p>
- * @see <a href="https://github.com/OWASP/java-html-sanitizer/blob/master/docs/credits.md">usage</a>
+ * @see <a href="https://github.com/OWASP/java-html-sanitizer/blob/main/docs/credits.md">usage</a>
* @author Mike Samuel (mikesamuel@gmail.com)
*/
@javax.annotation.ParametersAreNonnullByDefault
diff --git a/parent/pom.xml b/parent/pom.xml
index e62ece3..ec4f263 100644
--- a/parent/pom.xml
+++ b/parent/pom.xml
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
<artifactId>parent</artifactId>
- <version>20191001.1</version>
+ <version>20220608.2-SNAPSHOT</version>
<packaging>pom</packaging>
@@ -88,7 +88,7 @@ application while protecting against XSS.
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
- <guava.version>27.1-jre</guava.version>
+ <guava.version>30.1-jre</guava.version>
</properties>
<build>
@@ -151,7 +151,7 @@ application while protecting against XSS.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
- <version>3.1.1</version>
+ <version>3.2.0</version>
<executions>
<execution>
<id>attach-javadocs</id>
@@ -176,6 +176,7 @@ application while protecting against XSS.
<value>bar</value>
</property>
</javaApiLinks>
+ <source>6</source>
</configuration>
</plugin>
<plugin>
@@ -264,7 +265,7 @@ application while protecting against XSS.
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
- <version>4.12</version>
+ <version>4.13.1</version>
<scope>test</scope>
</dependency>
</dependencies>
diff --git a/pom.xml b/pom.xml
index eb6368e..ed9b523 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
<relativePath>parent</relativePath>
<groupId>com.googlecode.owasp-java-html-sanitizer</groupId>
<artifactId>parent</artifactId>
- <version>20191001.1</version>
+ <version>20220608.2-SNAPSHOT</version>
</parent>
<name>OWASP Java HTML Sanitizer</name>
diff --git a/scripts/build_for_travis.sh b/scripts/build_for_travis.sh
index 8d8ff5e..5400a2f 100755
--- a/scripts/build_for_travis.sh
+++ b/scripts/build_for_travis.sh
@@ -14,13 +14,16 @@ if echo $TRAVIS_JDK_VERSION | egrep -q '(jdk|jre)[67]($|[^0-9])'; then
# The main library only uses jdk6 compatible dependencies,
# but Guava 21.0 is compatibility with jdk 7.
COMMON_FLAGS="$COMMON_FLAGS -Dguava.version=20.0"
-
+fi
+if echo $TRAVIS_JDK_VERSION | egrep -q '(jdk|jre)([678]|11)($|[^0-9])'; then
# Older versions of javadoc barf on -Xdoclint flags used
# to configure the maven-javadoc-plugin.
+ # JDK8 javadoc barfs on the flag "-html5]
+ # JDK11 barfs too. https://bugs.openjdk.java.net/browse/JDK-8212233
+ # JDK9 is okay. Yay!
COMMON_FLAGS="$COMMON_FLAGS -Dmaven.javadoc.skip=true"
fi
-
echo "*** TRAVIS_JDK_VERSION=$TRAVIS_JDK_VERSION COMMON_FLAGS=($COMMON_FLAGS) IS_LEGACY=$IS_LEGACY"
mvn install -DskipTests=true $COMMON_FLAGS
diff --git a/src/main/java/org/owasp/html/CssSchema.java b/src/main/java/org/owasp/html/CssSchema.java
index 38e6132..8438628 100644
--- a/src/main/java/org/owasp/html/CssSchema.java
+++ b/src/main/java/org/owasp/html/CssSchema.java
@@ -293,7 +293,9 @@ public final class CssSchema {
ImmutableSet<String> mozOutlineLiterals3 = ImmutableSet.of(
"hidden", "inherit", "inset", "invert", "medium", "none");
ImmutableMap<String, String> mozOutlineFunctions =
- ImmutableMap.<String, String>of("rgb(", "rgb()", "rgba(", "rgba()");
+ ImmutableMap.<String, String>of(
+ "rgb(", "rgb()", "rgba(", "rgba()",
+ "hsl(", "hsl()", "hsla(", "hsla()");
ImmutableSet<String> mozOutlineColorLiterals0 =
ImmutableSet.of("inherit", "invert");
ImmutableSet<String> mozOutlineStyleLiterals0 =
@@ -324,6 +326,7 @@ public final class CssSchema {
.put("repeating-linear-gradient(", "repeating-linear-gradient()")
.put("repeating-radial-gradient(", "repeating-radial-gradient()")
.put("rgb(", "rgb()").put("rgba(", "rgba()")
+ .put("hsl(", "hsl()").put("hsla(", "hsla()")
.build();
ImmutableSet<String> backgroundAttachmentLiterals0 =
ImmutableSet.of(",", "fixed", "local", "scroll");
@@ -742,6 +745,9 @@ public final class CssSchema {
builder.put("zoom", new Property(1, fontStretchLiterals1, zeroFns));
Property rgb$Fun = new Property(1, rgb$FunLiterals0, zeroFns);
builder.put("rgb()", rgb$Fun);
+ builder.put("rgba()", rgb$Fun);
+ builder.put("hsl()", rgb$Fun);
+ builder.put("hsla()", rgb$Fun);
@SuppressWarnings("unchecked")
Property image$Fun = new Property(
18, union(mozOutlineLiterals0, rgb$FunLiterals0), mozOutlineFunctions);
@@ -835,7 +841,6 @@ public final class CssSchema {
builder.put("width", margin);
builder.put("word-spacing", letterSpacing);
builder.put("z-index", bottom);
- builder.put("rgba()", rgb$Fun);
builder.put("repeating-linear-gradient()", linearGradient$Fun);
builder.put("repeating-radial-gradient()", radialGradient$Fun);
DEFINITIONS = builder.build();
@@ -961,6 +966,8 @@ public final class CssSchema {
"repeating-radial-gradient()",
"rgb()",
"rgba()",
+ "hsl()",
+ "hsla()",
"richness",
"speak",
"speak-header",
diff --git a/src/main/java/org/owasp/html/CssTokens.java b/src/main/java/org/owasp/html/CssTokens.java
index 28aa16d..7fd4490 100644
--- a/src/main/java/org/owasp/html/CssTokens.java
+++ b/src/main/java/org/owasp/html/CssTokens.java
@@ -453,7 +453,7 @@ final class CssTokens implements Iterable<String> {
char ch = css.charAt(pos);
int startOfToken = pos;
int startOfOutputToken = sb.length();
- final TokenType type;
+ TokenType type;
switch (ch) {
case '\t': case '\n': case '\f': case '\r': case ' ': case '\ufeff':
consumeIgnorable();
@@ -514,6 +514,7 @@ final class CssTokens implements Iterable<String> {
type = TokenType.UNICODE_RANGE;
} else {
type = consumeIdentOrUrlOrFunction();
+ assert type != null;
}
break;
case '0': case '1': case '2': case '3': case '4':
@@ -533,7 +534,14 @@ final class CssTokens implements Iterable<String> {
if (consumeIgnorable()) { // -->
type = TokenType.WHITESPACE;
} else {
- type = consumeIdentOrUrlOrFunction();
+ TokenType identType = consumeIdentOrUrlOrFunction();
+ if (identType == null) {
+ breakOutput();
+ consumeDelim(ch);
+ type = TokenType.DELIM;
+ } else {
+ type = identType;
+ }
}
} else if (isIdentPart(lookahead)) {
// treat ".<IDENT>" as one token.
@@ -589,9 +597,17 @@ final class CssTokens implements Iterable<String> {
}
break;
}
- case '_':
- type = consumeIdentOrUrlOrFunction();
+ case '_': {
+ TokenType identType = consumeIdentOrUrlOrFunction();
+ if (identType != null) {
+ type = identType;
+ } else {
+ ++pos; // drop
+ breakOutput();
+ type = TokenType.WHITESPACE;
+ }
break;
+ }
case '\\': {
// Optimistically parse as an ident.
TokenType identType = consumeIdentOrUrlOrFunction();
@@ -624,7 +640,13 @@ final class CssTokens implements Iterable<String> {
type = TokenType.WHITESPACE;
}
}
- assert pos > startOfToken
+ // Make progress even in the face of errors above.
+ if (type == null && pos == startOfToken) {
+ type = TokenType.WHITESPACE;
+ breakOutput();
+ ++pos;
+ }
+ assert type != null && pos > startOfToken
: "empty token at " + pos + ", ch0=" + css.charAt(startOfToken)
+ ":U+" + Integer.toHexString(css.charAt(startOfToken));
int endOfOutputToken = sb.length();
diff --git a/src/main/java/org/owasp/html/ElementAndAttributePolicies.java b/src/main/java/org/owasp/html/ElementAndAttributePolicies.java
index e745473..8f2cdca 100644
--- a/src/main/java/org/owasp/html/ElementAndAttributePolicies.java
+++ b/src/main/java/org/owasp/html/ElementAndAttributePolicies.java
@@ -35,7 +35,7 @@ import javax.annotation.concurrent.Immutable;
/**
* Encapsulates all the information needed by the
- * {@link ElementAndAttributePolicySanitizerPolicy} to sanitize one kind
+ * {@link ElementAndAttributePolicyBasedSanitizerPolicy} to sanitize one kind
* of element.
*/
@Immutable
@@ -43,18 +43,18 @@ final class ElementAndAttributePolicies {
final String elementName;
final ElementPolicy elPolicy;
final ImmutableMap<String, AttributePolicy> attrPolicies;
- final boolean skipIfEmpty;
+ final HtmlTagSkipType htmlTagSkipType;
ElementAndAttributePolicies(
String elementName,
ElementPolicy elPolicy,
Map<? extends String, ? extends AttributePolicy>
attrPolicies,
- boolean skipIfEmpty) {
+ HtmlTagSkipType htmlTagSkipType) {
this.elementName = elementName;
this.elPolicy = elPolicy;
this.attrPolicies = ImmutableMap.copyOf(attrPolicies);
- this.skipIfEmpty = skipIfEmpty;
+ this.htmlTagSkipType = htmlTagSkipType;
}
ElementAndAttributePolicies and(ElementAndAttributePolicies p) {
@@ -78,24 +78,11 @@ final class ElementAndAttributePolicies {
}
}
- // HACK: this is attempting to recognize when skipIfEmpty has been
- // explicitly set in HtmlPolicyBuilder and can only make a best effort at
- // that and is also too tightly coupled with HtmlPolicyBuilder.
- // Maybe go tri-state.
- boolean combinedSkipIfEmpty;
- if (HtmlPolicyBuilder.DEFAULT_SKIP_IF_EMPTY.contains(elementName)) {
- // Either policy explicitly opted out of skip if empty.
- combinedSkipIfEmpty = skipIfEmpty && p.skipIfEmpty;
- } else {
- // Either policy explicitly specified skip if empty.
- combinedSkipIfEmpty = skipIfEmpty || p.skipIfEmpty;
- }
-
return new ElementAndAttributePolicies(
elementName,
ElementPolicy.Util.join(elPolicy, p.elPolicy),
joinedAttrPolicies.build(),
- combinedSkipIfEmpty);
+ this.htmlTagSkipType.and(p.htmlTagSkipType));
}
ElementAndAttributePolicies andGlobals(
@@ -130,7 +117,7 @@ final class ElementAndAttributePolicies {
}
if (anded == null) { return this; }
return new ElementAndAttributePolicies(
- elementName, elPolicy, anded, skipIfEmpty);
+ elementName, elPolicy, anded, htmlTagSkipType);
}
}
diff --git a/src/main/java/org/owasp/html/ElementAndAttributePolicyBasedSanitizerPolicy.java b/src/main/java/org/owasp/html/ElementAndAttributePolicyBasedSanitizerPolicy.java
index c643b73..c8da461 100644
--- a/src/main/java/org/owasp/html/ElementAndAttributePolicyBasedSanitizerPolicy.java
+++ b/src/main/java/org/owasp/html/ElementAndAttributePolicyBasedSanitizerPolicy.java
@@ -104,7 +104,7 @@ class ElementAndAttributePolicyBasedSanitizerPolicy
ElementAndAttributePolicies policies = elAndAttrPolicies.get(elementName);
String adjustedElementName = applyPolicies(elementName, attrs, policies);
if (adjustedElementName != null
- && !(attrs.isEmpty() && policies.skipIfEmpty)) {
+ && !(attrs.isEmpty() && policies.htmlTagSkipType.skipAvailability())) {
writeOpenTag(policies, adjustedElementName, attrs);
return;
}
@@ -144,7 +144,7 @@ class ElementAndAttributePolicyBasedSanitizerPolicy
adjustedElementName = policies.elPolicy.apply(elementName, attrs);
if (adjustedElementName != null) {
- adjustedElementName = HtmlLexer.canonicalName(adjustedElementName);
+ adjustedElementName = HtmlLexer.canonicalElementName(adjustedElementName);
}
} else {
adjustedElementName = null;
diff --git a/src/main/java/org/owasp/html/Encoding.java b/src/main/java/org/owasp/html/Encoding.java
index 4a2a601..20dbed9 100644
--- a/src/main/java/org/owasp/html/Encoding.java
+++ b/src/main/java/org/owasp/html/Encoding.java
@@ -41,8 +41,21 @@ public final class Encoding {
*
* @param s text/html
* @return text/plain
+ * @deprecated specify whether s is in an attribute value
*/
public static String decodeHtml(String s) {
+ return decodeHtml(s, false);
+ }
+
+ /**
+ * Decodes HTML entities to produce a string containing only valid
+ * Unicode scalar values.
+ *
+ * @param s text/html
+ * @param inAttribute is s in an attribute value?
+ * @return text/plain
+ */
+ public static String decodeHtml(String s, boolean inAttribute) {
int firstAmp = s.indexOf('&');
int safeLimit = longestPrefixOfGoodCodeunits(s);
if ((firstAmp & safeLimit) < 0) { return s; }
@@ -55,7 +68,7 @@ public final class Encoding {
int amp = firstAmp;
while (amp >= 0) {
sb.append(s, pos, amp);
- int end = HtmlEntities.appendDecodedEntity(s, amp, n, sb);
+ int end = HtmlEntities.appendDecodedEntity(s, amp, n, inAttribute, sb);
pos = end;
amp = s.indexOf('&', end);
}
diff --git a/src/main/java/org/owasp/html/HtmlElementTables.java b/src/main/java/org/owasp/html/HtmlElementTables.java
index ee2ea64..1ff74e4 100644
--- a/src/main/java/org/owasp/html/HtmlElementTables.java
+++ b/src/main/java/org/owasp/html/HtmlElementTables.java
@@ -142,10 +142,10 @@ public final class HtmlElementTables {
TD_TAG, new int[] { TR_TAG, TD_TAG, TH_TAG },
new int[] { TABLE_TAG, TBODY_TAG, TR_TAG }),
new FreeWrapper(
- TH_TAG, new int[] { TR_TAG, TD_TAG, TR_TAG },
+ TH_TAG, new int[] { TR_TAG, TD_TAG, TH_TAG },
new int[] { TABLE_TAG, TBODY_TAG, TR_TAG }),
new FreeWrapper(
- TR_TAG, new int[] { TBODY_TAG, THEAD_TAG, TFOOT_TAG, TR_TAG },
+ TR_TAG, new int[] { TBODY_TAG, THEAD_TAG, TFOOT_TAG, TR_TAG, TD_TAG, TH_TAG },
new int[] { TABLE_TAG, TBODY_TAG }),
new FreeWrapper(
TBODY_TAG, new int[] { TABLE_TAG, THEAD_TAG, TBODY_TAG, TFOOT_TAG },
diff --git a/src/main/java/org/owasp/html/HtmlEntities.java b/src/main/java/org/owasp/html/HtmlEntities.java
index 0842326..774108c 100644
--- a/src/main/java/org/owasp/html/HtmlEntities.java
+++ b/src/main/java/org/owasp/html/HtmlEntities.java
@@ -43,2149 +43,2277 @@ final class HtmlEntities {
private static final int LONGEST_ENTITY_NAME;
static {
- final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
-
// Source data: https://html.spec.whatwg.org/multipage/named-characters.html
+ // More readable: https://html.spec.whatwg.org/entities.json
+ String[] pairs = {
+ "AElig", "\u00c6",
+ "AElig;", "\u00c6",
+ "AMP", "\u0026",
+ "AMP;", "\u0026",
+ "Aacute", "\u00c1",
+ "Aacute;", "\u00c1",
+ "Abreve;", "\u0102",
+ "Acirc", "\u00c2",
+ "Acirc;", "\u00c2",
+ "Acy;", "\u0410",
+ "Afr;", "\ud835\udd04",
+ "Agrave", "\u00c0",
+ "Agrave;", "\u00c0",
+ "Alpha;", "\u0391",
+ "Amacr;", "\u0100",
+ "And;", "\u2a53",
+ "Aogon;", "\u0104",
+ "Aopf;", "\ud835\udd38",
+ "ApplyFunction;", "\u2061",
+ "Aring", "\u00c5",
+ "Aring;", "\u00c5",
+ "Ascr;", "\ud835\udc9c",
+ "Assign;", "\u2254",
+ "Atilde", "\u00c3",
+ "Atilde;", "\u00c3",
+ "Auml", "\u00c4",
+ "Auml;", "\u00c4",
+ "Backslash;", "\u2216",
+ "Barv;", "\u2ae7",
+ "Barwed;", "\u2306",
+ "Bcy;", "\u0411",
+ "Because;", "\u2235",
+ "Bernoullis;", "\u212c",
+ "Beta;", "\u0392",
+ "Bfr;", "\ud835\udd05",
+ "Bopf;", "\ud835\udd39",
+ "Breve;", "\u02d8",
+ "Bscr;", "\u212c",
+ "Bumpeq;", "\u224e",
+ "CHcy;", "\u0427",
+ "COPY", "\u00a9",
+ "COPY;", "\u00a9",
+ "Cacute;", "\u0106",
+ "Cap;", "\u22d2",
+ "CapitalDifferentialD;", "\u2145",
+ "Cayleys;", "\u212d",
+ "Ccaron;", "\u010c",
+ "Ccedil", "\u00c7",
+ "Ccedil;", "\u00c7",
+ "Ccirc;", "\u0108",
+ "Cconint;", "\u2230",
+ "Cdot;", "\u010a",
+ "Cedilla;", "\u00b8",
+ "CenterDot;", "\u00b7",
+ "Cfr;", "\u212d",
+ "Chi;", "\u03a7",
+ "CircleDot;", "\u2299",
+ "CircleMinus;", "\u2296",
+ "CirclePlus;", "\u2295",
+ "CircleTimes;", "\u2297",
+ "ClockwiseContourIntegral;", "\u2232",
+ "CloseCurlyDoubleQuote;", "\u201d",
+ "CloseCurlyQuote;", "\u2019",
+ "Colon;", "\u2237",
+ "Colone;", "\u2a74",
+ "Congruent;", "\u2261",
+ "Conint;", "\u222f",
+ "ContourIntegral;", "\u222e",
+ "Copf;", "\u2102",
+ "Coproduct;", "\u2210",
+ "CounterClockwiseContourIntegral;", "\u2233",
+ "Cross;", "\u2a2f",
+ "Cscr;", "\ud835\udc9e",
+ "Cup;", "\u22d3",
+ "CupCap;", "\u224d",
+ "DD;", "\u2145",
+ "DDotrahd;", "\u2911",
+ "DJcy;", "\u0402",
+ "DScy;", "\u0405",
+ "DZcy;", "\u040f",
+ "Dagger;", "\u2021",
+ "Darr;", "\u21a1",
+ "Dashv;", "\u2ae4",
+ "Dcaron;", "\u010e",
+ "Dcy;", "\u0414",
+ "Del;", "\u2207",
+ "Delta;", "\u0394",
+ "Dfr;", "\ud835\udd07",
+ "DiacriticalAcute;", "\u00b4",
+ "DiacriticalDot;", "\u02d9",
+ "DiacriticalDoubleAcute;", "\u02dd",
+ "DiacriticalGrave;", "\u0060",
+ "DiacriticalTilde;", "\u02dc",
+ "Diamond;", "\u22c4",
+ "DifferentialD;", "\u2146",
+ "Dopf;", "\ud835\udd3b",
+ "Dot;", "\u00a8",
+ "DotDot;", "\u20dc",
+ "DotEqual;", "\u2250",
+ "DoubleContourIntegral;", "\u222f",
+ "DoubleDot;", "\u00a8",
+ "DoubleDownArrow;", "\u21d3",
+ "DoubleLeftArrow;", "\u21d0",
+ "DoubleLeftRightArrow;", "\u21d4",
+ "DoubleLeftTee;", "\u2ae4",
+ "DoubleLongLeftArrow;", "\u27f8",
+ "DoubleLongLeftRightArrow;", "\u27fa",
+ "DoubleLongRightArrow;", "\u27f9",
+ "DoubleRightArrow;", "\u21d2",
+ "DoubleRightTee;", "\u22a8",
+ "DoubleUpArrow;", "\u21d1",
+ "DoubleUpDownArrow;", "\u21d5",
+ "DoubleVerticalBar;", "\u2225",
+ "DownArrow;", "\u2193",
+ "DownArrowBar;", "\u2913",
+ "DownArrowUpArrow;", "\u21f5",
+ "DownBreve;", "\u0311",
+ "DownLeftRightVector;", "\u2950",
+ "DownLeftTeeVector;", "\u295e",
+ "DownLeftVector;", "\u21bd",
+ "DownLeftVectorBar;", "\u2956",
+ "DownRightTeeVector;", "\u295f",
+ "DownRightVector;", "\u21c1",
+ "DownRightVectorBar;", "\u2957",
+ "DownTee;", "\u22a4",
+ "DownTeeArrow;", "\u21a7",
+ "Downarrow;", "\u21d3",
+ "Dscr;", "\ud835\udc9f",
+ "Dstrok;", "\u0110",
+ "ENG;", "\u014a",
+ "ETH", "\u00d0",
+ "ETH;", "\u00d0",
+ "Eacute", "\u00c9",
+ "Eacute;", "\u00c9",
+ "Ecaron;", "\u011a",
+ "Ecirc", "\u00ca",
+ "Ecirc;", "\u00ca",
+ "Ecy;", "\u042d",
+ "Edot;", "\u0116",
+ "Efr;", "\ud835\udd08",
+ "Egrave", "\u00c8",
+ "Egrave;", "\u00c8",
+ "Element;", "\u2208",
+ "Emacr;", "\u0112",
+ "EmptySmallSquare;", "\u25fb",
+ "EmptyVerySmallSquare;", "\u25ab",
+ "Eogon;", "\u0118",
+ "Eopf;", "\ud835\udd3c",
+ "Epsilon;", "\u0395",
+ "Equal;", "\u2a75",
+ "EqualTilde;", "\u2242",
+ "Equilibrium;", "\u21cc",
+ "Escr;", "\u2130",
+ "Esim;", "\u2a73",
+ "Eta;", "\u0397",
+ "Euml", "\u00cb",
+ "Euml;", "\u00cb",
+ "Exists;", "\u2203",
+ "ExponentialE;", "\u2147",
+ "Fcy;", "\u0424",
+ "Ffr;", "\ud835\udd09",
+ "FilledSmallSquare;", "\u25fc",
+ "FilledVerySmallSquare;", "\u25aa",
+ "Fopf;", "\ud835\udd3d",
+ "ForAll;", "\u2200",
+ "Fouriertrf;", "\u2131",
+ "Fscr;", "\u2131",
+ "GJcy;", "\u0403",
+ "GT", "\u003e",
+ "GT;", "\u003e",
+ "Gamma;", "\u0393",
+ "Gammad;", "\u03dc",
+ "Gbreve;", "\u011e",
+ "Gcedil;", "\u0122",
+ "Gcirc;", "\u011c",
+ "Gcy;", "\u0413",
+ "Gdot;", "\u0120",
+ "Gfr;", "\ud835\udd0a",
+ "Gg;", "\u22d9",
+ "Gopf;", "\ud835\udd3e",
+ "GreaterEqual;", "\u2265",
+ "GreaterEqualLess;", "\u22db",
+ "GreaterFullEqual;", "\u2267",
+ "GreaterGreater;", "\u2aa2",
+ "GreaterLess;", "\u2277",
+ "GreaterSlantEqual;", "\u2a7e",
+ "GreaterTilde;", "\u2273",
+ "Gscr;", "\ud835\udca2",
+ "Gt;", "\u226b",
+ "HARDcy;", "\u042a",
+ "Hacek;", "\u02c7",
+ "Hat;", "\u005e",
+ "Hcirc;", "\u0124",
+ "Hfr;", "\u210c",
+ "HilbertSpace;", "\u210b",
+ "Hopf;", "\u210d",
+ "HorizontalLine;", "\u2500",
+ "Hscr;", "\u210b",
+ "Hstrok;", "\u0126",
+ "HumpDownHump;", "\u224e",
+ "HumpEqual;", "\u224f",
+ "IEcy;", "\u0415",
+ "IJlig;", "\u0132",
+ "IOcy;", "\u0401",
+ "Iacute", "\u00cd",
+ "Iacute;", "\u00cd",
+ "Icirc", "\u00ce",
+ "Icirc;", "\u00ce",
+ "Icy;", "\u0418",
+ "Idot;", "\u0130",
+ "Ifr;", "\u2111",
+ "Igrave", "\u00cc",
+ "Igrave;", "\u00cc",
+ "Im;", "\u2111",
+ "Imacr;", "\u012a",
+ "ImaginaryI;", "\u2148",
+ "Implies;", "\u21d2",
+ "Int;", "\u222c",
+ "Integral;", "\u222b",
+ "Intersection;", "\u22c2",
+ "InvisibleComma;", "\u2063",
+ "InvisibleTimes;", "\u2062",
+ "Iogon;", "\u012e",
+ "Iopf;", "\ud835\udd40",
+ "Iota;", "\u0399",
+ "Iscr;", "\u2110",
+ "Itilde;", "\u0128",
+ "Iukcy;", "\u0406",
+ "Iuml", "\u00cf",
+ "Iuml;", "\u00cf",
+ "Jcirc;", "\u0134",
+ "Jcy;", "\u0419",
+ "Jfr;", "\ud835\udd0d",
+ "Jopf;", "\ud835\udd41",
+ "Jscr;", "\ud835\udca5",
+ "Jsercy;", "\u0408",
+ "Jukcy;", "\u0404",
+ "KHcy;", "\u0425",
+ "KJcy;", "\u040c",
+ "Kappa;", "\u039a",
+ "Kcedil;", "\u0136",
+ "Kcy;", "\u041a",
+ "Kfr;", "\ud835\udd0e",
+ "Kopf;", "\ud835\udd42",
+ "Kscr;", "\ud835\udca6",
+ "LJcy;", "\u0409",
+ "LT", "\u003c",
+ "LT;", "\u003c",
+ "Lacute;", "\u0139",
+ "Lambda;", "\u039b",
+ "Lang;", "\u27ea",
+ "Laplacetrf;", "\u2112",
+ "Larr;", "\u219e",
+ "Lcaron;", "\u013d",
+ "Lcedil;", "\u013b",
+ "Lcy;", "\u041b",
+ "LeftAngleBracket;", "\u27e8",
+ "LeftArrow;", "\u2190",
+ "LeftArrowBar;", "\u21e4",
+ "LeftArrowRightArrow;", "\u21c6",
+ "LeftCeiling;", "\u2308",
+ "LeftDoubleBracket;", "\u27e6",
+ "LeftDownTeeVector;", "\u2961",
+ "LeftDownVector;", "\u21c3",
+ "LeftDownVectorBar;", "\u2959",
+ "LeftFloor;", "\u230a",
+ "LeftRightArrow;", "\u2194",
+ "LeftRightVector;", "\u294e",
+ "LeftTee;", "\u22a3",
+ "LeftTeeArrow;", "\u21a4",
+ "LeftTeeVector;", "\u295a",
+ "LeftTriangle;", "\u22b2",
+ "LeftTriangleBar;", "\u29cf",
+ "LeftTriangleEqual;", "\u22b4",
+ "LeftUpDownVector;", "\u2951",
+ "LeftUpTeeVector;", "\u2960",
+ "LeftUpVector;", "\u21bf",
+ "LeftUpVectorBar;", "\u2958",
+ "LeftVector;", "\u21bc",
+ "LeftVectorBar;", "\u2952",
+ "Leftarrow;", "\u21d0",
+ "Leftrightarrow;", "\u21d4",
+ "LessEqualGreater;", "\u22da",
+ "LessFullEqual;", "\u2266",
+ "LessGreater;", "\u2276",
+ "LessLess;", "\u2aa1",
+ "LessSlantEqual;", "\u2a7d",
+ "LessTilde;", "\u2272",
+ "Lfr;", "\ud835\udd0f",
+ "Ll;", "\u22d8",
+ "Lleftarrow;", "\u21da",
+ "Lmidot;", "\u013f",
+ "LongLeftArrow;", "\u27f5",
+ "LongLeftRightArrow;", "\u27f7",
+ "LongRightArrow;", "\u27f6",
+ "Longleftarrow;", "\u27f8",
+ "Longleftrightarrow;", "\u27fa",
+ "Longrightarrow;", "\u27f9",
+ "Lopf;", "\ud835\udd43",
+ "LowerLeftArrow;", "\u2199",
+ "LowerRightArrow;", "\u2198",
+ "Lscr;", "\u2112",
+ "Lsh;", "\u21b0",
+ "Lstrok;", "\u0141",
+ "Lt;", "\u226a",
+ "Map;", "\u2905",
+ "Mcy;", "\u041c",
+ "MediumSpace;", "\u205f",
+ "Mellintrf;", "\u2133",
+ "Mfr;", "\ud835\udd10",
+ "MinusPlus;", "\u2213",
+ "Mopf;", "\ud835\udd44",
+ "Mscr;", "\u2133",
+ "Mu;", "\u039c",
+ "NJcy;", "\u040a",
+ "Nacute;", "\u0143",
+ "Ncaron;", "\u0147",
+ "Ncedil;", "\u0145",
+ "Ncy;", "\u041d",
+ "NegativeMediumSpace;", "\u200b",
+ "NegativeThickSpace;", "\u200b",
+ "NegativeThinSpace;", "\u200b",
+ "NegativeVeryThinSpace;", "\u200b",
+ "NestedGreaterGreater;", "\u226b",
+ "NestedLessLess;", "\u226a",
+ "NewLine;", "\n",
+ "Nfr;", "\ud835\udd11",
+ "NoBreak;", "\u2060",
+ "NonBreakingSpace;", "\u00a0",
+ "Nopf;", "\u2115",
+ "Not;", "\u2aec",
+ "NotCongruent;", "\u2262",
+ "NotCupCap;", "\u226d",
+ "NotDoubleVerticalBar;", "\u2226",
+ "NotElement;", "\u2209",
+ "NotEqual;", "\u2260",
+ "NotEqualTilde;", "\u2242\u0338",
+ "NotExists;", "\u2204",
+ "NotGreater;", "\u226f",
+ "NotGreaterEqual;", "\u2271",
+ "NotGreaterFullEqual;", "\u2267\u0338",
+ "NotGreaterGreater;", "\u226b\u0338",
+ "NotGreaterLess;", "\u2279",
+ "NotGreaterSlantEqual;", "\u2a7e\u0338",
+ "NotGreaterTilde;", "\u2275",
+ "NotHumpDownHump;", "\u224e\u0338",
+ "NotHumpEqual;", "\u224f\u0338",
+ "NotLeftTriangle;", "\u22ea",
+ "NotLeftTriangleBar;", "\u29cf\u0338",
+ "NotLeftTriangleEqual;", "\u22ec",
+ "NotLess;", "\u226e",
+ "NotLessEqual;", "\u2270",
+ "NotLessGreater;", "\u2278",
+ "NotLessLess;", "\u226a\u0338",
+ "NotLessSlantEqual;", "\u2a7d\u0338",
+ "NotLessTilde;", "\u2274",
+ "NotNestedGreaterGreater;", "\u2aa2\u0338",
+ "NotNestedLessLess;", "\u2aa1\u0338",
+ "NotPrecedes;", "\u2280",
+ "NotPrecedesEqual;", "\u2aaf\u0338",
+ "NotPrecedesSlantEqual;", "\u22e0",
+ "NotReverseElement;", "\u220c",
+ "NotRightTriangle;", "\u22eb",
+ "NotRightTriangleBar;", "\u29d0\u0338",
+ "NotRightTriangleEqual;", "\u22ed",
+ "NotSquareSubset;", "\u228f\u0338",
+ "NotSquareSubsetEqual;", "\u22e2",
+ "NotSquareSuperset;", "\u2290\u0338",
+ "NotSquareSupersetEqual;", "\u22e3",
+ "NotSubset;", "\u2282\u20d2",
+ "NotSubsetEqual;", "\u2288",
+ "NotSucceeds;", "\u2281",
+ "NotSucceedsEqual;", "\u2ab0\u0338",
+ "NotSucceedsSlantEqual;", "\u22e1",
+ "NotSucceedsTilde;", "\u227f\u0338",
+ "NotSuperset;", "\u2283\u20d2",
+ "NotSupersetEqual;", "\u2289",
+ "NotTilde;", "\u2241",
+ "NotTildeEqual;", "\u2244",
+ "NotTildeFullEqual;", "\u2247",
+ "NotTildeTilde;", "\u2249",
+ "NotVerticalBar;", "\u2224",
+ "Nscr;", "\ud835\udca9",
+ "Ntilde", "\u00d1",
+ "Ntilde;", "\u00d1",
+ "Nu;", "\u039d",
+ "OElig;", "\u0152",
+ "Oacute", "\u00d3",
+ "Oacute;", "\u00d3",
+ "Ocirc", "\u00d4",
+ "Ocirc;", "\u00d4",
+ "Ocy;", "\u041e",
+ "Odblac;", "\u0150",
+ "Ofr;", "\ud835\udd12",
+ "Ograve", "\u00d2",
+ "Ograve;", "\u00d2",
+ "Omacr;", "\u014c",
+ "Omega;", "\u03a9",
+ "Omicron;", "\u039f",
+ "Oopf;", "\ud835\udd46",
+ "OpenCurlyDoubleQuote;", "\u201c",
+ "OpenCurlyQuote;", "\u2018",
+ "Or;", "\u2a54",
+ "Oscr;", "\ud835\udcaa",
+ "Oslash", "\u00d8",
+ "Oslash;", "\u00d8",
+ "Otilde", "\u00d5",
+ "Otilde;", "\u00d5",
+ "Otimes;", "\u2a37",
+ "Ouml", "\u00d6",
+ "Ouml;", "\u00d6",
+ "OverBar;", "\u203e",
+ "OverBrace;", "\u23de",
+ "OverBracket;", "\u23b4",
+ "OverParenthesis;", "\u23dc",
+ "PartialD;", "\u2202",
+ "Pcy;", "\u041f",
+ "Pfr;", "\ud835\udd13",
+ "Phi;", "\u03a6",
+ "Pi;", "\u03a0",
+ "PlusMinus;", "\u00b1",
+ "Poincareplane;", "\u210c",
+ "Popf;", "\u2119",
+ "Pr;", "\u2abb",
+ "Precedes;", "\u227a",
+ "PrecedesEqual;", "\u2aaf",
+ "PrecedesSlantEqual;", "\u227c",
+ "PrecedesTilde;", "\u227e",
+ "Prime;", "\u2033",
+ "Product;", "\u220f",
+ "Proportion;", "\u2237",
+ "Proportional;", "\u221d",
+ "Pscr;", "\ud835\udcab",
+ "Psi;", "\u03a8",
+ "QUOT", "\"",
+ "QUOT;", "\"",
+ "Qfr;", "\ud835\udd14",
+ "Qopf;", "\u211a",
+ "Qscr;", "\ud835\udcac",
+ "RBarr;", "\u2910",
+ "REG", "\u00ae",
+ "REG;", "\u00ae",
+ "Racute;", "\u0154",
+ "Rang;", "\u27eb",
+ "Rarr;", "\u21a0",
+ "Rarrtl;", "\u2916",
+ "Rcaron;", "\u0158",
+ "Rcedil;", "\u0156",
+ "Rcy;", "\u0420",
+ "Re;", "\u211c",
+ "ReverseElement;", "\u220b",
+ "ReverseEquilibrium;", "\u21cb",
+ "ReverseUpEquilibrium;", "\u296f",
+ "Rfr;", "\u211c",
+ "Rho;", "\u03a1",
+ "RightAngleBracket;", "\u27e9",
+ "RightArrow;", "\u2192",
+ "RightArrowBar;", "\u21e5",
+ "RightArrowLeftArrow;", "\u21c4",
+ "RightCeiling;", "\u2309",
+ "RightDoubleBracket;", "\u27e7",
+ "RightDownTeeVector;", "\u295d",
+ "RightDownVector;", "\u21c2",
+ "RightDownVectorBar;", "\u2955",
+ "RightFloor;", "\u230b",
+ "RightTee;", "\u22a2",
+ "RightTeeArrow;", "\u21a6",
+ "RightTeeVector;", "\u295b",
+ "RightTriangle;", "\u22b3",
+ "RightTriangleBar;", "\u29d0",
+ "RightTriangleEqual;", "\u22b5",
+ "RightUpDownVector;", "\u294f",
+ "RightUpTeeVector;", "\u295c",
+ "RightUpVector;", "\u21be",
+ "RightUpVectorBar;", "\u2954",
+ "RightVector;", "\u21c0",
+ "RightVectorBar;", "\u2953",
+ "Rightarrow;", "\u21d2",
+ "Ropf;", "\u211d",
+ "RoundImplies;", "\u2970",
+ "Rrightarrow;", "\u21db",
+ "Rscr;", "\u211b",
+ "Rsh;", "\u21b1",
+ "RuleDelayed;", "\u29f4",
+ "SHCHcy;", "\u0429",
+ "SHcy;", "\u0428",
+ "SOFTcy;", "\u042c",
+ "Sacute;", "\u015a",
+ "Sc;", "\u2abc",
+ "Scaron;", "\u0160",
+ "Scedil;", "\u015e",
+ "Scirc;", "\u015c",
+ "Scy;", "\u0421",
+ "Sfr;", "\ud835\udd16",
+ "ShortDownArrow;", "\u2193",
+ "ShortLeftArrow;", "\u2190",
+ "ShortRightArrow;", "\u2192",
+ "ShortUpArrow;", "\u2191",
+ "Sigma;", "\u03a3",
+ "SmallCircle;", "\u2218",
+ "Sopf;", "\ud835\udd4a",
+ "Sqrt;", "\u221a",
+ "Square;", "\u25a1",
+ "SquareIntersection;", "\u2293",
+ "SquareSubset;", "\u228f",
+ "SquareSubsetEqual;", "\u2291",
+ "SquareSuperset;", "\u2290",
+ "SquareSupersetEqual;", "\u2292",
+ "SquareUnion;", "\u2294",
+ "Sscr;", "\ud835\udcae",
+ "Star;", "\u22c6",
+ "Sub;", "\u22d0",
+ "Subset;", "\u22d0",
+ "SubsetEqual;", "\u2286",
+ "Succeeds;", "\u227b",
+ "SucceedsEqual;", "\u2ab0",
+ "SucceedsSlantEqual;", "\u227d",
+ "SucceedsTilde;", "\u227f",
+ "SuchThat;", "\u220b",
+ "Sum;", "\u2211",
+ "Sup;", "\u22d1",
+ "Superset;", "\u2283",
+ "SupersetEqual;", "\u2287",
+ "Supset;", "\u22d1",
+ "THORN", "\u00de",
+ "THORN;", "\u00de",
+ "TRADE;", "\u2122",
+ "TSHcy;", "\u040b",
+ "TScy;", "\u0426",
+ "Tab;", "\u0009",
+ "Tau;", "\u03a4",
+ "Tcaron;", "\u0164",
+ "Tcedil;", "\u0162",
+ "Tcy;", "\u0422",
+ "Tfr;", "\ud835\udd17",
+ "Therefore;", "\u2234",
+ "Theta;", "\u0398",
+ "ThickSpace;", "\u205f\u200a",
+ "ThinSpace;", "\u2009",
+ "Tilde;", "\u223c",
+ "TildeEqual;", "\u2243",
+ "TildeFullEqual;", "\u2245",
+ "TildeTilde;", "\u2248",
+ "Topf;", "\ud835\udd4b",
+ "TripleDot;", "\u20db",
+ "Tscr;", "\ud835\udcaf",
+ "Tstrok;", "\u0166",
+ "Uacute", "\u00da",
+ "Uacute;", "\u00da",
+ "Uarr;", "\u219f",
+ "Uarrocir;", "\u2949",
+ "Ubrcy;", "\u040e",
+ "Ubreve;", "\u016c",
+ "Ucirc", "\u00db",
+ "Ucirc;", "\u00db",
+ "Ucy;", "\u0423",
+ "Udblac;", "\u0170",
+ "Ufr;", "\ud835\udd18",
+ "Ugrave", "\u00d9",
+ "Ugrave;", "\u00d9",
+ "Umacr;", "\u016a",
+ "UnderBar;", "\u005f",
+ "UnderBrace;", "\u23df",
+ "UnderBracket;", "\u23b5",
+ "UnderParenthesis;", "\u23dd",
+ "Union;", "\u22c3",
+ "UnionPlus;", "\u228e",
+ "Uogon;", "\u0172",
+ "Uopf;", "\ud835\udd4c",
+ "UpArrow;", "\u2191",
+ "UpArrowBar;", "\u2912",
+ "UpArrowDownArrow;", "\u21c5",
+ "UpDownArrow;", "\u2195",
+ "UpEquilibrium;", "\u296e",
+ "UpTee;", "\u22a5",
+ "UpTeeArrow;", "\u21a5",
+ "Uparrow;", "\u21d1",
+ "Updownarrow;", "\u21d5",
+ "UpperLeftArrow;", "\u2196",
+ "UpperRightArrow;", "\u2197",
+ "Upsi;", "\u03d2",
+ "Upsilon;", "\u03a5",
+ "Uring;", "\u016e",
+ "Uscr;", "\ud835\udcb0",
+ "Utilde;", "\u0168",
+ "Uuml", "\u00dc",
+ "Uuml;", "\u00dc",
+ "VDash;", "\u22ab",
+ "Vbar;", "\u2aeb",
+ "Vcy;", "\u0412",
+ "Vdash;", "\u22a9",
+ "Vdashl;", "\u2ae6",
+ "Vee;", "\u22c1",
+ "Verbar;", "\u2016",
+ "Vert;", "\u2016",
+ "VerticalBar;", "\u2223",
+ "VerticalLine;", "\u007c",
+ "VerticalSeparator;", "\u2758",
+ "VerticalTilde;", "\u2240",
+ "VeryThinSpace;", "\u200a",
+ "Vfr;", "\ud835\udd19",
+ "Vopf;", "\ud835\udd4d",
+ "Vscr;", "\ud835\udcb1",
+ "Vvdash;", "\u22aa",
+ "Wcirc;", "\u0174",
+ "Wedge;", "\u22c0",
+ "Wfr;", "\ud835\udd1a",
+ "Wopf;", "\ud835\udd4e",
+ "Wscr;", "\ud835\udcb2",
+ "Xfr;", "\ud835\udd1b",
+ "Xi;", "\u039e",
+ "Xopf;", "\ud835\udd4f",
+ "Xscr;", "\ud835\udcb3",
+ "YAcy;", "\u042f",
+ "YIcy;", "\u0407",
+ "YUcy;", "\u042e",
+ "Yacute", "\u00dd",
+ "Yacute;", "\u00dd",
+ "Ycirc;", "\u0176",
+ "Ycy;", "\u042b",
+ "Yfr;", "\ud835\udd1c",
+ "Yopf;", "\ud835\udd50",
+ "Yscr;", "\ud835\udcb4",
+ "Yuml;", "\u0178",
+ "ZHcy;", "\u0416",
+ "Zacute;", "\u0179",
+ "Zcaron;", "\u017d",
+ "Zcy;", "\u0417",
+ "Zdot;", "\u017b",
+ "ZeroWidthSpace;", "\u200b",
+ "Zeta;", "\u0396",
+ "Zfr;", "\u2128",
+ "Zopf;", "\u2124",
+ "Zscr;", "\ud835\udcb5",
+ "aacute", "\u00e1",
+ "aacute;", "\u00e1",
+ "abreve;", "\u0103",
+ "ac;", "\u223e",
+ "acE;", "\u223e\u0333",
+ "acd;", "\u223f",
+ "acirc", "\u00e2",
+ "acirc;", "\u00e2",
+ "acute", "\u00b4",
+ "acute;", "\u00b4",
+ "acy;", "\u0430",
+ "aelig", "\u00e6",
+ "aelig;", "\u00e6",
+ "af;", "\u2061",
+ "afr;", "\ud835\udd1e",
+ "agrave", "\u00e0",
+ "agrave;", "\u00e0",
+ "alefsym;", "\u2135",
+ "aleph;", "\u2135",
+ "alpha;", "\u03b1",
+ "amacr;", "\u0101",
+ "amalg;", "\u2a3f",
+ "amp", "\u0026",
+ "amp;", "\u0026",
+ "and;", "\u2227",
+ "andand;", "\u2a55",
+ "andd;", "\u2a5c",
+ "andslope;", "\u2a58",
+ "andv;", "\u2a5a",
+ "ang;", "\u2220",
+ "ange;", "\u29a4",
+ "angle;", "\u2220",
+ "angmsd;", "\u2221",
+ "angmsdaa;", "\u29a8",
+ "angmsdab;", "\u29a9",
+ "angmsdac;", "\u29aa",
+ "angmsdad;", "\u29ab",
+ "angmsdae;", "\u29ac",
+ "angmsdaf;", "\u29ad",
+ "angmsdag;", "\u29ae",
+ "angmsdah;", "\u29af",
+ "angrt;", "\u221f",
+ "angrtvb;", "\u22be",
+ "angrtvbd;", "\u299d",
+ "angsph;", "\u2222",
+ "angst;", "\u00c5",
+ "angzarr;", "\u237c",
+ "aogon;", "\u0105",
+ "aopf;", "\ud835\udd52",
+ "ap;", "\u2248",
+ "apE;", "\u2a70",
+ "apacir;", "\u2a6f",
+ "ape;", "\u224a",
+ "apid;", "\u224b",
+ "apos;", "\u0027",
+ "approx;", "\u2248",
+ "approxeq;", "\u224a",
+ "aring", "\u00e5",
+ "aring;", "\u00e5",
+ "ascr;", "\ud835\udcb6",
+ "ast;", "\u002a",
+ "asymp;", "\u2248",
+ "asympeq;", "\u224d",
+ "atilde", "\u00e3",
+ "atilde;", "\u00e3",
+ "auml", "\u00e4",
+ "auml;", "\u00e4",
+ "awconint;", "\u2233",
+ "awint;", "\u2a11",
+ "bNot;", "\u2aed",
+ "backcong;", "\u224c",
+ "backepsilon;", "\u03f6",
+ "backprime;", "\u2035",
+ "backsim;", "\u223d",
+ "backsimeq;", "\u22cd",
+ "barvee;", "\u22bd",
+ "barwed;", "\u2305",
+ "barwedge;", "\u2305",
+ "bbrk;", "\u23b5",
+ "bbrktbrk;", "\u23b6",
+ "bcong;", "\u224c",
+ "bcy;", "\u0431",
+ "bdquo;", "\u201e",
+ "becaus;", "\u2235",
+ "because;", "\u2235",
+ "bemptyv;", "\u29b0",
+ "bepsi;", "\u03f6",
+ "bernou;", "\u212c",
+ "beta;", "\u03b2",
+ "beth;", "\u2136",
+ "between;", "\u226c",
+ "bfr;", "\ud835\udd1f",
+ "bigcap;", "\u22c2",
+ "bigcirc;", "\u25ef",
+ "bigcup;", "\u22c3",
+ "bigodot;", "\u2a00",
+ "bigoplus;", "\u2a01",
+ "bigotimes;", "\u2a02",
+ "bigsqcup;", "\u2a06",
+ "bigstar;", "\u2605",
+ "bigtriangledown;", "\u25bd",
+ "bigtriangleup;", "\u25b3",
+ "biguplus;", "\u2a04",
+ "bigvee;", "\u22c1",
+ "bigwedge;", "\u22c0",
+ "bkarow;", "\u290d",
+ "blacklozenge;", "\u29eb",
+ "blacksquare;", "\u25aa",
+ "blacktriangle;", "\u25b4",
+ "blacktriangledown;", "\u25be",
+ "blacktriangleleft;", "\u25c2",
+ "blacktriangleright;", "\u25b8",
+ "blank;", "\u2423",
+ "blk12;", "\u2592",
+ "blk14;", "\u2591",
+ "blk34;", "\u2593",
+ "block;", "\u2588",
+ "bne;", "\u003d\u20e5",
+ "bnequiv;", "\u2261\u20e5",
+ "bnot;", "\u2310",
+ "bopf;", "\ud835\udd53",
+ "bot;", "\u22a5",
+ "bottom;", "\u22a5",
+ "bowtie;", "\u22c8",
+ "boxDL;", "\u2557",
+ "boxDR;", "\u2554",
+ "boxDl;", "\u2556",
+ "boxDr;", "\u2553",
+ "boxH;", "\u2550",
+ "boxHD;", "\u2566",
+ "boxHU;", "\u2569",
+ "boxHd;", "\u2564",
+ "boxHu;", "\u2567",
+ "boxUL;", "\u255d",
+ "boxUR;", "\u255a",
+ "boxUl;", "\u255c",
+ "boxUr;", "\u2559",
+ "boxV;", "\u2551",
+ "boxVH;", "\u256c",
+ "boxVL;", "\u2563",
+ "boxVR;", "\u2560",
+ "boxVh;", "\u256b",
+ "boxVl;", "\u2562",
+ "boxVr;", "\u255f",
+ "boxbox;", "\u29c9",
+ "boxdL;", "\u2555",
+ "boxdR;", "\u2552",
+ "boxdl;", "\u2510",
+ "boxdr;", "\u250c",
+ "boxh;", "\u2500",
+ "boxhD;", "\u2565",
+ "boxhU;", "\u2568",
+ "boxhd;", "\u252c",
+ "boxhu;", "\u2534",
+ "boxminus;", "\u229f",
+ "boxplus;", "\u229e",
+ "boxtimes;", "\u22a0",
+ "boxuL;", "\u255b",
+ "boxuR;", "\u2558",
+ "boxul;", "\u2518",
+ "boxur;", "\u2514",
+ "boxv;", "\u2502",
+ "boxvH;", "\u256a",
+ "boxvL;", "\u2561",
+ "boxvR;", "\u255e",
+ "boxvh;", "\u253c",
+ "boxvl;", "\u2524",
+ "boxvr;", "\u251c",
+ "bprime;", "\u2035",
+ "breve;", "\u02d8",
+ "brvbar", "\u00a6",
+ "brvbar;", "\u00a6",
+ "bscr;", "\ud835\udcb7",
+ "bsemi;", "\u204f",
+ "bsim;", "\u223d",
+ "bsime;", "\u22cd",
+ "bsol;", "\\",
+ "bsolb;", "\u29c5",
+ "bsolhsub;", "\u27c8",
+ "bull;", "\u2022",
+ "bullet;", "\u2022",
+ "bump;", "\u224e",
+ "bumpE;", "\u2aae",
+ "bumpe;", "\u224f",
+ "bumpeq;", "\u224f",
+ "cacute;", "\u0107",
+ "cap;", "\u2229",
+ "capand;", "\u2a44",
+ "capbrcup;", "\u2a49",
+ "capcap;", "\u2a4b",
+ "capcup;", "\u2a47",
+ "capdot;", "\u2a40",
+ "caps;", "\u2229\ufe00",
+ "caret;", "\u2041",
+ "caron;", "\u02c7",
+ "ccaps;", "\u2a4d",
+ "ccaron;", "\u010d",
+ "ccedil", "\u00e7",
+ "ccedil;", "\u00e7",
+ "ccirc;", "\u0109",
+ "ccups;", "\u2a4c",
+ "ccupssm;", "\u2a50",
+ "cdot;", "\u010b",
+ "cedil", "\u00b8",
+ "cedil;", "\u00b8",
+ "cemptyv;", "\u29b2",
+ "cent", "\u00a2",
+ "cent;", "\u00a2",
+ "centerdot;", "\u00b7",
+ "cfr;", "\ud835\udd20",
+ "chcy;", "\u0447",
+ "check;", "\u2713",
+ "checkmark;", "\u2713",
+ "chi;", "\u03c7",
+ "cir;", "\u25cb",
+ "cirE;", "\u29c3",
+ "circ;", "\u02c6",
+ "circeq;", "\u2257",
+ "circlearrowleft;", "\u21ba",
+ "circlearrowright;", "\u21bb",
+ "circledR;", "\u00ae",
+ "circledS;", "\u24c8",
+ "circledast;", "\u229b",
+ "circledcirc;", "\u229a",
+ "circleddash;", "\u229d",
+ "cire;", "\u2257",
+ "cirfnint;", "\u2a10",
+ "cirmid;", "\u2aef",
+ "cirscir;", "\u29c2",
+ "clubs;", "\u2663",
+ "clubsuit;", "\u2663",
+ "colon;", "\u003a",
+ "colone;", "\u2254",
+ "coloneq;", "\u2254",
+ "comma;", "\u002c",
+ "commat;", "\u0040",
+ "comp;", "\u2201",
+ "compfn;", "\u2218",
+ "complement;", "\u2201",
+ "complexes;", "\u2102",
+ "cong;", "\u2245",
+ "congdot;", "\u2a6d",
+ "conint;", "\u222e",
+ "copf;", "\ud835\udd54",
+ "coprod;", "\u2210",
+ "copy", "\u00a9",
+ "copy;", "\u00a9",
+ "copysr;", "\u2117",
+ "crarr;", "\u21b5",
+ "cross;", "\u2717",
+ "cscr;", "\ud835\udcb8",
+ "csub;", "\u2acf",
+ "csube;", "\u2ad1",
+ "csup;", "\u2ad0",
+ "csupe;", "\u2ad2",
+ "ctdot;", "\u22ef",
+ "cudarrl;", "\u2938",
+ "cudarrr;", "\u2935",
+ "cuepr;", "\u22de",
+ "cuesc;", "\u22df",
+ "cularr;", "\u21b6",
+ "cularrp;", "\u293d",
+ "cup;", "\u222a",
+ "cupbrcap;", "\u2a48",
+ "cupcap;", "\u2a46",
+ "cupcup;", "\u2a4a",
+ "cupdot;", "\u228d",
+ "cupor;", "\u2a45",
+ "cups;", "\u222a\ufe00",
+ "curarr;", "\u21b7",
+ "curarrm;", "\u293c",
+ "curlyeqprec;", "\u22de",
+ "curlyeqsucc;", "\u22df",
+ "curlyvee;", "\u22ce",
+ "curlywedge;", "\u22cf",
+ "curren", "\u00a4",
+ "curren;", "\u00a4",
+ "curvearrowleft;", "\u21b6",
+ "curvearrowright;", "\u21b7",
+ "cuvee;", "\u22ce",
+ "cuwed;", "\u22cf",
+ "cwconint;", "\u2232",
+ "cwint;", "\u2231",
+ "cylcty;", "\u232d",
+ "dArr;", "\u21d3",
+ "dHar;", "\u2965",
+ "dagger;", "\u2020",
+ "daleth;", "\u2138",
+ "darr;", "\u2193",
+ "dash;", "\u2010",
+ "dashv;", "\u22a3",
+ "dbkarow;", "\u290f",
+ "dblac;", "\u02dd",
+ "dcaron;", "\u010f",
+ "dcy;", "\u0434",
+ "dd;", "\u2146",
+ "ddagger;", "\u2021",
+ "ddarr;", "\u21ca",
+ "ddotseq;", "\u2a77",
+ "deg", "\u00b0",
+ "deg;", "\u00b0",
+ "delta;", "\u03b4",
+ "demptyv;", "\u29b1",
+ "dfisht;", "\u297f",
+ "dfr;", "\ud835\udd21",
+ "dharl;", "\u21c3",
+ "dharr;", "\u21c2",
+ "diam;", "\u22c4",
+ "diamond;", "\u22c4",
+ "diamondsuit;", "\u2666",
+ "diams;", "\u2666",
+ "die;", "\u00a8",
+ "digamma;", "\u03dd",
+ "disin;", "\u22f2",
+ "div;", "\u00f7",
+ "divide", "\u00f7",
+ "divide;", "\u00f7",
+ "divideontimes;", "\u22c7",
+ "divonx;", "\u22c7",
+ "djcy;", "\u0452",
+ "dlcorn;", "\u231e",
+ "dlcrop;", "\u230d",
+ "dollar;", "\u0024",
+ "dopf;", "\ud835\udd55",
+ "dot;", "\u02d9",
+ "doteq;", "\u2250",
+ "doteqdot;", "\u2251",
+ "dotminus;", "\u2238",
+ "dotplus;", "\u2214",
+ "dotsquare;", "\u22a1",
+ "doublebarwedge;", "\u2306",
+ "downarrow;", "\u2193",
+ "downdownarrows;", "\u21ca",
+ "downharpoonleft;", "\u21c3",
+ "downharpoonright;", "\u21c2",
+ "drbkarow;", "\u2910",
+ "drcorn;", "\u231f",
+ "drcrop;", "\u230c",
+ "dscr;", "\ud835\udcb9",
+ "dscy;", "\u0455",
+ "dsol;", "\u29f6",
+ "dstrok;", "\u0111",
+ "dtdot;", "\u22f1",
+ "dtri;", "\u25bf",
+ "dtrif;", "\u25be",
+ "duarr;", "\u21f5",
+ "duhar;", "\u296f",
+ "dwangle;", "\u29a6",
+ "dzcy;", "\u045f",
+ "dzigrarr;", "\u27ff",
+ "eDDot;", "\u2a77",
+ "eDot;", "\u2251",
+ "eacute", "\u00e9",
+ "eacute;", "\u00e9",
+ "easter;", "\u2a6e",
+ "ecaron;", "\u011b",
+ "ecir;", "\u2256",
+ "ecirc", "\u00ea",
+ "ecirc;", "\u00ea",
+ "ecolon;", "\u2255",
+ "ecy;", "\u044d",
+ "edot;", "\u0117",
+ "ee;", "\u2147",
+ "efDot;", "\u2252",
+ "efr;", "\ud835\udd22",
+ "eg;", "\u2a9a",
+ "egrave", "\u00e8",
+ "egrave;", "\u00e8",
+ "egs;", "\u2a96",
+ "egsdot;", "\u2a98",
+ "el;", "\u2a99",
+ "elinters;", "\u23e7",
+ "ell;", "\u2113",
+ "els;", "\u2a95",
+ "elsdot;", "\u2a97",
+ "emacr;", "\u0113",
+ "empty;", "\u2205",
+ "emptyset;", "\u2205",
+ "emptyv;", "\u2205",
+ "emsp13;", "\u2004",
+ "emsp14;", "\u2005",
+ "emsp;", "\u2003",
+ "eng;", "\u014b",
+ "ensp;", "\u2002",
+ "eogon;", "\u0119",
+ "eopf;", "\ud835\udd56",
+ "epar;", "\u22d5",
+ "eparsl;", "\u29e3",
+ "eplus;", "\u2a71",
+ "epsi;", "\u03b5",
+ "epsilon;", "\u03b5",
+ "epsiv;", "\u03f5",
+ "eqcirc;", "\u2256",
+ "eqcolon;", "\u2255",
+ "eqsim;", "\u2242",
+ "eqslantgtr;", "\u2a96",
+ "eqslantless;", "\u2a95",
+ "equals;", "\u003d",
+ "equest;", "\u225f",
+ "equiv;", "\u2261",
+ "equivDD;", "\u2a78",
+ "eqvparsl;", "\u29e5",
+ "erDot;", "\u2253",
+ "erarr;", "\u2971",
+ "escr;", "\u212f",
+ "esdot;", "\u2250",
+ "esim;", "\u2242",
+ "eta;", "\u03b7",
+ "eth", "\u00f0",
+ "eth;", "\u00f0",
+ "euml", "\u00eb",
+ "euml;", "\u00eb",
+ "euro;", "\u20ac",
+ "excl;", "\u0021",
+ "exist;", "\u2203",
+ "expectation;", "\u2130",
+ "exponentiale;", "\u2147",
+ "fallingdotseq;", "\u2252",
+ "fcy;", "\u0444",
+ "female;", "\u2640",
+ "ffilig;", "\ufb03",
+ "fflig;", "\ufb00",
+ "ffllig;", "\ufb04",
+ "ffr;", "\ud835\udd23",
+ "filig;", "\ufb01",
+ "fjlig;", "\u0066\u006a",
+ "flat;", "\u266d",
+ "fllig;", "\ufb02",
+ "fltns;", "\u25b1",
+ "fnof;", "\u0192",
+ "fopf;", "\ud835\udd57",
+ "forall;", "\u2200",
+ "fork;", "\u22d4",
+ "forkv;", "\u2ad9",
+ "fpartint;", "\u2a0d",
+ "frac12", "\u00bd",
+ "frac12;", "\u00bd",
+ "frac13;", "\u2153",
+ "frac14", "\u00bc",
+ "frac14;", "\u00bc",
+ "frac15;", "\u2155",
+ "frac16;", "\u2159",
+ "frac18;", "\u215b",
+ "frac23;", "\u2154",
+ "frac25;", "\u2156",
+ "frac34", "\u00be",
+ "frac34;", "\u00be",
+ "frac35;", "\u2157",
+ "frac38;", "\u215c",
+ "frac45;", "\u2158",
+ "frac56;", "\u215a",
+ "frac58;", "\u215d",
+ "frac78;", "\u215e",
+ "frasl;", "\u2044",
+ "frown;", "\u2322",
+ "fscr;", "\ud835\udcbb",
+ "gE;", "\u2267",
+ "gEl;", "\u2a8c",
+ "gacute;", "\u01f5",
+ "gamma;", "\u03b3",
+ "gammad;", "\u03dd",
+ "gap;", "\u2a86",
+ "gbreve;", "\u011f",
+ "gcirc;", "\u011d",
+ "gcy;", "\u0433",
+ "gdot;", "\u0121",
+ "ge;", "\u2265",
+ "gel;", "\u22db",
+ "geq;", "\u2265",
+ "geqq;", "\u2267",
+ "geqslant;", "\u2a7e",
+ "ges;", "\u2a7e",
+ "gescc;", "\u2aa9",
+ "gesdot;", "\u2a80",
+ "gesdoto;", "\u2a82",
+ "gesdotol;", "\u2a84",
+ "gesl;", "\u22db\ufe00",
+ "gesles;", "\u2a94",
+ "gfr;", "\ud835\udd24",
+ "gg;", "\u226b",
+ "ggg;", "\u22d9",
+ "gimel;", "\u2137",
+ "gjcy;", "\u0453",
+ "gl;", "\u2277",
+ "glE;", "\u2a92",
+ "gla;", "\u2aa5",
+ "glj;", "\u2aa4",
+ "gnE;", "\u2269",
+ "gnap;", "\u2a8a",
+ "gnapprox;", "\u2a8a",
+ "gne;", "\u2a88",
+ "gneq;", "\u2a88",
+ "gneqq;", "\u2269",
+ "gnsim;", "\u22e7",
+ "gopf;", "\ud835\udd58",
+ "grave;", "\u0060",
+ "gscr;", "\u210a",
+ "gsim;", "\u2273",
+ "gsime;", "\u2a8e",
+ "gsiml;", "\u2a90",
+ "gt", "\u003e",
+ "gt;", "\u003e",
+ "gtcc;", "\u2aa7",
+ "gtcir;", "\u2a7a",
+ "gtdot;", "\u22d7",
+ "gtlPar;", "\u2995",
+ "gtquest;", "\u2a7c",
+ "gtrapprox;", "\u2a86",
+ "gtrarr;", "\u2978",
+ "gtrdot;", "\u22d7",
+ "gtreqless;", "\u22db",
+ "gtreqqless;", "\u2a8c",
+ "gtrless;", "\u2277",
+ "gtrsim;", "\u2273",
+ "gvertneqq;", "\u2269\ufe00",
+ "gvnE;", "\u2269\ufe00",
+ "hArr;", "\u21d4",
+ "hairsp;", "\u200a",
+ "half;", "\u00bd",
+ "hamilt;", "\u210b",
+ "hardcy;", "\u044a",
+ "harr;", "\u2194",
+ "harrcir;", "\u2948",
+ "harrw;", "\u21ad",
+ "hbar;", "\u210f",
+ "hcirc;", "\u0125",
+ "hearts;", "\u2665",
+ "heartsuit;", "\u2665",
+ "hellip;", "\u2026",
+ "hercon;", "\u22b9",
+ "hfr;", "\ud835\udd25",
+ "hksearow;", "\u2925",
+ "hkswarow;", "\u2926",
+ "hoarr;", "\u21ff",
+ "homtht;", "\u223b",
+ "hookleftarrow;", "\u21a9",
+ "hookrightarrow;", "\u21aa",
+ "hopf;", "\ud835\udd59",
+ "horbar;", "\u2015",
+ "hscr;", "\ud835\udcbd",
+ "hslash;", "\u210f",
+ "hstrok;", "\u0127",
+ "hybull;", "\u2043",
+ "hyphen;", "\u2010",
+ "iacute", "\u00ed",
+ "iacute;", "\u00ed",
+ "ic;", "\u2063",
+ "icirc", "\u00ee",
+ "icirc;", "\u00ee",
+ "icy;", "\u0438",
+ "iecy;", "\u0435",
+ "iexcl", "\u00a1",
+ "iexcl;", "\u00a1",
+ "iff;", "\u21d4",
+ "ifr;", "\ud835\udd26",
+ "igrave", "\u00ec",
+ "igrave;", "\u00ec",
+ "ii;", "\u2148",
+ "iiiint;", "\u2a0c",
+ "iiint;", "\u222d",
+ "iinfin;", "\u29dc",
+ "iiota;", "\u2129",
+ "ijlig;", "\u0133",
+ "imacr;", "\u012b",
+ "image;", "\u2111",
+ "imagline;", "\u2110",
+ "imagpart;", "\u2111",
+ "imath;", "\u0131",
+ "imof;", "\u22b7",
+ "imped;", "\u01b5",
+ "in;", "\u2208",
+ "incare;", "\u2105",
+ "infin;", "\u221e",
+ "infintie;", "\u29dd",
+ "inodot;", "\u0131",
+ "int;", "\u222b",
+ "intcal;", "\u22ba",
+ "integers;", "\u2124",
+ "intercal;", "\u22ba",
+ "intlarhk;", "\u2a17",
+ "intprod;", "\u2a3c",
+ "iocy;", "\u0451",
+ "iogon;", "\u012f",
+ "iopf;", "\ud835\udd5a",
+ "iota;", "\u03b9",
+ "iprod;", "\u2a3c",
+ "iquest", "\u00bf",
+ "iquest;", "\u00bf",
+ "iscr;", "\ud835\udcbe",
+ "isin;", "\u2208",
+ "isinE;", "\u22f9",
+ "isindot;", "\u22f5",
+ "isins;", "\u22f4",
+ "isinsv;", "\u22f3",
+ "isinv;", "\u2208",
+ "it;", "\u2062",
+ "itilde;", "\u0129",
+ "iukcy;", "\u0456",
+ "iuml", "\u00ef",
+ "iuml;", "\u00ef",
+ "jcirc;", "\u0135",
+ "jcy;", "\u0439",
+ "jfr;", "\ud835\udd27",
+ "jmath;", "\u0237",
+ "jopf;", "\ud835\udd5b",
+ "jscr;", "\ud835\udcbf",
+ "jsercy;", "\u0458",
+ "jukcy;", "\u0454",
+ "kappa;", "\u03ba",
+ "kappav;", "\u03f0",
+ "kcedil;", "\u0137",
+ "kcy;", "\u043a",
+ "kfr;", "\ud835\udd28",
+ "kgreen;", "\u0138",
+ "khcy;", "\u0445",
+ "kjcy;", "\u045c",
+ "kopf;", "\ud835\udd5c",
+ "kscr;", "\ud835\udcc0",
+ "lAarr;", "\u21da",
+ "lArr;", "\u21d0",
+ "lAtail;", "\u291b",
+ "lBarr;", "\u290e",
+ "lE;", "\u2266",
+ "lEg;", "\u2a8b",
+ "lHar;", "\u2962",
+ "lacute;", "\u013a",
+ "laemptyv;", "\u29b4",
+ "lagran;", "\u2112",
+ "lambda;", "\u03bb",
+ "lang;", "\u27e8",
+ "langd;", "\u2991",
+ "langle;", "\u27e8",
+ "lap;", "\u2a85",
+ "laquo", "\u00ab",
+ "laquo;", "\u00ab",
+ "larr;", "\u2190",
+ "larrb;", "\u21e4",
+ "larrbfs;", "\u291f",
+ "larrfs;", "\u291d",
+ "larrhk;", "\u21a9",
+ "larrlp;", "\u21ab",
+ "larrpl;", "\u2939",
+ "larrsim;", "\u2973",
+ "larrtl;", "\u21a2",
+ "lat;", "\u2aab",
+ "latail;", "\u2919",
+ "late;", "\u2aad",
+ "lates;", "\u2aad\ufe00",
+ "lbarr;", "\u290c",
+ "lbbrk;", "\u2772",
+ "lbrace;", "\u007b",
+ "lbrack;", "\u005b",
+ "lbrke;", "\u298b",
+ "lbrksld;", "\u298f",
+ "lbrkslu;", "\u298d",
+ "lcaron;", "\u013e",
+ "lcedil;", "\u013c",
+ "lceil;", "\u2308",
+ "lcub;", "\u007b",
+ "lcy;", "\u043b",
+ "ldca;", "\u2936",
+ "ldquo;", "\u201c",
+ "ldquor;", "\u201e",
+ "ldrdhar;", "\u2967",
+ "ldrushar;", "\u294b",
+ "ldsh;", "\u21b2",
+ "le;", "\u2264",
+ "leftarrow;", "\u2190",
+ "leftarrowtail;", "\u21a2",
+ "leftharpoondown;", "\u21bd",
+ "leftharpoonup;", "\u21bc",
+ "leftleftarrows;", "\u21c7",
+ "leftrightarrow;", "\u2194",
+ "leftrightarrows;", "\u21c6",
+ "leftrightharpoons;", "\u21cb",
+ "leftrightsquigarrow;", "\u21ad",
+ "leftthreetimes;", "\u22cb",
+ "leg;", "\u22da",
+ "leq;", "\u2264",
+ "leqq;", "\u2266",
+ "leqslant;", "\u2a7d",
+ "les;", "\u2a7d",
+ "lescc;", "\u2aa8",
+ "lesdot;", "\u2a7f",
+ "lesdoto;", "\u2a81",
+ "lesdotor;", "\u2a83",
+ "lesg;", "\u22da\ufe00",
+ "lesges;", "\u2a93",
+ "lessapprox;", "\u2a85",
+ "lessdot;", "\u22d6",
+ "lesseqgtr;", "\u22da",
+ "lesseqqgtr;", "\u2a8b",
+ "lessgtr;", "\u2276",
+ "lesssim;", "\u2272",
+ "lfisht;", "\u297c",
+ "lfloor;", "\u230a",
+ "lfr;", "\ud835\udd29",
+ "lg;", "\u2276",
+ "lgE;", "\u2a91",
+ "lhard;", "\u21bd",
+ "lharu;", "\u21bc",
+ "lharul;", "\u296a",
+ "lhblk;", "\u2584",
+ "ljcy;", "\u0459",
+ "ll;", "\u226a",
+ "llarr;", "\u21c7",
+ "llcorner;", "\u231e",
+ "llhard;", "\u296b",
+ "lltri;", "\u25fa",
+ "lmidot;", "\u0140",
+ "lmoust;", "\u23b0",
+ "lmoustache;", "\u23b0",
+ "lnE;", "\u2268",
+ "lnap;", "\u2a89",
+ "lnapprox;", "\u2a89",
+ "lne;", "\u2a87",
+ "lneq;", "\u2a87",
+ "lneqq;", "\u2268",
+ "lnsim;", "\u22e6",
+ "loang;", "\u27ec",
+ "loarr;", "\u21fd",
+ "lobrk;", "\u27e6",
+ "longleftarrow;", "\u27f5",
+ "longleftrightarrow;", "\u27f7",
+ "longmapsto;", "\u27fc",
+ "longrightarrow;", "\u27f6",
+ "looparrowleft;", "\u21ab",
+ "looparrowright;", "\u21ac",
+ "lopar;", "\u2985",
+ "lopf;", "\ud835\udd5d",
+ "loplus;", "\u2a2d",
+ "lotimes;", "\u2a34",
+ "lowast;", "\u2217",
+ "lowbar;", "\u005f",
+ "loz;", "\u25ca",
+ "lozenge;", "\u25ca",
+ "lozf;", "\u29eb",
+ "lpar;", "\u0028",
+ "lparlt;", "\u2993",
+ "lrarr;", "\u21c6",
+ "lrcorner;", "\u231f",
+ "lrhar;", "\u21cb",
+ "lrhard;", "\u296d",
+ "lrm;", "\u200e",
+ "lrtri;", "\u22bf",
+ "lsaquo;", "\u2039",
+ "lscr;", "\ud835\udcc1",
+ "lsh;", "\u21b0",
+ "lsim;", "\u2272",
+ "lsime;", "\u2a8d",
+ "lsimg;", "\u2a8f",
+ "lsqb;", "\u005b",
+ "lsquo;", "\u2018",
+ "lsquor;", "\u201a",
+ "lstrok;", "\u0142",
+ "lt", "\u003c",
+ "lt;", "\u003c",
+ "ltcc;", "\u2aa6",
+ "ltcir;", "\u2a79",
+ "ltdot;", "\u22d6",
+ "lthree;", "\u22cb",
+ "ltimes;", "\u22c9",
+ "ltlarr;", "\u2976",
+ "ltquest;", "\u2a7b",
+ "ltrPar;", "\u2996",
+ "ltri;", "\u25c3",
+ "ltrie;", "\u22b4",
+ "ltrif;", "\u25c2",
+ "lurdshar;", "\u294a",
+ "luruhar;", "\u2966",
+ "lvertneqq;", "\u2268\ufe00",
+ "lvnE;", "\u2268\ufe00",
+ "mDDot;", "\u223a",
+ "macr", "\u00af",
+ "macr;", "\u00af",
+ "male;", "\u2642",
+ "malt;", "\u2720",
+ "maltese;", "\u2720",
+ "map;", "\u21a6",
+ "mapsto;", "\u21a6",
+ "mapstodown;", "\u21a7",
+ "mapstoleft;", "\u21a4",
+ "mapstoup;", "\u21a5",
+ "marker;", "\u25ae",
+ "mcomma;", "\u2a29",
+ "mcy;", "\u043c",
+ "mdash;", "\u2014",
+ "measuredangle;", "\u2221",
+ "mfr;", "\ud835\udd2a",
+ "mho;", "\u2127",
+ "micro", "\u00b5",
+ "micro;", "\u00b5",
+ "mid;", "\u2223",
+ "midast;", "\u002a",
+ "midcir;", "\u2af0",
+ "middot", "\u00b7",
+ "middot;", "\u00b7",
+ "minus;", "\u2212",
+ "minusb;", "\u229f",
+ "minusd;", "\u2238",
+ "minusdu;", "\u2a2a",
+ "mlcp;", "\u2adb",
+ "mldr;", "\u2026",
+ "mnplus;", "\u2213",
+ "models;", "\u22a7",
+ "mopf;", "\ud835\udd5e",
+ "mp;", "\u2213",
+ "mscr;", "\ud835\udcc2",
+ "mstpos;", "\u223e",
+ "mu;", "\u03bc",
+ "multimap;", "\u22b8",
+ "mumap;", "\u22b8",
+ "nGg;", "\u22d9\u0338",
+ "nGt;", "\u226b\u20d2",
+ "nGtv;", "\u226b\u0338",
+ "nLeftarrow;", "\u21cd",
+ "nLeftrightarrow;", "\u21ce",
+ "nLl;", "\u22d8\u0338",
+ "nLt;", "\u226a\u20d2",
+ "nLtv;", "\u226a\u0338",
+ "nRightarrow;", "\u21cf",
+ "nVDash;", "\u22af",
+ "nVdash;", "\u22ae",
+ "nabla;", "\u2207",
+ "nacute;", "\u0144",
+ "nang;", "\u2220\u20d2",
+ "nap;", "\u2249",
+ "napE;", "\u2a70\u0338",
+ "napid;", "\u224b\u0338",
+ "napos;", "\u0149",
+ "napprox;", "\u2249",
+ "natur;", "\u266e",
+ "natural;", "\u266e",
+ "naturals;", "\u2115",
+ "nbsp", "\u00a0",
+ "nbsp;", "\u00a0",
+ "nbump;", "\u224e\u0338",
+ "nbumpe;", "\u224f\u0338",
+ "ncap;", "\u2a43",
+ "ncaron;", "\u0148",
+ "ncedil;", "\u0146",
+ "ncong;", "\u2247",
+ "ncongdot;", "\u2a6d\u0338",
+ "ncup;", "\u2a42",
+ "ncy;", "\u043d",
+ "ndash;", "\u2013",
+ "ne;", "\u2260",
+ "neArr;", "\u21d7",
+ "nearhk;", "\u2924",
+ "nearr;", "\u2197",
+ "nearrow;", "\u2197",
+ "nedot;", "\u2250\u0338",
+ "nequiv;", "\u2262",
+ "nesear;", "\u2928",
+ "nesim;", "\u2242\u0338",
+ "nexist;", "\u2204",
+ "nexists;", "\u2204",
+ "nfr;", "\ud835\udd2b",
+ "ngE;", "\u2267\u0338",
+ "nge;", "\u2271",
+ "ngeq;", "\u2271",
+ "ngeqq;", "\u2267\u0338",
+ "ngeqslant;", "\u2a7e\u0338",
+ "nges;", "\u2a7e\u0338",
+ "ngsim;", "\u2275",
+ "ngt;", "\u226f",
+ "ngtr;", "\u226f",
+ "nhArr;", "\u21ce",
+ "nharr;", "\u21ae",
+ "nhpar;", "\u2af2",
+ "ni;", "\u220b",
+ "nis;", "\u22fc",
+ "nisd;", "\u22fa",
+ "niv;", "\u220b",
+ "njcy;", "\u045a",
+ "nlArr;", "\u21cd",
+ "nlE;", "\u2266\u0338",
+ "nlarr;", "\u219a",
+ "nldr;", "\u2025",
+ "nle;", "\u2270",
+ "nleftarrow;", "\u219a",
+ "nleftrightarrow;", "\u21ae",
+ "nleq;", "\u2270",
+ "nleqq;", "\u2266\u0338",
+ "nleqslant;", "\u2a7d\u0338",
+ "nles;", "\u2a7d\u0338",
+ "nless;", "\u226e",
+ "nlsim;", "\u2274",
+ "nlt;", "\u226e",
+ "nltri;", "\u22ea",
+ "nltrie;", "\u22ec",
+ "nmid;", "\u2224",
+ "nopf;", "\ud835\udd5f",
+ "not", "\u00ac",
+ "not;", "\u00ac",
+ "notin;", "\u2209",
+ "notinE;", "\u22f9\u0338",
+ "notindot;", "\u22f5\u0338",
+ "notinva;", "\u2209",
+ "notinvb;", "\u22f7",
+ "notinvc;", "\u22f6",
+ "notni;", "\u220c",
+ "notniva;", "\u220c",
+ "notnivb;", "\u22fe",
+ "notnivc;", "\u22fd",
+ "npar;", "\u2226",
+ "nparallel;", "\u2226",
+ "nparsl;", "\u2afd\u20e5",
+ "npart;", "\u2202\u0338",
+ "npolint;", "\u2a14",
+ "npr;", "\u2280",
+ "nprcue;", "\u22e0",
+ "npre;", "\u2aaf\u0338",
+ "nprec;", "\u2280",
+ "npreceq;", "\u2aaf\u0338",
+ "nrArr;", "\u21cf",
+ "nrarr;", "\u219b",
+ "nrarrc;", "\u2933\u0338",
+ "nrarrw;", "\u219d\u0338",
+ "nrightarrow;", "\u219b",
+ "nrtri;", "\u22eb",
+ "nrtrie;", "\u22ed",
+ "nsc;", "\u2281",
+ "nsccue;", "\u22e1",
+ "nsce;", "\u2ab0\u0338",
+ "nscr;", "\ud835\udcc3",
+ "nshortmid;", "\u2224",
+ "nshortparallel;", "\u2226",
+ "nsim;", "\u2241",
+ "nsime;", "\u2244",
+ "nsimeq;", "\u2244",
+ "nsmid;", "\u2224",
+ "nspar;", "\u2226",
+ "nsqsube;", "\u22e2",
+ "nsqsupe;", "\u22e3",
+ "nsub;", "\u2284",
+ "nsubE;", "\u2ac5\u0338",
+ "nsube;", "\u2288",
+ "nsubset;", "\u2282\u20d2",
+ "nsubseteq;", "\u2288",
+ "nsubseteqq;", "\u2ac5\u0338",
+ "nsucc;", "\u2281",
+ "nsucceq;", "\u2ab0\u0338",
+ "nsup;", "\u2285",
+ "nsupE;", "\u2ac6\u0338",
+ "nsupe;", "\u2289",
+ "nsupset;", "\u2283\u20d2",
+ "nsupseteq;", "\u2289",
+ "nsupseteqq;", "\u2ac6\u0338",
+ "ntgl;", "\u2279",
+ "ntilde", "\u00f1",
+ "ntilde;", "\u00f1",
+ "ntlg;", "\u2278",
+ "ntriangleleft;", "\u22ea",
+ "ntrianglelefteq;", "\u22ec",
+ "ntriangleright;", "\u22eb",
+ "ntrianglerighteq;", "\u22ed",
+ "nu;", "\u03bd",
+ "num;", "\u0023",
+ "numero;", "\u2116",
+ "numsp;", "\u2007",
+ "nvDash;", "\u22ad",
+ "nvHarr;", "\u2904",
+ "nvap;", "\u224d\u20d2",
+ "nvdash;", "\u22ac",
+ "nvge;", "\u2265\u20d2",
+ "nvgt;", "\u003e\u20d2",
+ "nvinfin;", "\u29de",
+ "nvlArr;", "\u2902",
+ "nvle;", "\u2264\u20d2",
+ "nvlt;", "\u003c\u20d2",
+ "nvltrie;", "\u22b4\u20d2",
+ "nvrArr;", "\u2903",
+ "nvrtrie;", "\u22b5\u20d2",
+ "nvsim;", "\u223c\u20d2",
+ "nwArr;", "\u21d6",
+ "nwarhk;", "\u2923",
+ "nwarr;", "\u2196",
+ "nwarrow;", "\u2196",
+ "nwnear;", "\u2927",
+ "oS;", "\u24c8",
+ "oacute", "\u00f3",
+ "oacute;", "\u00f3",
+ "oast;", "\u229b",
+ "ocir;", "\u229a",
+ "ocirc", "\u00f4",
+ "ocirc;", "\u00f4",
+ "ocy;", "\u043e",
+ "odash;", "\u229d",
+ "odblac;", "\u0151",
+ "odiv;", "\u2a38",
+ "odot;", "\u2299",
+ "odsold;", "\u29bc",
+ "oelig;", "\u0153",
+ "ofcir;", "\u29bf",
+ "ofr;", "\ud835\udd2c",
+ "ogon;", "\u02db",
+ "ograve", "\u00f2",
+ "ograve;", "\u00f2",
+ "ogt;", "\u29c1",
+ "ohbar;", "\u29b5",
+ "ohm;", "\u03a9",
+ "oint;", "\u222e",
+ "olarr;", "\u21ba",
+ "olcir;", "\u29be",
+ "olcross;", "\u29bb",
+ "oline;", "\u203e",
+ "olt;", "\u29c0",
+ "omacr;", "\u014d",
+ "omega;", "\u03c9",
+ "omicron;", "\u03bf",
+ "omid;", "\u29b6",
+ "ominus;", "\u2296",
+ "oopf;", "\ud835\udd60",
+ "opar;", "\u29b7",
+ "operp;", "\u29b9",
+ "oplus;", "\u2295",
+ "or;", "\u2228",
+ "orarr;", "\u21bb",
+ "ord;", "\u2a5d",
+ "order;", "\u2134",
+ "orderof;", "\u2134",
+ "ordf", "\u00aa",
+ "ordf;", "\u00aa",
+ "ordm", "\u00ba",
+ "ordm;", "\u00ba",
+ "origof;", "\u22b6",
+ "oror;", "\u2a56",
+ "orslope;", "\u2a57",
+ "orv;", "\u2a5b",
+ "oscr;", "\u2134",
+ "oslash", "\u00f8",
+ "oslash;", "\u00f8",
+ "osol;", "\u2298",
+ "otilde", "\u00f5",
+ "otilde;", "\u00f5",
+ "otimes;", "\u2297",
+ "otimesas;", "\u2a36",
+ "ouml", "\u00f6",
+ "ouml;", "\u00f6",
+ "ovbar;", "\u233d",
+ "par;", "\u2225",
+ "para", "\u00b6",
+ "para;", "\u00b6",
+ "parallel;", "\u2225",
+ "parsim;", "\u2af3",
+ "parsl;", "\u2afd",
+ "part;", "\u2202",
+ "pcy;", "\u043f",
+ "percnt;", "\u0025",
+ "period;", "\u002e",
+ "permil;", "\u2030",
+ "perp;", "\u22a5",
+ "pertenk;", "\u2031",
+ "pfr;", "\ud835\udd2d",
+ "phi;", "\u03c6",
+ "phiv;", "\u03d5",
+ "phmmat;", "\u2133",
+ "phone;", "\u260e",
+ "pi;", "\u03c0",
+ "pitchfork;", "\u22d4",
+ "piv;", "\u03d6",
+ "planck;", "\u210f",
+ "planckh;", "\u210e",
+ "plankv;", "\u210f",
+ "plus;", "\u002b",
+ "plusacir;", "\u2a23",
+ "plusb;", "\u229e",
+ "pluscir;", "\u2a22",
+ "plusdo;", "\u2214",
+ "plusdu;", "\u2a25",
+ "pluse;", "\u2a72",
+ "plusmn", "\u00b1",
+ "plusmn;", "\u00b1",
+ "plussim;", "\u2a26",
+ "plustwo;", "\u2a27",
+ "pm;", "\u00b1",
+ "pointint;", "\u2a15",
+ "popf;", "\ud835\udd61",
+ "pound", "\u00a3",
+ "pound;", "\u00a3",
+ "pr;", "\u227a",
+ "prE;", "\u2ab3",
+ "prap;", "\u2ab7",
+ "prcue;", "\u227c",
+ "pre;", "\u2aaf",
+ "prec;", "\u227a",
+ "precapprox;", "\u2ab7",
+ "preccurlyeq;", "\u227c",
+ "preceq;", "\u2aaf",
+ "precnapprox;", "\u2ab9",
+ "precneqq;", "\u2ab5",
+ "precnsim;", "\u22e8",
+ "precsim;", "\u227e",
+ "prime;", "\u2032",
+ "primes;", "\u2119",
+ "prnE;", "\u2ab5",
+ "prnap;", "\u2ab9",
+ "prnsim;", "\u22e8",
+ "prod;", "\u220f",
+ "profalar;", "\u232e",
+ "profline;", "\u2312",
+ "profsurf;", "\u2313",
+ "prop;", "\u221d",
+ "propto;", "\u221d",
+ "prsim;", "\u227e",
+ "prurel;", "\u22b0",
+ "pscr;", "\ud835\udcc5",
+ "psi;", "\u03c8",
+ "puncsp;", "\u2008",
+ "qfr;", "\ud835\udd2e",
+ "qint;", "\u2a0c",
+ "qopf;", "\ud835\udd62",
+ "qprime;", "\u2057",
+ "qscr;", "\ud835\udcc6",
+ "quaternions;", "\u210d",
+ "quatint;", "\u2a16",
+ "quest;", "\u003f",
+ "questeq;", "\u225f",
+ "quot", "\"",
+ "quot;", "\"",
+ "rAarr;", "\u21db",
+ "rArr;", "\u21d2",
+ "rAtail;", "\u291c",
+ "rBarr;", "\u290f",
+ "rHar;", "\u2964",
+ "race;", "\u223d\u0331",
+ "racute;", "\u0155",
+ "radic;", "\u221a",
+ "raemptyv;", "\u29b3",
+ "rang;", "\u27e9",
+ "rangd;", "\u2992",
+ "range;", "\u29a5",
+ "rangle;", "\u27e9",
+ "raquo", "\u00bb",
+ "raquo;", "\u00bb",
+ "rarr;", "\u2192",
+ "rarrap;", "\u2975",
+ "rarrb;", "\u21e5",
+ "rarrbfs;", "\u2920",
+ "rarrc;", "\u2933",
+ "rarrfs;", "\u291e",
+ "rarrhk;", "\u21aa",
+ "rarrlp;", "\u21ac",
+ "rarrpl;", "\u2945",
+ "rarrsim;", "\u2974",
+ "rarrtl;", "\u21a3",
+ "rarrw;", "\u219d",
+ "ratail;", "\u291a",
+ "ratio;", "\u2236",
+ "rationals;", "\u211a",
+ "rbarr;", "\u290d",
+ "rbbrk;", "\u2773",
+ "rbrace;", "\u007d",
+ "rbrack;", "\u005d",
+ "rbrke;", "\u298c",
+ "rbrksld;", "\u298e",
+ "rbrkslu;", "\u2990",
+ "rcaron;", "\u0159",
+ "rcedil;", "\u0157",
+ "rceil;", "\u2309",
+ "rcub;", "\u007d",
+ "rcy;", "\u0440",
+ "rdca;", "\u2937",
+ "rdldhar;", "\u2969",
+ "rdquo;", "\u201d",
+ "rdquor;", "\u201d",
+ "rdsh;", "\u21b3",
+ "real;", "\u211c",
+ "realine;", "\u211b",
+ "realpart;", "\u211c",
+ "reals;", "\u211d",
+ "rect;", "\u25ad",
+ "reg", "\u00ae",
+ "reg;", "\u00ae",
+ "rfisht;", "\u297d",
+ "rfloor;", "\u230b",
+ "rfr;", "\ud835\udd2f",
+ "rhard;", "\u21c1",
+ "rharu;", "\u21c0",
+ "rharul;", "\u296c",
+ "rho;", "\u03c1",
+ "rhov;", "\u03f1",
+ "rightarrow;", "\u2192",
+ "rightarrowtail;", "\u21a3",
+ "rightharpoondown;", "\u21c1",
+ "rightharpoonup;", "\u21c0",
+ "rightleftarrows;", "\u21c4",
+ "rightleftharpoons;", "\u21cc",
+ "rightrightarrows;", "\u21c9",
+ "rightsquigarrow;", "\u219d",
+ "rightthreetimes;", "\u22cc",
+ "ring;", "\u02da",
+ "risingdotseq;", "\u2253",
+ "rlarr;", "\u21c4",
+ "rlhar;", "\u21cc",
+ "rlm;", "\u200f",
+ "rmoust;", "\u23b1",
+ "rmoustache;", "\u23b1",
+ "rnmid;", "\u2aee",
+ "roang;", "\u27ed",
+ "roarr;", "\u21fe",
+ "robrk;", "\u27e7",
+ "ropar;", "\u2986",
+ "ropf;", "\ud835\udd63",
+ "roplus;", "\u2a2e",
+ "rotimes;", "\u2a35",
+ "rpar;", "\u0029",
+ "rpargt;", "\u2994",
+ "rppolint;", "\u2a12",
+ "rrarr;", "\u21c9",
+ "rsaquo;", "\u203a",
+ "rscr;", "\ud835\udcc7",
+ "rsh;", "\u21b1",
+ "rsqb;", "\u005d",
+ "rsquo;", "\u2019",
+ "rsquor;", "\u2019",
+ "rthree;", "\u22cc",
+ "rtimes;", "\u22ca",
+ "rtri;", "\u25b9",
+ "rtrie;", "\u22b5",
+ "rtrif;", "\u25b8",
+ "rtriltri;", "\u29ce",
+ "ruluhar;", "\u2968",
+ "rx;", "\u211e",
+ "sacute;", "\u015b",
+ "sbquo;", "\u201a",
+ "sc;", "\u227b",
+ "scE;", "\u2ab4",
+ "scap;", "\u2ab8",
+ "scaron;", "\u0161",
+ "sccue;", "\u227d",
+ "sce;", "\u2ab0",
+ "scedil;", "\u015f",
+ "scirc;", "\u015d",
+ "scnE;", "\u2ab6",
+ "scnap;", "\u2aba",
+ "scnsim;", "\u22e9",
+ "scpolint;", "\u2a13",
+ "scsim;", "\u227f",
+ "scy;", "\u0441",
+ "sdot;", "\u22c5",
+ "sdotb;", "\u22a1",
+ "sdote;", "\u2a66",
+ "seArr;", "\u21d8",
+ "searhk;", "\u2925",
+ "searr;", "\u2198",
+ "searrow;", "\u2198",
+ "sect", "\u00a7",
+ "sect;", "\u00a7",
+ "semi;", "\u003b",
+ "seswar;", "\u2929",
+ "setminus;", "\u2216",
+ "setmn;", "\u2216",
+ "sext;", "\u2736",
+ "sfr;", "\ud835\udd30",
+ "sfrown;", "\u2322",
+ "sharp;", "\u266f",
+ "shchcy;", "\u0449",
+ "shcy;", "\u0448",
+ "shortmid;", "\u2223",
+ "shortparallel;", "\u2225",
+ "shy", "\u00ad",
+ "shy;", "\u00ad",
+ "sigma;", "\u03c3",
+ "sigmaf;", "\u03c2",
+ "sigmav;", "\u03c2",
+ "sim;", "\u223c",
+ "simdot;", "\u2a6a",
+ "sime;", "\u2243",
+ "simeq;", "\u2243",
+ "simg;", "\u2a9e",
+ "simgE;", "\u2aa0",
+ "siml;", "\u2a9d",
+ "simlE;", "\u2a9f",
+ "simne;", "\u2246",
+ "simplus;", "\u2a24",
+ "simrarr;", "\u2972",
+ "slarr;", "\u2190",
+ "smallsetminus;", "\u2216",
+ "smashp;", "\u2a33",
+ "smeparsl;", "\u29e4",
+ "smid;", "\u2223",
+ "smile;", "\u2323",
+ "smt;", "\u2aaa",
+ "smte;", "\u2aac",
+ "smtes;", "\u2aac\ufe00",
+ "softcy;", "\u044c",
+ "sol;", "\u002f",
+ "solb;", "\u29c4",
+ "solbar;", "\u233f",
+ "sopf;", "\ud835\udd64",
+ "spades;", "\u2660",
+ "spadesuit;", "\u2660",
+ "spar;", "\u2225",
+ "sqcap;", "\u2293",
+ "sqcaps;", "\u2293\ufe00",
+ "sqcup;", "\u2294",
+ "sqcups;", "\u2294\ufe00",
+ "sqsub;", "\u228f",
+ "sqsube;", "\u2291",
+ "sqsubset;", "\u228f",
+ "sqsubseteq;", "\u2291",
+ "sqsup;", "\u2290",
+ "sqsupe;", "\u2292",
+ "sqsupset;", "\u2290",
+ "sqsupseteq;", "\u2292",
+ "squ;", "\u25a1",
+ "square;", "\u25a1",
+ "squarf;", "\u25aa",
+ "squf;", "\u25aa",
+ "srarr;", "\u2192",
+ "sscr;", "\ud835\udcc8",
+ "ssetmn;", "\u2216",
+ "ssmile;", "\u2323",
+ "sstarf;", "\u22c6",
+ "star;", "\u2606",
+ "starf;", "\u2605",
+ "straightepsilon;", "\u03f5",
+ "straightphi;", "\u03d5",
+ "strns;", "\u00af",
+ "sub;", "\u2282",
+ "subE;", "\u2ac5",
+ "subdot;", "\u2abd",
+ "sube;", "\u2286",
+ "subedot;", "\u2ac3",
+ "submult;", "\u2ac1",
+ "subnE;", "\u2acb",
+ "subne;", "\u228a",
+ "subplus;", "\u2abf",
+ "subrarr;", "\u2979",
+ "subset;", "\u2282",
+ "subseteq;", "\u2286",
+ "subseteqq;", "\u2ac5",
+ "subsetneq;", "\u228a",
+ "subsetneqq;", "\u2acb",
+ "subsim;", "\u2ac7",
+ "subsub;", "\u2ad5",
+ "subsup;", "\u2ad3",
+ "succ;", "\u227b",
+ "succapprox;", "\u2ab8",
+ "succcurlyeq;", "\u227d",
+ "succeq;", "\u2ab0",
+ "succnapprox;", "\u2aba",
+ "succneqq;", "\u2ab6",
+ "succnsim;", "\u22e9",
+ "succsim;", "\u227f",
+ "sum;", "\u2211",
+ "sung;", "\u266a",
+ "sup1", "\u00b9",
+ "sup1;", "\u00b9",
+ "sup2", "\u00b2",
+ "sup2;", "\u00b2",
+ "sup3", "\u00b3",
+ "sup3;", "\u00b3",
+ "sup;", "\u2283",
+ "supE;", "\u2ac6",
+ "supdot;", "\u2abe",
+ "supdsub;", "\u2ad8",
+ "supe;", "\u2287",
+ "supedot;", "\u2ac4",
+ "suphsol;", "\u27c9",
+ "suphsub;", "\u2ad7",
+ "suplarr;", "\u297b",
+ "supmult;", "\u2ac2",
+ "supnE;", "\u2acc",
+ "supne;", "\u228b",
+ "supplus;", "\u2ac0",
+ "supset;", "\u2283",
+ "supseteq;", "\u2287",
+ "supseteqq;", "\u2ac6",
+ "supsetneq;", "\u228b",
+ "supsetneqq;", "\u2acc",
+ "supsim;", "\u2ac8",
+ "supsub;", "\u2ad4",
+ "supsup;", "\u2ad6",
+ "swArr;", "\u21d9",
+ "swarhk;", "\u2926",
+ "swarr;", "\u2199",
+ "swarrow;", "\u2199",
+ "swnwar;", "\u292a",
+ "szlig", "\u00df",
+ "szlig;", "\u00df",
+ "target;", "\u2316",
+ "tau;", "\u03c4",
+ "tbrk;", "\u23b4",
+ "tcaron;", "\u0165",
+ "tcedil;", "\u0163",
+ "tcy;", "\u0442",
+ "tdot;", "\u20db",
+ "telrec;", "\u2315",
+ "tfr;", "\ud835\udd31",
+ "there4;", "\u2234",
+ "therefore;", "\u2234",
+ "theta;", "\u03b8",
+ "thetasym;", "\u03d1",
+ "thetav;", "\u03d1",
+ "thickapprox;", "\u2248",
+ "thicksim;", "\u223c",
+ "thinsp;", "\u2009",
+ "thkap;", "\u2248",
+ "thksim;", "\u223c",
+ "thorn", "\u00fe",
+ "thorn;", "\u00fe",
+ "tilde;", "\u02dc",
+ "times", "\u00d7",
+ "times;", "\u00d7",
+ "timesb;", "\u22a0",
+ "timesbar;", "\u2a31",
+ "timesd;", "\u2a30",
+ "tint;", "\u222d",
+ "toea;", "\u2928",
+ "top;", "\u22a4",
+ "topbot;", "\u2336",
+ "topcir;", "\u2af1",
+ "topf;", "\ud835\udd65",
+ "topfork;", "\u2ada",
+ "tosa;", "\u2929",
+ "tprime;", "\u2034",
+ "trade;", "\u2122",
+ "triangle;", "\u25b5",
+ "triangledown;", "\u25bf",
+ "triangleleft;", "\u25c3",
+ "trianglelefteq;", "\u22b4",
+ "triangleq;", "\u225c",
+ "triangleright;", "\u25b9",
+ "trianglerighteq;", "\u22b5",
+ "tridot;", "\u25ec",
+ "trie;", "\u225c",
+ "triminus;", "\u2a3a",
+ "triplus;", "\u2a39",
+ "trisb;", "\u29cd",
+ "tritime;", "\u2a3b",
+ "trpezium;", "\u23e2",
+ "tscr;", "\ud835\udcc9",
+ "tscy;", "\u0446",
+ "tshcy;", "\u045b",
+ "tstrok;", "\u0167",
+ "twixt;", "\u226c",
+ "twoheadleftarrow;", "\u219e",
+ "twoheadrightarrow;", "\u21a0",
+ "uArr;", "\u21d1",
+ "uHar;", "\u2963",
+ "uacute", "\u00fa",
+ "uacute;", "\u00fa",
+ "uarr;", "\u2191",
+ "ubrcy;", "\u045e",
+ "ubreve;", "\u016d",
+ "ucirc", "\u00fb",
+ "ucirc;", "\u00fb",
+ "ucy;", "\u0443",
+ "udarr;", "\u21c5",
+ "udblac;", "\u0171",
+ "udhar;", "\u296e",
+ "ufisht;", "\u297e",
+ "ufr;", "\ud835\udd32",
+ "ugrave", "\u00f9",
+ "ugrave;", "\u00f9",
+ "uharl;", "\u21bf",
+ "uharr;", "\u21be",
+ "uhblk;", "\u2580",
+ "ulcorn;", "\u231c",
+ "ulcorner;", "\u231c",
+ "ulcrop;", "\u230f",
+ "ultri;", "\u25f8",
+ "umacr;", "\u016b",
+ "uml", "\u00a8",
+ "uml;", "\u00a8",
+ "uogon;", "\u0173",
+ "uopf;", "\ud835\udd66",
+ "uparrow;", "\u2191",
+ "updownarrow;", "\u2195",
+ "upharpoonleft;", "\u21bf",
+ "upharpoonright;", "\u21be",
+ "uplus;", "\u228e",
+ "upsi;", "\u03c5",
+ "upsih;", "\u03d2",
+ "upsilon;", "\u03c5",
+ "upuparrows;", "\u21c8",
+ "urcorn;", "\u231d",
+ "urcorner;", "\u231d",
+ "urcrop;", "\u230e",
+ "uring;", "\u016f",
+ "urtri;", "\u25f9",
+ "uscr;", "\ud835\udcca",
+ "utdot;", "\u22f0",
+ "utilde;", "\u0169",
+ "utri;", "\u25b5",
+ "utrif;", "\u25b4",
+ "uuarr;", "\u21c8",
+ "uuml", "\u00fc",
+ "uuml;", "\u00fc",
+ "uwangle;", "\u29a7",
+ "vArr;", "\u21d5",
+ "vBar;", "\u2ae8",
+ "vBarv;", "\u2ae9",
+ "vDash;", "\u22a8",
+ "vangrt;", "\u299c",
+ "varepsilon;", "\u03f5",
+ "varkappa;", "\u03f0",
+ "varnothing;", "\u2205",
+ "varphi;", "\u03d5",
+ "varpi;", "\u03d6",
+ "varpropto;", "\u221d",
+ "varr;", "\u2195",
+ "varrho;", "\u03f1",
+ "varsigma;", "\u03c2",
+ "varsubsetneq;", "\u228a\ufe00",
+ "varsubsetneqq;", "\u2acb\ufe00",
+ "varsupsetneq;", "\u228b\ufe00",
+ "varsupsetneqq;", "\u2acc\ufe00",
+ "vartheta;", "\u03d1",
+ "vartriangleleft;", "\u22b2",
+ "vartriangleright;", "\u22b3",
+ "vcy;", "\u0432",
+ "vdash;", "\u22a2",
+ "vee;", "\u2228",
+ "veebar;", "\u22bb",
+ "veeeq;", "\u225a",
+ "vellip;", "\u22ee",
+ "verbar;", "\u007c",
+ "vert;", "\u007c",
+ "vfr;", "\ud835\udd33",
+ "vltri;", "\u22b2",
+ "vnsub;", "\u2282\u20d2",
+ "vnsup;", "\u2283\u20d2",
+ "vopf;", "\ud835\udd67",
+ "vprop;", "\u221d",
+ "vrtri;", "\u22b3",
+ "vscr;", "\ud835\udccb",
+ "vsubnE;", "\u2acb\ufe00",
+ "vsubne;", "\u228a\ufe00",
+ "vsupnE;", "\u2acc\ufe00",
+ "vsupne;", "\u228b\ufe00",
+ "vzigzag;", "\u299a",
+ "wcirc;", "\u0175",
+ "wedbar;", "\u2a5f",
+ "wedge;", "\u2227",
+ "wedgeq;", "\u2259",
+ "weierp;", "\u2118",
+ "wfr;", "\ud835\udd34",
+ "wopf;", "\ud835\udd68",
+ "wp;", "\u2118",
+ "wr;", "\u2240",
+ "wreath;", "\u2240",
+ "wscr;", "\ud835\udccc",
+ "xcap;", "\u22c2",
+ "xcirc;", "\u25ef",
+ "xcup;", "\u22c3",
+ "xdtri;", "\u25bd",
+ "xfr;", "\ud835\udd35",
+ "xhArr;", "\u27fa",
+ "xharr;", "\u27f7",
+ "xi;", "\u03be",
+ "xlArr;", "\u27f8",
+ "xlarr;", "\u27f5",
+ "xmap;", "\u27fc",
+ "xnis;", "\u22fb",
+ "xodot;", "\u2a00",
+ "xopf;", "\ud835\udd69",
+ "xoplus;", "\u2a01",
+ "xotime;", "\u2a02",
+ "xrArr;", "\u27f9",
+ "xrarr;", "\u27f6",
+ "xscr;", "\ud835\udccd",
+ "xsqcup;", "\u2a06",
+ "xuplus;", "\u2a04",
+ "xutri;", "\u25b3",
+ "xvee;", "\u22c1",
+ "xwedge;", "\u22c0",
+ "yacute", "\u00fd",
+ "yacute;", "\u00fd",
+ "yacy;", "\u044f",
+ "ycirc;", "\u0177",
+ "ycy;", "\u044b",
+ "yen", "\u00a5",
+ "yen;", "\u00a5",
+ "yfr;", "\ud835\udd36",
+ "yicy;", "\u0457",
+ "yopf;", "\ud835\udd6a",
+ "yscr;", "\ud835\udcce",
+ "yucy;", "\u044e",
+ "yuml", "\u00ff",
+ "yuml;", "\u00ff",
+ "zacute;", "\u017a",
+ "zcaron;", "\u017e",
+ "zcy;", "\u0437",
+ "zdot;", "\u017c",
+ "zeetrf;", "\u2128",
+ "zeta;", "\u03b6",
+ "zfr;", "\ud835\udd37",
+ "zhcy;", "\u0436",
+ "zigrarr;", "\u21dd",
+ "zopf;", "\ud835\udd6b",
+ "zscr;", "\ud835\udccf",
+ "zwj;", "\u200d",
+ "zwnj;", "\u200c",
+ };
- builder.put("AElig", "\u00c6");
- builder.put("AMP", "\u0026");
- builder.put("Aacute", "\u00c1");
- builder.put("Abreve", "\u0102");
- builder.put("Acirc", "\u00c2");
- builder.put("Acy", "\u0410");
- builder.put("Afr", "\ud835\udd04");
- builder.put("Agrave", "\u00c0");
- builder.put("Alpha", "\u0391");
- builder.put("Amacr", "\u0100");
- builder.put("And", "\u2a53");
- builder.put("Aogon", "\u0104");
- builder.put("Aopf", "\ud835\udd38");
- builder.put("ApplyFunction", "\u2061");
- builder.put("Aring", "\u00c5");
- builder.put("Ascr", "\ud835\udc9c");
- builder.put("Assign", "\u2254");
- builder.put("Atilde", "\u00c3");
- builder.put("Auml", "\u00c4");
- builder.put("Backslash", "\u2216");
- builder.put("Barv", "\u2ae7");
- builder.put("Barwed", "\u2306");
- builder.put("Bcy", "\u0411");
- builder.put("Because", "\u2235");
- builder.put("Bernoullis", "\u212c");
- builder.put("Beta", "\u0392");
- builder.put("Bfr", "\ud835\udd05");
- builder.put("Bopf", "\ud835\udd39");
- builder.put("Breve", "\u02d8");
- builder.put("Bscr", "\u212c");
- builder.put("Bumpeq", "\u224e");
- builder.put("CHcy", "\u0427");
- builder.put("COPY", "\u00a9");
- builder.put("Cacute", "\u0106");
- builder.put("Cap", "\u22d2");
- builder.put("CapitalDifferentialD", "\u2145");
- builder.put("Cayleys", "\u212d");
- builder.put("Ccaron", "\u010c");
- builder.put("Ccedil", "\u00c7");
- builder.put("Ccirc", "\u0108");
- builder.put("Cconint", "\u2230");
- builder.put("Cdot", "\u010a");
- builder.put("Cedilla", "\u00b8");
- builder.put("CenterDot", "\u00b7");
- builder.put("Cfr", "\u212d");
- builder.put("Chi", "\u03a7");
- builder.put("CircleDot", "\u2299");
- builder.put("CircleMinus", "\u2296");
- builder.put("CirclePlus", "\u2295");
- builder.put("CircleTimes", "\u2297");
- builder.put("ClockwiseContourIntegral", "\u2232");
- builder.put("CloseCurlyDoubleQuote", "\u201d");
- builder.put("CloseCurlyQuote", "\u2019");
- builder.put("Colon", "\u2237");
- builder.put("Colone", "\u2a74");
- builder.put("Congruent", "\u2261");
- builder.put("Conint", "\u222f");
- builder.put("ContourIntegral", "\u222e");
- builder.put("Copf", "\u2102");
- builder.put("Coproduct", "\u2210");
- builder.put("CounterClockwiseContourIntegral", "\u2233");
- builder.put("Cross", "\u2a2f");
- builder.put("Cscr", "\ud835\udc9e");
- builder.put("Cup", "\u22d3");
- builder.put("CupCap", "\u224d");
- builder.put("DD", "\u2145");
- builder.put("DDotrahd", "\u2911");
- builder.put("DJcy", "\u0402");
- builder.put("DScy", "\u0405");
- builder.put("DZcy", "\u040f");
- builder.put("Dagger", "\u2021");
- builder.put("Darr", "\u21a1");
- builder.put("Dashv", "\u2ae4");
- builder.put("Dcaron", "\u010e");
- builder.put("Dcy", "\u0414");
- builder.put("Del", "\u2207");
- builder.put("Delta", "\u0394");
- builder.put("Dfr", "\ud835\udd07");
- builder.put("DiacriticalAcute", "\u00b4");
- builder.put("DiacriticalDot", "\u02d9");
- builder.put("DiacriticalDoubleAcute", "\u02dd");
- builder.put("DiacriticalGrave", "\u0060");
- builder.put("DiacriticalTilde", "\u02dc");
- builder.put("Diamond", "\u22c4");
- builder.put("DifferentialD", "\u2146");
- builder.put("Dopf", "\ud835\udd3b");
- builder.put("Dot", "\u00a8");
- builder.put("DotDot", "\u20dc");
- builder.put("DotEqual", "\u2250");
- builder.put("DoubleContourIntegral", "\u222f");
- builder.put("DoubleDot", "\u00a8");
- builder.put("DoubleDownArrow", "\u21d3");
- builder.put("DoubleLeftArrow", "\u21d0");
- builder.put("DoubleLeftRightArrow", "\u21d4");
- builder.put("DoubleLeftTee", "\u2ae4");
- builder.put("DoubleLongLeftArrow", "\u27f8");
- builder.put("DoubleLongLeftRightArrow", "\u27fa");
- builder.put("DoubleLongRightArrow", "\u27f9");
- builder.put("DoubleRightArrow", "\u21d2");
- builder.put("DoubleRightTee", "\u22a8");
- builder.put("DoubleUpArrow", "\u21d1");
- builder.put("DoubleUpDownArrow", "\u21d5");
- builder.put("DoubleVerticalBar", "\u2225");
- builder.put("DownArrow", "\u2193");
- builder.put("DownArrowBar", "\u2913");
- builder.put("DownArrowUpArrow", "\u21f5");
- builder.put("DownBreve", "\u0311");
- builder.put("DownLeftRightVector", "\u2950");
- builder.put("DownLeftTeeVector", "\u295e");
- builder.put("DownLeftVector", "\u21bd");
- builder.put("DownLeftVectorBar", "\u2956");
- builder.put("DownRightTeeVector", "\u295f");
- builder.put("DownRightVector", "\u21c1");
- builder.put("DownRightVectorBar", "\u2957");
- builder.put("DownTee", "\u22a4");
- builder.put("DownTeeArrow", "\u21a7");
- builder.put("Downarrow", "\u21d3");
- builder.put("Dscr", "\ud835\udc9f");
- builder.put("Dstrok", "\u0110");
- builder.put("ENG", "\u014a");
- builder.put("ETH", "\u00d0");
- builder.put("Eacute", "\u00c9");
- builder.put("Ecaron", "\u011a");
- builder.put("Ecirc", "\u00ca");
- builder.put("Ecy", "\u042d");
- builder.put("Edot", "\u0116");
- builder.put("Efr", "\ud835\udd08");
- builder.put("Egrave", "\u00c8");
- builder.put("Element", "\u2208");
- builder.put("Emacr", "\u0112");
- builder.put("EmptySmallSquare", "\u25fb");
- builder.put("EmptyVerySmallSquare", "\u25ab");
- builder.put("Eogon", "\u0118");
- builder.put("Eopf", "\ud835\udd3c");
- builder.put("Epsilon", "\u0395");
- builder.put("Equal", "\u2a75");
- builder.put("EqualTilde", "\u2242");
- builder.put("Equilibrium", "\u21cc");
- builder.put("Escr", "\u2130");
- builder.put("Esim", "\u2a73");
- builder.put("Eta", "\u0397");
- builder.put("Euml", "\u00cb");
- builder.put("Exists", "\u2203");
- builder.put("ExponentialE", "\u2147");
- builder.put("Fcy", "\u0424");
- builder.put("Ffr", "\ud835\udd09");
- builder.put("FilledSmallSquare", "\u25fc");
- builder.put("FilledVerySmallSquare", "\u25aa");
- builder.put("Fopf", "\ud835\udd3d");
- builder.put("ForAll", "\u2200");
- builder.put("Fouriertrf", "\u2131");
- builder.put("Fscr", "\u2131");
- builder.put("GJcy", "\u0403");
- builder.put("GT", "\u003e");
- builder.put("Gamma", "\u0393");
- builder.put("Gammad", "\u03dc");
- builder.put("Gbreve", "\u011e");
- builder.put("Gcedil", "\u0122");
- builder.put("Gcirc", "\u011c");
- builder.put("Gcy", "\u0413");
- builder.put("Gdot", "\u0120");
- builder.put("Gfr", "\ud835\udd0a");
- builder.put("Gg", "\u22d9");
- builder.put("Gopf", "\ud835\udd3e");
- builder.put("GreaterEqual", "\u2265");
- builder.put("GreaterEqualLess", "\u22db");
- builder.put("GreaterFullEqual", "\u2267");
- builder.put("GreaterGreater", "\u2aa2");
- builder.put("GreaterLess", "\u2277");
- builder.put("GreaterSlantEqual", "\u2a7e");
- builder.put("GreaterTilde", "\u2273");
- builder.put("Gscr", "\ud835\udca2");
- builder.put("Gt", "\u226b");
- builder.put("HARDcy", "\u042a");
- builder.put("Hacek", "\u02c7");
- builder.put("Hat", "\u005e");
- builder.put("Hcirc", "\u0124");
- builder.put("Hfr", "\u210c");
- builder.put("HilbertSpace", "\u210b");
- builder.put("Hopf", "\u210d");
- builder.put("HorizontalLine", "\u2500");
- builder.put("Hscr", "\u210b");
- builder.put("Hstrok", "\u0126");
- builder.put("HumpDownHump", "\u224e");
- builder.put("HumpEqual", "\u224f");
- builder.put("IEcy", "\u0415");
- builder.put("IJlig", "\u0132");
- builder.put("IOcy", "\u0401");
- builder.put("Iacute", "\u00cd");
- builder.put("Icirc", "\u00ce");
- builder.put("Icy", "\u0418");
- builder.put("Idot", "\u0130");
- builder.put("Ifr", "\u2111");
- builder.put("Igrave", "\u00cc");
- builder.put("Im", "\u2111");
- builder.put("Imacr", "\u012a");
- builder.put("ImaginaryI", "\u2148");
- builder.put("Implies", "\u21d2");
- builder.put("Int", "\u222c");
- builder.put("Integral", "\u222b");
- builder.put("Intersection", "\u22c2");
- builder.put("InvisibleComma", "\u2063");
- builder.put("InvisibleTimes", "\u2062");
- builder.put("Iogon", "\u012e");
- builder.put("Iopf", "\ud835\udd40");
- builder.put("Iota", "\u0399");
- builder.put("Iscr", "\u2110");
- builder.put("Itilde", "\u0128");
- builder.put("Iukcy", "\u0406");
- builder.put("Iuml", "\u00cf");
- builder.put("Jcirc", "\u0134");
- builder.put("Jcy", "\u0419");
- builder.put("Jfr", "\ud835\udd0d");
- builder.put("Jopf", "\ud835\udd41");
- builder.put("Jscr", "\ud835\udca5");
- builder.put("Jsercy", "\u0408");
- builder.put("Jukcy", "\u0404");
- builder.put("KHcy", "\u0425");
- builder.put("KJcy", "\u040c");
- builder.put("Kappa", "\u039a");
- builder.put("Kcedil", "\u0136");
- builder.put("Kcy", "\u041a");
- builder.put("Kfr", "\ud835\udd0e");
- builder.put("Kopf", "\ud835\udd42");
- builder.put("Kscr", "\ud835\udca6");
- builder.put("LJcy", "\u0409");
- builder.put("LT", "\u003c");
- builder.put("Lacute", "\u0139");
- builder.put("Lambda", "\u039b");
- builder.put("Lang", "\u27ea");
- builder.put("Laplacetrf", "\u2112");
- builder.put("Larr", "\u219e");
- builder.put("Lcaron", "\u013d");
- builder.put("Lcedil", "\u013b");
- builder.put("Lcy", "\u041b");
- builder.put("LeftAngleBracket", "\u27e8");
- builder.put("LeftArrow", "\u2190");
- builder.put("LeftArrowBar", "\u21e4");
- builder.put("LeftArrowRightArrow", "\u21c6");
- builder.put("LeftCeiling", "\u2308");
- builder.put("LeftDoubleBracket", "\u27e6");
- builder.put("LeftDownTeeVector", "\u2961");
- builder.put("LeftDownVector", "\u21c3");
- builder.put("LeftDownVectorBar", "\u2959");
- builder.put("LeftFloor", "\u230a");
- builder.put("LeftRightArrow", "\u2194");
- builder.put("LeftRightVector", "\u294e");
- builder.put("LeftTee", "\u22a3");
- builder.put("LeftTeeArrow", "\u21a4");
- builder.put("LeftTeeVector", "\u295a");
- builder.put("LeftTriangle", "\u22b2");
- builder.put("LeftTriangleBar", "\u29cf");
- builder.put("LeftTriangleEqual", "\u22b4");
- builder.put("LeftUpDownVector", "\u2951");
- builder.put("LeftUpTeeVector", "\u2960");
- builder.put("LeftUpVector", "\u21bf");
- builder.put("LeftUpVectorBar", "\u2958");
- builder.put("LeftVector", "\u21bc");
- builder.put("LeftVectorBar", "\u2952");
- builder.put("Leftarrow", "\u21d0");
- builder.put("Leftrightarrow", "\u21d4");
- builder.put("LessEqualGreater", "\u22da");
- builder.put("LessFullEqual", "\u2266");
- builder.put("LessGreater", "\u2276");
- builder.put("LessLess", "\u2aa1");
- builder.put("LessSlantEqual", "\u2a7d");
- builder.put("LessTilde", "\u2272");
- builder.put("Lfr", "\ud835\udd0f");
- builder.put("Ll", "\u22d8");
- builder.put("Lleftarrow", "\u21da");
- builder.put("Lmidot", "\u013f");
- builder.put("LongLeftArrow", "\u27f5");
- builder.put("LongLeftRightArrow", "\u27f7");
- builder.put("LongRightArrow", "\u27f6");
- builder.put("Longleftarrow", "\u27f8");
- builder.put("Longleftrightarrow", "\u27fa");
- builder.put("Longrightarrow", "\u27f9");
- builder.put("Lopf", "\ud835\udd43");
- builder.put("LowerLeftArrow", "\u2199");
- builder.put("LowerRightArrow", "\u2198");
- builder.put("Lscr", "\u2112");
- builder.put("Lsh", "\u21b0");
- builder.put("Lstrok", "\u0141");
- builder.put("Lt", "\u226a");
- builder.put("Map", "\u2905");
- builder.put("Mcy", "\u041c");
- builder.put("MediumSpace", "\u205f");
- builder.put("Mellintrf", "\u2133");
- builder.put("Mfr", "\ud835\udd10");
- builder.put("MinusPlus", "\u2213");
- builder.put("Mopf", "\ud835\udd44");
- builder.put("Mscr", "\u2133");
- builder.put("Mu", "\u039c");
- builder.put("NJcy", "\u040a");
- builder.put("Nacute", "\u0143");
- builder.put("Ncaron", "\u0147");
- builder.put("Ncedil", "\u0145");
- builder.put("Ncy", "\u041d");
- builder.put("NegativeMediumSpace", "\u200b");
- builder.put("NegativeThickSpace", "\u200b");
- builder.put("NegativeThinSpace", "\u200b");
- builder.put("NegativeVeryThinSpace", "\u200b");
- builder.put("NestedGreaterGreater", "\u226b");
- builder.put("NestedLessLess", "\u226a");
- builder.put("NewLine", "\n");
- builder.put("Nfr", "\ud835\udd11");
- builder.put("NoBreak", "\u2060");
- builder.put("NonBreakingSpace", "\u00a0");
- builder.put("Nopf", "\u2115");
- builder.put("Not", "\u2aec");
- builder.put("NotCongruent", "\u2262");
- builder.put("NotCupCap", "\u226d");
- builder.put("NotDoubleVerticalBar", "\u2226");
- builder.put("NotElement", "\u2209");
- builder.put("NotEqual", "\u2260");
- builder.put("NotEqualTilde", "\u2242\u0338");
- builder.put("NotExists", "\u2204");
- builder.put("NotGreater", "\u226f");
- builder.put("NotGreaterEqual", "\u2271");
- builder.put("NotGreaterFullEqual", "\u2267\u0338");
- builder.put("NotGreaterGreater", "\u226b\u0338");
- builder.put("NotGreaterLess", "\u2279");
- builder.put("NotGreaterSlantEqual", "\u2a7e\u0338");
- builder.put("NotGreaterTilde", "\u2275");
- builder.put("NotHumpDownHump", "\u224e\u0338");
- builder.put("NotHumpEqual", "\u224f\u0338");
- builder.put("NotLeftTriangle", "\u22ea");
- builder.put("NotLeftTriangleBar", "\u29cf\u0338");
- builder.put("NotLeftTriangleEqual", "\u22ec");
- builder.put("NotLess", "\u226e");
- builder.put("NotLessEqual", "\u2270");
- builder.put("NotLessGreater", "\u2278");
- builder.put("NotLessLess", "\u226a\u0338");
- builder.put("NotLessSlantEqual", "\u2a7d\u0338");
- builder.put("NotLessTilde", "\u2274");
- builder.put("NotNestedGreaterGreater", "\u2aa2\u0338");
- builder.put("NotNestedLessLess", "\u2aa1\u0338");
- builder.put("NotPrecedes", "\u2280");
- builder.put("NotPrecedesEqual", "\u2aaf\u0338");
- builder.put("NotPrecedesSlantEqual", "\u22e0");
- builder.put("NotReverseElement", "\u220c");
- builder.put("NotRightTriangle", "\u22eb");
- builder.put("NotRightTriangleBar", "\u29d0\u0338");
- builder.put("NotRightTriangleEqual", "\u22ed");
- builder.put("NotSquareSubset", "\u228f\u0338");
- builder.put("NotSquareSubsetEqual", "\u22e2");
- builder.put("NotSquareSuperset", "\u2290\u0338");
- builder.put("NotSquareSupersetEqual", "\u22e3");
- builder.put("NotSubset", "\u2282\u20d2");
- builder.put("NotSubsetEqual", "\u2288");
- builder.put("NotSucceeds", "\u2281");
- builder.put("NotSucceedsEqual", "\u2ab0\u0338");
- builder.put("NotSucceedsSlantEqual", "\u22e1");
- builder.put("NotSucceedsTilde", "\u227f\u0338");
- builder.put("NotSuperset", "\u2283\u20d2");
- builder.put("NotSupersetEqual", "\u2289");
- builder.put("NotTilde", "\u2241");
- builder.put("NotTildeEqual", "\u2244");
- builder.put("NotTildeFullEqual", "\u2247");
- builder.put("NotTildeTilde", "\u2249");
- builder.put("NotVerticalBar", "\u2224");
- builder.put("Nscr", "\ud835\udca9");
- builder.put("Ntilde", "\u00d1");
- builder.put("Nu", "\u039d");
- builder.put("OElig", "\u0152");
- builder.put("Oacute", "\u00d3");
- builder.put("Ocirc", "\u00d4");
- builder.put("Ocy", "\u041e");
- builder.put("Odblac", "\u0150");
- builder.put("Ofr", "\ud835\udd12");
- builder.put("Ograve", "\u00d2");
- builder.put("Omacr", "\u014c");
- builder.put("Omega", "\u03a9");
- builder.put("Omicron", "\u039f");
- builder.put("Oopf", "\ud835\udd46");
- builder.put("OpenCurlyDoubleQuote", "\u201c");
- builder.put("OpenCurlyQuote", "\u2018");
- builder.put("Or", "\u2a54");
- builder.put("Oscr", "\ud835\udcaa");
- builder.put("Oslash", "\u00d8");
- builder.put("Otilde", "\u00d5");
- builder.put("Otimes", "\u2a37");
- builder.put("Ouml", "\u00d6");
- builder.put("OverBar", "\u203e");
- builder.put("OverBrace", "\u23de");
- builder.put("OverBracket", "\u23b4");
- builder.put("OverParenthesis", "\u23dc");
- builder.put("PartialD", "\u2202");
- builder.put("Pcy", "\u041f");
- builder.put("Pfr", "\ud835\udd13");
- builder.put("Phi", "\u03a6");
- builder.put("Pi", "\u03a0");
- builder.put("PlusMinus", "\u00b1");
- builder.put("Poincareplane", "\u210c");
- builder.put("Popf", "\u2119");
- builder.put("Pr", "\u2abb");
- builder.put("Precedes", "\u227a");
- builder.put("PrecedesEqual", "\u2aaf");
- builder.put("PrecedesSlantEqual", "\u227c");
- builder.put("PrecedesTilde", "\u227e");
- builder.put("Prime", "\u2033");
- builder.put("Product", "\u220f");
- builder.put("Proportion", "\u2237");
- builder.put("Proportional", "\u221d");
- builder.put("Pscr", "\ud835\udcab");
- builder.put("Psi", "\u03a8");
- builder.put("QUOT", "\"");
- builder.put("Qfr", "\ud835\udd14");
- builder.put("Qopf", "\u211a");
- builder.put("Qscr", "\ud835\udcac");
- builder.put("RBarr", "\u2910");
- builder.put("REG", "\u00ae");
- builder.put("Racute", "\u0154");
- builder.put("Rang", "\u27eb");
- builder.put("Rarr", "\u21a0");
- builder.put("Rarrtl", "\u2916");
- builder.put("Rcaron", "\u0158");
- builder.put("Rcedil", "\u0156");
- builder.put("Rcy", "\u0420");
- builder.put("Re", "\u211c");
- builder.put("ReverseElement", "\u220b");
- builder.put("ReverseEquilibrium", "\u21cb");
- builder.put("ReverseUpEquilibrium", "\u296f");
- builder.put("Rfr", "\u211c");
- builder.put("Rho", "\u03a1");
- builder.put("RightAngleBracket", "\u27e9");
- builder.put("RightArrow", "\u2192");
- builder.put("RightArrowBar", "\u21e5");
- builder.put("RightArrowLeftArrow", "\u21c4");
- builder.put("RightCeiling", "\u2309");
- builder.put("RightDoubleBracket", "\u27e7");
- builder.put("RightDownTeeVector", "\u295d");
- builder.put("RightDownVector", "\u21c2");
- builder.put("RightDownVectorBar", "\u2955");
- builder.put("RightFloor", "\u230b");
- builder.put("RightTee", "\u22a2");
- builder.put("RightTeeArrow", "\u21a6");
- builder.put("RightTeeVector", "\u295b");
- builder.put("RightTriangle", "\u22b3");
- builder.put("RightTriangleBar", "\u29d0");
- builder.put("RightTriangleEqual", "\u22b5");
- builder.put("RightUpDownVector", "\u294f");
- builder.put("RightUpTeeVector", "\u295c");
- builder.put("RightUpVector", "\u21be");
- builder.put("RightUpVectorBar", "\u2954");
- builder.put("RightVector", "\u21c0");
- builder.put("RightVectorBar", "\u2953");
- builder.put("Rightarrow", "\u21d2");
- builder.put("Ropf", "\u211d");
- builder.put("RoundImplies", "\u2970");
- builder.put("Rrightarrow", "\u21db");
- builder.put("Rscr", "\u211b");
- builder.put("Rsh", "\u21b1");
- builder.put("RuleDelayed", "\u29f4");
- builder.put("SHCHcy", "\u0429");
- builder.put("SHcy", "\u0428");
- builder.put("SOFTcy", "\u042c");
- builder.put("Sacute", "\u015a");
- builder.put("Sc", "\u2abc");
- builder.put("Scaron", "\u0160");
- builder.put("Scedil", "\u015e");
- builder.put("Scirc", "\u015c");
- builder.put("Scy", "\u0421");
- builder.put("Sfr", "\ud835\udd16");
- builder.put("ShortDownArrow", "\u2193");
- builder.put("ShortLeftArrow", "\u2190");
- builder.put("ShortRightArrow", "\u2192");
- builder.put("ShortUpArrow", "\u2191");
- builder.put("Sigma", "\u03a3");
- builder.put("SmallCircle", "\u2218");
- builder.put("Sopf", "\ud835\udd4a");
- builder.put("Sqrt", "\u221a");
- builder.put("Square", "\u25a1");
- builder.put("SquareIntersection", "\u2293");
- builder.put("SquareSubset", "\u228f");
- builder.put("SquareSubsetEqual", "\u2291");
- builder.put("SquareSuperset", "\u2290");
- builder.put("SquareSupersetEqual", "\u2292");
- builder.put("SquareUnion", "\u2294");
- builder.put("Sscr", "\ud835\udcae");
- builder.put("Star", "\u22c6");
- builder.put("Sub", "\u22d0");
- builder.put("Subset", "\u22d0");
- builder.put("SubsetEqual", "\u2286");
- builder.put("Succeeds", "\u227b");
- builder.put("SucceedsEqual", "\u2ab0");
- builder.put("SucceedsSlantEqual", "\u227d");
- builder.put("SucceedsTilde", "\u227f");
- builder.put("SuchThat", "\u220b");
- builder.put("Sum", "\u2211");
- builder.put("Sup", "\u22d1");
- builder.put("Superset", "\u2283");
- builder.put("SupersetEqual", "\u2287");
- builder.put("Supset", "\u22d1");
- builder.put("THORN", "\u00de");
- builder.put("TRADE", "\u2122");
- builder.put("TSHcy", "\u040b");
- builder.put("TScy", "\u0426");
- builder.put("Tab", "\u0009");
- builder.put("Tau", "\u03a4");
- builder.put("Tcaron", "\u0164");
- builder.put("Tcedil", "\u0162");
- builder.put("Tcy", "\u0422");
- builder.put("Tfr", "\ud835\udd17");
- builder.put("Therefore", "\u2234");
- builder.put("Theta", "\u0398");
- builder.put("ThickSpace", "\u205f\u200a");
- builder.put("ThinSpace", "\u2009");
- builder.put("Tilde", "\u223c");
- builder.put("TildeEqual", "\u2243");
- builder.put("TildeFullEqual", "\u2245");
- builder.put("TildeTilde", "\u2248");
- builder.put("Topf", "\ud835\udd4b");
- builder.put("TripleDot", "\u20db");
- builder.put("Tscr", "\ud835\udcaf");
- builder.put("Tstrok", "\u0166");
- builder.put("Uacute", "\u00da");
- builder.put("Uarr", "\u219f");
- builder.put("Uarrocir", "\u2949");
- builder.put("Ubrcy", "\u040e");
- builder.put("Ubreve", "\u016c");
- builder.put("Ucirc", "\u00db");
- builder.put("Ucy", "\u0423");
- builder.put("Udblac", "\u0170");
- builder.put("Ufr", "\ud835\udd18");
- builder.put("Ugrave", "\u00d9");
- builder.put("Umacr", "\u016a");
- builder.put("UnderBar", "\u005f");
- builder.put("UnderBrace", "\u23df");
- builder.put("UnderBracket", "\u23b5");
- builder.put("UnderParenthesis", "\u23dd");
- builder.put("Union", "\u22c3");
- builder.put("UnionPlus", "\u228e");
- builder.put("Uogon", "\u0172");
- builder.put("Uopf", "\ud835\udd4c");
- builder.put("UpArrow", "\u2191");
- builder.put("UpArrowBar", "\u2912");
- builder.put("UpArrowDownArrow", "\u21c5");
- builder.put("UpDownArrow", "\u2195");
- builder.put("UpEquilibrium", "\u296e");
- builder.put("UpTee", "\u22a5");
- builder.put("UpTeeArrow", "\u21a5");
- builder.put("Uparrow", "\u21d1");
- builder.put("Updownarrow", "\u21d5");
- builder.put("UpperLeftArrow", "\u2196");
- builder.put("UpperRightArrow", "\u2197");
- builder.put("Upsi", "\u03d2");
- builder.put("Upsilon", "\u03a5");
- builder.put("Uring", "\u016e");
- builder.put("Uscr", "\ud835\udcb0");
- builder.put("Utilde", "\u0168");
- builder.put("Uuml", "\u00dc");
- builder.put("VDash", "\u22ab");
- builder.put("Vbar", "\u2aeb");
- builder.put("Vcy", "\u0412");
- builder.put("Vdash", "\u22a9");
- builder.put("Vdashl", "\u2ae6");
- builder.put("Vee", "\u22c1");
- builder.put("Verbar", "\u2016");
- builder.put("Vert", "\u2016");
- builder.put("VerticalBar", "\u2223");
- builder.put("VerticalLine", "\u007c");
- builder.put("VerticalSeparator", "\u2758");
- builder.put("VerticalTilde", "\u2240");
- builder.put("VeryThinSpace", "\u200a");
- builder.put("Vfr", "\ud835\udd19");
- builder.put("Vopf", "\ud835\udd4d");
- builder.put("Vscr", "\ud835\udcb1");
- builder.put("Vvdash", "\u22aa");
- builder.put("Wcirc", "\u0174");
- builder.put("Wedge", "\u22c0");
- builder.put("Wfr", "\ud835\udd1a");
- builder.put("Wopf", "\ud835\udd4e");
- builder.put("Wscr", "\ud835\udcb2");
- builder.put("Xfr", "\ud835\udd1b");
- builder.put("Xi", "\u039e");
- builder.put("Xopf", "\ud835\udd4f");
- builder.put("Xscr", "\ud835\udcb3");
- builder.put("YAcy", "\u042f");
- builder.put("YIcy", "\u0407");
- builder.put("YUcy", "\u042e");
- builder.put("Yacute", "\u00dd");
- builder.put("Ycirc", "\u0176");
- builder.put("Ycy", "\u042b");
- builder.put("Yfr", "\ud835\udd1c");
- builder.put("Yopf", "\ud835\udd50");
- builder.put("Yscr", "\ud835\udcb4");
- builder.put("Yuml", "\u0178");
- builder.put("ZHcy", "\u0416");
- builder.put("Zacute", "\u0179");
- builder.put("Zcaron", "\u017d");
- builder.put("Zcy", "\u0417");
- builder.put("Zdot", "\u017b");
- builder.put("ZeroWidthSpace", "\u200b");
- builder.put("Zeta", "\u0396");
- builder.put("Zfr", "\u2128");
- builder.put("Zopf", "\u2124");
- builder.put("Zscr", "\ud835\udcb5");
- builder.put("aacute", "\u00e1");
- builder.put("abreve", "\u0103");
- builder.put("ac", "\u223e");
- builder.put("acE", "\u223e\u0333");
- builder.put("acd", "\u223f");
- builder.put("acirc", "\u00e2");
- builder.put("acute", "\u00b4");
- builder.put("acy", "\u0430");
- builder.put("aelig", "\u00e6");
- builder.put("af", "\u2061");
- builder.put("afr", "\ud835\udd1e");
- builder.put("agrave", "\u00e0");
- builder.put("alefsym", "\u2135");
- builder.put("aleph", "\u2135");
- builder.put("alpha", "\u03b1");
- builder.put("amacr", "\u0101");
- builder.put("amalg", "\u2a3f");
- builder.put("amp", "\u0026");
- builder.put("and", "\u2227");
- builder.put("andand", "\u2a55");
- builder.put("andd", "\u2a5c");
- builder.put("andslope", "\u2a58");
- builder.put("andv", "\u2a5a");
- builder.put("ang", "\u2220");
- builder.put("ange", "\u29a4");
- builder.put("angle", "\u2220");
- builder.put("angmsd", "\u2221");
- builder.put("angmsdaa", "\u29a8");
- builder.put("angmsdab", "\u29a9");
- builder.put("angmsdac", "\u29aa");
- builder.put("angmsdad", "\u29ab");
- builder.put("angmsdae", "\u29ac");
- builder.put("angmsdaf", "\u29ad");
- builder.put("angmsdag", "\u29ae");
- builder.put("angmsdah", "\u29af");
- builder.put("angrt", "\u221f");
- builder.put("angrtvb", "\u22be");
- builder.put("angrtvbd", "\u299d");
- builder.put("angsph", "\u2222");
- builder.put("angst", "\u00c5");
- builder.put("angzarr", "\u237c");
- builder.put("aogon", "\u0105");
- builder.put("aopf", "\ud835\udd52");
- builder.put("ap", "\u2248");
- builder.put("apE", "\u2a70");
- builder.put("apacir", "\u2a6f");
- builder.put("ape", "\u224a");
- builder.put("apid", "\u224b");
- builder.put("apos", "\u0027");
- builder.put("approx", "\u2248");
- builder.put("approxeq", "\u224a");
- builder.put("aring", "\u00e5");
- builder.put("ascr", "\ud835\udcb6");
- builder.put("ast", "\u002a");
- builder.put("asymp", "\u2248");
- builder.put("asympeq", "\u224d");
- builder.put("atilde", "\u00e3");
- builder.put("auml", "\u00e4");
- builder.put("awconint", "\u2233");
- builder.put("awint", "\u2a11");
- builder.put("bNot", "\u2aed");
- builder.put("backcong", "\u224c");
- builder.put("backepsilon", "\u03f6");
- builder.put("backprime", "\u2035");
- builder.put("backsim", "\u223d");
- builder.put("backsimeq", "\u22cd");
- builder.put("barvee", "\u22bd");
- builder.put("barwed", "\u2305");
- builder.put("barwedge", "\u2305");
- builder.put("bbrk", "\u23b5");
- builder.put("bbrktbrk", "\u23b6");
- builder.put("bcong", "\u224c");
- builder.put("bcy", "\u0431");
- builder.put("bdquo", "\u201e");
- builder.put("becaus", "\u2235");
- builder.put("because", "\u2235");
- builder.put("bemptyv", "\u29b0");
- builder.put("bepsi", "\u03f6");
- builder.put("bernou", "\u212c");
- builder.put("beta", "\u03b2");
- builder.put("beth", "\u2136");
- builder.put("between", "\u226c");
- builder.put("bfr", "\ud835\udd1f");
- builder.put("bigcap", "\u22c2");
- builder.put("bigcirc", "\u25ef");
- builder.put("bigcup", "\u22c3");
- builder.put("bigodot", "\u2a00");
- builder.put("bigoplus", "\u2a01");
- builder.put("bigotimes", "\u2a02");
- builder.put("bigsqcup", "\u2a06");
- builder.put("bigstar", "\u2605");
- builder.put("bigtriangledown", "\u25bd");
- builder.put("bigtriangleup", "\u25b3");
- builder.put("biguplus", "\u2a04");
- builder.put("bigvee", "\u22c1");
- builder.put("bigwedge", "\u22c0");
- builder.put("bkarow", "\u290d");
- builder.put("blacklozenge", "\u29eb");
- builder.put("blacksquare", "\u25aa");
- builder.put("blacktriangle", "\u25b4");
- builder.put("blacktriangledown", "\u25be");
- builder.put("blacktriangleleft", "\u25c2");
- builder.put("blacktriangleright", "\u25b8");
- builder.put("blank", "\u2423");
- builder.put("blk12", "\u2592");
- builder.put("blk14", "\u2591");
- builder.put("blk34", "\u2593");
- builder.put("block", "\u2588");
- builder.put("bne", "\u003d\u20e5");
- builder.put("bnequiv", "\u2261\u20e5");
- builder.put("bnot", "\u2310");
- builder.put("bopf", "\ud835\udd53");
- builder.put("bot", "\u22a5");
- builder.put("bottom", "\u22a5");
- builder.put("bowtie", "\u22c8");
- builder.put("boxDL", "\u2557");
- builder.put("boxDR", "\u2554");
- builder.put("boxDl", "\u2556");
- builder.put("boxDr", "\u2553");
- builder.put("boxH", "\u2550");
- builder.put("boxHD", "\u2566");
- builder.put("boxHU", "\u2569");
- builder.put("boxHd", "\u2564");
- builder.put("boxHu", "\u2567");
- builder.put("boxUL", "\u255d");
- builder.put("boxUR", "\u255a");
- builder.put("boxUl", "\u255c");
- builder.put("boxUr", "\u2559");
- builder.put("boxV", "\u2551");
- builder.put("boxVH", "\u256c");
- builder.put("boxVL", "\u2563");
- builder.put("boxVR", "\u2560");
- builder.put("boxVh", "\u256b");
- builder.put("boxVl", "\u2562");
- builder.put("boxVr", "\u255f");
- builder.put("boxbox", "\u29c9");
- builder.put("boxdL", "\u2555");
- builder.put("boxdR", "\u2552");
- builder.put("boxdl", "\u2510");
- builder.put("boxdr", "\u250c");
- builder.put("boxh", "\u2500");
- builder.put("boxhD", "\u2565");
- builder.put("boxhU", "\u2568");
- builder.put("boxhd", "\u252c");
- builder.put("boxhu", "\u2534");
- builder.put("boxminus", "\u229f");
- builder.put("boxplus", "\u229e");
- builder.put("boxtimes", "\u22a0");
- builder.put("boxuL", "\u255b");
- builder.put("boxuR", "\u2558");
- builder.put("boxul", "\u2518");
- builder.put("boxur", "\u2514");
- builder.put("boxv", "\u2502");
- builder.put("boxvH", "\u256a");
- builder.put("boxvL", "\u2561");
- builder.put("boxvR", "\u255e");
- builder.put("boxvh", "\u253c");
- builder.put("boxvl", "\u2524");
- builder.put("boxvr", "\u251c");
- builder.put("bprime", "\u2035");
- builder.put("breve", "\u02d8");
- builder.put("brvbar", "\u00a6");
- builder.put("bscr", "\ud835\udcb7");
- builder.put("bsemi", "\u204f");
- builder.put("bsim", "\u223d");
- builder.put("bsime", "\u22cd");
- builder.put("bsol", "\\");
- builder.put("bsolb", "\u29c5");
- builder.put("bsolhsub", "\u27c8");
- builder.put("bull", "\u2022");
- builder.put("bullet", "\u2022");
- builder.put("bump", "\u224e");
- builder.put("bumpE", "\u2aae");
- builder.put("bumpe", "\u224f");
- builder.put("bumpeq", "\u224f");
- builder.put("cacute", "\u0107");
- builder.put("cap", "\u2229");
- builder.put("capand", "\u2a44");
- builder.put("capbrcup", "\u2a49");
- builder.put("capcap", "\u2a4b");
- builder.put("capcup", "\u2a47");
- builder.put("capdot", "\u2a40");
- builder.put("caps", "\u2229\ufe00");
- builder.put("caret", "\u2041");
- builder.put("caron", "\u02c7");
- builder.put("ccaps", "\u2a4d");
- builder.put("ccaron", "\u010d");
- builder.put("ccedil", "\u00e7");
- builder.put("ccirc", "\u0109");
- builder.put("ccups", "\u2a4c");
- builder.put("ccupssm", "\u2a50");
- builder.put("cdot", "\u010b");
- builder.put("cedil", "\u00b8");
- builder.put("cemptyv", "\u29b2");
- builder.put("cent", "\u00a2");
- builder.put("centerdot", "\u00b7");
- builder.put("cfr", "\ud835\udd20");
- builder.put("chcy", "\u0447");
- builder.put("check", "\u2713");
- builder.put("checkmark", "\u2713");
- builder.put("chi", "\u03c7");
- builder.put("cir", "\u25cb");
- builder.put("cirE", "\u29c3");
- builder.put("circ", "\u02c6");
- builder.put("circeq", "\u2257");
- builder.put("circlearrowleft", "\u21ba");
- builder.put("circlearrowright", "\u21bb");
- builder.put("circledR", "\u00ae");
- builder.put("circledS", "\u24c8");
- builder.put("circledast", "\u229b");
- builder.put("circledcirc", "\u229a");
- builder.put("circleddash", "\u229d");
- builder.put("cire", "\u2257");
- builder.put("cirfnint", "\u2a10");
- builder.put("cirmid", "\u2aef");
- builder.put("cirscir", "\u29c2");
- builder.put("clubs", "\u2663");
- builder.put("clubsuit", "\u2663");
- builder.put("colon", "\u003a");
- builder.put("colone", "\u2254");
- builder.put("coloneq", "\u2254");
- builder.put("comma", "\u002c");
- builder.put("commat", "\u0040");
- builder.put("comp", "\u2201");
- builder.put("compfn", "\u2218");
- builder.put("complement", "\u2201");
- builder.put("complexes", "\u2102");
- builder.put("cong", "\u2245");
- builder.put("congdot", "\u2a6d");
- builder.put("conint", "\u222e");
- builder.put("copf", "\ud835\udd54");
- builder.put("coprod", "\u2210");
- builder.put("copy", "\u00a9");
- builder.put("copysr", "\u2117");
- builder.put("crarr", "\u21b5");
- builder.put("cross", "\u2717");
- builder.put("cscr", "\ud835\udcb8");
- builder.put("csub", "\u2acf");
- builder.put("csube", "\u2ad1");
- builder.put("csup", "\u2ad0");
- builder.put("csupe", "\u2ad2");
- builder.put("ctdot", "\u22ef");
- builder.put("cudarrl", "\u2938");
- builder.put("cudarrr", "\u2935");
- builder.put("cuepr", "\u22de");
- builder.put("cuesc", "\u22df");
- builder.put("cularr", "\u21b6");
- builder.put("cularrp", "\u293d");
- builder.put("cup", "\u222a");
- builder.put("cupbrcap", "\u2a48");
- builder.put("cupcap", "\u2a46");
- builder.put("cupcup", "\u2a4a");
- builder.put("cupdot", "\u228d");
- builder.put("cupor", "\u2a45");
- builder.put("cups", "\u222a\ufe00");
- builder.put("curarr", "\u21b7");
- builder.put("curarrm", "\u293c");
- builder.put("curlyeqprec", "\u22de");
- builder.put("curlyeqsucc", "\u22df");
- builder.put("curlyvee", "\u22ce");
- builder.put("curlywedge", "\u22cf");
- builder.put("curren", "\u00a4");
- builder.put("curvearrowleft", "\u21b6");
- builder.put("curvearrowright", "\u21b7");
- builder.put("cuvee", "\u22ce");
- builder.put("cuwed", "\u22cf");
- builder.put("cwconint", "\u2232");
- builder.put("cwint", "\u2231");
- builder.put("cylcty", "\u232d");
- builder.put("dArr", "\u21d3");
- builder.put("dHar", "\u2965");
- builder.put("dagger", "\u2020");
- builder.put("daleth", "\u2138");
- builder.put("darr", "\u2193");
- builder.put("dash", "\u2010");
- builder.put("dashv", "\u22a3");
- builder.put("dbkarow", "\u290f");
- builder.put("dblac", "\u02dd");
- builder.put("dcaron", "\u010f");
- builder.put("dcy", "\u0434");
- builder.put("dd", "\u2146");
- builder.put("ddagger", "\u2021");
- builder.put("ddarr", "\u21ca");
- builder.put("ddotseq", "\u2a77");
- builder.put("deg", "\u00b0");
- builder.put("delta", "\u03b4");
- builder.put("demptyv", "\u29b1");
- builder.put("dfisht", "\u297f");
- builder.put("dfr", "\ud835\udd21");
- builder.put("dharl", "\u21c3");
- builder.put("dharr", "\u21c2");
- builder.put("diam", "\u22c4");
- builder.put("diamond", "\u22c4");
- builder.put("diamondsuit", "\u2666");
- builder.put("diams", "\u2666");
- builder.put("die", "\u00a8");
- builder.put("digamma", "\u03dd");
- builder.put("disin", "\u22f2");
- builder.put("div", "\u00f7");
- builder.put("divide", "\u00f7");
- builder.put("divideontimes", "\u22c7");
- builder.put("divonx", "\u22c7");
- builder.put("djcy", "\u0452");
- builder.put("dlcorn", "\u231e");
- builder.put("dlcrop", "\u230d");
- builder.put("dollar", "\u0024");
- builder.put("dopf", "\ud835\udd55");
- builder.put("dot", "\u02d9");
- builder.put("doteq", "\u2250");
- builder.put("doteqdot", "\u2251");
- builder.put("dotminus", "\u2238");
- builder.put("dotplus", "\u2214");
- builder.put("dotsquare", "\u22a1");
- builder.put("doublebarwedge", "\u2306");
- builder.put("downarrow", "\u2193");
- builder.put("downdownarrows", "\u21ca");
- builder.put("downharpoonleft", "\u21c3");
- builder.put("downharpoonright", "\u21c2");
- builder.put("drbkarow", "\u2910");
- builder.put("drcorn", "\u231f");
- builder.put("drcrop", "\u230c");
- builder.put("dscr", "\ud835\udcb9");
- builder.put("dscy", "\u0455");
- builder.put("dsol", "\u29f6");
- builder.put("dstrok", "\u0111");
- builder.put("dtdot", "\u22f1");
- builder.put("dtri", "\u25bf");
- builder.put("dtrif", "\u25be");
- builder.put("duarr", "\u21f5");
- builder.put("duhar", "\u296f");
- builder.put("dwangle", "\u29a6");
- builder.put("dzcy", "\u045f");
- builder.put("dzigrarr", "\u27ff");
- builder.put("eDDot", "\u2a77");
- builder.put("eDot", "\u2251");
- builder.put("eacute", "\u00e9");
- builder.put("easter", "\u2a6e");
- builder.put("ecaron", "\u011b");
- builder.put("ecir", "\u2256");
- builder.put("ecirc", "\u00ea");
- builder.put("ecolon", "\u2255");
- builder.put("ecy", "\u044d");
- builder.put("edot", "\u0117");
- builder.put("ee", "\u2147");
- builder.put("efDot", "\u2252");
- builder.put("efr", "\ud835\udd22");
- builder.put("eg", "\u2a9a");
- builder.put("egrave", "\u00e8");
- builder.put("egs", "\u2a96");
- builder.put("egsdot", "\u2a98");
- builder.put("el", "\u2a99");
- builder.put("elinters", "\u23e7");
- builder.put("ell", "\u2113");
- builder.put("els", "\u2a95");
- builder.put("elsdot", "\u2a97");
- builder.put("emacr", "\u0113");
- builder.put("empty", "\u2205");
- builder.put("emptyset", "\u2205");
- builder.put("emptyv", "\u2205");
- builder.put("emsp13", "\u2004");
- builder.put("emsp14", "\u2005");
- builder.put("emsp", "\u2003");
- builder.put("eng", "\u014b");
- builder.put("ensp", "\u2002");
- builder.put("eogon", "\u0119");
- builder.put("eopf", "\ud835\udd56");
- builder.put("epar", "\u22d5");
- builder.put("eparsl", "\u29e3");
- builder.put("eplus", "\u2a71");
- builder.put("epsi", "\u03b5");
- builder.put("epsilon", "\u03b5");
- builder.put("epsiv", "\u03f5");
- builder.put("eqcirc", "\u2256");
- builder.put("eqcolon", "\u2255");
- builder.put("eqsim", "\u2242");
- builder.put("eqslantgtr", "\u2a96");
- builder.put("eqslantless", "\u2a95");
- builder.put("equals", "\u003d");
- builder.put("equest", "\u225f");
- builder.put("equiv", "\u2261");
- builder.put("equivDD", "\u2a78");
- builder.put("eqvparsl", "\u29e5");
- builder.put("erDot", "\u2253");
- builder.put("erarr", "\u2971");
- builder.put("escr", "\u212f");
- builder.put("esdot", "\u2250");
- builder.put("esim", "\u2242");
- builder.put("eta", "\u03b7");
- builder.put("eth", "\u00f0");
- builder.put("euml", "\u00eb");
- builder.put("euro", "\u20ac");
- builder.put("excl", "\u0021");
- builder.put("exist", "\u2203");
- builder.put("expectation", "\u2130");
- builder.put("exponentiale", "\u2147");
- builder.put("fallingdotseq", "\u2252");
- builder.put("fcy", "\u0444");
- builder.put("female", "\u2640");
- builder.put("ffilig", "\ufb03");
- builder.put("fflig", "\ufb00");
- builder.put("ffllig", "\ufb04");
- builder.put("ffr", "\ud835\udd23");
- builder.put("filig", "\ufb01");
- builder.put("fjlig", "\u0066\u006a");
- builder.put("flat", "\u266d");
- builder.put("fllig", "\ufb02");
- builder.put("fltns", "\u25b1");
- builder.put("fnof", "\u0192");
- builder.put("fopf", "\ud835\udd57");
- builder.put("forall", "\u2200");
- builder.put("fork", "\u22d4");
- builder.put("forkv", "\u2ad9");
- builder.put("fpartint", "\u2a0d");
- builder.put("frac12", "\u00bd");
- builder.put("frac13", "\u2153");
- builder.put("frac14", "\u00bc");
- builder.put("frac15", "\u2155");
- builder.put("frac16", "\u2159");
- builder.put("frac18", "\u215b");
- builder.put("frac23", "\u2154");
- builder.put("frac25", "\u2156");
- builder.put("frac34", "\u00be");
- builder.put("frac35", "\u2157");
- builder.put("frac38", "\u215c");
- builder.put("frac45", "\u2158");
- builder.put("frac56", "\u215a");
- builder.put("frac58", "\u215d");
- builder.put("frac78", "\u215e");
- builder.put("frasl", "\u2044");
- builder.put("frown", "\u2322");
- builder.put("fscr", "\ud835\udcbb");
- builder.put("gE", "\u2267");
- builder.put("gEl", "\u2a8c");
- builder.put("gacute", "\u01f5");
- builder.put("gamma", "\u03b3");
- builder.put("gammad", "\u03dd");
- builder.put("gap", "\u2a86");
- builder.put("gbreve", "\u011f");
- builder.put("gcirc", "\u011d");
- builder.put("gcy", "\u0433");
- builder.put("gdot", "\u0121");
- builder.put("ge", "\u2265");
- builder.put("gel", "\u22db");
- builder.put("geq", "\u2265");
- builder.put("geqq", "\u2267");
- builder.put("geqslant", "\u2a7e");
- builder.put("ges", "\u2a7e");
- builder.put("gescc", "\u2aa9");
- builder.put("gesdot", "\u2a80");
- builder.put("gesdoto", "\u2a82");
- builder.put("gesdotol", "\u2a84");
- builder.put("gesl", "\u22db\ufe00");
- builder.put("gesles", "\u2a94");
- builder.put("gfr", "\ud835\udd24");
- builder.put("gg", "\u226b");
- builder.put("ggg", "\u22d9");
- builder.put("gimel", "\u2137");
- builder.put("gjcy", "\u0453");
- builder.put("gl", "\u2277");
- builder.put("glE", "\u2a92");
- builder.put("gla", "\u2aa5");
- builder.put("glj", "\u2aa4");
- builder.put("gnE", "\u2269");
- builder.put("gnap", "\u2a8a");
- builder.put("gnapprox", "\u2a8a");
- builder.put("gne", "\u2a88");
- builder.put("gneq", "\u2a88");
- builder.put("gneqq", "\u2269");
- builder.put("gnsim", "\u22e7");
- builder.put("gopf", "\ud835\udd58");
- builder.put("grave", "\u0060");
- builder.put("gscr", "\u210a");
- builder.put("gsim", "\u2273");
- builder.put("gsime", "\u2a8e");
- builder.put("gsiml", "\u2a90");
- builder.put("gt", "\u003e");
- builder.put("gtcc", "\u2aa7");
- builder.put("gtcir", "\u2a7a");
- builder.put("gtdot", "\u22d7");
- builder.put("gtlPar", "\u2995");
- builder.put("gtquest", "\u2a7c");
- builder.put("gtrapprox", "\u2a86");
- builder.put("gtrarr", "\u2978");
- builder.put("gtrdot", "\u22d7");
- builder.put("gtreqless", "\u22db");
- builder.put("gtreqqless", "\u2a8c");
- builder.put("gtrless", "\u2277");
- builder.put("gtrsim", "\u2273");
- builder.put("gvertneqq", "\u2269\ufe00");
- builder.put("gvnE", "\u2269\ufe00");
- builder.put("hArr", "\u21d4");
- builder.put("hairsp", "\u200a");
- builder.put("half", "\u00bd");
- builder.put("hamilt", "\u210b");
- builder.put("hardcy", "\u044a");
- builder.put("harr", "\u2194");
- builder.put("harrcir", "\u2948");
- builder.put("harrw", "\u21ad");
- builder.put("hbar", "\u210f");
- builder.put("hcirc", "\u0125");
- builder.put("hearts", "\u2665");
- builder.put("heartsuit", "\u2665");
- builder.put("hellip", "\u2026");
- builder.put("hercon", "\u22b9");
- builder.put("hfr", "\ud835\udd25");
- builder.put("hksearow", "\u2925");
- builder.put("hkswarow", "\u2926");
- builder.put("hoarr", "\u21ff");
- builder.put("homtht", "\u223b");
- builder.put("hookleftarrow", "\u21a9");
- builder.put("hookrightarrow", "\u21aa");
- builder.put("hopf", "\ud835\udd59");
- builder.put("horbar", "\u2015");
- builder.put("hscr", "\ud835\udcbd");
- builder.put("hslash", "\u210f");
- builder.put("hstrok", "\u0127");
- builder.put("hybull", "\u2043");
- builder.put("hyphen", "\u2010");
- builder.put("iacute", "\u00ed");
- builder.put("ic", "\u2063");
- builder.put("icirc", "\u00ee");
- builder.put("icy", "\u0438");
- builder.put("iecy", "\u0435");
- builder.put("iexcl", "\u00a1");
- builder.put("iff", "\u21d4");
- builder.put("ifr", "\ud835\udd26");
- builder.put("igrave", "\u00ec");
- builder.put("ii", "\u2148");
- builder.put("iiiint", "\u2a0c");
- builder.put("iiint", "\u222d");
- builder.put("iinfin", "\u29dc");
- builder.put("iiota", "\u2129");
- builder.put("ijlig", "\u0133");
- builder.put("imacr", "\u012b");
- builder.put("image", "\u2111");
- builder.put("imagline", "\u2110");
- builder.put("imagpart", "\u2111");
- builder.put("imath", "\u0131");
- builder.put("imof", "\u22b7");
- builder.put("imped", "\u01b5");
- builder.put("in", "\u2208");
- builder.put("incare", "\u2105");
- builder.put("infin", "\u221e");
- builder.put("infintie", "\u29dd");
- builder.put("inodot", "\u0131");
- builder.put("int", "\u222b");
- builder.put("intcal", "\u22ba");
- builder.put("integers", "\u2124");
- builder.put("intercal", "\u22ba");
- builder.put("intlarhk", "\u2a17");
- builder.put("intprod", "\u2a3c");
- builder.put("iocy", "\u0451");
- builder.put("iogon", "\u012f");
- builder.put("iopf", "\ud835\udd5a");
- builder.put("iota", "\u03b9");
- builder.put("iprod", "\u2a3c");
- builder.put("iquest", "\u00bf");
- builder.put("iscr", "\ud835\udcbe");
- builder.put("isin", "\u2208");
- builder.put("isinE", "\u22f9");
- builder.put("isindot", "\u22f5");
- builder.put("isins", "\u22f4");
- builder.put("isinsv", "\u22f3");
- builder.put("isinv", "\u2208");
- builder.put("it", "\u2062");
- builder.put("itilde", "\u0129");
- builder.put("iukcy", "\u0456");
- builder.put("iuml", "\u00ef");
- builder.put("jcirc", "\u0135");
- builder.put("jcy", "\u0439");
- builder.put("jfr", "\ud835\udd27");
- builder.put("jmath", "\u0237");
- builder.put("jopf", "\ud835\udd5b");
- builder.put("jscr", "\ud835\udcbf");
- builder.put("jsercy", "\u0458");
- builder.put("jukcy", "\u0454");
- builder.put("kappa", "\u03ba");
- builder.put("kappav", "\u03f0");
- builder.put("kcedil", "\u0137");
- builder.put("kcy", "\u043a");
- builder.put("kfr", "\ud835\udd28");
- builder.put("kgreen", "\u0138");
- builder.put("khcy", "\u0445");
- builder.put("kjcy", "\u045c");
- builder.put("kopf", "\ud835\udd5c");
- builder.put("kscr", "\ud835\udcc0");
- builder.put("lAarr", "\u21da");
- builder.put("lArr", "\u21d0");
- builder.put("lAtail", "\u291b");
- builder.put("lBarr", "\u290e");
- builder.put("lE", "\u2266");
- builder.put("lEg", "\u2a8b");
- builder.put("lHar", "\u2962");
- builder.put("lacute", "\u013a");
- builder.put("laemptyv", "\u29b4");
- builder.put("lagran", "\u2112");
- builder.put("lambda", "\u03bb");
- builder.put("lang", "\u27e8");
- builder.put("langd", "\u2991");
- builder.put("langle", "\u27e8");
- builder.put("lap", "\u2a85");
- builder.put("laquo", "\u00ab");
- builder.put("larr", "\u2190");
- builder.put("larrb", "\u21e4");
- builder.put("larrbfs", "\u291f");
- builder.put("larrfs", "\u291d");
- builder.put("larrhk", "\u21a9");
- builder.put("larrlp", "\u21ab");
- builder.put("larrpl", "\u2939");
- builder.put("larrsim", "\u2973");
- builder.put("larrtl", "\u21a2");
- builder.put("lat", "\u2aab");
- builder.put("latail", "\u2919");
- builder.put("late", "\u2aad");
- builder.put("lates", "\u2aad\ufe00");
- builder.put("lbarr", "\u290c");
- builder.put("lbbrk", "\u2772");
- builder.put("lbrace", "\u007b");
- builder.put("lbrack", "\u005b");
- builder.put("lbrke", "\u298b");
- builder.put("lbrksld", "\u298f");
- builder.put("lbrkslu", "\u298d");
- builder.put("lcaron", "\u013e");
- builder.put("lcedil", "\u013c");
- builder.put("lceil", "\u2308");
- builder.put("lcub", "\u007b");
- builder.put("lcy", "\u043b");
- builder.put("ldca", "\u2936");
- builder.put("ldquo", "\u201c");
- builder.put("ldquor", "\u201e");
- builder.put("ldrdhar", "\u2967");
- builder.put("ldrushar", "\u294b");
- builder.put("ldsh", "\u21b2");
- builder.put("le", "\u2264");
- builder.put("leftarrow", "\u2190");
- builder.put("leftarrowtail", "\u21a2");
- builder.put("leftharpoondown", "\u21bd");
- builder.put("leftharpoonup", "\u21bc");
- builder.put("leftleftarrows", "\u21c7");
- builder.put("leftrightarrow", "\u2194");
- builder.put("leftrightarrows", "\u21c6");
- builder.put("leftrightharpoons", "\u21cb");
- builder.put("leftrightsquigarrow", "\u21ad");
- builder.put("leftthreetimes", "\u22cb");
- builder.put("leg", "\u22da");
- builder.put("leq", "\u2264");
- builder.put("leqq", "\u2266");
- builder.put("leqslant", "\u2a7d");
- builder.put("les", "\u2a7d");
- builder.put("lescc", "\u2aa8");
- builder.put("lesdot", "\u2a7f");
- builder.put("lesdoto", "\u2a81");
- builder.put("lesdotor", "\u2a83");
- builder.put("lesg", "\u22da\ufe00");
- builder.put("lesges", "\u2a93");
- builder.put("lessapprox", "\u2a85");
- builder.put("lessdot", "\u22d6");
- builder.put("lesseqgtr", "\u22da");
- builder.put("lesseqqgtr", "\u2a8b");
- builder.put("lessgtr", "\u2276");
- builder.put("lesssim", "\u2272");
- builder.put("lfisht", "\u297c");
- builder.put("lfloor", "\u230a");
- builder.put("lfr", "\ud835\udd29");
- builder.put("lg", "\u2276");
- builder.put("lgE", "\u2a91");
- builder.put("lhard", "\u21bd");
- builder.put("lharu", "\u21bc");
- builder.put("lharul", "\u296a");
- builder.put("lhblk", "\u2584");
- builder.put("ljcy", "\u0459");
- builder.put("ll", "\u226a");
- builder.put("llarr", "\u21c7");
- builder.put("llcorner", "\u231e");
- builder.put("llhard", "\u296b");
- builder.put("lltri", "\u25fa");
- builder.put("lmidot", "\u0140");
- builder.put("lmoust", "\u23b0");
- builder.put("lmoustache", "\u23b0");
- builder.put("lnE", "\u2268");
- builder.put("lnap", "\u2a89");
- builder.put("lnapprox", "\u2a89");
- builder.put("lne", "\u2a87");
- builder.put("lneq", "\u2a87");
- builder.put("lneqq", "\u2268");
- builder.put("lnsim", "\u22e6");
- builder.put("loang", "\u27ec");
- builder.put("loarr", "\u21fd");
- builder.put("lobrk", "\u27e6");
- builder.put("longleftarrow", "\u27f5");
- builder.put("longleftrightarrow", "\u27f7");
- builder.put("longmapsto", "\u27fc");
- builder.put("longrightarrow", "\u27f6");
- builder.put("looparrowleft", "\u21ab");
- builder.put("looparrowright", "\u21ac");
- builder.put("lopar", "\u2985");
- builder.put("lopf", "\ud835\udd5d");
- builder.put("loplus", "\u2a2d");
- builder.put("lotimes", "\u2a34");
- builder.put("lowast", "\u2217");
- builder.put("lowbar", "\u005f");
- builder.put("loz", "\u25ca");
- builder.put("lozenge", "\u25ca");
- builder.put("lozf", "\u29eb");
- builder.put("lpar", "\u0028");
- builder.put("lparlt", "\u2993");
- builder.put("lrarr", "\u21c6");
- builder.put("lrcorner", "\u231f");
- builder.put("lrhar", "\u21cb");
- builder.put("lrhard", "\u296d");
- builder.put("lrm", "\u200e");
- builder.put("lrtri", "\u22bf");
- builder.put("lsaquo", "\u2039");
- builder.put("lscr", "\ud835\udcc1");
- builder.put("lsh", "\u21b0");
- builder.put("lsim", "\u2272");
- builder.put("lsime", "\u2a8d");
- builder.put("lsimg", "\u2a8f");
- builder.put("lsqb", "\u005b");
- builder.put("lsquo", "\u2018");
- builder.put("lsquor", "\u201a");
- builder.put("lstrok", "\u0142");
- builder.put("lt", "\u003c");
- builder.put("ltcc", "\u2aa6");
- builder.put("ltcir", "\u2a79");
- builder.put("ltdot", "\u22d6");
- builder.put("lthree", "\u22cb");
- builder.put("ltimes", "\u22c9");
- builder.put("ltlarr", "\u2976");
- builder.put("ltquest", "\u2a7b");
- builder.put("ltrPar", "\u2996");
- builder.put("ltri", "\u25c3");
- builder.put("ltrie", "\u22b4");
- builder.put("ltrif", "\u25c2");
- builder.put("lurdshar", "\u294a");
- builder.put("luruhar", "\u2966");
- builder.put("lvertneqq", "\u2268\ufe00");
- builder.put("lvnE", "\u2268\ufe00");
- builder.put("mDDot", "\u223a");
- builder.put("macr", "\u00af");
- builder.put("male", "\u2642");
- builder.put("malt", "\u2720");
- builder.put("maltese", "\u2720");
- builder.put("map", "\u21a6");
- builder.put("mapsto", "\u21a6");
- builder.put("mapstodown", "\u21a7");
- builder.put("mapstoleft", "\u21a4");
- builder.put("mapstoup", "\u21a5");
- builder.put("marker", "\u25ae");
- builder.put("mcomma", "\u2a29");
- builder.put("mcy", "\u043c");
- builder.put("mdash", "\u2014");
- builder.put("measuredangle", "\u2221");
- builder.put("mfr", "\ud835\udd2a");
- builder.put("mho", "\u2127");
- builder.put("micro", "\u00b5");
- builder.put("mid", "\u2223");
- builder.put("midast", "\u002a");
- builder.put("midcir", "\u2af0");
- builder.put("middot", "\u00b7");
- builder.put("minus", "\u2212");
- builder.put("minusb", "\u229f");
- builder.put("minusd", "\u2238");
- builder.put("minusdu", "\u2a2a");
- builder.put("mlcp", "\u2adb");
- builder.put("mldr", "\u2026");
- builder.put("mnplus", "\u2213");
- builder.put("models", "\u22a7");
- builder.put("mopf", "\ud835\udd5e");
- builder.put("mp", "\u2213");
- builder.put("mscr", "\ud835\udcc2");
- builder.put("mstpos", "\u223e");
- builder.put("mu", "\u03bc");
- builder.put("multimap", "\u22b8");
- builder.put("mumap", "\u22b8");
- builder.put("nGg", "\u22d9\u0338");
- builder.put("nGt", "\u226b\u20d2");
- builder.put("nGtv", "\u226b\u0338");
- builder.put("nLeftarrow", "\u21cd");
- builder.put("nLeftrightarrow", "\u21ce");
- builder.put("nLl", "\u22d8\u0338");
- builder.put("nLt", "\u226a\u20d2");
- builder.put("nLtv", "\u226a\u0338");
- builder.put("nRightarrow", "\u21cf");
- builder.put("nVDash", "\u22af");
- builder.put("nVdash", "\u22ae");
- builder.put("nabla", "\u2207");
- builder.put("nacute", "\u0144");
- builder.put("nang", "\u2220\u20d2");
- builder.put("nap", "\u2249");
- builder.put("napE", "\u2a70\u0338");
- builder.put("napid", "\u224b\u0338");
- builder.put("napos", "\u0149");
- builder.put("napprox", "\u2249");
- builder.put("natur", "\u266e");
- builder.put("natural", "\u266e");
- builder.put("naturals", "\u2115");
- builder.put("nbsp", "\u00a0");
- builder.put("nbump", "\u224e\u0338");
- builder.put("nbumpe", "\u224f\u0338");
- builder.put("ncap", "\u2a43");
- builder.put("ncaron", "\u0148");
- builder.put("ncedil", "\u0146");
- builder.put("ncong", "\u2247");
- builder.put("ncongdot", "\u2a6d\u0338");
- builder.put("ncup", "\u2a42");
- builder.put("ncy", "\u043d");
- builder.put("ndash", "\u2013");
- builder.put("ne", "\u2260");
- builder.put("neArr", "\u21d7");
- builder.put("nearhk", "\u2924");
- builder.put("nearr", "\u2197");
- builder.put("nearrow", "\u2197");
- builder.put("nedot", "\u2250\u0338");
- builder.put("nequiv", "\u2262");
- builder.put("nesear", "\u2928");
- builder.put("nesim", "\u2242\u0338");
- builder.put("nexist", "\u2204");
- builder.put("nexists", "\u2204");
- builder.put("nfr", "\ud835\udd2b");
- builder.put("ngE", "\u2267\u0338");
- builder.put("nge", "\u2271");
- builder.put("ngeq", "\u2271");
- builder.put("ngeqq", "\u2267\u0338");
- builder.put("ngeqslant", "\u2a7e\u0338");
- builder.put("nges", "\u2a7e\u0338");
- builder.put("ngsim", "\u2275");
- builder.put("ngt", "\u226f");
- builder.put("ngtr", "\u226f");
- builder.put("nhArr", "\u21ce");
- builder.put("nharr", "\u21ae");
- builder.put("nhpar", "\u2af2");
- builder.put("ni", "\u220b");
- builder.put("nis", "\u22fc");
- builder.put("nisd", "\u22fa");
- builder.put("niv", "\u220b");
- builder.put("njcy", "\u045a");
- builder.put("nlArr", "\u21cd");
- builder.put("nlE", "\u2266\u0338");
- builder.put("nlarr", "\u219a");
- builder.put("nldr", "\u2025");
- builder.put("nle", "\u2270");
- builder.put("nleftarrow", "\u219a");
- builder.put("nleftrightarrow", "\u21ae");
- builder.put("nleq", "\u2270");
- builder.put("nleqq", "\u2266\u0338");
- builder.put("nleqslant", "\u2a7d\u0338");
- builder.put("nles", "\u2a7d\u0338");
- builder.put("nless", "\u226e");
- builder.put("nlsim", "\u2274");
- builder.put("nlt", "\u226e");
- builder.put("nltri", "\u22ea");
- builder.put("nltrie", "\u22ec");
- builder.put("nmid", "\u2224");
- builder.put("nopf", "\ud835\udd5f");
- builder.put("not", "\u00ac");
- builder.put("notin", "\u2209");
- builder.put("notinE", "\u22f9\u0338");
- builder.put("notindot", "\u22f5\u0338");
- builder.put("notinva", "\u2209");
- builder.put("notinvb", "\u22f7");
- builder.put("notinvc", "\u22f6");
- builder.put("notni", "\u220c");
- builder.put("notniva", "\u220c");
- builder.put("notnivb", "\u22fe");
- builder.put("notnivc", "\u22fd");
- builder.put("npar", "\u2226");
- builder.put("nparallel", "\u2226");
- builder.put("nparsl", "\u2afd\u20e5");
- builder.put("npart", "\u2202\u0338");
- builder.put("npolint", "\u2a14");
- builder.put("npr", "\u2280");
- builder.put("nprcue", "\u22e0");
- builder.put("npre", "\u2aaf\u0338");
- builder.put("nprec", "\u2280");
- builder.put("npreceq", "\u2aaf\u0338");
- builder.put("nrArr", "\u21cf");
- builder.put("nrarr", "\u219b");
- builder.put("nrarrc", "\u2933\u0338");
- builder.put("nrarrw", "\u219d\u0338");
- builder.put("nrightarrow", "\u219b");
- builder.put("nrtri", "\u22eb");
- builder.put("nrtrie", "\u22ed");
- builder.put("nsc", "\u2281");
- builder.put("nsccue", "\u22e1");
- builder.put("nsce", "\u2ab0\u0338");
- builder.put("nscr", "\ud835\udcc3");
- builder.put("nshortmid", "\u2224");
- builder.put("nshortparallel", "\u2226");
- builder.put("nsim", "\u2241");
- builder.put("nsime", "\u2244");
- builder.put("nsimeq", "\u2244");
- builder.put("nsmid", "\u2224");
- builder.put("nspar", "\u2226");
- builder.put("nsqsube", "\u22e2");
- builder.put("nsqsupe", "\u22e3");
- builder.put("nsub", "\u2284");
- builder.put("nsubE", "\u2ac5\u0338");
- builder.put("nsube", "\u2288");
- builder.put("nsubset", "\u2282\u20d2");
- builder.put("nsubseteq", "\u2288");
- builder.put("nsubseteqq", "\u2ac5\u0338");
- builder.put("nsucc", "\u2281");
- builder.put("nsucceq", "\u2ab0\u0338");
- builder.put("nsup", "\u2285");
- builder.put("nsupE", "\u2ac6\u0338");
- builder.put("nsupe", "\u2289");
- builder.put("nsupset", "\u2283\u20d2");
- builder.put("nsupseteq", "\u2289");
- builder.put("nsupseteqq", "\u2ac6\u0338");
- builder.put("ntgl", "\u2279");
- builder.put("ntilde", "\u00f1");
- builder.put("ntlg", "\u2278");
- builder.put("ntriangleleft", "\u22ea");
- builder.put("ntrianglelefteq", "\u22ec");
- builder.put("ntriangleright", "\u22eb");
- builder.put("ntrianglerighteq", "\u22ed");
- builder.put("nu", "\u03bd");
- builder.put("num", "\u0023");
- builder.put("numero", "\u2116");
- builder.put("numsp", "\u2007");
- builder.put("nvDash", "\u22ad");
- builder.put("nvHarr", "\u2904");
- builder.put("nvap", "\u224d\u20d2");
- builder.put("nvdash", "\u22ac");
- builder.put("nvge", "\u2265\u20d2");
- builder.put("nvgt", "\u003e\u20d2");
- builder.put("nvinfin", "\u29de");
- builder.put("nvlArr", "\u2902");
- builder.put("nvle", "\u2264\u20d2");
- builder.put("nvlt", "\u003c\u20d2");
- builder.put("nvltrie", "\u22b4\u20d2");
- builder.put("nvrArr", "\u2903");
- builder.put("nvrtrie", "\u22b5\u20d2");
- builder.put("nvsim", "\u223c\u20d2");
- builder.put("nwArr", "\u21d6");
- builder.put("nwarhk", "\u2923");
- builder.put("nwarr", "\u2196");
- builder.put("nwarrow", "\u2196");
- builder.put("nwnear", "\u2927");
- builder.put("oS", "\u24c8");
- builder.put("oacute", "\u00f3");
- builder.put("oast", "\u229b");
- builder.put("ocir", "\u229a");
- builder.put("ocirc", "\u00f4");
- builder.put("ocy", "\u043e");
- builder.put("odash", "\u229d");
- builder.put("odblac", "\u0151");
- builder.put("odiv", "\u2a38");
- builder.put("odot", "\u2299");
- builder.put("odsold", "\u29bc");
- builder.put("oelig", "\u0153");
- builder.put("ofcir", "\u29bf");
- builder.put("ofr", "\ud835\udd2c");
- builder.put("ogon", "\u02db");
- builder.put("ograve", "\u00f2");
- builder.put("ogt", "\u29c1");
- builder.put("ohbar", "\u29b5");
- builder.put("ohm", "\u03a9");
- builder.put("oint", "\u222e");
- builder.put("olarr", "\u21ba");
- builder.put("olcir", "\u29be");
- builder.put("olcross", "\u29bb");
- builder.put("oline", "\u203e");
- builder.put("olt", "\u29c0");
- builder.put("omacr", "\u014d");
- builder.put("omega", "\u03c9");
- builder.put("omicron", "\u03bf");
- builder.put("omid", "\u29b6");
- builder.put("ominus", "\u2296");
- builder.put("oopf", "\ud835\udd60");
- builder.put("opar", "\u29b7");
- builder.put("operp", "\u29b9");
- builder.put("oplus", "\u2295");
- builder.put("or", "\u2228");
- builder.put("orarr", "\u21bb");
- builder.put("ord", "\u2a5d");
- builder.put("order", "\u2134");
- builder.put("orderof", "\u2134");
- builder.put("ordf", "\u00aa");
- builder.put("ordm", "\u00ba");
- builder.put("origof", "\u22b6");
- builder.put("oror", "\u2a56");
- builder.put("orslope", "\u2a57");
- builder.put("orv", "\u2a5b");
- builder.put("oscr", "\u2134");
- builder.put("oslash", "\u00f8");
- builder.put("osol", "\u2298");
- builder.put("otilde", "\u00f5");
- builder.put("otimes", "\u2297");
- builder.put("otimesas", "\u2a36");
- builder.put("ouml", "\u00f6");
- builder.put("ovbar", "\u233d");
- builder.put("par", "\u2225");
- builder.put("para", "\u00b6");
- builder.put("parallel", "\u2225");
- builder.put("parsim", "\u2af3");
- builder.put("parsl", "\u2afd");
- builder.put("part", "\u2202");
- builder.put("pcy", "\u043f");
- builder.put("percnt", "\u0025");
- builder.put("period", "\u002e");
- builder.put("permil", "\u2030");
- builder.put("perp", "\u22a5");
- builder.put("pertenk", "\u2031");
- builder.put("pfr", "\ud835\udd2d");
- builder.put("phi", "\u03c6");
- builder.put("phiv", "\u03d5");
- builder.put("phmmat", "\u2133");
- builder.put("phone", "\u260e");
- builder.put("pi", "\u03c0");
- builder.put("pitchfork", "\u22d4");
- builder.put("piv", "\u03d6");
- builder.put("planck", "\u210f");
- builder.put("planckh", "\u210e");
- builder.put("plankv", "\u210f");
- builder.put("plus", "\u002b");
- builder.put("plusacir", "\u2a23");
- builder.put("plusb", "\u229e");
- builder.put("pluscir", "\u2a22");
- builder.put("plusdo", "\u2214");
- builder.put("plusdu", "\u2a25");
- builder.put("pluse", "\u2a72");
- builder.put("plusmn", "\u00b1");
- builder.put("plussim", "\u2a26");
- builder.put("plustwo", "\u2a27");
- builder.put("pm", "\u00b1");
- builder.put("pointint", "\u2a15");
- builder.put("popf", "\ud835\udd61");
- builder.put("pound", "\u00a3");
- builder.put("pr", "\u227a");
- builder.put("prE", "\u2ab3");
- builder.put("prap", "\u2ab7");
- builder.put("prcue", "\u227c");
- builder.put("pre", "\u2aaf");
- builder.put("prec", "\u227a");
- builder.put("precapprox", "\u2ab7");
- builder.put("preccurlyeq", "\u227c");
- builder.put("preceq", "\u2aaf");
- builder.put("precnapprox", "\u2ab9");
- builder.put("precneqq", "\u2ab5");
- builder.put("precnsim", "\u22e8");
- builder.put("precsim", "\u227e");
- builder.put("prime", "\u2032");
- builder.put("primes", "\u2119");
- builder.put("prnE", "\u2ab5");
- builder.put("prnap", "\u2ab9");
- builder.put("prnsim", "\u22e8");
- builder.put("prod", "\u220f");
- builder.put("profalar", "\u232e");
- builder.put("profline", "\u2312");
- builder.put("profsurf", "\u2313");
- builder.put("prop", "\u221d");
- builder.put("propto", "\u221d");
- builder.put("prsim", "\u227e");
- builder.put("prurel", "\u22b0");
- builder.put("pscr", "\ud835\udcc5");
- builder.put("psi", "\u03c8");
- builder.put("puncsp", "\u2008");
- builder.put("qfr", "\ud835\udd2e");
- builder.put("qint", "\u2a0c");
- builder.put("qopf", "\ud835\udd62");
- builder.put("qprime", "\u2057");
- builder.put("qscr", "\ud835\udcc6");
- builder.put("quaternions", "\u210d");
- builder.put("quatint", "\u2a16");
- builder.put("quest", "\u003f");
- builder.put("questeq", "\u225f");
- builder.put("quot", "\"");
- builder.put("rAarr", "\u21db");
- builder.put("rArr", "\u21d2");
- builder.put("rAtail", "\u291c");
- builder.put("rBarr", "\u290f");
- builder.put("rHar", "\u2964");
- builder.put("race", "\u223d\u0331");
- builder.put("racute", "\u0155");
- builder.put("radic", "\u221a");
- builder.put("raemptyv", "\u29b3");
- builder.put("rang", "\u27e9");
- builder.put("rangd", "\u2992");
- builder.put("range", "\u29a5");
- builder.put("rangle", "\u27e9");
- builder.put("raquo", "\u00bb");
- builder.put("rarr", "\u2192");
- builder.put("rarrap", "\u2975");
- builder.put("rarrb", "\u21e5");
- builder.put("rarrbfs", "\u2920");
- builder.put("rarrc", "\u2933");
- builder.put("rarrfs", "\u291e");
- builder.put("rarrhk", "\u21aa");
- builder.put("rarrlp", "\u21ac");
- builder.put("rarrpl", "\u2945");
- builder.put("rarrsim", "\u2974");
- builder.put("rarrtl", "\u21a3");
- builder.put("rarrw", "\u219d");
- builder.put("ratail", "\u291a");
- builder.put("ratio", "\u2236");
- builder.put("rationals", "\u211a");
- builder.put("rbarr", "\u290d");
- builder.put("rbbrk", "\u2773");
- builder.put("rbrace", "\u007d");
- builder.put("rbrack", "\u005d");
- builder.put("rbrke", "\u298c");
- builder.put("rbrksld", "\u298e");
- builder.put("rbrkslu", "\u2990");
- builder.put("rcaron", "\u0159");
- builder.put("rcedil", "\u0157");
- builder.put("rceil", "\u2309");
- builder.put("rcub", "\u007d");
- builder.put("rcy", "\u0440");
- builder.put("rdca", "\u2937");
- builder.put("rdldhar", "\u2969");
- builder.put("rdquo", "\u201d");
- builder.put("rdquor", "\u201d");
- builder.put("rdsh", "\u21b3");
- builder.put("real", "\u211c");
- builder.put("realine", "\u211b");
- builder.put("realpart", "\u211c");
- builder.put("reals", "\u211d");
- builder.put("rect", "\u25ad");
- builder.put("reg", "\u00ae");
- builder.put("rfisht", "\u297d");
- builder.put("rfloor", "\u230b");
- builder.put("rfr", "\ud835\udd2f");
- builder.put("rhard", "\u21c1");
- builder.put("rharu", "\u21c0");
- builder.put("rharul", "\u296c");
- builder.put("rho", "\u03c1");
- builder.put("rhov", "\u03f1");
- builder.put("rightarrow", "\u2192");
- builder.put("rightarrowtail", "\u21a3");
- builder.put("rightharpoondown", "\u21c1");
- builder.put("rightharpoonup", "\u21c0");
- builder.put("rightleftarrows", "\u21c4");
- builder.put("rightleftharpoons", "\u21cc");
- builder.put("rightrightarrows", "\u21c9");
- builder.put("rightsquigarrow", "\u219d");
- builder.put("rightthreetimes", "\u22cc");
- builder.put("ring", "\u02da");
- builder.put("risingdotseq", "\u2253");
- builder.put("rlarr", "\u21c4");
- builder.put("rlhar", "\u21cc");
- builder.put("rlm", "\u200f");
- builder.put("rmoust", "\u23b1");
- builder.put("rmoustache", "\u23b1");
- builder.put("rnmid", "\u2aee");
- builder.put("roang", "\u27ed");
- builder.put("roarr", "\u21fe");
- builder.put("robrk", "\u27e7");
- builder.put("ropar", "\u2986");
- builder.put("ropf", "\ud835\udd63");
- builder.put("roplus", "\u2a2e");
- builder.put("rotimes", "\u2a35");
- builder.put("rpar", "\u0029");
- builder.put("rpargt", "\u2994");
- builder.put("rppolint", "\u2a12");
- builder.put("rrarr", "\u21c9");
- builder.put("rsaquo", "\u203a");
- builder.put("rscr", "\ud835\udcc7");
- builder.put("rsh", "\u21b1");
- builder.put("rsqb", "\u005d");
- builder.put("rsquo", "\u2019");
- builder.put("rsquor", "\u2019");
- builder.put("rthree", "\u22cc");
- builder.put("rtimes", "\u22ca");
- builder.put("rtri", "\u25b9");
- builder.put("rtrie", "\u22b5");
- builder.put("rtrif", "\u25b8");
- builder.put("rtriltri", "\u29ce");
- builder.put("ruluhar", "\u2968");
- builder.put("rx", "\u211e");
- builder.put("sacute", "\u015b");
- builder.put("sbquo", "\u201a");
- builder.put("sc", "\u227b");
- builder.put("scE", "\u2ab4");
- builder.put("scap", "\u2ab8");
- builder.put("scaron", "\u0161");
- builder.put("sccue", "\u227d");
- builder.put("sce", "\u2ab0");
- builder.put("scedil", "\u015f");
- builder.put("scirc", "\u015d");
- builder.put("scnE", "\u2ab6");
- builder.put("scnap", "\u2aba");
- builder.put("scnsim", "\u22e9");
- builder.put("scpolint", "\u2a13");
- builder.put("scsim", "\u227f");
- builder.put("scy", "\u0441");
- builder.put("sdot", "\u22c5");
- builder.put("sdotb", "\u22a1");
- builder.put("sdote", "\u2a66");
- builder.put("seArr", "\u21d8");
- builder.put("searhk", "\u2925");
- builder.put("searr", "\u2198");
- builder.put("searrow", "\u2198");
- builder.put("sect", "\u00a7");
- builder.put("semi", "\u003b");
- builder.put("seswar", "\u2929");
- builder.put("setminus", "\u2216");
- builder.put("setmn", "\u2216");
- builder.put("sext", "\u2736");
- builder.put("sfr", "\ud835\udd30");
- builder.put("sfrown", "\u2322");
- builder.put("sharp", "\u266f");
- builder.put("shchcy", "\u0449");
- builder.put("shcy", "\u0448");
- builder.put("shortmid", "\u2223");
- builder.put("shortparallel", "\u2225");
- builder.put("shy", "\u00ad");
- builder.put("sigma", "\u03c3");
- builder.put("sigmaf", "\u03c2");
- builder.put("sigmav", "\u03c2");
- builder.put("sim", "\u223c");
- builder.put("simdot", "\u2a6a");
- builder.put("sime", "\u2243");
- builder.put("simeq", "\u2243");
- builder.put("simg", "\u2a9e");
- builder.put("simgE", "\u2aa0");
- builder.put("siml", "\u2a9d");
- builder.put("simlE", "\u2a9f");
- builder.put("simne", "\u2246");
- builder.put("simplus", "\u2a24");
- builder.put("simrarr", "\u2972");
- builder.put("slarr", "\u2190");
- builder.put("smallsetminus", "\u2216");
- builder.put("smashp", "\u2a33");
- builder.put("smeparsl", "\u29e4");
- builder.put("smid", "\u2223");
- builder.put("smile", "\u2323");
- builder.put("smt", "\u2aaa");
- builder.put("smte", "\u2aac");
- builder.put("smtes", "\u2aac\ufe00");
- builder.put("softcy", "\u044c");
- builder.put("sol", "\u002f");
- builder.put("solb", "\u29c4");
- builder.put("solbar", "\u233f");
- builder.put("sopf", "\ud835\udd64");
- builder.put("spades", "\u2660");
- builder.put("spadesuit", "\u2660");
- builder.put("spar", "\u2225");
- builder.put("sqcap", "\u2293");
- builder.put("sqcaps", "\u2293\ufe00");
- builder.put("sqcup", "\u2294");
- builder.put("sqcups", "\u2294\ufe00");
- builder.put("sqsub", "\u228f");
- builder.put("sqsube", "\u2291");
- builder.put("sqsubset", "\u228f");
- builder.put("sqsubseteq", "\u2291");
- builder.put("sqsup", "\u2290");
- builder.put("sqsupe", "\u2292");
- builder.put("sqsupset", "\u2290");
- builder.put("sqsupseteq", "\u2292");
- builder.put("squ", "\u25a1");
- builder.put("square", "\u25a1");
- builder.put("squarf", "\u25aa");
- builder.put("squf", "\u25aa");
- builder.put("srarr", "\u2192");
- builder.put("sscr", "\ud835\udcc8");
- builder.put("ssetmn", "\u2216");
- builder.put("ssmile", "\u2323");
- builder.put("sstarf", "\u22c6");
- builder.put("star", "\u2606");
- builder.put("starf", "\u2605");
- builder.put("straightepsilon", "\u03f5");
- builder.put("straightphi", "\u03d5");
- builder.put("strns", "\u00af");
- builder.put("sub", "\u2282");
- builder.put("subE", "\u2ac5");
- builder.put("subdot", "\u2abd");
- builder.put("sube", "\u2286");
- builder.put("subedot", "\u2ac3");
- builder.put("submult", "\u2ac1");
- builder.put("subnE", "\u2acb");
- builder.put("subne", "\u228a");
- builder.put("subplus", "\u2abf");
- builder.put("subrarr", "\u2979");
- builder.put("subset", "\u2282");
- builder.put("subseteq", "\u2286");
- builder.put("subseteqq", "\u2ac5");
- builder.put("subsetneq", "\u228a");
- builder.put("subsetneqq", "\u2acb");
- builder.put("subsim", "\u2ac7");
- builder.put("subsub", "\u2ad5");
- builder.put("subsup", "\u2ad3");
- builder.put("succ", "\u227b");
- builder.put("succapprox", "\u2ab8");
- builder.put("succcurlyeq", "\u227d");
- builder.put("succeq", "\u2ab0");
- builder.put("succnapprox", "\u2aba");
- builder.put("succneqq", "\u2ab6");
- builder.put("succnsim", "\u22e9");
- builder.put("succsim", "\u227f");
- builder.put("sum", "\u2211");
- builder.put("sung", "\u266a");
- builder.put("sup1", "\u00b9");
- builder.put("sup2", "\u00b2");
- builder.put("sup3", "\u00b3");
- builder.put("sup", "\u2283");
- builder.put("supE", "\u2ac6");
- builder.put("supdot", "\u2abe");
- builder.put("supdsub", "\u2ad8");
- builder.put("supe", "\u2287");
- builder.put("supedot", "\u2ac4");
- builder.put("suphsol", "\u27c9");
- builder.put("suphsub", "\u2ad7");
- builder.put("suplarr", "\u297b");
- builder.put("supmult", "\u2ac2");
- builder.put("supnE", "\u2acc");
- builder.put("supne", "\u228b");
- builder.put("supplus", "\u2ac0");
- builder.put("supset", "\u2283");
- builder.put("supseteq", "\u2287");
- builder.put("supseteqq", "\u2ac6");
- builder.put("supsetneq", "\u228b");
- builder.put("supsetneqq", "\u2acc");
- builder.put("supsim", "\u2ac8");
- builder.put("supsub", "\u2ad4");
- builder.put("supsup", "\u2ad6");
- builder.put("swArr", "\u21d9");
- builder.put("swarhk", "\u2926");
- builder.put("swarr", "\u2199");
- builder.put("swarrow", "\u2199");
- builder.put("swnwar", "\u292a");
- builder.put("szlig", "\u00df");
- builder.put("target", "\u2316");
- builder.put("tau", "\u03c4");
- builder.put("tbrk", "\u23b4");
- builder.put("tcaron", "\u0165");
- builder.put("tcedil", "\u0163");
- builder.put("tcy", "\u0442");
- builder.put("tdot", "\u20db");
- builder.put("telrec", "\u2315");
- builder.put("tfr", "\ud835\udd31");
- builder.put("there4", "\u2234");
- builder.put("therefore", "\u2234");
- builder.put("theta", "\u03b8");
- builder.put("thetasym", "\u03d1");
- builder.put("thetav", "\u03d1");
- builder.put("thickapprox", "\u2248");
- builder.put("thicksim", "\u223c");
- builder.put("thinsp", "\u2009");
- builder.put("thkap", "\u2248");
- builder.put("thksim", "\u223c");
- builder.put("thorn", "\u00fe");
- builder.put("tilde", "\u02dc");
- builder.put("times", "\u00d7");
- builder.put("timesb", "\u22a0");
- builder.put("timesbar", "\u2a31");
- builder.put("timesd", "\u2a30");
- builder.put("tint", "\u222d");
- builder.put("toea", "\u2928");
- builder.put("top", "\u22a4");
- builder.put("topbot", "\u2336");
- builder.put("topcir", "\u2af1");
- builder.put("topf", "\ud835\udd65");
- builder.put("topfork", "\u2ada");
- builder.put("tosa", "\u2929");
- builder.put("tprime", "\u2034");
- builder.put("trade", "\u2122");
- builder.put("triangle", "\u25b5");
- builder.put("triangledown", "\u25bf");
- builder.put("triangleleft", "\u25c3");
- builder.put("trianglelefteq", "\u22b4");
- builder.put("triangleq", "\u225c");
- builder.put("triangleright", "\u25b9");
- builder.put("trianglerighteq", "\u22b5");
- builder.put("tridot", "\u25ec");
- builder.put("trie", "\u225c");
- builder.put("triminus", "\u2a3a");
- builder.put("triplus", "\u2a39");
- builder.put("trisb", "\u29cd");
- builder.put("tritime", "\u2a3b");
- builder.put("trpezium", "\u23e2");
- builder.put("tscr", "\ud835\udcc9");
- builder.put("tscy", "\u0446");
- builder.put("tshcy", "\u045b");
- builder.put("tstrok", "\u0167");
- builder.put("twixt", "\u226c");
- builder.put("twoheadleftarrow", "\u219e");
- builder.put("twoheadrightarrow", "\u21a0");
- builder.put("uArr", "\u21d1");
- builder.put("uHar", "\u2963");
- builder.put("uacute", "\u00fa");
- builder.put("uarr", "\u2191");
- builder.put("ubrcy", "\u045e");
- builder.put("ubreve", "\u016d");
- builder.put("ucirc", "\u00fb");
- builder.put("ucy", "\u0443");
- builder.put("udarr", "\u21c5");
- builder.put("udblac", "\u0171");
- builder.put("udhar", "\u296e");
- builder.put("ufisht", "\u297e");
- builder.put("ufr", "\ud835\udd32");
- builder.put("ugrave", "\u00f9");
- builder.put("uharl", "\u21bf");
- builder.put("uharr", "\u21be");
- builder.put("uhblk", "\u2580");
- builder.put("ulcorn", "\u231c");
- builder.put("ulcorner", "\u231c");
- builder.put("ulcrop", "\u230f");
- builder.put("ultri", "\u25f8");
- builder.put("umacr", "\u016b");
- builder.put("uml", "\u00a8");
- builder.put("uogon", "\u0173");
- builder.put("uopf", "\ud835\udd66");
- builder.put("uparrow", "\u2191");
- builder.put("updownarrow", "\u2195");
- builder.put("upharpoonleft", "\u21bf");
- builder.put("upharpoonright", "\u21be");
- builder.put("uplus", "\u228e");
- builder.put("upsi", "\u03c5");
- builder.put("upsih", "\u03d2");
- builder.put("upsilon", "\u03c5");
- builder.put("upuparrows", "\u21c8");
- builder.put("urcorn", "\u231d");
- builder.put("urcorner", "\u231d");
- builder.put("urcrop", "\u230e");
- builder.put("uring", "\u016f");
- builder.put("urtri", "\u25f9");
- builder.put("uscr", "\ud835\udcca");
- builder.put("utdot", "\u22f0");
- builder.put("utilde", "\u0169");
- builder.put("utri", "\u25b5");
- builder.put("utrif", "\u25b4");
- builder.put("uuarr", "\u21c8");
- builder.put("uuml", "\u00fc");
- builder.put("uwangle", "\u29a7");
- builder.put("vArr", "\u21d5");
- builder.put("vBar", "\u2ae8");
- builder.put("vBarv", "\u2ae9");
- builder.put("vDash", "\u22a8");
- builder.put("vangrt", "\u299c");
- builder.put("varepsilon", "\u03f5");
- builder.put("varkappa", "\u03f0");
- builder.put("varnothing", "\u2205");
- builder.put("varphi", "\u03d5");
- builder.put("varpi", "\u03d6");
- builder.put("varpropto", "\u221d");
- builder.put("varr", "\u2195");
- builder.put("varrho", "\u03f1");
- builder.put("varsigma", "\u03c2");
- builder.put("varsubsetneq", "\u228a\ufe00");
- builder.put("varsubsetneqq", "\u2acb\ufe00");
- builder.put("varsupsetneq", "\u228b\ufe00");
- builder.put("varsupsetneqq", "\u2acc\ufe00");
- builder.put("vartheta", "\u03d1");
- builder.put("vartriangleleft", "\u22b2");
- builder.put("vartriangleright", "\u22b3");
- builder.put("vcy", "\u0432");
- builder.put("vdash", "\u22a2");
- builder.put("vee", "\u2228");
- builder.put("veebar", "\u22bb");
- builder.put("veeeq", "\u225a");
- builder.put("vellip", "\u22ee");
- builder.put("verbar", "\u007c");
- builder.put("vert", "\u007c");
- builder.put("vfr", "\ud835\udd33");
- builder.put("vltri", "\u22b2");
- builder.put("vnsub", "\u2282\u20d2");
- builder.put("vnsup", "\u2283\u20d2");
- builder.put("vopf", "\ud835\udd67");
- builder.put("vprop", "\u221d");
- builder.put("vrtri", "\u22b3");
- builder.put("vscr", "\ud835\udccb");
- builder.put("vsubnE", "\u2acb\ufe00");
- builder.put("vsubne", "\u228a\ufe00");
- builder.put("vsupnE", "\u2acc\ufe00");
- builder.put("vsupne", "\u228b\ufe00");
- builder.put("vzigzag", "\u299a");
- builder.put("wcirc", "\u0175");
- builder.put("wedbar", "\u2a5f");
- builder.put("wedge", "\u2227");
- builder.put("wedgeq", "\u2259");
- builder.put("weierp", "\u2118");
- builder.put("wfr", "\ud835\udd34");
- builder.put("wopf", "\ud835\udd68");
- builder.put("wp", "\u2118");
- builder.put("wr", "\u2240");
- builder.put("wreath", "\u2240");
- builder.put("wscr", "\ud835\udccc");
- builder.put("xcap", "\u22c2");
- builder.put("xcirc", "\u25ef");
- builder.put("xcup", "\u22c3");
- builder.put("xdtri", "\u25bd");
- builder.put("xfr", "\ud835\udd35");
- builder.put("xhArr", "\u27fa");
- builder.put("xharr", "\u27f7");
- builder.put("xi", "\u03be");
- builder.put("xlArr", "\u27f8");
- builder.put("xlarr", "\u27f5");
- builder.put("xmap", "\u27fc");
- builder.put("xnis", "\u22fb");
- builder.put("xodot", "\u2a00");
- builder.put("xopf", "\ud835\udd69");
- builder.put("xoplus", "\u2a01");
- builder.put("xotime", "\u2a02");
- builder.put("xrArr", "\u27f9");
- builder.put("xrarr", "\u27f6");
- builder.put("xscr", "\ud835\udccd");
- builder.put("xsqcup", "\u2a06");
- builder.put("xuplus", "\u2a04");
- builder.put("xutri", "\u25b3");
- builder.put("xvee", "\u22c1");
- builder.put("xwedge", "\u22c0");
- builder.put("yacute", "\u00fd");
- builder.put("yacy", "\u044f");
- builder.put("ycirc", "\u0177");
- builder.put("ycy", "\u044b");
- builder.put("yen", "\u00a5");
- builder.put("yfr", "\ud835\udd36");
- builder.put("yicy", "\u0457");
- builder.put("yopf", "\ud835\udd6a");
- builder.put("yscr", "\ud835\udcce");
- builder.put("yucy", "\u044e");
- builder.put("yuml", "\u00ff");
- builder.put("zacute", "\u017a");
- builder.put("zcaron", "\u017e");
- builder.put("zcy", "\u0437");
- builder.put("zdot", "\u017c");
- builder.put("zeetrf", "\u2128");
- builder.put("zeta", "\u03b6");
- builder.put("zfr", "\ud835\udd37");
- builder.put("zhcy", "\u0436");
- builder.put("zigrarr", "\u21dd");
- builder.put("zopf", "\ud835\udd6b");
- builder.put("zscr", "\ud835\udccf");
- builder.put("zwj", "\u200d");
- builder.put("zwnj", "\u200c");
-
- final Map<String, String> entityNameToCodePointMap = builder.build();
+ final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
int longestEntityName = 0;
- for (String entityName : entityNameToCodePointMap.keySet()) {
+ for (int i = 0, n = pairs.length; i < n; i += 2) {
+ String entityName = pairs[i];
+ String encodedText = pairs[i + 1];
+ builder.put(entityName, encodedText);
if (entityName.length() > longestEntityName) {
longestEntityName = entityName.length();
}
}
+ final Map<String, String> entityNameToCodePointMap = builder.build();
+
ENTITY_TRIE = new Trie<String>(entityNameToCodePointMap);
LONGEST_ENTITY_NAME = longestEntityName;
}
+ /**
+ * Decodes any HTML entity at the given location and appends it to a string
+ * builder. This handles both named and numeric entities.
+ *
+ * @param html HTML text.
+ * @param offset the position of the sequence to decode in {@code html}.
+ * @param limit the last position that could be part of the sequence to decode
+ * in {@code html}.
+ * @param sb string builder to append to.
+ * @return The offset after the end of the decoded sequence in {@code html}.
+ * @deprecated specify whether html is in an attribute value.
+ */
+ public static int appendDecodedEntity(
+ String html, int offset, int limit, StringBuilder sb) {
+ return appendDecodedEntity(html, offset, limit, false, sb);
+ }
+
/**
* Decodes any HTML entity at the given location and appends it to a string
* builder. This handles both named and numeric entities.
@@ -2198,74 +2326,49 @@ final class HtmlEntities {
* @return The offset after the end of the decoded sequence in {@code html}.
*/
public static int appendDecodedEntity(
- String html, int offset, int limit, StringBuilder sb) {
+ String html, int offset, int limit, boolean inAttribute, StringBuilder sb) {
char ch = html.charAt(offset);
if ('&' != ch) {
sb.append(ch);
return offset + 1;
}
- int entityLimit = Math.min(limit, offset + LONGEST_ENTITY_NAME + 2); // + 2 for & and ; characters
- int end = -1;
- int tail = -1;
- if (entityLimit == limit) {
- // Assume a broken entity that ends at the end until shown otherwise.
- end = tail = entityLimit;
- }
- entityloop:
- for (int i = offset + 1; i < entityLimit; ++i) {
- switch (html.charAt(i)) {
- case ';': // An unbroken entity.
- end = i;
- tail = end + 1;
- break entityloop;
- case '#':
- case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
- case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
- case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
- case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
- case 'Y': case 'Z':
- case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
- case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
- case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
- case 's': case 't': case 'u': case 'v': case 'w': case 'x':
- case 'y': case 'z':
- case '0': case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
- break;
- case '=':
- // An equal sign after an entity missing a closing semicolon should
- // never have the semicolon inserted since that causes trouble with
- // parameters in partially encoded URLs.
- sb.append('&');
- return offset + 1;
- default: // A possible broken entity.
- end = i;
- tail = i;
- break entityloop;
- }
- }
- if (end < 0 || offset + 2 >= end) {
+ if (offset + 2 >= limit) {
sb.append('&');
return offset + 1;
}
+ // Cap limit to limit the amount of time spent processing inputs like
+ // &a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a&a
+ limit = Math.min(limit, offset + (1 + LONGEST_ENTITY_NAME));
+
// Now we know where the entity ends, and that there is at least one
// character in the entity name
char ch1 = html.charAt(offset + 1);
char ch2 = html.charAt(offset + 2);
int codepoint = -1;
+ int tail = limit;
if ('#' == ch1) {
// numeric entity
if ('x' == ch2 || 'X' == ch2) {
- if (end == offset + 3) { // No digits
+ if (limit == offset + 3) { // No digits
sb.append('&');
return offset + 1;
}
codepoint = 0;
// hex literal
digloop:
- for (int i = offset + 3; i < end; ++i) {
+ for (int i = offset + 3; i < limit; ++i) {
char digit = html.charAt(i);
+ if (!isHtmlIdContinueChar(digit)) {
+ if (i == offset + 3) {
+ codepoint = -1;
+ }
+ if (digit == ';') {
+ i += 1;
+ }
+ tail = i;
+ break;
+ }
switch (digit & 0xfff8) {
case 0x30: case 0x38: // ASCII 48-57 are '0'-'9'
int decDig = digit & 0xf;
@@ -2298,8 +2401,18 @@ final class HtmlEntities {
codepoint = 0;
// decimal literal
digloop:
- for (int i = offset + 2; i < end; ++i) {
+ for (int i = offset + 2; i < limit; ++i) {
char digit = html.charAt(i);
+ if (!isHtmlIdContinueChar(digit)) {
+ if (i == offset + 2) {
+ codepoint = -1;
+ }
+ if (digit == ';') {
+ i += 1;
+ }
+ tail = i;
+ break;
+ }
switch (digit & 0xfff8) {
case 0x30: case 0x38: // ASCII 48-57 are '0'-'9'
int decDig = digit - '0';
@@ -2320,23 +2433,33 @@ final class HtmlEntities {
}
}
} else {
+ Trie<String> longestDecode = null;
Trie<String> t = ENTITY_TRIE;
- for (int i = offset + 1; i < end; ++i) {
+ for (int i = offset + 1; i < limit; ++i) {
char nameChar = html.charAt(i);
t = t.lookup(nameChar);
if (t == null) { break; }
+ if (t.isTerminal() && mayComplete(inAttribute, html, i, limit)) {
+ longestDecode = t;
+ tail = i + 1;
+ }
}
- if (t == null) {
+ // Try again, case insensitively.
+ if (longestDecode == null) {
t = ENTITY_TRIE;
- for (int i = offset + 1; i < end; ++i) {
+ for (int i = offset + 1; i < limit; ++i) {
char nameChar = html.charAt(i);
if ('Z' >= nameChar && nameChar >= 'A') { nameChar |= 32; }
t = t.lookup(nameChar);
if (t == null) { break; }
+ if (t.isTerminal() && mayComplete(inAttribute, html, i, limit)) {
+ longestDecode = t;
+ tail = i + 1;
+ }
}
}
- if (t != null && t.isTerminal()) {
- sb.append(t.getValue());
+ if (longestDecode != null) {
+ sb.append(longestDecode.getValue());
return tail;
}
}
@@ -2349,6 +2472,37 @@ final class HtmlEntities {
}
}
+ private static boolean isHtmlIdContinueChar(char ch) {
+ int chLower = ch | 32;
+ return ('0' <= ch && ch <= '9')
+ || ('a' <= chLower && chLower <= 'z')
+ || ('-' == ch);
+ }
+
+ /** True if the character at i in html may complete a named character reference */
+ private static boolean mayComplete(boolean inAttribute, String html, int i, int limit) {
+ if (inAttribute && html.charAt(i) != ';' && i + 1 < limit) {
+ // See if the next character blocks treating this as a full match.
+ // This avoids problems like "¶" being treated as a decoding in
+ // <a href="?foo¶m=1">
+ if (continuesCharacterReferenceName(html.charAt(i + 1))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @see <a href="https://github.com/OWASP/java-html-sanitizer/issues/254#issuecomment-1080864368"
+ * >comments in issue 254</a>
+ */
+ private static boolean continuesCharacterReferenceName(char ch) {
+ int chLower = ch | 32;
+ return ('0' <= ch && ch <= '9')
+ || ('a' <= chLower && chLower <= 'z')
+ || (ch == '=');
+ }
+
// /** A possible entity name like "amp" or "gt". */
// public static boolean isEntityName(String name) {
// Trie t = ENTITY_TRIE;
diff --git a/src/main/java/org/owasp/html/HtmlLexer.java b/src/main/java/org/owasp/html/HtmlLexer.java
index ed326b1..00fcc7d 100644
--- a/src/main/java/org/owasp/html/HtmlLexer.java
+++ b/src/main/java/org/owasp/html/HtmlLexer.java
@@ -55,11 +55,27 @@ final class HtmlLexer extends AbstractTokenStream {
/**
* Normalize case of names that are not name-spaced. This lower-cases HTML
- * element and attribute names, but not ones for embedded SVG or MATHML.
+ * element names, but not ones for embedded SVG or MathML.
*/
- static String canonicalName(String elementOrAttribName) {
- return elementOrAttribName.indexOf(':') >= 0
- ? elementOrAttribName : Strings.toLowerCase(elementOrAttribName);
+ static String canonicalElementName(String elementName) {
+ return elementName.indexOf(':') >= 0 || mixedCaseForeignElementNames.contains(elementName)
+ ? elementName : Strings.toLowerCase(elementName);
+ }
+
+ /**
+ * Normalize case of names that are not name-spaced. This lower-cases HTML
+ * attribute names, but not ones for embedded SVG or MathML.
+ */
+ static String canonicalAttributeName(String attribName) {
+ return attribName.indexOf(':') >= 0 || mixedCaseForeignAttributeNames.contains(attribName)
+ ? attribName : Strings.toLowerCase(attribName);
+ }
+
+ /**
+ * Normalize case of keywords in attribute values.
+ */
+ public static String canonicalKeywordAttributeValue(String keywordValue) {
+ return Strings.toLowerCase(keywordValue);
}
/**
@@ -243,9 +259,7 @@ final class HtmlLexer extends AbstractTokenStream {
/** Can the attribute appear in HTML without a value. */
private static boolean isValuelessAttribute(String attribName) {
- boolean valueless = VALUELESS_ATTRIB_NAMES.contains(
- Strings.toLowerCase(attribName));
- return valueless;
+ return VALUELESS_ATTRIB_NAMES.contains(canonicalAttributeName(attribName));
}
// From http://issues.apache.org/jira/browse/XALANC-519
@@ -253,6 +267,125 @@ final class HtmlLexer extends AbstractTokenStream {
"checked", "compact", "declare", "defer", "disabled",
"ismap", "multiple", "nohref", "noresize", "noshade",
"nowrap", "readonly", "selected");
+
+ private static final ImmutableSet<String> mixedCaseForeignAttributeNames = ImmutableSet.of(
+ "attributeName",
+ "attributeType",
+ "baseFrequency",
+ "baseProfile",
+ "calcMode",
+ "clipPathUnits",
+ "contentScriptType",
+ "defaultAction",
+ "definitionURL",
+ "diffuseConstant",
+ "edgeMode",
+ "externalResourcesRequired",
+ "filterUnits",
+ "focusHighlight",
+ "gradientTransform",
+ "gradientUnits",
+ "initialVisibility",
+ "kernelMatrix",
+ "kernelUnitLength",
+ "keyPoints",
+ "keySplines",
+ "keyTimes",
+ "lengthAdjust",
+ "limitingConeAngle",
+ "markerHeight",
+ "markerUnits",
+ "markerWidth",
+ "maskContentUnits",
+ "maskUnits",
+ "mediaCharacterEncoding",
+ "mediaContentEncodings",
+ "mediaSize",
+ "mediaTime",
+ "numOctaves",
+ "pathLength",
+ "patternContentUnits",
+ "patternTransform",
+ "patternUnits",
+ "playbackOrder",
+ "pointsAtX",
+ "pointsAtY",
+ "pointsAtZ",
+ "preserveAlpha",
+ "preserveAspectRatio",
+ "primitiveUnits",
+ "refX",
+ "refY",
+ "repeatCount",
+ "repeatDur",
+ "requiredExtensions",
+ "requiredFeatures",
+ "requiredFonts",
+ "requiredFormats",
+ "schemaLocation",
+ "snapshotTime",
+ "specularConstant",
+ "specularExponent",
+ "spreadMethod",
+ "startOffset",
+ "stdDeviation",
+ "stitchTiles",
+ "surfaceScale",
+ "syncBehavior",
+ "syncBehaviorDefault",
+ "syncMaster",
+ "syncTolerance",
+ "syncToleranceDefault",
+ "systemLanguage",
+ "tableValues",
+ "targetX",
+ "targetY",
+ "textLength",
+ "timelineBegin",
+ "transformBehavior",
+ "viewBox",
+ "xChannelSelector",
+ "yChannelSelector",
+ "zoomAndPan"
+ );
+
+ private static final ImmutableSet<String> mixedCaseForeignElementNames = ImmutableSet.of(
+ "animateColor",
+ "animateMotion",
+ "animateTransform",
+ "clipPath",
+ "feBlend",
+ "feColorMatrix",
+ "feComponentTransfer",
+ "feComposite",
+ "feConvolveMatrix",
+ "feDiffuseLighting",
+ "feDisplacementMap",
+ "feDistantLight",
+ "feDropShadow",
+ "feFlood",
+ "feFuncA",
+ "feFuncB",
+ "feFuncG",
+ "feFuncR",
+ "feGaussianBlur",
+ "feImage",
+ "feMerge",
+ "feMergeNode",
+ "feMorphology",
+ "feOffset",
+ "fePointLight",
+ "feSpecularLighting",
+ "feSpotLight",
+ "feTile",
+ "feTurbulence",
+ "foreignObject",
+ "linearGradient",
+ "radialGradient",
+ "solidColor",
+ "textArea",
+ "textPath"
+ );
}
/**
@@ -311,7 +444,7 @@ final class HtmlInputSplitter extends AbstractTokenStream {
switch (token.type) {
case TAGBEGIN:
{
- String canonTagName = canonicalName(
+ String canonTagName = canonicalElementName(
token.start + 1, token.end);
if (HtmlTextEscapingMode.isTagFollowedByLiteralContent(
canonTagName)) {
@@ -478,7 +611,7 @@ final class HtmlInputSplitter extends AbstractTokenStream {
if (this.inEscapeExemptBlock
&& '/' == input.charAt(start + 1)
&& textEscapingMode != HtmlTextEscapingMode.PLAIN_TEXT
- && canonicalName(start + 2, end)
+ && canonicalElementName(start + 2, end)
.equals(escapeExemptTagName)) {
this.inEscapeExemptBlock = false;
this.escapeExemptTagName = null;
@@ -612,8 +745,8 @@ final class HtmlInputSplitter extends AbstractTokenStream {
return result;
}
- private String canonicalName(int start, int end) {
- return HtmlLexer.canonicalName(input.substring(start, end));
+ private String canonicalElementName(int start, int end) {
+ return HtmlLexer.canonicalElementName(input.substring(start, end));
}
private static boolean isIdentStart(char ch) {
diff --git a/src/main/java/org/owasp/html/HtmlPolicyBuilder.java b/src/main/java/org/owasp/html/HtmlPolicyBuilder.java
index 34a3192..c43bfb8 100644
--- a/src/main/java/org/owasp/html/HtmlPolicyBuilder.java
+++ b/src/main/java/org/owasp/html/HtmlPolicyBuilder.java
@@ -168,6 +168,15 @@ public class HtmlPolicyBuilder {
public static final ImmutableSet<String> DEFAULT_SKIP_IF_EMPTY
= ImmutableSet.of("a", "font", "img", "input", "span");
+ static final ImmutableMap<String, HtmlTagSkipType> DEFAULT_SKIP_TAG_MAP_IF_EMPTY_ATTR;
+ static {
+ ImmutableMap.Builder<String, HtmlTagSkipType> b = ImmutableMap.builder();
+ for (String elementName : DEFAULT_SKIP_IF_EMPTY) {
+ b.put(elementName, HtmlTagSkipType.SKIP_BY_DEFAULT);
+ }
+ DEFAULT_SKIP_TAG_MAP_IF_EMPTY_ATTR = b.build();
+ }
+
/**
* These
* <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types"
@@ -190,8 +199,7 @@ public class HtmlPolicyBuilder {
private final Map<String, AttributePolicy> globalAttrPolicies
= Maps.newLinkedHashMap();
private final Set<String> allowedProtocols = Sets.newLinkedHashSet();
- private final Set<String> skipIfEmpty = Sets.newLinkedHashSet(
- DEFAULT_SKIP_IF_EMPTY);
+ private final Map<String, HtmlTagSkipType> skipIssueTagMap = Maps.newLinkedHashMap(DEFAULT_SKIP_TAG_MAP_IF_EMPTY_ATTR);
private final Map<String, Boolean> textContainers = Maps.newLinkedHashMap();
private HtmlStreamEventProcessor postprocessor =
HtmlStreamEventProcessor.Processors.IDENTITY;
@@ -230,7 +238,7 @@ public class HtmlPolicyBuilder {
ElementPolicy policy, String... elementNames) {
invalidateCompiledState();
for (String elementName : elementNames) {
- elementName = HtmlLexer.canonicalName(elementName);
+ elementName = HtmlLexer.canonicalElementName(elementName);
ElementPolicy newPolicy = ElementPolicy.Util.join(
elPolicies.get(elementName), policy);
// Don't remove if newPolicy is the always reject policy since we want
@@ -278,7 +286,7 @@ public class HtmlPolicyBuilder {
public HtmlPolicyBuilder allowTextIn(String... elementNames) {
invalidateCompiledState();
for (String elementName : elementNames) {
- elementName = HtmlLexer.canonicalName(elementName);
+ elementName = HtmlLexer.canonicalElementName(elementName);
textContainers.put(elementName, true);
}
return this;
@@ -297,7 +305,7 @@ public class HtmlPolicyBuilder {
public HtmlPolicyBuilder disallowTextIn(String... elementNames) {
invalidateCompiledState();
for (String elementName : elementNames) {
- elementName = HtmlLexer.canonicalName(elementName);
+ elementName = HtmlLexer.canonicalElementName(elementName);
textContainers.put(elementName, false);
}
return this;
@@ -307,14 +315,14 @@ public class HtmlPolicyBuilder {
* Assuming the given elements are allowed, allows them to appear without
* attributes.
*
- * @see #DEFAULT_SKIP_IF_EMPTY
+ * @see #DEFAULT_SKIP_TAG_MAP_IF_EMPTY_ATTR
* @see #disallowWithoutAttributes
*/
public HtmlPolicyBuilder allowWithoutAttributes(String... elementNames) {
invalidateCompiledState();
for (String elementName : elementNames) {
- elementName = HtmlLexer.canonicalName(elementName);
- skipIfEmpty.remove(elementName);
+ elementName = HtmlLexer.canonicalElementName(elementName);
+ skipIssueTagMap.put(elementName, HtmlTagSkipType.DO_NOT_SKIP);
}
return this;
}
@@ -322,14 +330,14 @@ public class HtmlPolicyBuilder {
/**
* Disallows the given elements from appearing without attributes.
*
- * @see #DEFAULT_SKIP_IF_EMPTY
+ * @see #DEFAULT_SKIP_TAG_MAP_IF_EMPTY_ATTR
* @see #allowWithoutAttributes
*/
public HtmlPolicyBuilder disallowWithoutAttributes(String... elementNames) {
invalidateCompiledState();
for (String elementName : elementNames) {
- elementName = HtmlLexer.canonicalName(elementName);
- skipIfEmpty.add(elementName);
+ elementName = HtmlLexer.canonicalElementName(elementName);
+ skipIssueTagMap.put(elementName, HtmlTagSkipType.SKIP);
}
return this;
}
@@ -341,7 +349,7 @@ public class HtmlPolicyBuilder {
public AttributeBuilder allowAttributes(String... attributeNames) {
ImmutableList.Builder<String> b = ImmutableList.builder();
for (String attributeName : attributeNames) {
- b.add(HtmlLexer.canonicalName(attributeName));
+ b.add(HtmlLexer.canonicalAttributeName(attributeName));
}
return new AttributeBuilder(b.build());
}
@@ -424,7 +432,7 @@ public class HtmlPolicyBuilder {
this.extraRelsForLinks = Sets.newLinkedHashSet();
}
for (String linkValue : linkValues) {
- linkValue = HtmlLexer.canonicalName(linkValue);
+ linkValue = HtmlLexer.canonicalKeywordAttributeValue(linkValue);
Preconditions.checkArgument(
!Strings.containsHtmlSpace(linkValue),
"spaces in input. use f(\"foo\", \"bar\") not f(\"foo bar\")");
@@ -448,7 +456,7 @@ public class HtmlPolicyBuilder {
this.skipRelsForLinks = Sets.newLinkedHashSet();
}
for (String linkValue : linkValues) {
- linkValue = HtmlLexer.canonicalName(linkValue);
+ linkValue = HtmlLexer.canonicalKeywordAttributeValue(linkValue);
Preconditions.checkArgument(
!Strings.containsHtmlSpace(linkValue),
"spaces in input. use f(\"foo\", \"bar\") not f(\"foo bar\")");
@@ -835,13 +843,29 @@ public class HtmlPolicyBuilder {
elementName,
new ElementAndAttributePolicies(
elementName,
- elPolicy, attrs.build(), skipIfEmpty.contains(elementName)));
+ elPolicy, attrs.build(),
+ getHtmlTagSkipType(elementName)
+ )
+ );
}
compiledState = new CompiledState(
globalAttrPolicies, policiesBuilder.build());
return compiledState;
}
+ private HtmlTagSkipType getHtmlTagSkipType(String elementName) {
+ HtmlTagSkipType htmlTagSkipType = skipIssueTagMap.get(elementName);
+ if (htmlTagSkipType == null) {
+ if (DEFAULT_SKIP_TAG_MAP_IF_EMPTY_ATTR.containsKey(elementName)) {
+ return HtmlTagSkipType.SKIP_BY_DEFAULT;
+ } else {
+ return HtmlTagSkipType.DO_NOT_SKIP_BY_DEFAULT;
+ }
+ }
+
+ return htmlTagSkipType;
+ }
+
/**
* Builds the relationship between attributes, the values that they may have,
* and the elements on which they may appear.
@@ -944,8 +968,12 @@ public class HtmlPolicyBuilder {
*/
@SuppressWarnings("synthetic-access")
public HtmlPolicyBuilder globally() {
- return HtmlPolicyBuilder.this.allowAttributesGlobally(
- policy, attributeNames);
+ if(attributeNames.get(0).equals("style")) {
+ return allowStyling();
+ } else {
+ return HtmlPolicyBuilder.this.allowAttributesGlobally(
+ policy, attributeNames);
+ }
}
/**
@@ -956,7 +984,7 @@ public class HtmlPolicyBuilder {
public HtmlPolicyBuilder onElements(String... elementNames) {
ImmutableList.Builder<String> b = ImmutableList.builder();
for (String elementName : elementNames) {
- b.add(HtmlLexer.canonicalName(elementName));
+ b.add(HtmlLexer.canonicalElementName(elementName));
}
return HtmlPolicyBuilder.this.allowAttributesOnElements(
policy, attributeNames, b.build());
@@ -1118,4 +1146,4 @@ final class AttributeGuardIntermediates {
this.styleUrlPolicy = styleUrlPolicy;
this.cssSchema = cssSchema;
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/org/owasp/html/HtmlSanitizer.java b/src/main/java/org/owasp/html/HtmlSanitizer.java
index f9e932e..d5f8750 100644
--- a/src/main/java/org/owasp/html/HtmlSanitizer.java
+++ b/src/main/java/org/owasp/html/HtmlSanitizer.java
@@ -144,7 +144,7 @@ public final class HtmlSanitizer {
switch (token.type) {
case TEXT:
receiver.text(
- Encoding.decodeHtml(htmlContent.substring(token.start, token.end)));
+ Encoding.decodeHtml(htmlContent.substring(token.start, token.end), false));
break;
case UNESCAPED:
receiver.text(Encoding.stripBannedCodeunits(
@@ -152,7 +152,7 @@ public final class HtmlSanitizer {
break;
case TAGBEGIN:
if (htmlContent.charAt(token.start + 1) == '/') { // A close tag.
- receiver.closeTag(HtmlLexer.canonicalName(
+ receiver.closeTag(HtmlLexer.canonicalElementName(
htmlContent.substring(token.start + 2, token.end)));
while (lexer.hasNext()
&& lexer.next().type != HtmlTokenType.TAGEND) {
@@ -173,12 +173,13 @@ public final class HtmlSanitizer {
} else {
attrsReadyForName = false;
}
- attrs.add(HtmlLexer.canonicalName(
+ attrs.add(HtmlLexer.canonicalAttributeName(
htmlContent.substring(tagBodyToken.start, tagBodyToken.end)));
break;
case ATTRVALUE:
- attrs.add(Encoding.decodeHtml(stripQuotes(
- htmlContent.substring(tagBodyToken.start, tagBodyToken.end))));
+ String attributeContentRaw =
+ stripQuotes(htmlContent.substring(tagBodyToken.start, tagBodyToken.end));
+ attrs.add(Encoding.decodeHtml(attributeContentRaw, true));
attrsReadyForName = true;
break;
case TAGEND:
@@ -191,7 +192,7 @@ public final class HtmlSanitizer {
attrs.add(attrs.getLast());
}
receiver.openTag(
- HtmlLexer.canonicalName(
+ HtmlLexer.canonicalElementName(
htmlContent.substring(token.start + 1, token.end)),
attrs);
}
diff --git a/src/main/java/org/owasp/html/HtmlStreamRenderer.java b/src/main/java/org/owasp/html/HtmlStreamRenderer.java
index 019895a..9c079d1 100644
--- a/src/main/java/org/owasp/html/HtmlStreamRenderer.java
+++ b/src/main/java/org/owasp/html/HtmlStreamRenderer.java
@@ -29,11 +29,15 @@
package org.owasp.html;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableSet;
+
import java.io.Closeable;
import java.io.Flushable;
import java.io.IOException;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
import javax.annotation.WillCloseWhenClosed;
import javax.annotation.concurrent.NotThreadSafe;
@@ -187,7 +191,7 @@ public class HtmlStreamRenderer implements HtmlStreamEventReceiver {
attrIt.hasNext();) {
String name = attrIt.next();
String value = attrIt.next();
- name = HtmlLexer.canonicalName(name);
+ name = HtmlLexer.canonicalAttributeName(name);
if (!isValidHtmlName(name)) {
error("Invalid attr name", name);
continue;
@@ -234,7 +238,7 @@ public class HtmlStreamRenderer implements HtmlStreamEventReceiver {
private final void writeCloseTag(String uncanonElementName)
throws IOException {
if (!open) { throw new IllegalStateException(); }
- String elementName = HtmlLexer.canonicalName(uncanonElementName);
+ String elementName = HtmlLexer.canonicalElementName(uncanonElementName);
if (!isValidHtmlName(elementName)) {
error("Invalid element name", elementName);
return;
@@ -250,7 +254,9 @@ public class HtmlStreamRenderer implements HtmlStreamEventReceiver {
Encoding.stripBannedCodeunits(cdataContent);
int problemIndex = checkHtmlCdataCloseable(lastTagOpened, cdataContent);
if (problemIndex == -1) {
- output.append(cdataContent);
+ if (cdataContent.length() != 0) {
+ output.append(cdataContent);
+ }
} else {
error(
"Invalid CDATA text content",
@@ -386,7 +392,7 @@ public class HtmlStreamRenderer implements HtmlStreamEventReceiver {
* that has more consistent semantics.
*/
static String safeName(String unsafeElementName) {
- String elementName = HtmlLexer.canonicalName(unsafeElementName);
+ String elementName = HtmlLexer.canonicalElementName(unsafeElementName);
// Substitute a reliably non-raw-text element for raw-text and
// plain-text elements.
diff --git a/src/main/java/org/owasp/html/HtmlTagSkipType.java b/src/main/java/org/owasp/html/HtmlTagSkipType.java
new file mode 100644
index 0000000..e136fc2
--- /dev/null
+++ b/src/main/java/org/owasp/html/HtmlTagSkipType.java
@@ -0,0 +1,34 @@
+package org.owasp.html;
+
+public enum HtmlTagSkipType {
+ SKIP(true),
+ SKIP_BY_DEFAULT(true),
+ DO_NOT_SKIP(false),
+ DO_NOT_SKIP_BY_DEFAULT(false);
+
+ private final boolean skipAvailability;
+
+ HtmlTagSkipType(boolean skipAvailability) {
+ this.skipAvailability = skipAvailability;
+ }
+
+ public HtmlTagSkipType and(HtmlTagSkipType s) {
+ if (this == s || s == SKIP_BY_DEFAULT) {
+ return this;
+ }
+
+ if (s == DO_NOT_SKIP) {
+ return s;
+ }
+
+ if (s == DO_NOT_SKIP_BY_DEFAULT) {
+ return this;
+ }
+
+ return SKIP;
+ }
+
+ public boolean skipAvailability() {
+ return this.skipAvailability;
+ }
+}
diff --git a/src/main/java/org/owasp/html/TagBalancingHtmlStreamEventReceiver.java b/src/main/java/org/owasp/html/TagBalancingHtmlStreamEventReceiver.java
index c94d573..6df2a28 100644
--- a/src/main/java/org/owasp/html/TagBalancingHtmlStreamEventReceiver.java
+++ b/src/main/java/org/owasp/html/TagBalancingHtmlStreamEventReceiver.java
@@ -97,7 +97,7 @@ public class TagBalancingHtmlStreamEventReceiver
if (DEBUG) {
dumpState("open " + elementName);
}
- String canonElementName = HtmlLexer.canonicalName(elementName);
+ String canonElementName = HtmlLexer.canonicalElementName(elementName);
int elIndex = METADATA.indexForName(canonElementName);
// Treat unrecognized tags as void, but emit closing tags in closeTag().
@@ -217,6 +217,15 @@ public class TagBalancingHtmlStreamEventReceiver
private boolean canContain(
int child, int container, int containerIndexOnStack) {
Preconditions.checkArgument(containerIndexOnStack >= 0);
+ if (child == HtmlElementTables.TEXT_NODE && hasSpecialTextMode(container)) {
+ // If there's a select element on the stack, then we need to be extra careful.
+ int selectElementIndex = METADATA.indexForName("select");
+ for (int i = containerIndexOnStack; --i >= 0;) {
+ if (selectElementIndex == openElements.get(i)) {
+ return false;
+ }
+ }
+ }
int anc = container;
int ancIndexOnStack = containerIndexOnStack;
while (true) {
@@ -238,7 +247,7 @@ public class TagBalancingHtmlStreamEventReceiver
if (DEBUG) {
dumpState("close " + elementName);
}
- String canonElementName = HtmlLexer.canonicalName(elementName);
+ String canonElementName = HtmlLexer.canonicalElementName(elementName);
int elIndex = METADATA.indexForName(canonElementName);
if (elIndex == UNRECOGNIZED_TAG) { // Allow unrecognized end tags through.
@@ -363,6 +372,17 @@ public class TagBalancingHtmlStreamEventReceiver
&& canonElementName.charAt(1) <= '9';
}
+ private static boolean hasSpecialTextMode(int elementIndex) {
+ String name = METADATA.canonNameForIndex(elementIndex);
+ switch (HtmlTextEscapingMode.getModeForTag(name)) {
+ case PCDATA: case VOID:
+ return false;
+ case CDATA: case CDATA_SOMETIMES: case RCDATA: case PLAIN_TEXT:
+ return true;
+ }
+ throw new IllegalArgumentException(name);
+ }
+
private static final byte ALL_SCOPES;
private static final byte[] SCOPES_BY_ELEMENT;
private static final byte[] SCOPE_FOR_END_TAG;
diff --git a/src/test/java/org/owasp/html/EncodingTest.java b/src/test/java/org/owasp/html/EncodingTest.java
index e128708..54ff0b4 100644
--- a/src/test/java/org/owasp/html/EncodingTest.java
+++ b/src/test/java/org/owasp/html/EncodingTest.java
@@ -34,6 +34,24 @@ import junit.framework.TestCase;
@SuppressWarnings("javadoc")
public final class EncodingTest extends TestCase {
+ private static void assertDecodedHtml(String want, String inputHtml) {
+ assertDecodedHtml(want, want, inputHtml);
+ }
+
+ private static void assertDecodedHtml(
+ String wantText, String wantAttr, String inputHtml
+ ) {
+ assertEquals(
+ "!inAttribute: " + inputHtml,
+ wantText,
+ Encoding.decodeHtml(inputHtml, false)
+ );
+ assertEquals(
+ "inAttribute: " + inputHtml,
+ wantAttr,
+ Encoding.decodeHtml(inputHtml, true)
+ );
+ }
@Test
public static final void testDecodeHtml() {
@@ -43,171 +61,90 @@ public final class EncodingTest extends TestCase {
// 123456789012345678901234567890123456789012345678901234567890123456789
String golden =
"The quick\u00a0brown fox\njumps over\r\nthe lazy dog\n";
- assertEquals(golden, Encoding.decodeHtml(html));
+ assertDecodedHtml(golden, html);
// Don't allocate a new string when no entities.
- assertSame(golden, Encoding.decodeHtml(golden));
+ assertSame(golden, golden);
// test interrupted escapes and escapes at end of file handled gracefully
- assertEquals(
- "\\\\u000a",
- Encoding.decodeHtml("\\\\u000a"));
- assertEquals(
- "\n",
- Encoding.decodeHtml("
"));
- assertEquals(
- "\n",
- Encoding.decodeHtml("
"));
- assertEquals(
- "\n",
- Encoding.decodeHtml("
"));
- assertEquals(
- "\n",
- Encoding.decodeHtml("
"));
- assertEquals(
+ assertDecodedHtml("\\\\u000a", "\\\\u000a");
+ assertDecodedHtml("\n", "
");
+ assertDecodedHtml("\n", "
");
+ assertDecodedHtml("\n", "
");
+ assertDecodedHtml("\n", "
");
+ assertDecodedHtml(
String.valueOf(Character.toChars(0x10000)),
- Encoding.decodeHtml("𐀀"));
- assertEquals(
- "\n",
- Encoding.decodeHtml("
"));
- assertEquals(
- "�ziggy",
- Encoding.decodeHtml("�ziggy"));
- assertEquals(
- "਀z;",
- Encoding.decodeHtml("਀z;"));
- assertEquals(
- "&#\n",
- Encoding.decodeHtml("&#
"));
- assertEquals(
- "&#x\n",
- Encoding.decodeHtml("&#x
"));
- assertEquals(
- "\n\n",
- Encoding.decodeHtml("

"));
- assertEquals(
- "&#\n",
- Encoding.decodeHtml("&#
"));
- assertEquals(
- "&#x",
- Encoding.decodeHtml("&#x"));
- assertEquals(
- "", // NUL elided.
- Encoding.decodeHtml("�"));
- assertEquals(
- "&#",
- Encoding.decodeHtml("&#"));
-
- assertEquals(
- "\\",
- Encoding.decodeHtml("\\"));
- assertEquals(
- "&",
- Encoding.decodeHtml("&"));
-
- assertEquals(
- "�a;",
- Encoding.decodeHtml("�a;"));
- assertEquals(
- "\n",
- Encoding.decodeHtml(" "));
- assertEquals(
- "\n",
- Encoding.decodeHtml("
"));
- assertEquals(
- "\n",
- Encoding.decodeHtml("
"));
- assertEquals(
- "\t",
- Encoding.decodeHtml("	"));
- assertEquals(
- "\n",
- Encoding.decodeHtml("
"));
- assertEquals(
- "�ziggy",
- Encoding.decodeHtml("�ziggy"));
- assertEquals(
- "&#\n",
- Encoding.decodeHtml("&#
"));
- assertEquals(
- "\n",
- Encoding.decodeHtml("�
"));
- assertEquals(
- "\n",
- Encoding.decodeHtml(" "));
- assertEquals(
- "&#\n",
- Encoding.decodeHtml("&# "));
- assertEquals(
- "", // Invalid XML char elided.
- Encoding.decodeHtml(""));
- assertEquals(
- "\t",
- Encoding.decodeHtml("	"));
- assertEquals(
- "\n",
- Encoding.decodeHtml("
"));
+ "𐀀"
+ );
+ assertDecodedHtml("\n", "
");
+ assertDecodedHtml("�ziggy", "�ziggy");
+ assertDecodedHtml("਀z;", "਀z;");
+ assertDecodedHtml("&#\n", "&#
");
+ assertDecodedHtml("&#x\n", "&#x
");
+ assertDecodedHtml("\n\n", "

");
+ assertDecodedHtml("&#\n", "&#
");
+ assertDecodedHtml("&#x", "&#x");
+ assertDecodedHtml("", "�"); // NUL elided.
+ assertDecodedHtml("&#", "&#");
+
+ assertDecodedHtml("\\", "\\");
+ assertDecodedHtml("&", "&");
+
+ assertDecodedHtml("�a;", "�a;");
+ assertDecodedHtml("\n", " ");
+ assertDecodedHtml("\n", "
");
+ assertDecodedHtml("\n", "
");
+ assertDecodedHtml("\t", "	");
+ assertDecodedHtml("\n", "
");
+ assertDecodedHtml("�ziggy", "�ziggy");
+ assertDecodedHtml("&#\n", "&#
");
+ assertDecodedHtml("\n", "�
");
+ assertDecodedHtml("\n", " ");
+ assertDecodedHtml("&#\n", "&# ");
+ assertDecodedHtml("", ""); // Invalid XML char elided.
+ assertDecodedHtml("\t", "	");
+ assertDecodedHtml("\n", "
");
// test the named escapes
- assertEquals(
- "<",
- Encoding.decodeHtml("<"));
- assertEquals(
- ">",
- Encoding.decodeHtml(">"));
- assertEquals(
- "\"",
- Encoding.decodeHtml("""));
- assertEquals(
- "'",
- Encoding.decodeHtml("'"));
- assertEquals(
- "'",
- Encoding.decodeHtml("'"));
- assertEquals(
- "'",
- Encoding.decodeHtml("'"));
- assertEquals(
- "&",
- Encoding.decodeHtml("&"));
- assertEquals(
- "<",
- Encoding.decodeHtml("&lt;"));
- assertEquals(
- "&",
- Encoding.decodeHtml("&"));
- assertEquals(
- "&",
- Encoding.decodeHtml("&"));
- assertEquals(
- "&",
- Encoding.decodeHtml("&AmP;"));
- assertEquals(
- "\u0391",
- Encoding.decodeHtml("Α"));
- assertEquals(
- "\u03b1",
- Encoding.decodeHtml("α"));
- assertEquals(
- "\ud835\udc9c", // U+1D49C requires a surrogate pair in UTF-16.
- Encoding.decodeHtml("𝒜"));
- assertEquals(
- "fj", // fj refers to 2 characters.
- Encoding.decodeHtml("fj"));
- assertEquals(
- "\u2233", // HTML entity with the longest name.
- Encoding.decodeHtml("∳"));
- assertEquals(
- // Longest entity name with missing terminator to check for boundary bugs.
- "\u2233",
- Encoding.decodeHtml("&CounterClockwiseContourIntegral"));
-
- assertEquals(
- "&;",
- Encoding.decodeHtml("&;"));
- assertEquals(
- "&bogus;",
- Encoding.decodeHtml("&bogus;"));
+ assertDecodedHtml("<", "<");
+ assertDecodedHtml(">", ">");
+ assertDecodedHtml("\"", """);
+ assertDecodedHtml("'", "'");
+ assertDecodedHtml("'", "'");
+ assertDecodedHtml("'", "'");
+ assertDecodedHtml("&", "&");
+ assertDecodedHtml("<", "&lt;");
+ assertDecodedHtml("&", "&");
+ assertDecodedHtml("&", "&");
+ assertDecodedHtml("&", "&AmP;");
+ assertDecodedHtml("\u0391", "Α");
+ assertDecodedHtml("\u03b1", "α");
+ // U+1D49C requires a surrogate pair in UTF-16.
+ assertDecodedHtml("\ud835\udc9c", "𝒜");
+ // fj refers to 2 characters.
+ assertDecodedHtml("fj", "fj");
+ // HTML entity with the longest name.
+ assertDecodedHtml("\u2233", "∳");
+ // Missing the semicolon.
+ assertDecodedHtml(
+ "&CounterClockwiseContourIntegral",
+ "&CounterClockwiseContourIntegral"
+ );
+
+ assertDecodedHtml("&;", "&;");
+ assertDecodedHtml("&bogus;", "&bogus;");
+
+ // Some strings decode differently depending on whether or not they're in an HTML attribute.
+ assertDecodedHtml(
+ "?foo\u00B6m=bar",
+ "?foo¶m=bar",
+ "?foo¶m=bar"
+ );
+ assertDecodedHtml(
+ "?foo\u00B6=bar",
+ "?foo¶=bar",
+ "?foo¶=bar"
+ );
}
@Test
diff --git a/src/test/java/org/owasp/html/HtmlPolicyBuilderTest.java b/src/test/java/org/owasp/html/HtmlPolicyBuilderTest.java
index f59863e..db75e4c 100644
--- a/src/test/java/org/owasp/html/HtmlPolicyBuilderTest.java
+++ b/src/test/java/org/owasp/html/HtmlPolicyBuilderTest.java
@@ -958,6 +958,42 @@ public class HtmlPolicyBuilderTest extends TestCase {
"<noscript><p title=\"</noscript><img src=x onerror=alert(1)>\">"));
}
+ @Test
+ public static final void testTableStructure() {
+ String input =
+ "<TABLE>"
+ + "<TR><TD>Foo<TD>Bar"
+ + "<TR><TH>Baz<TH>Boo<TH>Far<TH>Faz"
+ + "<TR><TD>Oink<TD>Doink<TD>Poink<TD>Toink";
+ String sanitized = Sanitizers.TABLES.sanitize(input);
+ assertEquals(
+ ("<table><tbody>"
+ + "<tr><td>Foo</td><td>Bar</td></tr>"
+ + "<tr><th>Baz</th><th>Boo</th><th>Far</th><th>Faz</th></tr>"
+ + "<tr><td>Oink</td><td>Doink</td><td>Poink</td><td>Toink</td></tr>"
+ + "</tbody></table>"),
+ sanitized);
+ }
+
+ @Test
+ public static final void testSvgNames() {
+ PolicyFactory policyFactory = new HtmlPolicyBuilder()
+ .allowElements("svg", "animateColor")
+ .allowAttributes("viewBox").onElements("svg")
+ .toFactory();
+ String svg = "<svg viewBox=\"0 0 0 0\"><animateColor></animateColor></svg>";
+ assertEquals(svg, policyFactory.sanitize(svg));
+ }
+
+ @Test
+ public static final void testTextareaIsNotTextArea() {
+ String input = "<textarea>x</textarea><textArea>y</textArea>";
+ PolicyFactory textareaPolicy = new HtmlPolicyBuilder().allowElements("textarea").toFactory();
+ PolicyFactory textAreaPolicy = new HtmlPolicyBuilder().allowElements("textArea").toFactory();
+ assertEquals("<textarea>x</textarea>y", textareaPolicy.sanitize(input));
+ assertEquals("x<textArea>y</textArea>", textAreaPolicy.sanitize(input));
+ }
+
private static String apply(HtmlPolicyBuilder b) {
return apply(b, EXAMPLE);
}
diff --git a/src/test/java/org/owasp/html/HtmlSanitizerTest.java b/src/test/java/org/owasp/html/HtmlSanitizerTest.java
index 53ff927..1ff169d 100644
--- a/src/test/java/org/owasp/html/HtmlSanitizerTest.java
+++ b/src/test/java/org/owasp/html/HtmlSanitizerTest.java
@@ -440,6 +440,20 @@ public class HtmlSanitizerTest extends TestCase {
}
}
+ @Test
+ public static final void testIssue254SemicolonlessNamedCharactersInUrls() {
+ String input = "<a href=\"/test/?param1=valueOne¶m2=valueTwo\">click me</a>";
+ String want = "<a href=\"/test/?param1=valueOne&param2=valueTwo\">click me</a>";
+ assertEquals(want, sanitize(input));
+ }
+
+ @Test
+ public static final void testStylingCornerCase() {
+ String input = "<a style=\\006-\\000038";
+ String want = "";
+ assertEquals(want, sanitize(input));
+ }
+
private static String sanitize(@Nullable String html) {
StringBuilder sb = new StringBuilder();
HtmlStreamRenderer renderer = HtmlStreamRenderer.create(
diff --git a/src/test/java/org/owasp/html/PolicyFactoryTest.java b/src/test/java/org/owasp/html/PolicyFactoryTest.java
index fae3db2..6d4f3e9 100644
--- a/src/test/java/org/owasp/html/PolicyFactoryTest.java
+++ b/src/test/java/org/owasp/html/PolicyFactoryTest.java
@@ -201,6 +201,408 @@ public final class PolicyFactoryTest extends TestCase {
}
}
+ // Default Skip Tag
+ // beforePolicy : X
+ // afterPolicy : X
+ @Test
+ public void testHtmlTagSkipPolicy1() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("span")
+ .toFactory();
+
+ String spanTagString = "<span>Hi</span>";
+ String resultString = beforePolicy.sanitize(spanTagString);
+ assertEquals("Hi", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("span")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(spanTagString);
+ assertEquals("Hi", resultString);
+ }
+
+ // Default Skip Tag
+ // beforePolicy : X
+ // afterPolicy : allow
+ @Test
+ public void testHtmlTagSkipPolicy2() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("span")
+ .toFactory();
+
+ String spanTagString = "<span>Hi</span>";
+ String resultString = beforePolicy.sanitize(spanTagString);
+ assertEquals("Hi", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("span")
+ .allowWithoutAttributes("span")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(spanTagString);
+ assertEquals("<span>Hi</span>", resultString);
+ }
+
+ // Default Skip Tag
+ // beforePolicy : X
+ // afterPolicy : disallow
+ @Test
+ public void testHtmlTagSkipPolicy3() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("span")
+ .toFactory();
+
+ String spanTagString = "<span>Hi</span>";
+ String resultString = beforePolicy.sanitize(spanTagString);
+ assertEquals("Hi", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("span")
+ .disallowWithoutAttributes("span")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(spanTagString);
+ assertEquals("Hi", resultString);
+ }
+
+ // Default Skip Tag
+ // beforePolicy : allow
+ // afterPolicy : X
+ @Test
+ public void testHtmlTagSkipPolicy4() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("span")
+ .allowWithoutAttributes("span")
+ .toFactory();
+
+ String spanTagString = "<span>Hi</span>";
+ String resultString = beforePolicy.sanitize(spanTagString);
+ assertEquals("<span>Hi</span>", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("span")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(spanTagString);
+ assertEquals("<span>Hi</span>", resultString);
+ }
+
+ // Default Skip Tag
+ // beforePolicy : allow
+ // afterPolicy : allow
+ @Test
+ public void testHtmlTagSkipPolicy5() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("span")
+ .allowWithoutAttributes("span")
+ .toFactory();
+
+ String spanTagString = "<span>Hi</span>";
+ String resultString = beforePolicy.sanitize(spanTagString);
+ assertEquals("<span>Hi</span>", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("span")
+ .allowWithoutAttributes("span")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(spanTagString);
+ assertEquals("<span>Hi</span>", resultString);
+ }
+
+ // Default Skip Tag
+ // beforePolicy : allow
+ // afterPolicy : disallow
+ @Test
+ public void testHtmlTagSkipPolicy6() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("span")
+ .allowWithoutAttributes("span")
+ .toFactory();
+
+ String spanTagString = "<span>Hi</span>";
+ String resultString = beforePolicy.sanitize(spanTagString);
+ assertEquals("<span>Hi</span>", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("span")
+ .disallowWithoutAttributes("span")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(spanTagString);
+ assertEquals("Hi", resultString);
+ }
+
+ // Default Skip Tag
+ // beforePolicy : disallow
+ // afterPolicy : X
+ @Test
+ public void testHtmlTagSkipPolicy7() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("span")
+ .disallowWithoutAttributes("span")
+ .toFactory();
+
+ String spanTagString = "<span>Hi</span>";
+ String resultString = beforePolicy.sanitize(spanTagString);
+ assertEquals("Hi", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("span")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(spanTagString);
+ assertEquals("Hi", resultString);
+ }
+
+ // Default Skip Tag
+ // beforePolicy : disallow
+ // afterPolicy : allow
+ @Test
+ public void testHtmlTagSkipPolicy8() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("span")
+ .disallowWithoutAttributes("span")
+ .toFactory();
+
+ String spanTagString = "<span>Hi</span>";
+ String resultString = beforePolicy.sanitize(spanTagString);
+ assertEquals("Hi", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("span")
+ .allowWithoutAttributes("span")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(spanTagString);
+ assertEquals("<span>Hi</span>", resultString);
+ }
+
+ // Default Skip Tag
+ // beforePolicy : disallow
+ // afterPolicy : disallow
+ @Test
+ public void testHtmlTagSkipPolicy9() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("span")
+ .disallowWithoutAttributes("span")
+ .toFactory();
+
+ String spanTagString = "<span>Hi</span>";
+ String resultString = beforePolicy.sanitize(spanTagString);
+ assertEquals("Hi", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("span")
+ .disallowWithoutAttributes("span")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(spanTagString);
+ assertEquals("Hi", resultString);
+ }
+
+ // Not Default Skip Tag
+ // beforePolicy : X
+ // afterPolicy : X
+ @Test
+ public void testHtmlTagSkipPolicy10() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("p")
+ .toFactory();
+
+ String pTagString = "<p>Hi</p>";
+ String resultString = beforePolicy.sanitize(pTagString);
+ assertEquals("<p>Hi</p>", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("p")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(pTagString);
+ assertEquals("<p>Hi</p>", resultString);
+ }
+
+ // Not Default Skip Tag
+ // beforePolicy : X
+ // afterPolicy : allow
+ @Test
+ public void testHtmlTagSkipPolicy11() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("p")
+ .toFactory();
+
+ String pTagString = "<p>Hi</p>";
+ String resultString = beforePolicy.sanitize(pTagString);
+ assertEquals("<p>Hi</p>", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("p")
+ .allowWithoutAttributes("p")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(pTagString);
+ assertEquals("<p>Hi</p>", resultString);
+ }
+
+ // Not Default Skip Tag
+ // beforePolicy : X
+ // afterPolicy : disallow
+ @Test
+ public void testHtmlTagSkipPolicy12() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("p")
+ .toFactory();
+
+ String pTagString = "<p>Hi</p>";
+ String resultString = beforePolicy.sanitize(pTagString);
+ assertEquals("<p>Hi</p>", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("p")
+ .disallowWithoutAttributes("p")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(pTagString);
+ assertEquals("Hi", resultString);
+ }
+
+ // Not Default Skip Tag
+ // beforePolicy : allow
+ // afterPolicy : X
+ @Test
+ public void testHtmlTagSkipPolicy13() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("p")
+ .allowWithoutAttributes("p")
+ .toFactory();
+
+ String pTagString = "<p>Hi</p>";
+ String resultString = beforePolicy.sanitize(pTagString);
+ assertEquals("<p>Hi</p>", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("p")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(pTagString);
+ assertEquals("<p>Hi</p>", resultString);
+ }
+
+ // Not Default Skip Tag
+ // beforePolicy : allow
+ // afterPolicy : allow
+ @Test
+ public void testHtmlTagSkipPolicy14() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("p")
+ .allowWithoutAttributes("p")
+ .toFactory();
+
+ String pTagString = "<p>Hi</p>";
+ String resultString = beforePolicy.sanitize(pTagString);
+ assertEquals("<p>Hi</p>", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("p")
+ .allowWithoutAttributes("p")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(pTagString);
+ assertEquals("<p>Hi</p>", resultString);
+ }
+
+ // Not Default Skip Tag
+ // beforePolicy : allow
+ // afterPolicy : disallow
+ @Test
+ public void testHtmlTagSkipPolicy15() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("p")
+ .allowWithoutAttributes("p")
+ .toFactory();
+
+ String pTagString = "<p>Hi</p>";
+ String resultString = beforePolicy.sanitize(pTagString);
+ assertEquals("<p>Hi</p>", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("p")
+ .disallowWithoutAttributes("p")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(pTagString);
+ assertEquals("Hi", resultString);
+ }
+
+ // Not Default Skip Tag
+ // beforePolicy : disallow
+ // afterPolicy : X
+ @Test
+ public void testHtmlTagSkipPolicy16() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("p")
+ .disallowWithoutAttributes("p")
+ .toFactory();
+
+ String pTagString = "<p>Hi</p>";
+ String resultString = beforePolicy.sanitize(pTagString);
+ assertEquals("Hi", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("p")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(pTagString);
+ assertEquals("Hi", resultString);
+ }
+
+ // Not Default Skip Tag
+ // beforePolicy : disallow
+ // afterPolicy : allow
+ @Test
+ public void testHtmlTagSkipPolicy17() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("p")
+ .disallowWithoutAttributes("p")
+ .toFactory();
+
+ String pTagString = "<p>Hi</p>";
+ String resultString = beforePolicy.sanitize(pTagString);
+ assertEquals("Hi", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("p")
+ .allowWithoutAttributes("p")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(pTagString);
+ assertEquals("<p>Hi</p>", resultString);
+ }
+
+ // Not Default Skip Tag
+ // beforePolicy : disallow
+ // afterPolicy : disallow
+ @Test
+ public void testHtmlTagSkipPolicy18() {
+ PolicyFactory beforePolicy = new HtmlPolicyBuilder()
+ .allowElements("p")
+ .disallowWithoutAttributes("p")
+ .toFactory();
+
+ String pTagString = "<p>Hi</p>";
+ String resultString = beforePolicy.sanitize(pTagString);
+ assertEquals("Hi", resultString);
+
+ PolicyFactory afterPolicy = beforePolicy.and(new HtmlPolicyBuilder()
+ .allowElements("p")
+ .disallowWithoutAttributes("p")
+ .toFactory());
+
+ resultString = afterPolicy.sanitize(pTagString);
+ assertEquals("Hi", resultString);
+ }
+
static final class SubstringFilter implements AttributePolicy {
final String substr;
diff --git a/src/test/java/org/owasp/html/SanitizersTest.java b/src/test/java/org/owasp/html/SanitizersTest.java
index 5841ada..4cb7bbc 100644
--- a/src/test/java/org/owasp/html/SanitizersTest.java
+++ b/src/test/java/org/owasp/html/SanitizersTest.java
@@ -434,11 +434,78 @@ public class SanitizersTest extends TestCase {
pf.sanitize(input));
}
+ @Test
+ public static final void testStyleTagsInAllTheWrongPlaces() {
+ String input = ""
+ + "<select><option><style><script>alert(1)</script></style></option></select>"
+ + "<svg><style>.r { color: red }</style></svg>"
+ + "<style>.b { color: blue }</style>";
+ PolicyFactory pf = new HtmlPolicyBuilder()
+ .allowElements("option", "select", "style", "svg")
+ .allowTextIn("style")
+ .toFactory();
+ assertEquals(
+ ""
+ + "<select><option>"
+ + "<style></style><script>alert(1)</script>"
+ + "</option></select>"
+ + "<svg>"
+ + "<style>.r { color: red }</style>"
+ + "</svg>"
+ + "<style>.b { color: blue }</style>",
+ pf.sanitize(input)
+ );
+ }
+
+ @Test
+ public static final void testSelectIsOdd() {
+ // Special text modes interact badly with select and option
+ String input = "<select><option><xmp><script>alert(1)</script></xmp></option></select>";
+ PolicyFactory pf = new HtmlPolicyBuilder()
+ .allowElements("option", "select", "xmp")
+ .allowTextIn("xmp", "option")
+ .toFactory();
+ assertEquals(
+ ""
+ + "<select><option><pre></pre>"
+ + "<script>alert(1)</script>"
+ + "</option></select>",
+ pf.sanitize(input)
+ );
+ }
+
+ @Test
+ public static final void testOptionAllowsText() {
+ String input = "<select><option><pre>code goes here</pre></option></select>";
+ PolicyFactory pf = new HtmlPolicyBuilder()
+ .allowElements("option", "select", "pre")
+ .allowTextIn("pre", "option")
+ .toFactory();
+ assertEquals(
+ ""
+ + "<select><option>"
+ + "<pre>code goes here</pre>"
+ + "</option></select>",
+ pf.sanitize(input)
+ );
+ }
+
+ @Test
+ public static final void testStyleGlobally() {
+ PolicyFactory policyBuilder = new HtmlPolicyBuilder()
+ .allowAttributes("style").globally()
+ .allowElements("a", "label", "h1", "h2", "h3", "h4", "h5", "h6")
+ .toFactory();
+ String input = "<h1 style=\"color:green ;name:user ;\">This is some green text</h1>";
+ String want = "<h1 style=\"color:green\">This is some green text</h1>";
+ assertEquals(want, policyBuilder.sanitize(input));
+ }
+
static int fac(int n) {
int ifac = 1;
for (int i = 1; i <= n; ++i) {
int ifacp = ifac * i;
- if (ifacp < ifac) { throw new IllegalArgumentException("undeflow"); }
+ if (ifacp < ifac) { throw new IllegalArgumentException("underflow"); }
ifac = ifacp;
}
return ifac;
diff --git a/src/test/java/org/owasp/html/TagBalancingHtmlStreamRendererTest.java b/src/test/java/org/owasp/html/TagBalancingHtmlStreamRendererTest.java
index 004e95c..38a854e 100644
--- a/src/test/java/org/owasp/html/TagBalancingHtmlStreamRendererTest.java
+++ b/src/test/java/org/owasp/html/TagBalancingHtmlStreamRendererTest.java
@@ -158,7 +158,9 @@ public class TagBalancingHtmlStreamRendererTest extends TestCase {
+ "<p>Hello, <textarea>World!</textarea></p>"
+ "<h1>Hello"
// Text allowed in special style tag.
- + "<style type=\"text/css\">\n.World {\n color: blue\n}\n</style></h1>"
+ + "<style type=\"text/css\">\n"
+ + ".World {\n color: blue\n}\n"
+ + "</style></h1>"
// Whitespace allowed inside <ul> but non-whitespace text nodes are
// moved inside <li>.
+ "<ul><li>Hello,</li><li>World!</li></ul>",
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/share/maven-repo/com/googlecode/owasp-java-html-sanitizer/owasp-java-html-sanitizer/20220608.2-SNAPSHOT/owasp-java-html-sanitizer-20220608.2-SNAPSHOT.pom lrwxrwxrwx root/root /usr/share/java/owasp-java-html-sanitizer-20220608.2-SNAPSHOT.jar -> owasp-java-html-sanitizer.jar lrwxrwxrwx root/root /usr/share/maven-repo/com/googlecode/owasp-java-html-sanitizer/owasp-java-html-sanitizer/20220608.2-SNAPSHOT/owasp-java-html-sanitizer-20220608.2-SNAPSHOT.jar -> ../../../../../../java/owasp-java-html-sanitizer.jar
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/share/maven-repo/com/googlecode/owasp-java-html-sanitizer/owasp-java-html-sanitizer/20191001.1/owasp-java-html-sanitizer-20191001.1.pom lrwxrwxrwx root/root /usr/share/java/owasp-java-html-sanitizer-20191001.1.jar -> owasp-java-html-sanitizer.jar lrwxrwxrwx root/root /usr/share/maven-repo/com/googlecode/owasp-java-html-sanitizer/owasp-java-html-sanitizer/20191001.1/owasp-java-html-sanitizer-20191001.1.jar -> ../../../../../../java/owasp-java-html-sanitizer.jar
No differences were encountered in the control files