You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by je...@apache.org on 2018/10/25 16:40:12 UTC
[sling-whiteboard] branch master updated: initial commit
This is an automated email from the ASF dual-hosted git repository.
jeb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
The following commit(s) were added to refs/heads/master by this push:
new 87bcf1b initial commit
87bcf1b is described below
commit 87bcf1b9d002cb26e1bf377f58697a07373c4278
Author: JE Bailey <ja...@sas.com>
AuthorDate: Wed Oct 24 12:39:51 2018 -0400
initial commit
---
tag-modifier/LICENSE | 201 ++
tag-modifier/README.md | 45 +
tag-modifier/pom.xml | 105 +
.../org/apache/sling/tagmodifier/AttrValue.java | 96 +
.../java/org/apache/sling/tagmodifier/Element.java | 87 +
.../org/apache/sling/tagmodifier/ElementType.java | 21 +
.../java/org/apache/sling/tagmodifier/Tag.java | 52 +
.../org/apache/sling/tagmodifier/TagIterator.java | 74 +
.../org/apache/sling/tagmodifier/TagMapping.java | 64 +
.../java/org/apache/sling/tagmodifier/Visitor.java | 21 +
.../sling/tagmodifier/consumer/HtmlSAXSupport.java | 90 +
.../sling/tagmodifier/impl/ParseException.java | 187 ++
.../sling/tagmodifier/impl/SimpleCharStream.java | 471 ++++
.../apache/sling/tagmodifier/impl/TagParser.java | 532 +++++
.../sling/tagmodifier/impl/TagParserConstants.java | 113 +
.../tagmodifier/impl/TagParserTokenManager.java | 1138 ++++++++++
.../org/apache/sling/tagmodifier/impl/Token.java | 131 ++
.../sling/tagmodifier/impl/TokenMgrError.java | 147 ++
.../impl/components/HtmlGeneratorFactory.java | 110 +
.../tagmodifier/impl/components/TagHtmlParser.java | 62 +
.../apache/sling/tagmodifier/impl/tag/Comment.java | 51 +
.../apache/sling/tagmodifier/impl/tag/DocType.java | 52 +
.../sling/tagmodifier/impl/tag/EndOfFile.java | 45 +
.../apache/sling/tagmodifier/impl/tag/EndTag.java | 49 +
.../sling/tagmodifier/impl/tag/StartTag.java | 52 +
.../sling/tagmodifier/impl/tag/TextData.java | 66 +
.../sling/tagmodifier/map/HtmlTextEncoder.java | 75 +
.../org/apache/sling/tagmodifier/package-info.java | 15 +
.../apache/sling/tagmodifier/util/DOMBuilder.java | 171 ++
.../sling/tagmodifier/util/Html5Entities.java | 2273 ++++++++++++++++++++
.../tagmodifier/util/HtmlEntityTranslator.java | 37 +
.../apache/sling/tagmodifier/util/HtmlStreams.java | 72 +
tag-modifier/src/main/javacc/htmlParser.jj | 231 ++
tag-modifier/src/main/resources/entities.json | 2233 +++++++++++++++++++
tag-modifier/src/main/resources/structure.json | 87 +
.../java/com/github/htmlparser/HtmlParseTest.java | 117 +
.../com/github/htmlparser/UnusualHtmlTest.java | 65 +
tag-modifier/src/test/resources/demo.html | 864 ++++++++
tag-modifier/src/test/resources/fail.html | 23 +
39 files changed, 10325 insertions(+)
diff --git a/tag-modifier/LICENSE b/tag-modifier/LICENSE
new file mode 100644
index 0000000..261eeb9
--- /dev/null
+++ b/tag-modifier/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/tag-modifier/README.md b/tag-modifier/README.md
new file mode 100644
index 0000000..8f1d0d5
--- /dev/null
+++ b/tag-modifier/README.md
@@ -0,0 +1,45 @@
+[](https://www.apache.org/licenses/LICENSE-2.0)
+
+# TagStream
+Module to provide a fast, HTML5/XML tokenzier. TagStream takes an InputStream and tokenizes into a Tag or Text element which can be used for inspection or transformation by leveraging Java's Stream API.
+
+This provides:
+* Reduced memory footprint by eliminating the virtual dom
+* Event based/pull processing of the source
+* Enables stream processing from an input to an output stream
+
+
+## Using TagStream
+There are multiple ways which provides access to the processing of an HTML/XML source.
+
+### Iteration
+The ``TagIterator`` allows you to iterate the HTML/XML document utilizing a pull methodology. Whenever you request the next element, the element is tokenized from the InputStream
+
+### Stream
+The ``Tag`` class wraps the ``TagIterator`` to provide a ``Stream<Element>`` provider.
+
+
+Examples:
+
+```java
+//count the number of start tags
+Tag.stream(inputStream).filter(elem -> elem.getType() == ElementType.START_TAG ).count();
+```
+
+```java
+// find any elements that has an href attribute that doesn't point anywhere
+// print out the bad links as an html list of anchors
+stream.filter(elem -> elem.getType() == ElementType.START_TAG && elem.hasAttribute("href") )
+ .filter(elem -> isLinkBad(elem.getAttribute("href")))
+ .map(HtmlStreams.TO_HTML)
+ .forEach(System.out::println);
+```
+
+```java
+//count the number of tags
+HtmlSAXSupport saxEventGenerator = new HtmlSAXSupport(customHandler);
+Tag.stream(inputStream).forEach(saxEventGenerator);
+```
+TagStream works by using the W3C's HTML5 *parsing* rules to properly identify a Tag. This is a separate set of guidelines from what defines valid HTML. The TagStream parser responds with a Tag or Text element and then proceeds to the next section. It does not attempt to create a DOM tree, it doesn't perform validation of tag it found. It assumes that you know what you are doing and won't judge you.
+
+
diff --git a/tag-modifier/pom.xml b/tag-modifier/pom.xml
new file mode 100644
index 0000000..b9effb1
--- /dev/null
+++ b/tag-modifier/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor
+ license agreements. See the NOTICE file distributed with this work for additional
+ information regarding copyright ownership. The ASF licenses this file to
+ you under the Apache License, Version 2.0 (the "License"); you may not use
+ this file except in compliance with the License. You may obtain a copy of
+ the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required
+ by applicable law or agreed to in writing, software distributed under the
+ License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
+ OF ANY KIND, either express or implied. See the License for the specific
+ language governing permissions and limitations under the License. -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>sling</artifactId>
+ <version>34</version>
+ </parent>
+
+ <artifactId>org.apache.sling.tag-modifier</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+
+ <name>Apache Sling Tag Modifier</name>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.resources.sourceEncoding>UTF-8</project.resources.sourceEncoding>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>maven-sling-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>javacc-maven-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>javacc</id>
+ <goals>
+ <goal>javacc</goal>
+ </goals>
+ <configuration>
+ <jdkVersion>1.8</jdkVersion>
+ <javadocFriendlyComments>true</javadocFriendlyComments>
+ <outputDirectory>${basedir}/src/main/java</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.testing.sling-mock</artifactId>
+ <version>2.2.10</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.commons.johnzon</artifactId>
+ <version>1.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-text</artifactId>
+ <version>1.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.annotation.versioning</artifactId>
+ <version>1.1.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.api</artifactId>
+ <version>2.18.4</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.commons.html</artifactId>
+ <version>1.0.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.rewriter</artifactId>
+ <version>1.2.2</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <packaging>bundle</packaging>
+</project>
\ No newline at end of file
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/AttrValue.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/AttrValue.java
new file mode 100644
index 0000000..23bc487
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/AttrValue.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier;
+
+import java.util.function.Predicate;
+import java.util.regex.Pattern;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+@ProviderType
+public class AttrValue implements CharSequence {
+
+ Predicate<String> nonQuotable = Pattern.compile("^[a-zA-Z][-_a-zA-Z0-9\\u00A0-\\u10FFFF]*$").asPredicate();
+
+ private String value;
+
+ public AttrValue() {
+ }
+
+ public AttrValue(String value) {
+ this.value = value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public String quoteIfNeeded() {
+ if (shouldBeQuoted()) {
+ return getQuoted('"');
+ }
+ return value;
+ }
+
+ public String getQuoted(char paren) {
+ if (isEmpty()) {
+ return null;
+ }
+ return paren + value + paren;
+ }
+
+ public boolean shouldBeQuoted() {
+ if (isEmpty()) {
+ return false;
+ }
+ return nonQuotable.negate().test(value);
+ }
+
+ public boolean isEmpty() {
+ return value == null;
+ }
+
+ @Override
+ public int length() {
+ if (isEmpty()) {
+ return 0;
+ }
+ return value.length();
+ }
+
+ @Override
+ public char charAt(int index) {
+ if (isEmpty()) {
+ throw new IndexOutOfBoundsException();
+ }
+ return value.charAt(index);
+ }
+
+ @Override
+ public CharSequence subSequence(int start, int end) {
+ if (isEmpty()) {
+ throw new IndexOutOfBoundsException();
+ }
+ return value.subSequence(start, end);
+ }
+ @Override
+ public String toString() {
+ return value;
+ }
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/Element.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/Element.java
new file mode 100644
index 0000000..64639ac
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/Element.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier;
+
+import java.util.Map;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+@ProviderType
+public interface Element {
+ /**
+ * Retrieve the associated ElementType
+ *
+ * @return the type of element
+ */
+ ElementType getType();
+
+ /**
+ * Must be defined as true to allow default methods to work correctly, this
+ * method and the getAttributes method are used together to implement attribute
+ * support in an element.
+ *
+ * @return true if Element supports attributes
+ */
+ boolean supportsAttributes();
+
+ Map<String, AttrValue> getAttributes();
+
+ /**
+ * The String value that best represents what this element is.
+ *
+ * @return
+ */
+ String getValue();
+
+ /**
+ * Accepts a Visitor to visit
+ *
+ * @param visitor
+ * @return
+ */
+ default <T> T accept(Visitor<T> visitor) {
+ return visitor.visit(this);
+ }
+
+ /**
+ * Whether this element contains Attributes
+ *
+ * @return
+ */
+ default boolean hasAttributes() {
+ if (supportsAttributes()) {
+ return !getAttributes().isEmpty();
+ }
+ return false;
+ }
+
+ default boolean containsAttribute(String attrName) {
+ return getAttributes().containsKey(attrName);
+ }
+
+ default String getAttributeValue(String name) {
+ if (supportsAttributes()) {
+ return getAttributes().get(name).toString();
+ }
+ return null;
+ }
+
+ default void setAttribute(String name, String value) {
+ if (supportsAttributes()) {
+ getAttributes().put(name, new AttrValue(value));
+ return;
+ }
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/ElementType.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/ElementType.java
new file mode 100644
index 0000000..7e09d9e
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/ElementType.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+@ProviderType
+public enum ElementType {
+ EOF, START_TAG, COMMENT, END_TAG, TEXT, DOCTYPE;
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/Tag.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/Tag.java
new file mode 100644
index 0000000..facaad3
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/Tag.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Provides access to a stream of elements from a XML/HTML source
+ *
+ */
+@ProviderType
+public class Tag {
+
+ private Tag() {
+ }
+
+ public static Stream<Element> stream(String input) {
+ return stream(new ByteArrayInputStream(input.getBytes()));
+ }
+
+ public static Stream<Element> stream(InputStream is) {
+ return stream(new TagIterator(is));
+ }
+
+ public static Stream<Element> stream(InputStream is, String encoding) {
+ return stream(new TagIterator(is, encoding));
+ }
+
+ private static Stream<Element> stream(TagIterator iterator) {
+ return StreamSupport.stream(
+ Spliterators.spliteratorUnknownSize(iterator, Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
+ }
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/TagIterator.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/TagIterator.java
new file mode 100644
index 0000000..7f450ba
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/TagIterator.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier;
+
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import org.apache.sling.tagmodifier.impl.ParseException;
+import org.apache.sling.tagmodifier.impl.TagParser;
+import org.osgi.annotation.versioning.ProviderType;
+
+@ProviderType
+public class TagIterator implements Iterator<Element> {
+
+ private Element current;
+
+ boolean eof = false;
+ private TagParser parser;
+
+ public TagIterator(InputStream is) {
+ parser = new TagParser(is);
+ }
+
+ public TagIterator(InputStream is, String encoding) {
+ parser = new TagParser(is, encoding);
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (current == null && !eof) {
+ return seek();
+ }
+ return !eof;
+ }
+
+ @Override
+ public Element next() {
+ if (current == null && !eof) {
+ seek();
+ }
+ if (current == null || eof) {
+ throw new NoSuchElementException();
+ }
+ Element response = current;
+ current = null;
+ return response;
+ }
+
+ private boolean seek() {
+ if (eof) {
+ return false;
+ }
+ try {
+ current = parser.element();
+ eof = (current.getType() == ElementType.EOF);
+ return !eof;
+ } catch (ParseException e) {
+ }
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/TagMapping.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/TagMapping.java
new file mode 100644
index 0000000..369b754
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/TagMapping.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Utility class that allows you to define a flatMap process in the form of a
+ * BiConsumer<Element,TagMapping> lambda.
+ *
+ * This allows you to use the next() method to collect the elements that will be
+ * passed on to the stream method. This can modify the eventual output and assists in use cases where
+ * there is a need to add or remove elements
+ *
+ */
+@ProviderType
+public class TagMapping {
+
+ private List<Element> list = new ArrayList<>();
+
+ private TagMapping() {
+ }
+
+ /**
+ * Collects all the elements that are either being passed through or created in
+ * the accept method of the consumer so that they may be passed on to the next
+ * process.
+ */
+ public void next(Element... elements) {
+ Collections.addAll(list, elements);
+ }
+
+ Function<Element, Stream<Element>> createFlatMap(BiConsumer<Element, TagMapping> consumer, TagMapping mapper) {
+ return element -> {
+ list.clear();
+ consumer.accept(element, mapper);
+ return list.stream();
+ };
+ }
+
+ public static Function<Element, Stream<Element>> map(BiConsumer<Element, TagMapping> consumer) {
+ TagMapping mapper = new TagMapping();
+ return mapper.createFlatMap(consumer, mapper);
+ }
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/Visitor.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/Visitor.java
new file mode 100644
index 0000000..ac9a609
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/Visitor.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.sling.tagmodifier;
+
+public interface Visitor<T> {
+
+ T visit(Element element);
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/consumer/HtmlSAXSupport.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/consumer/HtmlSAXSupport.java
new file mode 100644
index 0000000..3c4aa87
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/consumer/HtmlSAXSupport.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier.consumer;
+
+import java.util.Map;
+import java.util.function.Consumer;
+
+import org.apache.sling.tagmodifier.AttrValue;
+import org.apache.sling.tagmodifier.Element;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.Attributes2Impl;
+import org.xml.sax.ext.DefaultHandler2;
+import org.xml.sax.ext.LexicalHandler;
+
+public class HtmlSAXSupport implements Consumer<Element> {
+
+ private static final DefaultHandler2 handler = new DefaultHandler2();
+
+ private ContentHandler contentHandler = handler;
+ private LexicalHandler lexicalHandler = handler;
+ private boolean initialized;
+
+ public HtmlSAXSupport(ContentHandler ch, final LexicalHandler lh) {
+ if (ch != null) {
+ contentHandler = ch;
+ }
+ if (lh != null ) {
+ lexicalHandler = lh;
+ }
+ }
+
+ @Override
+ public void accept(Element element) {
+ try {
+ if (!initialized) {
+ contentHandler.startDocument();
+ initialized = true;
+ }
+ String value = element.getValue();
+ switch (element.getType()) {
+ case COMMENT:
+ lexicalHandler.comment(value.toCharArray(), 0, value.length());
+ break;
+ case DOCTYPE:
+ break;
+ case END_TAG:
+ lexicalHandler.endEntity(value);
+ contentHandler.endElement("", value, value);
+ break;
+ case EOF:
+ contentHandler.endDocument();
+ break;
+ case START_TAG:
+ lexicalHandler.startEntity(value);
+ contentHandler.startElement("", value, value, HtmlSAXSupport.convert(element.getAttributes()));
+ break;
+ case TEXT:
+ contentHandler.characters(value.toCharArray(), 0, value.toCharArray().length);
+ break;
+ default:
+ break;
+ }
+ } catch (SAXException se) {
+ //log message
+ }
+
+ }
+
+ public static Attributes convert(Map<String,AttrValue> attributes) {
+ Attributes2Impl response = new Attributes2Impl();
+ attributes.entrySet().forEach(attr ->
+ response.addAttribute("",attr.getKey(), attr.getKey(), "xsi:String", attr.getValue().toString())
+ );
+ return response;
+ }
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/ParseException.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/ParseException.java
new file mode 100644
index 0000000..bb13d80
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/ParseException.java
@@ -0,0 +1,187 @@
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 5.0 */
+/* JavaCCOptions:KEEP_LINE_COL=null */
+package org.apache.sling.tagmodifier.impl;
+
+/**
+ * This exception is thrown when parse errors are encountered.
+ * You can explicitly create objects of this exception type by
+ * calling the method generateParseException in the generated
+ * parser.
+ *
+ * You can modify this class to customize your error reporting
+ * mechanisms so long as you retain the public fields.
+ */
+public class ParseException extends Exception {
+
+ /**
+ * The version identifier for this Serializable class.
+ * Increment only if the <i>serialized</i> form of the
+ * class changes.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * This constructor is used by the method "generateParseException"
+ * in the generated parser. Calling this constructor generates
+ * a new object of this type with the fields "currentToken",
+ * "expectedTokenSequences", and "tokenImage" set.
+ */
+ public ParseException(Token currentTokenVal,
+ int[][] expectedTokenSequencesVal,
+ String[] tokenImageVal
+ )
+ {
+ super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
+ currentToken = currentTokenVal;
+ expectedTokenSequences = expectedTokenSequencesVal;
+ tokenImage = tokenImageVal;
+ }
+
+ /**
+ * The following constructors are for use by you for whatever
+ * purpose you can think of. Constructing the exception in this
+ * manner makes the exception behave in the normal way - i.e., as
+ * documented in the class "Throwable". The fields "errorToken",
+ * "expectedTokenSequences", and "tokenImage" do not contain
+ * relevant information. The JavaCC generated code does not use
+ * these constructors.
+ */
+
+ public ParseException() {
+ super();
+ }
+
+ /** Constructor with message. */
+ public ParseException(String message) {
+ super(message);
+ }
+
+
+ /**
+ * This is the last token that has been consumed successfully. If
+ * this object has been created due to a parse error, the token
+ * followng this token will (therefore) be the first error token.
+ */
+ public Token currentToken;
+
+ /**
+ * Each entry in this array is an array of integers. Each array
+ * of integers represents a sequence of tokens (by their ordinal
+ * values) that is expected at this point of the parse.
+ */
+ public int[][] expectedTokenSequences;
+
+ /**
+ * This is a reference to the "tokenImage" array of the generated
+ * parser within which the parse error occurred. This array is
+ * defined in the generated ...Constants interface.
+ */
+ public String[] tokenImage;
+
+ /**
+ * It uses "currentToken" and "expectedTokenSequences" to generate a parse
+ * error message and returns it. If this object has been created
+ * due to a parse error, and you do not catch it (it gets thrown
+ * from the parser) the correct error message
+ * gets displayed.
+ */
+ private static String initialise(Token currentToken,
+ int[][] expectedTokenSequences,
+ String[] tokenImage) {
+ String eol = System.getProperty("line.separator", "\n");
+ StringBuffer expected = new StringBuffer();
+ int maxSize = 0;
+ for (int i = 0; i < expectedTokenSequences.length; i++) {
+ if (maxSize < expectedTokenSequences[i].length) {
+ maxSize = expectedTokenSequences[i].length;
+ }
+ for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+ expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
+ }
+ if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+ expected.append("...");
+ }
+ expected.append(eol).append(" ");
+ }
+ String retval = "Encountered \"";
+ Token tok = currentToken.next;
+ for (int i = 0; i < maxSize; i++) {
+ if (i != 0) retval += " ";
+ if (tok.kind == 0) {
+ retval += tokenImage[0];
+ break;
+ }
+ retval += " " + tokenImage[tok.kind];
+ retval += " \"";
+ retval += add_escapes(tok.image);
+ retval += " \"";
+ tok = tok.next;
+ }
+ retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+ retval += "." + eol;
+ if (expectedTokenSequences.length == 1) {
+ retval += "Was expecting:" + eol + " ";
+ } else {
+ retval += "Was expecting one of:" + eol + " ";
+ }
+ retval += expected.toString();
+ return retval;
+ }
+
+ /**
+ * The end of line string for this machine.
+ */
+ protected String eol = System.getProperty("line.separator", "\n");
+
+ /**
+ * Used to convert raw characters to their escaped version
+ * when these raw version cannot be used as part of an ASCII
+ * string literal.
+ */
+ static String add_escapes(String str) {
+ StringBuffer retval = new StringBuffer();
+ char ch;
+ for (int i = 0; i < str.length(); i++) {
+ switch (str.charAt(i))
+ {
+ case 0 :
+ continue;
+ case '\b':
+ retval.append("\\b");
+ continue;
+ case '\t':
+ retval.append("\\t");
+ continue;
+ case '\n':
+ retval.append("\\n");
+ continue;
+ case '\f':
+ retval.append("\\f");
+ continue;
+ case '\r':
+ retval.append("\\r");
+ continue;
+ case '\"':
+ retval.append("\\\"");
+ continue;
+ case '\'':
+ retval.append("\\\'");
+ continue;
+ case '\\':
+ retval.append("\\\\");
+ continue;
+ default:
+ if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+ String s = "0000" + Integer.toString(ch, 16);
+ retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+ } else {
+ retval.append(ch);
+ }
+ continue;
+ }
+ }
+ return retval.toString();
+ }
+
+}
+/* JavaCC - OriginalChecksum=ba1d20fcfc9de1875bf962a12af6f93e (do not edit this line) */
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/SimpleCharStream.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/SimpleCharStream.java
new file mode 100644
index 0000000..da12233
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/SimpleCharStream.java
@@ -0,0 +1,471 @@
+/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 5.0 */
+/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package org.apache.sling.tagmodifier.impl;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (without unicode processing).
+ */
+
+public class SimpleCharStream
+{
+/** Whether parser is static. */
+ public static final boolean staticFlag = false;
+ int bufsize;
+ int available;
+ int tokenBegin;
+/** Position in buffer. */
+ public int bufpos = -1;
+ protected int bufline[];
+ protected int bufcolumn[];
+
+ protected int column = 0;
+ protected int line = 1;
+
+ protected boolean prevCharIsCR = false;
+ protected boolean prevCharIsLF = false;
+
+ protected java.io.Reader inputStream;
+
+ protected char[] buffer;
+ protected int maxNextCharInd = 0;
+ protected int inBuf = 0;
+ protected int tabSize = 8;
+
+ protected void setTabSize(int i) { tabSize = i; }
+ protected int getTabSize(int i) { return tabSize; }
+
+
+ protected void ExpandBuff(boolean wrapAround)
+ {
+ char[] newbuffer = new char[bufsize + 2048];
+ int newbufline[] = new int[bufsize + 2048];
+ int newbufcolumn[] = new int[bufsize + 2048];
+
+ try
+ {
+ if (wrapAround)
+ {
+ System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+ System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
+ buffer = newbuffer;
+
+ System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+ System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+ bufline = newbufline;
+
+ System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+ System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+ bufcolumn = newbufcolumn;
+
+ maxNextCharInd = (bufpos += (bufsize - tokenBegin));
+ }
+ else
+ {
+ System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+ buffer = newbuffer;
+
+ System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+ bufline = newbufline;
+
+ System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+ bufcolumn = newbufcolumn;
+
+ maxNextCharInd = (bufpos -= tokenBegin);
+ }
+ }
+ catch (Throwable t)
+ {
+ throw new Error(t.getMessage());
+ }
+
+
+ bufsize += 2048;
+ available = bufsize;
+ tokenBegin = 0;
+ }
+
+ protected void FillBuff() throws java.io.IOException
+ {
+ if (maxNextCharInd == available)
+ {
+ if (available == bufsize)
+ {
+ if (tokenBegin > 2048)
+ {
+ bufpos = maxNextCharInd = 0;
+ available = tokenBegin;
+ }
+ else if (tokenBegin < 0)
+ bufpos = maxNextCharInd = 0;
+ else
+ ExpandBuff(false);
+ }
+ else if (available > tokenBegin)
+ available = bufsize;
+ else if ((tokenBegin - available) < 2048)
+ ExpandBuff(true);
+ else
+ available = tokenBegin;
+ }
+
+ int i;
+ try {
+ if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
+ {
+ inputStream.close();
+ throw new java.io.IOException();
+ }
+ else
+ maxNextCharInd += i;
+ return;
+ }
+ catch(java.io.IOException e) {
+ --bufpos;
+ backup(0);
+ if (tokenBegin == -1)
+ tokenBegin = bufpos;
+ throw e;
+ }
+ }
+
+/** Start. */
+ public char BeginToken() throws java.io.IOException
+ {
+ tokenBegin = -1;
+ char c = readChar();
+ tokenBegin = bufpos;
+
+ return c;
+ }
+
+ protected void UpdateLineColumn(char c)
+ {
+ column++;
+
+ if (prevCharIsLF)
+ {
+ prevCharIsLF = false;
+ line += (column = 1);
+ }
+ else if (prevCharIsCR)
+ {
+ prevCharIsCR = false;
+ if (c == '\n')
+ {
+ prevCharIsLF = true;
+ }
+ else
+ line += (column = 1);
+ }
+
+ switch (c)
+ {
+ case '\r' :
+ prevCharIsCR = true;
+ break;
+ case '\n' :
+ prevCharIsLF = true;
+ break;
+ case '\t' :
+ column--;
+ column += (tabSize - (column % tabSize));
+ break;
+ default :
+ break;
+ }
+
+ bufline[bufpos] = line;
+ bufcolumn[bufpos] = column;
+ }
+
+/** Read a character. */
+ public char readChar() throws java.io.IOException
+ {
+ if (inBuf > 0)
+ {
+ --inBuf;
+
+ if (++bufpos == bufsize)
+ bufpos = 0;
+
+ return buffer[bufpos];
+ }
+
+ if (++bufpos >= maxNextCharInd)
+ FillBuff();
+
+ char c = buffer[bufpos];
+
+ UpdateLineColumn(c);
+ return c;
+ }
+
+ @Deprecated
+ /**
+ * @deprecated
+ * @see #getEndColumn
+ */
+
+ public int getColumn() {
+ return bufcolumn[bufpos];
+ }
+
+ @Deprecated
+ /**
+ * @deprecated
+ * @see #getEndLine
+ */
+
+ public int getLine() {
+ return bufline[bufpos];
+ }
+
+ /** Get token end column number. */
+ public int getEndColumn() {
+ return bufcolumn[bufpos];
+ }
+
+ /** Get token end line number. */
+ public int getEndLine() {
+ return bufline[bufpos];
+ }
+
+ /** Get token beginning column number. */
+ public int getBeginColumn() {
+ return bufcolumn[tokenBegin];
+ }
+
+ /** Get token beginning line number. */
+ public int getBeginLine() {
+ return bufline[tokenBegin];
+ }
+
+/** Backup a number of characters. */
+ public void backup(int amount) {
+
+ inBuf += amount;
+ if ((bufpos -= amount) < 0)
+ bufpos += bufsize;
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.Reader dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ inputStream = dstream;
+ line = startline;
+ column = startcolumn - 1;
+
+ available = bufsize = buffersize;
+ buffer = new char[buffersize];
+ bufline = new int[buffersize];
+ bufcolumn = new int[buffersize];
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.Reader dstream, int startline,
+ int startcolumn)
+ {
+ this(dstream, startline, startcolumn, 4096);
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.Reader dstream)
+ {
+ this(dstream, 1, 1, 4096);
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.Reader dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ inputStream = dstream;
+ line = startline;
+ column = startcolumn - 1;
+
+ if (buffer == null || buffersize != buffer.length)
+ {
+ available = bufsize = buffersize;
+ buffer = new char[buffersize];
+ bufline = new int[buffersize];
+ bufcolumn = new int[buffersize];
+ }
+ prevCharIsLF = prevCharIsCR = false;
+ tokenBegin = inBuf = maxNextCharInd = 0;
+ bufpos = -1;
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.Reader dstream, int startline,
+ int startcolumn)
+ {
+ ReInit(dstream, startline, startcolumn, 4096);
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.Reader dstream)
+ {
+ ReInit(dstream, 1, 1, 4096);
+ }
+ /** Constructor. */
+ public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+ {
+ this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.InputStream dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn) throws java.io.UnsupportedEncodingException
+ {
+ this(dstream, encoding, startline, startcolumn, 4096);
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.InputStream dstream, int startline,
+ int startcolumn)
+ {
+ this(dstream, startline, startcolumn, 4096);
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+ {
+ this(dstream, encoding, 1, 1, 4096);
+ }
+
+ /** Constructor. */
+ public SimpleCharStream(java.io.InputStream dstream)
+ {
+ this(dstream, 1, 1, 4096);
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+ {
+ ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, int startline,
+ int startcolumn, int buffersize)
+ {
+ ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+ {
+ ReInit(dstream, encoding, 1, 1, 4096);
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream)
+ {
+ ReInit(dstream, 1, 1, 4096);
+ }
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+ int startcolumn) throws java.io.UnsupportedEncodingException
+ {
+ ReInit(dstream, encoding, startline, startcolumn, 4096);
+ }
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream dstream, int startline,
+ int startcolumn)
+ {
+ ReInit(dstream, startline, startcolumn, 4096);
+ }
+ /** Get token literal value. */
+ public String GetImage()
+ {
+ if (bufpos >= tokenBegin)
+ return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+ else
+ return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+ new String(buffer, 0, bufpos + 1);
+ }
+
+ /** Get the suffix. */
+ public char[] GetSuffix(int len)
+ {
+ char[] ret = new char[len];
+
+ if ((bufpos + 1) >= len)
+ System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+ else
+ {
+ System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+ len - bufpos - 1);
+ System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+ }
+
+ return ret;
+ }
+
+ /** Reset buffer when finished. */
+ public void Done()
+ {
+ buffer = null;
+ bufline = null;
+ bufcolumn = null;
+ }
+
+ /**
+ * Method to adjust line and column numbers for the start of a token.
+ */
+ public void adjustBeginLineColumn(int newLine, int newCol)
+ {
+ int start = tokenBegin;
+ int len;
+
+ if (bufpos >= tokenBegin)
+ {
+ len = bufpos - tokenBegin + inBuf + 1;
+ }
+ else
+ {
+ len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+ }
+
+ int i = 0, j = 0, k = 0;
+ int nextColDiff = 0, columnDiff = 0;
+
+ while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
+ {
+ bufline[j] = newLine;
+ nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+ bufcolumn[j] = newCol + columnDiff;
+ columnDiff = nextColDiff;
+ i++;
+ }
+
+ if (i < len)
+ {
+ bufline[j] = newLine++;
+ bufcolumn[j] = newCol + columnDiff;
+
+ while (i++ < len)
+ {
+ if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+ bufline[j] = newLine++;
+ else
+ bufline[j] = newLine;
+ }
+ }
+
+ line = bufline[j];
+ column = bufcolumn[j];
+ }
+
+}
+/* JavaCC - OriginalChecksum=4df3cbf20a871d13662e770c6d3acff3 (do not edit this line) */
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/TagParser.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/TagParser.java
new file mode 100644
index 0000000..85c8ca9
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/TagParser.java
@@ -0,0 +1,532 @@
+/* Generated By:JavaCC: Do not edit this line. TagParser.java */
+package org.apache.sling.tagmodifier.impl;
+
+import java.util.*;
+
+import org.apache.sling.tagmodifier.*;
+import org.apache.sling.tagmodifier.impl.tag.*;
+
+public class TagParser implements TagParserConstants {
+
+ private static String getTokenHtmlText(Token first, Token cur) {
+ Token t;
+ StringBuilder sb = new StringBuilder();
+
+ for (t=first; t != cur.next; t = t.next) {
+ if (t.specialToken != null) {
+ Token tt=t.specialToken;
+ while (tt.specialToken != null)
+ tt = tt.specialToken;
+ for (; tt != null; tt = tt.next)
+ sb.append(tt.image);
+ };
+ sb.append(t.image);
+ };
+ return sb.toString();
+ }
+
+ final public Element element() throws ParseException {
+ Element e;
+ Token text;
+ if (jj_2_1(2)) {
+ e = tag();
+ {if (true) return e;}
+ } else {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case ENDTAG_START:
+ e = endHtmlElement();
+ {if (true) return e;}
+ break;
+ case COMMENT_START:
+ e = commentHtmlElement();
+ {if (true) return e;}
+ break;
+ case DECL_START:
+ e = decltag();
+ {if (true) return e;}
+ break;
+ default:
+ jj_la1[0] = jj_gen;
+ if (jj_2_2(2)) {
+ jj_consume_token(TAG_START);
+ text = jj_consume_token(LST_ERROR);
+ {if (true) return new TextData("<" + text.image);}
+ } else {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case RAWTEXT:
+ text = jj_consume_token(RAWTEXT);
+ {if (true) return new TextData(text.image);}
+ break;
+ case 0:
+ jj_consume_token(0);
+ {if (true) return new EndOfFile();}
+ break;
+ default:
+ jj_la1[1] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ }
+ }
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+/** @return an attribute */
+ final public void attribute(Map<String,AttrValue > alist) throws ParseException {
+ Token t1, t2=null;
+ t1 = jj_consume_token(ATTR_NAME);
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case ATTR_EQ:
+ case ATTR_VAL:
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case ATTR_EQ:
+ jj_consume_token(ATTR_EQ);
+ t2 = jj_consume_token(QUOTED_STRING);
+ break;
+ case ATTR_VAL:
+ t2 = jj_consume_token(ATTR_VAL);
+ break;
+ default:
+ jj_la1[2] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ break;
+ default:
+ jj_la1[3] = jj_gen;
+ ;
+ }
+ if (t2 == null) {
+ alist.put(t1.image,new AttrValue());
+ } else {
+ alist.put(t1.image,new AttrValue(t2.image));
+ }
+ }
+
+ final public Map<String,AttrValue> attributeList() throws ParseException {
+ Map<String,AttrValue> alist = new HashMap<String,AttrValue>();
+ label_1:
+ while (true) {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case ATTR_NAME:
+ ;
+ break;
+ default:
+ jj_la1[4] = jj_gen;
+ break label_1;
+ }
+ attribute(alist);
+ }
+ {if (true) return alist;}
+ throw new Error("Missing return statement in function");
+ }
+
+ final public Element tag() throws ParseException {
+ Token t, et;
+ Map<String,AttrValue> alist;
+ Token firstToken = getToken(1);
+ try {
+ jj_consume_token(TAG_START);
+ t = jj_consume_token(TAG_NAME);
+ alist = attributeList();
+ et = jj_consume_token(END_OF_TAG);
+ {if (true) return new StartTag(t.image, alist);}
+ } catch (ParseException ex) {
+ token_source.SwitchTo(DEFAULT);
+ String s = getTokenHtmlText(firstToken, getNextToken());
+ {if (true) return new TextData(s);}
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+/** @return the end of a tag */
+ final public Element endHtmlElement() throws ParseException {
+ Token t;
+ Token firstToken = getToken(1);
+ try {
+ jj_consume_token(ENDTAG_START);
+ t = jj_consume_token(TAG_NAME);
+ jj_consume_token(END_OF_TAG);
+ {if (true) return new EndTag(t.image);}
+ } catch (ParseException ex) {
+ token_source.SwitchTo(DEFAULT);
+ String s = getTokenHtmlText(firstToken, getNextToken());
+ {if (true) return new TextData(s);}
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+ final public Comment commentHtmlElement() throws ParseException {
+ StringBuilder sb = new StringBuilder();
+ jj_consume_token(COMMENT_START);
+ label_2:
+ while (true) {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case COMMENT_WORD:
+ ;
+ break;
+ default:
+ jj_la1[5] = jj_gen;
+ break label_2;
+ }
+ jj_consume_token(COMMENT_WORD);
+ sb.append(token.image);
+ }
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case 0:
+ jj_consume_token(0);
+ break;
+ case COMMENT_END:
+ jj_consume_token(COMMENT_END);
+ break;
+ default:
+ jj_la1[6] = jj_gen;
+ jj_consume_token(-1);
+ throw new ParseException();
+ }
+ {if (true) return new Comment(sb.toString());}
+ throw new Error("Missing return statement in function");
+ }
+
+/** @return the start of a DECLARATION */
+ final public Element decltag() throws ParseException {
+ Token tok = null;
+ Map<String,AttrValue > alist = new HashMap<String,AttrValue>();
+ Token firstToken = getToken(1);
+ try {
+ jj_consume_token(DECL_START);
+ tok = jj_consume_token(DECL_TAG);
+ label_3:
+ while (true) {
+ switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
+ case DECL_ATTR:
+ ;
+ break;
+ default:
+ jj_la1[7] = jj_gen;
+ break label_3;
+ }
+ jj_consume_token(DECL_ATTR);
+ alist.put(token.image,new AttrValue());
+ }
+ jj_consume_token(DECL_END);
+ {if (true) return new StartTag(tok.image, alist);}
+ } catch (ParseException ex) {
+ token_source.SwitchTo(DEFAULT);
+ String s = getTokenHtmlText(firstToken, getNextToken());
+ {if (true) return new TextData(s);}
+ }
+ throw new Error("Missing return statement in function");
+ }
+
+ private boolean jj_2_1(int xla) {
+ jj_la = xla; jj_lastpos = jj_scanpos = token;
+ try { return !jj_3_1(); }
+ catch(LookaheadSuccess ls) { return true; }
+ finally { jj_save(0, xla); }
+ }
+
+ private boolean jj_2_2(int xla) {
+ jj_la = xla; jj_lastpos = jj_scanpos = token;
+ try { return !jj_3_2(); }
+ catch(LookaheadSuccess ls) { return true; }
+ finally { jj_save(1, xla); }
+ }
+
+ private boolean jj_3_1() {
+ if (jj_3R_4()) return true;
+ return false;
+ }
+
+ private boolean jj_3_2() {
+ if (jj_scan_token(TAG_START)) return true;
+ if (jj_scan_token(LST_ERROR)) return true;
+ return false;
+ }
+
+ private boolean jj_3R_4() {
+ if (jj_scan_token(TAG_START)) return true;
+ if (jj_scan_token(TAG_NAME)) return true;
+ return false;
+ }
+
+ /** Generated Token Manager. */
+ public TagParserTokenManager token_source;
+ SimpleCharStream jj_input_stream;
+ /** Current token. */
+ public Token token;
+ /** Next token. */
+ public Token jj_nt;
+ private int jj_ntk;
+ private Token jj_scanpos, jj_lastpos;
+ private int jj_la;
+ private int jj_gen;
+ final private int[] jj_la1 = new int[8];
+ static private int[] jj_la1_0;
+ static {
+ jj_la1_init_0();
+ }
+ private static void jj_la1_init_0() {
+ jj_la1_0 = new int[] {0xe00,0x1001,0x240000,0x240000,0x10000,0x1000000,0x800001,0x4000000,};
+ }
+ final private JJCalls[] jj_2_rtns = new JJCalls[2];
+ private boolean jj_rescan = false;
+ private int jj_gc = 0;
+
+ /** Constructor with InputStream. */
+ public TagParser(java.io.InputStream stream) {
+ this(stream, null);
+ }
+ /** Constructor with InputStream and supplied encoding */
+ public TagParser(java.io.InputStream stream, String encoding) {
+ try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+ token_source = new TagParserTokenManager(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 8; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream stream) {
+ ReInit(stream, null);
+ }
+ /** Reinitialise. */
+ public void ReInit(java.io.InputStream stream, String encoding) {
+ try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+ token_source.ReInit(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 8; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ /** Constructor. */
+ public TagParser(java.io.Reader stream) {
+ jj_input_stream = new SimpleCharStream(stream, 1, 1);
+ token_source = new TagParserTokenManager(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 8; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ /** Reinitialise. */
+ public void ReInit(java.io.Reader stream) {
+ jj_input_stream.ReInit(stream, 1, 1);
+ token_source.ReInit(jj_input_stream);
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 8; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ /** Constructor with generated Token Manager. */
+ public TagParser(TagParserTokenManager tm) {
+ token_source = tm;
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 8; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ /** Reinitialise. */
+ public void ReInit(TagParserTokenManager tm) {
+ token_source = tm;
+ token = new Token();
+ jj_ntk = -1;
+ jj_gen = 0;
+ for (int i = 0; i < 8; i++) jj_la1[i] = -1;
+ for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
+ }
+
+ private Token jj_consume_token(int kind) throws ParseException {
+ Token oldToken;
+ if ((oldToken = token).next != null) token = token.next;
+ else token = token.next = token_source.getNextToken();
+ jj_ntk = -1;
+ if (token.kind == kind) {
+ jj_gen++;
+ if (++jj_gc > 100) {
+ jj_gc = 0;
+ for (int i = 0; i < jj_2_rtns.length; i++) {
+ JJCalls c = jj_2_rtns[i];
+ while (c != null) {
+ if (c.gen < jj_gen) c.first = null;
+ c = c.next;
+ }
+ }
+ }
+ return token;
+ }
+ token = oldToken;
+ jj_kind = kind;
+ throw generateParseException();
+ }
+
+ static private final class LookaheadSuccess extends java.lang.Error { }
+ final private LookaheadSuccess jj_ls = new LookaheadSuccess();
+ private boolean jj_scan_token(int kind) {
+ if (jj_scanpos == jj_lastpos) {
+ jj_la--;
+ if (jj_scanpos.next == null) {
+ jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
+ } else {
+ jj_lastpos = jj_scanpos = jj_scanpos.next;
+ }
+ } else {
+ jj_scanpos = jj_scanpos.next;
+ }
+ if (jj_rescan) {
+ int i = 0; Token tok = token;
+ while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
+ if (tok != null) jj_add_error_token(kind, i);
+ }
+ if (jj_scanpos.kind != kind) return true;
+ if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
+ return false;
+ }
+
+
+/** Get the next Token. */
+ final public Token getNextToken() {
+ if (token.next != null) token = token.next;
+ else token = token.next = token_source.getNextToken();
+ jj_ntk = -1;
+ jj_gen++;
+ return token;
+ }
+
+/** Get the specific Token. */
+ final public Token getToken(int index) {
+ Token t = token;
+ for (int i = 0; i < index; i++) {
+ if (t.next != null) t = t.next;
+ else t = t.next = token_source.getNextToken();
+ }
+ return t;
+ }
+
+ private int jj_ntk() {
+ if ((jj_nt=token.next) == null)
+ return (jj_ntk = (token.next=token_source.getNextToken()).kind);
+ else
+ return (jj_ntk = jj_nt.kind);
+ }
+
+ private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>();
+ private int[] jj_expentry;
+ private int jj_kind = -1;
+ private int[] jj_lasttokens = new int[100];
+ private int jj_endpos;
+
+ private void jj_add_error_token(int kind, int pos) {
+ if (pos >= 100) return;
+ if (pos == jj_endpos + 1) {
+ jj_lasttokens[jj_endpos++] = kind;
+ } else if (jj_endpos != 0) {
+ jj_expentry = new int[jj_endpos];
+ for (int i = 0; i < jj_endpos; i++) {
+ jj_expentry[i] = jj_lasttokens[i];
+ }
+ jj_entries_loop: for (java.util.Iterator<?> it = jj_expentries.iterator(); it.hasNext();) {
+ int[] oldentry = (int[])(it.next());
+ if (oldentry.length == jj_expentry.length) {
+ for (int i = 0; i < jj_expentry.length; i++) {
+ if (oldentry[i] != jj_expentry[i]) {
+ continue jj_entries_loop;
+ }
+ }
+ jj_expentries.add(jj_expentry);
+ break jj_entries_loop;
+ }
+ }
+ if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
+ }
+ }
+
+ /** Generate ParseException. */
+ public ParseException generateParseException() {
+ jj_expentries.clear();
+ boolean[] la1tokens = new boolean[28];
+ if (jj_kind >= 0) {
+ la1tokens[jj_kind] = true;
+ jj_kind = -1;
+ }
+ for (int i = 0; i < 8; i++) {
+ if (jj_la1[i] == jj_gen) {
+ for (int j = 0; j < 32; j++) {
+ if ((jj_la1_0[i] & (1<<j)) != 0) {
+ la1tokens[j] = true;
+ }
+ }
+ }
+ }
+ for (int i = 0; i < 28; i++) {
+ if (la1tokens[i]) {
+ jj_expentry = new int[1];
+ jj_expentry[0] = i;
+ jj_expentries.add(jj_expentry);
+ }
+ }
+ jj_endpos = 0;
+ jj_rescan_token();
+ jj_add_error_token(0, 0);
+ int[][] exptokseq = new int[jj_expentries.size()][];
+ for (int i = 0; i < jj_expentries.size(); i++) {
+ exptokseq[i] = jj_expentries.get(i);
+ }
+ return new ParseException(token, exptokseq, tokenImage);
+ }
+
+ /** Enable tracing. */
+ final public void enable_tracing() {
+ }
+
+ /** Disable tracing. */
+ final public void disable_tracing() {
+ }
+
+ private void jj_rescan_token() {
+ jj_rescan = true;
+ for (int i = 0; i < 2; i++) {
+ try {
+ JJCalls p = jj_2_rtns[i];
+ do {
+ if (p.gen > jj_gen) {
+ jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
+ switch (i) {
+ case 0: jj_3_1(); break;
+ case 1: jj_3_2(); break;
+ }
+ }
+ p = p.next;
+ } while (p != null);
+ } catch(LookaheadSuccess ls) { }
+ }
+ jj_rescan = false;
+ }
+
+ private void jj_save(int index, int xla) {
+ JJCalls p = jj_2_rtns[index];
+ while (p.gen > jj_gen) {
+ if (p.next == null) { p = p.next = new JJCalls(); break; }
+ p = p.next;
+ }
+ p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
+ }
+
+ static final class JJCalls {
+ int gen;
+ Token first;
+ int arg;
+ JJCalls next;
+ }
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/TagParserConstants.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/TagParserConstants.java
new file mode 100644
index 0000000..035c5e8
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/TagParserConstants.java
@@ -0,0 +1,113 @@
+/* Generated By:JavaCC: Do not edit this line. TagParserConstants.java */
+package org.apache.sling.tagmodifier.impl;
+
+
+/**
+ * Token literal values and constants.
+ * Generated by org.javacc.parser.OtherFilesGen#start()
+ */
+public interface TagParserConstants {
+
+ /** End of File. */
+ int EOF = 0;
+ /** RegularExpression Id. */
+ int SPACE = 1;
+ /** RegularExpression Id. */
+ int ATTR_IDENTIFIER = 2;
+ /** RegularExpression Id. */
+ int NAME_IDENTIFIER = 3;
+ /** RegularExpression Id. */
+ int SQUOTE = 4;
+ /** RegularExpression Id. */
+ int DQUOTE = 5;
+ /** RegularExpression Id. */
+ int TAG_END = 6;
+ /** RegularExpression Id. */
+ int TAG_SLASHEND = 7;
+ /** RegularExpression Id. */
+ int TAG_START = 8;
+ /** RegularExpression Id. */
+ int ENDTAG_START = 9;
+ /** RegularExpression Id. */
+ int COMMENT_START = 10;
+ /** RegularExpression Id. */
+ int DECL_START = 11;
+ /** RegularExpression Id. */
+ int RAWTEXT = 12;
+ /** RegularExpression Id. */
+ int TAG_NAME = 13;
+ /** RegularExpression Id. */
+ int LST_ERROR = 14;
+ /** RegularExpression Id. */
+ int ATTR_NAME = 16;
+ /** RegularExpression Id. */
+ int END_OF_TAG = 17;
+ /** RegularExpression Id. */
+ int ATTR_EQ = 18;
+ /** RegularExpression Id. */
+ int LIT_ERROR = 19;
+ /** RegularExpression Id. */
+ int QUOTED_STRING = 20;
+ /** RegularExpression Id. */
+ int ATTR_VAL = 21;
+ /** RegularExpression Id. */
+ int ERROR = 22;
+ /** RegularExpression Id. */
+ int COMMENT_END = 23;
+ /** RegularExpression Id. */
+ int COMMENT_WORD = 24;
+ /** RegularExpression Id. */
+ int DECL_TAG = 25;
+ /** RegularExpression Id. */
+ int DECL_ATTR = 26;
+ /** RegularExpression Id. */
+ int DECL_END = 27;
+
+ /** Lexical state. */
+ int DECLARATION = 0;
+ /** Lexical state. */
+ int COMMENT = 1;
+ /** Lexical state. */
+ int IN_DECLARATION = 2;
+ /** Lexical state. */
+ int ATTR_VALUE = 3;
+ /** Lexical state. */
+ int IN_TAG = 4;
+ /** Lexical state. */
+ int START_TAG = 5;
+ /** Lexical state. */
+ int DEFAULT = 6;
+
+ /** Literal token values. */
+ String[] tokenImage = {
+ "<EOF>",
+ "<SPACE>",
+ "<ATTR_IDENTIFIER>",
+ "<NAME_IDENTIFIER>",
+ "<SQUOTE>",
+ "<DQUOTE>",
+ "\">\"",
+ "\"/>\"",
+ "\"<\"",
+ "\"</\"",
+ "\"<!--\"",
+ "\"<!\"",
+ "<RAWTEXT>",
+ "<TAG_NAME>",
+ "<LST_ERROR>",
+ "<token of kind 15>",
+ "<ATTR_NAME>",
+ "<END_OF_TAG>",
+ "\"=\"",
+ "<LIT_ERROR>",
+ "<QUOTED_STRING>",
+ "<ATTR_VAL>",
+ "<ERROR>",
+ "\"-->\"",
+ "<COMMENT_WORD>",
+ "<DECL_TAG>",
+ "<DECL_ATTR>",
+ "<DECL_END>",
+ };
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/TagParserTokenManager.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/TagParserTokenManager.java
new file mode 100644
index 0000000..15c0f72
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/TagParserTokenManager.java
@@ -0,0 +1,1138 @@
+/* Generated By:JavaCC: Do not edit this line. TagParserTokenManager.java */
+package org.apache.sling.tagmodifier.impl;
+import java.util.*;
+
+import org.apache.sling.tagmodifier.*;
+import org.apache.sling.tagmodifier.impl.tag.*;
+
+/** Token Manager. */
+public class TagParserTokenManager implements TagParserConstants
+{
+
+ /** Debug output. */
+ public java.io.PrintStream debugStream = System.out;
+ /** Set debug output. */
+ public void setDebugStream(java.io.PrintStream ds) { debugStream = ds; }
+private final int jjStopStringLiteralDfa_6(int pos, long active0)
+{
+ switch (pos)
+ {
+ default :
+ return -1;
+ }
+}
+private final int jjStartNfa_6(int pos, long active0)
+{
+ return jjMoveNfa_6(jjStopStringLiteralDfa_6(pos, active0), pos + 1);
+}
+private int jjStopAtPos(int pos, int kind)
+{
+ jjmatchedKind = kind;
+ jjmatchedPos = pos;
+ return pos + 1;
+}
+private int jjMoveStringLiteralDfa0_6()
+{
+ switch(curChar)
+ {
+ case 60:
+ jjmatchedKind = 8;
+ return jjMoveStringLiteralDfa1_6(0xe00L);
+ default :
+ return jjMoveNfa_6(0, 0);
+ }
+}
+private int jjMoveStringLiteralDfa1_6(long active0)
+{
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_6(0, active0);
+ return 1;
+ }
+ switch(curChar)
+ {
+ case 33:
+ if ((active0 & 0x800L) != 0L)
+ {
+ jjmatchedKind = 11;
+ jjmatchedPos = 1;
+ }
+ return jjMoveStringLiteralDfa2_6(active0, 0x400L);
+ case 47:
+ if ((active0 & 0x200L) != 0L)
+ return jjStopAtPos(1, 9);
+ break;
+ default :
+ break;
+ }
+ return jjStartNfa_6(0, active0);
+}
+private int jjMoveStringLiteralDfa2_6(long old0, long active0)
+{
+ if (((active0 &= old0)) == 0L)
+ return jjStartNfa_6(0, old0);
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_6(1, active0);
+ return 2;
+ }
+ switch(curChar)
+ {
+ case 45:
+ return jjMoveStringLiteralDfa3_6(active0, 0x400L);
+ default :
+ break;
+ }
+ return jjStartNfa_6(1, active0);
+}
+private int jjMoveStringLiteralDfa3_6(long old0, long active0)
+{
+ if (((active0 &= old0)) == 0L)
+ return jjStartNfa_6(1, old0);
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ jjStopStringLiteralDfa_6(2, active0);
+ return 3;
+ }
+ switch(curChar)
+ {
+ case 45:
+ if ((active0 & 0x400L) != 0L)
+ return jjStopAtPos(3, 10);
+ break;
+ default :
+ break;
+ }
+ return jjStartNfa_6(2, active0);
+}
+static final long[] jjbitVec0 = {
+ 0xfffffffffffffffeL, 0xffffffffffffffffL, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+static final long[] jjbitVec2 = {
+ 0x0L, 0x0L, 0xffffffffffffffffL, 0xffffffffffffffffL
+};
+private int jjMoveNfa_6(int startState, int curPos)
+{
+ int startsAt = 0;
+ jjnewStateCnt = 1;
+ int i = 1;
+ jjstateSet[0] = startState;
+ int kind = 0x7fffffff;
+ for (;;)
+ {
+ if (++jjround == 0x7fffffff)
+ ReInitRounds();
+ if (curChar < 64)
+ {
+ long l = 1L << curChar;
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ if ((0xefffffffffffffffL & l) == 0L)
+ break;
+ kind = 12;
+ jjstateSet[jjnewStateCnt++] = 0;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ long l = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ kind = 12;
+ jjstateSet[jjnewStateCnt++] = 0;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else
+ {
+ int hiByte = (int)(curChar >> 8);
+ int i1 = hiByte >> 6;
+ long l1 = 1L << (hiByte & 077);
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ if (!jjCanMove_0(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 12)
+ kind = 12;
+ jjstateSet[jjnewStateCnt++] = 0;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 1 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return curPos; }
+ }
+}
+private int jjMoveStringLiteralDfa0_5()
+{
+ return jjMoveNfa_5(0, 0);
+}
+private int jjMoveNfa_5(int startState, int curPos)
+{
+ int startsAt = 0;
+ jjnewStateCnt = 1;
+ int i = 1;
+ jjstateSet[0] = startState;
+ int kind = 0x7fffffff;
+ for (;;)
+ {
+ if (++jjround == 0x7fffffff)
+ ReInitRounds();
+ if (curChar < 64)
+ {
+ long l = 1L << curChar;
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ if ((0xbfff7ffeffffc9ffL & l) == 0L)
+ break;
+ kind = 13;
+ jjstateSet[jjnewStateCnt++] = 0;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ long l = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ kind = 13;
+ jjstateSet[jjnewStateCnt++] = 0;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else
+ {
+ int hiByte = (int)(curChar >> 8);
+ int i1 = hiByte >> 6;
+ long l1 = 1L << (hiByte & 077);
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ if (!jjCanMove_0(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 13)
+ kind = 13;
+ jjstateSet[jjnewStateCnt++] = 0;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 1 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return curPos; }
+ }
+}
+private int jjMoveStringLiteralDfa0_1()
+{
+ switch(curChar)
+ {
+ case 45:
+ return jjMoveStringLiteralDfa1_1(0x800000L);
+ default :
+ return 1;
+ }
+}
+private int jjMoveStringLiteralDfa1_1(long active0)
+{
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ return 1;
+ }
+ switch(curChar)
+ {
+ case 45:
+ return jjMoveStringLiteralDfa2_1(active0, 0x800000L);
+ default :
+ return 2;
+ }
+}
+private int jjMoveStringLiteralDfa2_1(long old0, long active0)
+{
+ if (((active0 &= old0)) == 0L)
+ return 2;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) {
+ return 2;
+ }
+ switch(curChar)
+ {
+ case 62:
+ if ((active0 & 0x800000L) != 0L)
+ return jjStopAtPos(2, 23);
+ break;
+ default :
+ return 3;
+ }
+ return 3;
+}
+private int jjMoveStringLiteralDfa0_2()
+{
+ return jjMoveNfa_2(2, 0);
+}
+private int jjMoveNfa_2(int startState, int curPos)
+{
+ int startsAt = 0;
+ jjnewStateCnt = 11;
+ int i = 1;
+ jjstateSet[0] = startState;
+ int kind = 0x7fffffff;
+ for (;;)
+ {
+ if (++jjround == 0x7fffffff)
+ ReInitRounds();
+ if (curChar < 64)
+ {
+ long l = 1L << curChar;
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 2:
+ if ((0xbfffff7affffd9ffL & l) != 0L)
+ {
+ if (kind > 26)
+ kind = 26;
+ jjCheckNAdd(1);
+ }
+ else if (curChar == 62)
+ {
+ if (kind > 27)
+ kind = 27;
+ }
+ else if (curChar == 39)
+ jjCheckNAddTwoStates(6, 7);
+ else if (curChar == 34)
+ jjCheckNAddTwoStates(3, 4);
+ if ((0x100003600L & l) != 0L)
+ {
+ if (kind > 15)
+ kind = 15;
+ jjCheckNAdd(0);
+ }
+ else if (curChar == 47)
+ jjstateSet[jjnewStateCnt++] = 9;
+ break;
+ case 0:
+ if ((0x100003600L & l) == 0L)
+ break;
+ if (kind > 15)
+ kind = 15;
+ jjCheckNAdd(0);
+ break;
+ case 1:
+ if ((0xbfffff7affffd9ffL & l) == 0L)
+ break;
+ if (kind > 26)
+ kind = 26;
+ jjCheckNAdd(1);
+ break;
+ case 3:
+ if ((0xfffffffbffffffffL & l) != 0L)
+ jjCheckNAddTwoStates(3, 4);
+ break;
+ case 4:
+ if (curChar == 34 && kind > 26)
+ kind = 26;
+ break;
+ case 5:
+ if (curChar == 39)
+ jjCheckNAddTwoStates(6, 7);
+ break;
+ case 6:
+ if ((0xffffff7fffffffffL & l) != 0L)
+ jjCheckNAddTwoStates(6, 7);
+ break;
+ case 7:
+ if (curChar == 39 && kind > 26)
+ kind = 26;
+ break;
+ case 8:
+ case 9:
+ if (curChar == 62 && kind > 27)
+ kind = 27;
+ break;
+ case 10:
+ if (curChar == 47)
+ jjstateSet[jjnewStateCnt++] = 9;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ long l = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 2:
+ case 1:
+ if (kind > 26)
+ kind = 26;
+ jjCheckNAdd(1);
+ break;
+ case 3:
+ jjAddStates(0, 1);
+ break;
+ case 6:
+ jjAddStates(2, 3);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else
+ {
+ int hiByte = (int)(curChar >> 8);
+ int i1 = hiByte >> 6;
+ long l1 = 1L << (hiByte & 077);
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 2:
+ case 1:
+ if (!jjCanMove_0(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 26)
+ kind = 26;
+ jjCheckNAdd(1);
+ break;
+ case 3:
+ if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+ jjAddStates(0, 1);
+ break;
+ case 6:
+ if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+ jjAddStates(2, 3);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 11 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return curPos; }
+ }
+}
+private int jjMoveStringLiteralDfa0_0()
+{
+ return jjMoveNfa_0(0, 0);
+}
+private int jjMoveNfa_0(int startState, int curPos)
+{
+ int startsAt = 0;
+ jjnewStateCnt = 1;
+ int i = 1;
+ jjstateSet[0] = startState;
+ int kind = 0x7fffffff;
+ for (;;)
+ {
+ if (++jjround == 0x7fffffff)
+ ReInitRounds();
+ if (curChar < 64)
+ {
+ long l = 1L << curChar;
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ if ((0xbfff7ffeffffc9ffL & l) == 0L)
+ break;
+ kind = 25;
+ jjstateSet[jjnewStateCnt++] = 0;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ long l = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ kind = 25;
+ jjstateSet[jjnewStateCnt++] = 0;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else
+ {
+ int hiByte = (int)(curChar >> 8);
+ int i1 = hiByte >> 6;
+ long l1 = 1L << (hiByte & 077);
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 0:
+ if (!jjCanMove_0(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 25)
+ kind = 25;
+ jjstateSet[jjnewStateCnt++] = 0;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 1 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return curPos; }
+ }
+}
+private final int jjStopStringLiteralDfa_4(int pos, long active0)
+{
+ switch (pos)
+ {
+ default :
+ return -1;
+ }
+}
+private final int jjStartNfa_4(int pos, long active0)
+{
+ return jjMoveNfa_4(jjStopStringLiteralDfa_4(pos, active0), pos + 1);
+}
+private int jjMoveStringLiteralDfa0_4()
+{
+ switch(curChar)
+ {
+ case 61:
+ return jjStopAtPos(0, 18);
+ default :
+ return jjMoveNfa_4(2, 0);
+ }
+}
+private int jjMoveNfa_4(int startState, int curPos)
+{
+ int startsAt = 0;
+ jjnewStateCnt = 5;
+ int i = 1;
+ jjstateSet[0] = startState;
+ int kind = 0x7fffffff;
+ for (;;)
+ {
+ if (++jjround == 0x7fffffff)
+ ReInitRounds();
+ if (curChar < 64)
+ {
+ long l = 1L << curChar;
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 2:
+ if ((0x9fff7ffeffffc9ffL & l) != 0L)
+ {
+ if (kind > 16)
+ kind = 16;
+ jjCheckNAdd(1);
+ }
+ else if ((0x100003600L & l) != 0L)
+ {
+ if (kind > 15)
+ kind = 15;
+ jjCheckNAdd(0);
+ }
+ else if (curChar == 47)
+ jjstateSet[jjnewStateCnt++] = 3;
+ else if (curChar == 62)
+ {
+ if (kind > 17)
+ kind = 17;
+ }
+ break;
+ case 0:
+ if ((0x100003600L & l) == 0L)
+ break;
+ kind = 15;
+ jjCheckNAdd(0);
+ break;
+ case 1:
+ if ((0x9fff7ffeffffc9ffL & l) == 0L)
+ break;
+ kind = 16;
+ jjCheckNAdd(1);
+ break;
+ case 3:
+ if (curChar == 62 && kind > 17)
+ kind = 17;
+ break;
+ case 4:
+ if (curChar == 47)
+ jjstateSet[jjnewStateCnt++] = 3;
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ long l = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 2:
+ case 1:
+ kind = 16;
+ jjCheckNAdd(1);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else
+ {
+ int hiByte = (int)(curChar >> 8);
+ int i1 = hiByte >> 6;
+ long l1 = 1L << (hiByte & 077);
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 2:
+ case 1:
+ if (!jjCanMove_0(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 16)
+ kind = 16;
+ jjCheckNAdd(1);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 5 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return curPos; }
+ }
+}
+private int jjMoveStringLiteralDfa0_3()
+{
+ return jjMoveNfa_3(1, 0);
+}
+private int jjMoveNfa_3(int startState, int curPos)
+{
+ int startsAt = 0;
+ jjnewStateCnt = 8;
+ int i = 1;
+ jjstateSet[0] = startState;
+ int kind = 0x7fffffff;
+ for (;;)
+ {
+ if (++jjround == 0x7fffffff)
+ ReInitRounds();
+ if (curChar < 64)
+ {
+ long l = 1L << curChar;
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 1:
+ if ((0xbfffff7affffd9ffL & l) != 0L)
+ {
+ if (kind > 21)
+ kind = 21;
+ jjCheckNAdd(7);
+ }
+ else if (curChar == 34)
+ jjCheckNAddTwoStates(5, 6);
+ else if (curChar == 39)
+ jjCheckNAddTwoStates(2, 3);
+ if ((0x100003600L & l) != 0L)
+ {
+ if (kind > 15)
+ kind = 15;
+ jjCheckNAdd(0);
+ }
+ break;
+ case 0:
+ if ((0x100003600L & l) == 0L)
+ break;
+ if (kind > 15)
+ kind = 15;
+ jjCheckNAdd(0);
+ break;
+ case 2:
+ if ((0xffffff7fffffffffL & l) != 0L)
+ jjCheckNAddTwoStates(2, 3);
+ break;
+ case 3:
+ if (curChar == 39 && kind > 20)
+ kind = 20;
+ break;
+ case 4:
+ if (curChar == 34)
+ jjCheckNAddTwoStates(5, 6);
+ break;
+ case 5:
+ if ((0xfffffffbffffffffL & l) != 0L)
+ jjCheckNAddTwoStates(5, 6);
+ break;
+ case 6:
+ if (curChar == 34 && kind > 20)
+ kind = 20;
+ break;
+ case 7:
+ if ((0xbfffff7affffd9ffL & l) == 0L)
+ break;
+ if (kind > 21)
+ kind = 21;
+ jjCheckNAdd(7);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else if (curChar < 128)
+ {
+ long l = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 1:
+ case 7:
+ if (kind > 21)
+ kind = 21;
+ jjCheckNAdd(7);
+ break;
+ case 2:
+ jjAddStates(4, 5);
+ break;
+ case 5:
+ jjAddStates(6, 7);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ else
+ {
+ int hiByte = (int)(curChar >> 8);
+ int i1 = hiByte >> 6;
+ long l1 = 1L << (hiByte & 077);
+ int i2 = (curChar & 0xff) >> 6;
+ long l2 = 1L << (curChar & 077);
+ do
+ {
+ switch(jjstateSet[--i])
+ {
+ case 1:
+ case 7:
+ if (!jjCanMove_0(hiByte, i1, i2, l1, l2))
+ break;
+ if (kind > 21)
+ kind = 21;
+ jjCheckNAdd(7);
+ break;
+ case 2:
+ if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+ jjAddStates(4, 5);
+ break;
+ case 5:
+ if (jjCanMove_0(hiByte, i1, i2, l1, l2))
+ jjAddStates(6, 7);
+ break;
+ default : break;
+ }
+ } while(i != startsAt);
+ }
+ if (kind != 0x7fffffff)
+ {
+ jjmatchedKind = kind;
+ jjmatchedPos = curPos;
+ kind = 0x7fffffff;
+ }
+ ++curPos;
+ if ((i = jjnewStateCnt) == (startsAt = 8 - (jjnewStateCnt = startsAt)))
+ return curPos;
+ try { curChar = input_stream.readChar(); }
+ catch(java.io.IOException e) { return curPos; }
+ }
+}
+static final int[] jjnextStates = {
+ 3, 4, 6, 7, 2, 3, 5, 6,
+};
+private static final boolean jjCanMove_0(int hiByte, int i1, int i2, long l1, long l2)
+{
+ switch(hiByte)
+ {
+ case 0:
+ return ((jjbitVec2[i2] & l2) != 0L);
+ default :
+ if ((jjbitVec0[i1] & l1) != 0L)
+ return true;
+ return false;
+ }
+}
+
+/** Token literal values. */
+public static final String[] jjstrLiteralImages = {
+"", null, null, null, null, null, null, null, "\74", "\74\57", "\74\41\55\55",
+"\74\41", null, null, null, null, null, null, "\75", null, null, null, null,
+"\55\55\76", null, null, null, null, };
+
+/** Lexer state names. */
+public static final String[] lexStateNames = {
+ "DECLARATION",
+ "COMMENT",
+ "IN_DECLARATION",
+ "ATTR_VALUE",
+ "IN_TAG",
+ "START_TAG",
+ "DEFAULT",
+};
+
+/** Lex State array. */
+public static final int[] jjnewLexState = {
+ -1, -1, -1, -1, -1, -1, -1, -1, 5, 5, 1, 0, -1, 4, 6, -1, -1, 6, 3, -1, 4, 4, -1, 6, -1,
+ 2, -1, 6,
+};
+static final long[] jjtoToken = {
+ 0xfff7f01L,
+};
+static final long[] jjtoSkip = {
+ 0x8000L,
+};
+static final long[] jjtoSpecial = {
+ 0x8000L,
+};
+protected SimpleCharStream input_stream;
+private final int[] jjrounds = new int[11];
+private final int[] jjstateSet = new int[22];
+private final StringBuilder jjimage = new StringBuilder();
+private StringBuilder image = jjimage;
+private int jjimageLen;
+private int lengthOfMatch;
+protected char curChar;
+/** Constructor. */
+public TagParserTokenManager(SimpleCharStream stream){
+ if (SimpleCharStream.staticFlag)
+ throw new Error("ERROR: Cannot use a static CharStream class with a non-static lexical analyzer.");
+ input_stream = stream;
+}
+
+/** Constructor. */
+public TagParserTokenManager(SimpleCharStream stream, int lexState){
+ this(stream);
+ SwitchTo(lexState);
+}
+
+/** Reinitialise parser. */
+public void ReInit(SimpleCharStream stream)
+{
+ jjmatchedPos = jjnewStateCnt = 0;
+ curLexState = defaultLexState;
+ input_stream = stream;
+ ReInitRounds();
+}
+private void ReInitRounds()
+{
+ int i;
+ jjround = 0x80000001;
+ for (i = 11; i-- > 0;)
+ jjrounds[i] = 0x80000000;
+}
+
+/** Reinitialise parser. */
+public void ReInit(SimpleCharStream stream, int lexState)
+{
+ ReInit(stream);
+ SwitchTo(lexState);
+}
+
+/** Switch to specified lex state. */
+public void SwitchTo(int lexState)
+{
+ if (lexState >= 7 || lexState < 0)
+ throw new TokenMgrError("Error: Ignoring invalid lexical state : " + lexState + ". State unchanged.", TokenMgrError.INVALID_LEXICAL_STATE);
+ else
+ curLexState = lexState;
+}
+
+protected Token jjFillToken()
+{
+ final Token t;
+ final String curTokenImage;
+ final int beginLine;
+ final int endLine;
+ final int beginColumn;
+ final int endColumn;
+ String im = jjstrLiteralImages[jjmatchedKind];
+ curTokenImage = (im == null) ? input_stream.GetImage() : im;
+ beginLine = input_stream.getBeginLine();
+ beginColumn = input_stream.getBeginColumn();
+ endLine = input_stream.getEndLine();
+ endColumn = input_stream.getEndColumn();
+ t = Token.newToken(jjmatchedKind, curTokenImage);
+
+ t.beginLine = beginLine;
+ t.endLine = endLine;
+ t.beginColumn = beginColumn;
+ t.endColumn = endColumn;
+
+ return t;
+}
+
+int curLexState = 6;
+int defaultLexState = 6;
+int jjnewStateCnt;
+int jjround;
+int jjmatchedPos;
+int jjmatchedKind;
+
+/** Get the next Token. */
+public Token getNextToken()
+{
+ Token specialToken = null;
+ Token matchedToken;
+ int curPos = 0;
+
+ EOFLoop :
+ for (;;)
+ {
+ try
+ {
+ curChar = input_stream.BeginToken();
+ }
+ catch(java.io.IOException e)
+ {
+ jjmatchedKind = 0;
+ matchedToken = jjFillToken();
+ matchedToken.specialToken = specialToken;
+ return matchedToken;
+ }
+ image = jjimage;
+ image.setLength(0);
+ jjimageLen = 0;
+
+ switch(curLexState)
+ {
+ case 0:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_0();
+ break;
+ case 1:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_1();
+ if (jjmatchedPos == 0 && jjmatchedKind > 24)
+ {
+ jjmatchedKind = 24;
+ }
+ break;
+ case 2:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_2();
+ break;
+ case 3:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_3();
+ if (jjmatchedPos == 0 && jjmatchedKind > 22)
+ {
+ jjmatchedKind = 22;
+ }
+ break;
+ case 4:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_4();
+ if (jjmatchedPos == 0 && jjmatchedKind > 19)
+ {
+ jjmatchedKind = 19;
+ }
+ break;
+ case 5:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_5();
+ if (jjmatchedPos == 0 && jjmatchedKind > 14)
+ {
+ jjmatchedKind = 14;
+ }
+ break;
+ case 6:
+ jjmatchedKind = 0x7fffffff;
+ jjmatchedPos = 0;
+ curPos = jjMoveStringLiteralDfa0_6();
+ break;
+ }
+ if (jjmatchedKind != 0x7fffffff)
+ {
+ if (jjmatchedPos + 1 < curPos)
+ input_stream.backup(curPos - jjmatchedPos - 1);
+ if ((jjtoToken[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+ {
+ matchedToken = jjFillToken();
+ matchedToken.specialToken = specialToken;
+ TokenLexicalActions(matchedToken);
+ if (jjnewLexState[jjmatchedKind] != -1)
+ curLexState = jjnewLexState[jjmatchedKind];
+ return matchedToken;
+ }
+ else
+ {
+ if ((jjtoSpecial[jjmatchedKind >> 6] & (1L << (jjmatchedKind & 077))) != 0L)
+ {
+ matchedToken = jjFillToken();
+ if (specialToken == null)
+ specialToken = matchedToken;
+ else
+ {
+ matchedToken.specialToken = specialToken;
+ specialToken = (specialToken.next = matchedToken);
+ }
+ }
+ if (jjnewLexState[jjmatchedKind] != -1)
+ curLexState = jjnewLexState[jjmatchedKind];
+ continue EOFLoop;
+ }
+ }
+ int error_line = input_stream.getEndLine();
+ int error_column = input_stream.getEndColumn();
+ String error_after = null;
+ boolean EOFSeen = false;
+ try { input_stream.readChar(); input_stream.backup(1); }
+ catch (java.io.IOException e1) {
+ EOFSeen = true;
+ error_after = curPos <= 1 ? "" : input_stream.GetImage();
+ if (curChar == '\n' || curChar == '\r') {
+ error_line++;
+ error_column = 0;
+ }
+ else
+ error_column++;
+ }
+ if (!EOFSeen) {
+ input_stream.backup(1);
+ error_after = curPos <= 1 ? "" : input_stream.GetImage();
+ }
+ throw new TokenMgrError(EOFSeen, curLexState, error_line, error_column, error_after, curChar, TokenMgrError.LEXICAL_ERROR);
+ }
+}
+
+void TokenLexicalActions(Token matchedToken)
+{
+ switch(jjmatchedKind)
+ {
+ case 20 :
+ image.append(input_stream.GetSuffix(jjimageLen + (lengthOfMatch = jjmatchedPos + 1)));
+ matchedToken.image = image.substring(1, lengthOfMatch - 1);
+ break;
+ default :
+ break;
+ }
+}
+private void jjCheckNAdd(int state)
+{
+ if (jjrounds[state] != jjround)
+ {
+ jjstateSet[jjnewStateCnt++] = state;
+ jjrounds[state] = jjround;
+ }
+}
+private void jjAddStates(int start, int end)
+{
+ do {
+ jjstateSet[jjnewStateCnt++] = jjnextStates[start];
+ } while (start++ != end);
+}
+private void jjCheckNAddTwoStates(int state1, int state2)
+{
+ jjCheckNAdd(state1);
+ jjCheckNAdd(state2);
+}
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/Token.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/Token.java
new file mode 100644
index 0000000..d9bc9bd
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/Token.java
@@ -0,0 +1,131 @@
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 5.0 */
+/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COL=null,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package org.apache.sling.tagmodifier.impl;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token implements java.io.Serializable {
+
+ /**
+ * The version identifier for this Serializable class.
+ * Increment only if the <i>serialized</i> form of the
+ * class changes.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * An integer that describes the kind of this token. This numbering
+ * system is determined by JavaCCParser, and a table of these numbers is
+ * stored in the file ...Constants.java.
+ */
+ public int kind;
+
+ /** The line number of the first character of this Token. */
+ public int beginLine;
+ /** The column number of the first character of this Token. */
+ public int beginColumn;
+ /** The line number of the last character of this Token. */
+ public int endLine;
+ /** The column number of the last character of this Token. */
+ public int endColumn;
+
+ /**
+ * The string image of the token.
+ */
+ public String image;
+
+ /**
+ * A reference to the next regular (non-special) token from the input
+ * stream. If this is the last token from the input stream, or if the
+ * token manager has not read tokens beyond this one, this field is
+ * set to null. This is true only if this token is also a regular
+ * token. Otherwise, see below for a description of the contents of
+ * this field.
+ */
+ public Token next;
+
+ /**
+ * This field is used to access special tokens that occur prior to this
+ * token, but after the immediately preceding regular (non-special) token.
+ * If there are no such special tokens, this field is set to null.
+ * When there are more than one such special token, this field refers
+ * to the last of these special tokens, which in turn refers to the next
+ * previous special token through its specialToken field, and so on
+ * until the first special token (whose specialToken field is null).
+ * The next fields of special tokens refer to other special tokens that
+ * immediately follow it (without an intervening regular token). If there
+ * is no such token, this field is null.
+ */
+ public Token specialToken;
+
+ /**
+ * An optional attribute value of the Token.
+ * Tokens which are not used as syntactic sugar will often contain
+ * meaningful values that will be used later on by the compiler or
+ * interpreter. This attribute value is often different from the image.
+ * Any subclass of Token that actually wants to return a non-null value can
+ * override this method as appropriate.
+ */
+ public Object getValue() {
+ return null;
+ }
+
+ /**
+ * No-argument constructor
+ */
+ public Token() {}
+
+ /**
+ * Constructs a new token for the specified Image.
+ */
+ public Token(int kind)
+ {
+ this(kind, null);
+ }
+
+ /**
+ * Constructs a new token for the specified Image and Kind.
+ */
+ public Token(int kind, String image)
+ {
+ this.kind = kind;
+ this.image = image;
+ }
+
+ /**
+ * Returns the image.
+ */
+ public String toString()
+ {
+ return image;
+ }
+
+ /**
+ * Returns a new Token object, by default. However, if you want, you
+ * can create and return subclass objects based on the value of ofKind.
+ * Simply add the cases to the switch for all those special cases.
+ * For example, if you have a subclass of Token called IDToken that
+ * you want to create if ofKind is ID, simply add something like :
+ *
+ * case MyParserConstants.ID : return new IDToken(ofKind, image);
+ *
+ * to the following switch statement. Then you can cast matchedToken
+ * variable to the appropriate type and use sit in your lexical actions.
+ */
+ public static Token newToken(int ofKind, String image)
+ {
+ switch(ofKind)
+ {
+ default : return new Token(ofKind, image);
+ }
+ }
+
+ public static Token newToken(int ofKind)
+ {
+ return newToken(ofKind, null);
+ }
+
+}
+/* JavaCC - OriginalChecksum=81ad7854912711be917c774d4f150610 (do not edit this line) */
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/TokenMgrError.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/TokenMgrError.java
new file mode 100644
index 0000000..411e939
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/TokenMgrError.java
@@ -0,0 +1,147 @@
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 5.0 */
+/* JavaCCOptions: */
+package org.apache.sling.tagmodifier.impl;
+
+/** Token Manager Error. */
+public class TokenMgrError extends Error
+{
+
+ /**
+ * The version identifier for this Serializable class.
+ * Increment only if the <i>serialized</i> form of the
+ * class changes.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /*
+ * Ordinals for various reasons why an Error of this type can be thrown.
+ */
+
+ /**
+ * Lexical error occurred.
+ */
+ static final int LEXICAL_ERROR = 0;
+
+ /**
+ * An attempt was made to create a second instance of a static token manager.
+ */
+ static final int STATIC_LEXER_ERROR = 1;
+
+ /**
+ * Tried to change to an invalid lexical state.
+ */
+ static final int INVALID_LEXICAL_STATE = 2;
+
+ /**
+ * Detected (and bailed out of) an infinite loop in the token manager.
+ */
+ static final int LOOP_DETECTED = 3;
+
+ /**
+ * Indicates the reason why the exception is thrown. It will have
+ * one of the above 4 values.
+ */
+ int errorCode;
+
+ /**
+ * Replaces unprintable characters by their escaped (or unicode escaped)
+ * equivalents in the given string
+ */
+ protected static final String addEscapes(String str) {
+ StringBuffer retval = new StringBuffer();
+ char ch;
+ for (int i = 0; i < str.length(); i++) {
+ switch (str.charAt(i))
+ {
+ case 0 :
+ continue;
+ case '\b':
+ retval.append("\\b");
+ continue;
+ case '\t':
+ retval.append("\\t");
+ continue;
+ case '\n':
+ retval.append("\\n");
+ continue;
+ case '\f':
+ retval.append("\\f");
+ continue;
+ case '\r':
+ retval.append("\\r");
+ continue;
+ case '\"':
+ retval.append("\\\"");
+ continue;
+ case '\'':
+ retval.append("\\\'");
+ continue;
+ case '\\':
+ retval.append("\\\\");
+ continue;
+ default:
+ if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+ String s = "0000" + Integer.toString(ch, 16);
+ retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+ } else {
+ retval.append(ch);
+ }
+ continue;
+ }
+ }
+ return retval.toString();
+ }
+
+ /**
+ * Returns a detailed message for the Error when it is thrown by the
+ * token manager to indicate a lexical error.
+ * Parameters :
+ * EOFSeen : indicates if EOF caused the lexical error
+ * curLexState : lexical state in which this error occurred
+ * errorLine : line number when the error occurred
+ * errorColumn : column number when the error occurred
+ * errorAfter : prefix that was seen before this error occurred
+ * curchar : the offending character
+ * Note: You can customize the lexical error message by modifying this method.
+ */
+ protected static String LexicalError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar) {
+ return("Lexical error at line " +
+ errorLine + ", column " +
+ errorColumn + ". Encountered: " +
+ (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar)) + "\"") + " (" + (int)curChar + "), ") +
+ "after : \"" + addEscapes(errorAfter) + "\"");
+ }
+
+ /**
+ * You can also modify the body of this method to customize your error messages.
+ * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+ * of end-users concern, so you can return something like :
+ *
+ * "Internal Error : Please file a bug report .... "
+ *
+ * from this method for such cases in the release version of your parser.
+ */
+ public String getMessage() {
+ return super.getMessage();
+ }
+
+ /*
+ * Constructors of various flavors follow.
+ */
+
+ /** No arg constructor. */
+ public TokenMgrError() {
+ }
+
+ /** Constructor with message and reason. */
+ public TokenMgrError(String message, int reason) {
+ super(message);
+ errorCode = reason;
+ }
+
+ /** Full Constructor. */
+ public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, char curChar, int reason) {
+ this(LexicalError(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+ }
+}
+/* JavaCC - OriginalChecksum=f7fa2506e61d308a4e64469fb4552a86 (do not edit this line) */
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/components/HtmlGeneratorFactory.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/components/HtmlGeneratorFactory.java
new file mode 100644
index 0000000..758c7ea
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/components/HtmlGeneratorFactory.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier.impl.components;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.apache.sling.commons.html.HtmlParser;
+import org.apache.sling.rewriter.Generator;
+import org.apache.sling.rewriter.GeneratorFactory;
+import org.apache.sling.rewriter.ProcessingComponentConfiguration;
+import org.apache.sling.rewriter.ProcessingContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * On the fly HTML parser which can be used as the
+ * starting point for html pipelines.
+ *
+ */
+@Component(service = GeneratorFactory.class,
+ property = {
+ Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
+ "pipeline.type=html5-generator"
+ })
+public class HtmlGeneratorFactory implements GeneratorFactory {
+
+ @Reference(target="(version=html5)")
+ private HtmlParser htmlParser;
+
+ /**
+ * @see org.apache.sling.rewriter.GeneratorFactory#createGenerator()
+ */
+ @Override
+ public Generator createGenerator() {
+ return new HtmlGenerator(htmlParser);
+ }
+
+ public static final class HtmlGenerator implements Generator {
+
+ private final StringWriter writer;
+
+ private final HtmlParser htmlParser;
+
+ private ContentHandler contentHandler;
+
+ public HtmlGenerator(final HtmlParser parser) {
+ this.htmlParser = parser;
+ this.writer = new StringWriter();
+ }
+
+ /**
+ * @see org.apache.sling.rewriter.Generator#finished()
+ */
+ @Override
+ public void finished() throws IOException, SAXException {
+ this.htmlParser.parse(new ByteArrayInputStream(this.writer.toString().getBytes("UTF-8")), "UTF-8", this.contentHandler);
+ }
+
+ /**
+ * @see org.apache.sling.rewriter.Generator#getWriter()
+ */
+ @Override
+ public PrintWriter getWriter() {
+ return new PrintWriter(writer);
+ }
+
+ @Override
+ public void init(ProcessingContext context,
+ ProcessingComponentConfiguration config)
+ throws IOException {
+ // nothing to do
+ }
+
+ /**
+ * @see org.apache.sling.rewriter.Generator#setContentHandler(org.xml.sax.ContentHandler)
+ */
+ @Override
+ public void setContentHandler(ContentHandler handler) {
+ this.contentHandler = handler;
+ }
+
+ /**
+ * @see org.apache.sling.rewriter.Generator#dispose()
+ */
+ @Override
+ public void dispose() {
+ // nothing to do
+ }
+ }
+}
\ No newline at end of file
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/components/TagHtmlParser.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/components/TagHtmlParser.java
new file mode 100644
index 0000000..74c9646
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/components/TagHtmlParser.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.tagmodifier.impl.components;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.sling.commons.html.HtmlParser;
+import org.apache.sling.tagmodifier.Tag;
+import org.apache.sling.tagmodifier.consumer.HtmlSAXSupport;
+import org.apache.sling.tagmodifier.util.DOMBuilder;
+import org.osgi.service.component.annotations.Component;
+import org.w3c.dom.Document;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+@Component(
+ property = {
+ "dom=tagmodifier",
+ "sax=tagmodifier",
+ "version=html5"
+ }
+)
+public class TagHtmlParser implements HtmlParser {
+
+
+
+ /**
+ * @see org.apache.sling.commons.html.HtmlParser#parse(java.io.InputStream, java.lang.String, org.xml.sax.ContentHandler)
+ */
+ @Override
+ public void parse(final InputStream stream, final String encoding, final ContentHandler contentHandler) throws SAXException {
+ Tag.stream(stream,encoding).forEach(new HtmlSAXSupport(contentHandler, null));
+ }
+
+ /**
+ * @see org.apache.sling.commons.html.HtmlParser#parse(java.lang.String, java.io.InputStream, java.lang.String)
+ */
+ @Override
+ public Document parse(String systemId, InputStream stream, String encoding) throws IOException {
+ final DOMBuilder builder = new DOMBuilder();
+ Tag.stream(stream, encoding).forEach(new HtmlSAXSupport(builder, builder));
+ return builder.getDocument();
+ }
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/Comment.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/Comment.java
new file mode 100644
index 0000000..1bd23d1
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/Comment.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier.impl.tag;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.sling.tagmodifier.AttrValue;
+import org.apache.sling.tagmodifier.Element;
+import org.apache.sling.tagmodifier.ElementType;
+
+public class Comment implements Element {
+
+ private String value;
+
+ public Comment(String text) {
+ this.value = text;
+ }
+
+ @Override
+ public ElementType getType() {
+ return ElementType.COMMENT;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public boolean supportsAttributes() {
+ return false;
+ }
+
+ @Override
+ public Map<String, AttrValue> getAttributes() {
+ return Collections.emptyMap();
+ }
+
+
+}
\ No newline at end of file
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/DocType.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/DocType.java
new file mode 100644
index 0000000..71e844e
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/DocType.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier.impl.tag;
+
+import java.util.Map;
+
+import org.apache.sling.tagmodifier.AttrValue;
+import org.apache.sling.tagmodifier.Element;
+import org.apache.sling.tagmodifier.ElementType;
+
+public class DocType implements Element {
+
+ private String value;
+ private Map<String,AttrValue> attributes;
+
+ public DocType(String tag, Map<String,AttrValue> attrList) {
+ this.value = tag;
+ this.attributes = attrList;
+ }
+
+ @Override
+ public ElementType getType() {
+ return ElementType.DOCTYPE;
+ }
+
+ @Override
+ public boolean supportsAttributes() {
+ return true;
+ }
+
+ @Override
+ public Map<String, AttrValue> getAttributes() {
+ return attributes;
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/EndOfFile.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/EndOfFile.java
new file mode 100644
index 0000000..23fa85b
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/EndOfFile.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier.impl.tag;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.sling.tagmodifier.AttrValue;
+import org.apache.sling.tagmodifier.Element;
+import org.apache.sling.tagmodifier.ElementType;
+
+public class EndOfFile implements Element {
+
+ @Override
+ public ElementType getType() {
+ return ElementType.EOF;
+ }
+
+ @Override
+ public boolean supportsAttributes() {
+ return false;
+ }
+
+ @Override
+ public Map<String, AttrValue> getAttributes() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public String getValue() {
+ return "EOF";
+ }
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/EndTag.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/EndTag.java
new file mode 100644
index 0000000..481d2d9
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/EndTag.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier.impl.tag;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.sling.tagmodifier.AttrValue;
+import org.apache.sling.tagmodifier.Element;
+import org.apache.sling.tagmodifier.ElementType;
+
+public class EndTag implements Element {
+
+ private String value;
+
+ public EndTag(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public ElementType getType() {
+ return ElementType.END_TAG;
+ }
+
+ @Override
+ public boolean supportsAttributes() {
+ return false;
+ }
+
+ @Override
+ public Map<String, AttrValue> getAttributes() {
+ return Collections.emptyMap();
+ }
+}
\ No newline at end of file
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/StartTag.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/StartTag.java
new file mode 100644
index 0000000..690849a
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/StartTag.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier.impl.tag;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.sling.tagmodifier.AttrValue;
+import org.apache.sling.tagmodifier.Element;
+import org.apache.sling.tagmodifier.ElementType;
+
+public class StartTag implements Element {
+
+ private String value;
+ private Map<String, AttrValue> attributes = Collections.emptyMap();
+
+ public StartTag(String value, Map<String, AttrValue> attrList) {
+ this.value = value;
+ attributes = attrList;
+ }
+
+ @Override
+ public ElementType getType() {
+ return ElementType.START_TAG;
+ }
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public boolean supportsAttributes() {
+ return true;
+ }
+
+ @Override
+ public Map<String, AttrValue> getAttributes() {
+ return attributes;
+ }
+}
\ No newline at end of file
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/TextData.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/TextData.java
new file mode 100644
index 0000000..5b903de
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/impl/tag/TextData.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier.impl.tag;
+/**
+ * Plain text
+ */
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.sling.tagmodifier.AttrValue;
+import org.apache.sling.tagmodifier.Element;
+import org.apache.sling.tagmodifier.ElementType;
+
+/**
+ * Represents the data that is found between tags.
+ *
+ *
+ */
+public class TextData implements Element {
+
+ private String value;
+
+ public TextData(String t) {
+ value = t;
+ }
+
+ public String toString() {
+ return value;
+ }
+
+ @Override
+ public ElementType getType() {
+ return ElementType.TEXT;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setText(String text) {
+ this.value = text;
+ }
+
+ @Override
+ public boolean supportsAttributes() {
+ return false;
+ }
+
+ @Override
+ public Map<String, AttrValue> getAttributes() {
+ return Collections.emptyMap();
+ }
+
+}
\ No newline at end of file
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/map/HtmlTextEncoder.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/map/HtmlTextEncoder.java
new file mode 100644
index 0000000..9473443
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/map/HtmlTextEncoder.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier.map;
+
+import java.util.LinkedList;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import org.apache.sling.tagmodifier.Element;
+import org.apache.sling.tagmodifier.impl.tag.TextData;
+import org.apache.sling.tagmodifier.util.HtmlEntityTranslator;
+
+public class HtmlTextEncoder implements Function<Element, Stream<Element>> {
+
+ LinkedList<String> insideOf = new LinkedList<>();
+
+ @Override
+ public Stream<Element> apply(Element element) {
+ switch (element.getType()) {
+
+ case START_TAG:
+ String name = element.getValue();
+ switch (name) {
+ case "noframes":
+ case "noscript":
+ case "style":
+ case "script":
+ insideOf.push(name);
+ break;
+ default:
+ break;
+ }
+ break;
+ case END_TAG:
+ String endName = element.getValue();
+ switch (endName) {
+ case "noframes":
+ case "noscript":
+ case "style":
+ case "script":
+ while (!insideOf.isEmpty()) {
+ String tagName = insideOf.pop();
+ if (tagName.equals(endName)) {
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ case TEXT:
+ if (!insideOf.isEmpty()) {
+ TextData text = (TextData)element;
+ text.setText(HtmlEntityTranslator.encodeHTML(text.getValue()));
+ }
+ break;
+ default:
+ break;
+ }
+ return Stream.of(element);
+ }
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/package-info.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/package-info.java
new file mode 100644
index 0000000..55de967
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/package-info.java
@@ -0,0 +1,15 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+@org.osgi.annotation.versioning.Version("0.0.1")
+package org.apache.sling.tagmodifier;
\ No newline at end of file
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/util/DOMBuilder.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/util/DOMBuilder.java
new file mode 100644
index 0000000..cd170ce
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/util/DOMBuilder.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier.util;
+
+import java.io.IOException;
+
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.sax.SAXTransformerFactory;
+import javax.xml.transform.sax.TransformerHandler;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.LexicalHandler;
+
+/**
+ * The <code>DOMBuilder</code> is a utility class that will generate a W3C
+ * DOM Document from SAX events.
+ */
+public class DOMBuilder implements ContentHandler, LexicalHandler {
+
+ /**
+ * The default transformer factory shared by all instances
+ */
+ private static final SAXTransformerFactory FACTORY = (SAXTransformerFactory) TransformerFactory.newInstance();
+
+ private final DOMResult result;
+
+ private final ContentHandler contentHandler;
+ private final LexicalHandler lexicalHandler;
+
+ /**
+ * Construct a new instance of this DOMBuilder.
+ *
+ * @throws IOException If for some reason the <code>TransformerHandler</code> cannot be created.
+ */
+ public DOMBuilder() throws IOException {
+ try {
+ final TransformerHandler handler = FACTORY.newTransformerHandler();
+ this.contentHandler = handler;
+ this.lexicalHandler = handler;
+ this.result = new DOMResult();
+ handler.setResult(this.result);
+ } catch (TransformerException te) {
+ throw new IOException("Unable to get transformer handler", te);
+ }
+ }
+
+ /**
+ * @return The newly built <code>Document</code> or <code>null</code>.
+ */
+ public Document getDocument() {
+ if (this.result.getNode() == null) {
+ return null;
+ } else if (this.result.getNode().getNodeType() == Node.DOCUMENT_NODE) {
+ return (Document) this.result.getNode();
+ } else {
+ return this.result.getNode().getOwnerDocument();
+ }
+ }
+
+ @Override
+ public void setDocumentLocator(Locator locator) {
+ contentHandler.setDocumentLocator(locator);
+ }
+
+ @Override
+ public void startDocument() throws SAXException {
+ contentHandler.startDocument();
+ }
+
+ @Override
+ public void endDocument() throws SAXException {
+ contentHandler.endDocument();
+ }
+
+ @Override
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ contentHandler.startPrefixMapping(prefix, uri);
+ }
+
+ @Override
+ public void endPrefixMapping(String prefix) throws SAXException {
+ contentHandler.endPrefixMapping(prefix);
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
+ contentHandler.startElement(uri, localName, qName, atts);
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ contentHandler.endElement(uri, localName, qName);
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ contentHandler.characters(ch, start, length);
+ }
+
+ @Override
+ public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+ contentHandler.ignorableWhitespace(ch, start, length);
+ }
+
+ @Override
+ public void processingInstruction(String target, String data) throws SAXException {
+ contentHandler.processingInstruction(target, data);
+ }
+
+ @Override
+ public void skippedEntity(String name) throws SAXException {
+ contentHandler.skippedEntity(name);
+ }
+
+ @Override
+ public void startDTD(String name, String publicId, String systemId) throws SAXException {
+ lexicalHandler.startDTD(name, publicId, systemId);
+ }
+
+ @Override
+ public void endDTD() throws SAXException {
+ lexicalHandler.endDTD();
+ }
+
+ @Override
+ public void startEntity(String name) throws SAXException {
+ lexicalHandler.startEntity(name);
+ }
+
+ @Override
+ public void endEntity(String name) throws SAXException {
+ lexicalHandler.endEntity(name);
+ }
+
+ @Override
+ public void startCDATA() throws SAXException {
+ lexicalHandler.startCDATA();
+ }
+
+ @Override
+ public void endCDATA() throws SAXException {
+ lexicalHandler.endCDATA();
+ }
+
+ @Override
+ public void comment(char[] ch, int start, int length) throws SAXException {
+ lexicalHandler.comment(ch, start, length);
+ }
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/util/Html5Entities.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/util/Html5Entities.java
new file mode 100644
index 0000000..64572c1
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/util/Html5Entities.java
@@ -0,0 +1,2273 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier.util;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.text.translate.EntityArrays;
+
+public class Html5Entities {
+
+ private Html5Entities() {
+ }
+
+ /**
+ * HTML 5.0 character entities.
+ */
+ public static final Map<CharSequence, CharSequence> HTML50_EXTENDED_ESCAPE;
+ static {
+ final Map<CharSequence, CharSequence> initialMap = new HashMap<>();
+ initialMap.put("\u200C", "‌");
+ initialMap.put("\u200D", "‍");
+ initialMap.put("\uD835\uDCCF", "𝓏");
+ initialMap.put("\uD835\uDCB5", "𝒵");
+ initialMap.put("\u2124", "ℤ");
+ initialMap.put("\uD835\uDD6B", "𝕫");
+ initialMap.put("\u21DD", "⇝");
+ initialMap.put("\u0436", "ж");
+ initialMap.put("\u0416", "Ж");
+ initialMap.put("\u2128", "ℨ");
+ initialMap.put("\uD835\uDD37", "𝔷");
+ initialMap.put("\u03B6", "ζ");
+ initialMap.put("\u0396", "Ζ");
+ initialMap.put("\u200B", "​");
+ initialMap.put("\u2128", "ℨ");
+ initialMap.put("\u017C", "ż");
+ initialMap.put("\u017B", "Ż");
+ initialMap.put("\u0437", "з");
+ initialMap.put("\u0417", "З");
+ initialMap.put("\u017E", "ž");
+ initialMap.put("\u017D", "Ž");
+ initialMap.put("\u017A", "ź");
+ initialMap.put("\u0179", "Ź");
+ initialMap.put("\u0178", "Ÿ");
+ initialMap.put("\u00FF", "ÿ");
+ initialMap.put("\u00FF", "ÿ");
+ initialMap.put("\u044E", "ю");
+ initialMap.put("\u042E", "Ю");
+ initialMap.put("\uD835\uDCCE", "𝓎");
+ initialMap.put("\uD835\uDCB4", "𝒴");
+ initialMap.put("\uD835\uDD6A", "𝕪");
+ initialMap.put("\uD835\uDD50", "𝕐");
+ initialMap.put("\u0457", "ї");
+ initialMap.put("\u0407", "Ї");
+ initialMap.put("\uD835\uDD36", "𝔶");
+ initialMap.put("\uD835\uDD1C", "𝔜");
+ initialMap.put("\u00A5", "¥");
+ initialMap.put("\u00A5", "¥");
+ initialMap.put("\u044B", "ы");
+ initialMap.put("\u042B", "Ы");
+ initialMap.put("\u0177", "ŷ");
+ initialMap.put("\u0176", "Ŷ");
+ initialMap.put("\u044F", "я");
+ initialMap.put("\u042F", "Я");
+ initialMap.put("\u00FD", "ý");
+ initialMap.put("\u00FD", "ý");
+ initialMap.put("\u00DD", "Ý");
+ initialMap.put("\u00DD", "Ý");
+ initialMap.put("\u22C0", "⋀");
+ initialMap.put("\u22C1", "⋁");
+ initialMap.put("\u25B3", "△");
+ initialMap.put("\u2A04", "⨄");
+ initialMap.put("\u2A06", "⨆");
+ initialMap.put("\uD835\uDCCD", "𝓍");
+ initialMap.put("\uD835\uDCB3", "𝒳");
+ initialMap.put("\u27F9", "⟹");
+ initialMap.put("\u27F6", "⟶");
+ initialMap.put("\u2A02", "⨂");
+ initialMap.put("\u2A01", "⨁");
+ initialMap.put("\uD835\uDD69", "𝕩");
+ initialMap.put("\uD835\uDD4F", "𝕏");
+ initialMap.put("\u2A00", "⨀");
+ initialMap.put("\u22FB", "⋻");
+ initialMap.put("\u27FC", "⟼");
+ initialMap.put("\u27F8", "⟸");
+ initialMap.put("\u27F5", "⟵");
+ initialMap.put("\u03BE", "ξ");
+ initialMap.put("\u039E", "Ξ");
+ initialMap.put("\u27FA", "⟺");
+ initialMap.put("\u27F7", "⟷");
+ initialMap.put("\uD835\uDD35", "𝔵");
+ initialMap.put("\uD835\uDD1B", "𝔛");
+ initialMap.put("\u25BD", "▽");
+ initialMap.put("\u22C3", "⋃");
+ initialMap.put("\u25EF", "◯");
+ initialMap.put("\u22C2", "⋂");
+ initialMap.put("\uD835\uDCCC", "𝓌");
+ initialMap.put("\uD835\uDCB2", "𝒲");
+ initialMap.put("\u2240", "≀");
+ initialMap.put("\u2240", "≀");
+ initialMap.put("\u2118", "℘");
+ initialMap.put("\uD835\uDD68", "𝕨");
+ initialMap.put("\uD835\uDD4E", "𝕎");
+ initialMap.put("\uD835\uDD34", "𝔴");
+ initialMap.put("\uD835\uDD1A", "𝔚");
+ initialMap.put("\u2118", "℘");
+ initialMap.put("\u2259", "≙");
+ initialMap.put("\u22C0", "⋀");
+ initialMap.put("\u2227", "∧");
+ initialMap.put("\u2A5F", "⩟");
+ initialMap.put("\u0175", "ŵ");
+ initialMap.put("\u0174", "Ŵ");
+ initialMap.put("\u299A", "⦚");
+ initialMap.put("\u22AA", "⊪");
+ initialMap.put("\u228B\uFE00", "⊋︀");
+ initialMap.put("\u2ACC\uFE00", "⫌︀");
+ initialMap.put("\u228A\uFE00", "⊊︀");
+ initialMap.put("\u2ACB\uFE00", "⫋︀");
+ initialMap.put("\uD835\uDCCB", "𝓋");
+ initialMap.put("\uD835\uDCB1", "𝒱");
+ initialMap.put("\u22B3", "⊳");
+ initialMap.put("\u221D", "∝");
+ initialMap.put("\uD835\uDD67", "𝕧");
+ initialMap.put("\uD835\uDD4D", "𝕍");
+ initialMap.put("\u2283\u20D2", "⊃⃒");
+ initialMap.put("\u2282\u20D2", "⊂⃒");
+ initialMap.put("\u22B2", "⊲");
+ initialMap.put("\uD835\uDD33", "𝔳");
+ initialMap.put("\uD835\uDD19", "𝔙");
+ initialMap.put("\u200A", " ");
+ initialMap.put("\u2240", "≀");
+ initialMap.put("\u2758", "❘");
+ initialMap.put("\u007C", "|");
+ initialMap.put("\u2223", "∣");
+ initialMap.put("\u2016", "‖");
+ initialMap.put("\u007C", "|");
+ initialMap.put("\u2016", "‖");
+ initialMap.put("\u007C", "|");
+ initialMap.put("\u22EE", "⋮");
+ initialMap.put("\u225A", "≚");
+ initialMap.put("\u22C1", "⋁");
+ initialMap.put("\u2228", "∨");
+ initialMap.put("\u22BB", "⊻");
+ initialMap.put("\u2AE6", "⫦");
+ initialMap.put("\u22AB", "⊫");
+ initialMap.put("\u22A9", "⊩");
+ initialMap.put("\u22A8", "⊨");
+ initialMap.put("\u22A2", "⊢");
+ initialMap.put("\u0432", "в");
+ initialMap.put("\u0412", "В");
+ initialMap.put("\u2AE9", "⫩");
+ initialMap.put("\u2AEB", "⫫");
+ initialMap.put("\u2AE8", "⫨");
+ initialMap.put("\u22B3", "⊳");
+ initialMap.put("\u22B2", "⊲");
+ initialMap.put("\u03D1", "ϑ");
+ initialMap.put("\u2ACC\uFE00", "⫌︀");
+ initialMap.put("\u228B\uFE00", "⊋︀");
+ initialMap.put("\u2ACB\uFE00", "⫋︀");
+ initialMap.put("\u228A\uFE00", "⊊︀");
+ initialMap.put("\u03C2", "ς");
+ initialMap.put("\u03F1", "ϱ");
+ initialMap.put("\u21D5", "⇕");
+ initialMap.put("\u2195", "↕");
+ initialMap.put("\u221D", "∝");
+ initialMap.put("\u03D6", "ϖ");
+ initialMap.put("\u03D5", "ϕ");
+ initialMap.put("\u2205", "∅");
+ initialMap.put("\u03F0", "ϰ");
+ initialMap.put("\u03F5", "ϵ");
+ initialMap.put("\u299C", "⦜");
+ initialMap.put("\u29A7", "⦧");
+ initialMap.put("\u00FC", "ü");
+ initialMap.put("\u00FC", "ü");
+ initialMap.put("\u00DC", "Ü");
+ initialMap.put("\u00DC", "Ü");
+ initialMap.put("\u21C8", "⇈");
+ initialMap.put("\u25B4", "▴");
+ initialMap.put("\u25B5", "▵");
+ initialMap.put("\u0169", "ũ");
+ initialMap.put("\u0168", "Ũ");
+ initialMap.put("\u22F0", "⋰");
+ initialMap.put("\uD835\uDCCA", "𝓊");
+ initialMap.put("\uD835\uDCB0", "𝒰");
+ initialMap.put("\u25F9", "◹");
+ initialMap.put("\u016F", "ů");
+ initialMap.put("\u016E", "Ů");
+ initialMap.put("\u230E", "⌎");
+ initialMap.put("\u231D", "⌝");
+ initialMap.put("\u231D", "⌝");
+ initialMap.put("\u21C8", "⇈");
+ initialMap.put("\u22A5", "⊥");
+ initialMap.put("\u21A5", "↥");
+ initialMap.put("\u03C5", "υ");
+ initialMap.put("\u03A5", "Υ");
+ initialMap.put("\u03D2", "ϒ");
+ initialMap.put("\u03D2", "ϒ");
+ initialMap.put("\u03C5", "υ");
+ initialMap.put("\u2197", "↗");
+ initialMap.put("\u2196", "↖");
+ initialMap.put("\u228E", "⊎");
+ initialMap.put("\u21BE", "↾");
+ initialMap.put("\u21BF", "↿");
+ initialMap.put("\u296E", "⥮");
+ initialMap.put("\u21D5", "⇕");
+ initialMap.put("\u2195", "↕");
+ initialMap.put("\u2195", "↕");
+ initialMap.put("\u21C5", "⇅");
+ initialMap.put("\u21D1", "⇑");
+ initialMap.put("\u2191", "↑");
+ initialMap.put("\u2191", "↑");
+ initialMap.put("\u2912", "⤒");
+ initialMap.put("\uD835\uDD66", "𝕦");
+ initialMap.put("\uD835\uDD4C", "𝕌");
+ initialMap.put("\u0173", "ų");
+ initialMap.put("\u0172", "Ų");
+ initialMap.put("\u228E", "⊎");
+ initialMap.put("\u22C3", "⋃");
+ initialMap.put("\u23DD", "⏝");
+ initialMap.put("\u23B5", "⎵");
+ initialMap.put("\u23DF", "⏟");
+ initialMap.put("\u005F", "_");
+ initialMap.put("\u00A8", "¨");
+ initialMap.put("\u00A8", "¨");
+ initialMap.put("\u016B", "ū");
+ initialMap.put("\u016A", "Ū");
+ initialMap.put("\u25F8", "◸");
+ initialMap.put("\u230F", "⌏");
+ initialMap.put("\u231C", "⌜");
+ initialMap.put("\u231C", "⌜");
+ initialMap.put("\u2580", "▀");
+ initialMap.put("\u21BE", "↾");
+ initialMap.put("\u21BF", "↿");
+ initialMap.put("\u2963", "⥣");
+ initialMap.put("\u00F9", "ù");
+ initialMap.put("\u00F9", "ù");
+ initialMap.put("\u00D9", "Ù");
+ initialMap.put("\u00D9", "Ù");
+ initialMap.put("\uD835\uDD32", "𝔲");
+ initialMap.put("\uD835\uDD18", "𝔘");
+ initialMap.put("\u297E", "⥾");
+ initialMap.put("\u296E", "⥮");
+ initialMap.put("\u0171", "ű");
+ initialMap.put("\u0170", "Ű");
+ initialMap.put("\u21C5", "⇅");
+ initialMap.put("\u0443", "у");
+ initialMap.put("\u0423", "У");
+ initialMap.put("\u00FB", "û");
+ initialMap.put("\u00FB", "û");
+ initialMap.put("\u00DB", "Û");
+ initialMap.put("\u00DB", "Û");
+ initialMap.put("\u016D", "ŭ");
+ initialMap.put("\u016C", "Ŭ");
+ initialMap.put("\u045E", "ў");
+ initialMap.put("\u040E", "Ў");
+ initialMap.put("\u2949", "⥉");
+ initialMap.put("\u21D1", "⇑");
+ initialMap.put("\u219F", "↟");
+ initialMap.put("\u2191", "↑");
+ initialMap.put("\u00FA", "ú");
+ initialMap.put("\u00FA", "ú");
+ initialMap.put("\u00DA", "Ú");
+ initialMap.put("\u00DA", "Ú");
+ initialMap.put("\u21A0", "↠");
+ initialMap.put("\u219E", "↞");
+ initialMap.put("\u226C", "≬");
+ initialMap.put("\u0167", "ŧ");
+ initialMap.put("\u0166", "Ŧ");
+ initialMap.put("\u045B", "ћ");
+ initialMap.put("\u040B", "Ћ");
+ initialMap.put("\u0446", "ц");
+ initialMap.put("\u0426", "Ц");
+ initialMap.put("\uD835\uDCC9", "𝓉");
+ initialMap.put("\uD835\uDCAF", "𝒯");
+ initialMap.put("\u23E2", "⏢");
+ initialMap.put("\u2A3B", "⨻");
+ initialMap.put("\u29CD", "⧍");
+ initialMap.put("\u2A39", "⨹");
+ initialMap.put("\u20DB", "⃛");
+ initialMap.put("\u2A3A", "⨺");
+ initialMap.put("\u225C", "≜");
+ initialMap.put("\u25EC", "◬");
+ initialMap.put("\u22B5", "⊵");
+ initialMap.put("\u25B9", "▹");
+ initialMap.put("\u225C", "≜");
+ initialMap.put("\u22B4", "⊴");
+ initialMap.put("\u25C3", "◃");
+ initialMap.put("\u25BF", "▿");
+ initialMap.put("\u25B5", "▵");
+ initialMap.put("\u2122", "™");
+ initialMap.put("\u2122", "™");
+ initialMap.put("\u2034", "‴");
+ initialMap.put("\u2929", "⤩");
+ initialMap.put("\u2ADA", "⫚");
+ initialMap.put("\uD835\uDD65", "𝕥");
+ initialMap.put("\uD835\uDD4B", "𝕋");
+ initialMap.put("\u22A4", "⊤");
+ initialMap.put("\u2AF1", "⫱");
+ initialMap.put("\u2336", "⌶");
+ initialMap.put("\u2928", "⤨");
+ initialMap.put("\u222D", "∭");
+ initialMap.put("\u2A30", "⨰");
+ initialMap.put("\u00D7", "×");
+ initialMap.put("\u00D7", "×");
+ initialMap.put("\u22A0", "⊠");
+ initialMap.put("\u2A31", "⨱");
+ initialMap.put("\u2248", "≈");
+ initialMap.put("\u2245", "≅");
+ initialMap.put("\u2243", "≃");
+ initialMap.put("\u223C", "∼");
+ initialMap.put("\u02DC", "˜");
+ initialMap.put("\u00FE", "þ");
+ initialMap.put("\u00FE", "þ");
+ initialMap.put("\u00DE", "Þ");
+ initialMap.put("\u00DE", "Þ");
+ initialMap.put("\u223C", "∼");
+ initialMap.put("\u2248", "≈");
+ initialMap.put("\u2009", " ");
+ initialMap.put("\u2009", " ");
+ initialMap.put("\u205F\u200A", "  ");
+ initialMap.put("\u223C", "∼");
+ initialMap.put("\u2248", "≈");
+ initialMap.put("\u03D1", "ϑ");
+ initialMap.put("\u03D1", "ϑ");
+ initialMap.put("\u03B8", "θ");
+ initialMap.put("\u0398", "Θ");
+ initialMap.put("\u2234", "∴");
+ initialMap.put("\u2234", "∴");
+ initialMap.put("\u2234", "∴");
+ initialMap.put("\uD835\uDD31", "𝔱");
+ initialMap.put("\uD835\uDD17", "𝔗");
+ initialMap.put("\u2315", "⌕");
+ initialMap.put("\u20DB", "⃛");
+ initialMap.put("\u0442", "т");
+ initialMap.put("\u0422", "Т");
+ initialMap.put("\u0163", "ţ");
+ initialMap.put("\u0162", "Ţ");
+ initialMap.put("\u0165", "ť");
+ initialMap.put("\u0164", "Ť");
+ initialMap.put("\u23B4", "⎴");
+ initialMap.put("\u03C4", "τ");
+ initialMap.put("\u03A4", "Τ");
+ initialMap.put("\u2316", "⌖");
+ initialMap.put("\u0009", "	");
+ initialMap.put("\u00DF", "ß");
+ initialMap.put("\u00DF", "ß");
+ initialMap.put("\u292A", "⤪");
+ initialMap.put("\u2199", "↙");
+ initialMap.put("\u21D9", "⇙");
+ initialMap.put("\u2199", "↙");
+ initialMap.put("\u2926", "⤦");
+ initialMap.put("\u2AD6", "⫖");
+ initialMap.put("\u2AD4", "⫔");
+ initialMap.put("\u2AC8", "⫈");
+ initialMap.put("\u2ACC", "⫌");
+ initialMap.put("\u228B", "⊋");
+ initialMap.put("\u2AC6", "⫆");
+ initialMap.put("\u2287", "⊇");
+ initialMap.put("\u22D1", "⋑");
+ initialMap.put("\u2283", "⊃");
+ initialMap.put("\u2AC0", "⫀");
+ initialMap.put("\u228B", "⊋");
+ initialMap.put("\u2ACC", "⫌");
+ initialMap.put("\u2AC2", "⫂");
+ initialMap.put("\u297B", "⥻");
+ initialMap.put("\u2AD7", "⫗");
+ initialMap.put("\u27C9", "⟉");
+ initialMap.put("\u2287", "⊇");
+ initialMap.put("\u2283", "⊃");
+ initialMap.put("\u2AC4", "⫄");
+ initialMap.put("\u2287", "⊇");
+ initialMap.put("\u2AC6", "⫆");
+ initialMap.put("\u2AD8", "⫘");
+ initialMap.put("\u2ABE", "⪾");
+ initialMap.put("\u22D1", "⋑");
+ initialMap.put("\u2283", "⊃");
+ initialMap.put("\u00B3", "³");
+ initialMap.put("\u00B3", "³");
+ initialMap.put("\u00B2", "²");
+ initialMap.put("\u00B2", "²");
+ initialMap.put("\u00B9", "¹");
+ initialMap.put("\u00B9", "¹");
+ initialMap.put("\u266A", "♪");
+ initialMap.put("\u2211", "∑");
+ initialMap.put("\u2211", "∑");
+ initialMap.put("\u220B", "∋");
+ initialMap.put("\u227F", "≿");
+ initialMap.put("\u22E9", "⋩");
+ initialMap.put("\u2AB6", "⪶");
+ initialMap.put("\u2ABA", "⪺");
+ initialMap.put("\u2AB0", "⪰");
+ initialMap.put("\u227F", "≿");
+ initialMap.put("\u227D", "≽");
+ initialMap.put("\u2AB0", "⪰");
+ initialMap.put("\u227B", "≻");
+ initialMap.put("\u227D", "≽");
+ initialMap.put("\u227B", "≻");
+ initialMap.put("\u2AB8", "⪸");
+ initialMap.put("\u2AD3", "⫓");
+ initialMap.put("\u2AD5", "⫕");
+ initialMap.put("\u2AC7", "⫇");
+ initialMap.put("\u2ACB", "⫋");
+ initialMap.put("\u228A", "⊊");
+ initialMap.put("\u2286", "⊆");
+ initialMap.put("\u2AC5", "⫅");
+ initialMap.put("\u2286", "⊆");
+ initialMap.put("\u22D0", "⋐");
+ initialMap.put("\u2282", "⊂");
+ initialMap.put("\u2979", "⥹");
+ initialMap.put("\u2ABF", "⪿");
+ initialMap.put("\u228A", "⊊");
+ initialMap.put("\u2ACB", "⫋");
+ initialMap.put("\u2AC1", "⫁");
+ initialMap.put("\u2AC3", "⫃");
+ initialMap.put("\u2286", "⊆");
+ initialMap.put("\u2AC5", "⫅");
+ initialMap.put("\u2ABD", "⪽");
+ initialMap.put("\u22D0", "⋐");
+ initialMap.put("\u2282", "⊂");
+ initialMap.put("\u00AF", "¯");
+ initialMap.put("\u03D5", "ϕ");
+ initialMap.put("\u03F5", "ϵ");
+ initialMap.put("\u2605", "★");
+ initialMap.put("\u2606", "☆");
+ initialMap.put("\u22C6", "⋆");
+ initialMap.put("\u22C6", "⋆");
+ initialMap.put("\u2323", "⌣");
+ initialMap.put("\u2216", "∖");
+ initialMap.put("\uD835\uDCC8", "𝓈");
+ initialMap.put("\uD835\uDCAE", "𝒮");
+ initialMap.put("\u2192", "→");
+ initialMap.put("\u25AA", "▪");
+ initialMap.put("\u25A1", "□");
+ initialMap.put("\u25AA", "▪");
+ initialMap.put("\u2294", "⊔");
+ initialMap.put("\u2292", "⊒");
+ initialMap.put("\u2290", "⊐");
+ initialMap.put("\u2291", "⊑");
+ initialMap.put("\u228F", "⊏");
+ initialMap.put("\u2293", "⊓");
+ initialMap.put("\u25A1", "□");
+ initialMap.put("\u25A1", "□");
+ initialMap.put("\u2292", "⊒");
+ initialMap.put("\u2290", "⊐");
+ initialMap.put("\u2292", "⊒");
+ initialMap.put("\u2290", "⊐");
+ initialMap.put("\u2291", "⊑");
+ initialMap.put("\u228F", "⊏");
+ initialMap.put("\u2291", "⊑");
+ initialMap.put("\u228F", "⊏");
+ initialMap.put("\u221A", "√");
+ initialMap.put("\u2294\uFE00", "⊔︀");
+ initialMap.put("\u2294", "⊔");
+ initialMap.put("\u2293\uFE00", "⊓︀");
+ initialMap.put("\u2293", "⊓");
+ initialMap.put("\u2225", "∥");
+ initialMap.put("\u2660", "♠");
+ initialMap.put("\u2660", "♠");
+ initialMap.put("\uD835\uDD64", "𝕤");
+ initialMap.put("\uD835\uDD4A", "𝕊");
+ initialMap.put("\u002F", "/");
+ initialMap.put("\u29C4", "⧄");
+ initialMap.put("\u233F", "⌿");
+ initialMap.put("\u044C", "ь");
+ initialMap.put("\u042C", "Ь");
+ initialMap.put("\u2AAC\uFE00", "⪬︀");
+ initialMap.put("\u2AAC", "⪬");
+ initialMap.put("\u2AAA", "⪪");
+ initialMap.put("\u2323", "⌣");
+ initialMap.put("\u2223", "∣");
+ initialMap.put("\u29E4", "⧤");
+ initialMap.put("\u2A33", "⨳");
+ initialMap.put("\u2216", "∖");
+ initialMap.put("\u2218", "∘");
+ initialMap.put("\u2190", "←");
+ initialMap.put("\u2972", "⥲");
+ initialMap.put("\u2A24", "⨤");
+ initialMap.put("\u2246", "≆");
+ initialMap.put("\u2A9F", "⪟");
+ initialMap.put("\u2A9D", "⪝");
+ initialMap.put("\u2AA0", "⪠");
+ initialMap.put("\u2A9E", "⪞");
+ initialMap.put("\u2243", "≃");
+ initialMap.put("\u2243", "≃");
+ initialMap.put("\u2A6A", "⩪");
+ initialMap.put("\u223C", "∼");
+ initialMap.put("\u03C2", "ς");
+ initialMap.put("\u03C2", "ς");
+ initialMap.put("\u03C3", "σ");
+ initialMap.put("\u03A3", "Σ");
+ initialMap.put("\u00AD", "­");
+ initialMap.put("\u00AD", "­");
+ initialMap.put("\u2191", "↑");
+ initialMap.put("\u2192", "→");
+ initialMap.put("\u2225", "∥");
+ initialMap.put("\u2223", "∣");
+ initialMap.put("\u2190", "←");
+ initialMap.put("\u2193", "↓");
+ initialMap.put("\u0448", "ш");
+ initialMap.put("\u0428", "Ш");
+ initialMap.put("\u0449", "щ");
+ initialMap.put("\u0429", "Щ");
+ initialMap.put("\u266F", "♯");
+ initialMap.put("\u2322", "⌢");
+ initialMap.put("\uD835\uDD30", "𝔰");
+ initialMap.put("\uD835\uDD16", "𝔖");
+ initialMap.put("\u2736", "✶");
+ initialMap.put("\u2216", "∖");
+ initialMap.put("\u2216", "∖");
+ initialMap.put("\u2929", "⤩");
+ initialMap.put("\u003B", ";");
+ initialMap.put("\u00A7", "§");
+ initialMap.put("\u00A7", "§");
+ initialMap.put("\u2198", "↘");
+ initialMap.put("\u21D8", "⇘");
+ initialMap.put("\u2198", "↘");
+ initialMap.put("\u2925", "⤥");
+ initialMap.put("\u2A66", "⩦");
+ initialMap.put("\u22C5", "⋅");
+ initialMap.put("\u22A1", "⊡");
+ initialMap.put("\u0441", "с");
+ initialMap.put("\u0421", "С");
+ initialMap.put("\u227F", "≿");
+ initialMap.put("\u2A13", "⨓");
+ initialMap.put("\u22E9", "⋩");
+ initialMap.put("\u2AB6", "⪶");
+ initialMap.put("\u2ABA", "⪺");
+ initialMap.put("\u015D", "ŝ");
+ initialMap.put("\u015C", "Ŝ");
+ initialMap.put("\u015F", "ş");
+ initialMap.put("\u015E", "Ş");
+ initialMap.put("\u2AB4", "⪴");
+ initialMap.put("\u2AB0", "⪰");
+ initialMap.put("\u227D", "≽");
+ initialMap.put("\u227B", "≻");
+ initialMap.put("\u2ABC", "⪼");
+ initialMap.put("\u0161", "š");
+ initialMap.put("\u0160", "Š");
+ initialMap.put("\u2AB8", "⪸");
+ initialMap.put("\u201A", "‚");
+ initialMap.put("\u015B", "ś");
+ initialMap.put("\u015A", "Ś");
+ initialMap.put("\u211E", "℞");
+ initialMap.put("\u2968", "⥨");
+ initialMap.put("\u29F4", "⧴");
+ initialMap.put("\u29CE", "⧎");
+ initialMap.put("\u25B8", "▸");
+ initialMap.put("\u22B5", "⊵");
+ initialMap.put("\u25B9", "▹");
+ initialMap.put("\u22CA", "⋊");
+ initialMap.put("\u22CC", "⋌");
+ initialMap.put("\u2019", "’");
+ initialMap.put("\u2019", "’");
+ initialMap.put("\u005D", "]");
+ initialMap.put("\u21B1", "↱");
+ initialMap.put("\u21B1", "↱");
+ initialMap.put("\u211B", "ℛ");
+ initialMap.put("\uD835\uDCC7", "𝓇");
+ initialMap.put("\u203A", "›");
+ initialMap.put("\u21DB", "⇛");
+ initialMap.put("\u21C9", "⇉");
+ initialMap.put("\u2A12", "⨒");
+ initialMap.put("\u2994", "⦔");
+ initialMap.put("\u0029", ")");
+ initialMap.put("\u2970", "⥰");
+ initialMap.put("\u2A35", "⨵");
+ initialMap.put("\u2A2E", "⨮");
+ initialMap.put("\u211D", "ℝ");
+ initialMap.put("\uD835\uDD63", "𝕣");
+ initialMap.put("\u2986", "⦆");
+ initialMap.put("\u27E7", "⟧");
+ initialMap.put("\u21FE", "⇾");
+ initialMap.put("\u27ED", "⟭");
+ initialMap.put("\u2AEE", "⫮");
+ initialMap.put("\u23B1", "⎱");
+ initialMap.put("\u23B1", "⎱");
+ initialMap.put("\u200F", "‏");
+ initialMap.put("\u21CC", "⇌");
+ initialMap.put("\u21C4", "⇄");
+ initialMap.put("\u2253", "≓");
+ initialMap.put("\u02DA", "˚");
+ initialMap.put("\u21C0", "⇀");
+ initialMap.put("\u2953", "⥓");
+ initialMap.put("\u21BE", "↾");
+ initialMap.put("\u2954", "⥔");
+ initialMap.put("\u295C", "⥜");
+ initialMap.put("\u294F", "⥏");
+ initialMap.put("\u22B5", "⊵");
+ initialMap.put("\u22B3", "⊳");
+ initialMap.put("\u29D0", "⧐");
+ initialMap.put("\u22CC", "⋌");
+ initialMap.put("\u295B", "⥛");
+ initialMap.put("\u22A2", "⊢");
+ initialMap.put("\u21A6", "↦");
+ initialMap.put("\u219D", "↝");
+ initialMap.put("\u21C9", "⇉");
+ initialMap.put("\u21CC", "⇌");
+ initialMap.put("\u21C4", "⇄");
+ initialMap.put("\u21C0", "⇀");
+ initialMap.put("\u21C1", "⇁");
+ initialMap.put("\u230B", "⌋");
+ initialMap.put("\u21C2", "⇂");
+ initialMap.put("\u2955", "⥕");
+ initialMap.put("\u295D", "⥝");
+ initialMap.put("\u27E7", "⟧");
+ initialMap.put("\u2309", "⌉");
+ initialMap.put("\u21A3", "↣");
+ initialMap.put("\u21C4", "⇄");
+ initialMap.put("\u21D2", "⇒");
+ initialMap.put("\u2192", "→");
+ initialMap.put("\u2192", "→");
+ initialMap.put("\u21E5", "⇥");
+ initialMap.put("\u27E9", "⟩");
+ initialMap.put("\u03F1", "ϱ");
+ initialMap.put("\u03C1", "ρ");
+ initialMap.put("\u03A1", "Ρ");
+ initialMap.put("\u296C", "⥬");
+ initialMap.put("\u21C0", "⇀");
+ initialMap.put("\u21C1", "⇁");
+ initialMap.put("\u2964", "⥤");
+ initialMap.put("\u211C", "ℜ");
+ initialMap.put("\uD835\uDD2F", "𝔯");
+ initialMap.put("\u230B", "⌋");
+ initialMap.put("\u297D", "⥽");
+ initialMap.put("\u296F", "⥯");
+ initialMap.put("\u21CB", "⇋");
+ initialMap.put("\u220B", "∋");
+ initialMap.put("\u00AE", "®");
+ initialMap.put("\u00AE", "®");
+ initialMap.put("\u00AE", "®");
+ initialMap.put("\u00AE", "®");
+ initialMap.put("\u25AD", "▭");
+ initialMap.put("\u211C", "ℜ");
+ initialMap.put("\u211D", "ℝ");
+ initialMap.put("\u211C", "ℜ");
+ initialMap.put("\u211B", "ℛ");
+ initialMap.put("\u211C", "ℜ");
+ initialMap.put("\u21B3", "↳");
+ initialMap.put("\u201D", "”");
+ initialMap.put("\u201D", "”");
+ initialMap.put("\u2969", "⥩");
+ initialMap.put("\u2937", "⤷");
+ initialMap.put("\u0440", "р");
+ initialMap.put("\u0420", "Р");
+ initialMap.put("\u007D", "}");
+ initialMap.put("\u2309", "⌉");
+ initialMap.put("\u0157", "ŗ");
+ initialMap.put("\u0156", "Ŗ");
+ initialMap.put("\u0159", "ř");
+ initialMap.put("\u0158", "Ř");
+ initialMap.put("\u2990", "⦐");
+ initialMap.put("\u298E", "⦎");
+ initialMap.put("\u298C", "⦌");
+ initialMap.put("\u005D", "]");
+ initialMap.put("\u007D", "}");
+ initialMap.put("\u2773", "❳");
+ initialMap.put("\u2910", "⤐");
+ initialMap.put("\u290F", "⤏");
+ initialMap.put("\u290D", "⤍");
+ initialMap.put("\u211A", "ℚ");
+ initialMap.put("\u2236", "∶");
+ initialMap.put("\u291C", "⤜");
+ initialMap.put("\u291A", "⤚");
+ initialMap.put("\u219D", "↝");
+ initialMap.put("\u21A3", "↣");
+ initialMap.put("\u2916", "⤖");
+ initialMap.put("\u2974", "⥴");
+ initialMap.put("\u2945", "⥅");
+ initialMap.put("\u21AC", "↬");
+ initialMap.put("\u21AA", "↪");
+ initialMap.put("\u291E", "⤞");
+ initialMap.put("\u21D2", "⇒");
+ initialMap.put("\u21A0", "↠");
+ initialMap.put("\u2192", "→");
+ initialMap.put("\u2933", "⤳");
+ initialMap.put("\u2920", "⤠");
+ initialMap.put("\u21E5", "⇥");
+ initialMap.put("\u2975", "⥵");
+ initialMap.put("\u00BB", "»");
+ initialMap.put("\u00BB", "»");
+ initialMap.put("\u27E9", "⟩");
+ initialMap.put("\u29A5", "⦥");
+ initialMap.put("\u2992", "⦒");
+ initialMap.put("\u27EB", "⟫");
+ initialMap.put("\u27E9", "⟩");
+ initialMap.put("\u29B3", "⦳");
+ initialMap.put("\u221A", "√");
+ initialMap.put("\u0155", "ŕ");
+ initialMap.put("\u0154", "Ŕ");
+ initialMap.put("\u223D\u0331", "∽̱");
+ initialMap.put("\u21DB", "⇛");
+ initialMap.put("\"", """);
+ initialMap.put("\"", """);
+ initialMap.put("\"", """);
+ initialMap.put("\"", """);
+ initialMap.put("\u225F", "≟");
+ initialMap.put("\u003F", "?");
+ initialMap.put("\u2A16", "⨖");
+ initialMap.put("\u210D", "ℍ");
+ initialMap.put("\uD835\uDCC6", "𝓆");
+ initialMap.put("\uD835\uDCAC", "𝒬");
+ initialMap.put("\u2057", "⁗");
+ initialMap.put("\u211A", "ℚ");
+ initialMap.put("\uD835\uDD62", "𝕢");
+ initialMap.put("\u2A0C", "⨌");
+ initialMap.put("\uD835\uDD2E", "𝔮");
+ initialMap.put("\uD835\uDD14", "𝔔");
+ initialMap.put("\u2008", " ");
+ initialMap.put("\u03C8", "ψ");
+ initialMap.put("\u03A8", "Ψ");
+ initialMap.put("\uD835\uDCC5", "𝓅");
+ initialMap.put("\uD835\uDCAB", "𝒫");
+ initialMap.put("\u22B0", "⊰");
+ initialMap.put("\u227E", "≾");
+ initialMap.put("\u221D", "∝");
+ initialMap.put("\u2237", "∷");
+ initialMap.put("\u221D", "∝");
+ initialMap.put("\u221D", "∝");
+ initialMap.put("\u2313", "⌓");
+ initialMap.put("\u2312", "⌒");
+ initialMap.put("\u232E", "⌮");
+ initialMap.put("\u220F", "∏");
+ initialMap.put("\u220F", "∏");
+ initialMap.put("\u22E8", "⋨");
+ initialMap.put("\u2AB5", "⪵");
+ initialMap.put("\u2AB9", "⪹");
+ initialMap.put("\u2119", "ℙ");
+ initialMap.put("\u2033", "″");
+ initialMap.put("\u2032", "′");
+ initialMap.put("\u227E", "≾");
+ initialMap.put("\u2AB3", "⪳");
+ initialMap.put("\u2AAF", "⪯");
+ initialMap.put("\u22E8", "⋨");
+ initialMap.put("\u2AB5", "⪵");
+ initialMap.put("\u2AB9", "⪹");
+ initialMap.put("\u2AAF", "⪯");
+ initialMap.put("\u227E", "≾");
+ initialMap.put("\u227C", "≼");
+ initialMap.put("\u2AAF", "⪯");
+ initialMap.put("\u227A", "≺");
+ initialMap.put("\u227C", "≼");
+ initialMap.put("\u227A", "≺");
+ initialMap.put("\u2AB7", "⪷");
+ initialMap.put("\u227C", "≼");
+ initialMap.put("\u227A", "≺");
+ initialMap.put("\u2ABB", "⪻");
+ initialMap.put("\u2AB7", "⪷");
+ initialMap.put("\u00A3", "£");
+ initialMap.put("\u00A3", "£");
+ initialMap.put("\u2119", "ℙ");
+ initialMap.put("\uD835\uDD61", "𝕡");
+ initialMap.put("\u2A15", "⨕");
+ initialMap.put("\u210C", "ℌ");
+ initialMap.put("\u00B1", "±");
+ initialMap.put("\u2A27", "⨧");
+ initialMap.put("\u2A26", "⨦");
+ initialMap.put("\u00B1", "±");
+ initialMap.put("\u00B1", "±");
+ initialMap.put("\u00B1", "±");
+ initialMap.put("\u2A72", "⩲");
+ initialMap.put("\u2A25", "⨥");
+ initialMap.put("\u2214", "∔");
+ initialMap.put("\u002B", "+");
+ initialMap.put("\u2A22", "⨢");
+ initialMap.put("\u229E", "⊞");
+ initialMap.put("\u2A23", "⨣");
+ initialMap.put("\u210F", "ℏ");
+ initialMap.put("\u210E", "ℎ");
+ initialMap.put("\u210F", "ℏ");
+ initialMap.put("\u03D6", "ϖ");
+ initialMap.put("\u22D4", "⋔");
+ initialMap.put("\u03C0", "π");
+ initialMap.put("\u03A0", "Π");
+ initialMap.put("\u260E", "☎");
+ initialMap.put("\u2133", "ℳ");
+ initialMap.put("\u03D5", "ϕ");
+ initialMap.put("\u03C6", "φ");
+ initialMap.put("\u03A6", "Φ");
+ initialMap.put("\uD835\uDD2D", "𝔭");
+ initialMap.put("\uD835\uDD13", "𝔓");
+ initialMap.put("\u2031", "‱");
+ initialMap.put("\u22A5", "⊥");
+ initialMap.put("\u2030", "‰");
+ initialMap.put("\u002E", ".");
+ initialMap.put("\u0025", "%");
+ initialMap.put("\u043F", "п");
+ initialMap.put("\u041F", "П");
+ initialMap.put("\u2202", "∂");
+ initialMap.put("\u2202", "∂");
+ initialMap.put("\u2AFD", "⫽");
+ initialMap.put("\u2AF3", "⫳");
+ initialMap.put("\u2225", "∥");
+ initialMap.put("\u2225", "∥");
+ initialMap.put("\u00B6", "¶");
+ initialMap.put("\u00B6", "¶");
+ initialMap.put("\u23DC", "⏜");
+ initialMap.put("\u23B4", "⎴");
+ initialMap.put("\u23DE", "⏞");
+ initialMap.put("\u203E", "‾");
+ initialMap.put("\u233D", "⌽");
+ initialMap.put("\u00F6", "ö");
+ initialMap.put("\u00F6", "ö");
+ initialMap.put("\u00D6", "Ö");
+ initialMap.put("\u00D6", "Ö");
+ initialMap.put("\u2297", "⊗");
+ initialMap.put("\u2A37", "⨷");
+ initialMap.put("\u2A36", "⨶");
+ initialMap.put("\u00F5", "õ");
+ initialMap.put("\u00F5", "õ");
+ initialMap.put("\u00D5", "Õ");
+ initialMap.put("\u00D5", "Õ");
+ initialMap.put("\u2298", "⊘");
+ initialMap.put("\u00F8", "ø");
+ initialMap.put("\u00F8", "ø");
+ initialMap.put("\u00D8", "Ø");
+ initialMap.put("\u00D8", "Ø");
+ initialMap.put("\u2134", "ℴ");
+ initialMap.put("\uD835\uDCAA", "𝒪");
+ initialMap.put("\u24C8", "Ⓢ");
+ initialMap.put("\u2A5B", "⩛");
+ initialMap.put("\u2A57", "⩗");
+ initialMap.put("\u2A56", "⩖");
+ initialMap.put("\u22B6", "⊶");
+ initialMap.put("\u00BA", "º");
+ initialMap.put("\u00BA", "º");
+ initialMap.put("\u00AA", "ª");
+ initialMap.put("\u00AA", "ª");
+ initialMap.put("\u2134", "ℴ");
+ initialMap.put("\u2134", "ℴ");
+ initialMap.put("\u2A5D", "⩝");
+ initialMap.put("\u2228", "∨");
+ initialMap.put("\u2A54", "⩔");
+ initialMap.put("\u21BB", "↻");
+ initialMap.put("\u2295", "⊕");
+ initialMap.put("\u29B9", "⦹");
+ initialMap.put("\u2018", "‘");
+ initialMap.put("\u201C", "“");
+ initialMap.put("\u29B7", "⦷");
+ initialMap.put("\uD835\uDD60", "𝕠");
+ initialMap.put("\uD835\uDD46", "𝕆");
+ initialMap.put("\u2296", "⊖");
+ initialMap.put("\u29B6", "⦶");
+ initialMap.put("\u03BF", "ο");
+ initialMap.put("\u039F", "Ο");
+ initialMap.put("\u03C9", "ω");
+ initialMap.put("\u03A9", "Ω");
+ initialMap.put("\u014D", "ō");
+ initialMap.put("\u014C", "Ō");
+ initialMap.put("\u29C0", "⧀");
+ initialMap.put("\u203E", "‾");
+ initialMap.put("\u29BB", "⦻");
+ initialMap.put("\u29BE", "⦾");
+ initialMap.put("\u21BA", "↺");
+ initialMap.put("\u222E", "∮");
+ initialMap.put("\u03A9", "Ω");
+ initialMap.put("\u29B5", "⦵");
+ initialMap.put("\u29C1", "⧁");
+ initialMap.put("\u00F2", "ò");
+ initialMap.put("\u00F2", "ò");
+ initialMap.put("\u00D2", "Ò");
+ initialMap.put("\u00D2", "Ò");
+ initialMap.put("\u02DB", "˛");
+ initialMap.put("\uD835\uDD2C", "𝔬");
+ initialMap.put("\uD835\uDD12", "𝔒");
+ initialMap.put("\u29BF", "⦿");
+ initialMap.put("\u0153", "œ");
+ initialMap.put("\u0152", "Œ");
+ initialMap.put("\u29BC", "⦼");
+ initialMap.put("\u2299", "⊙");
+ initialMap.put("\u2A38", "⨸");
+ initialMap.put("\u0151", "ő");
+ initialMap.put("\u0150", "Ő");
+ initialMap.put("\u229D", "⊝");
+ initialMap.put("\u043E", "о");
+ initialMap.put("\u041E", "О");
+ initialMap.put("\u229A", "⊚");
+ initialMap.put("\u00F4", "ô");
+ initialMap.put("\u00F4", "ô");
+ initialMap.put("\u00D4", "Ô");
+ initialMap.put("\u00D4", "Ô");
+ initialMap.put("\u229B", "⊛");
+ initialMap.put("\u00F3", "ó");
+ initialMap.put("\u00F3", "ó");
+ initialMap.put("\u00D3", "Ó");
+ initialMap.put("\u00D3", "Ó");
+ initialMap.put("\u2927", "⤧");
+ initialMap.put("\u2196", "↖");
+ initialMap.put("\u21D6", "⇖");
+ initialMap.put("\u2196", "↖");
+ initialMap.put("\u2923", "⤣");
+ initialMap.put("\u223C\u20D2", "∼⃒");
+ initialMap.put("\u22B5\u20D2", "⊵⃒");
+ initialMap.put("\u2903", "⤃");
+ initialMap.put("\u22B4\u20D2", "⊴⃒");
+ initialMap.put("\u003C\u20D2", "<⃒");
+ initialMap.put("\u2264\u20D2", "≤⃒");
+ initialMap.put("\u2902", "⤂");
+ initialMap.put("\u29DE", "⧞");
+ initialMap.put("\u2904", "⤄");
+ initialMap.put("\u003E\u20D2", ">⃒");
+ initialMap.put("\u2265\u20D2", "≥⃒");
+ initialMap.put("\u22AF", "⊯");
+ initialMap.put("\u22AE", "⊮");
+ initialMap.put("\u22AD", "⊭");
+ initialMap.put("\u22AC", "⊬");
+ initialMap.put("\u224D\u20D2", "≍⃒");
+ initialMap.put("\u2007", " ");
+ initialMap.put("\u2116", "№");
+ initialMap.put("\u0023", "#");
+ initialMap.put("\u03BD", "ν");
+ initialMap.put("\u039D", "Ν");
+ initialMap.put("\u22ED", "⋭");
+ initialMap.put("\u22EB", "⋫");
+ initialMap.put("\u22EC", "⋬");
+ initialMap.put("\u22EA", "⋪");
+ initialMap.put("\u2278", "≸");
+ initialMap.put("\u00F1", "ñ");
+ initialMap.put("\u00F1", "ñ");
+ initialMap.put("\u00D1", "Ñ");
+ initialMap.put("\u00D1", "Ñ");
+ initialMap.put("\u2279", "≹");
+ initialMap.put("\u2AC6\u0338", "⫆̸");
+ initialMap.put("\u2289", "⊉");
+ initialMap.put("\u2283\u20D2", "⊃⃒");
+ initialMap.put("\u2289", "⊉");
+ initialMap.put("\u2AC6\u0338", "⫆̸");
+ initialMap.put("\u2285", "⊅");
+ initialMap.put("\u2AB0\u0338", "⪰̸");
+ initialMap.put("\u2281", "⊁");
+ initialMap.put("\u2AC5\u0338", "⫅̸");
+ initialMap.put("\u2288", "⊈");
+ initialMap.put("\u2282\u20D2", "⊂⃒");
+ initialMap.put("\u2288", "⊈");
+ initialMap.put("\u2AC5\u0338", "⫅̸");
+ initialMap.put("\u2284", "⊄");
+ initialMap.put("\u22E3", "⋣");
+ initialMap.put("\u22E2", "⋢");
+ initialMap.put("\u2226", "∦");
+ initialMap.put("\u2224", "∤");
+ initialMap.put("\u2244", "≄");
+ initialMap.put("\u2244", "≄");
+ initialMap.put("\u2241", "≁");
+ initialMap.put("\u2226", "∦");
+ initialMap.put("\u2224", "∤");
+ initialMap.put("\uD835\uDCC3", "𝓃");
+ initialMap.put("\uD835\uDCA9", "𝒩");
+ initialMap.put("\u2AB0\u0338", "⪰̸");
+ initialMap.put("\u22E1", "⋡");
+ initialMap.put("\u2281", "⊁");
+ initialMap.put("\u22ED", "⋭");
+ initialMap.put("\u22EB", "⋫");
+ initialMap.put("\u21CF", "⇏");
+ initialMap.put("\u219B", "↛");
+ initialMap.put("\u219D\u0338", "↝̸");
+ initialMap.put("\u21CF", "⇏");
+ initialMap.put("\u219B", "↛");
+ initialMap.put("\u2933\u0338", "⤳̸");
+ initialMap.put("\u2AAF\u0338", "⪯̸");
+ initialMap.put("\u2AAF\u0338", "⪯̸");
+ initialMap.put("\u2280", "⊀");
+ initialMap.put("\u22E0", "⋠");
+ initialMap.put("\u2280", "⊀");
+ initialMap.put("\u2A14", "⨔");
+ initialMap.put("\u2202\u0338", "∂̸");
+ initialMap.put("\u2AFD\u20E5", "⫽⃥");
+ initialMap.put("\u2226", "∦");
+ initialMap.put("\u2226", "∦");
+ initialMap.put("\u2224", "∤");
+ initialMap.put("\u2249", "≉");
+ initialMap.put("\u2247", "≇");
+ initialMap.put("\u2244", "≄");
+ initialMap.put("\u2241", "≁");
+ initialMap.put("\u2289", "⊉");
+ initialMap.put("\u2283\u20D2", "⊃⃒");
+ initialMap.put("\u227F\u0338", "≿̸");
+ initialMap.put("\u22E1", "⋡");
+ initialMap.put("\u2AB0\u0338", "⪰̸");
+ initialMap.put("\u2281", "⊁");
+ initialMap.put("\u2288", "⊈");
+ initialMap.put("\u2282\u20D2", "⊂⃒");
+ initialMap.put("\u22E3", "⋣");
+ initialMap.put("\u2290\u0338", "⊐̸");
+ initialMap.put("\u22E2", "⋢");
+ initialMap.put("\u228F\u0338", "⊏̸");
+ initialMap.put("\u22ED", "⋭");
+ initialMap.put("\u22EB", "⋫");
+ initialMap.put("\u29D0\u0338", "⧐̸");
+ initialMap.put("\u220C", "∌");
+ initialMap.put("\u22E0", "⋠");
+ initialMap.put("\u2AAF\u0338", "⪯̸");
+ initialMap.put("\u2280", "⊀");
+ initialMap.put("\u22FD", "⋽");
+ initialMap.put("\u22FE", "⋾");
+ initialMap.put("\u220C", "∌");
+ initialMap.put("\u220C", "∌");
+ initialMap.put("\u2AA1\u0338", "⪡̸");
+ initialMap.put("\u2AA2\u0338", "⪢̸");
+ initialMap.put("\u2274", "≴");
+ initialMap.put("\u2A7D\u0338", "⩽̸");
+ initialMap.put("\u226A\u0338", "≪̸");
+ initialMap.put("\u2278", "≸");
+ initialMap.put("\u2270", "≰");
+ initialMap.put("\u226E", "≮");
+ initialMap.put("\u22EC", "⋬");
+ initialMap.put("\u22EA", "⋪");
+ initialMap.put("\u29CF\u0338", "⧏̸");
+ initialMap.put("\u22F6", "⋶");
+ initialMap.put("\u22F7", "⋷");
+ initialMap.put("\u2209", "∉");
+ initialMap.put("\u22F9\u0338", "⋹̸");
+ initialMap.put("\u22F5\u0338", "⋵̸");
+ initialMap.put("\u2209", "∉");
+ initialMap.put("\u224F\u0338", "≏̸");
+ initialMap.put("\u224E\u0338", "≎̸");
+ initialMap.put("\u2275", "≵");
+ initialMap.put("\u2A7E\u0338", "⩾̸");
+ initialMap.put("\u2279", "≹");
+ initialMap.put("\u226B\u0338", "≫̸");
+ initialMap.put("\u2267\u0338", "≧̸");
+ initialMap.put("\u2271", "≱");
+ initialMap.put("\u226F", "≯");
+ initialMap.put("\u2204", "∄");
+ initialMap.put("\u2242\u0338", "≂̸");
+ initialMap.put("\u2260", "≠");
+ initialMap.put("\u2209", "∉");
+ initialMap.put("\u2226", "∦");
+ initialMap.put("\u226D", "≭");
+ initialMap.put("\u2262", "≢");
+ initialMap.put("\u00AC", "¬");
+ initialMap.put("\u00AC", "¬");
+ initialMap.put("\u2AEC", "⫬");
+ initialMap.put("\u2115", "ℕ");
+ initialMap.put("\uD835\uDD5F", "𝕟");
+ initialMap.put("\u00A0", " ");
+ initialMap.put("\u2060", "⁠");
+ initialMap.put("\u2224", "∤");
+ initialMap.put("\u226A\u0338", "≪̸");
+ initialMap.put("\u22EC", "⋬");
+ initialMap.put("\u22EA", "⋪");
+ initialMap.put("\u226E", "≮");
+ initialMap.put("\u226A\u20D2", "≪⃒");
+ initialMap.put("\u2274", "≴");
+ initialMap.put("\u22D8\u0338", "⋘̸");
+ initialMap.put("\u226E", "≮");
+ initialMap.put("\u2A7D\u0338", "⩽̸");
+ initialMap.put("\u2A7D\u0338", "⩽̸");
+ initialMap.put("\u2266\u0338", "≦̸");
+ initialMap.put("\u2270", "≰");
+ initialMap.put("\u21CE", "⇎");
+ initialMap.put("\u21AE", "↮");
+ initialMap.put("\u21CD", "⇍");
+ initialMap.put("\u219A", "↚");
+ initialMap.put("\u2270", "≰");
+ initialMap.put("\u2266\u0338", "≦̸");
+ initialMap.put("\u2025", "‥");
+ initialMap.put("\u21CD", "⇍");
+ initialMap.put("\u219A", "↚");
+ initialMap.put("\u045A", "њ");
+ initialMap.put("\u040A", "Њ");
+ initialMap.put("\u220B", "∋");
+ initialMap.put("\u22FA", "⋺");
+ initialMap.put("\u22FC", "⋼");
+ initialMap.put("\u220B", "∋");
+ initialMap.put("\u2AF2", "⫲");
+ initialMap.put("\u21CE", "⇎");
+ initialMap.put("\u21AE", "↮");
+ initialMap.put("\u226B\u0338", "≫̸");
+ initialMap.put("\u226F", "≯");
+ initialMap.put("\u226F", "≯");
+ initialMap.put("\u226B\u20D2", "≫⃒");
+ initialMap.put("\u2275", "≵");
+ initialMap.put("\u22D9\u0338", "⋙̸");
+ initialMap.put("\u2A7E\u0338", "⩾̸");
+ initialMap.put("\u2A7E\u0338", "⩾̸");
+ initialMap.put("\u2267\u0338", "≧̸");
+ initialMap.put("\u2271", "≱");
+ initialMap.put("\u2271", "≱");
+ initialMap.put("\u2267\u0338", "≧̸");
+ initialMap.put("\uD835\uDD2B", "𝔫");
+ initialMap.put("\uD835\uDD11", "𝔑");
+ initialMap.put("\u2204", "∄");
+ initialMap.put("\u2204", "∄");
+ initialMap.put("\n", "
");
+ initialMap.put("\u226A", "≪");
+ initialMap.put("\u226B", "≫");
+ initialMap.put("\u2242\u0338", "≂̸");
+ initialMap.put("\u2928", "⤨");
+ initialMap.put("\u2262", "≢");
+ initialMap.put("\u200B", "​");
+ initialMap.put("\u200B", "​");
+ initialMap.put("\u200B", "​");
+ initialMap.put("\u200B", "​");
+ initialMap.put("\u2250\u0338", "≐̸");
+ initialMap.put("\u2260", "≠");
+ initialMap.put("\u2197", "↗");
+ initialMap.put("\u21D7", "⇗");
+ initialMap.put("\u2197", "↗");
+ initialMap.put("\u2924", "⤤");
+ initialMap.put("\u2013", "–");
+ initialMap.put("\u043D", "н");
+ initialMap.put("\u041D", "Н");
+ initialMap.put("\u2A42", "⩂");
+ initialMap.put("\u2A6D\u0338", "⩭̸");
+ initialMap.put("\u2247", "≇");
+ initialMap.put("\u0146", "ņ");
+ initialMap.put("\u0145", "Ņ");
+ initialMap.put("\u0148", "ň");
+ initialMap.put("\u0147", "Ň");
+ initialMap.put("\u2A43", "⩃");
+ initialMap.put("\u224F\u0338", "≏̸");
+ initialMap.put("\u224E\u0338", "≎̸");
+ initialMap.put("\u00A0", " ");
+ initialMap.put("\u00A0", " ");
+ initialMap.put("\u266E", "♮");
+ initialMap.put("\u2115", "ℕ");
+ initialMap.put("\u266E", "♮");
+ initialMap.put("\u2249", "≉");
+ initialMap.put("\u0149", "ʼn");
+ initialMap.put("\u224B\u0338", "≋̸");
+ initialMap.put("\u2A70\u0338", "⩰̸");
+ initialMap.put("\u2249", "≉");
+ initialMap.put("\u2220\u20D2", "∠⃒");
+ initialMap.put("\u0144", "ń");
+ initialMap.put("\u0143", "Ń");
+ initialMap.put("\u2207", "∇");
+ initialMap.put("\u22B8", "⊸");
+ initialMap.put("\u22B8", "⊸");
+ initialMap.put("\u03BC", "μ");
+ initialMap.put("\u039C", "Μ");
+ initialMap.put("\u223E", "∾");
+ initialMap.put("\u2133", "ℳ");
+ initialMap.put("\uD835\uDCC2", "𝓂");
+ initialMap.put("\u2213", "∓");
+ initialMap.put("\uD835\uDD5E", "𝕞");
+ initialMap.put("\uD835\uDD44", "𝕄");
+ initialMap.put("\u22A7", "⊧");
+ initialMap.put("\u2213", "∓");
+ initialMap.put("\u2026", "…");
+ initialMap.put("\u2ADB", "⫛");
+ initialMap.put("\u2213", "∓");
+ initialMap.put("\u2A2A", "⨪");
+ initialMap.put("\u2238", "∸");
+ initialMap.put("\u2212", "−");
+ initialMap.put("\u229F", "⊟");
+ initialMap.put("\u00B7", "·");
+ initialMap.put("\u00B7", "·");
+ initialMap.put("\u2223", "∣");
+ initialMap.put("\u2AF0", "⫰");
+ initialMap.put("\u002A", "*");
+ initialMap.put("\u00B5", "µ");
+ initialMap.put("\u00B5", "µ");
+ initialMap.put("\u2127", "℧");
+ initialMap.put("\uD835\uDD2A", "𝔪");
+ initialMap.put("\uD835\uDD10", "𝔐");
+ initialMap.put("\u2133", "ℳ");
+ initialMap.put("\u205F", " ");
+ initialMap.put("\u2221", "∡");
+ initialMap.put("\u223A", "∺");
+ initialMap.put("\u2014", "—");
+ initialMap.put("\u043C", "м");
+ initialMap.put("\u041C", "М");
+ initialMap.put("\u2A29", "⨩");
+ initialMap.put("\u25AE", "▮");
+ initialMap.put("\u21A5", "↥");
+ initialMap.put("\u21A4", "↤");
+ initialMap.put("\u21A7", "↧");
+ initialMap.put("\u21A6", "↦");
+ initialMap.put("\u21A6", "↦");
+ initialMap.put("\u2905", "⤅");
+ initialMap.put("\u2720", "✠");
+ initialMap.put("\u2720", "✠");
+ initialMap.put("\u2642", "♂");
+ initialMap.put("\u00AF", "¯");
+ initialMap.put("\u00AF", "¯");
+ initialMap.put("\u2268\uFE00", "≨︀");
+ initialMap.put("\u2268\uFE00", "≨︀");
+ initialMap.put("\u2966", "⥦");
+ initialMap.put("\u294A", "⥊");
+ initialMap.put("\u2996", "⦖");
+ initialMap.put("\u25C2", "◂");
+ initialMap.put("\u22B4", "⊴");
+ initialMap.put("\u25C3", "◃");
+ initialMap.put("\u2A7B", "⩻");
+ initialMap.put("\u2976", "⥶");
+ initialMap.put("\u22C9", "⋉");
+ initialMap.put("\u22CB", "⋋");
+ initialMap.put("\u22D6", "⋖");
+ initialMap.put("\u226A", "≪");
+ initialMap.put("\u003C", "<");
+ initialMap.put("\u003C", "<");
+ initialMap.put("\u003C", "<");
+ initialMap.put("\u003C", "<");
+ initialMap.put("\u2A79", "⩹");
+ initialMap.put("\u2AA6", "⪦");
+ initialMap.put("\u0142", "ł");
+ initialMap.put("\u0141", "Ł");
+ initialMap.put("\u201A", "‚");
+ initialMap.put("\u2018", "‘");
+ initialMap.put("\u005B", "[");
+ initialMap.put("\u2A8F", "⪏");
+ initialMap.put("\u2A8D", "⪍");
+ initialMap.put("\u2272", "≲");
+ initialMap.put("\u21B0", "↰");
+ initialMap.put("\u21B0", "↰");
+ initialMap.put("\u2112", "ℒ");
+ initialMap.put("\uD835\uDCC1", "𝓁");
+ initialMap.put("\u2039", "‹");
+ initialMap.put("\u22BF", "⊿");
+ initialMap.put("\u200E", "‎");
+ initialMap.put("\u296D", "⥭");
+ initialMap.put("\u21CB", "⇋");
+ initialMap.put("\u231F", "⌟");
+ initialMap.put("\u21C6", "⇆");
+ initialMap.put("\u2993", "⦓");
+ initialMap.put("\u0028", "(");
+ initialMap.put("\u29EB", "⧫");
+ initialMap.put("\u25CA", "◊");
+ initialMap.put("\u25CA", "◊");
+ initialMap.put("\u2198", "↘");
+ initialMap.put("\u2199", "↙");
+ initialMap.put("\u005F", "_");
+ initialMap.put("\u2217", "∗");
+ initialMap.put("\u2A34", "⨴");
+ initialMap.put("\u2A2D", "⨭");
+ initialMap.put("\uD835\uDD5D", "𝕝");
+ initialMap.put("\uD835\uDD43", "𝕃");
+ initialMap.put("\u2985", "⦅");
+ initialMap.put("\u21AC", "↬");
+ initialMap.put("\u21AB", "↫");
+ initialMap.put("\u27F9", "⟹");
+ initialMap.put("\u27F6", "⟶");
+ initialMap.put("\u27F6", "⟶");
+ initialMap.put("\u27FC", "⟼");
+ initialMap.put("\u27FA", "⟺");
+ initialMap.put("\u27F7", "⟷");
+ initialMap.put("\u27F7", "⟷");
+ initialMap.put("\u27F8", "⟸");
+ initialMap.put("\u27F5", "⟵");
+ initialMap.put("\u27F5", "⟵");
+ initialMap.put("\u27E6", "⟦");
+ initialMap.put("\u21FD", "⇽");
+ initialMap.put("\u27EC", "⟬");
+ initialMap.put("\u22E6", "⋦");
+ initialMap.put("\u2268", "≨");
+ initialMap.put("\u2A87", "⪇");
+ initialMap.put("\u2268", "≨");
+ initialMap.put("\u2A87", "⪇");
+ initialMap.put("\u2A89", "⪉");
+ initialMap.put("\u2A89", "⪉");
+ initialMap.put("\u23B0", "⎰");
+ initialMap.put("\u23B0", "⎰");
+ initialMap.put("\u0140", "ŀ");
+ initialMap.put("\u013F", "Ŀ");
+ initialMap.put("\u25FA", "◺");
+ initialMap.put("\u296B", "⥫");
+ initialMap.put("\u21DA", "⇚");
+ initialMap.put("\u231E", "⌞");
+ initialMap.put("\u22D8", "⋘");
+ initialMap.put("\u226A", "≪");
+ initialMap.put("\u21C7", "⇇");
+ initialMap.put("\u0459", "љ");
+ initialMap.put("\u0409", "Љ");
+ initialMap.put("\u2584", "▄");
+ initialMap.put("\u296A", "⥪");
+ initialMap.put("\u21BC", "↼");
+ initialMap.put("\u21BD", "↽");
+ initialMap.put("\u2962", "⥢");
+ initialMap.put("\u2A91", "⪑");
+ initialMap.put("\u2276", "≶");
+ initialMap.put("\uD835\uDD29", "𝔩");
+ initialMap.put("\uD835\uDD0F", "𝔏");
+ initialMap.put("\u230A", "⌊");
+ initialMap.put("\u297C", "⥼");
+ initialMap.put("\u2272", "≲");
+ initialMap.put("\u2A7D", "⩽");
+ initialMap.put("\u2272", "≲");
+ initialMap.put("\u2AA1", "⪡");
+ initialMap.put("\u2276", "≶");
+ initialMap.put("\u2276", "≶");
+ initialMap.put("\u2266", "≦");
+ initialMap.put("\u22DA", "⋚");
+ initialMap.put("\u2A8B", "⪋");
+ initialMap.put("\u22DA", "⋚");
+ initialMap.put("\u22D6", "⋖");
+ initialMap.put("\u2A85", "⪅");
+ initialMap.put("\u2A93", "⪓");
+ initialMap.put("\u22DA\uFE00", "⋚︀");
+ initialMap.put("\u2A83", "⪃");
+ initialMap.put("\u2A81", "⪁");
+ initialMap.put("\u2A7F", "⩿");
+ initialMap.put("\u2A7D", "⩽");
+ initialMap.put("\u2AA8", "⪨");
+ initialMap.put("\u2A7D", "⩽");
+ initialMap.put("\u2266", "≦");
+ initialMap.put("\u2264", "≤");
+ initialMap.put("\u22DA", "⋚");
+ initialMap.put("\u2A8B", "⪋");
+ initialMap.put("\u21BC", "↼");
+ initialMap.put("\u2952", "⥒");
+ initialMap.put("\u21BF", "↿");
+ initialMap.put("\u2958", "⥘");
+ initialMap.put("\u2960", "⥠");
+ initialMap.put("\u2951", "⥑");
+ initialMap.put("\u22B4", "⊴");
+ initialMap.put("\u22B2", "⊲");
+ initialMap.put("\u29CF", "⧏");
+ initialMap.put("\u22CB", "⋋");
+ initialMap.put("\u295A", "⥚");
+ initialMap.put("\u22A3", "⊣");
+ initialMap.put("\u21A4", "↤");
+ initialMap.put("\u294E", "⥎");
+ initialMap.put("\u21AD", "↭");
+ initialMap.put("\u21CB", "⇋");
+ initialMap.put("\u21C6", "⇆");
+ initialMap.put("\u21D4", "⇔");
+ initialMap.put("\u2194", "↔");
+ initialMap.put("\u2194", "↔");
+ initialMap.put("\u21C7", "⇇");
+ initialMap.put("\u21BC", "↼");
+ initialMap.put("\u21BD", "↽");
+ initialMap.put("\u230A", "⌊");
+ initialMap.put("\u21C3", "⇃");
+ initialMap.put("\u2959", "⥙");
+ initialMap.put("\u2961", "⥡");
+ initialMap.put("\u27E6", "⟦");
+ initialMap.put("\u2308", "⌈");
+ initialMap.put("\u21A2", "↢");
+ initialMap.put("\u21C6", "⇆");
+ initialMap.put("\u21D0", "⇐");
+ initialMap.put("\u2190", "←");
+ initialMap.put("\u2190", "←");
+ initialMap.put("\u21E4", "⇤");
+ initialMap.put("\u27E8", "⟨");
+ initialMap.put("\u2266", "≦");
+ initialMap.put("\u2264", "≤");
+ initialMap.put("\u21B2", "↲");
+ initialMap.put("\u294B", "⥋");
+ initialMap.put("\u2967", "⥧");
+ initialMap.put("\u201E", "„");
+ initialMap.put("\u201C", "“");
+ initialMap.put("\u2936", "⤶");
+ initialMap.put("\u043B", "л");
+ initialMap.put("\u041B", "Л");
+ initialMap.put("\u007B", "{");
+ initialMap.put("\u2308", "⌈");
+ initialMap.put("\u013C", "ļ");
+ initialMap.put("\u013B", "Ļ");
+ initialMap.put("\u013E", "ľ");
+ initialMap.put("\u013D", "Ľ");
+ initialMap.put("\u298D", "⦍");
+ initialMap.put("\u298F", "⦏");
+ initialMap.put("\u298B", "⦋");
+ initialMap.put("\u005B", "[");
+ initialMap.put("\u007B", "{");
+ initialMap.put("\u2772", "❲");
+ initialMap.put("\u290E", "⤎");
+ initialMap.put("\u290C", "⤌");
+ initialMap.put("\u2AAD\uFE00", "⪭︀");
+ initialMap.put("\u2AAD", "⪭");
+ initialMap.put("\u2AAB", "⪫");
+ initialMap.put("\u291B", "⤛");
+ initialMap.put("\u2919", "⤙");
+ initialMap.put("\u21A2", "↢");
+ initialMap.put("\u2973", "⥳");
+ initialMap.put("\u2939", "⤹");
+ initialMap.put("\u21AB", "↫");
+ initialMap.put("\u21A9", "↩");
+ initialMap.put("\u291D", "⤝");
+ initialMap.put("\u21D0", "⇐");
+ initialMap.put("\u219E", "↞");
+ initialMap.put("\u2190", "←");
+ initialMap.put("\u291F", "⤟");
+ initialMap.put("\u21E4", "⇤");
+ initialMap.put("\u00AB", "«");
+ initialMap.put("\u00AB", "«");
+ initialMap.put("\u2112", "ℒ");
+ initialMap.put("\u2A85", "⪅");
+ initialMap.put("\u27E8", "⟨");
+ initialMap.put("\u2991", "⦑");
+ initialMap.put("\u27EA", "⟪");
+ initialMap.put("\u27E8", "⟨");
+ initialMap.put("\u03BB", "λ");
+ initialMap.put("\u039B", "Λ");
+ initialMap.put("\u2112", "ℒ");
+ initialMap.put("\u29B4", "⦴");
+ initialMap.put("\u013A", "ĺ");
+ initialMap.put("\u0139", "Ĺ");
+ initialMap.put("\u21DA", "⇚");
+ initialMap.put("\uD835\uDCC0", "𝓀");
+ initialMap.put("\uD835\uDCA6", "𝒦");
+ initialMap.put("\uD835\uDD5C", "𝕜");
+ initialMap.put("\uD835\uDD42", "𝕂");
+ initialMap.put("\u045C", "ќ");
+ initialMap.put("\u040C", "Ќ");
+ initialMap.put("\u0445", "х");
+ initialMap.put("\u0425", "Х");
+ initialMap.put("\u0138", "ĸ");
+ initialMap.put("\uD835\uDD28", "𝔨");
+ initialMap.put("\uD835\uDD0E", "𝔎");
+ initialMap.put("\u043A", "к");
+ initialMap.put("\u041A", "К");
+ initialMap.put("\u0137", "ķ");
+ initialMap.put("\u0136", "Ķ");
+ initialMap.put("\u03F0", "ϰ");
+ initialMap.put("\u03BA", "κ");
+ initialMap.put("\u039A", "Κ");
+ initialMap.put("\u0454", "є");
+ initialMap.put("\u0404", "Є");
+ initialMap.put("\u0458", "ј");
+ initialMap.put("\u0408", "Ј");
+ initialMap.put("\uD835\uDCBF", "𝒿");
+ initialMap.put("\uD835\uDCA5", "𝒥");
+ initialMap.put("\uD835\uDD5B", "𝕛");
+ initialMap.put("\uD835\uDD41", "𝕁");
+ initialMap.put("\u0237", "ȷ");
+ initialMap.put("\uD835\uDD27", "𝔧");
+ initialMap.put("\uD835\uDD0D", "𝔍");
+ initialMap.put("\u0439", "й");
+ initialMap.put("\u0419", "Й");
+ initialMap.put("\u0135", "ĵ");
+ initialMap.put("\u0134", "Ĵ");
+ initialMap.put("\u00EF", "ï");
+ initialMap.put("\u00EF", "ï");
+ initialMap.put("\u00CF", "Ï");
+ initialMap.put("\u00CF", "Ï");
+ initialMap.put("\u0456", "і");
+ initialMap.put("\u0406", "І");
+ initialMap.put("\u0129", "ĩ");
+ initialMap.put("\u0128", "Ĩ");
+ initialMap.put("\u2062", "⁢");
+ initialMap.put("\u2208", "∈");
+ initialMap.put("\u22F3", "⋳");
+ initialMap.put("\u22F4", "⋴");
+ initialMap.put("\u22F9", "⋹");
+ initialMap.put("\u22F5", "⋵");
+ initialMap.put("\u2208", "∈");
+ initialMap.put("\u2110", "ℐ");
+ initialMap.put("\uD835\uDCBE", "𝒾");
+ initialMap.put("\u00BF", "¿");
+ initialMap.put("\u00BF", "¿");
+ initialMap.put("\u2A3C", "⨼");
+ initialMap.put("\u03B9", "ι");
+ initialMap.put("\u0399", "Ι");
+ initialMap.put("\uD835\uDD5A", "𝕚");
+ initialMap.put("\uD835\uDD40", "𝕀");
+ initialMap.put("\u012F", "į");
+ initialMap.put("\u012E", "Į");
+ initialMap.put("\u0451", "ё");
+ initialMap.put("\u0401", "Ё");
+ initialMap.put("\u2062", "⁢");
+ initialMap.put("\u2063", "⁣");
+ initialMap.put("\u2A3C", "⨼");
+ initialMap.put("\u2A17", "⨗");
+ initialMap.put("\u22C2", "⋂");
+ initialMap.put("\u22BA", "⊺");
+ initialMap.put("\u222B", "∫");
+ initialMap.put("\u2124", "ℤ");
+ initialMap.put("\u222C", "∬");
+ initialMap.put("\u222B", "∫");
+ initialMap.put("\u22BA", "⊺");
+ initialMap.put("\u0131", "ı");
+ initialMap.put("\u29DD", "⧝");
+ initialMap.put("\u221E", "∞");
+ initialMap.put("\u2208", "∈");
+ initialMap.put("\u2105", "℅");
+ initialMap.put("\u21D2", "⇒");
+ initialMap.put("\u01B5", "Ƶ");
+ initialMap.put("\u22B7", "⊷");
+ initialMap.put("\u2111", "ℑ");
+ initialMap.put("\u0131", "ı");
+ initialMap.put("\u2111", "ℑ");
+ initialMap.put("\u2110", "ℐ");
+ initialMap.put("\u2148", "ⅈ");
+ initialMap.put("\u2111", "ℑ");
+ initialMap.put("\u012B", "ī");
+ initialMap.put("\u012A", "Ī");
+ initialMap.put("\u0133", "ij");
+ initialMap.put("\u0132", "IJ");
+ initialMap.put("\u2129", "℩");
+ initialMap.put("\u29DC", "⧜");
+ initialMap.put("\u222D", "∭");
+ initialMap.put("\u2A0C", "⨌");
+ initialMap.put("\u2148", "ⅈ");
+ initialMap.put("\u00EC", "ì");
+ initialMap.put("\u00EC", "ì");
+ initialMap.put("\u00CC", "Ì");
+ initialMap.put("\u00CC", "Ì");
+ initialMap.put("\u2111", "ℑ");
+ initialMap.put("\uD835\uDD26", "𝔦");
+ initialMap.put("\u21D4", "⇔");
+ initialMap.put("\u00A1", "¡");
+ initialMap.put("\u00A1", "¡");
+ initialMap.put("\u0435", "е");
+ initialMap.put("\u0415", "Е");
+ initialMap.put("\u0130", "İ");
+ initialMap.put("\u0438", "и");
+ initialMap.put("\u0418", "И");
+ initialMap.put("\u00EE", "î");
+ initialMap.put("\u00EE", "î");
+ initialMap.put("\u00CE", "Î");
+ initialMap.put("\u00CE", "Î");
+ initialMap.put("\u2063", "⁣");
+ initialMap.put("\u00ED", "í");
+ initialMap.put("\u00ED", "í");
+ initialMap.put("\u00CD", "Í");
+ initialMap.put("\u00CD", "Í");
+ initialMap.put("\u2010", "‐");
+ initialMap.put("\u2043", "⁃");
+ initialMap.put("\u224F", "≏");
+ initialMap.put("\u224E", "≎");
+ initialMap.put("\u0127", "ħ");
+ initialMap.put("\u0126", "Ħ");
+ initialMap.put("\u210F", "ℏ");
+ initialMap.put("\u210B", "ℋ");
+ initialMap.put("\uD835\uDCBD", "𝒽");
+ initialMap.put("\u2500", "─");
+ initialMap.put("\u2015", "―");
+ initialMap.put("\u210D", "ℍ");
+ initialMap.put("\uD835\uDD59", "𝕙");
+ initialMap.put("\u21AA", "↪");
+ initialMap.put("\u21A9", "↩");
+ initialMap.put("\u223B", "∻");
+ initialMap.put("\u21FF", "⇿");
+ initialMap.put("\u2926", "⤦");
+ initialMap.put("\u2925", "⤥");
+ initialMap.put("\u210B", "ℋ");
+ initialMap.put("\u210C", "ℌ");
+ initialMap.put("\uD835\uDD25", "𝔥");
+ initialMap.put("\u22B9", "⊹");
+ initialMap.put("\u2026", "…");
+ initialMap.put("\u2665", "♥");
+ initialMap.put("\u2665", "♥");
+ initialMap.put("\u0125", "ĥ");
+ initialMap.put("\u0124", "Ĥ");
+ initialMap.put("\u210F", "ℏ");
+ initialMap.put("\u005E", "^");
+ initialMap.put("\u21AD", "↭");
+ initialMap.put("\u21D4", "⇔");
+ initialMap.put("\u2194", "↔");
+ initialMap.put("\u2948", "⥈");
+ initialMap.put("\u044A", "ъ");
+ initialMap.put("\u042A", "Ъ");
+ initialMap.put("\u210B", "ℋ");
+ initialMap.put("\u00BD", "½");
+ initialMap.put("\u200A", " ");
+ initialMap.put("\u02C7", "ˇ");
+ initialMap.put("\u2269\uFE00", "≩︀");
+ initialMap.put("\u2269\uFE00", "≩︀");
+ initialMap.put("\u2273", "≳");
+ initialMap.put("\u2277", "≷");
+ initialMap.put("\u2A8C", "⪌");
+ initialMap.put("\u22DB", "⋛");
+ initialMap.put("\u22D7", "⋗");
+ initialMap.put("\u2978", "⥸");
+ initialMap.put("\u2A86", "⪆");
+ initialMap.put("\u2A7C", "⩼");
+ initialMap.put("\u2995", "⦕");
+ initialMap.put("\u22D7", "⋗");
+ initialMap.put("\u226B", "≫");
+ initialMap.put("\u003E", ">");
+ initialMap.put("\u003E", ">");
+ initialMap.put("\u003E", ">");
+ initialMap.put("\u003E", ">");
+ initialMap.put("\u2A7A", "⩺");
+ initialMap.put("\u2AA7", "⪧");
+ initialMap.put("\u2A90", "⪐");
+ initialMap.put("\u2A8E", "⪎");
+ initialMap.put("\u2273", "≳");
+ initialMap.put("\u210A", "ℊ");
+ initialMap.put("\uD835\uDCA2", "𝒢");
+ initialMap.put("\u2273", "≳");
+ initialMap.put("\u2A7E", "⩾");
+ initialMap.put("\u2277", "≷");
+ initialMap.put("\u2AA2", "⪢");
+ initialMap.put("\u2267", "≧");
+ initialMap.put("\u22DB", "⋛");
+ initialMap.put("\u2265", "≥");
+ initialMap.put("\u0060", "`");
+ initialMap.put("\uD835\uDD58", "𝕘");
+ initialMap.put("\uD835\uDD3E", "𝔾");
+ initialMap.put("\u22E7", "⋧");
+ initialMap.put("\u2269", "≩");
+ initialMap.put("\u2A88", "⪈");
+ initialMap.put("\u2269", "≩");
+ initialMap.put("\u2A88", "⪈");
+ initialMap.put("\u2A8A", "⪊");
+ initialMap.put("\u2A8A", "⪊");
+ initialMap.put("\u2AA4", "⪤");
+ initialMap.put("\u2A92", "⪒");
+ initialMap.put("\u2277", "≷");
+ initialMap.put("\u2AA5", "⪥");
+ initialMap.put("\u0453", "ѓ");
+ initialMap.put("\u0403", "Ѓ");
+ initialMap.put("\u2137", "ℷ");
+ initialMap.put("\u22D9", "⋙");
+ initialMap.put("\u22D9", "⋙");
+ initialMap.put("\u226B", "≫");
+ initialMap.put("\uD835\uDD24", "𝔤");
+ initialMap.put("\uD835\uDD0A", "𝔊");
+ initialMap.put("\u2A94", "⪔");
+ initialMap.put("\u22DB\uFE00", "⋛︀");
+ initialMap.put("\u2A84", "⪄");
+ initialMap.put("\u2A82", "⪂");
+ initialMap.put("\u2A80", "⪀");
+ initialMap.put("\u2A7E", "⩾");
+ initialMap.put("\u2AA9", "⪩");
+ initialMap.put("\u2A7E", "⩾");
+ initialMap.put("\u2267", "≧");
+ initialMap.put("\u2265", "≥");
+ initialMap.put("\u22DB", "⋛");
+ initialMap.put("\u2A8C", "⪌");
+ initialMap.put("\u2267", "≧");
+ initialMap.put("\u2265", "≥");
+ initialMap.put("\u0121", "ġ");
+ initialMap.put("\u0120", "Ġ");
+ initialMap.put("\u0433", "г");
+ initialMap.put("\u0413", "Г");
+ initialMap.put("\u011D", "ĝ");
+ initialMap.put("\u011C", "Ĝ");
+ initialMap.put("\u0122", "Ģ");
+ initialMap.put("\u011F", "ğ");
+ initialMap.put("\u011E", "Ğ");
+ initialMap.put("\u2A86", "⪆");
+ initialMap.put("\u03DD", "ϝ");
+ initialMap.put("\u03DC", "Ϝ");
+ initialMap.put("\u03B3", "γ");
+ initialMap.put("\u0393", "Γ");
+ initialMap.put("\u01F5", "ǵ");
+ initialMap.put("\u2131", "ℱ");
+ initialMap.put("\uD835\uDCBB", "𝒻");
+ initialMap.put("\u2322", "⌢");
+ initialMap.put("\u2044", "⁄");
+ initialMap.put("\u215E", "⅞");
+ initialMap.put("\u215D", "⅝");
+ initialMap.put("\u215A", "⅚");
+ initialMap.put("\u2158", "⅘");
+ initialMap.put("\u215C", "⅜");
+ initialMap.put("\u2157", "⅗");
+ initialMap.put("\u00BE", "¾");
+ initialMap.put("\u00BE", "¾");
+ initialMap.put("\u2156", "⅖");
+ initialMap.put("\u2154", "⅔");
+ initialMap.put("\u215B", "⅛");
+ initialMap.put("\u2159", "⅙");
+ initialMap.put("\u2155", "⅕");
+ initialMap.put("\u00BC", "¼");
+ initialMap.put("\u00BC", "¼");
+ initialMap.put("\u2153", "⅓");
+ initialMap.put("\u00BD", "½");
+ initialMap.put("\u00BD", "½");
+ initialMap.put("\u2A0D", "⨍");
+ initialMap.put("\u2131", "ℱ");
+ initialMap.put("\u2AD9", "⫙");
+ initialMap.put("\u22D4", "⋔");
+ initialMap.put("\u2200", "∀");
+ initialMap.put("\u2200", "∀");
+ initialMap.put("\uD835\uDD57", "𝕗");
+ initialMap.put("\uD835\uDD3D", "𝔽");
+ initialMap.put("\u0192", "ƒ");
+ initialMap.put("\u25B1", "▱");
+ initialMap.put("\uFB02", "fl");
+ initialMap.put("\u266D", "♭");
+ initialMap.put("\u0066\u006A", "fj");
+ initialMap.put("\u25AA", "▪");
+ initialMap.put("\u25FC", "◼");
+ initialMap.put("\uFB01", "fi");
+ initialMap.put("\uD835\uDD23", "𝔣");
+ initialMap.put("\uD835\uDD09", "𝔉");
+ initialMap.put("\uFB04", "ffl");
+ initialMap.put("\uFB00", "ff");
+ initialMap.put("\uFB03", "ffi");
+ initialMap.put("\u2640", "♀");
+ initialMap.put("\u0444", "ф");
+ initialMap.put("\u0424", "Ф");
+ initialMap.put("\u2252", "≒");
+ initialMap.put("\u2147", "ⅇ");
+ initialMap.put("\u2147", "ⅇ");
+ initialMap.put("\u2130", "ℰ");
+ initialMap.put("\u2203", "∃");
+ initialMap.put("\u2203", "∃");
+ initialMap.put("\u0021", "!");
+ initialMap.put("\u20AC", "€");
+ initialMap.put("\u00EB", "ë");
+ initialMap.put("\u00EB", "ë");
+ initialMap.put("\u00CB", "Ë");
+ initialMap.put("\u00CB", "Ë");
+ initialMap.put("\u00F0", "ð");
+ initialMap.put("\u00F0", "ð");
+ initialMap.put("\u00D0", "Ð");
+ initialMap.put("\u00D0", "Ð");
+ initialMap.put("\u03B7", "η");
+ initialMap.put("\u0397", "Η");
+ initialMap.put("\u2242", "≂");
+ initialMap.put("\u2A73", "⩳");
+ initialMap.put("\u2250", "≐");
+ initialMap.put("\u2130", "ℰ");
+ initialMap.put("\u212F", "ℯ");
+ initialMap.put("\u2253", "≓");
+ initialMap.put("\u2971", "⥱");
+ initialMap.put("\u29E5", "⧥");
+ initialMap.put("\u2A78", "⩸");
+ initialMap.put("\u2261", "≡");
+ initialMap.put("\u21CC", "⇌");
+ initialMap.put("\u225F", "≟");
+ initialMap.put("\u2242", "≂");
+ initialMap.put("\u003D", "=");
+ initialMap.put("\u2A75", "⩵");
+ initialMap.put("\u2A95", "⪕");
+ initialMap.put("\u2A96", "⪖");
+ initialMap.put("\u2242", "≂");
+ initialMap.put("\u2255", "≕");
+ initialMap.put("\u2256", "≖");
+ initialMap.put("\u03F5", "ϵ");
+ initialMap.put("\u03B5", "ε");
+ initialMap.put("\u0395", "Ε");
+ initialMap.put("\u03B5", "ε");
+ initialMap.put("\u2A71", "⩱");
+ initialMap.put("\u29E3", "⧣");
+ initialMap.put("\u22D5", "⋕");
+ initialMap.put("\uD835\uDD56", "𝕖");
+ initialMap.put("\uD835\uDD3C", "𝔼");
+ initialMap.put("\u0119", "ę");
+ initialMap.put("\u0118", "Ę");
+ initialMap.put("\u2002", " ");
+ initialMap.put("\u014B", "ŋ");
+ initialMap.put("\u014A", "Ŋ");
+ initialMap.put("\u2003", " ");
+ initialMap.put("\u2005", " ");
+ initialMap.put("\u2004", " ");
+ initialMap.put("\u25AB", "▫");
+ initialMap.put("\u2205", "∅");
+ initialMap.put("\u25FB", "◻");
+ initialMap.put("\u2205", "∅");
+ initialMap.put("\u2205", "∅");
+ initialMap.put("\u0113", "ē");
+ initialMap.put("\u0112", "Ē");
+ initialMap.put("\u2A97", "⪗");
+ initialMap.put("\u2A95", "⪕");
+ initialMap.put("\u2113", "ℓ");
+ initialMap.put("\u23E7", "⏧");
+ initialMap.put("\u2208", "∈");
+ initialMap.put("\u2A99", "⪙");
+ initialMap.put("\u2A98", "⪘");
+ initialMap.put("\u2A96", "⪖");
+ initialMap.put("\u00E8", "è");
+ initialMap.put("\u00E8", "è");
+ initialMap.put("\u00C8", "È");
+ initialMap.put("\u00C8", "È");
+ initialMap.put("\u2A9A", "⪚");
+ initialMap.put("\uD835\uDD22", "𝔢");
+ initialMap.put("\uD835\uDD08", "𝔈");
+ initialMap.put("\u2252", "≒");
+ initialMap.put("\u2147", "ⅇ");
+ initialMap.put("\u2251", "≑");
+ initialMap.put("\u0117", "ė");
+ initialMap.put("\u0116", "Ė");
+ initialMap.put("\u2A77", "⩷");
+ initialMap.put("\u044D", "э");
+ initialMap.put("\u042D", "Э");
+ initialMap.put("\u2255", "≕");
+ initialMap.put("\u2256", "≖");
+ initialMap.put("\u00EA", "ê");
+ initialMap.put("\u00EA", "ê");
+ initialMap.put("\u00CA", "Ê");
+ initialMap.put("\u00CA", "Ê");
+ initialMap.put("\u011B", "ě");
+ initialMap.put("\u011A", "Ě");
+ initialMap.put("\u2A6E", "⩮");
+ initialMap.put("\u00E9", "é");
+ initialMap.put("\u00E9", "é");
+ initialMap.put("\u00C9", "É");
+ initialMap.put("\u00C9", "É");
+ initialMap.put("\u27FF", "⟿");
+ initialMap.put("\u045F", "џ");
+ initialMap.put("\u040F", "Џ");
+ initialMap.put("\u29A6", "⦦");
+ initialMap.put("\u296F", "⥯");
+ initialMap.put("\u21F5", "⇵");
+ initialMap.put("\u25BE", "▾");
+ initialMap.put("\u25BF", "▿");
+ initialMap.put("\u22F1", "⋱");
+ initialMap.put("\u0111", "đ");
+ initialMap.put("\u0110", "Đ");
+ initialMap.put("\u29F6", "⧶");
+ initialMap.put("\u0455", "ѕ");
+ initialMap.put("\u0405", "Ѕ");
+ initialMap.put("\uD835\uDCB9", "𝒹");
+ initialMap.put("\uD835\uDC9F", "𝒟");
+ initialMap.put("\u230C", "⌌");
+ initialMap.put("\u231F", "⌟");
+ initialMap.put("\u2910", "⤐");
+ initialMap.put("\u22A4", "⊤");
+ initialMap.put("\u21A7", "↧");
+ initialMap.put("\u21C1", "⇁");
+ initialMap.put("\u2957", "⥗");
+ initialMap.put("\u295F", "⥟");
+ initialMap.put("\u21BD", "↽");
+ initialMap.put("\u2956", "⥖");
+ initialMap.put("\u295E", "⥞");
+ initialMap.put("\u2950", "⥐");
+ initialMap.put("\u21C2", "⇂");
+ initialMap.put("\u21C3", "⇃");
+ initialMap.put("\u21CA", "⇊");
+ initialMap.put("\u0311", "̑");
+ initialMap.put("\u21F5", "⇵");
+ initialMap.put("\u21D3", "⇓");
+ initialMap.put("\u2193", "↓");
+ initialMap.put("\u2193", "↓");
+ initialMap.put("\u2913", "⤓");
+ initialMap.put("\u2225", "∥");
+ initialMap.put("\u21D5", "⇕");
+ initialMap.put("\u21D1", "⇑");
+ initialMap.put("\u22A8", "⊨");
+ initialMap.put("\u21D2", "⇒");
+ initialMap.put("\u27F9", "⟹");
+ initialMap.put("\u27FA", "⟺");
+ initialMap.put("\u27F8", "⟸");
+ initialMap.put("\u2AE4", "⫤");
+ initialMap.put("\u21D4", "⇔");
+ initialMap.put("\u21D0", "⇐");
+ initialMap.put("\u21D3", "⇓");
+ initialMap.put("\u00A8", "¨");
+ initialMap.put("\u222F", "∯");
+ initialMap.put("\u2306", "⌆");
+ initialMap.put("\u22A1", "⊡");
+ initialMap.put("\u2214", "∔");
+ initialMap.put("\u2238", "∸");
+ initialMap.put("\u2250", "≐");
+ initialMap.put("\u2251", "≑");
+ initialMap.put("\u2250", "≐");
+ initialMap.put("\u20DC", "⃜");
+ initialMap.put("\u02D9", "˙");
+ initialMap.put("\u00A8", "¨");
+ initialMap.put("\uD835\uDD55", "𝕕");
+ initialMap.put("\uD835\uDD3B", "𝔻");
+ initialMap.put("\u0024", "$");
+ initialMap.put("\u230D", "⌍");
+ initialMap.put("\u231E", "⌞");
+ initialMap.put("\u0452", "ђ");
+ initialMap.put("\u0402", "Ђ");
+ initialMap.put("\u22C7", "⋇");
+ initialMap.put("\u22C7", "⋇");
+ initialMap.put("\u00F7", "÷");
+ initialMap.put("\u00F7", "÷");
+ initialMap.put("\u00F7", "÷");
+ initialMap.put("\u22F2", "⋲");
+ initialMap.put("\u03DD", "ϝ");
+ initialMap.put("\u2146", "ⅆ");
+ initialMap.put("\u00A8", "¨");
+ initialMap.put("\u2666", "♦");
+ initialMap.put("\u2666", "♦");
+ initialMap.put("\u22C4", "⋄");
+ initialMap.put("\u22C4", "⋄");
+ initialMap.put("\u22C4", "⋄");
+ initialMap.put("\u02DC", "˜");
+ initialMap.put("\u0060", "`");
+ initialMap.put("\u02DD", "˝");
+ initialMap.put("\u02D9", "˙");
+ initialMap.put("\u00B4", "´");
+ initialMap.put("\u21C2", "⇂");
+ initialMap.put("\u21C3", "⇃");
+ initialMap.put("\u2965", "⥥");
+ initialMap.put("\uD835\uDD21", "𝔡");
+ initialMap.put("\uD835\uDD07", "𝔇");
+ initialMap.put("\u297F", "⥿");
+ initialMap.put("\u29B1", "⦱");
+ initialMap.put("\u03B4", "δ");
+ initialMap.put("\u0394", "Δ");
+ initialMap.put("\u2207", "∇");
+ initialMap.put("\u00B0", "°");
+ initialMap.put("\u00B0", "°");
+ initialMap.put("\u2A77", "⩷");
+ initialMap.put("\u2911", "⤑");
+ initialMap.put("\u2146", "ⅆ");
+ initialMap.put("\u2145", "ⅅ");
+ initialMap.put("\u21CA", "⇊");
+ initialMap.put("\u2021", "‡");
+ initialMap.put("\u0434", "д");
+ initialMap.put("\u0414", "Д");
+ initialMap.put("\u010F", "ď");
+ initialMap.put("\u010E", "Ď");
+ initialMap.put("\u02DD", "˝");
+ initialMap.put("\u290F", "⤏");
+ initialMap.put("\u22A3", "⊣");
+ initialMap.put("\u2AE4", "⫤");
+ initialMap.put("\u2010", "‐");
+ initialMap.put("\u21D3", "⇓");
+ initialMap.put("\u21A1", "↡");
+ initialMap.put("\u2193", "↓");
+ initialMap.put("\u2138", "ℸ");
+ initialMap.put("\u2021", "‡");
+ initialMap.put("\u2020", "†");
+ initialMap.put("\u232D", "⌭");
+ initialMap.put("\u2231", "∱");
+ initialMap.put("\u2232", "∲");
+ initialMap.put("\u22CF", "⋏");
+ initialMap.put("\u22CE", "⋎");
+ initialMap.put("\u21B7", "↷");
+ initialMap.put("\u21B6", "↶");
+ initialMap.put("\u00A4", "¤");
+ initialMap.put("\u00A4", "¤");
+ initialMap.put("\u22CF", "⋏");
+ initialMap.put("\u22CE", "⋎");
+ initialMap.put("\u22DF", "⋟");
+ initialMap.put("\u22DE", "⋞");
+ initialMap.put("\u293C", "⤼");
+ initialMap.put("\u21B7", "↷");
+ initialMap.put("\u222A\uFE00", "∪︀");
+ initialMap.put("\u2A45", "⩅");
+ initialMap.put("\u228D", "⊍");
+ initialMap.put("\u2A4A", "⩊");
+ initialMap.put("\u22D3", "⋓");
+ initialMap.put("\u222A", "∪");
+ initialMap.put("\u224D", "≍");
+ initialMap.put("\u2A46", "⩆");
+ initialMap.put("\u2A48", "⩈");
+ initialMap.put("\u293D", "⤽");
+ initialMap.put("\u21B6", "↶");
+ initialMap.put("\u22DF", "⋟");
+ initialMap.put("\u22DE", "⋞");
+ initialMap.put("\u2935", "⤵");
+ initialMap.put("\u2938", "⤸");
+ initialMap.put("\u22EF", "⋯");
+ initialMap.put("\u2AD2", "⫒");
+ initialMap.put("\u2AD0", "⫐");
+ initialMap.put("\u2AD1", "⫑");
+ initialMap.put("\u2ACF", "⫏");
+ initialMap.put("\uD835\uDCB8", "𝒸");
+ initialMap.put("\uD835\uDC9E", "𝒞");
+ initialMap.put("\u2A2F", "⨯");
+ initialMap.put("\u2717", "✗");
+ initialMap.put("\u21B5", "↵");
+ initialMap.put("\u2233", "∳");
+ initialMap.put("\u2117", "℗");
+ initialMap.put("\u00A9", "©");
+ initialMap.put("\u00A9", "©");
+ initialMap.put("\u00A9", "©");
+ initialMap.put("\u00A9", "©");
+ initialMap.put("\u2210", "∐");
+ initialMap.put("\u2210", "∐");
+ initialMap.put("\u2102", "ℂ");
+ initialMap.put("\uD835\uDD54", "𝕔");
+ initialMap.put("\u222E", "∮");
+ initialMap.put("\u222F", "∯");
+ initialMap.put("\u222E", "∮");
+ initialMap.put("\u2261", "≡");
+ initialMap.put("\u2A6D", "⩭");
+ initialMap.put("\u2245", "≅");
+ initialMap.put("\u2102", "ℂ");
+ initialMap.put("\u2201", "∁");
+ initialMap.put("\u2218", "∘");
+ initialMap.put("\u2201", "∁");
+ initialMap.put("\u0040", "@");
+ initialMap.put("\u002C", ",");
+ initialMap.put("\u2254", "≔");
+ initialMap.put("\u2254", "≔");
+ initialMap.put("\u2A74", "⩴");
+ initialMap.put("\u2237", "∷");
+ initialMap.put("\u003A", ":");
+ initialMap.put("\u2663", "♣");
+ initialMap.put("\u2663", "♣");
+ initialMap.put("\u2019", "’");
+ initialMap.put("\u201D", "”");
+ initialMap.put("\u2232", "∲");
+ initialMap.put("\u29C2", "⧂");
+ initialMap.put("\u2AEF", "⫯");
+ initialMap.put("\u2A10", "⨐");
+ initialMap.put("\u2257", "≗");
+ initialMap.put("\u29C3", "⧃");
+ initialMap.put("\u25CB", "○");
+ initialMap.put("\u2297", "⊗");
+ initialMap.put("\u2295", "⊕");
+ initialMap.put("\u2296", "⊖");
+ initialMap.put("\u24C8", "Ⓢ");
+ initialMap.put("\u00AE", "®");
+ initialMap.put("\u2299", "⊙");
+ initialMap.put("\u229D", "⊝");
+ initialMap.put("\u229A", "⊚");
+ initialMap.put("\u229B", "⊛");
+ initialMap.put("\u21BB", "↻");
+ initialMap.put("\u21BA", "↺");
+ initialMap.put("\u2257", "≗");
+ initialMap.put("\u02C6", "ˆ");
+ initialMap.put("\u03C7", "χ");
+ initialMap.put("\u03A7", "Χ");
+ initialMap.put("\u2713", "✓");
+ initialMap.put("\u2713", "✓");
+ initialMap.put("\u0447", "ч");
+ initialMap.put("\u0427", "Ч");
+ initialMap.put("\u212D", "ℭ");
+ initialMap.put("\uD835\uDD20", "𝔠");
+ initialMap.put("\u00B7", "·");
+ initialMap.put("\u00B7", "·");
+ initialMap.put("\u00A2", "¢");
+ initialMap.put("\u00A2", "¢");
+ initialMap.put("\u29B2", "⦲");
+ initialMap.put("\u00B8", "¸");
+ initialMap.put("\u00B8", "¸");
+ initialMap.put("\u00B8", "¸");
+ initialMap.put("\u010B", "ċ");
+ initialMap.put("\u010A", "Ċ");
+ initialMap.put("\u2A50", "⩐");
+ initialMap.put("\u2A4C", "⩌");
+ initialMap.put("\u2230", "∰");
+ initialMap.put("\u0109", "ĉ");
+ initialMap.put("\u0108", "Ĉ");
+ initialMap.put("\u00E7", "ç");
+ initialMap.put("\u00E7", "ç");
+ initialMap.put("\u00C7", "Ç");
+ initialMap.put("\u00C7", "Ç");
+ initialMap.put("\u010D", "č");
+ initialMap.put("\u010C", "Č");
+ initialMap.put("\u2A4D", "⩍");
+ initialMap.put("\u212D", "ℭ");
+ initialMap.put("\u02C7", "ˇ");
+ initialMap.put("\u2041", "⁁");
+ initialMap.put("\u2229\uFE00", "∩︀");
+ initialMap.put("\u2145", "ⅅ");
+ initialMap.put("\u2A40", "⩀");
+ initialMap.put("\u2A47", "⩇");
+ initialMap.put("\u22D2", "⋒");
+ initialMap.put("\u2229", "∩");
+ initialMap.put("\u2A4B", "⩋");
+ initialMap.put("\u2A49", "⩉");
+ initialMap.put("\u2A44", "⩄");
+ initialMap.put("\u0107", "ć");
+ initialMap.put("\u0106", "Ć");
+ initialMap.put("\u224F", "≏");
+ initialMap.put("\u224E", "≎");
+ initialMap.put("\u224F", "≏");
+ initialMap.put("\u2AAE", "⪮");
+ initialMap.put("\u224E", "≎");
+ initialMap.put("\u2022", "•");
+ initialMap.put("\u2022", "•");
+ initialMap.put("\u27C8", "⟈");
+ initialMap.put("\\", "\");
+ initialMap.put("\u29C5", "⧅");
+ initialMap.put("\u22CD", "⋍");
+ initialMap.put("\u223D", "∽");
+ initialMap.put("\u204F", "⁏");
+ initialMap.put("\u212C", "ℬ");
+ initialMap.put("\uD835\uDCB7", "𝒷");
+ initialMap.put("\u00A6", "¦");
+ initialMap.put("\u00A6", "¦");
+ initialMap.put("\u02D8", "˘");
+ initialMap.put("\u02D8", "˘");
+ initialMap.put("\u2035", "‵");
+ initialMap.put("\u2560", "╠");
+ initialMap.put("\u255F", "╟");
+ initialMap.put("\u255E", "╞");
+ initialMap.put("\u251C", "├");
+ initialMap.put("\u2563", "╣");
+ initialMap.put("\u2562", "╢");
+ initialMap.put("\u2561", "╡");
+ initialMap.put("\u2524", "┤");
+ initialMap.put("\u256C", "╬");
+ initialMap.put("\u256B", "╫");
+ initialMap.put("\u256A", "╪");
+ initialMap.put("\u253C", "┼");
+ initialMap.put("\u2551", "║");
+ initialMap.put("\u2502", "│");
+ initialMap.put("\u255A", "╚");
+ initialMap.put("\u2559", "╙");
+ initialMap.put("\u2558", "╘");
+ initialMap.put("\u2514", "└");
+ initialMap.put("\u255D", "╝");
+ initialMap.put("\u255C", "╜");
+ initialMap.put("\u255B", "╛");
+ initialMap.put("\u2518", "┘");
+ initialMap.put("\u22A0", "⊠");
+ initialMap.put("\u229E", "⊞");
+ initialMap.put("\u229F", "⊟");
+ initialMap.put("\u2569", "╩");
+ initialMap.put("\u2568", "╨");
+ initialMap.put("\u2567", "╧");
+ initialMap.put("\u2534", "┴");
+ initialMap.put("\u2566", "╦");
+ initialMap.put("\u2565", "╥");
+ initialMap.put("\u2564", "╤");
+ initialMap.put("\u252C", "┬");
+ initialMap.put("\u2550", "═");
+ initialMap.put("\u2500", "─");
+ initialMap.put("\u2554", "╔");
+ initialMap.put("\u2553", "╓");
+ initialMap.put("\u2552", "╒");
+ initialMap.put("\u250C", "┌");
+ initialMap.put("\u2557", "╗");
+ initialMap.put("\u2556", "╖");
+ initialMap.put("\u2555", "╕");
+ initialMap.put("\u2510", "┐");
+ initialMap.put("\u29C9", "⧉");
+ initialMap.put("\u22C8", "⋈");
+ initialMap.put("\u22A5", "⊥");
+ initialMap.put("\u22A5", "⊥");
+ initialMap.put("\uD835\uDD53", "𝕓");
+ initialMap.put("\uD835\uDD39", "𝔹");
+ initialMap.put("\u2310", "⌐");
+ initialMap.put("\u2AED", "⫭");
+ initialMap.put("\u2261\u20E5", "≡⃥");
+ initialMap.put("\u003D\u20E5", "=⃥");
+ initialMap.put("\u2588", "█");
+ initialMap.put("\u2593", "▓");
+ initialMap.put("\u2591", "░");
+ initialMap.put("\u2592", "▒");
+ initialMap.put("\u2423", "␣");
+ initialMap.put("\u25B8", "▸");
+ initialMap.put("\u25C2", "◂");
+ initialMap.put("\u25BE", "▾");
+ initialMap.put("\u25B4", "▴");
+ initialMap.put("\u25AA", "▪");
+ initialMap.put("\u29EB", "⧫");
+ initialMap.put("\u290D", "⤍");
+ initialMap.put("\u22C0", "⋀");
+ initialMap.put("\u22C1", "⋁");
+ initialMap.put("\u2A04", "⨄");
+ initialMap.put("\u25B3", "△");
+ initialMap.put("\u25BD", "▽");
+ initialMap.put("\u2605", "★");
+ initialMap.put("\u2A06", "⨆");
+ initialMap.put("\u2A02", "⨂");
+ initialMap.put("\u2A01", "⨁");
+ initialMap.put("\u2A00", "⨀");
+ initialMap.put("\u22C3", "⋃");
+ initialMap.put("\u25EF", "◯");
+ initialMap.put("\u22C2", "⋂");
+ initialMap.put("\uD835\uDD1F", "𝔟");
+ initialMap.put("\uD835\uDD05", "𝔅");
+ initialMap.put("\u226C", "≬");
+ initialMap.put("\u2136", "ℶ");
+ initialMap.put("\u03B2", "β");
+ initialMap.put("\u0392", "Β");
+ initialMap.put("\u212C", "ℬ");
+ initialMap.put("\u212C", "ℬ");
+ initialMap.put("\u03F6", "϶");
+ initialMap.put("\u29B0", "⦰");
+ initialMap.put("\u2235", "∵");
+ initialMap.put("\u2235", "∵");
+ initialMap.put("\u2235", "∵");
+ initialMap.put("\u201E", "„");
+ initialMap.put("\u0431", "б");
+ initialMap.put("\u0411", "Б");
+ initialMap.put("\u224C", "≌");
+ initialMap.put("\u23B6", "⎶");
+ initialMap.put("\u23B5", "⎵");
+ initialMap.put("\u2305", "⌅");
+ initialMap.put("\u2306", "⌆");
+ initialMap.put("\u2305", "⌅");
+ initialMap.put("\u22BD", "⊽");
+ initialMap.put("\u2AE7", "⫧");
+ initialMap.put("\u2216", "∖");
+ initialMap.put("\u22CD", "⋍");
+ initialMap.put("\u223D", "∽");
+ initialMap.put("\u2035", "‵");
+ initialMap.put("\u03F6", "϶");
+ initialMap.put("\u224C", "≌");
+ initialMap.put("\u2A11", "⨑");
+ initialMap.put("\u2233", "∳");
+ initialMap.put("\u00E4", "ä");
+ initialMap.put("\u00E4", "ä");
+ initialMap.put("\u00C4", "Ä");
+ initialMap.put("\u00C4", "Ä");
+ initialMap.put("\u00E3", "ã");
+ initialMap.put("\u00E3", "ã");
+ initialMap.put("\u00C3", "Ã");
+ initialMap.put("\u00C3", "Ã");
+ initialMap.put("\u224D", "≍");
+ initialMap.put("\u2248", "≈");
+ initialMap.put("\u002A", "*");
+ initialMap.put("\u2254", "≔");
+ initialMap.put("\uD835\uDCB6", "𝒶");
+ initialMap.put("\uD835\uDC9C", "𝒜");
+ initialMap.put("\u00E5", "å");
+ initialMap.put("\u00E5", "å");
+ initialMap.put("\u00C5", "Å");
+ initialMap.put("\u00C5", "Å");
+ initialMap.put("\u224A", "≊");
+ initialMap.put("\u2248", "≈");
+ initialMap.put("\u2061", "⁡");
+ initialMap.put("\u0027", "'");
+ initialMap.put("\u224B", "≋");
+ initialMap.put("\u224A", "≊");
+ initialMap.put("\u2A70", "⩰");
+ initialMap.put("\u2248", "≈");
+ initialMap.put("\u2A6F", "⩯");
+ initialMap.put("\uD835\uDD52", "𝕒");
+ initialMap.put("\uD835\uDD38", "𝔸");
+ initialMap.put("\u0105", "ą");
+ initialMap.put("\u0104", "Ą");
+ initialMap.put("\u237C", "⍼");
+ initialMap.put("\u00C5", "Å");
+ initialMap.put("\u2222", "∢");
+ initialMap.put("\u299D", "⦝");
+ initialMap.put("\u22BE", "⊾");
+ initialMap.put("\u221F", "∟");
+ initialMap.put("\u2221", "∡");
+ initialMap.put("\u29AF", "⦯");
+ initialMap.put("\u29AE", "⦮");
+ initialMap.put("\u29AD", "⦭");
+ initialMap.put("\u29AC", "⦬");
+ initialMap.put("\u29AB", "⦫");
+ initialMap.put("\u29AA", "⦪");
+ initialMap.put("\u29A9", "⦩");
+ initialMap.put("\u29A8", "⦨");
+ initialMap.put("\u2220", "∠");
+ initialMap.put("\u29A4", "⦤");
+ initialMap.put("\u2220", "∠");
+ initialMap.put("\u2A5A", "⩚");
+ initialMap.put("\u2A58", "⩘");
+ initialMap.put("\u2A5C", "⩜");
+ initialMap.put("\u2227", "∧");
+ initialMap.put("\u2A53", "⩓");
+ initialMap.put("\u2A55", "⩕");
+ initialMap.put("\u0026", "&");
+ initialMap.put("\u0026", "&");
+ initialMap.put("\u0026", "&");
+ initialMap.put("\u0026", "&");
+ initialMap.put("\u2A3F", "⨿");
+ initialMap.put("\u0101", "ā");
+ initialMap.put("\u0100", "Ā");
+ initialMap.put("\u03B1", "α");
+ initialMap.put("\u0391", "Α");
+ initialMap.put("\u2135", "ℵ");
+ initialMap.put("\u2135", "ℵ");
+ initialMap.put("\u00E0", "à");
+ initialMap.put("\u00E0", "à");
+ initialMap.put("\u00C0", "À");
+ initialMap.put("\u00C0", "À");
+ initialMap.put("\uD835\uDD1E", "𝔞");
+ initialMap.put("\uD835\uDD04", "𝔄");
+ initialMap.put("\u2061", "⁡");
+ initialMap.put("\u00E6", "æ");
+ initialMap.put("\u00E6", "æ");
+ initialMap.put("\u00C6", "Æ");
+ initialMap.put("\u00C6", "Æ");
+ initialMap.put("\u0430", "а");
+ initialMap.put("\u0410", "А");
+ initialMap.put("\u00B4", "´");
+ initialMap.put("\u00B4", "´");
+ initialMap.put("\u00E2", "â");
+ initialMap.put("\u00E2", "â");
+ initialMap.put("\u00C2", "Â");
+ initialMap.put("\u00C2", "Â");
+ initialMap.put("\u223E\u0333", "∾̳");
+ initialMap.put("\u223F", "∿");
+ initialMap.put("\u223E", "∾");
+ initialMap.put("\u0103", "ă");
+ initialMap.put("\u0102", "Ă");
+ initialMap.put("\u00E1", "á");
+ initialMap.put("\u00E1", "á");
+ initialMap.put("\u00C1", "Á");
+ initialMap.put("\u00C1", "Á");
+ HTML50_EXTENDED_ESCAPE = Collections.unmodifiableMap(initialMap);
+ }
+
+ public static final Map<CharSequence, CharSequence> HTML50_EXTENDED_UNESCAPE;
+ static {
+ HTML50_EXTENDED_UNESCAPE = Collections.unmodifiableMap(EntityArrays.invert(HTML50_EXTENDED_ESCAPE));
+}
+
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/util/HtmlEntityTranslator.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/util/HtmlEntityTranslator.java
new file mode 100644
index 0000000..a9d736d
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/util/HtmlEntityTranslator.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier.util;
+
+import javax.json.JsonObject;
+
+import org.apache.commons.text.translate.CharSequenceTranslator;
+import org.apache.commons.text.translate.LookupTranslator;
+
+public class HtmlEntityTranslator {
+
+ JsonObject jsonEntities;
+ JsonObject oldEntities;
+
+ public static final CharSequenceTranslator ESCAPE_HTML = new LookupTranslator(Html5Entities.HTML50_EXTENDED_ESCAPE);
+ public static final CharSequenceTranslator UNESCAPE_HTML = new LookupTranslator(Html5Entities.HTML50_EXTENDED_UNESCAPE);
+
+ public static String encodeHTML(String text) {
+ return ESCAPE_HTML.translate(text);
+ }
+
+ public static String decodeHTML(String text) {
+ return UNESCAPE_HTML.translate(text);
+ }
+
+}
diff --git a/tag-modifier/src/main/java/org/apache/sling/tagmodifier/util/HtmlStreams.java b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/util/HtmlStreams.java
new file mode 100644
index 0000000..0bac268
--- /dev/null
+++ b/tag-modifier/src/main/java/org/apache/sling/tagmodifier/util/HtmlStreams.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.tagmodifier.util;
+
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.apache.sling.tagmodifier.AttrValue;
+import org.apache.sling.tagmodifier.Element;
+import org.apache.sling.tagmodifier.impl.tag.StartTag;
+
+public class HtmlStreams {
+
+ private HtmlStreams() {
+ }
+
+ public static final Function<Element, String> TO_HTML = element ->{
+ StringBuilder sb = new StringBuilder();
+ switch (element.getType()) {
+ case COMMENT:
+ sb.append("<!--");
+ sb.append(element.getValue());
+ sb.append("-->");
+ break;
+ case DOCTYPE:
+ sb.append("<!");
+ sb.append(element.getValue());
+ sb.append(">");
+ break;
+ case END_TAG:
+ sb.append("</");
+ sb.append(element.getValue());
+ sb.append('>');
+ break;
+ case EOF:
+ break;
+ case START_TAG:
+ sb.append('<');
+ sb.append(element.getValue());
+ StartTag tag = (StartTag) element;
+ if (tag.hasAttributes()) {
+ sb.append(' ');
+ sb.append(tag.getAttributes().entrySet().stream().map(entry -> {
+ StringBuilder sb2 = new StringBuilder();
+ sb2.append(entry.getKey());
+ AttrValue value = entry.getValue();
+ if (!value.isEmpty()) {
+ sb2.append("=");
+ sb2.append(value.quoteIfNeeded());
+ }
+ return sb2.toString();
+ }).collect(Collectors.joining(" ")));
+ }
+ sb.append('>');
+ break;
+ case TEXT:
+ sb.append(element.toString());
+ }
+ return sb.toString();
+ };
+}
diff --git a/tag-modifier/src/main/javacc/htmlParser.jj b/tag-modifier/src/main/javacc/htmlParser.jj
new file mode 100644
index 0000000..9b41e05
--- /dev/null
+++ b/tag-modifier/src/main/javacc/htmlParser.jj
@@ -0,0 +1,231 @@
+/*
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+options {
+ IGNORE_CASE = true;
+ STATIC = false;
+ UNICODE_INPUT = true;
+}
+
+PARSER_BEGIN(TagParser)
+package org.apache.sling.tagmodifier.impl;
+
+import com.github.tagstream.*;
+import com.github.tagstream.impl.tag.*;
+import java.util.*;
+
+public class TagParser {
+
+ private static String getTokenHtmlText(Token first, Token cur) {
+ Token t;
+ StringBuilder sb = new StringBuilder();
+
+ for (t=first; t != cur.next; t = t.next) {
+ if (t.specialToken != null) {
+ Token tt=t.specialToken;
+ while (tt.specialToken != null)
+ tt = tt.specialToken;
+ for (; tt != null; tt = tt.next)
+ sb.append(tt.image);
+ };
+ sb.append(t.image);
+ };
+ return sb.toString();
+ }
+
+}
+
+PARSER_END(TagParser)
+
+< * >TOKEN :
+{
+ <#SPACE: ( " " | "\t" | "\n" | "\r" | "\u000C" ) >
+| <#ATTR_IDENTIFIER: (~[" ", "\t", "\n", "\r", "\u000C", "=", "/", ">" ])+ >
+| <#NAME_IDENTIFIER: (~[" ", "\t", "\n", "\r", "\u000C", "/", ">" ])+ >
+| <#SQUOTE : ( "'" ( ~["'"] )* "'") >
+| <#DQUOTE : ( "\"" ( ~["\""] )* "\"") >
+| <#TAG_END: ">" >
+| <#TAG_SLASHEND: "/>" >
+}
+
+
+<DEFAULT> TOKEN :
+{
+ <TAG_START: "<" > : START_TAG
+| <ENDTAG_START: "</" > : START_TAG
+| <COMMENT_START: "<!--" > : COMMENT
+| <DECL_START: "<!" > : DECLARATION
+| <RAWTEXT: ( ~["<"] )+ >
+}
+
+
+<START_TAG> TOKEN :
+{
+ <TAG_NAME: <NAME_IDENTIFIER> > : IN_TAG
+| <LST_ERROR: ~[]> : DEFAULT
+}
+
+<IN_TAG, ATTR_VALUE, IN_DECLARATION> SPECIAL_TOKEN :
+{
+ < (<SPACE>)+ >
+}
+
+<IN_TAG> TOKEN :
+{
+ <ATTR_NAME: <ATTR_IDENTIFIER> >
+| <END_OF_TAG: <TAG_END> | <TAG_SLASHEND> > : DEFAULT
+| <ATTR_EQ: "=" > : ATTR_VALUE
+| <LIT_ERROR: ~[]>
+}
+
+
+<ATTR_VALUE> TOKEN :
+{
+ <QUOTED_STRING : < SQUOTE > | < DQUOTE > >{matchedToken.image = image.substring(1, lengthOfMatch - 1);} : IN_TAG
+| <ATTR_VAL: ( ~[">", "\"", "'", " ", "\t", "\n", "\r"] )+ > : IN_TAG
+| <ERROR: ~[]>
+}
+
+<COMMENT> TOKEN :
+{
+ < COMMENT_END: "-->" > : DEFAULT
+| < COMMENT_WORD: ~[] >
+}
+
+<DECLARATION> TOKEN :
+{
+ <DECL_TAG: <NAME_IDENTIFIER> > : IN_DECLARATION
+}
+
+<IN_DECLARATION> TOKEN :
+{
+ <DECL_ATTR: <QUOTED_STRING> | ( ~[">", "\"", "'", " ", "\t", "\n", "\r"] )+ >
+| <DECL_END: <TAG_END> | <TAG_SLASHEND> > : DEFAULT
+}
+
+
+Element element() :
+{
+ Element e;
+ Token text;
+}
+{
+(
+ LOOKAHEAD(2)
+ e = tag() { return e; }
+ | e = endHtmlElement() { return e; }
+ | e = commentHtmlElement() { return e; }
+ | e = decltag() { return e; }
+ | LOOKAHEAD(2)
+ <TAG_START> text=<LST_ERROR>
+ { return new TextData("<" + text.image); }
+ | text = <RAWTEXT> { return new TextData(text.image); }
+ | <EOF> { return new EndOfFile(); }
+)
+}
+
+/** @return an attribute */
+void attribute(Map<String,AttrValue > alist) :
+{
+ Token t1, t2=null;
+}
+{
+ t1=<ATTR_NAME> [ <ATTR_EQ> t2= < QUOTED_STRING > | t2 = <ATTR_VAL> ]
+ {
+ if (t2 == null) {
+ alist.put(t1.image,new AttrValue());
+ } else {
+ alist.put(t1.image,new AttrValue(t2.image));
+ }
+ }
+}
+
+Map<String,AttrValue> attributeList() :
+{
+ Map<String,AttrValue> alist = new HashMap<String,AttrValue>();
+
+}
+{
+ (attribute(alist) )*
+ {
+ return alist;
+ }
+}
+
+
+Element tag() :
+{
+ Token t, et;
+ Map<String,AttrValue> alist;
+ Token firstToken = getToken(1);
+}
+{
+ try {
+ <TAG_START> t=<TAG_NAME> alist=attributeList() et=<END_OF_TAG>
+ {
+ return new StartTag(t.image, alist);
+ }
+ } catch (ParseException ex) {
+ token_source.SwitchTo(DEFAULT);
+ String s = getTokenHtmlText(firstToken, getNextToken());
+ return new TextData(s);
+ }
+}
+
+/** @return the end of a tag */
+Element endHtmlElement() :
+{
+ Token t;
+ Token firstToken = getToken(1);
+}
+{
+ try {
+ <ENDTAG_START> t=<TAG_NAME> <END_OF_TAG>
+ { return new EndTag(t.image); }
+ } catch (ParseException ex) {
+ token_source.SwitchTo(DEFAULT);
+ String s = getTokenHtmlText(firstToken, getNextToken());
+ return new TextData(s);
+ }
+}
+
+
+Comment commentHtmlElement() :
+{
+ StringBuilder sb = new StringBuilder();
+}
+{
+ <COMMENT_START> ( <COMMENT_WORD> { sb.append(token.image); } )* (<EOF> | <COMMENT_END>)
+ { return new Comment(sb.toString()); }
+}
+
+/** @return the start of a DECLARATION */
+Element decltag() :
+{
+ Token tok = null;
+ Map<String,AttrValue > alist = new HashMap<String,AttrValue>();
+ Token firstToken = getToken(1);
+}
+{
+ try {
+ <DECL_START> tok=<DECL_TAG> (< DECL_ATTR > { alist.put(token.image,new AttrValue()); })* <DECL_END>
+ {
+ return new StartTag(tok.image, alist);
+ }
+ } catch (ParseException ex) {
+ token_source.SwitchTo(DEFAULT);
+ String s = getTokenHtmlText(firstToken, getNextToken());
+ return new TextData(s);
+ }
+}
diff --git a/tag-modifier/src/main/resources/entities.json b/tag-modifier/src/main/resources/entities.json
new file mode 100644
index 0000000..6fed08d
--- /dev/null
+++ b/tag-modifier/src/main/resources/entities.json
@@ -0,0 +1,2233 @@
+{
+ "Á": { "codepoints": [193], "characters": "\u00C1" },
+ "Á": { "codepoints": [193], "characters": "\u00C1" },
+ "á": { "codepoints": [225], "characters": "\u00E1" },
+ "á": { "codepoints": [225], "characters": "\u00E1" },
+ "Ă": { "codepoints": [258], "characters": "\u0102" },
+ "ă": { "codepoints": [259], "characters": "\u0103" },
+ "∾": { "codepoints": [8766], "characters": "\u223E" },
+ "∿": { "codepoints": [8767], "characters": "\u223F" },
+ "∾̳": { "codepoints": [8766, 819], "characters": "\u223E\u0333" },
+ "Â": { "codepoints": [194], "characters": "\u00C2" },
+ "Â": { "codepoints": [194], "characters": "\u00C2" },
+ "â": { "codepoints": [226], "characters": "\u00E2" },
+ "â": { "codepoints": [226], "characters": "\u00E2" },
+ "´": { "codepoints": [180], "characters": "\u00B4" },
+ "´": { "codepoints": [180], "characters": "\u00B4" },
+ "А": { "codepoints": [1040], "characters": "\u0410" },
+ "а": { "codepoints": [1072], "characters": "\u0430" },
+ "Æ": { "codepoints": [198], "characters": "\u00C6" },
+ "Æ": { "codepoints": [198], "characters": "\u00C6" },
+ "æ": { "codepoints": [230], "characters": "\u00E6" },
+ "æ": { "codepoints": [230], "characters": "\u00E6" },
+ "⁡": { "codepoints": [8289], "characters": "\u2061" },
+ "𝔄": { "codepoints": [120068], "characters": "\uD835\uDD04" },
+ "𝔞": { "codepoints": [120094], "characters": "\uD835\uDD1E" },
+ "À": { "codepoints": [192], "characters": "\u00C0" },
+ "À": { "codepoints": [192], "characters": "\u00C0" },
+ "à": { "codepoints": [224], "characters": "\u00E0" },
+ "à": { "codepoints": [224], "characters": "\u00E0" },
+ "ℵ": { "codepoints": [8501], "characters": "\u2135" },
+ "ℵ": { "codepoints": [8501], "characters": "\u2135" },
+ "Α": { "codepoints": [913], "characters": "\u0391" },
+ "α": { "codepoints": [945], "characters": "\u03B1" },
+ "Ā": { "codepoints": [256], "characters": "\u0100" },
+ "ā": { "codepoints": [257], "characters": "\u0101" },
+ "⨿": { "codepoints": [10815], "characters": "\u2A3F" },
+ "&": { "codepoints": [38], "characters": "\u0026" },
+ "&": { "codepoints": [38], "characters": "\u0026" },
+ "&": { "codepoints": [38], "characters": "\u0026" },
+ "&": { "codepoints": [38], "characters": "\u0026" },
+ "⩕": { "codepoints": [10837], "characters": "\u2A55" },
+ "⩓": { "codepoints": [10835], "characters": "\u2A53" },
+ "∧": { "codepoints": [8743], "characters": "\u2227" },
+ "⩜": { "codepoints": [10844], "characters": "\u2A5C" },
+ "⩘": { "codepoints": [10840], "characters": "\u2A58" },
+ "⩚": { "codepoints": [10842], "characters": "\u2A5A" },
+ "∠": { "codepoints": [8736], "characters": "\u2220" },
+ "⦤": { "codepoints": [10660], "characters": "\u29A4" },
+ "∠": { "codepoints": [8736], "characters": "\u2220" },
+ "⦨": { "codepoints": [10664], "characters": "\u29A8" },
+ "⦩": { "codepoints": [10665], "characters": "\u29A9" },
+ "⦪": { "codepoints": [10666], "characters": "\u29AA" },
+ "⦫": { "codepoints": [10667], "characters": "\u29AB" },
+ "⦬": { "codepoints": [10668], "characters": "\u29AC" },
+ "⦭": { "codepoints": [10669], "characters": "\u29AD" },
+ "⦮": { "codepoints": [10670], "characters": "\u29AE" },
+ "⦯": { "codepoints": [10671], "characters": "\u29AF" },
+ "∡": { "codepoints": [8737], "characters": "\u2221" },
+ "∟": { "codepoints": [8735], "characters": "\u221F" },
+ "⊾": { "codepoints": [8894], "characters": "\u22BE" },
+ "⦝": { "codepoints": [10653], "characters": "\u299D" },
+ "∢": { "codepoints": [8738], "characters": "\u2222" },
+ "Å": { "codepoints": [197], "characters": "\u00C5" },
+ "⍼": { "codepoints": [9084], "characters": "\u237C" },
+ "Ą": { "codepoints": [260], "characters": "\u0104" },
+ "ą": { "codepoints": [261], "characters": "\u0105" },
+ "𝔸": { "codepoints": [120120], "characters": "\uD835\uDD38" },
+ "𝕒": { "codepoints": [120146], "characters": "\uD835\uDD52" },
+ "⩯": { "codepoints": [10863], "characters": "\u2A6F" },
+ "≈": { "codepoints": [8776], "characters": "\u2248" },
+ "⩰": { "codepoints": [10864], "characters": "\u2A70" },
+ "≊": { "codepoints": [8778], "characters": "\u224A" },
+ "≋": { "codepoints": [8779], "characters": "\u224B" },
+ "'": { "codepoints": [39], "characters": "\u0027" },
+ "⁡": { "codepoints": [8289], "characters": "\u2061" },
+ "≈": { "codepoints": [8776], "characters": "\u2248" },
+ "≊": { "codepoints": [8778], "characters": "\u224A" },
+ "Å": { "codepoints": [197], "characters": "\u00C5" },
+ "Å": { "codepoints": [197], "characters": "\u00C5" },
+ "å": { "codepoints": [229], "characters": "\u00E5" },
+ "å": { "codepoints": [229], "characters": "\u00E5" },
+ "𝒜": { "codepoints": [119964], "characters": "\uD835\uDC9C" },
+ "𝒶": { "codepoints": [119990], "characters": "\uD835\uDCB6" },
+ "≔": { "codepoints": [8788], "characters": "\u2254" },
+ "*": { "codepoints": [42], "characters": "\u002A" },
+ "≈": { "codepoints": [8776], "characters": "\u2248" },
+ "≍": { "codepoints": [8781], "characters": "\u224D" },
+ "Ã": { "codepoints": [195], "characters": "\u00C3" },
+ "Ã": { "codepoints": [195], "characters": "\u00C3" },
+ "ã": { "codepoints": [227], "characters": "\u00E3" },
+ "ã": { "codepoints": [227], "characters": "\u00E3" },
+ "Ä": { "codepoints": [196], "characters": "\u00C4" },
+ "Ä": { "codepoints": [196], "characters": "\u00C4" },
+ "ä": { "codepoints": [228], "characters": "\u00E4" },
+ "ä": { "codepoints": [228], "characters": "\u00E4" },
+ "∳": { "codepoints": [8755], "characters": "\u2233" },
+ "⨑": { "codepoints": [10769], "characters": "\u2A11" },
+ "≌": { "codepoints": [8780], "characters": "\u224C" },
+ "϶": { "codepoints": [1014], "characters": "\u03F6" },
+ "‵": { "codepoints": [8245], "characters": "\u2035" },
+ "∽": { "codepoints": [8765], "characters": "\u223D" },
+ "⋍": { "codepoints": [8909], "characters": "\u22CD" },
+ "∖": { "codepoints": [8726], "characters": "\u2216" },
+ "⫧": { "codepoints": [10983], "characters": "\u2AE7" },
+ "⊽": { "codepoints": [8893], "characters": "\u22BD" },
+ "⌅": { "codepoints": [8965], "characters": "\u2305" },
+ "⌆": { "codepoints": [8966], "characters": "\u2306" },
+ "⌅": { "codepoints": [8965], "characters": "\u2305" },
+ "⎵": { "codepoints": [9141], "characters": "\u23B5" },
+ "⎶": { "codepoints": [9142], "characters": "\u23B6" },
+ "≌": { "codepoints": [8780], "characters": "\u224C" },
+ "Б": { "codepoints": [1041], "characters": "\u0411" },
+ "б": { "codepoints": [1073], "characters": "\u0431" },
+ "„": { "codepoints": [8222], "characters": "\u201E" },
+ "∵": { "codepoints": [8757], "characters": "\u2235" },
+ "∵": { "codepoints": [8757], "characters": "\u2235" },
+ "∵": { "codepoints": [8757], "characters": "\u2235" },
+ "⦰": { "codepoints": [10672], "characters": "\u29B0" },
+ "϶": { "codepoints": [1014], "characters": "\u03F6" },
+ "ℬ": { "codepoints": [8492], "characters": "\u212C" },
+ "ℬ": { "codepoints": [8492], "characters": "\u212C" },
+ "Β": { "codepoints": [914], "characters": "\u0392" },
+ "β": { "codepoints": [946], "characters": "\u03B2" },
+ "ℶ": { "codepoints": [8502], "characters": "\u2136" },
+ "≬": { "codepoints": [8812], "characters": "\u226C" },
+ "𝔅": { "codepoints": [120069], "characters": "\uD835\uDD05" },
+ "𝔟": { "codepoints": [120095], "characters": "\uD835\uDD1F" },
+ "⋂": { "codepoints": [8898], "characters": "\u22C2" },
+ "◯": { "codepoints": [9711], "characters": "\u25EF" },
+ "⋃": { "codepoints": [8899], "characters": "\u22C3" },
+ "⨀": { "codepoints": [10752], "characters": "\u2A00" },
+ "⨁": { "codepoints": [10753], "characters": "\u2A01" },
+ "⨂": { "codepoints": [10754], "characters": "\u2A02" },
+ "⨆": { "codepoints": [10758], "characters": "\u2A06" },
+ "★": { "codepoints": [9733], "characters": "\u2605" },
+ "▽": { "codepoints": [9661], "characters": "\u25BD" },
+ "△": { "codepoints": [9651], "characters": "\u25B3" },
+ "⨄": { "codepoints": [10756], "characters": "\u2A04" },
+ "⋁": { "codepoints": [8897], "characters": "\u22C1" },
+ "⋀": { "codepoints": [8896], "characters": "\u22C0" },
+ "⤍": { "codepoints": [10509], "characters": "\u290D" },
+ "⧫": { "codepoints": [10731], "characters": "\u29EB" },
+ "▪": { "codepoints": [9642], "characters": "\u25AA" },
+ "▴": { "codepoints": [9652], "characters": "\u25B4" },
+ "▾": { "codepoints": [9662], "characters": "\u25BE" },
+ "◂": { "codepoints": [9666], "characters": "\u25C2" },
+ "▸": { "codepoints": [9656], "characters": "\u25B8" },
+ "␣": { "codepoints": [9251], "characters": "\u2423" },
+ "▒": { "codepoints": [9618], "characters": "\u2592" },
+ "░": { "codepoints": [9617], "characters": "\u2591" },
+ "▓": { "codepoints": [9619], "characters": "\u2593" },
+ "█": { "codepoints": [9608], "characters": "\u2588" },
+ "=⃥": { "codepoints": [61, 8421], "characters": "\u003D\u20E5" },
+ "≡⃥": { "codepoints": [8801, 8421], "characters": "\u2261\u20E5" },
+ "⫭": { "codepoints": [10989], "characters": "\u2AED" },
+ "⌐": { "codepoints": [8976], "characters": "\u2310" },
+ "𝔹": { "codepoints": [120121], "characters": "\uD835\uDD39" },
+ "𝕓": { "codepoints": [120147], "characters": "\uD835\uDD53" },
+ "⊥": { "codepoints": [8869], "characters": "\u22A5" },
+ "⊥": { "codepoints": [8869], "characters": "\u22A5" },
+ "⋈": { "codepoints": [8904], "characters": "\u22C8" },
+ "⧉": { "codepoints": [10697], "characters": "\u29C9" },
+ "┐": { "codepoints": [9488], "characters": "\u2510" },
+ "╕": { "codepoints": [9557], "characters": "\u2555" },
+ "╖": { "codepoints": [9558], "characters": "\u2556" },
+ "╗": { "codepoints": [9559], "characters": "\u2557" },
+ "┌": { "codepoints": [9484], "characters": "\u250C" },
+ "╒": { "codepoints": [9554], "characters": "\u2552" },
+ "╓": { "codepoints": [9555], "characters": "\u2553" },
+ "╔": { "codepoints": [9556], "characters": "\u2554" },
+ "─": { "codepoints": [9472], "characters": "\u2500" },
+ "═": { "codepoints": [9552], "characters": "\u2550" },
+ "┬": { "codepoints": [9516], "characters": "\u252C" },
+ "╤": { "codepoints": [9572], "characters": "\u2564" },
+ "╥": { "codepoints": [9573], "characters": "\u2565" },
+ "╦": { "codepoints": [9574], "characters": "\u2566" },
+ "┴": { "codepoints": [9524], "characters": "\u2534" },
+ "╧": { "codepoints": [9575], "characters": "\u2567" },
+ "╨": { "codepoints": [9576], "characters": "\u2568" },
+ "╩": { "codepoints": [9577], "characters": "\u2569" },
+ "⊟": { "codepoints": [8863], "characters": "\u229F" },
+ "⊞": { "codepoints": [8862], "characters": "\u229E" },
+ "⊠": { "codepoints": [8864], "characters": "\u22A0" },
+ "┘": { "codepoints": [9496], "characters": "\u2518" },
+ "╛": { "codepoints": [9563], "characters": "\u255B" },
+ "╜": { "codepoints": [9564], "characters": "\u255C" },
+ "╝": { "codepoints": [9565], "characters": "\u255D" },
+ "└": { "codepoints": [9492], "characters": "\u2514" },
+ "╘": { "codepoints": [9560], "characters": "\u2558" },
+ "╙": { "codepoints": [9561], "characters": "\u2559" },
+ "╚": { "codepoints": [9562], "characters": "\u255A" },
+ "│": { "codepoints": [9474], "characters": "\u2502" },
+ "║": { "codepoints": [9553], "characters": "\u2551" },
+ "┼": { "codepoints": [9532], "characters": "\u253C" },
+ "╪": { "codepoints": [9578], "characters": "\u256A" },
+ "╫": { "codepoints": [9579], "characters": "\u256B" },
+ "╬": { "codepoints": [9580], "characters": "\u256C" },
+ "┤": { "codepoints": [9508], "characters": "\u2524" },
+ "╡": { "codepoints": [9569], "characters": "\u2561" },
+ "╢": { "codepoints": [9570], "characters": "\u2562" },
+ "╣": { "codepoints": [9571], "characters": "\u2563" },
+ "├": { "codepoints": [9500], "characters": "\u251C" },
+ "╞": { "codepoints": [9566], "characters": "\u255E" },
+ "╟": { "codepoints": [9567], "characters": "\u255F" },
+ "╠": { "codepoints": [9568], "characters": "\u2560" },
+ "‵": { "codepoints": [8245], "characters": "\u2035" },
+ "˘": { "codepoints": [728], "characters": "\u02D8" },
+ "˘": { "codepoints": [728], "characters": "\u02D8" },
+ "¦": { "codepoints": [166], "characters": "\u00A6" },
+ "¦": { "codepoints": [166], "characters": "\u00A6" },
+ "𝒷": { "codepoints": [119991], "characters": "\uD835\uDCB7" },
+ "ℬ": { "codepoints": [8492], "characters": "\u212C" },
+ "⁏": { "codepoints": [8271], "characters": "\u204F" },
+ "∽": { "codepoints": [8765], "characters": "\u223D" },
+ "⋍": { "codepoints": [8909], "characters": "\u22CD" },
+ "⧅": { "codepoints": [10693], "characters": "\u29C5" },
+ "\": { "codepoints": [92], "characters": "\u005C" },
+ "⟈": { "codepoints": [10184], "characters": "\u27C8" },
+ "•": { "codepoints": [8226], "characters": "\u2022" },
+ "•": { "codepoints": [8226], "characters": "\u2022" },
+ "≎": { "codepoints": [8782], "characters": "\u224E" },
+ "⪮": { "codepoints": [10926], "characters": "\u2AAE" },
+ "≏": { "codepoints": [8783], "characters": "\u224F" },
+ "≎": { "codepoints": [8782], "characters": "\u224E" },
+ "≏": { "codepoints": [8783], "characters": "\u224F" },
+ "Ć": { "codepoints": [262], "characters": "\u0106" },
+ "ć": { "codepoints": [263], "characters": "\u0107" },
+ "⩄": { "codepoints": [10820], "characters": "\u2A44" },
+ "⩉": { "codepoints": [10825], "characters": "\u2A49" },
+ "⩋": { "codepoints": [10827], "characters": "\u2A4B" },
+ "∩": { "codepoints": [8745], "characters": "\u2229" },
+ "⋒": { "codepoints": [8914], "characters": "\u22D2" },
+ "⩇": { "codepoints": [10823], "characters": "\u2A47" },
+ "⩀": { "codepoints": [10816], "characters": "\u2A40" },
+ "ⅅ": { "codepoints": [8517], "characters": "\u2145" },
+ "∩︀": { "codepoints": [8745, 65024], "characters": "\u2229\uFE00" },
+ "⁁": { "codepoints": [8257], "characters": "\u2041" },
+ "ˇ": { "codepoints": [711], "characters": "\u02C7" },
+ "ℭ": { "codepoints": [8493], "characters": "\u212D" },
+ "⩍": { "codepoints": [10829], "characters": "\u2A4D" },
+ "Č": { "codepoints": [268], "characters": "\u010C" },
+ "č": { "codepoints": [269], "characters": "\u010D" },
+ "Ç": { "codepoints": [199], "characters": "\u00C7" },
+ "Ç": { "codepoints": [199], "characters": "\u00C7" },
+ "ç": { "codepoints": [231], "characters": "\u00E7" },
+ "ç": { "codepoints": [231], "characters": "\u00E7" },
+ "Ĉ": { "codepoints": [264], "characters": "\u0108" },
+ "ĉ": { "codepoints": [265], "characters": "\u0109" },
+ "∰": { "codepoints": [8752], "characters": "\u2230" },
+ "⩌": { "codepoints": [10828], "characters": "\u2A4C" },
+ "⩐": { "codepoints": [10832], "characters": "\u2A50" },
+ "Ċ": { "codepoints": [266], "characters": "\u010A" },
+ "ċ": { "codepoints": [267], "characters": "\u010B" },
+ "¸": { "codepoints": [184], "characters": "\u00B8" },
+ "¸": { "codepoints": [184], "characters": "\u00B8" },
+ "¸": { "codepoints": [184], "characters": "\u00B8" },
+ "⦲": { "codepoints": [10674], "characters": "\u29B2" },
+ "¢": { "codepoints": [162], "characters": "\u00A2" },
+ "¢": { "codepoints": [162], "characters": "\u00A2" },
+ "·": { "codepoints": [183], "characters": "\u00B7" },
+ "·": { "codepoints": [183], "characters": "\u00B7" },
+ "𝔠": { "codepoints": [120096], "characters": "\uD835\uDD20" },
+ "ℭ": { "codepoints": [8493], "characters": "\u212D" },
+ "Ч": { "codepoints": [1063], "characters": "\u0427" },
+ "ч": { "codepoints": [1095], "characters": "\u0447" },
+ "✓": { "codepoints": [10003], "characters": "\u2713" },
+ "✓": { "codepoints": [10003], "characters": "\u2713" },
+ "Χ": { "codepoints": [935], "characters": "\u03A7" },
+ "χ": { "codepoints": [967], "characters": "\u03C7" },
+ "ˆ": { "codepoints": [710], "characters": "\u02C6" },
+ "≗": { "codepoints": [8791], "characters": "\u2257" },
+ "↺": { "codepoints": [8634], "characters": "\u21BA" },
+ "↻": { "codepoints": [8635], "characters": "\u21BB" },
+ "⊛": { "codepoints": [8859], "characters": "\u229B" },
+ "⊚": { "codepoints": [8858], "characters": "\u229A" },
+ "⊝": { "codepoints": [8861], "characters": "\u229D" },
+ "⊙": { "codepoints": [8857], "characters": "\u2299" },
+ "®": { "codepoints": [174], "characters": "\u00AE" },
+ "Ⓢ": { "codepoints": [9416], "characters": "\u24C8" },
+ "⊖": { "codepoints": [8854], "characters": "\u2296" },
+ "⊕": { "codepoints": [8853], "characters": "\u2295" },
+ "⊗": { "codepoints": [8855], "characters": "\u2297" },
+ "○": { "codepoints": [9675], "characters": "\u25CB" },
+ "⧃": { "codepoints": [10691], "characters": "\u29C3" },
+ "≗": { "codepoints": [8791], "characters": "\u2257" },
+ "⨐": { "codepoints": [10768], "characters": "\u2A10" },
+ "⫯": { "codepoints": [10991], "characters": "\u2AEF" },
+ "⧂": { "codepoints": [10690], "characters": "\u29C2" },
+ "∲": { "codepoints": [8754], "characters": "\u2232" },
+ "”": { "codepoints": [8221], "characters": "\u201D" },
+ "’": { "codepoints": [8217], "characters": "\u2019" },
+ "♣": { "codepoints": [9827], "characters": "\u2663" },
+ "♣": { "codepoints": [9827], "characters": "\u2663" },
+ ":": { "codepoints": [58], "characters": "\u003A" },
+ "∷": { "codepoints": [8759], "characters": "\u2237" },
+ "⩴": { "codepoints": [10868], "characters": "\u2A74" },
+ "≔": { "codepoints": [8788], "characters": "\u2254" },
+ "≔": { "codepoints": [8788], "characters": "\u2254" },
+ ",": { "codepoints": [44], "characters": "\u002C" },
+ "@": { "codepoints": [64], "characters": "\u0040" },
+ "∁": { "codepoints": [8705], "characters": "\u2201" },
+ "∘": { "codepoints": [8728], "characters": "\u2218" },
+ "∁": { "codepoints": [8705], "characters": "\u2201" },
+ "ℂ": { "codepoints": [8450], "characters": "\u2102" },
+ "≅": { "codepoints": [8773], "characters": "\u2245" },
+ "⩭": { "codepoints": [10861], "characters": "\u2A6D" },
+ "≡": { "codepoints": [8801], "characters": "\u2261" },
+ "∮": { "codepoints": [8750], "characters": "\u222E" },
+ "∯": { "codepoints": [8751], "characters": "\u222F" },
+ "∮": { "codepoints": [8750], "characters": "\u222E" },
+ "𝕔": { "codepoints": [120148], "characters": "\uD835\uDD54" },
+ "ℂ": { "codepoints": [8450], "characters": "\u2102" },
+ "∐": { "codepoints": [8720], "characters": "\u2210" },
+ "∐": { "codepoints": [8720], "characters": "\u2210" },
+ "©": { "codepoints": [169], "characters": "\u00A9" },
+ "©": { "codepoints": [169], "characters": "\u00A9" },
+ "©": { "codepoints": [169], "characters": "\u00A9" },
+ "©": { "codepoints": [169], "characters": "\u00A9" },
+ "℗": { "codepoints": [8471], "characters": "\u2117" },
+ "∳": { "codepoints": [8755], "characters": "\u2233" },
+ "↵": { "codepoints": [8629], "characters": "\u21B5" },
+ "✗": { "codepoints": [10007], "characters": "\u2717" },
+ "⨯": { "codepoints": [10799], "characters": "\u2A2F" },
+ "𝒞": { "codepoints": [119966], "characters": "\uD835\uDC9E" },
+ "𝒸": { "codepoints": [119992], "characters": "\uD835\uDCB8" },
+ "⫏": { "codepoints": [10959], "characters": "\u2ACF" },
+ "⫑": { "codepoints": [10961], "characters": "\u2AD1" },
+ "⫐": { "codepoints": [10960], "characters": "\u2AD0" },
+ "⫒": { "codepoints": [10962], "characters": "\u2AD2" },
+ "⋯": { "codepoints": [8943], "characters": "\u22EF" },
+ "⤸": { "codepoints": [10552], "characters": "\u2938" },
+ "⤵": { "codepoints": [10549], "characters": "\u2935" },
+ "⋞": { "codepoints": [8926], "characters": "\u22DE" },
+ "⋟": { "codepoints": [8927], "characters": "\u22DF" },
+ "↶": { "codepoints": [8630], "characters": "\u21B6" },
+ "⤽": { "codepoints": [10557], "characters": "\u293D" },
+ "⩈": { "codepoints": [10824], "characters": "\u2A48" },
+ "⩆": { "codepoints": [10822], "characters": "\u2A46" },
+ "≍": { "codepoints": [8781], "characters": "\u224D" },
+ "∪": { "codepoints": [8746], "characters": "\u222A" },
+ "⋓": { "codepoints": [8915], "characters": "\u22D3" },
+ "⩊": { "codepoints": [10826], "characters": "\u2A4A" },
+ "⊍": { "codepoints": [8845], "characters": "\u228D" },
+ "⩅": { "codepoints": [10821], "characters": "\u2A45" },
+ "∪︀": { "codepoints": [8746, 65024], "characters": "\u222A\uFE00" },
+ "↷": { "codepoints": [8631], "characters": "\u21B7" },
+ "⤼": { "codepoints": [10556], "characters": "\u293C" },
+ "⋞": { "codepoints": [8926], "characters": "\u22DE" },
+ "⋟": { "codepoints": [8927], "characters": "\u22DF" },
+ "⋎": { "codepoints": [8910], "characters": "\u22CE" },
+ "⋏": { "codepoints": [8911], "characters": "\u22CF" },
+ "¤": { "codepoints": [164], "characters": "\u00A4" },
+ "¤": { "codepoints": [164], "characters": "\u00A4" },
+ "↶": { "codepoints": [8630], "characters": "\u21B6" },
+ "↷": { "codepoints": [8631], "characters": "\u21B7" },
+ "⋎": { "codepoints": [8910], "characters": "\u22CE" },
+ "⋏": { "codepoints": [8911], "characters": "\u22CF" },
+ "∲": { "codepoints": [8754], "characters": "\u2232" },
+ "∱": { "codepoints": [8753], "characters": "\u2231" },
+ "⌭": { "codepoints": [9005], "characters": "\u232D" },
+ "†": { "codepoints": [8224], "characters": "\u2020" },
+ "‡": { "codepoints": [8225], "characters": "\u2021" },
+ "ℸ": { "codepoints": [8504], "characters": "\u2138" },
+ "↓": { "codepoints": [8595], "characters": "\u2193" },
+ "↡": { "codepoints": [8609], "characters": "\u21A1" },
+ "⇓": { "codepoints": [8659], "characters": "\u21D3" },
+ "‐": { "codepoints": [8208], "characters": "\u2010" },
+ "⫤": { "codepoints": [10980], "characters": "\u2AE4" },
+ "⊣": { "codepoints": [8867], "characters": "\u22A3" },
+ "⤏": { "codepoints": [10511], "characters": "\u290F" },
+ "˝": { "codepoints": [733], "characters": "\u02DD" },
+ "Ď": { "codepoints": [270], "characters": "\u010E" },
+ "ď": { "codepoints": [271], "characters": "\u010F" },
+ "Д": { "codepoints": [1044], "characters": "\u0414" },
+ "д": { "codepoints": [1076], "characters": "\u0434" },
+ "‡": { "codepoints": [8225], "characters": "\u2021" },
+ "⇊": { "codepoints": [8650], "characters": "\u21CA" },
+ "ⅅ": { "codepoints": [8517], "characters": "\u2145" },
+ "ⅆ": { "codepoints": [8518], "characters": "\u2146" },
+ "⤑": { "codepoints": [10513], "characters": "\u2911" },
+ "⩷": { "codepoints": [10871], "characters": "\u2A77" },
+ "°": { "codepoints": [176], "characters": "\u00B0" },
+ "°": { "codepoints": [176], "characters": "\u00B0" },
+ "∇": { "codepoints": [8711], "characters": "\u2207" },
+ "Δ": { "codepoints": [916], "characters": "\u0394" },
+ "δ": { "codepoints": [948], "characters": "\u03B4" },
+ "⦱": { "codepoints": [10673], "characters": "\u29B1" },
+ "⥿": { "codepoints": [10623], "characters": "\u297F" },
+ "𝔇": { "codepoints": [120071], "characters": "\uD835\uDD07" },
+ "𝔡": { "codepoints": [120097], "characters": "\uD835\uDD21" },
+ "⥥": { "codepoints": [10597], "characters": "\u2965" },
+ "⇃": { "codepoints": [8643], "characters": "\u21C3" },
+ "⇂": { "codepoints": [8642], "characters": "\u21C2" },
+ "´": { "codepoints": [180], "characters": "\u00B4" },
+ "˙": { "codepoints": [729], "characters": "\u02D9" },
+ "˝": { "codepoints": [733], "characters": "\u02DD" },
+ "`": { "codepoints": [96], "characters": "\u0060" },
+ "˜": { "codepoints": [732], "characters": "\u02DC" },
+ "⋄": { "codepoints": [8900], "characters": "\u22C4" },
+ "⋄": { "codepoints": [8900], "characters": "\u22C4" },
+ "⋄": { "codepoints": [8900], "characters": "\u22C4" },
+ "♦": { "codepoints": [9830], "characters": "\u2666" },
+ "♦": { "codepoints": [9830], "characters": "\u2666" },
+ "¨": { "codepoints": [168], "characters": "\u00A8" },
+ "ⅆ": { "codepoints": [8518], "characters": "\u2146" },
+ "ϝ": { "codepoints": [989], "characters": "\u03DD" },
+ "⋲": { "codepoints": [8946], "characters": "\u22F2" },
+ "÷": { "codepoints": [247], "characters": "\u00F7" },
+ "÷": { "codepoints": [247], "characters": "\u00F7" },
+ "÷": { "codepoints": [247], "characters": "\u00F7" },
+ "⋇": { "codepoints": [8903], "characters": "\u22C7" },
+ "⋇": { "codepoints": [8903], "characters": "\u22C7" },
+ "Ђ": { "codepoints": [1026], "characters": "\u0402" },
+ "ђ": { "codepoints": [1106], "characters": "\u0452" },
+ "⌞": { "codepoints": [8990], "characters": "\u231E" },
+ "⌍": { "codepoints": [8973], "characters": "\u230D" },
+ "$": { "codepoints": [36], "characters": "\u0024" },
+ "𝔻": { "codepoints": [120123], "characters": "\uD835\uDD3B" },
+ "𝕕": { "codepoints": [120149], "characters": "\uD835\uDD55" },
+ "¨": { "codepoints": [168], "characters": "\u00A8" },
+ "˙": { "codepoints": [729], "characters": "\u02D9" },
+ "⃜": { "codepoints": [8412], "characters": "\u20DC" },
+ "≐": { "codepoints": [8784], "characters": "\u2250" },
+ "≑": { "codepoints": [8785], "characters": "\u2251" },
+ "≐": { "codepoints": [8784], "characters": "\u2250" },
+ "∸": { "codepoints": [8760], "characters": "\u2238" },
+ "∔": { "codepoints": [8724], "characters": "\u2214" },
+ "⊡": { "codepoints": [8865], "characters": "\u22A1" },
+ "⌆": { "codepoints": [8966], "characters": "\u2306" },
+ "∯": { "codepoints": [8751], "characters": "\u222F" },
+ "¨": { "codepoints": [168], "characters": "\u00A8" },
+ "⇓": { "codepoints": [8659], "characters": "\u21D3" },
+ "⇐": { "codepoints": [8656], "characters": "\u21D0" },
+ "⇔": { "codepoints": [8660], "characters": "\u21D4" },
+ "⫤": { "codepoints": [10980], "characters": "\u2AE4" },
+ "⟸": { "codepoints": [10232], "characters": "\u27F8" },
+ "⟺": { "codepoints": [10234], "characters": "\u27FA" },
+ "⟹": { "codepoints": [10233], "characters": "\u27F9" },
+ "⇒": { "codepoints": [8658], "characters": "\u21D2" },
+ "⊨": { "codepoints": [8872], "characters": "\u22A8" },
+ "⇑": { "codepoints": [8657], "characters": "\u21D1" },
+ "⇕": { "codepoints": [8661], "characters": "\u21D5" },
+ "∥": { "codepoints": [8741], "characters": "\u2225" },
+ "⤓": { "codepoints": [10515], "characters": "\u2913" },
+ "↓": { "codepoints": [8595], "characters": "\u2193" },
+ "↓": { "codepoints": [8595], "characters": "\u2193" },
+ "⇓": { "codepoints": [8659], "characters": "\u21D3" },
+ "⇵": { "codepoints": [8693], "characters": "\u21F5" },
+ "̑": { "codepoints": [785], "characters": "\u0311" },
+ "⇊": { "codepoints": [8650], "characters": "\u21CA" },
+ "⇃": { "codepoints": [8643], "characters": "\u21C3" },
+ "⇂": { "codepoints": [8642], "characters": "\u21C2" },
+ "⥐": { "codepoints": [10576], "characters": "\u2950" },
+ "⥞": { "codepoints": [10590], "characters": "\u295E" },
+ "⥖": { "codepoints": [10582], "characters": "\u2956" },
+ "↽": { "codepoints": [8637], "characters": "\u21BD" },
+ "⥟": { "codepoints": [10591], "characters": "\u295F" },
+ "⥗": { "codepoints": [10583], "characters": "\u2957" },
+ "⇁": { "codepoints": [8641], "characters": "\u21C1" },
+ "↧": { "codepoints": [8615], "characters": "\u21A7" },
+ "⊤": { "codepoints": [8868], "characters": "\u22A4" },
+ "⤐": { "codepoints": [10512], "characters": "\u2910" },
+ "⌟": { "codepoints": [8991], "characters": "\u231F" },
+ "⌌": { "codepoints": [8972], "characters": "\u230C" },
+ "𝒟": { "codepoints": [119967], "characters": "\uD835\uDC9F" },
+ "𝒹": { "codepoints": [119993], "characters": "\uD835\uDCB9" },
+ "Ѕ": { "codepoints": [1029], "characters": "\u0405" },
+ "ѕ": { "codepoints": [1109], "characters": "\u0455" },
+ "⧶": { "codepoints": [10742], "characters": "\u29F6" },
+ "Đ": { "codepoints": [272], "characters": "\u0110" },
+ "đ": { "codepoints": [273], "characters": "\u0111" },
+ "⋱": { "codepoints": [8945], "characters": "\u22F1" },
+ "▿": { "codepoints": [9663], "characters": "\u25BF" },
+ "▾": { "codepoints": [9662], "characters": "\u25BE" },
+ "⇵": { "codepoints": [8693], "characters": "\u21F5" },
+ "⥯": { "codepoints": [10607], "characters": "\u296F" },
+ "⦦": { "codepoints": [10662], "characters": "\u29A6" },
+ "Џ": { "codepoints": [1039], "characters": "\u040F" },
+ "џ": { "codepoints": [1119], "characters": "\u045F" },
+ "⟿": { "codepoints": [10239], "characters": "\u27FF" },
+ "É": { "codepoints": [201], "characters": "\u00C9" },
+ "É": { "codepoints": [201], "characters": "\u00C9" },
+ "é": { "codepoints": [233], "characters": "\u00E9" },
+ "é": { "codepoints": [233], "characters": "\u00E9" },
+ "⩮": { "codepoints": [10862], "characters": "\u2A6E" },
+ "Ě": { "codepoints": [282], "characters": "\u011A" },
+ "ě": { "codepoints": [283], "characters": "\u011B" },
+ "Ê": { "codepoints": [202], "characters": "\u00CA" },
+ "Ê": { "codepoints": [202], "characters": "\u00CA" },
+ "ê": { "codepoints": [234], "characters": "\u00EA" },
+ "ê": { "codepoints": [234], "characters": "\u00EA" },
+ "≖": { "codepoints": [8790], "characters": "\u2256" },
+ "≕": { "codepoints": [8789], "characters": "\u2255" },
+ "Э": { "codepoints": [1069], "characters": "\u042D" },
+ "э": { "codepoints": [1101], "characters": "\u044D" },
+ "⩷": { "codepoints": [10871], "characters": "\u2A77" },
+ "Ė": { "codepoints": [278], "characters": "\u0116" },
+ "ė": { "codepoints": [279], "characters": "\u0117" },
+ "≑": { "codepoints": [8785], "characters": "\u2251" },
+ "ⅇ": { "codepoints": [8519], "characters": "\u2147" },
+ "≒": { "codepoints": [8786], "characters": "\u2252" },
+ "𝔈": { "codepoints": [120072], "characters": "\uD835\uDD08" },
+ "𝔢": { "codepoints": [120098], "characters": "\uD835\uDD22" },
+ "⪚": { "codepoints": [10906], "characters": "\u2A9A" },
+ "È": { "codepoints": [200], "characters": "\u00C8" },
+ "È": { "codepoints": [200], "characters": "\u00C8" },
+ "è": { "codepoints": [232], "characters": "\u00E8" },
+ "è": { "codepoints": [232], "characters": "\u00E8" },
+ "⪖": { "codepoints": [10902], "characters": "\u2A96" },
+ "⪘": { "codepoints": [10904], "characters": "\u2A98" },
+ "⪙": { "codepoints": [10905], "characters": "\u2A99" },
+ "∈": { "codepoints": [8712], "characters": "\u2208" },
+ "⏧": { "codepoints": [9191], "characters": "\u23E7" },
+ "ℓ": { "codepoints": [8467], "characters": "\u2113" },
+ "⪕": { "codepoints": [10901], "characters": "\u2A95" },
+ "⪗": { "codepoints": [10903], "characters": "\u2A97" },
+ "Ē": { "codepoints": [274], "characters": "\u0112" },
+ "ē": { "codepoints": [275], "characters": "\u0113" },
+ "∅": { "codepoints": [8709], "characters": "\u2205" },
+ "∅": { "codepoints": [8709], "characters": "\u2205" },
+ "◻": { "codepoints": [9723], "characters": "\u25FB" },
+ "∅": { "codepoints": [8709], "characters": "\u2205" },
+ "▫": { "codepoints": [9643], "characters": "\u25AB" },
+ " ": { "codepoints": [8196], "characters": "\u2004" },
+ " ": { "codepoints": [8197], "characters": "\u2005" },
+ " ": { "codepoints": [8195], "characters": "\u2003" },
+ "Ŋ": { "codepoints": [330], "characters": "\u014A" },
+ "ŋ": { "codepoints": [331], "characters": "\u014B" },
+ " ": { "codepoints": [8194], "characters": "\u2002" },
+ "Ę": { "codepoints": [280], "characters": "\u0118" },
+ "ę": { "codepoints": [281], "characters": "\u0119" },
+ "𝔼": { "codepoints": [120124], "characters": "\uD835\uDD3C" },
+ "𝕖": { "codepoints": [120150], "characters": "\uD835\uDD56" },
+ "⋕": { "codepoints": [8917], "characters": "\u22D5" },
+ "⧣": { "codepoints": [10723], "characters": "\u29E3" },
+ "⩱": { "codepoints": [10865], "characters": "\u2A71" },
+ "ε": { "codepoints": [949], "characters": "\u03B5" },
+ "Ε": { "codepoints": [917], "characters": "\u0395" },
+ "ε": { "codepoints": [949], "characters": "\u03B5" },
+ "ϵ": { "codepoints": [1013], "characters": "\u03F5" },
+ "≖": { "codepoints": [8790], "characters": "\u2256" },
+ "≕": { "codepoints": [8789], "characters": "\u2255" },
+ "≂": { "codepoints": [8770], "characters": "\u2242" },
+ "⪖": { "codepoints": [10902], "characters": "\u2A96" },
+ "⪕": { "codepoints": [10901], "characters": "\u2A95" },
+ "⩵": { "codepoints": [10869], "characters": "\u2A75" },
+ "=": { "codepoints": [61], "characters": "\u003D" },
+ "≂": { "codepoints": [8770], "characters": "\u2242" },
+ "≟": { "codepoints": [8799], "characters": "\u225F" },
+ "⇌": { "codepoints": [8652], "characters": "\u21CC" },
+ "≡": { "codepoints": [8801], "characters": "\u2261" },
+ "⩸": { "codepoints": [10872], "characters": "\u2A78" },
+ "⧥": { "codepoints": [10725], "characters": "\u29E5" },
+ "⥱": { "codepoints": [10609], "characters": "\u2971" },
+ "≓": { "codepoints": [8787], "characters": "\u2253" },
+ "ℯ": { "codepoints": [8495], "characters": "\u212F" },
+ "ℰ": { "codepoints": [8496], "characters": "\u2130" },
+ "≐": { "codepoints": [8784], "characters": "\u2250" },
+ "⩳": { "codepoints": [10867], "characters": "\u2A73" },
+ "≂": { "codepoints": [8770], "characters": "\u2242" },
+ "Η": { "codepoints": [919], "characters": "\u0397" },
+ "η": { "codepoints": [951], "characters": "\u03B7" },
+ "Ð": { "codepoints": [208], "characters": "\u00D0" },
+ "Ð": { "codepoints": [208], "characters": "\u00D0" },
+ "ð": { "codepoints": [240], "characters": "\u00F0" },
+ "ð": { "codepoints": [240], "characters": "\u00F0" },
+ "Ë": { "codepoints": [203], "characters": "\u00CB" },
+ "Ë": { "codepoints": [203], "characters": "\u00CB" },
+ "ë": { "codepoints": [235], "characters": "\u00EB" },
+ "ë": { "codepoints": [235], "characters": "\u00EB" },
+ "€": { "codepoints": [8364], "characters": "\u20AC" },
+ "!": { "codepoints": [33], "characters": "\u0021" },
+ "∃": { "codepoints": [8707], "characters": "\u2203" },
+ "∃": { "codepoints": [8707], "characters": "\u2203" },
+ "ℰ": { "codepoints": [8496], "characters": "\u2130" },
+ "ⅇ": { "codepoints": [8519], "characters": "\u2147" },
+ "ⅇ": { "codepoints": [8519], "characters": "\u2147" },
+ "≒": { "codepoints": [8786], "characters": "\u2252" },
+ "Ф": { "codepoints": [1060], "characters": "\u0424" },
+ "ф": { "codepoints": [1092], "characters": "\u0444" },
+ "♀": { "codepoints": [9792], "characters": "\u2640" },
+ "ffi": { "codepoints": [64259], "characters": "\uFB03" },
+ "ff": { "codepoints": [64256], "characters": "\uFB00" },
+ "ffl": { "codepoints": [64260], "characters": "\uFB04" },
+ "𝔉": { "codepoints": [120073], "characters": "\uD835\uDD09" },
+ "𝔣": { "codepoints": [120099], "characters": "\uD835\uDD23" },
+ "fi": { "codepoints": [64257], "characters": "\uFB01" },
+ "◼": { "codepoints": [9724], "characters": "\u25FC" },
+ "▪": { "codepoints": [9642], "characters": "\u25AA" },
+ "fj": { "codepoints": [102, 106], "characters": "\u0066\u006A" },
+ "♭": { "codepoints": [9837], "characters": "\u266D" },
+ "fl": { "codepoints": [64258], "characters": "\uFB02" },
+ "▱": { "codepoints": [9649], "characters": "\u25B1" },
+ "ƒ": { "codepoints": [402], "characters": "\u0192" },
+ "𝔽": { "codepoints": [120125], "characters": "\uD835\uDD3D" },
+ "𝕗": { "codepoints": [120151], "characters": "\uD835\uDD57" },
+ "∀": { "codepoints": [8704], "characters": "\u2200" },
+ "∀": { "codepoints": [8704], "characters": "\u2200" },
+ "⋔": { "codepoints": [8916], "characters": "\u22D4" },
+ "⫙": { "codepoints": [10969], "characters": "\u2AD9" },
+ "ℱ": { "codepoints": [8497], "characters": "\u2131" },
+ "⨍": { "codepoints": [10765], "characters": "\u2A0D" },
+ "½": { "codepoints": [189], "characters": "\u00BD" },
+ "½": { "codepoints": [189], "characters": "\u00BD" },
+ "⅓": { "codepoints": [8531], "characters": "\u2153" },
+ "¼": { "codepoints": [188], "characters": "\u00BC" },
+ "¼": { "codepoints": [188], "characters": "\u00BC" },
+ "⅕": { "codepoints": [8533], "characters": "\u2155" },
+ "⅙": { "codepoints": [8537], "characters": "\u2159" },
+ "⅛": { "codepoints": [8539], "characters": "\u215B" },
+ "⅔": { "codepoints": [8532], "characters": "\u2154" },
+ "⅖": { "codepoints": [8534], "characters": "\u2156" },
+ "¾": { "codepoints": [190], "characters": "\u00BE" },
+ "¾": { "codepoints": [190], "characters": "\u00BE" },
+ "⅗": { "codepoints": [8535], "characters": "\u2157" },
+ "⅜": { "codepoints": [8540], "characters": "\u215C" },
+ "⅘": { "codepoints": [8536], "characters": "\u2158" },
+ "⅚": { "codepoints": [8538], "characters": "\u215A" },
+ "⅝": { "codepoints": [8541], "characters": "\u215D" },
+ "⅞": { "codepoints": [8542], "characters": "\u215E" },
+ "⁄": { "codepoints": [8260], "characters": "\u2044" },
+ "⌢": { "codepoints": [8994], "characters": "\u2322" },
+ "𝒻": { "codepoints": [119995], "characters": "\uD835\uDCBB" },
+ "ℱ": { "codepoints": [8497], "characters": "\u2131" },
+ "ǵ": { "codepoints": [501], "characters": "\u01F5" },
+ "Γ": { "codepoints": [915], "characters": "\u0393" },
+ "γ": { "codepoints": [947], "characters": "\u03B3" },
+ "Ϝ": { "codepoints": [988], "characters": "\u03DC" },
+ "ϝ": { "codepoints": [989], "characters": "\u03DD" },
+ "⪆": { "codepoints": [10886], "characters": "\u2A86" },
+ "Ğ": { "codepoints": [286], "characters": "\u011E" },
+ "ğ": { "codepoints": [287], "characters": "\u011F" },
+ "Ģ": { "codepoints": [290], "characters": "\u0122" },
+ "Ĝ": { "codepoints": [284], "characters": "\u011C" },
+ "ĝ": { "codepoints": [285], "characters": "\u011D" },
+ "Г": { "codepoints": [1043], "characters": "\u0413" },
+ "г": { "codepoints": [1075], "characters": "\u0433" },
+ "Ġ": { "codepoints": [288], "characters": "\u0120" },
+ "ġ": { "codepoints": [289], "characters": "\u0121" },
+ "≥": { "codepoints": [8805], "characters": "\u2265" },
+ "≧": { "codepoints": [8807], "characters": "\u2267" },
+ "⪌": { "codepoints": [10892], "characters": "\u2A8C" },
+ "⋛": { "codepoints": [8923], "characters": "\u22DB" },
+ "≥": { "codepoints": [8805], "characters": "\u2265" },
+ "≧": { "codepoints": [8807], "characters": "\u2267" },
+ "⩾": { "codepoints": [10878], "characters": "\u2A7E" },
+ "⪩": { "codepoints": [10921], "characters": "\u2AA9" },
+ "⩾": { "codepoints": [10878], "characters": "\u2A7E" },
+ "⪀": { "codepoints": [10880], "characters": "\u2A80" },
+ "⪂": { "codepoints": [10882], "characters": "\u2A82" },
+ "⪄": { "codepoints": [10884], "characters": "\u2A84" },
+ "⋛︀": { "codepoints": [8923, 65024], "characters": "\u22DB\uFE00" },
+ "⪔": { "codepoints": [10900], "characters": "\u2A94" },
+ "𝔊": { "codepoints": [120074], "characters": "\uD835\uDD0A" },
+ "𝔤": { "codepoints": [120100], "characters": "\uD835\uDD24" },
+ "≫": { "codepoints": [8811], "characters": "\u226B" },
+ "⋙": { "codepoints": [8921], "characters": "\u22D9" },
+ "⋙": { "codepoints": [8921], "characters": "\u22D9" },
+ "ℷ": { "codepoints": [8503], "characters": "\u2137" },
+ "Ѓ": { "codepoints": [1027], "characters": "\u0403" },
+ "ѓ": { "codepoints": [1107], "characters": "\u0453" },
+ "⪥": { "codepoints": [10917], "characters": "\u2AA5" },
+ "≷": { "codepoints": [8823], "characters": "\u2277" },
+ "⪒": { "codepoints": [10898], "characters": "\u2A92" },
+ "⪤": { "codepoints": [10916], "characters": "\u2AA4" },
+ "⪊": { "codepoints": [10890], "characters": "\u2A8A" },
+ "⪊": { "codepoints": [10890], "characters": "\u2A8A" },
+ "⪈": { "codepoints": [10888], "characters": "\u2A88" },
+ "≩": { "codepoints": [8809], "characters": "\u2269" },
+ "⪈": { "codepoints": [10888], "characters": "\u2A88" },
+ "≩": { "codepoints": [8809], "characters": "\u2269" },
+ "⋧": { "codepoints": [8935], "characters": "\u22E7" },
+ "𝔾": { "codepoints": [120126], "characters": "\uD835\uDD3E" },
+ "𝕘": { "codepoints": [120152], "characters": "\uD835\uDD58" },
+ "`": { "codepoints": [96], "characters": "\u0060" },
+ "≥": { "codepoints": [8805], "characters": "\u2265" },
+ "⋛": { "codepoints": [8923], "characters": "\u22DB" },
+ "≧": { "codepoints": [8807], "characters": "\u2267" },
+ "⪢": { "codepoints": [10914], "characters": "\u2AA2" },
+ "≷": { "codepoints": [8823], "characters": "\u2277" },
+ "⩾": { "codepoints": [10878], "characters": "\u2A7E" },
+ "≳": { "codepoints": [8819], "characters": "\u2273" },
+ "𝒢": { "codepoints": [119970], "characters": "\uD835\uDCA2" },
+ "ℊ": { "codepoints": [8458], "characters": "\u210A" },
+ "≳": { "codepoints": [8819], "characters": "\u2273" },
+ "⪎": { "codepoints": [10894], "characters": "\u2A8E" },
+ "⪐": { "codepoints": [10896], "characters": "\u2A90" },
+ "⪧": { "codepoints": [10919], "characters": "\u2AA7" },
+ "⩺": { "codepoints": [10874], "characters": "\u2A7A" },
+ ">": { "codepoints": [62], "characters": "\u003E" },
+ ">": { "codepoints": [62], "characters": "\u003E" },
+ ">": { "codepoints": [62], "characters": "\u003E" },
+ ">": { "codepoints": [62], "characters": "\u003E" },
+ "≫": { "codepoints": [8811], "characters": "\u226B" },
+ "⋗": { "codepoints": [8919], "characters": "\u22D7" },
+ "⦕": { "codepoints": [10645], "characters": "\u2995" },
+ "⩼": { "codepoints": [10876], "characters": "\u2A7C" },
+ "⪆": { "codepoints": [10886], "characters": "\u2A86" },
+ "⥸": { "codepoints": [10616], "characters": "\u2978" },
+ "⋗": { "codepoints": [8919], "characters": "\u22D7" },
+ "⋛": { "codepoints": [8923], "characters": "\u22DB" },
+ "⪌": { "codepoints": [10892], "characters": "\u2A8C" },
+ "≷": { "codepoints": [8823], "characters": "\u2277" },
+ "≳": { "codepoints": [8819], "characters": "\u2273" },
+ "≩︀": { "codepoints": [8809, 65024], "characters": "\u2269\uFE00" },
+ "≩︀": { "codepoints": [8809, 65024], "characters": "\u2269\uFE00" },
+ "ˇ": { "codepoints": [711], "characters": "\u02C7" },
+ " ": { "codepoints": [8202], "characters": "\u200A" },
+ "½": { "codepoints": [189], "characters": "\u00BD" },
+ "ℋ": { "codepoints": [8459], "characters": "\u210B" },
+ "Ъ": { "codepoints": [1066], "characters": "\u042A" },
+ "ъ": { "codepoints": [1098], "characters": "\u044A" },
+ "⥈": { "codepoints": [10568], "characters": "\u2948" },
+ "↔": { "codepoints": [8596], "characters": "\u2194" },
+ "⇔": { "codepoints": [8660], "characters": "\u21D4" },
+ "↭": { "codepoints": [8621], "characters": "\u21AD" },
+ "^": { "codepoints": [94], "characters": "\u005E" },
+ "ℏ": { "codepoints": [8463], "characters": "\u210F" },
+ "Ĥ": { "codepoints": [292], "characters": "\u0124" },
+ "ĥ": { "codepoints": [293], "characters": "\u0125" },
+ "♥": { "codepoints": [9829], "characters": "\u2665" },
+ "♥": { "codepoints": [9829], "characters": "\u2665" },
+ "…": { "codepoints": [8230], "characters": "\u2026" },
+ "⊹": { "codepoints": [8889], "characters": "\u22B9" },
+ "𝔥": { "codepoints": [120101], "characters": "\uD835\uDD25" },
+ "ℌ": { "codepoints": [8460], "characters": "\u210C" },
+ "ℋ": { "codepoints": [8459], "characters": "\u210B" },
+ "⤥": { "codepoints": [10533], "characters": "\u2925" },
+ "⤦": { "codepoints": [10534], "characters": "\u2926" },
+ "⇿": { "codepoints": [8703], "characters": "\u21FF" },
+ "∻": { "codepoints": [8763], "characters": "\u223B" },
+ "↩": { "codepoints": [8617], "characters": "\u21A9" },
+ "↪": { "codepoints": [8618], "characters": "\u21AA" },
+ "𝕙": { "codepoints": [120153], "characters": "\uD835\uDD59" },
+ "ℍ": { "codepoints": [8461], "characters": "\u210D" },
+ "―": { "codepoints": [8213], "characters": "\u2015" },
+ "─": { "codepoints": [9472], "characters": "\u2500" },
+ "𝒽": { "codepoints": [119997], "characters": "\uD835\uDCBD" },
+ "ℋ": { "codepoints": [8459], "characters": "\u210B" },
+ "ℏ": { "codepoints": [8463], "characters": "\u210F" },
+ "Ħ": { "codepoints": [294], "characters": "\u0126" },
+ "ħ": { "codepoints": [295], "characters": "\u0127" },
+ "≎": { "codepoints": [8782], "characters": "\u224E" },
+ "≏": { "codepoints": [8783], "characters": "\u224F" },
+ "⁃": { "codepoints": [8259], "characters": "\u2043" },
+ "‐": { "codepoints": [8208], "characters": "\u2010" },
+ "Í": { "codepoints": [205], "characters": "\u00CD" },
+ "Í": { "codepoints": [205], "characters": "\u00CD" },
+ "í": { "codepoints": [237], "characters": "\u00ED" },
+ "í": { "codepoints": [237], "characters": "\u00ED" },
+ "⁣": { "codepoints": [8291], "characters": "\u2063" },
+ "Î": { "codepoints": [206], "characters": "\u00CE" },
+ "Î": { "codepoints": [206], "characters": "\u00CE" },
+ "î": { "codepoints": [238], "characters": "\u00EE" },
+ "î": { "codepoints": [238], "characters": "\u00EE" },
+ "И": { "codepoints": [1048], "characters": "\u0418" },
+ "и": { "codepoints": [1080], "characters": "\u0438" },
+ "İ": { "codepoints": [304], "characters": "\u0130" },
+ "Е": { "codepoints": [1045], "characters": "\u0415" },
+ "е": { "codepoints": [1077], "characters": "\u0435" },
+ "¡": { "codepoints": [161], "characters": "\u00A1" },
+ "¡": { "codepoints": [161], "characters": "\u00A1" },
+ "⇔": { "codepoints": [8660], "characters": "\u21D4" },
+ "𝔦": { "codepoints": [120102], "characters": "\uD835\uDD26" },
+ "ℑ": { "codepoints": [8465], "characters": "\u2111" },
+ "Ì": { "codepoints": [204], "characters": "\u00CC" },
+ "Ì": { "codepoints": [204], "characters": "\u00CC" },
+ "ì": { "codepoints": [236], "characters": "\u00EC" },
+ "ì": { "codepoints": [236], "characters": "\u00EC" },
+ "ⅈ": { "codepoints": [8520], "characters": "\u2148" },
+ "⨌": { "codepoints": [10764], "characters": "\u2A0C" },
+ "∭": { "codepoints": [8749], "characters": "\u222D" },
+ "⧜": { "codepoints": [10716], "characters": "\u29DC" },
+ "℩": { "codepoints": [8489], "characters": "\u2129" },
+ "IJ": { "codepoints": [306], "characters": "\u0132" },
+ "ij": { "codepoints": [307], "characters": "\u0133" },
+ "Ī": { "codepoints": [298], "characters": "\u012A" },
+ "ī": { "codepoints": [299], "characters": "\u012B" },
+ "ℑ": { "codepoints": [8465], "characters": "\u2111" },
+ "ⅈ": { "codepoints": [8520], "characters": "\u2148" },
+ "ℐ": { "codepoints": [8464], "characters": "\u2110" },
+ "ℑ": { "codepoints": [8465], "characters": "\u2111" },
+ "ı": { "codepoints": [305], "characters": "\u0131" },
+ "ℑ": { "codepoints": [8465], "characters": "\u2111" },
+ "⊷": { "codepoints": [8887], "characters": "\u22B7" },
+ "Ƶ": { "codepoints": [437], "characters": "\u01B5" },
+ "⇒": { "codepoints": [8658], "characters": "\u21D2" },
+ "℅": { "codepoints": [8453], "characters": "\u2105" },
+ "∈": { "codepoints": [8712], "characters": "\u2208" },
+ "∞": { "codepoints": [8734], "characters": "\u221E" },
+ "⧝": { "codepoints": [10717], "characters": "\u29DD" },
+ "ı": { "codepoints": [305], "characters": "\u0131" },
+ "⊺": { "codepoints": [8890], "characters": "\u22BA" },
+ "∫": { "codepoints": [8747], "characters": "\u222B" },
+ "∬": { "codepoints": [8748], "characters": "\u222C" },
+ "ℤ": { "codepoints": [8484], "characters": "\u2124" },
+ "∫": { "codepoints": [8747], "characters": "\u222B" },
+ "⊺": { "codepoints": [8890], "characters": "\u22BA" },
+ "⋂": { "codepoints": [8898], "characters": "\u22C2" },
+ "⨗": { "codepoints": [10775], "characters": "\u2A17" },
+ "⨼": { "codepoints": [10812], "characters": "\u2A3C" },
+ "⁣": { "codepoints": [8291], "characters": "\u2063" },
+ "⁢": { "codepoints": [8290], "characters": "\u2062" },
+ "Ё": { "codepoints": [1025], "characters": "\u0401" },
+ "ё": { "codepoints": [1105], "characters": "\u0451" },
+ "Į": { "codepoints": [302], "characters": "\u012E" },
+ "į": { "codepoints": [303], "characters": "\u012F" },
+ "𝕀": { "codepoints": [120128], "characters": "\uD835\uDD40" },
+ "𝕚": { "codepoints": [120154], "characters": "\uD835\uDD5A" },
+ "Ι": { "codepoints": [921], "characters": "\u0399" },
+ "ι": { "codepoints": [953], "characters": "\u03B9" },
+ "⨼": { "codepoints": [10812], "characters": "\u2A3C" },
+ "¿": { "codepoints": [191], "characters": "\u00BF" },
+ "¿": { "codepoints": [191], "characters": "\u00BF" },
+ "𝒾": { "codepoints": [119998], "characters": "\uD835\uDCBE" },
+ "ℐ": { "codepoints": [8464], "characters": "\u2110" },
+ "∈": { "codepoints": [8712], "characters": "\u2208" },
+ "⋵": { "codepoints": [8949], "characters": "\u22F5" },
+ "⋹": { "codepoints": [8953], "characters": "\u22F9" },
+ "⋴": { "codepoints": [8948], "characters": "\u22F4" },
+ "⋳": { "codepoints": [8947], "characters": "\u22F3" },
+ "∈": { "codepoints": [8712], "characters": "\u2208" },
+ "⁢": { "codepoints": [8290], "characters": "\u2062" },
+ "Ĩ": { "codepoints": [296], "characters": "\u0128" },
+ "ĩ": { "codepoints": [297], "characters": "\u0129" },
+ "І": { "codepoints": [1030], "characters": "\u0406" },
+ "і": { "codepoints": [1110], "characters": "\u0456" },
+ "Ï": { "codepoints": [207], "characters": "\u00CF" },
+ "Ï": { "codepoints": [207], "characters": "\u00CF" },
+ "ï": { "codepoints": [239], "characters": "\u00EF" },
+ "ï": { "codepoints": [239], "characters": "\u00EF" },
+ "Ĵ": { "codepoints": [308], "characters": "\u0134" },
+ "ĵ": { "codepoints": [309], "characters": "\u0135" },
+ "Й": { "codepoints": [1049], "characters": "\u0419" },
+ "й": { "codepoints": [1081], "characters": "\u0439" },
+ "𝔍": { "codepoints": [120077], "characters": "\uD835\uDD0D" },
+ "𝔧": { "codepoints": [120103], "characters": "\uD835\uDD27" },
+ "ȷ": { "codepoints": [567], "characters": "\u0237" },
+ "𝕁": { "codepoints": [120129], "characters": "\uD835\uDD41" },
+ "𝕛": { "codepoints": [120155], "characters": "\uD835\uDD5B" },
+ "𝒥": { "codepoints": [119973], "characters": "\uD835\uDCA5" },
+ "𝒿": { "codepoints": [119999], "characters": "\uD835\uDCBF" },
+ "Ј": { "codepoints": [1032], "characters": "\u0408" },
+ "ј": { "codepoints": [1112], "characters": "\u0458" },
+ "Є": { "codepoints": [1028], "characters": "\u0404" },
+ "є": { "codepoints": [1108], "characters": "\u0454" },
+ "Κ": { "codepoints": [922], "characters": "\u039A" },
+ "κ": { "codepoints": [954], "characters": "\u03BA" },
+ "ϰ": { "codepoints": [1008], "characters": "\u03F0" },
+ "Ķ": { "codepoints": [310], "characters": "\u0136" },
+ "ķ": { "codepoints": [311], "characters": "\u0137" },
+ "К": { "codepoints": [1050], "characters": "\u041A" },
+ "к": { "codepoints": [1082], "characters": "\u043A" },
+ "𝔎": { "codepoints": [120078], "characters": "\uD835\uDD0E" },
+ "𝔨": { "codepoints": [120104], "characters": "\uD835\uDD28" },
+ "ĸ": { "codepoints": [312], "characters": "\u0138" },
+ "Х": { "codepoints": [1061], "characters": "\u0425" },
+ "х": { "codepoints": [1093], "characters": "\u0445" },
+ "Ќ": { "codepoints": [1036], "characters": "\u040C" },
+ "ќ": { "codepoints": [1116], "characters": "\u045C" },
+ "𝕂": { "codepoints": [120130], "characters": "\uD835\uDD42" },
+ "𝕜": { "codepoints": [120156], "characters": "\uD835\uDD5C" },
+ "𝒦": { "codepoints": [119974], "characters": "\uD835\uDCA6" },
+ "𝓀": { "codepoints": [120000], "characters": "\uD835\uDCC0" },
+ "⇚": { "codepoints": [8666], "characters": "\u21DA" },
+ "Ĺ": { "codepoints": [313], "characters": "\u0139" },
+ "ĺ": { "codepoints": [314], "characters": "\u013A" },
+ "⦴": { "codepoints": [10676], "characters": "\u29B4" },
+ "ℒ": { "codepoints": [8466], "characters": "\u2112" },
+ "Λ": { "codepoints": [923], "characters": "\u039B" },
+ "λ": { "codepoints": [955], "characters": "\u03BB" },
+ "⟨": { "codepoints": [10216], "characters": "\u27E8" },
+ "⟪": { "codepoints": [10218], "characters": "\u27EA" },
+ "⦑": { "codepoints": [10641], "characters": "\u2991" },
+ "⟨": { "codepoints": [10216], "characters": "\u27E8" },
+ "⪅": { "codepoints": [10885], "characters": "\u2A85" },
+ "ℒ": { "codepoints": [8466], "characters": "\u2112" },
+ "«": { "codepoints": [171], "characters": "\u00AB" },
+ "«": { "codepoints": [171], "characters": "\u00AB" },
+ "⇤": { "codepoints": [8676], "characters": "\u21E4" },
+ "⤟": { "codepoints": [10527], "characters": "\u291F" },
+ "←": { "codepoints": [8592], "characters": "\u2190" },
+ "↞": { "codepoints": [8606], "characters": "\u219E" },
+ "⇐": { "codepoints": [8656], "characters": "\u21D0" },
+ "⤝": { "codepoints": [10525], "characters": "\u291D" },
+ "↩": { "codepoints": [8617], "characters": "\u21A9" },
+ "↫": { "codepoints": [8619], "characters": "\u21AB" },
+ "⤹": { "codepoints": [10553], "characters": "\u2939" },
+ "⥳": { "codepoints": [10611], "characters": "\u2973" },
+ "↢": { "codepoints": [8610], "characters": "\u21A2" },
+ "⤙": { "codepoints": [10521], "characters": "\u2919" },
+ "⤛": { "codepoints": [10523], "characters": "\u291B" },
+ "⪫": { "codepoints": [10923], "characters": "\u2AAB" },
+ "⪭": { "codepoints": [10925], "characters": "\u2AAD" },
+ "⪭︀": { "codepoints": [10925, 65024], "characters": "\u2AAD\uFE00" },
+ "⤌": { "codepoints": [10508], "characters": "\u290C" },
+ "⤎": { "codepoints": [10510], "characters": "\u290E" },
+ "❲": { "codepoints": [10098], "characters": "\u2772" },
+ "{": { "codepoints": [123], "characters": "\u007B" },
+ "[": { "codepoints": [91], "characters": "\u005B" },
+ "⦋": { "codepoints": [10635], "characters": "\u298B" },
+ "⦏": { "codepoints": [10639], "characters": "\u298F" },
+ "⦍": { "codepoints": [10637], "characters": "\u298D" },
+ "Ľ": { "codepoints": [317], "characters": "\u013D" },
+ "ľ": { "codepoints": [318], "characters": "\u013E" },
+ "Ļ": { "codepoints": [315], "characters": "\u013B" },
+ "ļ": { "codepoints": [316], "characters": "\u013C" },
+ "⌈": { "codepoints": [8968], "characters": "\u2308" },
+ "{": { "codepoints": [123], "characters": "\u007B" },
+ "Л": { "codepoints": [1051], "characters": "\u041B" },
+ "л": { "codepoints": [1083], "characters": "\u043B" },
+ "⤶": { "codepoints": [10550], "characters": "\u2936" },
+ "“": { "codepoints": [8220], "characters": "\u201C" },
+ "„": { "codepoints": [8222], "characters": "\u201E" },
+ "⥧": { "codepoints": [10599], "characters": "\u2967" },
+ "⥋": { "codepoints": [10571], "characters": "\u294B" },
+ "↲": { "codepoints": [8626], "characters": "\u21B2" },
+ "≤": { "codepoints": [8804], "characters": "\u2264" },
+ "≦": { "codepoints": [8806], "characters": "\u2266" },
+ "⟨": { "codepoints": [10216], "characters": "\u27E8" },
+ "⇤": { "codepoints": [8676], "characters": "\u21E4" },
+ "←": { "codepoints": [8592], "characters": "\u2190" },
+ "←": { "codepoints": [8592], "characters": "\u2190" },
+ "⇐": { "codepoints": [8656], "characters": "\u21D0" },
+ "⇆": { "codepoints": [8646], "characters": "\u21C6" },
+ "↢": { "codepoints": [8610], "characters": "\u21A2" },
+ "⌈": { "codepoints": [8968], "characters": "\u2308" },
+ "⟦": { "codepoints": [10214], "characters": "\u27E6" },
+ "⥡": { "codepoints": [10593], "characters": "\u2961" },
+ "⥙": { "codepoints": [10585], "characters": "\u2959" },
+ "⇃": { "codepoints": [8643], "characters": "\u21C3" },
+ "⌊": { "codepoints": [8970], "characters": "\u230A" },
+ "↽": { "codepoints": [8637], "characters": "\u21BD" },
+ "↼": { "codepoints": [8636], "characters": "\u21BC" },
+ "⇇": { "codepoints": [8647], "characters": "\u21C7" },
+ "↔": { "codepoints": [8596], "characters": "\u2194" },
+ "↔": { "codepoints": [8596], "characters": "\u2194" },
+ "⇔": { "codepoints": [8660], "characters": "\u21D4" },
+ "⇆": { "codepoints": [8646], "characters": "\u21C6" },
+ "⇋": { "codepoints": [8651], "characters": "\u21CB" },
+ "↭": { "codepoints": [8621], "characters": "\u21AD" },
+ "⥎": { "codepoints": [10574], "characters": "\u294E" },
+ "↤": { "codepoints": [8612], "characters": "\u21A4" },
+ "⊣": { "codepoints": [8867], "characters": "\u22A3" },
+ "⥚": { "codepoints": [10586], "characters": "\u295A" },
+ "⋋": { "codepoints": [8907], "characters": "\u22CB" },
+ "⧏": { "codepoints": [10703], "characters": "\u29CF" },
+ "⊲": { "codepoints": [8882], "characters": "\u22B2" },
+ "⊴": { "codepoints": [8884], "characters": "\u22B4" },
+ "⥑": { "codepoints": [10577], "characters": "\u2951" },
+ "⥠": { "codepoints": [10592], "characters": "\u2960" },
+ "⥘": { "codepoints": [10584], "characters": "\u2958" },
+ "↿": { "codepoints": [8639], "characters": "\u21BF" },
+ "⥒": { "codepoints": [10578], "characters": "\u2952" },
+ "↼": { "codepoints": [8636], "characters": "\u21BC" },
+ "⪋": { "codepoints": [10891], "characters": "\u2A8B" },
+ "⋚": { "codepoints": [8922], "characters": "\u22DA" },
+ "≤": { "codepoints": [8804], "characters": "\u2264" },
+ "≦": { "codepoints": [8806], "characters": "\u2266" },
+ "⩽": { "codepoints": [10877], "characters": "\u2A7D" },
+ "⪨": { "codepoints": [10920], "characters": "\u2AA8" },
+ "⩽": { "codepoints": [10877], "characters": "\u2A7D" },
+ "⩿": { "codepoints": [10879], "characters": "\u2A7F" },
+ "⪁": { "codepoints": [10881], "characters": "\u2A81" },
+ "⪃": { "codepoints": [10883], "characters": "\u2A83" },
+ "⋚︀": { "codepoints": [8922, 65024], "characters": "\u22DA\uFE00" },
+ "⪓": { "codepoints": [10899], "characters": "\u2A93" },
+ "⪅": { "codepoints": [10885], "characters": "\u2A85" },
+ "⋖": { "codepoints": [8918], "characters": "\u22D6" },
+ "⋚": { "codepoints": [8922], "characters": "\u22DA" },
+ "⪋": { "codepoints": [10891], "characters": "\u2A8B" },
+ "⋚": { "codepoints": [8922], "characters": "\u22DA" },
+ "≦": { "codepoints": [8806], "characters": "\u2266" },
+ "≶": { "codepoints": [8822], "characters": "\u2276" },
+ "≶": { "codepoints": [8822], "characters": "\u2276" },
+ "⪡": { "codepoints": [10913], "characters": "\u2AA1" },
+ "≲": { "codepoints": [8818], "characters": "\u2272" },
+ "⩽": { "codepoints": [10877], "characters": "\u2A7D" },
+ "≲": { "codepoints": [8818], "characters": "\u2272" },
+ "⥼": { "codepoints": [10620], "characters": "\u297C" },
+ "⌊": { "codepoints": [8970], "characters": "\u230A" },
+ "𝔏": { "codepoints": [120079], "characters": "\uD835\uDD0F" },
+ "𝔩": { "codepoints": [120105], "characters": "\uD835\uDD29" },
+ "≶": { "codepoints": [8822], "characters": "\u2276" },
+ "⪑": { "codepoints": [10897], "characters": "\u2A91" },
+ "⥢": { "codepoints": [10594], "characters": "\u2962" },
+ "↽": { "codepoints": [8637], "characters": "\u21BD" },
+ "↼": { "codepoints": [8636], "characters": "\u21BC" },
+ "⥪": { "codepoints": [10602], "characters": "\u296A" },
+ "▄": { "codepoints": [9604], "characters": "\u2584" },
+ "Љ": { "codepoints": [1033], "characters": "\u0409" },
+ "љ": { "codepoints": [1113], "characters": "\u0459" },
+ "⇇": { "codepoints": [8647], "characters": "\u21C7" },
+ "≪": { "codepoints": [8810], "characters": "\u226A" },
+ "⋘": { "codepoints": [8920], "characters": "\u22D8" },
+ "⌞": { "codepoints": [8990], "characters": "\u231E" },
+ "⇚": { "codepoints": [8666], "characters": "\u21DA" },
+ "⥫": { "codepoints": [10603], "characters": "\u296B" },
+ "◺": { "codepoints": [9722], "characters": "\u25FA" },
+ "Ŀ": { "codepoints": [319], "characters": "\u013F" },
+ "ŀ": { "codepoints": [320], "characters": "\u0140" },
+ "⎰": { "codepoints": [9136], "characters": "\u23B0" },
+ "⎰": { "codepoints": [9136], "characters": "\u23B0" },
+ "⪉": { "codepoints": [10889], "characters": "\u2A89" },
+ "⪉": { "codepoints": [10889], "characters": "\u2A89" },
+ "⪇": { "codepoints": [10887], "characters": "\u2A87" },
+ "≨": { "codepoints": [8808], "characters": "\u2268" },
+ "⪇": { "codepoints": [10887], "characters": "\u2A87" },
+ "≨": { "codepoints": [8808], "characters": "\u2268" },
+ "⋦": { "codepoints": [8934], "characters": "\u22E6" },
+ "⟬": { "codepoints": [10220], "characters": "\u27EC" },
+ "⇽": { "codepoints": [8701], "characters": "\u21FD" },
+ "⟦": { "codepoints": [10214], "characters": "\u27E6" },
+ "⟵": { "codepoints": [10229], "characters": "\u27F5" },
+ "⟵": { "codepoints": [10229], "characters": "\u27F5" },
+ "⟸": { "codepoints": [10232], "characters": "\u27F8" },
+ "⟷": { "codepoints": [10231], "characters": "\u27F7" },
+ "⟷": { "codepoints": [10231], "characters": "\u27F7" },
+ "⟺": { "codepoints": [10234], "characters": "\u27FA" },
+ "⟼": { "codepoints": [10236], "characters": "\u27FC" },
+ "⟶": { "codepoints": [10230], "characters": "\u27F6" },
+ "⟶": { "codepoints": [10230], "characters": "\u27F6" },
+ "⟹": { "codepoints": [10233], "characters": "\u27F9" },
+ "↫": { "codepoints": [8619], "characters": "\u21AB" },
+ "↬": { "codepoints": [8620], "characters": "\u21AC" },
+ "⦅": { "codepoints": [10629], "characters": "\u2985" },
+ "𝕃": { "codepoints": [120131], "characters": "\uD835\uDD43" },
+ "𝕝": { "codepoints": [120157], "characters": "\uD835\uDD5D" },
+ "⨭": { "codepoints": [10797], "characters": "\u2A2D" },
+ "⨴": { "codepoints": [10804], "characters": "\u2A34" },
+ "∗": { "codepoints": [8727], "characters": "\u2217" },
+ "_": { "codepoints": [95], "characters": "\u005F" },
+ "↙": { "codepoints": [8601], "characters": "\u2199" },
+ "↘": { "codepoints": [8600], "characters": "\u2198" },
+ "◊": { "codepoints": [9674], "characters": "\u25CA" },
+ "◊": { "codepoints": [9674], "characters": "\u25CA" },
+ "⧫": { "codepoints": [10731], "characters": "\u29EB" },
+ "(": { "codepoints": [40], "characters": "\u0028" },
+ "⦓": { "codepoints": [10643], "characters": "\u2993" },
+ "⇆": { "codepoints": [8646], "characters": "\u21C6" },
+ "⌟": { "codepoints": [8991], "characters": "\u231F" },
+ "⇋": { "codepoints": [8651], "characters": "\u21CB" },
+ "⥭": { "codepoints": [10605], "characters": "\u296D" },
+ "‎": { "codepoints": [8206], "characters": "\u200E" },
+ "⊿": { "codepoints": [8895], "characters": "\u22BF" },
+ "‹": { "codepoints": [8249], "characters": "\u2039" },
+ "𝓁": { "codepoints": [120001], "characters": "\uD835\uDCC1" },
+ "ℒ": { "codepoints": [8466], "characters": "\u2112" },
+ "↰": { "codepoints": [8624], "characters": "\u21B0" },
+ "↰": { "codepoints": [8624], "characters": "\u21B0" },
+ "≲": { "codepoints": [8818], "characters": "\u2272" },
+ "⪍": { "codepoints": [10893], "characters": "\u2A8D" },
+ "⪏": { "codepoints": [10895], "characters": "\u2A8F" },
+ "[": { "codepoints": [91], "characters": "\u005B" },
+ "‘": { "codepoints": [8216], "characters": "\u2018" },
+ "‚": { "codepoints": [8218], "characters": "\u201A" },
+ "Ł": { "codepoints": [321], "characters": "\u0141" },
+ "ł": { "codepoints": [322], "characters": "\u0142" },
+ "⪦": { "codepoints": [10918], "characters": "\u2AA6" },
+ "⩹": { "codepoints": [10873], "characters": "\u2A79" },
+ "<": { "codepoints": [60], "characters": "\u003C" },
+ "<": { "codepoints": [60], "characters": "\u003C" },
+ "<": { "codepoints": [60], "characters": "\u003C" },
+ "<": { "codepoints": [60], "characters": "\u003C" },
+ "≪": { "codepoints": [8810], "characters": "\u226A" },
+ "⋖": { "codepoints": [8918], "characters": "\u22D6" },
+ "⋋": { "codepoints": [8907], "characters": "\u22CB" },
+ "⋉": { "codepoints": [8905], "characters": "\u22C9" },
+ "⥶": { "codepoints": [10614], "characters": "\u2976" },
+ "⩻": { "codepoints": [10875], "characters": "\u2A7B" },
+ "◃": { "codepoints": [9667], "characters": "\u25C3" },
+ "⊴": { "codepoints": [8884], "characters": "\u22B4" },
+ "◂": { "codepoints": [9666], "characters": "\u25C2" },
+ "⦖": { "codepoints": [10646], "characters": "\u2996" },
+ "⥊": { "codepoints": [10570], "characters": "\u294A" },
+ "⥦": { "codepoints": [10598], "characters": "\u2966" },
+ "≨︀": { "codepoints": [8808, 65024], "characters": "\u2268\uFE00" },
+ "≨︀": { "codepoints": [8808, 65024], "characters": "\u2268\uFE00" },
+ "¯": { "codepoints": [175], "characters": "\u00AF" },
+ "¯": { "codepoints": [175], "characters": "\u00AF" },
+ "♂": { "codepoints": [9794], "characters": "\u2642" },
+ "✠": { "codepoints": [10016], "characters": "\u2720" },
+ "✠": { "codepoints": [10016], "characters": "\u2720" },
+ "⤅": { "codepoints": [10501], "characters": "\u2905" },
+ "↦": { "codepoints": [8614], "characters": "\u21A6" },
+ "↦": { "codepoints": [8614], "characters": "\u21A6" },
+ "↧": { "codepoints": [8615], "characters": "\u21A7" },
+ "↤": { "codepoints": [8612], "characters": "\u21A4" },
+ "↥": { "codepoints": [8613], "characters": "\u21A5" },
+ "▮": { "codepoints": [9646], "characters": "\u25AE" },
+ "⨩": { "codepoints": [10793], "characters": "\u2A29" },
+ "М": { "codepoints": [1052], "characters": "\u041C" },
+ "м": { "codepoints": [1084], "characters": "\u043C" },
+ "—": { "codepoints": [8212], "characters": "\u2014" },
+ "∺": { "codepoints": [8762], "characters": "\u223A" },
+ "∡": { "codepoints": [8737], "characters": "\u2221" },
+ " ": { "codepoints": [8287], "characters": "\u205F" },
+ "ℳ": { "codepoints": [8499], "characters": "\u2133" },
+ "𝔐": { "codepoints": [120080], "characters": "\uD835\uDD10" },
+ "𝔪": { "codepoints": [120106], "characters": "\uD835\uDD2A" },
+ "℧": { "codepoints": [8487], "characters": "\u2127" },
+ "µ": { "codepoints": [181], "characters": "\u00B5" },
+ "µ": { "codepoints": [181], "characters": "\u00B5" },
+ "*": { "codepoints": [42], "characters": "\u002A" },
+ "⫰": { "codepoints": [10992], "characters": "\u2AF0" },
+ "∣": { "codepoints": [8739], "characters": "\u2223" },
+ "·": { "codepoints": [183], "characters": "\u00B7" },
+ "·": { "codepoints": [183], "characters": "\u00B7" },
+ "⊟": { "codepoints": [8863], "characters": "\u229F" },
+ "−": { "codepoints": [8722], "characters": "\u2212" },
+ "∸": { "codepoints": [8760], "characters": "\u2238" },
+ "⨪": { "codepoints": [10794], "characters": "\u2A2A" },
+ "∓": { "codepoints": [8723], "characters": "\u2213" },
+ "⫛": { "codepoints": [10971], "characters": "\u2ADB" },
+ "…": { "codepoints": [8230], "characters": "\u2026" },
+ "∓": { "codepoints": [8723], "characters": "\u2213" },
+ "⊧": { "codepoints": [8871], "characters": "\u22A7" },
+ "𝕄": { "codepoints": [120132], "characters": "\uD835\uDD44" },
+ "𝕞": { "codepoints": [120158], "characters": "\uD835\uDD5E" },
+ "∓": { "codepoints": [8723], "characters": "\u2213" },
+ "𝓂": { "codepoints": [120002], "characters": "\uD835\uDCC2" },
+ "ℳ": { "codepoints": [8499], "characters": "\u2133" },
+ "∾": { "codepoints": [8766], "characters": "\u223E" },
+ "Μ": { "codepoints": [924], "characters": "\u039C" },
+ "μ": { "codepoints": [956], "characters": "\u03BC" },
+ "⊸": { "codepoints": [8888], "characters": "\u22B8" },
+ "⊸": { "codepoints": [8888], "characters": "\u22B8" },
+ "∇": { "codepoints": [8711], "characters": "\u2207" },
+ "Ń": { "codepoints": [323], "characters": "\u0143" },
+ "ń": { "codepoints": [324], "characters": "\u0144" },
+ "∠⃒": { "codepoints": [8736, 8402], "characters": "\u2220\u20D2" },
+ "≉": { "codepoints": [8777], "characters": "\u2249" },
+ "⩰̸": { "codepoints": [10864, 824], "characters": "\u2A70\u0338" },
+ "≋̸": { "codepoints": [8779, 824], "characters": "\u224B\u0338" },
+ "ʼn": { "codepoints": [329], "characters": "\u0149" },
+ "≉": { "codepoints": [8777], "characters": "\u2249" },
+ "♮": { "codepoints": [9838], "characters": "\u266E" },
+ "ℕ": { "codepoints": [8469], "characters": "\u2115" },
+ "♮": { "codepoints": [9838], "characters": "\u266E" },
+ " ": { "codepoints": [160], "characters": "\u00A0" },
+ " ": { "codepoints": [160], "characters": "\u00A0" },
+ "≎̸": { "codepoints": [8782, 824], "characters": "\u224E\u0338" },
+ "≏̸": { "codepoints": [8783, 824], "characters": "\u224F\u0338" },
+ "⩃": { "codepoints": [10819], "characters": "\u2A43" },
+ "Ň": { "codepoints": [327], "characters": "\u0147" },
+ "ň": { "codepoints": [328], "characters": "\u0148" },
+ "Ņ": { "codepoints": [325], "characters": "\u0145" },
+ "ņ": { "codepoints": [326], "characters": "\u0146" },
+ "≇": { "codepoints": [8775], "characters": "\u2247" },
+ "⩭̸": { "codepoints": [10861, 824], "characters": "\u2A6D\u0338" },
+ "⩂": { "codepoints": [10818], "characters": "\u2A42" },
+ "Н": { "codepoints": [1053], "characters": "\u041D" },
+ "н": { "codepoints": [1085], "characters": "\u043D" },
+ "–": { "codepoints": [8211], "characters": "\u2013" },
+ "⤤": { "codepoints": [10532], "characters": "\u2924" },
+ "↗": { "codepoints": [8599], "characters": "\u2197" },
+ "⇗": { "codepoints": [8663], "characters": "\u21D7" },
+ "↗": { "codepoints": [8599], "characters": "\u2197" },
+ "≠": { "codepoints": [8800], "characters": "\u2260" },
+ "≐̸": { "codepoints": [8784, 824], "characters": "\u2250\u0338" },
+ "​": { "codepoints": [8203], "characters": "\u200B" },
+ "​": { "codepoints": [8203], "characters": "\u200B" },
+ "​": { "codepoints": [8203], "characters": "\u200B" },
+ "​": { "codepoints": [8203], "characters": "\u200B" },
+ "≢": { "codepoints": [8802], "characters": "\u2262" },
+ "⤨": { "codepoints": [10536], "characters": "\u2928" },
+ "≂̸": { "codepoints": [8770, 824], "characters": "\u2242\u0338" },
+ "≫": { "codepoints": [8811], "characters": "\u226B" },
+ "≪": { "codepoints": [8810], "characters": "\u226A" },
+ "
": { "codepoints": [10], "characters": "\u000A" },
+ "∄": { "codepoints": [8708], "characters": "\u2204" },
+ "∄": { "codepoints": [8708], "characters": "\u2204" },
+ "𝔑": { "codepoints": [120081], "characters": "\uD835\uDD11" },
+ "𝔫": { "codepoints": [120107], "characters": "\uD835\uDD2B" },
+ "≧̸": { "codepoints": [8807, 824], "characters": "\u2267\u0338" },
+ "≱": { "codepoints": [8817], "characters": "\u2271" },
+ "≱": { "codepoints": [8817], "characters": "\u2271" },
+ "≧̸": { "codepoints": [8807, 824], "characters": "\u2267\u0338" },
+ "⩾̸": { "codepoints": [10878, 824], "characters": "\u2A7E\u0338" },
+ "⩾̸": { "codepoints": [10878, 824], "characters": "\u2A7E\u0338" },
+ "⋙̸": { "codepoints": [8921, 824], "characters": "\u22D9\u0338" },
+ "≵": { "codepoints": [8821], "characters": "\u2275" },
+ "≫⃒": { "codepoints": [8811, 8402], "characters": "\u226B\u20D2" },
+ "≯": { "codepoints": [8815], "characters": "\u226F" },
+ "≯": { "codepoints": [8815], "characters": "\u226F" },
+ "≫̸": { "codepoints": [8811, 824], "characters": "\u226B\u0338" },
+ "↮": { "codepoints": [8622], "characters": "\u21AE" },
+ "⇎": { "codepoints": [8654], "characters": "\u21CE" },
+ "⫲": { "codepoints": [10994], "characters": "\u2AF2" },
+ "∋": { "codepoints": [8715], "characters": "\u220B" },
+ "⋼": { "codepoints": [8956], "characters": "\u22FC" },
+ "⋺": { "codepoints": [8954], "characters": "\u22FA" },
+ "∋": { "codepoints": [8715], "characters": "\u220B" },
+ "Њ": { "codepoints": [1034], "characters": "\u040A" },
+ "њ": { "codepoints": [1114], "characters": "\u045A" },
+ "↚": { "codepoints": [8602], "characters": "\u219A" },
+ "⇍": { "codepoints": [8653], "characters": "\u21CD" },
+ "‥": { "codepoints": [8229], "characters": "\u2025" },
+ "≦̸": { "codepoints": [8806, 824], "characters": "\u2266\u0338" },
+ "≰": { "codepoints": [8816], "characters": "\u2270" },
+ "↚": { "codepoints": [8602], "characters": "\u219A" },
+ "⇍": { "codepoints": [8653], "characters": "\u21CD" },
+ "↮": { "codepoints": [8622], "characters": "\u21AE" },
+ "⇎": { "codepoints": [8654], "characters": "\u21CE" },
+ "≰": { "codepoints": [8816], "characters": "\u2270" },
+ "≦̸": { "codepoints": [8806, 824], "characters": "\u2266\u0338" },
+ "⩽̸": { "codepoints": [10877, 824], "characters": "\u2A7D\u0338" },
+ "⩽̸": { "codepoints": [10877, 824], "characters": "\u2A7D\u0338" },
+ "≮": { "codepoints": [8814], "characters": "\u226E" },
+ "⋘̸": { "codepoints": [8920, 824], "characters": "\u22D8\u0338" },
+ "≴": { "codepoints": [8820], "characters": "\u2274" },
+ "≪⃒": { "codepoints": [8810, 8402], "characters": "\u226A\u20D2" },
+ "≮": { "codepoints": [8814], "characters": "\u226E" },
+ "⋪": { "codepoints": [8938], "characters": "\u22EA" },
+ "⋬": { "codepoints": [8940], "characters": "\u22EC" },
+ "≪̸": { "codepoints": [8810, 824], "characters": "\u226A\u0338" },
+ "∤": { "codepoints": [8740], "characters": "\u2224" },
+ "⁠": { "codepoints": [8288], "characters": "\u2060" },
+ " ": { "codepoints": [160], "characters": "\u00A0" },
+ "𝕟": { "codepoints": [120159], "characters": "\uD835\uDD5F" },
+ "ℕ": { "codepoints": [8469], "characters": "\u2115" },
+ "⫬": { "codepoints": [10988], "characters": "\u2AEC" },
+ "¬": { "codepoints": [172], "characters": "\u00AC" },
+ "¬": { "codepoints": [172], "characters": "\u00AC" },
+ "≢": { "codepoints": [8802], "characters": "\u2262" },
+ "≭": { "codepoints": [8813], "characters": "\u226D" },
+ "∦": { "codepoints": [8742], "characters": "\u2226" },
+ "∉": { "codepoints": [8713], "characters": "\u2209" },
+ "≠": { "codepoints": [8800], "characters": "\u2260" },
+ "≂̸": { "codepoints": [8770, 824], "characters": "\u2242\u0338" },
+ "∄": { "codepoints": [8708], "characters": "\u2204" },
+ "≯": { "codepoints": [8815], "characters": "\u226F" },
+ "≱": { "codepoints": [8817], "characters": "\u2271" },
+ "≧̸": { "codepoints": [8807, 824], "characters": "\u2267\u0338" },
+ "≫̸": { "codepoints": [8811, 824], "characters": "\u226B\u0338" },
+ "≹": { "codepoints": [8825], "characters": "\u2279" },
+ "⩾̸": { "codepoints": [10878, 824], "characters": "\u2A7E\u0338" },
+ "≵": { "codepoints": [8821], "characters": "\u2275" },
+ "≎̸": { "codepoints": [8782, 824], "characters": "\u224E\u0338" },
+ "≏̸": { "codepoints": [8783, 824], "characters": "\u224F\u0338" },
+ "∉": { "codepoints": [8713], "characters": "\u2209" },
+ "⋵̸": { "codepoints": [8949, 824], "characters": "\u22F5\u0338" },
+ "⋹̸": { "codepoints": [8953, 824], "characters": "\u22F9\u0338" },
+ "∉": { "codepoints": [8713], "characters": "\u2209" },
+ "⋷": { "codepoints": [8951], "characters": "\u22F7" },
+ "⋶": { "codepoints": [8950], "characters": "\u22F6" },
+ "⧏̸": { "codepoints": [10703, 824], "characters": "\u29CF\u0338" },
+ "⋪": { "codepoints": [8938], "characters": "\u22EA" },
+ "⋬": { "codepoints": [8940], "characters": "\u22EC" },
+ "≮": { "codepoints": [8814], "characters": "\u226E" },
+ "≰": { "codepoints": [8816], "characters": "\u2270" },
+ "≸": { "codepoints": [8824], "characters": "\u2278" },
+ "≪̸": { "codepoints": [8810, 824], "characters": "\u226A\u0338" },
+ "⩽̸": { "codepoints": [10877, 824], "characters": "\u2A7D\u0338" },
+ "≴": { "codepoints": [8820], "characters": "\u2274" },
+ "⪢̸": { "codepoints": [10914, 824], "characters": "\u2AA2\u0338" },
+ "⪡̸": { "codepoints": [10913, 824], "characters": "\u2AA1\u0338" },
+ "∌": { "codepoints": [8716], "characters": "\u220C" },
+ "∌": { "codepoints": [8716], "characters": "\u220C" },
+ "⋾": { "codepoints": [8958], "characters": "\u22FE" },
+ "⋽": { "codepoints": [8957], "characters": "\u22FD" },
+ "⊀": { "codepoints": [8832], "characters": "\u2280" },
+ "⪯̸": { "codepoints": [10927, 824], "characters": "\u2AAF\u0338" },
+ "⋠": { "codepoints": [8928], "characters": "\u22E0" },
+ "∌": { "codepoints": [8716], "characters": "\u220C" },
+ "⧐̸": { "codepoints": [10704, 824], "characters": "\u29D0\u0338" },
+ "⋫": { "codepoints": [8939], "characters": "\u22EB" },
+ "⋭": { "codepoints": [8941], "characters": "\u22ED" },
+ "⊏̸": { "codepoints": [8847, 824], "characters": "\u228F\u0338" },
+ "⋢": { "codepoints": [8930], "characters": "\u22E2" },
+ "⊐̸": { "codepoints": [8848, 824], "characters": "\u2290\u0338" },
+ "⋣": { "codepoints": [8931], "characters": "\u22E3" },
+ "⊂⃒": { "codepoints": [8834, 8402], "characters": "\u2282\u20D2" },
+ "⊈": { "codepoints": [8840], "characters": "\u2288" },
+ "⊁": { "codepoints": [8833], "characters": "\u2281" },
+ "⪰̸": { "codepoints": [10928, 824], "characters": "\u2AB0\u0338" },
+ "⋡": { "codepoints": [8929], "characters": "\u22E1" },
+ "≿̸": { "codepoints": [8831, 824], "characters": "\u227F\u0338" },
+ "⊃⃒": { "codepoints": [8835, 8402], "characters": "\u2283\u20D2" },
+ "⊉": { "codepoints": [8841], "characters": "\u2289" },
+ "≁": { "codepoints": [8769], "characters": "\u2241" },
+ "≄": { "codepoints": [8772], "characters": "\u2244" },
+ "≇": { "codepoints": [8775], "characters": "\u2247" },
+ "≉": { "codepoints": [8777], "characters": "\u2249" },
+ "∤": { "codepoints": [8740], "characters": "\u2224" },
+ "∦": { "codepoints": [8742], "characters": "\u2226" },
+ "∦": { "codepoints": [8742], "characters": "\u2226" },
+ "⫽⃥": { "codepoints": [11005, 8421], "characters": "\u2AFD\u20E5" },
+ "∂̸": { "codepoints": [8706, 824], "characters": "\u2202\u0338" },
+ "⨔": { "codepoints": [10772], "characters": "\u2A14" },
+ "⊀": { "codepoints": [8832], "characters": "\u2280" },
+ "⋠": { "codepoints": [8928], "characters": "\u22E0" },
+ "⊀": { "codepoints": [8832], "characters": "\u2280" },
+ "⪯̸": { "codepoints": [10927, 824], "characters": "\u2AAF\u0338" },
+ "⪯̸": { "codepoints": [10927, 824], "characters": "\u2AAF\u0338" },
+ "⤳̸": { "codepoints": [10547, 824], "characters": "\u2933\u0338" },
+ "↛": { "codepoints": [8603], "characters": "\u219B" },
+ "⇏": { "codepoints": [8655], "characters": "\u21CF" },
+ "↝̸": { "codepoints": [8605, 824], "characters": "\u219D\u0338" },
+ "↛": { "codepoints": [8603], "characters": "\u219B" },
+ "⇏": { "codepoints": [8655], "characters": "\u21CF" },
+ "⋫": { "codepoints": [8939], "characters": "\u22EB" },
+ "⋭": { "codepoints": [8941], "characters": "\u22ED" },
+ "⊁": { "codepoints": [8833], "characters": "\u2281" },
+ "⋡": { "codepoints": [8929], "characters": "\u22E1" },
+ "⪰̸": { "codepoints": [10928, 824], "characters": "\u2AB0\u0338" },
+ "𝒩": { "codepoints": [119977], "characters": "\uD835\uDCA9" },
+ "𝓃": { "codepoints": [120003], "characters": "\uD835\uDCC3" },
+ "∤": { "codepoints": [8740], "characters": "\u2224" },
+ "∦": { "codepoints": [8742], "characters": "\u2226" },
+ "≁": { "codepoints": [8769], "characters": "\u2241" },
+ "≄": { "codepoints": [8772], "characters": "\u2244" },
+ "≄": { "codepoints": [8772], "characters": "\u2244" },
+ "∤": { "codepoints": [8740], "characters": "\u2224" },
+ "∦": { "codepoints": [8742], "characters": "\u2226" },
+ "⋢": { "codepoints": [8930], "characters": "\u22E2" },
+ "⋣": { "codepoints": [8931], "characters": "\u22E3" },
+ "⊄": { "codepoints": [8836], "characters": "\u2284" },
+ "⫅̸": { "codepoints": [10949, 824], "characters": "\u2AC5\u0338" },
+ "⊈": { "codepoints": [8840], "characters": "\u2288" },
+ "⊂⃒": { "codepoints": [8834, 8402], "characters": "\u2282\u20D2" },
+ "⊈": { "codepoints": [8840], "characters": "\u2288" },
+ "⫅̸": { "codepoints": [10949, 824], "characters": "\u2AC5\u0338" },
+ "⊁": { "codepoints": [8833], "characters": "\u2281" },
+ "⪰̸": { "codepoints": [10928, 824], "characters": "\u2AB0\u0338" },
+ "⊅": { "codepoints": [8837], "characters": "\u2285" },
+ "⫆̸": { "codepoints": [10950, 824], "characters": "\u2AC6\u0338" },
+ "⊉": { "codepoints": [8841], "characters": "\u2289" },
+ "⊃⃒": { "codepoints": [8835, 8402], "characters": "\u2283\u20D2" },
+ "⊉": { "codepoints": [8841], "characters": "\u2289" },
+ "⫆̸": { "codepoints": [10950, 824], "characters": "\u2AC6\u0338" },
+ "≹": { "codepoints": [8825], "characters": "\u2279" },
+ "Ñ": { "codepoints": [209], "characters": "\u00D1" },
+ "Ñ": { "codepoints": [209], "characters": "\u00D1" },
+ "ñ": { "codepoints": [241], "characters": "\u00F1" },
+ "ñ": { "codepoints": [241], "characters": "\u00F1" },
+ "≸": { "codepoints": [8824], "characters": "\u2278" },
+ "⋪": { "codepoints": [8938], "characters": "\u22EA" },
+ "⋬": { "codepoints": [8940], "characters": "\u22EC" },
+ "⋫": { "codepoints": [8939], "characters": "\u22EB" },
+ "⋭": { "codepoints": [8941], "characters": "\u22ED" },
+ "Ν": { "codepoints": [925], "characters": "\u039D" },
+ "ν": { "codepoints": [957], "characters": "\u03BD" },
+ "#": { "codepoints": [35], "characters": "\u0023" },
+ "№": { "codepoints": [8470], "characters": "\u2116" },
+ " ": { "codepoints": [8199], "characters": "\u2007" },
+ "≍⃒": { "codepoints": [8781, 8402], "characters": "\u224D\u20D2" },
+ "⊬": { "codepoints": [8876], "characters": "\u22AC" },
+ "⊭": { "codepoints": [8877], "characters": "\u22AD" },
+ "⊮": { "codepoints": [8878], "characters": "\u22AE" },
+ "⊯": { "codepoints": [8879], "characters": "\u22AF" },
+ "≥⃒": { "codepoints": [8805, 8402], "characters": "\u2265\u20D2" },
+ ">⃒": { "codepoints": [62, 8402], "characters": "\u003E\u20D2" },
+ "⤄": { "codepoints": [10500], "characters": "\u2904" },
+ "⧞": { "codepoints": [10718], "characters": "\u29DE" },
+ "⤂": { "codepoints": [10498], "characters": "\u2902" },
+ "≤⃒": { "codepoints": [8804, 8402], "characters": "\u2264\u20D2" },
+ "<⃒": { "codepoints": [60, 8402], "characters": "\u003C\u20D2" },
+ "⊴⃒": { "codepoints": [8884, 8402], "characters": "\u22B4\u20D2" },
+ "⤃": { "codepoints": [10499], "characters": "\u2903" },
+ "⊵⃒": { "codepoints": [8885, 8402], "characters": "\u22B5\u20D2" },
+ "∼⃒": { "codepoints": [8764, 8402], "characters": "\u223C\u20D2" },
+ "⤣": { "codepoints": [10531], "characters": "\u2923" },
+ "↖": { "codepoints": [8598], "characters": "\u2196" },
+ "⇖": { "codepoints": [8662], "characters": "\u21D6" },
+ "↖": { "codepoints": [8598], "characters": "\u2196" },
+ "⤧": { "codepoints": [10535], "characters": "\u2927" },
+ "Ó": { "codepoints": [211], "characters": "\u00D3" },
+ "Ó": { "codepoints": [211], "characters": "\u00D3" },
+ "ó": { "codepoints": [243], "characters": "\u00F3" },
+ "ó": { "codepoints": [243], "characters": "\u00F3" },
+ "⊛": { "codepoints": [8859], "characters": "\u229B" },
+ "Ô": { "codepoints": [212], "characters": "\u00D4" },
+ "Ô": { "codepoints": [212], "characters": "\u00D4" },
+ "ô": { "codepoints": [244], "characters": "\u00F4" },
+ "ô": { "codepoints": [244], "characters": "\u00F4" },
+ "⊚": { "codepoints": [8858], "characters": "\u229A" },
+ "О": { "codepoints": [1054], "characters": "\u041E" },
+ "о": { "codepoints": [1086], "characters": "\u043E" },
+ "⊝": { "codepoints": [8861], "characters": "\u229D" },
+ "Ő": { "codepoints": [336], "characters": "\u0150" },
+ "ő": { "codepoints": [337], "characters": "\u0151" },
+ "⨸": { "codepoints": [10808], "characters": "\u2A38" },
+ "⊙": { "codepoints": [8857], "characters": "\u2299" },
+ "⦼": { "codepoints": [10684], "characters": "\u29BC" },
+ "Œ": { "codepoints": [338], "characters": "\u0152" },
+ "œ": { "codepoints": [339], "characters": "\u0153" },
+ "⦿": { "codepoints": [10687], "characters": "\u29BF" },
+ "𝔒": { "codepoints": [120082], "characters": "\uD835\uDD12" },
+ "𝔬": { "codepoints": [120108], "characters": "\uD835\uDD2C" },
+ "˛": { "codepoints": [731], "characters": "\u02DB" },
+ "Ò": { "codepoints": [210], "characters": "\u00D2" },
+ "Ò": { "codepoints": [210], "characters": "\u00D2" },
+ "ò": { "codepoints": [242], "characters": "\u00F2" },
+ "ò": { "codepoints": [242], "characters": "\u00F2" },
+ "⧁": { "codepoints": [10689], "characters": "\u29C1" },
+ "⦵": { "codepoints": [10677], "characters": "\u29B5" },
+ "Ω": { "codepoints": [937], "characters": "\u03A9" },
+ "∮": { "codepoints": [8750], "characters": "\u222E" },
+ "↺": { "codepoints": [8634], "characters": "\u21BA" },
+ "⦾": { "codepoints": [10686], "characters": "\u29BE" },
+ "⦻": { "codepoints": [10683], "characters": "\u29BB" },
+ "‾": { "codepoints": [8254], "characters": "\u203E" },
+ "⧀": { "codepoints": [10688], "characters": "\u29C0" },
+ "Ō": { "codepoints": [332], "characters": "\u014C" },
+ "ō": { "codepoints": [333], "characters": "\u014D" },
+ "Ω": { "codepoints": [937], "characters": "\u03A9" },
+ "ω": { "codepoints": [969], "characters": "\u03C9" },
+ "Ο": { "codepoints": [927], "characters": "\u039F" },
+ "ο": { "codepoints": [959], "characters": "\u03BF" },
+ "⦶": { "codepoints": [10678], "characters": "\u29B6" },
+ "⊖": { "codepoints": [8854], "characters": "\u2296" },
+ "𝕆": { "codepoints": [120134], "characters": "\uD835\uDD46" },
+ "𝕠": { "codepoints": [120160], "characters": "\uD835\uDD60" },
+ "⦷": { "codepoints": [10679], "characters": "\u29B7" },
+ "“": { "codepoints": [8220], "characters": "\u201C" },
+ "‘": { "codepoints": [8216], "characters": "\u2018" },
+ "⦹": { "codepoints": [10681], "characters": "\u29B9" },
+ "⊕": { "codepoints": [8853], "characters": "\u2295" },
+ "↻": { "codepoints": [8635], "characters": "\u21BB" },
+ "⩔": { "codepoints": [10836], "characters": "\u2A54" },
+ "∨": { "codepoints": [8744], "characters": "\u2228" },
+ "⩝": { "codepoints": [10845], "characters": "\u2A5D" },
+ "ℴ": { "codepoints": [8500], "characters": "\u2134" },
+ "ℴ": { "codepoints": [8500], "characters": "\u2134" },
+ "ª": { "codepoints": [170], "characters": "\u00AA" },
+ "ª": { "codepoints": [170], "characters": "\u00AA" },
+ "º": { "codepoints": [186], "characters": "\u00BA" },
+ "º": { "codepoints": [186], "characters": "\u00BA" },
+ "⊶": { "codepoints": [8886], "characters": "\u22B6" },
+ "⩖": { "codepoints": [10838], "characters": "\u2A56" },
+ "⩗": { "codepoints": [10839], "characters": "\u2A57" },
+ "⩛": { "codepoints": [10843], "characters": "\u2A5B" },
+ "Ⓢ": { "codepoints": [9416], "characters": "\u24C8" },
+ "𝒪": { "codepoints": [119978], "characters": "\uD835\uDCAA" },
+ "ℴ": { "codepoints": [8500], "characters": "\u2134" },
+ "Ø": { "codepoints": [216], "characters": "\u00D8" },
+ "Ø": { "codepoints": [216], "characters": "\u00D8" },
+ "ø": { "codepoints": [248], "characters": "\u00F8" },
+ "ø": { "codepoints": [248], "characters": "\u00F8" },
+ "⊘": { "codepoints": [8856], "characters": "\u2298" },
+ "Õ": { "codepoints": [213], "characters": "\u00D5" },
+ "Õ": { "codepoints": [213], "characters": "\u00D5" },
+ "õ": { "codepoints": [245], "characters": "\u00F5" },
+ "õ": { "codepoints": [245], "characters": "\u00F5" },
+ "⨶": { "codepoints": [10806], "characters": "\u2A36" },
+ "⨷": { "codepoints": [10807], "characters": "\u2A37" },
+ "⊗": { "codepoints": [8855], "characters": "\u2297" },
+ "Ö": { "codepoints": [214], "characters": "\u00D6" },
+ "Ö": { "codepoints": [214], "characters": "\u00D6" },
+ "ö": { "codepoints": [246], "characters": "\u00F6" },
+ "ö": { "codepoints": [246], "characters": "\u00F6" },
+ "⌽": { "codepoints": [9021], "characters": "\u233D" },
+ "‾": { "codepoints": [8254], "characters": "\u203E" },
+ "⏞": { "codepoints": [9182], "characters": "\u23DE" },
+ "⎴": { "codepoints": [9140], "characters": "\u23B4" },
+ "⏜": { "codepoints": [9180], "characters": "\u23DC" },
+ "¶": { "codepoints": [182], "characters": "\u00B6" },
+ "¶": { "codepoints": [182], "characters": "\u00B6" },
+ "∥": { "codepoints": [8741], "characters": "\u2225" },
+ "∥": { "codepoints": [8741], "characters": "\u2225" },
+ "⫳": { "codepoints": [10995], "characters": "\u2AF3" },
+ "⫽": { "codepoints": [11005], "characters": "\u2AFD" },
+ "∂": { "codepoints": [8706], "characters": "\u2202" },
+ "∂": { "codepoints": [8706], "characters": "\u2202" },
+ "П": { "codepoints": [1055], "characters": "\u041F" },
+ "п": { "codepoints": [1087], "characters": "\u043F" },
+ "%": { "codepoints": [37], "characters": "\u0025" },
+ ".": { "codepoints": [46], "characters": "\u002E" },
+ "‰": { "codepoints": [8240], "characters": "\u2030" },
+ "⊥": { "codepoints": [8869], "characters": "\u22A5" },
+ "‱": { "codepoints": [8241], "characters": "\u2031" },
+ "𝔓": { "codepoints": [120083], "characters": "\uD835\uDD13" },
+ "𝔭": { "codepoints": [120109], "characters": "\uD835\uDD2D" },
+ "Φ": { "codepoints": [934], "characters": "\u03A6" },
+ "φ": { "codepoints": [966], "characters": "\u03C6" },
+ "ϕ": { "codepoints": [981], "characters": "\u03D5" },
+ "ℳ": { "codepoints": [8499], "characters": "\u2133" },
+ "☎": { "codepoints": [9742], "characters": "\u260E" },
+ "Π": { "codepoints": [928], "characters": "\u03A0" },
+ "π": { "codepoints": [960], "characters": "\u03C0" },
+ "⋔": { "codepoints": [8916], "characters": "\u22D4" },
+ "ϖ": { "codepoints": [982], "characters": "\u03D6" },
+ "ℏ": { "codepoints": [8463], "characters": "\u210F" },
+ "ℎ": { "codepoints": [8462], "characters": "\u210E" },
+ "ℏ": { "codepoints": [8463], "characters": "\u210F" },
+ "⨣": { "codepoints": [10787], "characters": "\u2A23" },
+ "⊞": { "codepoints": [8862], "characters": "\u229E" },
+ "⨢": { "codepoints": [10786], "characters": "\u2A22" },
+ "+": { "codepoints": [43], "characters": "\u002B" },
+ "∔": { "codepoints": [8724], "characters": "\u2214" },
+ "⨥": { "codepoints": [10789], "characters": "\u2A25" },
+ "⩲": { "codepoints": [10866], "characters": "\u2A72" },
+ "±": { "codepoints": [177], "characters": "\u00B1" },
+ "±": { "codepoints": [177], "characters": "\u00B1" },
+ "±": { "codepoints": [177], "characters": "\u00B1" },
+ "⨦": { "codepoints": [10790], "characters": "\u2A26" },
+ "⨧": { "codepoints": [10791], "characters": "\u2A27" },
+ "±": { "codepoints": [177], "characters": "\u00B1" },
+ "ℌ": { "codepoints": [8460], "characters": "\u210C" },
+ "⨕": { "codepoints": [10773], "characters": "\u2A15" },
+ "𝕡": { "codepoints": [120161], "characters": "\uD835\uDD61" },
+ "ℙ": { "codepoints": [8473], "characters": "\u2119" },
+ "£": { "codepoints": [163], "characters": "\u00A3" },
+ "£": { "codepoints": [163], "characters": "\u00A3" },
+ "⪷": { "codepoints": [10935], "characters": "\u2AB7" },
+ "⪻": { "codepoints": [10939], "characters": "\u2ABB" },
+ "≺": { "codepoints": [8826], "characters": "\u227A" },
+ "≼": { "codepoints": [8828], "characters": "\u227C" },
+ "⪷": { "codepoints": [10935], "characters": "\u2AB7" },
+ "≺": { "codepoints": [8826], "characters": "\u227A" },
+ "≼": { "codepoints": [8828], "characters": "\u227C" },
+ "≺": { "codepoints": [8826], "characters": "\u227A" },
+ "⪯": { "codepoints": [10927], "characters": "\u2AAF" },
+ "≼": { "codepoints": [8828], "characters": "\u227C" },
+ "≾": { "codepoints": [8830], "characters": "\u227E" },
+ "⪯": { "codepoints": [10927], "characters": "\u2AAF" },
+ "⪹": { "codepoints": [10937], "characters": "\u2AB9" },
+ "⪵": { "codepoints": [10933], "characters": "\u2AB5" },
+ "⋨": { "codepoints": [8936], "characters": "\u22E8" },
+ "⪯": { "codepoints": [10927], "characters": "\u2AAF" },
+ "⪳": { "codepoints": [10931], "characters": "\u2AB3" },
+ "≾": { "codepoints": [8830], "characters": "\u227E" },
+ "′": { "codepoints": [8242], "characters": "\u2032" },
+ "″": { "codepoints": [8243], "characters": "\u2033" },
+ "ℙ": { "codepoints": [8473], "characters": "\u2119" },
+ "⪹": { "codepoints": [10937], "characters": "\u2AB9" },
+ "⪵": { "codepoints": [10933], "characters": "\u2AB5" },
+ "⋨": { "codepoints": [8936], "characters": "\u22E8" },
+ "∏": { "codepoints": [8719], "characters": "\u220F" },
+ "∏": { "codepoints": [8719], "characters": "\u220F" },
+ "⌮": { "codepoints": [9006], "characters": "\u232E" },
+ "⌒": { "codepoints": [8978], "characters": "\u2312" },
+ "⌓": { "codepoints": [8979], "characters": "\u2313" },
+ "∝": { "codepoints": [8733], "characters": "\u221D" },
+ "∝": { "codepoints": [8733], "characters": "\u221D" },
+ "∷": { "codepoints": [8759], "characters": "\u2237" },
+ "∝": { "codepoints": [8733], "characters": "\u221D" },
+ "≾": { "codepoints": [8830], "characters": "\u227E" },
+ "⊰": { "codepoints": [8880], "characters": "\u22B0" },
+ "𝒫": { "codepoints": [119979], "characters": "\uD835\uDCAB" },
+ "𝓅": { "codepoints": [120005], "characters": "\uD835\uDCC5" },
+ "Ψ": { "codepoints": [936], "characters": "\u03A8" },
+ "ψ": { "codepoints": [968], "characters": "\u03C8" },
+ " ": { "codepoints": [8200], "characters": "\u2008" },
+ "𝔔": { "codepoints": [120084], "characters": "\uD835\uDD14" },
+ "𝔮": { "codepoints": [120110], "characters": "\uD835\uDD2E" },
+ "⨌": { "codepoints": [10764], "characters": "\u2A0C" },
+ "𝕢": { "codepoints": [120162], "characters": "\uD835\uDD62" },
+ "ℚ": { "codepoints": [8474], "characters": "\u211A" },
+ "⁗": { "codepoints": [8279], "characters": "\u2057" },
+ "𝒬": { "codepoints": [119980], "characters": "\uD835\uDCAC" },
+ "𝓆": { "codepoints": [120006], "characters": "\uD835\uDCC6" },
+ "ℍ": { "codepoints": [8461], "characters": "\u210D" },
+ "⨖": { "codepoints": [10774], "characters": "\u2A16" },
+ "?": { "codepoints": [63], "characters": "\u003F" },
+ "≟": { "codepoints": [8799], "characters": "\u225F" },
+ """: { "codepoints": [34], "characters": "\u0022" },
+ """: { "codepoints": [34], "characters": "\u0022" },
+ """: { "codepoints": [34], "characters": "\u0022" },
+ """: { "codepoints": [34], "characters": "\u0022" },
+ "⇛": { "codepoints": [8667], "characters": "\u21DB" },
+ "∽̱": { "codepoints": [8765, 817], "characters": "\u223D\u0331" },
+ "Ŕ": { "codepoints": [340], "characters": "\u0154" },
+ "ŕ": { "codepoints": [341], "characters": "\u0155" },
+ "√": { "codepoints": [8730], "characters": "\u221A" },
+ "⦳": { "codepoints": [10675], "characters": "\u29B3" },
+ "⟩": { "codepoints": [10217], "characters": "\u27E9" },
+ "⟫": { "codepoints": [10219], "characters": "\u27EB" },
+ "⦒": { "codepoints": [10642], "characters": "\u2992" },
+ "⦥": { "codepoints": [10661], "characters": "\u29A5" },
+ "⟩": { "codepoints": [10217], "characters": "\u27E9" },
+ "»": { "codepoints": [187], "characters": "\u00BB" },
+ "»": { "codepoints": [187], "characters": "\u00BB" },
+ "⥵": { "codepoints": [10613], "characters": "\u2975" },
+ "⇥": { "codepoints": [8677], "characters": "\u21E5" },
+ "⤠": { "codepoints": [10528], "characters": "\u2920" },
+ "⤳": { "codepoints": [10547], "characters": "\u2933" },
+ "→": { "codepoints": [8594], "characters": "\u2192" },
+ "↠": { "codepoints": [8608], "characters": "\u21A0" },
+ "⇒": { "codepoints": [8658], "characters": "\u21D2" },
+ "⤞": { "codepoints": [10526], "characters": "\u291E" },
+ "↪": { "codepoints": [8618], "characters": "\u21AA" },
+ "↬": { "codepoints": [8620], "characters": "\u21AC" },
+ "⥅": { "codepoints": [10565], "characters": "\u2945" },
+ "⥴": { "codepoints": [10612], "characters": "\u2974" },
+ "⤖": { "codepoints": [10518], "characters": "\u2916" },
+ "↣": { "codepoints": [8611], "characters": "\u21A3" },
+ "↝": { "codepoints": [8605], "characters": "\u219D" },
+ "⤚": { "codepoints": [10522], "characters": "\u291A" },
+ "⤜": { "codepoints": [10524], "characters": "\u291C" },
+ "∶": { "codepoints": [8758], "characters": "\u2236" },
+ "ℚ": { "codepoints": [8474], "characters": "\u211A" },
+ "⤍": { "codepoints": [10509], "characters": "\u290D" },
+ "⤏": { "codepoints": [10511], "characters": "\u290F" },
+ "⤐": { "codepoints": [10512], "characters": "\u2910" },
+ "❳": { "codepoints": [10099], "characters": "\u2773" },
+ "}": { "codepoints": [125], "characters": "\u007D" },
+ "]": { "codepoints": [93], "characters": "\u005D" },
+ "⦌": { "codepoints": [10636], "characters": "\u298C" },
+ "⦎": { "codepoints": [10638], "characters": "\u298E" },
+ "⦐": { "codepoints": [10640], "characters": "\u2990" },
+ "Ř": { "codepoints": [344], "characters": "\u0158" },
+ "ř": { "codepoints": [345], "characters": "\u0159" },
+ "Ŗ": { "codepoints": [342], "characters": "\u0156" },
+ "ŗ": { "codepoints": [343], "characters": "\u0157" },
+ "⌉": { "codepoints": [8969], "characters": "\u2309" },
+ "}": { "codepoints": [125], "characters": "\u007D" },
+ "Р": { "codepoints": [1056], "characters": "\u0420" },
+ "р": { "codepoints": [1088], "characters": "\u0440" },
+ "⤷": { "codepoints": [10551], "characters": "\u2937" },
+ "⥩": { "codepoints": [10601], "characters": "\u2969" },
+ "”": { "codepoints": [8221], "characters": "\u201D" },
+ "”": { "codepoints": [8221], "characters": "\u201D" },
+ "↳": { "codepoints": [8627], "characters": "\u21B3" },
+ "ℜ": { "codepoints": [8476], "characters": "\u211C" },
+ "ℛ": { "codepoints": [8475], "characters": "\u211B" },
+ "ℜ": { "codepoints": [8476], "characters": "\u211C" },
+ "ℝ": { "codepoints": [8477], "characters": "\u211D" },
+ "ℜ": { "codepoints": [8476], "characters": "\u211C" },
+ "▭": { "codepoints": [9645], "characters": "\u25AD" },
+ "®": { "codepoints": [174], "characters": "\u00AE" },
+ "®": { "codepoints": [174], "characters": "\u00AE" },
+ "®": { "codepoints": [174], "characters": "\u00AE" },
+ "®": { "codepoints": [174], "characters": "\u00AE" },
+ "∋": { "codepoints": [8715], "characters": "\u220B" },
+ "⇋": { "codepoints": [8651], "characters": "\u21CB" },
+ "⥯": { "codepoints": [10607], "characters": "\u296F" },
+ "⥽": { "codepoints": [10621], "characters": "\u297D" },
+ "⌋": { "codepoints": [8971], "characters": "\u230B" },
+ "𝔯": { "codepoints": [120111], "characters": "\uD835\uDD2F" },
+ "ℜ": { "codepoints": [8476], "characters": "\u211C" },
+ "⥤": { "codepoints": [10596], "characters": "\u2964" },
+ "⇁": { "codepoints": [8641], "characters": "\u21C1" },
+ "⇀": { "codepoints": [8640], "characters": "\u21C0" },
+ "⥬": { "codepoints": [10604], "characters": "\u296C" },
+ "Ρ": { "codepoints": [929], "characters": "\u03A1" },
+ "ρ": { "codepoints": [961], "characters": "\u03C1" },
+ "ϱ": { "codepoints": [1009], "characters": "\u03F1" },
+ "⟩": { "codepoints": [10217], "characters": "\u27E9" },
+ "⇥": { "codepoints": [8677], "characters": "\u21E5" },
+ "→": { "codepoints": [8594], "characters": "\u2192" },
+ "→": { "codepoints": [8594], "characters": "\u2192" },
+ "⇒": { "codepoints": [8658], "characters": "\u21D2" },
+ "⇄": { "codepoints": [8644], "characters": "\u21C4" },
+ "↣": { "codepoints": [8611], "characters": "\u21A3" },
+ "⌉": { "codepoints": [8969], "characters": "\u2309" },
+ "⟧": { "codepoints": [10215], "characters": "\u27E7" },
+ "⥝": { "codepoints": [10589], "characters": "\u295D" },
+ "⥕": { "codepoints": [10581], "characters": "\u2955" },
+ "⇂": { "codepoints": [8642], "characters": "\u21C2" },
+ "⌋": { "codepoints": [8971], "characters": "\u230B" },
+ "⇁": { "codepoints": [8641], "characters": "\u21C1" },
+ "⇀": { "codepoints": [8640], "characters": "\u21C0" },
+ "⇄": { "codepoints": [8644], "characters": "\u21C4" },
+ "⇌": { "codepoints": [8652], "characters": "\u21CC" },
+ "⇉": { "codepoints": [8649], "characters": "\u21C9" },
+ "↝": { "codepoints": [8605], "characters": "\u219D" },
+ "↦": { "codepoints": [8614], "characters": "\u21A6" },
+ "⊢": { "codepoints": [8866], "characters": "\u22A2" },
+ "⥛": { "codepoints": [10587], "characters": "\u295B" },
+ "⋌": { "codepoints": [8908], "characters": "\u22CC" },
+ "⧐": { "codepoints": [10704], "characters": "\u29D0" },
+ "⊳": { "codepoints": [8883], "characters": "\u22B3" },
+ "⊵": { "codepoints": [8885], "characters": "\u22B5" },
+ "⥏": { "codepoints": [10575], "characters": "\u294F" },
+ "⥜": { "codepoints": [10588], "characters": "\u295C" },
+ "⥔": { "codepoints": [10580], "characters": "\u2954" },
+ "↾": { "codepoints": [8638], "characters": "\u21BE" },
+ "⥓": { "codepoints": [10579], "characters": "\u2953" },
+ "⇀": { "codepoints": [8640], "characters": "\u21C0" },
+ "˚": { "codepoints": [730], "characters": "\u02DA" },
+ "≓": { "codepoints": [8787], "characters": "\u2253" },
+ "⇄": { "codepoints": [8644], "characters": "\u21C4" },
+ "⇌": { "codepoints": [8652], "characters": "\u21CC" },
+ "‏": { "codepoints": [8207], "characters": "\u200F" },
+ "⎱": { "codepoints": [9137], "characters": "\u23B1" },
+ "⎱": { "codepoints": [9137], "characters": "\u23B1" },
+ "⫮": { "codepoints": [10990], "characters": "\u2AEE" },
+ "⟭": { "codepoints": [10221], "characters": "\u27ED" },
+ "⇾": { "codepoints": [8702], "characters": "\u21FE" },
+ "⟧": { "codepoints": [10215], "characters": "\u27E7" },
+ "⦆": { "codepoints": [10630], "characters": "\u2986" },
+ "𝕣": { "codepoints": [120163], "characters": "\uD835\uDD63" },
+ "ℝ": { "codepoints": [8477], "characters": "\u211D" },
+ "⨮": { "codepoints": [10798], "characters": "\u2A2E" },
+ "⨵": { "codepoints": [10805], "characters": "\u2A35" },
+ "⥰": { "codepoints": [10608], "characters": "\u2970" },
+ ")": { "codepoints": [41], "characters": "\u0029" },
+ "⦔": { "codepoints": [10644], "characters": "\u2994" },
+ "⨒": { "codepoints": [10770], "characters": "\u2A12" },
+ "⇉": { "codepoints": [8649], "characters": "\u21C9" },
+ "⇛": { "codepoints": [8667], "characters": "\u21DB" },
+ "›": { "codepoints": [8250], "characters": "\u203A" },
+ "𝓇": { "codepoints": [120007], "characters": "\uD835\uDCC7" },
+ "ℛ": { "codepoints": [8475], "characters": "\u211B" },
+ "↱": { "codepoints": [8625], "characters": "\u21B1" },
+ "↱": { "codepoints": [8625], "characters": "\u21B1" },
+ "]": { "codepoints": [93], "characters": "\u005D" },
+ "’": { "codepoints": [8217], "characters": "\u2019" },
+ "’": { "codepoints": [8217], "characters": "\u2019" },
+ "⋌": { "codepoints": [8908], "characters": "\u22CC" },
+ "⋊": { "codepoints": [8906], "characters": "\u22CA" },
+ "▹": { "codepoints": [9657], "characters": "\u25B9" },
+ "⊵": { "codepoints": [8885], "characters": "\u22B5" },
+ "▸": { "codepoints": [9656], "characters": "\u25B8" },
+ "⧎": { "codepoints": [10702], "characters": "\u29CE" },
+ "⧴": { "codepoints": [10740], "characters": "\u29F4" },
+ "⥨": { "codepoints": [10600], "characters": "\u2968" },
+ "℞": { "codepoints": [8478], "characters": "\u211E" },
+ "Ś": { "codepoints": [346], "characters": "\u015A" },
+ "ś": { "codepoints": [347], "characters": "\u015B" },
+ "‚": { "codepoints": [8218], "characters": "\u201A" },
+ "⪸": { "codepoints": [10936], "characters": "\u2AB8" },
+ "Š": { "codepoints": [352], "characters": "\u0160" },
+ "š": { "codepoints": [353], "characters": "\u0161" },
+ "⪼": { "codepoints": [10940], "characters": "\u2ABC" },
+ "≻": { "codepoints": [8827], "characters": "\u227B" },
+ "≽": { "codepoints": [8829], "characters": "\u227D" },
+ "⪰": { "codepoints": [10928], "characters": "\u2AB0" },
+ "⪴": { "codepoints": [10932], "characters": "\u2AB4" },
+ "Ş": { "codepoints": [350], "characters": "\u015E" },
+ "ş": { "codepoints": [351], "characters": "\u015F" },
+ "Ŝ": { "codepoints": [348], "characters": "\u015C" },
+ "ŝ": { "codepoints": [349], "characters": "\u015D" },
+ "⪺": { "codepoints": [10938], "characters": "\u2ABA" },
+ "⪶": { "codepoints": [10934], "characters": "\u2AB6" },
+ "⋩": { "codepoints": [8937], "characters": "\u22E9" },
+ "⨓": { "codepoints": [10771], "characters": "\u2A13" },
+ "≿": { "codepoints": [8831], "characters": "\u227F" },
+ "С": { "codepoints": [1057], "characters": "\u0421" },
+ "с": { "codepoints": [1089], "characters": "\u0441" },
+ "⊡": { "codepoints": [8865], "characters": "\u22A1" },
+ "⋅": { "codepoints": [8901], "characters": "\u22C5" },
+ "⩦": { "codepoints": [10854], "characters": "\u2A66" },
+ "⤥": { "codepoints": [10533], "characters": "\u2925" },
+ "↘": { "codepoints": [8600], "characters": "\u2198" },
+ "⇘": { "codepoints": [8664], "characters": "\u21D8" },
+ "↘": { "codepoints": [8600], "characters": "\u2198" },
+ "§": { "codepoints": [167], "characters": "\u00A7" },
+ "§": { "codepoints": [167], "characters": "\u00A7" },
+ ";": { "codepoints": [59], "characters": "\u003B" },
+ "⤩": { "codepoints": [10537], "characters": "\u2929" },
+ "∖": { "codepoints": [8726], "characters": "\u2216" },
+ "∖": { "codepoints": [8726], "characters": "\u2216" },
+ "✶": { "codepoints": [10038], "characters": "\u2736" },
+ "𝔖": { "codepoints": [120086], "characters": "\uD835\uDD16" },
+ "𝔰": { "codepoints": [120112], "characters": "\uD835\uDD30" },
+ "⌢": { "codepoints": [8994], "characters": "\u2322" },
+ "♯": { "codepoints": [9839], "characters": "\u266F" },
+ "Щ": { "codepoints": [1065], "characters": "\u0429" },
+ "щ": { "codepoints": [1097], "characters": "\u0449" },
+ "Ш": { "codepoints": [1064], "characters": "\u0428" },
+ "ш": { "codepoints": [1096], "characters": "\u0448" },
+ "↓": { "codepoints": [8595], "characters": "\u2193" },
+ "←": { "codepoints": [8592], "characters": "\u2190" },
+ "∣": { "codepoints": [8739], "characters": "\u2223" },
+ "∥": { "codepoints": [8741], "characters": "\u2225" },
+ "→": { "codepoints": [8594], "characters": "\u2192" },
+ "↑": { "codepoints": [8593], "characters": "\u2191" },
+ "­": { "codepoints": [173], "characters": "\u00AD" },
+ "­": { "codepoints": [173], "characters": "\u00AD" },
+ "Σ": { "codepoints": [931], "characters": "\u03A3" },
+ "σ": { "codepoints": [963], "characters": "\u03C3" },
+ "ς": { "codepoints": [962], "characters": "\u03C2" },
+ "ς": { "codepoints": [962], "characters": "\u03C2" },
+ "∼": { "codepoints": [8764], "characters": "\u223C" },
+ "⩪": { "codepoints": [10858], "characters": "\u2A6A" },
+ "≃": { "codepoints": [8771], "characters": "\u2243" },
+ "≃": { "codepoints": [8771], "characters": "\u2243" },
+ "⪞": { "codepoints": [10910], "characters": "\u2A9E" },
+ "⪠": { "codepoints": [10912], "characters": "\u2AA0" },
+ "⪝": { "codepoints": [10909], "characters": "\u2A9D" },
+ "⪟": { "codepoints": [10911], "characters": "\u2A9F" },
+ "≆": { "codepoints": [8774], "characters": "\u2246" },
+ "⨤": { "codepoints": [10788], "characters": "\u2A24" },
+ "⥲": { "codepoints": [10610], "characters": "\u2972" },
+ "←": { "codepoints": [8592], "characters": "\u2190" },
+ "∘": { "codepoints": [8728], "characters": "\u2218" },
+ "∖": { "codepoints": [8726], "characters": "\u2216" },
+ "⨳": { "codepoints": [10803], "characters": "\u2A33" },
+ "⧤": { "codepoints": [10724], "characters": "\u29E4" },
+ "∣": { "codepoints": [8739], "characters": "\u2223" },
+ "⌣": { "codepoints": [8995], "characters": "\u2323" },
+ "⪪": { "codepoints": [10922], "characters": "\u2AAA" },
+ "⪬": { "codepoints": [10924], "characters": "\u2AAC" },
+ "⪬︀": { "codepoints": [10924, 65024], "characters": "\u2AAC\uFE00" },
+ "Ь": { "codepoints": [1068], "characters": "\u042C" },
+ "ь": { "codepoints": [1100], "characters": "\u044C" },
+ "⌿": { "codepoints": [9023], "characters": "\u233F" },
+ "⧄": { "codepoints": [10692], "characters": "\u29C4" },
+ "/": { "codepoints": [47], "characters": "\u002F" },
+ "𝕊": { "codepoints": [120138], "characters": "\uD835\uDD4A" },
+ "𝕤": { "codepoints": [120164], "characters": "\uD835\uDD64" },
+ "♠": { "codepoints": [9824], "characters": "\u2660" },
+ "♠": { "codepoints": [9824], "characters": "\u2660" },
+ "∥": { "codepoints": [8741], "characters": "\u2225" },
+ "⊓": { "codepoints": [8851], "characters": "\u2293" },
+ "⊓︀": { "codepoints": [8851, 65024], "characters": "\u2293\uFE00" },
+ "⊔": { "codepoints": [8852], "characters": "\u2294" },
+ "⊔︀": { "codepoints": [8852, 65024], "characters": "\u2294\uFE00" },
+ "√": { "codepoints": [8730], "characters": "\u221A" },
+ "⊏": { "codepoints": [8847], "characters": "\u228F" },
+ "⊑": { "codepoints": [8849], "characters": "\u2291" },
+ "⊏": { "codepoints": [8847], "characters": "\u228F" },
+ "⊑": { "codepoints": [8849], "characters": "\u2291" },
+ "⊐": { "codepoints": [8848], "characters": "\u2290" },
+ "⊒": { "codepoints": [8850], "characters": "\u2292" },
+ "⊐": { "codepoints": [8848], "characters": "\u2290" },
+ "⊒": { "codepoints": [8850], "characters": "\u2292" },
+ "□": { "codepoints": [9633], "characters": "\u25A1" },
+ "□": { "codepoints": [9633], "characters": "\u25A1" },
+ "⊓": { "codepoints": [8851], "characters": "\u2293" },
+ "⊏": { "codepoints": [8847], "characters": "\u228F" },
+ "⊑": { "codepoints": [8849], "characters": "\u2291" },
+ "⊐": { "codepoints": [8848], "characters": "\u2290" },
+ "⊒": { "codepoints": [8850], "characters": "\u2292" },
+ "⊔": { "codepoints": [8852], "characters": "\u2294" },
+ "▪": { "codepoints": [9642], "characters": "\u25AA" },
+ "□": { "codepoints": [9633], "characters": "\u25A1" },
+ "▪": { "codepoints": [9642], "characters": "\u25AA" },
+ "→": { "codepoints": [8594], "characters": "\u2192" },
+ "𝒮": { "codepoints": [119982], "characters": "\uD835\uDCAE" },
+ "𝓈": { "codepoints": [120008], "characters": "\uD835\uDCC8" },
+ "∖": { "codepoints": [8726], "characters": "\u2216" },
+ "⌣": { "codepoints": [8995], "characters": "\u2323" },
+ "⋆": { "codepoints": [8902], "characters": "\u22C6" },
+ "⋆": { "codepoints": [8902], "characters": "\u22C6" },
+ "☆": { "codepoints": [9734], "characters": "\u2606" },
+ "★": { "codepoints": [9733], "characters": "\u2605" },
+ "ϵ": { "codepoints": [1013], "characters": "\u03F5" },
+ "ϕ": { "codepoints": [981], "characters": "\u03D5" },
+ "¯": { "codepoints": [175], "characters": "\u00AF" },
+ "⊂": { "codepoints": [8834], "characters": "\u2282" },
+ "⋐": { "codepoints": [8912], "characters": "\u22D0" },
+ "⪽": { "codepoints": [10941], "characters": "\u2ABD" },
+ "⫅": { "codepoints": [10949], "characters": "\u2AC5" },
+ "⊆": { "codepoints": [8838], "characters": "\u2286" },
+ "⫃": { "codepoints": [10947], "characters": "\u2AC3" },
+ "⫁": { "codepoints": [10945], "characters": "\u2AC1" },
+ "⫋": { "codepoints": [10955], "characters": "\u2ACB" },
+ "⊊": { "codepoints": [8842], "characters": "\u228A" },
+ "⪿": { "codepoints": [10943], "characters": "\u2ABF" },
+ "⥹": { "codepoints": [10617], "characters": "\u2979" },
+ "⊂": { "codepoints": [8834], "characters": "\u2282" },
+ "⋐": { "codepoints": [8912], "characters": "\u22D0" },
+ "⊆": { "codepoints": [8838], "characters": "\u2286" },
+ "⫅": { "codepoints": [10949], "characters": "\u2AC5" },
+ "⊆": { "codepoints": [8838], "characters": "\u2286" },
+ "⊊": { "codepoints": [8842], "characters": "\u228A" },
+ "⫋": { "codepoints": [10955], "characters": "\u2ACB" },
+ "⫇": { "codepoints": [10951], "characters": "\u2AC7" },
+ "⫕": { "codepoints": [10965], "characters": "\u2AD5" },
+ "⫓": { "codepoints": [10963], "characters": "\u2AD3" },
+ "⪸": { "codepoints": [10936], "characters": "\u2AB8" },
+ "≻": { "codepoints": [8827], "characters": "\u227B" },
+ "≽": { "codepoints": [8829], "characters": "\u227D" },
+ "≻": { "codepoints": [8827], "characters": "\u227B" },
+ "⪰": { "codepoints": [10928], "characters": "\u2AB0" },
+ "≽": { "codepoints": [8829], "characters": "\u227D" },
+ "≿": { "codepoints": [8831], "characters": "\u227F" },
+ "⪰": { "codepoints": [10928], "characters": "\u2AB0" },
+ "⪺": { "codepoints": [10938], "characters": "\u2ABA" },
+ "⪶": { "codepoints": [10934], "characters": "\u2AB6" },
+ "⋩": { "codepoints": [8937], "characters": "\u22E9" },
+ "≿": { "codepoints": [8831], "characters": "\u227F" },
+ "∋": { "codepoints": [8715], "characters": "\u220B" },
+ "∑": { "codepoints": [8721], "characters": "\u2211" },
+ "∑": { "codepoints": [8721], "characters": "\u2211" },
+ "♪": { "codepoints": [9834], "characters": "\u266A" },
+ "¹": { "codepoints": [185], "characters": "\u00B9" },
+ "¹": { "codepoints": [185], "characters": "\u00B9" },
+ "²": { "codepoints": [178], "characters": "\u00B2" },
+ "²": { "codepoints": [178], "characters": "\u00B2" },
+ "³": { "codepoints": [179], "characters": "\u00B3" },
+ "³": { "codepoints": [179], "characters": "\u00B3" },
+ "⊃": { "codepoints": [8835], "characters": "\u2283" },
+ "⋑": { "codepoints": [8913], "characters": "\u22D1" },
+ "⪾": { "codepoints": [10942], "characters": "\u2ABE" },
+ "⫘": { "codepoints": [10968], "characters": "\u2AD8" },
+ "⫆": { "codepoints": [10950], "characters": "\u2AC6" },
+ "⊇": { "codepoints": [8839], "characters": "\u2287" },
+ "⫄": { "codepoints": [10948], "characters": "\u2AC4" },
+ "⊃": { "codepoints": [8835], "characters": "\u2283" },
+ "⊇": { "codepoints": [8839], "characters": "\u2287" },
+ "⟉": { "codepoints": [10185], "characters": "\u27C9" },
+ "⫗": { "codepoints": [10967], "characters": "\u2AD7" },
+ "⥻": { "codepoints": [10619], "characters": "\u297B" },
+ "⫂": { "codepoints": [10946], "characters": "\u2AC2" },
+ "⫌": { "codepoints": [10956], "characters": "\u2ACC" },
+ "⊋": { "codepoints": [8843], "characters": "\u228B" },
+ "⫀": { "codepoints": [10944], "characters": "\u2AC0" },
+ "⊃": { "codepoints": [8835], "characters": "\u2283" },
+ "⋑": { "codepoints": [8913], "characters": "\u22D1" },
+ "⊇": { "codepoints": [8839], "characters": "\u2287" },
+ "⫆": { "codepoints": [10950], "characters": "\u2AC6" },
+ "⊋": { "codepoints": [8843], "characters": "\u228B" },
+ "⫌": { "codepoints": [10956], "characters": "\u2ACC" },
+ "⫈": { "codepoints": [10952], "characters": "\u2AC8" },
+ "⫔": { "codepoints": [10964], "characters": "\u2AD4" },
+ "⫖": { "codepoints": [10966], "characters": "\u2AD6" },
+ "⤦": { "codepoints": [10534], "characters": "\u2926" },
+ "↙": { "codepoints": [8601], "characters": "\u2199" },
+ "⇙": { "codepoints": [8665], "characters": "\u21D9" },
+ "↙": { "codepoints": [8601], "characters": "\u2199" },
+ "⤪": { "codepoints": [10538], "characters": "\u292A" },
+ "ß": { "codepoints": [223], "characters": "\u00DF" },
+ "ß": { "codepoints": [223], "characters": "\u00DF" },
+ "	": { "codepoints": [9], "characters": "\u0009" },
+ "⌖": { "codepoints": [8982], "characters": "\u2316" },
+ "Τ": { "codepoints": [932], "characters": "\u03A4" },
+ "τ": { "codepoints": [964], "characters": "\u03C4" },
+ "⎴": { "codepoints": [9140], "characters": "\u23B4" },
+ "Ť": { "codepoints": [356], "characters": "\u0164" },
+ "ť": { "codepoints": [357], "characters": "\u0165" },
+ "Ţ": { "codepoints": [354], "characters": "\u0162" },
+ "ţ": { "codepoints": [355], "characters": "\u0163" },
+ "Т": { "codepoints": [1058], "characters": "\u0422" },
+ "т": { "codepoints": [1090], "characters": "\u0442" },
+ "⃛": { "codepoints": [8411], "characters": "\u20DB" },
+ "⌕": { "codepoints": [8981], "characters": "\u2315" },
+ "𝔗": { "codepoints": [120087], "characters": "\uD835\uDD17" },
+ "𝔱": { "codepoints": [120113], "characters": "\uD835\uDD31" },
+ "∴": { "codepoints": [8756], "characters": "\u2234" },
+ "∴": { "codepoints": [8756], "characters": "\u2234" },
+ "∴": { "codepoints": [8756], "characters": "\u2234" },
+ "Θ": { "codepoints": [920], "characters": "\u0398" },
+ "θ": { "codepoints": [952], "characters": "\u03B8" },
+ "ϑ": { "codepoints": [977], "characters": "\u03D1" },
+ "ϑ": { "codepoints": [977], "characters": "\u03D1" },
+ "≈": { "codepoints": [8776], "characters": "\u2248" },
+ "∼": { "codepoints": [8764], "characters": "\u223C" },
+ "  ": { "codepoints": [8287, 8202], "characters": "\u205F\u200A" },
+ " ": { "codepoints": [8201], "characters": "\u2009" },
+ " ": { "codepoints": [8201], "characters": "\u2009" },
+ "≈": { "codepoints": [8776], "characters": "\u2248" },
+ "∼": { "codepoints": [8764], "characters": "\u223C" },
+ "Þ": { "codepoints": [222], "characters": "\u00DE" },
+ "Þ": { "codepoints": [222], "characters": "\u00DE" },
+ "þ": { "codepoints": [254], "characters": "\u00FE" },
+ "þ": { "codepoints": [254], "characters": "\u00FE" },
+ "˜": { "codepoints": [732], "characters": "\u02DC" },
+ "∼": { "codepoints": [8764], "characters": "\u223C" },
+ "≃": { "codepoints": [8771], "characters": "\u2243" },
+ "≅": { "codepoints": [8773], "characters": "\u2245" },
+ "≈": { "codepoints": [8776], "characters": "\u2248" },
+ "⨱": { "codepoints": [10801], "characters": "\u2A31" },
+ "⊠": { "codepoints": [8864], "characters": "\u22A0" },
+ "×": { "codepoints": [215], "characters": "\u00D7" },
+ "×": { "codepoints": [215], "characters": "\u00D7" },
+ "⨰": { "codepoints": [10800], "characters": "\u2A30" },
+ "∭": { "codepoints": [8749], "characters": "\u222D" },
+ "⤨": { "codepoints": [10536], "characters": "\u2928" },
+ "⌶": { "codepoints": [9014], "characters": "\u2336" },
+ "⫱": { "codepoints": [10993], "characters": "\u2AF1" },
+ "⊤": { "codepoints": [8868], "characters": "\u22A4" },
+ "𝕋": { "codepoints": [120139], "characters": "\uD835\uDD4B" },
+ "𝕥": { "codepoints": [120165], "characters": "\uD835\uDD65" },
+ "⫚": { "codepoints": [10970], "characters": "\u2ADA" },
+ "⤩": { "codepoints": [10537], "characters": "\u2929" },
+ "‴": { "codepoints": [8244], "characters": "\u2034" },
+ "™": { "codepoints": [8482], "characters": "\u2122" },
+ "™": { "codepoints": [8482], "characters": "\u2122" },
+ "▵": { "codepoints": [9653], "characters": "\u25B5" },
+ "▿": { "codepoints": [9663], "characters": "\u25BF" },
+ "◃": { "codepoints": [9667], "characters": "\u25C3" },
+ "⊴": { "codepoints": [8884], "characters": "\u22B4" },
+ "≜": { "codepoints": [8796], "characters": "\u225C" },
+ "▹": { "codepoints": [9657], "characters": "\u25B9" },
+ "⊵": { "codepoints": [8885], "characters": "\u22B5" },
+ "◬": { "codepoints": [9708], "characters": "\u25EC" },
+ "≜": { "codepoints": [8796], "characters": "\u225C" },
+ "⨺": { "codepoints": [10810], "characters": "\u2A3A" },
+ "⃛": { "codepoints": [8411], "characters": "\u20DB" },
+ "⨹": { "codepoints": [10809], "characters": "\u2A39" },
+ "⧍": { "codepoints": [10701], "characters": "\u29CD" },
+ "⨻": { "codepoints": [10811], "characters": "\u2A3B" },
+ "⏢": { "codepoints": [9186], "characters": "\u23E2" },
+ "𝒯": { "codepoints": [119983], "characters": "\uD835\uDCAF" },
+ "𝓉": { "codepoints": [120009], "characters": "\uD835\uDCC9" },
+ "Ц": { "codepoints": [1062], "characters": "\u0426" },
+ "ц": { "codepoints": [1094], "characters": "\u0446" },
+ "Ћ": { "codepoints": [1035], "characters": "\u040B" },
+ "ћ": { "codepoints": [1115], "characters": "\u045B" },
+ "Ŧ": { "codepoints": [358], "characters": "\u0166" },
+ "ŧ": { "codepoints": [359], "characters": "\u0167" },
+ "≬": { "codepoints": [8812], "characters": "\u226C" },
+ "↞": { "codepoints": [8606], "characters": "\u219E" },
+ "↠": { "codepoints": [8608], "characters": "\u21A0" },
+ "Ú": { "codepoints": [218], "characters": "\u00DA" },
+ "Ú": { "codepoints": [218], "characters": "\u00DA" },
+ "ú": { "codepoints": [250], "characters": "\u00FA" },
+ "ú": { "codepoints": [250], "characters": "\u00FA" },
+ "↑": { "codepoints": [8593], "characters": "\u2191" },
+ "↟": { "codepoints": [8607], "characters": "\u219F" },
+ "⇑": { "codepoints": [8657], "characters": "\u21D1" },
+ "⥉": { "codepoints": [10569], "characters": "\u2949" },
+ "Ў": { "codepoints": [1038], "characters": "\u040E" },
+ "ў": { "codepoints": [1118], "characters": "\u045E" },
+ "Ŭ": { "codepoints": [364], "characters": "\u016C" },
+ "ŭ": { "codepoints": [365], "characters": "\u016D" },
+ "Û": { "codepoints": [219], "characters": "\u00DB" },
+ "Û": { "codepoints": [219], "characters": "\u00DB" },
+ "û": { "codepoints": [251], "characters": "\u00FB" },
+ "û": { "codepoints": [251], "characters": "\u00FB" },
+ "У": { "codepoints": [1059], "characters": "\u0423" },
+ "у": { "codepoints": [1091], "characters": "\u0443" },
+ "⇅": { "codepoints": [8645], "characters": "\u21C5" },
+ "Ű": { "codepoints": [368], "characters": "\u0170" },
+ "ű": { "codepoints": [369], "characters": "\u0171" },
+ "⥮": { "codepoints": [10606], "characters": "\u296E" },
+ "⥾": { "codepoints": [10622], "characters": "\u297E" },
+ "𝔘": { "codepoints": [120088], "characters": "\uD835\uDD18" },
+ "𝔲": { "codepoints": [120114], "characters": "\uD835\uDD32" },
+ "Ù": { "codepoints": [217], "characters": "\u00D9" },
+ "Ù": { "codepoints": [217], "characters": "\u00D9" },
+ "ù": { "codepoints": [249], "characters": "\u00F9" },
+ "ù": { "codepoints": [249], "characters": "\u00F9" },
+ "⥣": { "codepoints": [10595], "characters": "\u2963" },
+ "↿": { "codepoints": [8639], "characters": "\u21BF" },
+ "↾": { "codepoints": [8638], "characters": "\u21BE" },
+ "▀": { "codepoints": [9600], "characters": "\u2580" },
+ "⌜": { "codepoints": [8988], "characters": "\u231C" },
+ "⌜": { "codepoints": [8988], "characters": "\u231C" },
+ "⌏": { "codepoints": [8975], "characters": "\u230F" },
+ "◸": { "codepoints": [9720], "characters": "\u25F8" },
+ "Ū": { "codepoints": [362], "characters": "\u016A" },
+ "ū": { "codepoints": [363], "characters": "\u016B" },
+ "¨": { "codepoints": [168], "characters": "\u00A8" },
+ "¨": { "codepoints": [168], "characters": "\u00A8" },
+ "_": { "codepoints": [95], "characters": "\u005F" },
+ "⏟": { "codepoints": [9183], "characters": "\u23DF" },
+ "⎵": { "codepoints": [9141], "characters": "\u23B5" },
+ "⏝": { "codepoints": [9181], "characters": "\u23DD" },
+ "⋃": { "codepoints": [8899], "characters": "\u22C3" },
+ "⊎": { "codepoints": [8846], "characters": "\u228E" },
+ "Ų": { "codepoints": [370], "characters": "\u0172" },
+ "ų": { "codepoints": [371], "characters": "\u0173" },
+ "𝕌": { "codepoints": [120140], "characters": "\uD835\uDD4C" },
+ "𝕦": { "codepoints": [120166], "characters": "\uD835\uDD66" },
+ "⤒": { "codepoints": [10514], "characters": "\u2912" },
+ "↑": { "codepoints": [8593], "characters": "\u2191" },
+ "↑": { "codepoints": [8593], "characters": "\u2191" },
+ "⇑": { "codepoints": [8657], "characters": "\u21D1" },
+ "⇅": { "codepoints": [8645], "characters": "\u21C5" },
+ "↕": { "codepoints": [8597], "characters": "\u2195" },
+ "↕": { "codepoints": [8597], "characters": "\u2195" },
+ "⇕": { "codepoints": [8661], "characters": "\u21D5" },
+ "⥮": { "codepoints": [10606], "characters": "\u296E" },
+ "↿": { "codepoints": [8639], "characters": "\u21BF" },
+ "↾": { "codepoints": [8638], "characters": "\u21BE" },
+ "⊎": { "codepoints": [8846], "characters": "\u228E" },
+ "↖": { "codepoints": [8598], "characters": "\u2196" },
+ "↗": { "codepoints": [8599], "characters": "\u2197" },
+ "υ": { "codepoints": [965], "characters": "\u03C5" },
+ "ϒ": { "codepoints": [978], "characters": "\u03D2" },
+ "ϒ": { "codepoints": [978], "characters": "\u03D2" },
+ "Υ": { "codepoints": [933], "characters": "\u03A5" },
+ "υ": { "codepoints": [965], "characters": "\u03C5" },
+ "↥": { "codepoints": [8613], "characters": "\u21A5" },
+ "⊥": { "codepoints": [8869], "characters": "\u22A5" },
+ "⇈": { "codepoints": [8648], "characters": "\u21C8" },
+ "⌝": { "codepoints": [8989], "characters": "\u231D" },
+ "⌝": { "codepoints": [8989], "characters": "\u231D" },
+ "⌎": { "codepoints": [8974], "characters": "\u230E" },
+ "Ů": { "codepoints": [366], "characters": "\u016E" },
+ "ů": { "codepoints": [367], "characters": "\u016F" },
+ "◹": { "codepoints": [9721], "characters": "\u25F9" },
+ "𝒰": { "codepoints": [119984], "characters": "\uD835\uDCB0" },
+ "𝓊": { "codepoints": [120010], "characters": "\uD835\uDCCA" },
+ "⋰": { "codepoints": [8944], "characters": "\u22F0" },
+ "Ũ": { "codepoints": [360], "characters": "\u0168" },
+ "ũ": { "codepoints": [361], "characters": "\u0169" },
+ "▵": { "codepoints": [9653], "characters": "\u25B5" },
+ "▴": { "codepoints": [9652], "characters": "\u25B4" },
+ "⇈": { "codepoints": [8648], "characters": "\u21C8" },
+ "Ü": { "codepoints": [220], "characters": "\u00DC" },
+ "Ü": { "codepoints": [220], "characters": "\u00DC" },
+ "ü": { "codepoints": [252], "characters": "\u00FC" },
+ "ü": { "codepoints": [252], "characters": "\u00FC" },
+ "⦧": { "codepoints": [10663], "characters": "\u29A7" },
+ "⦜": { "codepoints": [10652], "characters": "\u299C" },
+ "ϵ": { "codepoints": [1013], "characters": "\u03F5" },
+ "ϰ": { "codepoints": [1008], "characters": "\u03F0" },
+ "∅": { "codepoints": [8709], "characters": "\u2205" },
+ "ϕ": { "codepoints": [981], "characters": "\u03D5" },
+ "ϖ": { "codepoints": [982], "characters": "\u03D6" },
+ "∝": { "codepoints": [8733], "characters": "\u221D" },
+ "↕": { "codepoints": [8597], "characters": "\u2195" },
+ "⇕": { "codepoints": [8661], "characters": "\u21D5" },
+ "ϱ": { "codepoints": [1009], "characters": "\u03F1" },
+ "ς": { "codepoints": [962], "characters": "\u03C2" },
+ "⊊︀": { "codepoints": [8842, 65024], "characters": "\u228A\uFE00" },
+ "⫋︀": { "codepoints": [10955, 65024], "characters": "\u2ACB\uFE00" },
+ "⊋︀": { "codepoints": [8843, 65024], "characters": "\u228B\uFE00" },
+ "⫌︀": { "codepoints": [10956, 65024], "characters": "\u2ACC\uFE00" },
+ "ϑ": { "codepoints": [977], "characters": "\u03D1" },
+ "⊲": { "codepoints": [8882], "characters": "\u22B2" },
+ "⊳": { "codepoints": [8883], "characters": "\u22B3" },
+ "⫨": { "codepoints": [10984], "characters": "\u2AE8" },
+ "⫫": { "codepoints": [10987], "characters": "\u2AEB" },
+ "⫩": { "codepoints": [10985], "characters": "\u2AE9" },
+ "В": { "codepoints": [1042], "characters": "\u0412" },
+ "в": { "codepoints": [1074], "characters": "\u0432" },
+ "⊢": { "codepoints": [8866], "characters": "\u22A2" },
+ "⊨": { "codepoints": [8872], "characters": "\u22A8" },
+ "⊩": { "codepoints": [8873], "characters": "\u22A9" },
+ "⊫": { "codepoints": [8875], "characters": "\u22AB" },
+ "⫦": { "codepoints": [10982], "characters": "\u2AE6" },
+ "⊻": { "codepoints": [8891], "characters": "\u22BB" },
+ "∨": { "codepoints": [8744], "characters": "\u2228" },
+ "⋁": { "codepoints": [8897], "characters": "\u22C1" },
+ "≚": { "codepoints": [8794], "characters": "\u225A" },
+ "⋮": { "codepoints": [8942], "characters": "\u22EE" },
+ "|": { "codepoints": [124], "characters": "\u007C" },
+ "‖": { "codepoints": [8214], "characters": "\u2016" },
+ "|": { "codepoints": [124], "characters": "\u007C" },
+ "‖": { "codepoints": [8214], "characters": "\u2016" },
+ "∣": { "codepoints": [8739], "characters": "\u2223" },
+ "|": { "codepoints": [124], "characters": "\u007C" },
+ "❘": { "codepoints": [10072], "characters": "\u2758" },
+ "≀": { "codepoints": [8768], "characters": "\u2240" },
+ " ": { "codepoints": [8202], "characters": "\u200A" },
+ "𝔙": { "codepoints": [120089], "characters": "\uD835\uDD19" },
+ "𝔳": { "codepoints": [120115], "characters": "\uD835\uDD33" },
+ "⊲": { "codepoints": [8882], "characters": "\u22B2" },
+ "⊂⃒": { "codepoints": [8834, 8402], "characters": "\u2282\u20D2" },
+ "⊃⃒": { "codepoints": [8835, 8402], "characters": "\u2283\u20D2" },
+ "𝕍": { "codepoints": [120141], "characters": "\uD835\uDD4D" },
+ "𝕧": { "codepoints": [120167], "characters": "\uD835\uDD67" },
+ "∝": { "codepoints": [8733], "characters": "\u221D" },
+ "⊳": { "codepoints": [8883], "characters": "\u22B3" },
+ "𝒱": { "codepoints": [119985], "characters": "\uD835\uDCB1" },
+ "𝓋": { "codepoints": [120011], "characters": "\uD835\uDCCB" },
+ "⫋︀": { "codepoints": [10955, 65024], "characters": "\u2ACB\uFE00" },
+ "⊊︀": { "codepoints": [8842, 65024], "characters": "\u228A\uFE00" },
+ "⫌︀": { "codepoints": [10956, 65024], "characters": "\u2ACC\uFE00" },
+ "⊋︀": { "codepoints": [8843, 65024], "characters": "\u228B\uFE00" },
+ "⊪": { "codepoints": [8874], "characters": "\u22AA" },
+ "⦚": { "codepoints": [10650], "characters": "\u299A" },
+ "Ŵ": { "codepoints": [372], "characters": "\u0174" },
+ "ŵ": { "codepoints": [373], "characters": "\u0175" },
+ "⩟": { "codepoints": [10847], "characters": "\u2A5F" },
+ "∧": { "codepoints": [8743], "characters": "\u2227" },
+ "⋀": { "codepoints": [8896], "characters": "\u22C0" },
+ "≙": { "codepoints": [8793], "characters": "\u2259" },
+ "℘": { "codepoints": [8472], "characters": "\u2118" },
+ "𝔚": { "codepoints": [120090], "characters": "\uD835\uDD1A" },
+ "𝔴": { "codepoints": [120116], "characters": "\uD835\uDD34" },
+ "𝕎": { "codepoints": [120142], "characters": "\uD835\uDD4E" },
+ "𝕨": { "codepoints": [120168], "characters": "\uD835\uDD68" },
+ "℘": { "codepoints": [8472], "characters": "\u2118" },
+ "≀": { "codepoints": [8768], "characters": "\u2240" },
+ "≀": { "codepoints": [8768], "characters": "\u2240" },
+ "𝒲": { "codepoints": [119986], "characters": "\uD835\uDCB2" },
+ "𝓌": { "codepoints": [120012], "characters": "\uD835\uDCCC" },
+ "⋂": { "codepoints": [8898], "characters": "\u22C2" },
+ "◯": { "codepoints": [9711], "characters": "\u25EF" },
+ "⋃": { "codepoints": [8899], "characters": "\u22C3" },
+ "▽": { "codepoints": [9661], "characters": "\u25BD" },
+ "𝔛": { "codepoints": [120091], "characters": "\uD835\uDD1B" },
+ "𝔵": { "codepoints": [120117], "characters": "\uD835\uDD35" },
+ "⟷": { "codepoints": [10231], "characters": "\u27F7" },
+ "⟺": { "codepoints": [10234], "characters": "\u27FA" },
+ "Ξ": { "codepoints": [926], "characters": "\u039E" },
+ "ξ": { "codepoints": [958], "characters": "\u03BE" },
+ "⟵": { "codepoints": [10229], "characters": "\u27F5" },
+ "⟸": { "codepoints": [10232], "characters": "\u27F8" },
+ "⟼": { "codepoints": [10236], "characters": "\u27FC" },
+ "⋻": { "codepoints": [8955], "characters": "\u22FB" },
+ "⨀": { "codepoints": [10752], "characters": "\u2A00" },
+ "𝕏": { "codepoints": [120143], "characters": "\uD835\uDD4F" },
+ "𝕩": { "codepoints": [120169], "characters": "\uD835\uDD69" },
+ "⨁": { "codepoints": [10753], "characters": "\u2A01" },
+ "⨂": { "codepoints": [10754], "characters": "\u2A02" },
+ "⟶": { "codepoints": [10230], "characters": "\u27F6" },
+ "⟹": { "codepoints": [10233], "characters": "\u27F9" },
+ "𝒳": { "codepoints": [119987], "characters": "\uD835\uDCB3" },
+ "𝓍": { "codepoints": [120013], "characters": "\uD835\uDCCD" },
+ "⨆": { "codepoints": [10758], "characters": "\u2A06" },
+ "⨄": { "codepoints": [10756], "characters": "\u2A04" },
+ "△": { "codepoints": [9651], "characters": "\u25B3" },
+ "⋁": { "codepoints": [8897], "characters": "\u22C1" },
+ "⋀": { "codepoints": [8896], "characters": "\u22C0" },
+ "Ý": { "codepoints": [221], "characters": "\u00DD" },
+ "Ý": { "codepoints": [221], "characters": "\u00DD" },
+ "ý": { "codepoints": [253], "characters": "\u00FD" },
+ "ý": { "codepoints": [253], "characters": "\u00FD" },
+ "Я": { "codepoints": [1071], "characters": "\u042F" },
+ "я": { "codepoints": [1103], "characters": "\u044F" },
+ "Ŷ": { "codepoints": [374], "characters": "\u0176" },
+ "ŷ": { "codepoints": [375], "characters": "\u0177" },
+ "Ы": { "codepoints": [1067], "characters": "\u042B" },
+ "ы": { "codepoints": [1099], "characters": "\u044B" },
+ "¥": { "codepoints": [165], "characters": "\u00A5" },
+ "¥": { "codepoints": [165], "characters": "\u00A5" },
+ "𝔜": { "codepoints": [120092], "characters": "\uD835\uDD1C" },
+ "𝔶": { "codepoints": [120118], "characters": "\uD835\uDD36" },
+ "Ї": { "codepoints": [1031], "characters": "\u0407" },
+ "ї": { "codepoints": [1111], "characters": "\u0457" },
+ "𝕐": { "codepoints": [120144], "characters": "\uD835\uDD50" },
+ "𝕪": { "codepoints": [120170], "characters": "\uD835\uDD6A" },
+ "𝒴": { "codepoints": [119988], "characters": "\uD835\uDCB4" },
+ "𝓎": { "codepoints": [120014], "characters": "\uD835\uDCCE" },
+ "Ю": { "codepoints": [1070], "characters": "\u042E" },
+ "ю": { "codepoints": [1102], "characters": "\u044E" },
+ "ÿ": { "codepoints": [255], "characters": "\u00FF" },
+ "ÿ": { "codepoints": [255], "characters": "\u00FF" },
+ "Ÿ": { "codepoints": [376], "characters": "\u0178" },
+ "Ź": { "codepoints": [377], "characters": "\u0179" },
+ "ź": { "codepoints": [378], "characters": "\u017A" },
+ "Ž": { "codepoints": [381], "characters": "\u017D" },
+ "ž": { "codepoints": [382], "characters": "\u017E" },
+ "З": { "codepoints": [1047], "characters": "\u0417" },
+ "з": { "codepoints": [1079], "characters": "\u0437" },
+ "Ż": { "codepoints": [379], "characters": "\u017B" },
+ "ż": { "codepoints": [380], "characters": "\u017C" },
+ "ℨ": { "codepoints": [8488], "characters": "\u2128" },
+ "​": { "codepoints": [8203], "characters": "\u200B" },
+ "Ζ": { "codepoints": [918], "characters": "\u0396" },
+ "ζ": { "codepoints": [950], "characters": "\u03B6" },
+ "𝔷": { "codepoints": [120119], "characters": "\uD835\uDD37" },
+ "ℨ": { "codepoints": [8488], "characters": "\u2128" },
+ "Ж": { "codepoints": [1046], "characters": "\u0416" },
+ "ж": { "codepoints": [1078], "characters": "\u0436" },
+ "⇝": { "codepoints": [8669], "characters": "\u21DD" },
+ "𝕫": { "codepoints": [120171], "characters": "\uD835\uDD6B" },
+ "ℤ": { "codepoints": [8484], "characters": "\u2124" },
+ "𝒵": { "codepoints": [119989], "characters": "\uD835\uDCB5" },
+ "𝓏": { "codepoints": [120015], "characters": "\uD835\uDCCF" },
+ "‍": { "codepoints": [8205], "characters": "\u200D" },
+ "‌": { "codepoints": [8204], "characters": "\u200C" }
+}
diff --git a/tag-modifier/src/main/resources/structure.json b/tag-modifier/src/main/resources/structure.json
new file mode 100644
index 0000000..cd880f7
--- /dev/null
+++ b/tag-modifier/src/main/resources/structure.json
@@ -0,0 +1,87 @@
+{
+ "a" :{
+ "type" : ["flow","phrasing", "palpable"],
+ "context" : ["phrasing"],
+ "contentModel" : {
+ "type" : "transparent",
+ "reject" : ["interactive"]
+ },
+ "attributeModifier" : {
+ "href" : {
+ "type" : "interactive"
+ }
+ }
+ },
+ "abbr" :{
+ "type" : ["flow","phrasing", "palpable"],
+ "context" : ["phrasing"],
+ "contentModel" : {
+ "type" : "phrasing"
+ }
+ },
+ "address" :{
+ "type" : ["flow", "palpable"],
+ "context" : ["flow"],
+ "contentModel" : {
+ "type" : "flow",
+ "reject" : ["heading", "sectioning"],
+ "rejectTags" : ["header", "footer", "address"]
+ },
+ "attributeModifier" : {
+ "href" : {
+ "type" : "interactive"
+ }
+ }
+ },
+ "article" :{
+ "type" : ["flow", "sectioning", "palpable"],
+ "context" : ["flow"],
+ "contentModel" : {
+ "type" : "flow",
+ "rejectTags" : ["main"]
+ }
+ },
+ "aside" :{
+ "type" : ["flow", "sectioning", "palpable"],
+ "context" : ["flow"],
+ "contentModel" : {
+ "type" : "flow",
+ "rejectTags" : ["main"]
+ }
+ },
+ "audio" :{
+ "type" : ["flow", "phrasing", "embedded"],
+ "context" : ["embedded"],
+ "contentModel" : {
+ "type" : "transparent",
+ "rejectTags" : ["audio", "video"]
+ },
+ "attributeModifier" : {
+ "controls" : {
+ "type" : ["interactive","palpable"]
+ }
+ }
+ },
+ "b" :{
+ "type" : ["flow", "phrasing", "palpable"],
+ "context" : ["phrasing"],
+ "contentModel" : {
+ "type" : "flow",
+ "reject" : ["heading", "sectioning"],
+ "rejectTags" : ["header", "footer", "address"]
+ },
+ "attributeModifier" : {
+ "href" : {
+ "type" : "interactive"
+ }
+ }
+ },
+ "p" :{
+ "type" : ["flow", "palpable"],
+ "context" : ["flow"],
+ "contentModel" : {
+ "type" : "phrasing"
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/tag-modifier/src/test/java/com/github/htmlparser/HtmlParseTest.java b/tag-modifier/src/test/java/com/github/htmlparser/HtmlParseTest.java
new file mode 100644
index 0000000..91c023e
--- /dev/null
+++ b/tag-modifier/src/test/java/com/github/htmlparser/HtmlParseTest.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.htmlparser;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.text.ParseException;
+import java.util.function.Function;
+import java.util.stream.Stream;
+
+import org.apache.sling.tagmodifier.Element;
+import org.apache.sling.tagmodifier.ElementType;
+import org.apache.sling.tagmodifier.Tag;
+import org.apache.sling.tagmodifier.TagMapping;
+import org.apache.sling.tagmodifier.consumer.HtmlSAXSupport;
+import org.apache.sling.tagmodifier.util.HtmlStreams;
+import org.junit.Before;
+import org.junit.Test;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.DefaultHandler2;
+
+public class HtmlParseTest {
+
+ Stream<Element> stream;
+
+ @Before
+ public void setUp() throws ParseException, Exception {
+ InputStream is = this.getClass().getResourceAsStream("/demo.html");
+ stream = Tag.stream(is, "UTF-8");
+ }
+
+ @Test
+ public void docParseTagTest() throws Exception {
+ long count = stream.filter(elem -> elem.getType() == ElementType.START_TAG).count();
+ assertEquals(902, count);
+ }
+
+ @Test
+ public void docParseAllTest() throws Exception {
+ long count = stream.count();
+ assertEquals(2928, count);
+ }
+
+ @Test
+ public void docParseAllTestToString() throws Exception {
+ stream.map(HtmlStreams.TO_HTML).count();
+ }
+
+ @Test
+ public void docParseSAXTest() {
+ HtmlSAXSupport support = new HtmlSAXSupport(new DefaultHandler2() {
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes)
+ throws SAXException {
+ //System.out.println(localName);
+ }
+
+ }, new DefaultHandler2());
+ stream.forEach(support);
+ }
+
+ @Test
+ public void docParseTagTest3() throws Exception {
+ long count = stream.flatMap(TagMapping.map((element, process) -> {
+ if (element.containsAttribute("href")) {
+ //System.out.println(element.getAttributeValue("href"));
+ process.next(element);
+ }
+ })).count();
+ assertEquals(356, count);
+ }
+
+ private static Function<Element, Stream<Element>> CONVERT_LINKS = TagMapping.map((element, process) -> {
+ if (element.containsAttribute("href")) {
+ String value = element.getAttributeValue("href");
+ if (value != null && value.startsWith("/")) {
+ element.setAttribute("href", "http://www.apache.org" + value);
+ }
+ }
+ if (element.containsAttribute("src")) {
+ String value = element.getAttributeValue("src");
+ if (value != null && value.startsWith("/")) {
+ element.setAttribute("src", "http://www.apache.org" + value);
+ }
+ }
+ process.next(element);
+ });
+
+ @Test
+ public void convertLinkTest() throws Exception {
+ long count = stream.flatMap(CONVERT_LINKS).count();
+ assertEquals(2928, count);
+ }
+
+ @Test
+ public void convertLinkAndPrintTest() throws Exception {
+ //stream.flatMap(CONVERT_LINKS).map(HtmlStreams.TO_HTML).forEach(System.out::print);
+ }
+
+}
diff --git a/tag-modifier/src/test/java/com/github/htmlparser/UnusualHtmlTest.java b/tag-modifier/src/test/java/com/github/htmlparser/UnusualHtmlTest.java
new file mode 100644
index 0000000..0ac95ef
--- /dev/null
+++ b/tag-modifier/src/test/java/com/github/htmlparser/UnusualHtmlTest.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.htmlparser;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.text.ParseException;
+import java.util.stream.Stream;
+
+import org.apache.sling.tagmodifier.Element;
+import org.apache.sling.tagmodifier.ElementType;
+import org.apache.sling.tagmodifier.Tag;
+import org.apache.sling.tagmodifier.TagMapping;
+import org.junit.Before;
+import org.junit.Test;
+
+public class UnusualHtmlTest {
+
+ private Stream<Element> stream;
+
+ @Before
+ public void setUp() throws ParseException, Exception {
+ InputStream is = this.getClass().getResourceAsStream("/fail.html");
+ stream = Tag.stream(is, "UTF-8");
+ }
+
+ @Test
+ public void docParseTagTest() throws Exception {
+ long count = stream.filter(elem -> elem.getType() != ElementType.TEXT ).count();
+ assertEquals(4, count);
+ }
+
+ @Test
+ public void docParseTagTest2() throws Exception {
+ long count = stream.filter(elem -> elem.getType() == ElementType.TEXT ).count();
+ assertEquals(7, count);
+ }
+
+ @Test
+ public void docParseTagTest3() throws Exception {
+ long count = stream.flatMap(TagMapping.map((element,process) ->{
+ if (element.containsAttribute("href")) {
+ process.next(element, element);
+ }
+ })).count();
+ assertEquals(0, count);
+ }
+
+}
diff --git a/tag-modifier/src/test/resources/demo.html b/tag-modifier/src/test/resources/demo.html
new file mode 100644
index 0000000..18a7366
--- /dev/null
+++ b/tag-modifier/src/test/resources/demo.html
@@ -0,0 +1,864 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <meta name="description" content="Home page of The Apache Software Foundation">
+
+ <link rel="apple-touch-icon" sizes="57x57" href="/favicons/apple-touch-icon-57x57.png">
+ <link rel="apple-touch-icon" sizes="60x60" href="/favicons/apple-touch-icon-60x60.png">
+ <link rel="apple-touch-icon" sizes="72x72" href="/favicons/apple-touch-icon-72x72.png">
+ <link rel="apple-touch-icon" sizes="76x76" href="/favicons/apple-touch-icon-76x76.png">
+ <link rel="apple-touch-icon" sizes="114x114" href="/favicons/apple-touch-icon-114x114.png">
+ <link rel="apple-touch-icon" sizes="120x120" href="/favicons/apple-touch-icon-120x120.png">
+ <link rel="apple-touch-icon" sizes="144x144" href="/favicons/apple-touch-icon-144x144.png">
+ <link rel="apple-touch-icon" sizes="152x152" href="/favicons/apple-touch-icon-152x152.png">
+ <link rel="apple-touch-icon" sizes="180x180" href="/favicons/apple-touch-icon-180x180.png">
+ <link rel="icon" type="image/png" href="/favicons/favicon-32x32.png" sizes="32x32">
+ <link rel="icon" type="image/png" href="/favicons/favicon-194x194.png" sizes="194x194">
+ <link rel="icon" type="image/png" href="/favicons/favicon-96x96.png" sizes="96x96">
+ <link rel="icon" type="image/png" href="/favicons/android-chrome-192x192.png" sizes="192x192">
+ <link rel="icon" type="image/png" href="/favicons/favicon-16x16.png" sizes="16x16">
+ <link rel="manifest" href="/favicons/manifest.json">
+ <link rel="shortcut icon" href="/favicons/favicon.ico">
+ <meta name="msapplication-TileColor" content="#603cba">
+ <meta name="msapplication-TileImage" content="/favicons/mstile-144x144.png">
+ <meta name="msapplication-config" content="/favicons/browserconfig.xml">
+ <meta name="theme-color" content="#303284">
+
+ <title>Welcome to The Apache Software Foundation!</title>
+ <link href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,700%7cDroid+Serif:400,700' rel='stylesheet' type='text/css'>
+ <link href="/css/min.bootstrap.css" rel="stylesheet">
+ <link href="/css/styles.css" rel="stylesheet">
+
+
+
+
+</head>
+
+<body>
+<!-- Navigation -->
+<header>
+ <nav class="navbar navbar-default navbar-fixed-top">
+ <div class="container">
+ <div class="navbar-header">
+ <button class="navbar-toggle" type="button" data-toggle="collapse" data-target="#mainnav-collapse">
+ <span class="sr-only">Toggle navigation</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ <a href="#" class="navbar-brand"><span class="glyphicon glyphicon-home"></span></a>
+ </div>
+ <div class="collapse navbar-collapse" id="mainnav-collapse">
+ <div style="line-height:20px; padding-top:5px; float:left"><a href="/">Home</a></div>
+ <ul class="nav navbar-nav navbar-right">
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">About <span class="caret"></span></a>
+ <ul class="dropdown-menu" role="menu">
+ <li><a href="/foundation">Overview</a></li>
+ <li><a href="/foundation/members.html">Members</a></li>
+ <li><a href="/foundation/how-it-works.html">Process</a></li>
+ <li><a href="/foundation/sponsorship.html">Sponsorship</a></li>
+ <li><a href="/foundation/glossary.html">Glossary</a></li>
+ <li><a href="/foundation/preFAQ.html">FAQ</a></li>
+ <li><a href="/foundation/policies/conduct.html">Code of Conduct</a></li>
+ <li><a href="/foundation/contact.html ">Contact</a></li>
+ </ul>
+ </li>
+ <li><a href="/index.html#projects-list">Projects</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">People <span class="caret"></span></a>
+ <ul class="dropdown-menu" role="menu">
+ <li><a href="http://people.apache.org/">Overview</a></li>
+ <li><a href="http://people.apache.org/committer-index.html">Committers</a></li>
+ <li><a href="/foundation/how-it-works.html#meritocracy">Meritocracy</a></li>
+ <li><a href="/foundation/how-it-works.html#roles">Roles</a></li>
+ <li><a href="/foundation/policies/conduct.html">Code of Conduct</a></li>
+ <li><a href="http://planet.apache.org/">Planet Apache</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Get Involved <span class="caret"></span></a>
+ <ul class="dropdown-menu" role="menu">
+ <li><a href="/foundation/getinvolved.html">Overview</a></li>
+ <li><a href="http://community.apache.org/">Community Development</a></li>
+ <li><a href="/foundation/policies/conduct.html">Code of Conduct</a></li>
+ <li><a href="http://helpwanted.apache.org/">Help Wanted</a></li>
+ <li><a href="http://www.apachecon.com/">ApacheCon</a></li>
+ </ul>
+ </li>
+ <li><a href="/dyn/closer.cgi">Download</a></li>
+ <li class="dropdown">
+ <a href="#" class="dropdown-toggle" data-toggle="dropdown">Support Apache <span class="caret"></span></a>
+ <ul class="dropdown-menu" role="menu">
+ <li><a href="/foundation/sponsorship.html">Sponsorship</a></li>
+ <li><a href="/foundation/contributing.html">Donations</a></li>
+ <li><a href="/foundation/buy_stuff.html">Buy Stuff</a></li>
+ <li><a href="/foundation/thanks.html">Thanks</a></li>
+ </ul>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </nav>
+</header>
+<!-- / Navigation -->
+<div class="container">
+ <div class="row">
+ <div class="col-md-6 col-sm-5 col-xs-12">
+ <img src="/img/asf_logo.png" alt="Apache Logo" style="max-width: 100%;">
+ </div>
+ <div class="col-md-3 col-sm-3 col-xs-6">
+ <a href="http://apache.org/foundation/contributing.html" title="Support Apache">
+ <img src="/images/SupportApache-small.png" style="height: 150px; width: 150px; margin-top: 5px; margin-bottom: 5px;">
+ </a>
+ </div>
+ <div class="col-md-3 col-sm-4 col-xs-6">
+ <div class="input-group" style="margin-bottom: 5px;">
+ <script>
+ (function() {
+ var cx = '005703438322411770421:5mgshgrgx2u';
+ var gcse = document.createElement('script');
+ gcse.type = 'text/javascript';
+ gcse.async = true;
+ gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
+ '//cse.google.com/cse.js?cx=' + cx;
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(gcse, s);
+ })();
+</script>
+ <gcse:searchbox-only></gcse:searchbox-only>
+ </div>
+ <a role="button" class="btn btn-block btn-default btn-xs" href="/foundation/governance/">The Apache Way</a>
+ <a role="button" class="btn btn-block btn-default btn-xs" href="https://community.apache.org/contributors/">Contribute</a>
+ <a role="button" class="btn btn-block btn-default btn-xs" href="/foundation/thanks.html">ASF Sponsors</a>
+ </div>
+ </div>
+</div>
+
+<!-- Apache Statements Section -->
+<section class="bg-gray" >
+ <div class="container">
+ <div class="row">
+ <div class="col-md-4">
+ <style type="text/css">
+/* The following code is added by mdx_elementid.py
+ It was originally lifted from http://subversion.apache.org/style/site.css */
+/*
+ * Hide class="elementid-permalink", except when an enclosing heading
+ * has the :hover property.
+ */
+.headerlink, .elementid-permalink {
+ visibility: hidden;
+}
+h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
+<h3>Open.</h3>
+
+<h5 class="no-btm-margin">The Apache Software Foundation</h5>
+
+<p class="small">provides support for the Apache Community of Open Source software projects, which provide software products for the public good.</p>
+ </div>
+ <div class="col-md-4">
+ <style type="text/css">
+/* The following code is added by mdx_elementid.py
+ It was originally lifted from http://subversion.apache.org/style/site.css */
+/*
+ * Hide class="elementid-permalink", except when an enclosing heading
+ * has the :hover property.
+ */
+.headerlink, .elementid-permalink {
+ visibility: hidden;
+}
+h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
+<h3>Innovation.</h3>
+
+<h5 class="no-btm-margin">Apache projects are defined</h5>
+
+<p class="small">by collaborative consensus based processes, an open, pragmatic software license and a desire to create high quality software that leads the way in its field.</p>
+ </div>
+ <div class="col-md-4">
+ <style type="text/css">
+/* The following code is added by mdx_elementid.py
+ It was originally lifted from http://subversion.apache.org/style/site.css */
+/*
+ * Hide class="elementid-permalink", except when an enclosing heading
+ * has the :hover property.
+ */
+.headerlink, .elementid-permalink {
+ visibility: hidden;
+}
+h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
+<h3>Community.</h3>
+
+<h5 class="no-btm-margin">We consider ourselves</h5>
+
+<p class="small">not simply a group of projects sharing a server, but rather a community of developers and users.</p>
+ </div>
+ </div>
+ </div>
+</section>
+<!-- / Apache Statements Section -->
+<!-- ApacheCon etc -->
+<section class="bg-gray" style="background: #F9F9F9; padding-top: 10px; padding-bottom: 0px; border-top: 1px solid #666; border-bottom: 1px solid #666;">
+ <div class="container">
+ <div class="row">
+ <div class="col-md-3">
+ <style type="text/css">
+/* The following code is added by mdx_elementid.py
+ It was originally lifted from http://subversion.apache.org/style/site.css */
+/*
+ * Hide class="elementid-permalink", except when an enclosing heading
+ * has the :hover property.
+ */
+.headerlink, .elementid-permalink {
+ visibility: hidden;
+}
+h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
+<p><a href="https://blogs.apache.org/foundation/entry/the-apache-software-foundation-celebrates">
+<img src="images/ASF-at-19-board.jpg" style="width: 95%; max-width: 260px;"/>
+</a></p>
+ </div>
+ <div class="col-md-6">
+ <style type="text/css">
+/* The following code is added by mdx_elementid.py
+ It was originally lifted from http://subversion.apache.org/style/site.css */
+/*
+ * Hide class="elementid-permalink", except when an enclosing heading
+ * has the :hover property.
+ */
+.headerlink, .elementid-permalink {
+ visibility: hidden;
+}
+h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
+<h4>APACHE IS OPEN</h4>
+
+<p class="small">
+<b><i>"The Apache Software Foundation is a cornerstone of the modern Open Source software ecosystem – supporting some of the most widely used and important software solutions powering today's Internet economy."</i>
+– Mark Driver, Research Vice President, Gartner
+</b>
+<p>Lauded among the most successful influencers in Open Source, The Apache Software Foundation's commitment to collaborative development has long served as a model for producing consistently high quality software that advances the future of open development. <a href="https://s.apache.org/PIRA">https://s.apache.org/PIRA</a></p>
+
+</p>
+ </div>
+ <div class="col-md-3">
+ <style type="text/css">
+/* The following code is added by mdx_elementid.py
+ It was originally lifted from http://subversion.apache.org/style/site.css */
+/*
+ * Hide class="elementid-permalink", except when an enclosing heading
+ * has the :hover property.
+ */
+.headerlink, .elementid-permalink {
+ visibility: hidden;
+}
+h2:hover > .headerlink, h3:hover > .headerlink, h1:hover > .headerlink, h6:hover > .headerlink, h4:hover > .headerlink, h5:hover > .headerlink, dt:hover > .elementid-permalink { visibility: visible }</style>
+<p style="text-align: center; vertical-align: middle; padding-top: 24px;">
+<a href="https://apachecon.com">
+<img src="images/acna18-glossy-wide.png" style="width: 95%; max-width: 260px; height: 108px;" title="ApacheCon North America"/><br/>
+Register for ApacheCon!
+</a>
+</p>
+ </div>
+ </div>
+ </div>
+</section>
+<!-- /ApacheCon etc -->
+<!-- Apache Featured Projects Section -->
+<section class="container">
+ <div class="row">
+ <div class="col-md-12">
+ <h2>Apache Projects</h2>
+ <p>The all-volunteer ASF develops, stewards, and incubates more than 350 Open Source projects and initiatives that cover a wide range of technologies.
+ From Accumulo to Zookeeper, if you are looking for a rewarding experience in Open Source and industry leading software, chances are you are going to find it here.
... 620 lines suppressed ...