diff --git a/.travis.yml b/.travis.yml index 3f04fd04b..ac50826f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ cache: - $HOME/.m2 before_install: # install the gwt-material-jquery because it will depends on built in jquery -- git clone -b release_2.6.1 https://github.com/GwtMaterialDesign/gwt-material-jquery.git +- git clone -b release_2.7.0 https://github.com/GwtMaterialDesign/gwt-material-jquery.git - cd gwt-material-jquery - mvn install -DskipTests=true -DdryRun=true - cd .. diff --git a/.utility/deploy.sh b/.utility/deploy.sh index 1b8ab8f15..a540c2ad5 100644 --- a/.utility/deploy.sh +++ b/.utility/deploy.sh @@ -1,6 +1,6 @@ #!/bin/bash set -ev -if [ "$TRAVIS_JDK_VERSION" == "oraclejdk8" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_BRANCH" == "release_2.6.1" ]; then +if [ "$TRAVIS_JDK_VERSION" == "oraclejdk8" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && [ "$TRAVIS_BRANCH" == "release_2.7.0" ]; then echo "ossrh\${env.OSSRH_USER}\${env.OSSRH_PASS}" > ~/settings.xml mvn deploy -DskipTests --settings ~/settings.xml fi \ No newline at end of file diff --git a/README.md b/README.md index effda1719..35c952711 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@
+ ## Migration 2.0 -> 2.1 - [Mojo to TBroyer](https://github.com/GwtMaterialDesign/gwt-material/wiki/Migrating-from-Mojo-GWT-Maven-Plugin-to-TBroyer) - [PWA Support](https://github.com/GwtMaterialDesign/gwt-material/wiki/PWA-:-Service-Worker-Automation) @@ -18,22 +19,21 @@ Support documentation can be found [here](https://github.com/GwtMaterialDesign/gwt-material/wiki)
We created Java Docs for developers - ## Maven -### Current Version 2.6.1 +### Current Version 2.7.0 ```xml com.github.gwtmaterialdesign gwt-material - 2.6.1 + 2.7.0 ``` -### Snapshot Version 2.6.1-SNAPSHOT +### Snapshot Version 2.8.0-SNAPSHOT ```xml com.github.gwtmaterialdesign gwt-material - 2.6.1-SNAPSHOT + 2.8.0-SNAPSHOT ``` diff --git a/gwt-material/pom.xml b/gwt-material/pom.xml index 652e68618..dec557bfc 100644 --- a/gwt-material/pom.xml +++ b/gwt-material/pom.xml @@ -4,7 +4,7 @@ gwt-material-parent com.github.gwtmaterialdesign - 2.6.1 + 2.7.0 4.0.0 diff --git a/gwt-material/src/main/java/gwt/material/design/client/base/AbstractValueWidget.java b/gwt-material/src/main/java/gwt/material/design/client/base/AbstractValueWidget.java index 431af00c3..07e1b9633 100644 --- a/gwt-material/src/main/java/gwt/material/design/client/base/AbstractValueWidget.java +++ b/gwt-material/src/main/java/gwt/material/design/client/base/AbstractValueWidget.java @@ -28,6 +28,7 @@ import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.ui.HasValue; import com.google.gwt.user.client.ui.UIObject; +import com.google.gwt.user.client.ui.Widget; import gwt.material.design.client.base.error.ErrorHandler; import gwt.material.design.client.base.error.ErrorHandlerType; import gwt.material.design.client.base.error.HasErrorHandler; @@ -44,7 +45,7 @@ import java.util.List; -public abstract class AbstractValueWidget extends MaterialWidget implements HasValue, LeafValueEditor, +public abstract class AbstractValueWidget extends MaterialWidget implements HasResetField, HasValue, LeafValueEditor, HasEditorErrors, HasErrorHandler, HasStatusText, HasValidators, HasRequiredField, HasClearOnKeyUp, HasCopyCommand { private V initialValue; @@ -55,6 +56,7 @@ public abstract class AbstractValueWidget extends MaterialWidget implements H private StatusTextMixin statusTextMixin; private ErrorHandlerMixin errorHandlerMixin; private RequiredFieldMixin requiredFieldMixin; + private ResetFieldMixin resetFieldMixin; private ClearOnKeyUpMixin clearOnKeyUpMixin; private HandlerRegistration attachHandler, blurHandler; protected CopyCommandMixin copyCommandMixin; @@ -151,6 +153,22 @@ public boolean isSuccessTextVisible() { return getStatusTextMixin().isSuccessTextVisible(); } + @Override + public void resetFields() { + getResetFieldMixin().resetFields(); + getValidatorMixin().reset(); + } + + @Override + public void setAllowResettingFields(boolean allowResettingFields) { + getResetFieldMixin().setAllowResettingFields(allowResettingFields); + } + + @Override + public boolean isAllowResettingFields() { + return getResetFieldMixin().isAllowResettingFields(); + } + @Override public void setStatusDisplayType(StatusDisplayType displayType) { getStatusTextMixin().setStatusDisplayType(displayType); @@ -432,4 +450,11 @@ protected CopyCommandMixin getCopyCommandMixin() { } return copyCommandMixin; } + + public ResetFieldMixin getResetFieldMixin() { + if (resetFieldMixin == null) { + resetFieldMixin = new ResetFieldMixin<>(this); + } + return resetFieldMixin; + } } diff --git a/gwt-material/src/main/java/gwt/material/design/client/base/DefaultMoreChipHandler.java b/gwt-material/src/main/java/gwt/material/design/client/base/DefaultMoreChipHandler.java new file mode 100644 index 000000000..4bb59d0d9 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/base/DefaultMoreChipHandler.java @@ -0,0 +1,167 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.base; + +import com.google.gwt.dom.client.Style; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.ui.Widget; +import gwt.material.design.client.base.mixin.ToggleStyleMixin; +import gwt.material.design.client.constants.Display; +import gwt.material.design.client.constants.IconType; +import gwt.material.design.client.ui.*; + +import java.util.List; + +import static gwt.material.design.client.js.JsMaterialElement.$; + +public class DefaultMoreChipHandler implements MoreChipHandler { + + protected int visibleChipsSize = 0; + protected MaterialLink more = new MaterialLink(); + protected String localizedMoreText = "Show {0} more items"; + protected MaterialChipContainer container; + protected ToggleStyleMixin toggleStyleMixin; + protected HandlerRegistration handlerRegistration; + protected MaterialLabel collapseLabel = new MaterialLabel(); + protected MaterialIcon collapseIcon = new MaterialIcon(IconType.KEYBOARD_ARROW_UP); + protected ToggleStyleMixin collapsibleMixin; + protected ToggleStyleMixin collapseMixin; + + public DefaultMoreChipHandler(MaterialChipContainer container) { + this.container = container; + more.setDisplay(Display.BLOCK); + more.setMarginLeft(4); + more.setMarginTop(12); + } + + @Override + public void setVisibleChipsSize(int visibleChipsSize) { + this.visibleChipsSize = visibleChipsSize; + } + + @Override + public void load() { + showHiddenChips(false); + collapseIcon.addStyleName("collapse"); + collapseLabel.addStyleName("collapse-label"); + collapseIcon.addClickHandler(this::toggle); + collapseLabel.addClickHandler(this::toggle); + if (!collapseIcon.isAttached()) { + collapseIcon.setVisible(false); + collapseLabel.setVisible(false); + container.add(collapseIcon); + container.add(collapseLabel); + } + } + + public void collapse() { + getCollapseMixin().setOn(true); + } + + public void expand() { + getCollapseMixin().setOn(false); + } + + public void setCollapsible(boolean enableCollapsible) { + getCollapsibleMixin().setOn(enableCollapsible); + } + + protected void toggle(ClickEvent event) { + if (!getCollapseMixin().isOn()) { + collapse(); + } else { + expand(); + } + event.stopPropagation(); + event.preventDefault(); + } + + @Override + public void reload() { + showHiddenChips(false); + } + + @Override + public void update(MaterialChip chip) { + if (getCollapseMixin().isOn()) { + MaterialIcon icon = chip.getIcon(); + icon.registerHandler(icon.addClickHandler(clickEvent -> updateCollapseLabel(chip))); + updateCollapseLabel(chip); + } + } + + protected void updateCollapseLabel(MaterialChip chip) { + int length = $(container.getElement()).find(".chip").length(); + collapseIcon.setVisible(length > 0); + collapseLabel.setVisible(length > 0); + collapseLabel.setText(length + ""); + } + + public void showHiddenChips(boolean showHiddenChips) { + if (visibleChipsSize > 0) { + if (handlerRegistration == null) { + handlerRegistration = more.addClickHandler(clickEvent -> showHiddenChips(!getToggleStyleMixin().isOn())); + } + if (!more.isAttached()) { + container.add(more); + } + List chipList = container.getChipList(); + int hiddenChipsSize = chipList.size() - visibleChipsSize; + for (MaterialChip widgets : chipList) { + if (showHiddenChips) { + $(widgets.getElement()).css("display", "block"); + } else { + if (chipList.indexOf(widgets) > visibleChipsSize) { + $(widgets.getElement()).css("display", "none"); + } + } + } + + if (showHiddenChips) { + more.setVisibility(Style.Visibility.HIDDEN); + } else { + more.setVisibility(Style.Visibility.VISIBLE); + more.setText(localizedMoreText.replace("{0}", hiddenChipsSize + "")); + } + } + } + + public ToggleStyleMixin getCollapseMixin() { + if (collapseMixin == null) { + collapseMixin = new ToggleStyleMixin<>(container, "collapse"); + } + return collapseMixin; + } + + public ToggleStyleMixin getCollapsibleMixin() { + if (collapsibleMixin == null) { + collapsibleMixin = new ToggleStyleMixin<>(container, "enable-collapsible"); + } + return collapsibleMixin; + } + + public ToggleStyleMixin getToggleStyleMixin() { + if (toggleStyleMixin == null) { + toggleStyleMixin = new ToggleStyleMixin<>(container, "expanded"); + } + return toggleStyleMixin; + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/base/MaterialWidget.java b/gwt-material/src/main/java/gwt/material/design/client/base/MaterialWidget.java index a7992ba4d..a539b65a9 100644 --- a/gwt-material/src/main/java/gwt/material/design/client/base/MaterialWidget.java +++ b/gwt-material/src/main/java/gwt/material/design/client/base/MaterialWidget.java @@ -39,6 +39,7 @@ import gwt.material.design.client.events.DropEvent; import gwt.material.design.client.events.*; import gwt.material.design.client.events.OrientationChangeEvent.OrientationChangeHandler; +import gwt.material.design.client.theme.GlobalThemeConfig; import gwt.material.design.client.theme.ThemeManager; import gwt.material.design.jquery.client.api.JQuery; import gwt.material.design.jquery.client.api.JQueryElement; @@ -58,6 +59,7 @@ public class MaterialWidget extends ComplexPanel implements HasId, HasEnabled, H private static JQueryElement window = null; private static JQueryElement body = null; + private static GlobalThemeConfig themeConfig; public static JQueryElement window() { if (window == null) { @@ -1960,4 +1962,11 @@ public void setTranslationKey(String key) { public String getTranslationKey() { return translationKey; } + + public static GlobalThemeConfig getGlobalTheme() { + if (themeConfig == null) { + themeConfig = new GlobalThemeConfig(); + } + return themeConfig; + } } diff --git a/gwt-material/src/main/java/gwt/material/design/client/base/MoreChipHandler.java b/gwt-material/src/main/java/gwt/material/design/client/base/MoreChipHandler.java new file mode 100644 index 000000000..5dcf8ad17 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/base/MoreChipHandler.java @@ -0,0 +1,39 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.base; + +import gwt.material.design.client.ui.MaterialChip; + +public interface MoreChipHandler { + + void setVisibleChipsSize(int visibleChipsSize); + + void load(); + + void collapse(); + + void expand(); + + void setCollapsible(boolean enableCollapsible); + + void reload(); + + void update(MaterialChip chip); +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/base/mixin/ResetFieldMixin.java b/gwt-material/src/main/java/gwt/material/design/client/base/mixin/ResetFieldMixin.java index 3934b7925..24dedaae5 100644 --- a/gwt-material/src/main/java/gwt/material/design/client/base/mixin/ResetFieldMixin.java +++ b/gwt-material/src/main/java/gwt/material/design/client/base/mixin/ResetFieldMixin.java @@ -57,8 +57,8 @@ public void resetFields() { protected void reset(Widget parent) { if (parent instanceof HasWidgets) { for (Widget child : (HasWidgets) parent) { - if (child instanceof AbstractValueWidget) { - ((AbstractValueWidget) child).reset(); + if (child instanceof HasResetField) { + ((HasResetField) child).resetFields(); } else if (propagateToChildren) { reset(child); diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/AbstractValueSanitizer.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/AbstractValueSanitizer.java new file mode 100644 index 000000000..3432b2dd4 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/AbstractValueSanitizer.java @@ -0,0 +1,182 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer; + +import com.google.gwt.event.shared.HandlerRegistration; +import gwt.material.design.client.sanitizer.handler.*; + +public abstract class AbstractValueSanitizer implements ValueSanitizer { + + protected boolean enabled = true; + + public AbstractValueSanitizer() { + //TODO: Self Register this + register(new StandardSanitizeHandler()); + register(new ChineseSanitizeHandler()); + register(new JapaneseSanitizeHandler()); + register(new EmojiSanitizeHandler()); + register(new NumericSanitizeHandler()); + register(new ReservedWordSanitizeHandler()); + register(new RtlCharacterSanitizeHandler()); + register(new SpecialCharacterSanitizeHandler()); + register(new UnicodeSanitizeHandler()); + register(new ZalgoTextSanitizeHandler()); + register(new OghamSanitizeHandler()); + register(new SuperscriptSubscriptSanitizeHandler()); + register(new SymbolsSanitizeHandler()); + register(new MathOperatorsSanitizeHandler()); + register(new NumberFormsSanitizeHandler()); + register(new QuotationSanitizeHandler()); + register(new NonWhiteSpaceC0SanitizeHandler()); + register(new NonWhiteSpaceC1SanitizeHandler()); + } + + @Override + public boolean sanitize(String value) throws ValueSanitizerException { + if (enabled) { + for (ValueSanitizeHandler enabledHandler : ValueSanitizerRegistry.getEnabledHandlers()) { + enabledHandler.sanitize(value); + } + } + return true; + } + + public void register(ValueSanitizeHandler handler) { + ValueSanitizerRegistry.register(handler); + } + + @Override + public void enabled(boolean enabled) { + this.enabled = enabled; + } + + @Override + public boolean isEnabled() { + return enabled; + } + + @Override + public ValueSanitizer standard(boolean sanitize) { + ValueSanitizerRegistry.enable(StandardSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer reservedString(boolean sanitize) { + ValueSanitizerRegistry.enable(ReservedWordSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer special(boolean sanitize) { + ValueSanitizerRegistry.enable(SpecialCharacterSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer numeric(boolean sanitize) { + ValueSanitizerRegistry.enable(NumericSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer unicode(boolean sanitize) { + ValueSanitizerRegistry.enable(UnicodeSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer chinese(boolean sanitize) { + ValueSanitizerRegistry.enable(ChineseSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer japanese(boolean sanitize) { + ValueSanitizerRegistry.enable(JapaneseSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer emoji(boolean sanitize) { + ValueSanitizerRegistry.enable(EmojiSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer rtl(boolean sanitize) { + ValueSanitizerRegistry.enable(RtlCharacterSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer zalgo(boolean sanitize) { + ValueSanitizerRegistry.enable(ZalgoTextSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer ogham(boolean sanitize) { + ValueSanitizerRegistry.enable(OghamSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer superscriptAndSubscript(boolean sanitize) { + ValueSanitizerRegistry.enable(SuperscriptSubscriptSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer symbols(boolean sanitize) { + ValueSanitizerRegistry.enable(SymbolsSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer numberForms(boolean sanitize) { + ValueSanitizerRegistry.enable(NumberFormsSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer quotation(boolean sanitize) { + ValueSanitizerRegistry.enable(QuotationSanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer nonWhiteSpaceC0Controls(boolean sanitize) { + ValueSanitizerRegistry.enable(NonWhiteSpaceC0SanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer nonWhiteSpaceC1Controls(boolean sanitize) { + ValueSanitizerRegistry.enable(NonWhiteSpaceC1SanitizeHandler.class, sanitize); + return this; + } + + @Override + public ValueSanitizer mathOperators(boolean sanitize) { + ValueSanitizerRegistry.enable(MathOperatorsSanitizeHandler.class, sanitize); + return this; + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/DefaultValueSanitizer.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/DefaultValueSanitizer.java new file mode 100644 index 000000000..f4d749fd2 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/DefaultValueSanitizer.java @@ -0,0 +1,27 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer; + +public class DefaultValueSanitizer extends AbstractValueSanitizer { + + public DefaultValueSanitizer() { + super(); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/HasValueSanitizer.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/HasValueSanitizer.java new file mode 100644 index 000000000..584d4f070 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/HasValueSanitizer.java @@ -0,0 +1,32 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer; + +import com.google.gwt.event.shared.HandlerRegistration; +import gwt.material.design.client.sanitizer.handler.ValueSanitizerErrorEvent; + +public interface HasValueSanitizer { + + ValueSanitizer getValueSanitizer(); + + void setValueSanitizer(ValueSanitizer valueSanitizer); + + HandlerRegistration addSanitizationErrorHandler(ValueSanitizerErrorEvent.ValueSanitizerErrorHandler handler); +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/Keywords.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/Keywords.java new file mode 100644 index 000000000..e63b8f936 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/Keywords.java @@ -0,0 +1,34 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer; + +public class Keywords { + + //TODO: https://www.thoughtco.com/reserved-words-in-java-2034200 + public static final String[] RESERVED_WORDS = new String[]{"abstract", "assert", "boolean", "break", "byte", "case", "catch", + "char", "class", "const", "continue", "default", "double", "do", + "else", "enum", "extends", "false", "final", "finally", "float", + "for", "goto", "if", "implements", "import", "instanceof", "int", + "interface", "long", "native", "new", "null", "package", "private", "protected", "public", + "return", "short", "static", "strictfp", "super", "switch", "synchronized", "this", + "throw", "throws", "transient", "true", "try", "void", "volatile", "why", + "undefined", "undef", "null", "NULL", "(null)", "nil", "NIL", "true", "false", + "True", "False", "TRUE", "FALSE", "None", "hasOwnProperty", "then", "constructor"}; +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/Patterns.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/Patterns.java new file mode 100644 index 000000000..d4f4ea2a7 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/Patterns.java @@ -0,0 +1,39 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer; + +public class Patterns { + + public static final String STANDARD = "[\\u0000-\\u0255]"; + public static final String CHINESE = "[\\u2E80-\\u2FD5\\u3190-\\u319f\\u3400-\\u4DBF\\u4E00-\\u9FCC\\uF900-\\uFAAD]"; + public static final String SPECIAL = "(?=.*[-\\/:-@\\[-\\`{-~]{1,})"; + public static final String UNICODE = "[\\uE700-\\uE72E\\uE730\\uE731\\uE734\\uE735\\uE737-\\uE756]"; + public static final String JAPANESE = "[\\u3000-\\u303f\\u3040-\\u309f\\u30a0-\\u30ff\\uff00-\\uff9f\\u4e00-\\u9faf\\u3400-\\u4dbf\\uac00-\\ud7a3]"; + public static final String ZALGO = "[\\u0300-\\u0361\\u0316-\\u0362\\u0334-\\u0338\\u0363-\\u036f]"; + public static final String OGHAM = "[\\u1680-\\u169f]"; + public static final String SUPERSCRIPT_SUBSCRIPT = "[\\u2070-\\u209f]"; + public static final String SYMBOLS = "[\\u20a0-\\u20cf\\u2100-\\u214f\\u2190-\\u21ff\\u27f0-\\u27ff\\u2900-\\u297f\\u1f800-\\u1f8ff\\u27c0-\\u27ef\\u2980-\\u29ff\\u2600-\\u26ff\\u2b00-\\u2bff\\u1d100-\\u1d1ff" + + "\\u2400-\\u243f\\u2460-\\u24ff\\u2500-\\u257f\\u2580-\\u259f\\u25a0-\\u25ff\\u1f780-\\u1f7ff\\u2700-\\u27bf\\u2800-\\u28ff\\u1f030-\\u1f09f\\u1f0a0-\\u1f0ff]"; + public static final String MATH_OPERATORS = "[\\u2200-\\u22ff\\u2a00-\\u2aff\\u2300-\\u23ff]"; + public static final String NUMBER_FORMS = "[\\u2150-\\u218f]"; + public static final String QUOTATION = "((?:'|\").*(?:'|\"))"; + public static final String NON_WHITESPACE_C0_CONTROLS ="[\\u0001-\\u0008\\u000e-\\u001f\\u007f]"; + public static final String NON_WHITESPACE_C1_CONTROLS = "[\\u0080-\\u0084\\u0086-\\u009f]"; +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/StandardValueSanitizer.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/StandardValueSanitizer.java new file mode 100644 index 000000000..166871817 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/StandardValueSanitizer.java @@ -0,0 +1,29 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer; + +public class StandardValueSanitizer extends AbstractValueSanitizer { + + public StandardValueSanitizer() { + super(); + + standard(true); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/ValueSanitizer.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/ValueSanitizer.java new file mode 100644 index 000000000..3973686ec --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/ValueSanitizer.java @@ -0,0 +1,68 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer; + +import com.google.gwt.event.shared.HandlerRegistration; +import gwt.material.design.client.sanitizer.handler.ValueSanitizerErrorEvent; + +public interface ValueSanitizer { + + boolean sanitize(String value) throws ValueSanitizerException; + + void enabled(boolean enabled); + + boolean isEnabled(); + + ValueSanitizer standard(boolean sanitize); + + ValueSanitizer reservedString(boolean sanitize); + + ValueSanitizer special(boolean sanitize); + + ValueSanitizer numeric(boolean sanitize); + + ValueSanitizer unicode(boolean sanitize); + + ValueSanitizer chinese(boolean sanitize); + + ValueSanitizer japanese(boolean sanitize); + + ValueSanitizer emoji(boolean sanitize); + + ValueSanitizer rtl(boolean sanitize); + + ValueSanitizer zalgo(boolean sanitize); + + ValueSanitizer ogham(boolean sanitize); + + ValueSanitizer superscriptAndSubscript(boolean sanitize); + + ValueSanitizer symbols(boolean sanitize); + + ValueSanitizer numberForms(boolean sanitize); + + ValueSanitizer quotation(boolean sanitize); + + ValueSanitizer nonWhiteSpaceC0Controls(boolean sanitize); + + ValueSanitizer nonWhiteSpaceC1Controls(boolean sanitize); + + ValueSanitizer mathOperators(boolean sanitize); +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/ValueSanitizerException.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/ValueSanitizerException.java new file mode 100644 index 000000000..5f4b584b6 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/ValueSanitizerException.java @@ -0,0 +1,27 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer; + +public class ValueSanitizerException extends RuntimeException { + + public ValueSanitizerException(String message) { + super(message); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/ValueSanitizerRegistry.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/ValueSanitizerRegistry.java new file mode 100644 index 000000000..d53b44345 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/ValueSanitizerRegistry.java @@ -0,0 +1,50 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer; + +import gwt.material.design.client.sanitizer.handler.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ValueSanitizerRegistry { + + protected static Map, ValueSanitizeHandler> map = new HashMap<>(); + + public static void register(ValueSanitizeHandler handler) { + map.put(handler.getClass(), handler); + } + + public static void enable(Class handler, boolean enable) { + map.get(handler).setEnabled(enable); + } + + public static List getEnabledHandlers() { + List handlers = new ArrayList<>(); + map.forEach((aClass, handler) -> { + if (handler.isEnabled()) { + handlers.add(handler); + } + }); + return handlers; + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/ValueSanitizerTester.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/ValueSanitizerTester.java new file mode 100644 index 000000000..5442c5c30 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/ValueSanitizerTester.java @@ -0,0 +1,34 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer; + +public class ValueSanitizerTester { + + public static DefaultValueSanitizer sanitizer = new DefaultValueSanitizer(); + + public static void main(String[] args) { + try { + String test = "\u0080"; + System.out.println("Valid : " + sanitizer.sanitize(test)); + } catch (Exception e) { + System.out.println(e + ""); + } + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/AbstractSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/AbstractSanitizeHandler.java new file mode 100644 index 000000000..5a567808f --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/AbstractSanitizeHandler.java @@ -0,0 +1,61 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import com.google.gwt.regexp.shared.MatchResult; +import com.google.gwt.regexp.shared.RegExp; +import gwt.material.design.client.sanitizer.ValueSanitizerException; + +public abstract class AbstractSanitizeHandler implements ValueSanitizeHandler { + + protected boolean enabled; + + public AbstractSanitizeHandler() { + + } + + @Override + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + @Override + public boolean isEnabled() { + return enabled; + } + + public boolean matches(String pattern, String value, String sanitizeError) { + RegExp regExp = RegExp.compile(pattern); + MatchResult matcher = regExp.exec(value); + if (matcher != null) { + throw new ValueSanitizerException(sanitizeError); + } + return false; + } + + public boolean contains(String[] strings, String value, String sanitizeError) { + for (String string : strings) { + if (value.equals(string)) { + throw new ValueSanitizerException(sanitizeError); + } + } + return false; + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ChineseSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ChineseSanitizeHandler.java new file mode 100644 index 000000000..b88a457a9 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ChineseSanitizeHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.Patterns; + +public class ChineseSanitizeHandler extends AbstractSanitizeHandler { + + public ChineseSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return matches(Patterns.CHINESE, value, "Value must not contain chinese characters"); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/EmojiSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/EmojiSanitizeHandler.java new file mode 100644 index 000000000..396a7d03b --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/EmojiSanitizeHandler.java @@ -0,0 +1,37 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.ValueSanitizerException; +import gwt.material.design.client.sanitizer.utils.EmojiUtil; + +public class EmojiSanitizeHandler extends AbstractSanitizeHandler { + + public EmojiSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + if (EmojiUtil.containsEmoji(value)) { + throw new ValueSanitizerException("Value must not contain reserved emoji characters"); + } + return true; + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/JapaneseSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/JapaneseSanitizeHandler.java new file mode 100644 index 000000000..16b768e58 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/JapaneseSanitizeHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.Patterns; + +public class JapaneseSanitizeHandler extends AbstractSanitizeHandler { + + public JapaneseSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return matches(Patterns.JAPANESE, value, "Value must not contain Japanese characters"); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/MathOperatorsSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/MathOperatorsSanitizeHandler.java new file mode 100644 index 000000000..be9790199 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/MathOperatorsSanitizeHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.Patterns; + +public class MathOperatorsSanitizeHandler extends AbstractSanitizeHandler { + + public MathOperatorsSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return matches(Patterns.MATH_OPERATORS, value, "Value must not contain math operators"); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/NonWhiteSpaceC0SanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/NonWhiteSpaceC0SanitizeHandler.java new file mode 100644 index 000000000..bd9482526 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/NonWhiteSpaceC0SanitizeHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.Patterns; + +public class NonWhiteSpaceC0SanitizeHandler extends AbstractSanitizeHandler { + + public NonWhiteSpaceC0SanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return matches(Patterns.NON_WHITESPACE_C0_CONTROLS, value, "Value must not contain non white space C0 controls"); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/NonWhiteSpaceC1SanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/NonWhiteSpaceC1SanitizeHandler.java new file mode 100644 index 000000000..0abc2338e --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/NonWhiteSpaceC1SanitizeHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.Patterns; + +public class NonWhiteSpaceC1SanitizeHandler extends AbstractSanitizeHandler { + + public NonWhiteSpaceC1SanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return matches(Patterns.NON_WHITESPACE_C1_CONTROLS, value, "Value must not contain non whitespace C1 controls"); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/NumberFormsSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/NumberFormsSanitizeHandler.java new file mode 100644 index 000000000..ee6d7ffce --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/NumberFormsSanitizeHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.Patterns; + +public class NumberFormsSanitizeHandler extends AbstractSanitizeHandler { + + public NumberFormsSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return matches(Patterns.NUMBER_FORMS, value, "Value must not contain fraction, roman numerals and other number forms"); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/NumericSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/NumericSanitizeHandler.java new file mode 100644 index 000000000..3dcaa1911 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/NumericSanitizeHandler.java @@ -0,0 +1,31 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +public class NumericSanitizeHandler extends AbstractSanitizeHandler { + + public NumericSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return true; + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/OghamSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/OghamSanitizeHandler.java new file mode 100644 index 000000000..7a99daf79 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/OghamSanitizeHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.Patterns; + +public class OghamSanitizeHandler extends AbstractSanitizeHandler { + + public OghamSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return matches(Patterns.OGHAM, value, "Value must not contain Ogham characters"); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/QuotationSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/QuotationSanitizeHandler.java new file mode 100644 index 000000000..86a3753a7 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/QuotationSanitizeHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.Patterns; + +public class QuotationSanitizeHandler extends AbstractSanitizeHandler { + + public QuotationSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return matches(Patterns.QUOTATION, value, "Value must not contain quotation marks"); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ReservedWordSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ReservedWordSanitizeHandler.java new file mode 100644 index 000000000..0b1756587 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ReservedWordSanitizeHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.Keywords; + +public class ReservedWordSanitizeHandler extends AbstractSanitizeHandler { + + public ReservedWordSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return contains(Keywords.RESERVED_WORDS, value, "Value must not contain reserved strings"); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/RtlCharacterSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/RtlCharacterSanitizeHandler.java new file mode 100644 index 000000000..c48ee9227 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/RtlCharacterSanitizeHandler.java @@ -0,0 +1,39 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.ValueSanitizerException; + +public class RtlCharacterSanitizeHandler extends AbstractSanitizeHandler { + + public RtlCharacterSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + char[] chars = value.toCharArray(); + for(char c: chars){ + if(c >= 0x600 && c <= 0x6ff){ + throw new ValueSanitizerException("Value must not contain right to left characters"); + } + } + return true; + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/SpecialCharacterSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/SpecialCharacterSanitizeHandler.java new file mode 100644 index 000000000..ab9882a3d --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/SpecialCharacterSanitizeHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.Patterns; + +public class SpecialCharacterSanitizeHandler extends AbstractSanitizeHandler { + + public SpecialCharacterSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return matches(Patterns.SPECIAL, value, "Value must not contain special characters"); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/StandardSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/StandardSanitizeHandler.java new file mode 100644 index 000000000..37b362ed2 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/StandardSanitizeHandler.java @@ -0,0 +1,41 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import com.google.gwt.regexp.shared.MatchResult; +import com.google.gwt.regexp.shared.RegExp; +import gwt.material.design.client.sanitizer.Patterns; +import gwt.material.design.client.sanitizer.ValueSanitizerException; + +public class StandardSanitizeHandler extends AbstractSanitizeHandler { + + public StandardSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + RegExp regExp = RegExp.compile(Patterns.STANDARD); + MatchResult matcher = regExp.exec(value); + if (value != null && !value.isEmpty() && matcher == null) { + throw new ValueSanitizerException("Only Standard characters are allowed"); + } + return true; + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/SuperscriptSubscriptSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/SuperscriptSubscriptSanitizeHandler.java new file mode 100644 index 000000000..c335a854c --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/SuperscriptSubscriptSanitizeHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.Patterns; + +public class SuperscriptSubscriptSanitizeHandler extends AbstractSanitizeHandler { + + public SuperscriptSubscriptSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return matches(Patterns.SUPERSCRIPT_SUBSCRIPT, value, "Value must not contain superscript and subscript characters"); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/SymbolsSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/SymbolsSanitizeHandler.java new file mode 100644 index 000000000..4c98595b1 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/SymbolsSanitizeHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.Patterns; + +public class SymbolsSanitizeHandler extends AbstractSanitizeHandler { + + public SymbolsSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return matches(Patterns.SYMBOLS, value, "Value must not contain symbols"); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/UnicodeSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/UnicodeSanitizeHandler.java new file mode 100644 index 000000000..bc1fa4ddc --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/UnicodeSanitizeHandler.java @@ -0,0 +1,31 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +public class UnicodeSanitizeHandler extends AbstractSanitizeHandler { + + public UnicodeSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return true; + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ValueSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ValueSanitizeHandler.java new file mode 100644 index 000000000..4a871d98b --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ValueSanitizeHandler.java @@ -0,0 +1,31 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.ValueSanitizerException; + +public interface ValueSanitizeHandler { + + boolean sanitize(String value) throws ValueSanitizerException; + + void setEnabled(boolean enabled); + + boolean isEnabled(); +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ValueSanitizerErrorEvent.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ValueSanitizerErrorEvent.java new file mode 100644 index 000000000..cc72b13bf --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ValueSanitizerErrorEvent.java @@ -0,0 +1,57 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import com.google.gwt.event.shared.EventHandler; +import com.google.gwt.event.shared.GwtEvent; +import com.google.gwt.event.shared.HasHandlers; + +public class ValueSanitizerErrorEvent extends GwtEvent { + + protected String localizedMessage; + + public ValueSanitizerErrorEvent(String localizedMessage) { + this.localizedMessage = localizedMessage; + } + + public interface ValueSanitizerErrorHandler extends EventHandler { + void onSideNavOpened(ValueSanitizerErrorEvent event); + } + + public static final Type TYPE = new Type<>(); + + public static void fire(HasHandlers source, String localizedMessage) { + source.fireEvent(new ValueSanitizerErrorEvent(localizedMessage)); + } + + @Override + public Type getAssociatedType() { + return TYPE; + } + + public String getLocalizedMessage() { + return localizedMessage; + } + + @Override + protected void dispatch(ValueSanitizerErrorHandler handler) { + handler.onSideNavOpened(this); + } +} \ No newline at end of file diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ZalgoTextSanitizeHandler.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ZalgoTextSanitizeHandler.java new file mode 100644 index 000000000..96a7c6c46 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/handler/ZalgoTextSanitizeHandler.java @@ -0,0 +1,33 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.sanitizer.handler; + +import gwt.material.design.client.sanitizer.Patterns; + +public class ZalgoTextSanitizeHandler extends AbstractSanitizeHandler { + + public ZalgoTextSanitizeHandler() { + } + + @Override + public boolean sanitize(String value) { + return matches(Patterns.ZALGO, value, "Value must not contain Zalgo Characters"); + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/sanitizer/utils/EmojiUtil.java b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/utils/EmojiUtil.java new file mode 100644 index 000000000..a414c6346 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/sanitizer/utils/EmojiUtil.java @@ -0,0 +1,484 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2022 GwtMaterialDesign + * %% + * 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. + * #L% + */ +/* +Copyright 2018 by coder4 https://github.com/liheyuan/simple-emoji-4j + +Licensed under the Apache License,Version2.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 gwt.material.design.client.sanitizer.utils; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +/** + * Support Emoji 12.0 2018-10-15 + * + * @author coder4 + */ +public class EmojiUtil { + + // Generated from http://unicode.org/Public/emoji/12.0/emoji-data.txt + private static Set EMOJI_HASH_SET = new HashSet<>(Arrays.asList( + "1f000", "1f001", "1f002", "1f003", "1f004", "1f005", "1f006", "1f007", "1f008", "1f009", + "1f00a", "1f00b", "1f00c", "1f00d", "1f00e", "1f00f", "1f010", "1f011", "1f012", "1f013", + "1f014", "1f015", "1f016", "1f017", "1f018", "1f019", "1f01a", "1f01b", "1f01c", "1f01d", + "1f01e", "1f01f", "1f020", "1f021", "1f022", "1f023", "1f024", "1f025", "1f026", "1f027", + "1f028", "1f029", "1f02a", "1f02b", "1f02c", "1f02d", "1f02e", "1f02f", "1f030", "1f031", + "1f032", "1f033", "1f034", "1f035", "1f036", "1f037", "1f038", "1f039", "1f03a", "1f03b", + "1f03c", "1f03d", "1f03e", "1f03f", "1f040", "1f041", "1f042", "1f043", "1f044", "1f045", + "1f046", "1f047", "1f048", "1f049", "1f04a", "1f04b", "1f04c", "1f04d", "1f04e", "1f04f", + "1f050", "1f051", "1f052", "1f053", "1f054", "1f055", "1f056", "1f057", "1f058", "1f059", + "1f05a", "1f05b", "1f05c", "1f05d", "1f05e", "1f05f", "1f060", "1f061", "1f062", "1f063", + "1f064", "1f065", "1f066", "1f067", "1f068", "1f069", "1f06a", "1f06b", "1f06c", "1f06d", + "1f06e", "1f06f", "1f070", "1f071", "1f072", "1f073", "1f074", "1f075", "1f076", "1f077", + "1f078", "1f079", "1f07a", "1f07b", "1f07c", "1f07d", "1f07e", "1f07f", "1f080", "1f081", + "1f082", "1f083", "1f084", "1f085", "1f086", "1f087", "1f088", "1f089", "1f08a", "1f08b", + "1f08c", "1f08d", "1f08e", "1f08f", "1f090", "1f091", "1f092", "1f093", "1f094", "1f095", + "1f096", "1f097", "1f098", "1f099", "1f09a", "1f09b", "1f09c", "1f09d", "1f09e", "1f09f", + "1f0a0", "1f0a1", "1f0a2", "1f0a3", "1f0a4", "1f0a5", "1f0a6", "1f0a7", "1f0a8", "1f0a9", + "1f0aa", "1f0ab", "1f0ac", "1f0ad", "1f0ae", "1f0af", "1f0b0", "1f0b1", "1f0b2", "1f0b3", + "1f0b4", "1f0b5", "1f0b6", "1f0b7", "1f0b8", "1f0b9", "1f0ba", "1f0bb", "1f0bc", "1f0bd", + "1f0be", "1f0bf", "1f0c0", "1f0c1", "1f0c2", "1f0c3", "1f0c4", "1f0c5", "1f0c6", "1f0c7", + "1f0c8", "1f0c9", "1f0ca", "1f0cb", "1f0cc", "1f0cd", "1f0ce", "1f0cf", "1f0d0", "1f0d1", + "1f0d2", "1f0d3", "1f0d4", "1f0d5", "1f0d6", "1f0d7", "1f0d8", "1f0d9", "1f0da", "1f0db", + "1f0dc", "1f0dd", "1f0de", "1f0df", "1f0e0", "1f0e1", "1f0e2", "1f0e3", "1f0e4", "1f0e5", + "1f0e6", "1f0e7", "1f0e8", "1f0e9", "1f0ea", "1f0eb", "1f0ec", "1f0ed", "1f0ee", "1f0ef", + "1f0f0", "1f0f1", "1f0f2", "1f0f3", "1f0f4", "1f0f5", "1f0f6", "1f0f7", "1f0f8", "1f0f9", + "1f0fa", "1f0fb", "1f0fc", "1f0fd", "1f0fe", "1f0ff", "1f10d", "1f10e", "1f10f", "1f12f", + "1f16c", "1f16d", "1f16e", "1f16f", "1f170", "1f171", "1f17e", "1f17f", "1f18e", "1f191", + "1f192", "1f193", "1f194", "1f195", "1f196", "1f197", "1f198", "1f199", "1f19a", "1f1ad", + "1f1ae", "1f1af", "1f1b0", "1f1b1", "1f1b2", "1f1b3", "1f1b4", "1f1b5", "1f1b6", "1f1b7", + "1f1b8", "1f1b9", "1f1ba", "1f1bb", "1f1bc", "1f1bd", "1f1be", "1f1bf", "1f1c0", "1f1c1", + "1f1c2", "1f1c3", "1f1c4", "1f1c5", "1f1c6", "1f1c7", "1f1c8", "1f1c9", "1f1ca", "1f1cb", + "1f1cc", "1f1cd", "1f1ce", "1f1cf", "1f1d0", "1f1d1", "1f1d2", "1f1d3", "1f1d4", "1f1d5", + "1f1d6", "1f1d7", "1f1d8", "1f1d9", "1f1da", "1f1db", "1f1dc", "1f1dd", "1f1de", "1f1df", + "1f1e0", "1f1e1", "1f1e2", "1f1e3", "1f1e4", "1f1e5", "1f1e6", "1f1e7", "1f1e8", "1f1e9", + "1f1ea", "1f1eb", "1f1ec", "1f1ed", "1f1ee", "1f1ef", "1f1f0", "1f1f1", "1f1f2", "1f1f3", + "1f1f4", "1f1f5", "1f1f6", "1f1f7", "1f1f8", "1f1f9", "1f1fa", "1f1fb", "1f1fc", "1f1fd", + "1f1fe", "1f1ff", "1f201", "1f202", "1f203", "1f204", "1f205", "1f206", "1f207", "1f208", + "1f209", "1f20a", "1f20b", "1f20c", "1f20d", "1f20e", "1f20f", "1f21a", "1f22f", "1f232", + "1f233", "1f234", "1f235", "1f236", "1f237", "1f238", "1f239", "1f23a", "1f23c", "1f23d", + "1f23e", "1f23f", "1f249", "1f24a", "1f24b", "1f24c", "1f24d", "1f24e", "1f24f", "1f250", + "1f251", "1f252", "1f253", "1f254", "1f255", "1f256", "1f257", "1f258", "1f259", "1f25a", + "1f25b", "1f25c", "1f25d", "1f25e", "1f25f", "1f260", "1f261", "1f262", "1f263", "1f264", + "1f265", "1f266", "1f267", "1f268", "1f269", "1f26a", "1f26b", "1f26c", "1f26d", "1f26e", + "1f26f", "1f270", "1f271", "1f272", "1f273", "1f274", "1f275", "1f276", "1f277", "1f278", + "1f279", "1f27a", "1f27b", "1f27c", "1f27d", "1f27e", "1f27f", "1f280", "1f281", "1f282", + "1f283", "1f284", "1f285", "1f286", "1f287", "1f288", "1f289", "1f28a", "1f28b", "1f28c", + "1f28d", "1f28e", "1f28f", "1f290", "1f291", "1f292", "1f293", "1f294", "1f295", "1f296", + "1f297", "1f298", "1f299", "1f29a", "1f29b", "1f29c", "1f29d", "1f29e", "1f29f", "1f2a0", + "1f2a1", "1f2a2", "1f2a3", "1f2a4", "1f2a5", "1f2a6", "1f2a7", "1f2a8", "1f2a9", "1f2aa", + "1f2ab", "1f2ac", "1f2ad", "1f2ae", "1f2af", "1f2b0", "1f2b1", "1f2b2", "1f2b3", "1f2b4", + "1f2b5", "1f2b6", "1f2b7", "1f2b8", "1f2b9", "1f2ba", "1f2bb", "1f2bc", "1f2bd", "1f2be", + "1f2bf", "1f2c0", "1f2c1", "1f2c2", "1f2c3", "1f2c4", "1f2c5", "1f2c6", "1f2c7", "1f2c8", + "1f2c9", "1f2ca", "1f2cb", "1f2cc", "1f2cd", "1f2ce", "1f2cf", "1f2d0", "1f2d1", "1f2d2", + "1f2d3", "1f2d4", "1f2d5", "1f2d6", "1f2d7", "1f2d8", "1f2d9", "1f2da", "1f2db", "1f2dc", + "1f2dd", "1f2de", "1f2df", "1f2e0", "1f2e1", "1f2e2", "1f2e3", "1f2e4", "1f2e5", "1f2e6", + "1f2e7", "1f2e8", "1f2e9", "1f2ea", "1f2eb", "1f2ec", "1f2ed", "1f2ee", "1f2ef", "1f2f0", + "1f2f1", "1f2f2", "1f2f3", "1f2f4", "1f2f5", "1f2f6", "1f2f7", "1f2f8", "1f2f9", "1f2fa", + "1f2fb", "1f2fc", "1f2fd", "1f2fe", "1f2ff", "1f300", "1f301", "1f302", "1f303", "1f304", + "1f305", "1f306", "1f307", "1f308", "1f309", "1f30a", "1f30b", "1f30c", "1f30d", "1f30e", + "1f30f", "1f310", "1f311", "1f312", "1f313", "1f314", "1f315", "1f316", "1f317", "1f318", + "1f319", "1f31a", "1f31b", "1f31c", "1f31d", "1f31e", "1f31f", "1f320", "1f321", "1f322", + "1f323", "1f324", "1f325", "1f326", "1f327", "1f328", "1f329", "1f32a", "1f32b", "1f32c", + "1f32d", "1f32e", "1f32f", "1f330", "1f331", "1f332", "1f333", "1f334", "1f335", "1f336", + "1f337", "1f338", "1f339", "1f33a", "1f33b", "1f33c", "1f33d", "1f33e", "1f33f", "1f340", + "1f341", "1f342", "1f343", "1f344", "1f345", "1f346", "1f347", "1f348", "1f349", "1f34a", + "1f34b", "1f34c", "1f34d", "1f34e", "1f34f", "1f350", "1f351", "1f352", "1f353", "1f354", + "1f355", "1f356", "1f357", "1f358", "1f359", "1f35a", "1f35b", "1f35c", "1f35d", "1f35e", + "1f35f", "1f360", "1f361", "1f362", "1f363", "1f364", "1f365", "1f366", "1f367", "1f368", + "1f369", "1f36a", "1f36b", "1f36c", "1f36d", "1f36e", "1f36f", "1f370", "1f371", "1f372", + "1f373", "1f374", "1f375", "1f376", "1f377", "1f378", "1f379", "1f37a", "1f37b", "1f37c", + "1f37d", "1f37e", "1f37f", "1f380", "1f381", "1f382", "1f383", "1f384", "1f385", "1f386", + "1f387", "1f388", "1f389", "1f38a", "1f38b", "1f38c", "1f38d", "1f38e", "1f38f", "1f390", + "1f391", "1f392", "1f393", "1f394", "1f395", "1f396", "1f397", "1f398", "1f399", "1f39a", + "1f39b", "1f39c", "1f39d", "1f39e", "1f39f", "1f3a0", "1f3a1", "1f3a2", "1f3a3", "1f3a4", + "1f3a5", "1f3a6", "1f3a7", "1f3a8", "1f3a9", "1f3aa", "1f3ab", "1f3ac", "1f3ad", "1f3ae", + "1f3af", "1f3b0", "1f3b1", "1f3b2", "1f3b3", "1f3b4", "1f3b5", "1f3b6", "1f3b7", "1f3b8", + "1f3b9", "1f3ba", "1f3bb", "1f3bc", "1f3bd", "1f3be", "1f3bf", "1f3c0", "1f3c1", "1f3c2", + "1f3c3", "1f3c4", "1f3c5", "1f3c6", "1f3c7", "1f3c8", "1f3c9", "1f3ca", "1f3cb", "1f3cc", + "1f3cd", "1f3ce", "1f3cf", "1f3d0", "1f3d1", "1f3d2", "1f3d3", "1f3d4", "1f3d5", "1f3d6", + "1f3d7", "1f3d8", "1f3d9", "1f3da", "1f3db", "1f3dc", "1f3dd", "1f3de", "1f3df", "1f3e0", + "1f3e1", "1f3e2", "1f3e3", "1f3e4", "1f3e5", "1f3e6", "1f3e7", "1f3e8", "1f3e9", "1f3ea", + "1f3eb", "1f3ec", "1f3ed", "1f3ee", "1f3ef", "1f3f0", "1f3f1", "1f3f2", "1f3f3", "1f3f4", + "1f3f5", "1f3f6", "1f3f7", "1f3f8", "1f3f9", "1f3fa", "1f3fb", "1f3fc", "1f3fd", "1f3fe", + "1f3ff", "1f400", "1f401", "1f402", "1f403", "1f404", "1f405", "1f406", "1f407", "1f408", + "1f409", "1f40a", "1f40b", "1f40c", "1f40d", "1f40e", "1f40f", "1f410", "1f411", "1f412", + "1f413", "1f414", "1f415", "1f416", "1f417", "1f418", "1f419", "1f41a", "1f41b", "1f41c", + "1f41d", "1f41e", "1f41f", "1f420", "1f421", "1f422", "1f423", "1f424", "1f425", "1f426", + "1f427", "1f428", "1f429", "1f42a", "1f42b", "1f42c", "1f42d", "1f42e", "1f42f", "1f430", + "1f431", "1f432", "1f433", "1f434", "1f435", "1f436", "1f437", "1f438", "1f439", "1f43a", + "1f43b", "1f43c", "1f43d", "1f43e", "1f43f", "1f440", "1f441", "1f442", "1f443", "1f444", + "1f445", "1f446", "1f447", "1f448", "1f449", "1f44a", "1f44b", "1f44c", "1f44d", "1f44e", + "1f44f", "1f450", "1f451", "1f452", "1f453", "1f454", "1f455", "1f456", "1f457", "1f458", + "1f459", "1f45a", "1f45b", "1f45c", "1f45d", "1f45e", "1f45f", "1f460", "1f461", "1f462", + "1f463", "1f464", "1f465", "1f466", "1f467", "1f468", "1f469", "1f46a", "1f46b", "1f46c", + "1f46d", "1f46e", "1f46f", "1f470", "1f471", "1f472", "1f473", "1f474", "1f475", "1f476", + "1f477", "1f478", "1f479", "1f47a", "1f47b", "1f47c", "1f47d", "1f47e", "1f47f", "1f480", + "1f481", "1f482", "1f483", "1f484", "1f485", "1f486", "1f487", "1f488", "1f489", "1f48a", + "1f48b", "1f48c", "1f48d", "1f48e", "1f48f", "1f490", "1f491", "1f492", "1f493", "1f494", + "1f495", "1f496", "1f497", "1f498", "1f499", "1f49a", "1f49b", "1f49c", "1f49d", "1f49e", + "1f49f", "1f4a0", "1f4a1", "1f4a2", "1f4a3", "1f4a4", "1f4a5", "1f4a6", "1f4a7", "1f4a8", + "1f4a9", "1f4aa", "1f4ab", "1f4ac", "1f4ad", "1f4ae", "1f4af", "1f4b0", "1f4b1", "1f4b2", + "1f4b3", "1f4b4", "1f4b5", "1f4b6", "1f4b7", "1f4b8", "1f4b9", "1f4ba", "1f4bb", "1f4bc", + "1f4bd", "1f4be", "1f4bf", "1f4c0", "1f4c1", "1f4c2", "1f4c3", "1f4c4", "1f4c5", "1f4c6", + "1f4c7", "1f4c8", "1f4c9", "1f4ca", "1f4cb", "1f4cc", "1f4cd", "1f4ce", "1f4cf", "1f4d0", + "1f4d1", "1f4d2", "1f4d3", "1f4d4", "1f4d5", "1f4d6", "1f4d7", "1f4d8", "1f4d9", "1f4da", + "1f4db", "1f4dc", "1f4dd", "1f4de", "1f4df", "1f4e0", "1f4e1", "1f4e2", "1f4e3", "1f4e4", + "1f4e5", "1f4e6", "1f4e7", "1f4e8", "1f4e9", "1f4ea", "1f4eb", "1f4ec", "1f4ed", "1f4ee", + "1f4ef", "1f4f0", "1f4f1", "1f4f2", "1f4f3", "1f4f4", "1f4f5", "1f4f6", "1f4f7", "1f4f8", + "1f4f9", "1f4fa", "1f4fb", "1f4fc", "1f4fd", "1f4fe", "1f4ff", "1f500", "1f501", "1f502", + "1f503", "1f504", "1f505", "1f506", "1f507", "1f508", "1f509", "1f50a", "1f50b", "1f50c", + "1f50d", "1f50e", "1f50f", "1f510", "1f511", "1f512", "1f513", "1f514", "1f515", "1f516", + "1f517", "1f518", "1f519", "1f51a", "1f51b", "1f51c", "1f51d", "1f51e", "1f51f", "1f520", + "1f521", "1f522", "1f523", "1f524", "1f525", "1f526", "1f527", "1f528", "1f529", "1f52a", + "1f52b", "1f52c", "1f52d", "1f52e", "1f52f", "1f530", "1f531", "1f532", "1f533", "1f534", + "1f535", "1f536", "1f537", "1f538", "1f539", "1f53a", "1f53b", "1f53c", "1f53d", "1f546", + "1f547", "1f548", "1f549", "1f54a", "1f54b", "1f54c", "1f54d", "1f54e", "1f54f", "1f550", + "1f551", "1f552", "1f553", "1f554", "1f555", "1f556", "1f557", "1f558", "1f559", "1f55a", + "1f55b", "1f55c", "1f55d", "1f55e", "1f55f", "1f560", "1f561", "1f562", "1f563", "1f564", + "1f565", "1f566", "1f567", "1f568", "1f569", "1f56a", "1f56b", "1f56c", "1f56d", "1f56e", + "1f56f", "1f570", "1f571", "1f572", "1f573", "1f574", "1f575", "1f576", "1f577", "1f578", + "1f579", "1f57a", "1f57b", "1f57c", "1f57d", "1f57e", "1f57f", "1f580", "1f581", "1f582", + "1f583", "1f584", "1f585", "1f586", "1f587", "1f588", "1f589", "1f58a", "1f58b", "1f58c", + "1f58d", "1f58e", "1f58f", "1f590", "1f591", "1f592", "1f593", "1f594", "1f595", "1f596", + "1f597", "1f598", "1f599", "1f59a", "1f59b", "1f59c", "1f59d", "1f59e", "1f59f", "1f5a0", + "1f5a1", "1f5a2", "1f5a3", "1f5a4", "1f5a5", "1f5a6", "1f5a7", "1f5a8", "1f5a9", "1f5aa", + "1f5ab", "1f5ac", "1f5ad", "1f5ae", "1f5af", "1f5b0", "1f5b1", "1f5b2", "1f5b3", "1f5b4", + "1f5b5", "1f5b6", "1f5b7", "1f5b8", "1f5b9", "1f5ba", "1f5bb", "1f5bc", "1f5bd", "1f5be", + "1f5bf", "1f5c0", "1f5c1", "1f5c2", "1f5c3", "1f5c4", "1f5c5", "1f5c6", "1f5c7", "1f5c8", + "1f5c9", "1f5ca", "1f5cb", "1f5cc", "1f5cd", "1f5ce", "1f5cf", "1f5d0", "1f5d1", "1f5d2", + "1f5d3", "1f5d4", "1f5d5", "1f5d6", "1f5d7", "1f5d8", "1f5d9", "1f5da", "1f5db", "1f5dc", + "1f5dd", "1f5de", "1f5df", "1f5e0", "1f5e1", "1f5e2", "1f5e3", "1f5e4", "1f5e5", "1f5e6", + "1f5e7", "1f5e8", "1f5e9", "1f5ea", "1f5eb", "1f5ec", "1f5ed", "1f5ee", "1f5ef", "1f5f0", + "1f5f1", "1f5f2", "1f5f3", "1f5f4", "1f5f5", "1f5f6", "1f5f7", "1f5f8", "1f5f9", "1f5fa", + "1f5fb", "1f5fc", "1f5fd", "1f5fe", "1f5ff", "1f600", "1f601", "1f602", "1f603", "1f604", + "1f605", "1f606", "1f607", "1f608", "1f609", "1f60a", "1f60b", "1f60c", "1f60d", "1f60e", + "1f60f", "1f610", "1f611", "1f612", "1f613", "1f614", "1f615", "1f616", "1f617", "1f618", + "1f619", "1f61a", "1f61b", "1f61c", "1f61d", "1f61e", "1f61f", "1f620", "1f621", "1f622", + "1f623", "1f624", "1f625", "1f626", "1f627", "1f628", "1f629", "1f62a", "1f62b", "1f62c", + "1f62d", "1f62e", "1f62f", "1f630", "1f631", "1f632", "1f633", "1f634", "1f635", "1f636", + "1f637", "1f638", "1f639", "1f63a", "1f63b", "1f63c", "1f63d", "1f63e", "1f63f", "1f640", + "1f641", "1f642", "1f643", "1f644", "1f645", "1f646", "1f647", "1f648", "1f649", "1f64a", + "1f64b", "1f64c", "1f64d", "1f64e", "1f64f", "1f680", "1f681", "1f682", "1f683", "1f684", + "1f685", "1f686", "1f687", "1f688", "1f689", "1f68a", "1f68b", "1f68c", "1f68d", "1f68e", + "1f68f", "1f690", "1f691", "1f692", "1f693", "1f694", "1f695", "1f696", "1f697", "1f698", + "1f699", "1f69a", "1f69b", "1f69c", "1f69d", "1f69e", "1f69f", "1f6a0", "1f6a1", "1f6a2", + "1f6a3", "1f6a4", "1f6a5", "1f6a6", "1f6a7", "1f6a8", "1f6a9", "1f6aa", "1f6ab", "1f6ac", + "1f6ad", "1f6ae", "1f6af", "1f6b0", "1f6b1", "1f6b2", "1f6b3", "1f6b4", "1f6b5", "1f6b6", + "1f6b7", "1f6b8", "1f6b9", "1f6ba", "1f6bb", "1f6bc", "1f6bd", "1f6be", "1f6bf", "1f6c0", + "1f6c1", "1f6c2", "1f6c3", "1f6c4", "1f6c5", "1f6c6", "1f6c7", "1f6c8", "1f6c9", "1f6ca", + "1f6cb", "1f6cc", "1f6cd", "1f6ce", "1f6cf", "1f6d0", "1f6d1", "1f6d2", "1f6d3", "1f6d4", + "1f6d5", "1f6d6", "1f6d7", "1f6d8", "1f6d9", "1f6da", "1f6db", "1f6dc", "1f6dd", "1f6de", + "1f6df", "1f6e0", "1f6e1", "1f6e2", "1f6e3", "1f6e4", "1f6e5", "1f6e6", "1f6e7", "1f6e8", + "1f6e9", "1f6ea", "1f6eb", "1f6ec", "1f6ed", "1f6ee", "1f6ef", "1f6f0", "1f6f1", "1f6f2", + "1f6f3", "1f6f4", "1f6f5", "1f6f6", "1f6f7", "1f6f8", "1f6f9", "1f6fa", "1f6fb", "1f6fc", + "1f6fd", "1f6fe", "1f6ff", "1f774", "1f775", "1f776", "1f777", "1f778", "1f779", "1f77a", + "1f77b", "1f77c", "1f77d", "1f77e", "1f77f", "1f7d5", "1f7d6", "1f7d7", "1f7d8", "1f7d9", + "1f7da", "1f7db", "1f7dc", "1f7dd", "1f7de", "1f7df", "1f7e0", "1f7e1", "1f7e2", "1f7e3", + "1f7e4", "1f7e5", "1f7e6", "1f7e7", "1f7e8", "1f7e9", "1f7ea", "1f7eb", "1f7ec", "1f7ed", + "1f7ee", "1f7ef", "1f7f0", "1f7f1", "1f7f2", "1f7f3", "1f7f4", "1f7f5", "1f7f6", "1f7f7", + "1f7f8", "1f7f9", "1f7fa", "1f7fb", "1f7fc", "1f7fd", "1f7fe", "1f7ff", "1f80c", "1f80d", + "1f80e", "1f80f", "1f848", "1f849", "1f84a", "1f84b", "1f84c", "1f84d", "1f84e", "1f84f", + "1f85a", "1f85b", "1f85c", "1f85d", "1f85e", "1f85f", "1f888", "1f889", "1f88a", "1f88b", + "1f88c", "1f88d", "1f88e", "1f88f", "1f8ae", "1f8af", "1f8b0", "1f8b1", "1f8b2", "1f8b3", + "1f8b4", "1f8b5", "1f8b6", "1f8b7", "1f8b8", "1f8b9", "1f8ba", "1f8bb", "1f8bc", "1f8bd", + "1f8be", "1f8bf", "1f8c0", "1f8c1", "1f8c2", "1f8c3", "1f8c4", "1f8c5", "1f8c6", "1f8c7", + "1f8c8", "1f8c9", "1f8ca", "1f8cb", "1f8cc", "1f8cd", "1f8ce", "1f8cf", "1f8d0", "1f8d1", + "1f8d2", "1f8d3", "1f8d4", "1f8d5", "1f8d6", "1f8d7", "1f8d8", "1f8d9", "1f8da", "1f8db", + "1f8dc", "1f8dd", "1f8de", "1f8df", "1f8e0", "1f8e1", "1f8e2", "1f8e3", "1f8e4", "1f8e5", + "1f8e6", "1f8e7", "1f8e8", "1f8e9", "1f8ea", "1f8eb", "1f8ec", "1f8ed", "1f8ee", "1f8ef", + "1f8f0", "1f8f1", "1f8f2", "1f8f3", "1f8f4", "1f8f5", "1f8f6", "1f8f7", "1f8f8", "1f8f9", + "1f8fa", "1f8fb", "1f8fc", "1f8fd", "1f8fe", "1f8ff", "1f90c", "1f90d", "1f90e", "1f90f", + "1f910", "1f911", "1f912", "1f913", "1f914", "1f915", "1f916", "1f917", "1f918", "1f919", + "1f91a", "1f91b", "1f91c", "1f91d", "1f91e", "1f91f", "1f920", "1f921", "1f922", "1f923", + "1f924", "1f925", "1f926", "1f927", "1f928", "1f929", "1f92a", "1f92b", "1f92c", "1f92d", + "1f92e", "1f92f", "1f930", "1f931", "1f932", "1f933", "1f934", "1f935", "1f936", "1f937", + "1f938", "1f939", "1f93a", "1f93c", "1f93d", "1f93e", "1f93f", "1f940", "1f941", "1f942", + "1f943", "1f944", "1f945", "1f947", "1f948", "1f949", "1f94a", "1f94b", "1f94c", "1f94d", + "1f94e", "1f94f", "1f950", "1f951", "1f952", "1f953", "1f954", "1f955", "1f956", "1f957", + "1f958", "1f959", "1f95a", "1f95b", "1f95c", "1f95d", "1f95e", "1f95f", "1f960", "1f961", + "1f962", "1f963", "1f964", "1f965", "1f966", "1f967", "1f968", "1f969", "1f96a", "1f96b", + "1f96c", "1f96d", "1f96e", "1f96f", "1f970", "1f971", "1f972", "1f973", "1f974", "1f975", + "1f976", "1f977", "1f978", "1f979", "1f97a", "1f97b", "1f97c", "1f97d", "1f97e", "1f97f", + "1f980", "1f981", "1f982", "1f983", "1f984", "1f985", "1f986", "1f987", "1f988", "1f989", + "1f98a", "1f98b", "1f98c", "1f98d", "1f98e", "1f98f", "1f990", "1f991", "1f992", "1f993", + "1f994", "1f995", "1f996", "1f997", "1f998", "1f999", "1f99a", "1f99b", "1f99c", "1f99d", + "1f99e", "1f99f", "1f9a0", "1f9a1", "1f9a2", "1f9a3", "1f9a4", "1f9a5", "1f9a6", "1f9a7", + "1f9a8", "1f9a9", "1f9aa", "1f9ab", "1f9ac", "1f9ad", "1f9ae", "1f9af", "1f9b0", "1f9b1", + "1f9b2", "1f9b3", "1f9b4", "1f9b5", "1f9b6", "1f9b7", "1f9b8", "1f9b9", "1f9ba", "1f9bb", + "1f9bc", "1f9bd", "1f9be", "1f9bf", "1f9c0", "1f9c1", "1f9c2", "1f9c3", "1f9c4", "1f9c5", + "1f9c6", "1f9c7", "1f9c8", "1f9c9", "1f9ca", "1f9cb", "1f9cc", "1f9cd", "1f9ce", "1f9cf", + "1f9d0", "1f9d1", "1f9d2", "1f9d3", "1f9d4", "1f9d5", "1f9d6", "1f9d7", "1f9d8", "1f9d9", + "1f9da", "1f9db", "1f9dc", "1f9dd", "1f9de", "1f9df", "1f9e0", "1f9e1", "1f9e2", "1f9e3", + "1f9e4", "1f9e5", "1f9e6", "1f9e7", "1f9e8", "1f9e9", "1f9ea", "1f9eb", "1f9ec", "1f9ed", + "1f9ee", "1f9ef", "1f9f0", "1f9f1", "1f9f2", "1f9f3", "1f9f4", "1f9f5", "1f9f6", "1f9f7", + "1f9f8", "1f9f9", "1f9fa", "1f9fb", "1f9fc", "1f9fd", "1f9fe", "1f9ff", "1fa00", "1fa01", + "1fa02", "1fa03", "1fa04", "1fa05", "1fa06", "1fa07", "1fa08", "1fa09", "1fa0a", "1fa0b", + "1fa0c", "1fa0d", "1fa0e", "1fa0f", "1fa10", "1fa11", "1fa12", "1fa13", "1fa14", "1fa15", + "1fa16", "1fa17", "1fa18", "1fa19", "1fa1a", "1fa1b", "1fa1c", "1fa1d", "1fa1e", "1fa1f", + "1fa20", "1fa21", "1fa22", "1fa23", "1fa24", "1fa25", "1fa26", "1fa27", "1fa28", "1fa29", + "1fa2a", "1fa2b", "1fa2c", "1fa2d", "1fa2e", "1fa2f", "1fa30", "1fa31", "1fa32", "1fa33", + "1fa34", "1fa35", "1fa36", "1fa37", "1fa38", "1fa39", "1fa3a", "1fa3b", "1fa3c", "1fa3d", + "1fa3e", "1fa3f", "1fa40", "1fa41", "1fa42", "1fa43", "1fa44", "1fa45", "1fa46", "1fa47", + "1fa48", "1fa49", "1fa4a", "1fa4b", "1fa4c", "1fa4d", "1fa4e", "1fa4f", "1fa50", "1fa51", + "1fa52", "1fa53", "1fa54", "1fa55", "1fa56", "1fa57", "1fa58", "1fa59", "1fa5a", "1fa5b", + "1fa5c", "1fa5d", "1fa5e", "1fa5f", "1fa60", "1fa61", "1fa62", "1fa63", "1fa64", "1fa65", + "1fa66", "1fa67", "1fa68", "1fa69", "1fa6a", "1fa6b", "1fa6c", "1fa6d", "1fa6e", "1fa6f", + "1fa70", "1fa71", "1fa72", "1fa73", "1fa74", "1fa75", "1fa76", "1fa77", "1fa78", "1fa79", + "1fa7a", "1fa7b", "1fa7c", "1fa7d", "1fa7e", "1fa7f", "1fa80", "1fa81", "1fa82", "1fa83", + "1fa84", "1fa85", "1fa86", "1fa87", "1fa88", "1fa89", "1fa8a", "1fa8b", "1fa8c", "1fa8d", + "1fa8e", "1fa8f", "1fa90", "1fa91", "1fa92", "1fa93", "1fa94", "1fa95", "1fa96", "1fa97", + "1fa98", "1fa99", "1fa9a", "1fa9b", "1fa9c", "1fa9d", "1fa9e", "1fa9f", "1faa0", "1faa1", + "1faa2", "1faa3", "1faa4", "1faa5", "1faa6", "1faa7", "1faa8", "1faa9", "1faaa", "1faab", + "1faac", "1faad", "1faae", "1faaf", "1fab0", "1fab1", "1fab2", "1fab3", "1fab4", "1fab5", + "1fab6", "1fab7", "1fab8", "1fab9", "1faba", "1fabb", "1fabc", "1fabd", "1fabe", "1fabf", + "1fac0", "1fac1", "1fac2", "1fac3", "1fac4", "1fac5", "1fac6", "1fac7", "1fac8", "1fac9", + "1faca", "1facb", "1facc", "1facd", "1face", "1facf", "1fad0", "1fad1", "1fad2", "1fad3", + "1fad4", "1fad5", "1fad6", "1fad7", "1fad8", "1fad9", "1fada", "1fadb", "1fadc", "1fadd", + "1fade", "1fadf", "1fae0", "1fae1", "1fae2", "1fae3", "1fae4", "1fae5", "1fae6", "1fae7", + "1fae8", "1fae9", "1faea", "1faeb", "1faec", "1faed", "1faee", "1faef", "1faf0", "1faf1", + "1faf2", "1faf3", "1faf4", "1faf5", "1faf6", "1faf7", "1faf8", "1faf9", "1fafa", "1fafb", + "1fafc", "1fafd", "1fafe", "1faff", "1fb00", "1fb01", "1fb02", "1fb03", "1fb04", "1fb05", + "1fb06", "1fb07", "1fb08", "1fb09", "1fb0a", "1fb0b", "1fb0c", "1fb0d", "1fb0e", "1fb0f", + "1fb10", "1fb11", "1fb12", "1fb13", "1fb14", "1fb15", "1fb16", "1fb17", "1fb18", "1fb19", + "1fb1a", "1fb1b", "1fb1c", "1fb1d", "1fb1e", "1fb1f", "1fb20", "1fb21", "1fb22", "1fb23", + "1fb24", "1fb25", "1fb26", "1fb27", "1fb28", "1fb29", "1fb2a", "1fb2b", "1fb2c", "1fb2d", + "1fb2e", "1fb2f", "1fb30", "1fb31", "1fb32", "1fb33", "1fb34", "1fb35", "1fb36", "1fb37", + "1fb38", "1fb39", "1fb3a", "1fb3b", "1fb3c", "1fb3d", "1fb3e", "1fb3f", "1fb40", "1fb41", + "1fb42", "1fb43", "1fb44", "1fb45", "1fb46", "1fb47", "1fb48", "1fb49", "1fb4a", "1fb4b", + "1fb4c", "1fb4d", "1fb4e", "1fb4f", "1fb50", "1fb51", "1fb52", "1fb53", "1fb54", "1fb55", + "1fb56", "1fb57", "1fb58", "1fb59", "1fb5a", "1fb5b", "1fb5c", "1fb5d", "1fb5e", "1fb5f", + "1fb60", "1fb61", "1fb62", "1fb63", "1fb64", "1fb65", "1fb66", "1fb67", "1fb68", "1fb69", + "1fb6a", "1fb6b", "1fb6c", "1fb6d", "1fb6e", "1fb6f", "1fb70", "1fb71", "1fb72", "1fb73", + "1fb74", "1fb75", "1fb76", "1fb77", "1fb78", "1fb79", "1fb7a", "1fb7b", "1fb7c", "1fb7d", + "1fb7e", "1fb7f", "1fb80", "1fb81", "1fb82", "1fb83", "1fb84", "1fb85", "1fb86", "1fb87", + "1fb88", "1fb89", "1fb8a", "1fb8b", "1fb8c", "1fb8d", "1fb8e", "1fb8f", "1fb90", "1fb91", + "1fb92", "1fb93", "1fb94", "1fb95", "1fb96", "1fb97", "1fb98", "1fb99", "1fb9a", "1fb9b", + "1fb9c", "1fb9d", "1fb9e", "1fb9f", "1fba0", "1fba1", "1fba2", "1fba3", "1fba4", "1fba5", + "1fba6", "1fba7", "1fba8", "1fba9", "1fbaa", "1fbab", "1fbac", "1fbad", "1fbae", "1fbaf", + "1fbb0", "1fbb1", "1fbb2", "1fbb3", "1fbb4", "1fbb5", "1fbb6", "1fbb7", "1fbb8", "1fbb9", + "1fbba", "1fbbb", "1fbbc", "1fbbd", "1fbbe", "1fbbf", "1fbc0", "1fbc1", "1fbc2", "1fbc3", + "1fbc4", "1fbc5", "1fbc6", "1fbc7", "1fbc8", "1fbc9", "1fbca", "1fbcb", "1fbcc", "1fbcd", + "1fbce", "1fbcf", "1fbd0", "1fbd1", "1fbd2", "1fbd3", "1fbd4", "1fbd5", "1fbd6", "1fbd7", + "1fbd8", "1fbd9", "1fbda", "1fbdb", "1fbdc", "1fbdd", "1fbde", "1fbdf", "1fbe0", "1fbe1", + "1fbe2", "1fbe3", "1fbe4", "1fbe5", "1fbe6", "1fbe7", "1fbe8", "1fbe9", "1fbea", "1fbeb", + "1fbec", "1fbed", "1fbee", "1fbef", "1fbf0", "1fbf1", "1fbf2", "1fbf3", "1fbf4", "1fbf5", + "1fbf6", "1fbf7", "1fbf8", "1fbf9", "1fbfa", "1fbfb", "1fbfc", "1fbfd", "1fbfe", "1fbff", + "1fc00", "1fc01", "1fc02", "1fc03", "1fc04", "1fc05", "1fc06", "1fc07", "1fc08", "1fc09", + "1fc0a", "1fc0b", "1fc0c", "1fc0d", "1fc0e", "1fc0f", "1fc10", "1fc11", "1fc12", "1fc13", + "1fc14", "1fc15", "1fc16", "1fc17", "1fc18", "1fc19", "1fc1a", "1fc1b", "1fc1c", "1fc1d", + "1fc1e", "1fc1f", "1fc20", "1fc21", "1fc22", "1fc23", "1fc24", "1fc25", "1fc26", "1fc27", + "1fc28", "1fc29", "1fc2a", "1fc2b", "1fc2c", "1fc2d", "1fc2e", "1fc2f", "1fc30", "1fc31", + "1fc32", "1fc33", "1fc34", "1fc35", "1fc36", "1fc37", "1fc38", "1fc39", "1fc3a", "1fc3b", + "1fc3c", "1fc3d", "1fc3e", "1fc3f", "1fc40", "1fc41", "1fc42", "1fc43", "1fc44", "1fc45", + "1fc46", "1fc47", "1fc48", "1fc49", "1fc4a", "1fc4b", "1fc4c", "1fc4d", "1fc4e", "1fc4f", + "1fc50", "1fc51", "1fc52", "1fc53", "1fc54", "1fc55", "1fc56", "1fc57", "1fc58", "1fc59", + "1fc5a", "1fc5b", "1fc5c", "1fc5d", "1fc5e", "1fc5f", "1fc60", "1fc61", "1fc62", "1fc63", + "1fc64", "1fc65", "1fc66", "1fc67", "1fc68", "1fc69", "1fc6a", "1fc6b", "1fc6c", "1fc6d", + "1fc6e", "1fc6f", "1fc70", "1fc71", "1fc72", "1fc73", "1fc74", "1fc75", "1fc76", "1fc77", + "1fc78", "1fc79", "1fc7a", "1fc7b", "1fc7c", "1fc7d", "1fc7e", "1fc7f", "1fc80", "1fc81", + "1fc82", "1fc83", "1fc84", "1fc85", "1fc86", "1fc87", "1fc88", "1fc89", "1fc8a", "1fc8b", + "1fc8c", "1fc8d", "1fc8e", "1fc8f", "1fc90", "1fc91", "1fc92", "1fc93", "1fc94", "1fc95", + "1fc96", "1fc97", "1fc98", "1fc99", "1fc9a", "1fc9b", "1fc9c", "1fc9d", "1fc9e", "1fc9f", + "1fca0", "1fca1", "1fca2", "1fca3", "1fca4", "1fca5", "1fca6", "1fca7", "1fca8", "1fca9", + "1fcaa", "1fcab", "1fcac", "1fcad", "1fcae", "1fcaf", "1fcb0", "1fcb1", "1fcb2", "1fcb3", + "1fcb4", "1fcb5", "1fcb6", "1fcb7", "1fcb8", "1fcb9", "1fcba", "1fcbb", "1fcbc", "1fcbd", + "1fcbe", "1fcbf", "1fcc0", "1fcc1", "1fcc2", "1fcc3", "1fcc4", "1fcc5", "1fcc6", "1fcc7", + "1fcc8", "1fcc9", "1fcca", "1fccb", "1fccc", "1fccd", "1fcce", "1fccf", "1fcd0", "1fcd1", + "1fcd2", "1fcd3", "1fcd4", "1fcd5", "1fcd6", "1fcd7", "1fcd8", "1fcd9", "1fcda", "1fcdb", + "1fcdc", "1fcdd", "1fcde", "1fcdf", "1fce0", "1fce1", "1fce2", "1fce3", "1fce4", "1fce5", + "1fce6", "1fce7", "1fce8", "1fce9", "1fcea", "1fceb", "1fcec", "1fced", "1fcee", "1fcef", + "1fcf0", "1fcf1", "1fcf2", "1fcf3", "1fcf4", "1fcf5", "1fcf6", "1fcf7", "1fcf8", "1fcf9", + "1fcfa", "1fcfb", "1fcfc", "1fcfd", "1fcfe", "1fcff", "1fd00", "1fd01", "1fd02", "1fd03", + "1fd04", "1fd05", "1fd06", "1fd07", "1fd08", "1fd09", "1fd0a", "1fd0b", "1fd0c", "1fd0d", + "1fd0e", "1fd0f", "1fd10", "1fd11", "1fd12", "1fd13", "1fd14", "1fd15", "1fd16", "1fd17", + "1fd18", "1fd19", "1fd1a", "1fd1b", "1fd1c", "1fd1d", "1fd1e", "1fd1f", "1fd20", "1fd21", + "1fd22", "1fd23", "1fd24", "1fd25", "1fd26", "1fd27", "1fd28", "1fd29", "1fd2a", "1fd2b", + "1fd2c", "1fd2d", "1fd2e", "1fd2f", "1fd30", "1fd31", "1fd32", "1fd33", "1fd34", "1fd35", + "1fd36", "1fd37", "1fd38", "1fd39", "1fd3a", "1fd3b", "1fd3c", "1fd3d", "1fd3e", "1fd3f", + "1fd40", "1fd41", "1fd42", "1fd43", "1fd44", "1fd45", "1fd46", "1fd47", "1fd48", "1fd49", + "1fd4a", "1fd4b", "1fd4c", "1fd4d", "1fd4e", "1fd4f", "1fd50", "1fd51", "1fd52", "1fd53", + "1fd54", "1fd55", "1fd56", "1fd57", "1fd58", "1fd59", "1fd5a", "1fd5b", "1fd5c", "1fd5d", + "1fd5e", "1fd5f", "1fd60", "1fd61", "1fd62", "1fd63", "1fd64", "1fd65", "1fd66", "1fd67", + "1fd68", "1fd69", "1fd6a", "1fd6b", "1fd6c", "1fd6d", "1fd6e", "1fd6f", "1fd70", "1fd71", + "1fd72", "1fd73", "1fd74", "1fd75", "1fd76", "1fd77", "1fd78", "1fd79", "1fd7a", "1fd7b", + "1fd7c", "1fd7d", "1fd7e", "1fd7f", "1fd80", "1fd81", "1fd82", "1fd83", "1fd84", "1fd85", + "1fd86", "1fd87", "1fd88", "1fd89", "1fd8a", "1fd8b", "1fd8c", "1fd8d", "1fd8e", "1fd8f", + "1fd90", "1fd91", "1fd92", "1fd93", "1fd94", "1fd95", "1fd96", "1fd97", "1fd98", "1fd99", + "1fd9a", "1fd9b", "1fd9c", "1fd9d", "1fd9e", "1fd9f", "1fda0", "1fda1", "1fda2", "1fda3", + "1fda4", "1fda5", "1fda6", "1fda7", "1fda8", "1fda9", "1fdaa", "1fdab", "1fdac", "1fdad", + "1fdae", "1fdaf", "1fdb0", "1fdb1", "1fdb2", "1fdb3", "1fdb4", "1fdb5", "1fdb6", "1fdb7", + "1fdb8", "1fdb9", "1fdba", "1fdbb", "1fdbc", "1fdbd", "1fdbe", "1fdbf", "1fdc0", "1fdc1", + "1fdc2", "1fdc3", "1fdc4", "1fdc5", "1fdc6", "1fdc7", "1fdc8", "1fdc9", "1fdca", "1fdcb", + "1fdcc", "1fdcd", "1fdce", "1fdcf", "1fdd0", "1fdd1", "1fdd2", "1fdd3", "1fdd4", "1fdd5", + "1fdd6", "1fdd7", "1fdd8", "1fdd9", "1fdda", "1fddb", "1fddc", "1fddd", "1fdde", "1fddf", + "1fde0", "1fde1", "1fde2", "1fde3", "1fde4", "1fde5", "1fde6", "1fde7", "1fde8", "1fde9", + "1fdea", "1fdeb", "1fdec", "1fded", "1fdee", "1fdef", "1fdf0", "1fdf1", "1fdf2", "1fdf3", + "1fdf4", "1fdf5", "1fdf6", "1fdf7", "1fdf8", "1fdf9", "1fdfa", "1fdfb", "1fdfc", "1fdfd", + "1fdfe", "1fdff", "1fe00", "1fe01", "1fe02", "1fe03", "1fe04", "1fe05", "1fe06", "1fe07", + "1fe08", "1fe09", "1fe0a", "1fe0b", "1fe0c", "1fe0d", "1fe0e", "1fe0f", "1fe10", "1fe11", + "1fe12", "1fe13", "1fe14", "1fe15", "1fe16", "1fe17", "1fe18", "1fe19", "1fe1a", "1fe1b", + "1fe1c", "1fe1d", "1fe1e", "1fe1f", "1fe20", "1fe21", "1fe22", "1fe23", "1fe24", "1fe25", + "1fe26", "1fe27", "1fe28", "1fe29", "1fe2a", "1fe2b", "1fe2c", "1fe2d", "1fe2e", "1fe2f", + "1fe30", "1fe31", "1fe32", "1fe33", "1fe34", "1fe35", "1fe36", "1fe37", "1fe38", "1fe39", + "1fe3a", "1fe3b", "1fe3c", "1fe3d", "1fe3e", "1fe3f", "1fe40", "1fe41", "1fe42", "1fe43", + "1fe44", "1fe45", "1fe46", "1fe47", "1fe48", "1fe49", "1fe4a", "1fe4b", "1fe4c", "1fe4d", + "1fe4e", "1fe4f", "1fe50", "1fe51", "1fe52", "1fe53", "1fe54", "1fe55", "1fe56", "1fe57", + "1fe58", "1fe59", "1fe5a", "1fe5b", "1fe5c", "1fe5d", "1fe5e", "1fe5f", "1fe60", "1fe61", + "1fe62", "1fe63", "1fe64", "1fe65", "1fe66", "1fe67", "1fe68", "1fe69", "1fe6a", "1fe6b", + "1fe6c", "1fe6d", "1fe6e", "1fe6f", "1fe70", "1fe71", "1fe72", "1fe73", "1fe74", "1fe75", + "1fe76", "1fe77", "1fe78", "1fe79", "1fe7a", "1fe7b", "1fe7c", "1fe7d", "1fe7e", "1fe7f", + "1fe80", "1fe81", "1fe82", "1fe83", "1fe84", "1fe85", "1fe86", "1fe87", "1fe88", "1fe89", + "1fe8a", "1fe8b", "1fe8c", "1fe8d", "1fe8e", "1fe8f", "1fe90", "1fe91", "1fe92", "1fe93", + "1fe94", "1fe95", "1fe96", "1fe97", "1fe98", "1fe99", "1fe9a", "1fe9b", "1fe9c", "1fe9d", + "1fe9e", "1fe9f", "1fea0", "1fea1", "1fea2", "1fea3", "1fea4", "1fea5", "1fea6", "1fea7", + "1fea8", "1fea9", "1feaa", "1feab", "1feac", "1fead", "1feae", "1feaf", "1feb0", "1feb1", + "1feb2", "1feb3", "1feb4", "1feb5", "1feb6", "1feb7", "1feb8", "1feb9", "1feba", "1febb", + "1febc", "1febd", "1febe", "1febf", "1fec0", "1fec1", "1fec2", "1fec3", "1fec4", "1fec5", + "1fec6", "1fec7", "1fec8", "1fec9", "1feca", "1fecb", "1fecc", "1fecd", "1fece", "1fecf", + "1fed0", "1fed1", "1fed2", "1fed3", "1fed4", "1fed5", "1fed6", "1fed7", "1fed8", "1fed9", + "1feda", "1fedb", "1fedc", "1fedd", "1fede", "1fedf", "1fee0", "1fee1", "1fee2", "1fee3", + "1fee4", "1fee5", "1fee6", "1fee7", "1fee8", "1fee9", "1feea", "1feeb", "1feec", "1feed", + "1feee", "1feef", "1fef0", "1fef1", "1fef2", "1fef3", "1fef4", "1fef5", "1fef6", "1fef7", + "1fef8", "1fef9", "1fefa", "1fefb", "1fefc", "1fefd", "1fefe", "1feff", "1ff00", "1ff01", + "1ff02", "1ff03", "1ff04", "1ff05", "1ff06", "1ff07", "1ff08", "1ff09", "1ff0a", "1ff0b", + "1ff0c", "1ff0d", "1ff0e", "1ff0f", "1ff10", "1ff11", "1ff12", "1ff13", "1ff14", "1ff15", + "1ff16", "1ff17", "1ff18", "1ff19", "1ff1a", "1ff1b", "1ff1c", "1ff1d", "1ff1e", "1ff1f", + "1ff20", "1ff21", "1ff22", "1ff23", "1ff24", "1ff25", "1ff26", "1ff27", "1ff28", "1ff29", + "1ff2a", "1ff2b", "1ff2c", "1ff2d", "1ff2e", "1ff2f", "1ff30", "1ff31", "1ff32", "1ff33", + "1ff34", "1ff35", "1ff36", "1ff37", "1ff38", "1ff39", "1ff3a", "1ff3b", "1ff3c", "1ff3d", + "1ff3e", "1ff3f", "1ff40", "1ff41", "1ff42", "1ff43", "1ff44", "1ff45", "1ff46", "1ff47", + "1ff48", "1ff49", "1ff4a", "1ff4b", "1ff4c", "1ff4d", "1ff4e", "1ff4f", "1ff50", "1ff51", + "1ff52", "1ff53", "1ff54", "1ff55", "1ff56", "1ff57", "1ff58", "1ff59", "1ff5a", "1ff5b", + "1ff5c", "1ff5d", "1ff5e", "1ff5f", "1ff60", "1ff61", "1ff62", "1ff63", "1ff64", "1ff65", + "1ff66", "1ff67", "1ff68", "1ff69", "1ff6a", "1ff6b", "1ff6c", "1ff6d", "1ff6e", "1ff6f", + "1ff70", "1ff71", "1ff72", "1ff73", "1ff74", "1ff75", "1ff76", "1ff77", "1ff78", "1ff79", + "1ff7a", "1ff7b", "1ff7c", "1ff7d", "1ff7e", "1ff7f", "1ff80", "1ff81", "1ff82", "1ff83", + "1ff84", "1ff85", "1ff86", "1ff87", "1ff88", "1ff89", "1ff8a", "1ff8b", "1ff8c", "1ff8d", + "1ff8e", "1ff8f", "1ff90", "1ff91", "1ff92", "1ff93", "1ff94", "1ff95", "1ff96", "1ff97", + "1ff98", "1ff99", "1ff9a", "1ff9b", "1ff9c", "1ff9d", "1ff9e", "1ff9f", "1ffa0", "1ffa1", + "1ffa2", "1ffa3", "1ffa4", "1ffa5", "1ffa6", "1ffa7", "1ffa8", "1ffa9", "1ffaa", "1ffab", + "1ffac", "1ffad", "1ffae", "1ffaf", "1ffb0", "1ffb1", "1ffb2", "1ffb3", "1ffb4", "1ffb5", + "1ffb6", "1ffb7", "1ffb8", "1ffb9", "1ffba", "1ffbb", "1ffbc", "1ffbd", "1ffbe", "1ffbf", + "1ffc0", "1ffc1", "1ffc2", "1ffc3", "1ffc4", "1ffc5", "1ffc6", "1ffc7", "1ffc8", "1ffc9", + "1ffca", "1ffcb", "1ffcc", "1ffcd", "1ffce", "1ffcf", "1ffd0", "1ffd1", "1ffd2", "1ffd3", + "1ffd4", "1ffd5", "1ffd6", "1ffd7", "1ffd8", "1ffd9", "1ffda", "1ffdb", "1ffdc", "1ffdd", + "1ffde", "1ffdf", "1ffe0", "1ffe1", "1ffe2", "1ffe3", "1ffe4", "1ffe5", "1ffe6", "1ffe7", + "1ffe8", "1ffe9", "1ffea", "1ffeb", "1ffec", "1ffed", "1ffee", "1ffef", "1fff0", "1fff1", + "1fff2", "1fff3", "1fff4", "1fff5", "1fff6", "1fff7", "1fff8", "1fff9", "1fffa", "1fffb", + "1fffc", "1fffd", "200d", "203c", "2049", "20e3", "2122", "2139", "2194", "2195", + "2196", "2197", "2198", "2199", "21a9", "21aa", "231a", "231b", "2328", "2388", + "23cf", "23e9", "23ea", "23eb", "23ec", "23ed", "23ee", "23ef", "23f0", "23f1", + "23f2", "23f3", "23f8", "23f9", "23fa", "24c2", "25aa", "25ab", "25b6", "25c0", + "25fb", "25fc", "25fd", "25fe", "2600", "2601", "2602", "2603", "2604", "2605", + "2607", "2608", "2609", "260a", "260b", "260c", "260d", "260e", "260f", "2610", + "2611", "2612", "2614", "2615", "2616", "2617", "2618", "2619", "261a", "261b", + "261c", "261d", "261e", "261f", "2620", "2621", "2622", "2623", "2624", "2625", + "2626", "2627", "2628", "2629", "262a", "262b", "262c", "262d", "262e", "262f", + "2630", "2631", "2632", "2633", "2634", "2635", "2636", "2637", "2638", "2639", + "263a", "263b", "263c", "263d", "263e", "263f", "2640", "2641", "2642", "2643", + "2644", "2645", "2646", "2647", "2648", "2649", "264a", "264b", "264c", "264d", + "264e", "264f", "2650", "2651", "2652", "2653", "2654", "2655", "2656", "2657", + "2658", "2659", "265a", "265b", "265c", "265d", "265e", "265f", "2660", "2661", + "2662", "2663", "2664", "2665", "2666", "2667", "2668", "2669", "266a", "266b", + "266c", "266d", "266e", "266f", "2670", "2671", "2672", "2673", "2674", "2675", + "2676", "2677", "2678", "2679", "267a", "267b", "267c", "267d", "267e", "267f", + "2680", "2681", "2682", "2683", "2684", "2685", "2690", "2691", "2692", "2693", + "2694", "2695", "2696", "2697", "2698", "2699", "269a", "269b", "269c", "269d", + "269e", "269f", "26a0", "26a1", "26a2", "26a3", "26a4", "26a5", "26a6", "26a7", + "26a8", "26a9", "26aa", "26ab", "26ac", "26ad", "26ae", "26af", "26b0", "26b1", + "26b2", "26b3", "26b4", "26b5", "26b6", "26b7", "26b8", "26b9", "26ba", "26bb", + "26bc", "26bd", "26be", "26bf", "26c0", "26c1", "26c2", "26c3", "26c4", "26c5", + "26c6", "26c7", "26c8", "26c9", "26ca", "26cb", "26cc", "26cd", "26ce", "26cf", + "26d0", "26d1", "26d2", "26d3", "26d4", "26d5", "26d6", "26d7", "26d8", "26d9", + "26da", "26db", "26dc", "26dd", "26de", "26df", "26e0", "26e1", "26e2", "26e3", + "26e4", "26e5", "26e6", "26e7", "26e8", "26e9", "26ea", "26eb", "26ec", "26ed", + "26ee", "26ef", "26f0", "26f1", "26f2", "26f3", "26f4", "26f5", "26f6", "26f7", + "26f8", "26f9", "26fa", "26fb", "26fc", "26fd", "26fe", "26ff", "2700", "2701", + "2702", "2703", "2704", "2705", "2708", "2709", "270a", "270b", "270c", "270d", + "270e", "270f", "2710", "2711", "2712", "2714", "2716", "271d", "2721", "2728", + "2733", "2734", "2744", "2747", "274c", "274e", "2753", "2754", "2755", "2757", + "2763", "2764", "2765", "2766", "2767", "2795", "2796", "2797", "27a1", "27b0", + "27bf", "2934", "2935", "2b05", "2b06", "2b07", "2b1b", "2b1c", "2b50", "2b55", + "3030", "303d", "3297", "3299", "e0020", "e0021", "e0022", "e0023", "e0024", "e0025", + "e0026", "e0027", "e0028", "e0029", "e002a", "e002b", "e002c", "e002d", "e002e", "e002f", + "e0030", "e0031", "e0032", "e0033", "e0034", "e0035", "e0036", "e0037", "e0038", "e0039", + "e003a", "e003b", "e003c", "e003d", "e003e", "e003f", "e0040", "e0041", "e0042", "e0043", + "e0044", "e0045", "e0046", "e0047", "e0048", "e0049", "e004a", "e004b", "e004c", "e004d", + "e004e", "e004f", "e0050", "e0051", "e0052", "e0053", "e0054", "e0055", "e0056", "e0057", + "e0058", "e0059", "e005a", "e005b", "e005c", "e005d", "e005e", "e005f", "e0060", "e0061", + "e0062", "e0063", "e0064", "e0065", "e0066", "e0067", "e0068", "e0069", "e006a", "e006b", + "e006c", "e006d", "e006e", "e006f", "e0070", "e0071", "e0072", "e0073", "e0074", "e0075", + "e0076", "e0077", "e0078", "e0079", "e007a", "e007b", "e007c", "e007d", "e007e", "e007f", + "fe0f")); + + private static String toHexStr(char c) { + return Integer.toHexString(c); + } + + private static String toHexStr(int c) { + return Integer.toHexString(c); + } + + public static boolean containsEmoji(String str) { + // unicode can be at most 2 Java Char(utf-16), use code point + int cpCnt = str.codePointCount(0, str.length()); + for (int index = 0; index < cpCnt; ++index) { + // i is index by code point + int i = str.offsetByCodePoints(0, index); + int codepoint = str.codePointAt(i); + if (EMOJI_HASH_SET.contains(toHexStr(codepoint))) { + return true; + } + } + + return false; + } + + public static String removeEmoji(String str) { + StringBuilder sb = new StringBuilder(); + // unicode can be at most 2 Java Char(utf-16), use code point + int cpCnt = str.codePointCount(0, str.length()); + for (int index = 0; index < cpCnt; ++index) { + // i is index by code point + int i = str.offsetByCodePoints(0, index); + int codepoint = str.codePointAt(i); + if (!EMOJI_HASH_SET.contains(toHexStr(codepoint))) { + // code point back to char + sb.append(Character.toChars(codepoint)); + } + } + return sb.toString(); + } + +} \ No newline at end of file diff --git a/gwt-material/src/main/java/gwt/material/design/client/theme/GlobalThemeConfig.java b/gwt-material/src/main/java/gwt/material/design/client/theme/GlobalThemeConfig.java new file mode 100644 index 000000000..73890de48 --- /dev/null +++ b/gwt-material/src/main/java/gwt/material/design/client/theme/GlobalThemeConfig.java @@ -0,0 +1,35 @@ +/* + * #%L + * GwtMaterial + * %% + * Copyright (C) 2015 - 2023 GwtMaterialDesign + * %% + * 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. + * #L% + */ +package gwt.material.design.client.theme; + +import gwt.material.design.client.constants.IconDisplay; + +public class GlobalThemeConfig { + + protected IconDisplay iconDisplay = IconDisplay.FILLED; + + public IconDisplay getIconDisplay() { + return iconDisplay; + } + + public void setIconDisplay(IconDisplay iconDisplay) { + this.iconDisplay = iconDisplay; + } +} diff --git a/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialChip.java b/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialChip.java index 40d2b34b3..3587ce552 100644 --- a/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialChip.java +++ b/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialChip.java @@ -74,10 +74,15 @@ public class MaterialChip extends AbstractValueWidget implements HasImag private LetterMixin letterMixin; private CssTypeMixin typeMixin; private ActiveMixin activeMixin; + private MaterialIcon prefixIcon = new MaterialIcon(IconType.CHECK); + private boolean enablePrefixIcon; public MaterialChip() { super(Document.get().createDivElement(), CssName.CHIP); add(chipLabel); + setEnablePrefixIcon(false); + prefixIcon.addStyleName("prefix-icon"); + prefixIcon.setIconPosition(IconPosition.LEFT); } public MaterialChip(String text) { @@ -110,6 +115,11 @@ public MaterialChip(String text, String bgColor, String textColor) { protected void onLoad() { super.onLoad(); + add(prefixIcon); + registerHandler(prefixIcon.addClickHandler(clickEvent -> { + clickEvent.stopPropagation(); + clickEvent.preventDefault(); + })); registerHandler(icon.addClickHandler(clickEvent -> close())); } @@ -305,10 +315,22 @@ public boolean isActive() { return getActiveMixin().isActive(); } + public void setEnablePrefixIcon(boolean enablePrefixIcon) { + prefixIcon.setVisible(enablePrefixIcon); + } + + public void setPrefixIcon(IconType icon) { + prefixIcon.setIconType(icon); + } + public Span getChipLabel() { return chipLabel; } + public MaterialIcon getPrefixIcon() { + return prefixIcon; + } + @Override public HandlerRegistration addCloseHandler(CloseHandler closeHandler) { return addHandler(closeHandler, CloseEvent.getType()); diff --git a/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialChipContainer.java b/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialChipContainer.java index b11f6c26b..a96303ad1 100644 --- a/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialChipContainer.java +++ b/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialChipContainer.java @@ -19,78 +19,102 @@ */ package gwt.material.design.client.ui; -import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.logical.shared.HasSelectionHandlers; import com.google.gwt.event.logical.shared.SelectionEvent; import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.Widget; +import gwt.material.design.client.base.DefaultMoreChipHandler; +import gwt.material.design.client.base.HasResetField; +import gwt.material.design.client.base.MoreChipHandler; +import gwt.material.design.client.base.mixin.ResetFieldMixin; +import gwt.material.design.client.base.mixin.ToggleStyleMixin; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; -public class MaterialChipContainer extends MaterialPanel implements HasSelectionHandlers> { +public class MaterialChipContainer extends MaterialPanel implements HasSelectionHandlers>, + HasResetField { - private List chipList = new ArrayList<>(); - private List selected = new ArrayList<>(); + private MoreChipHandler chipHandler = new DefaultMoreChipHandler(this); + private Map chipList = new HashMap<>(); + private boolean multiple = true; private boolean enableToggle = true; + private ResetFieldMixin resetFieldMixin; public MaterialChipContainer() { super("chip-container"); } - @Override + protected void onLoad() { + super.onLoad(); + + chipHandler.load(); + } + protected void add(Widget child, Element container) { super.add(child, container); if (child instanceof MaterialChip) { MaterialChip chip = (MaterialChip) child; + chip.setId(DOM.createUniqueId()); chip.setTabIndex(0); - chip.registerHandler(chip.addClickHandler(event -> { - if (isEnableToggle()) toggle(chip); + chip.registerHandler(chip.addClickHandler((event) -> { + if (isEnableToggle()) { + toggle(chip); + } })); - chip.registerHandler(chip.addKeyUpHandler(event -> { - if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) toggle(chip); + MaterialIcon icon = chip.getPrefixIcon(); + icon.registerHandler(icon.addClickHandler(clickEvent -> { + if (isEnableToggle()) { + setActive(chip, false); + } })); - chipList.add(chip); - } - } + chip.registerHandler(chip.addKeyUpHandler((event) -> { + if (event.getNativeKeyCode() == 13) { + toggle(chip); + } - @Override - protected void insert(Widget child, Element container, int beforeIndex, boolean domInsert) { - super.insert(child, container, beforeIndex, domInsert); - - if (child instanceof MaterialChip) { - chipList.add(beforeIndex, (MaterialChip) child); + })); + chipHandler.update(chip); + chipList.put(chip.getId(), chip); } } - @Override public boolean remove(Widget w) { if (w instanceof MaterialChip) { chipList.remove(w); + super.remove(w); + chipHandler.update((MaterialChip) w); } - return super.remove(w); + return true; } - @Override public void clear() { - super.clear(); - + for (MaterialChip value : chipList.values()) { + value.removeFromParent(); + } chipList.clear(); } - public void setActive(MaterialChip chip, boolean active) { - chip.setActive(active); + public void reload() { + chipHandler.reload(); + } - if (active && !selected.contains(chip)) { - selected.add(chip); - } else { - selected.remove(chip); + public void setActive(MaterialChip chip, boolean active) { + if (!multiple) { + clearActive(); } + chip.setActive(active); + SelectionEvent.fire(this, getSelected()); + } - SelectionEvent.fire(this, selected); + public void setVisibleChips(int visibleChips) { + chipHandler.setVisibleChipsSize(visibleChips); } public void toggle(MaterialChip chip) { @@ -98,7 +122,30 @@ public void toggle(MaterialChip chip) { } public void clearActive() { - chipList.forEach(c -> c.setActive(false)); + for (String s : chipList.keySet()) { + MaterialChip chip = chipList.get(s); + if (chip != null) chip.setActive(false); + } + } + + public void collapse() { + chipHandler.collapse(); + } + + public void expand() { + chipHandler.expand(); + } + + public void setCollapsible(boolean enableCollapsible) { + chipHandler.setCollapsible(enableCollapsible); + } + + public boolean isMultiple() { + return multiple; + } + + public void setMultiple(boolean multiple) { + this.multiple = multiple; } public boolean isEnableToggle() { @@ -109,8 +156,44 @@ public void setEnableToggle(boolean enableToggle) { this.enableToggle = enableToggle; } + public List getChipList() { + return new ArrayList<>(chipList.values()); + } + + public List getSelected() { + List selected = new ArrayList<>(); + List chips = getChipList(); + for (MaterialChip chip : chips) { + if (chip.isActive()) { + selected.add(chip); + } + } + return selected; + } + @Override + public void resetFields() { + getResetFieldMixin().resetFields(); + } + + @Override + public void setAllowResettingFields(boolean allowResettingFields) { + getResetFieldMixin().setAllowResettingFields(allowResettingFields); + } + + @Override + public boolean isAllowResettingFields() { + return getResetFieldMixin().isAllowResettingFields(); + } + public HandlerRegistration addSelectionHandler(SelectionHandler> handler) { return addHandler(handler, SelectionEvent.getType()); } + + public ResetFieldMixin getResetFieldMixin() { + if (resetFieldMixin == null) { + resetFieldMixin = new ResetFieldMixin<>(this); + } + return resetFieldMixin; + } } diff --git a/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialDropDown.java b/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialDropDown.java index a8fcefd6a..b1e009d90 100644 --- a/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialDropDown.java +++ b/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialDropDown.java @@ -143,8 +143,12 @@ public void unload() { // Hook for materialize bug on dropdown for not having closed once detach if (getElement() != null && isAttached()) { getElement().getStyle().setDisplay(Style.Display.NONE); + + } + + if (activatorElement != null) { + $(activatorElement).dropdown("remove"); } - $(activatorElement).dropdown("remove"); } @Override diff --git a/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialIcon.java b/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialIcon.java index b722c18a0..6f1c91d2b 100644 --- a/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialIcon.java +++ b/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialIcon.java @@ -28,11 +28,13 @@ import gwt.material.design.client.base.AbstractButton; import gwt.material.design.client.base.HasIcon; import gwt.material.design.client.base.HasSeparator; +import gwt.material.design.client.base.MaterialWidget; import gwt.material.design.client.base.mixin.ColorsMixin; import gwt.material.design.client.base.mixin.CssNameMixin; import gwt.material.design.client.base.mixin.StyleMixin; import gwt.material.design.client.base.mixin.ToggleStyleMixin; import gwt.material.design.client.constants.*; +import gwt.material.design.client.theme.GlobalThemeConfig; //@formatter:off @@ -57,7 +59,7 @@ public class MaterialIcon extends AbstractButton implements HasSeparator, HasIcon, IsAsyncWidget { - private IconDisplay iconDisplay = IconDisplay.FILLED; + private IconDisplay iconDisplay = MaterialWidget.getGlobalTheme().getIconDisplay(); private CssNameMixin positionMixin; private CssNameMixin sizeMixin; private ToggleStyleMixin prefixMixin; diff --git a/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialTextBox.java b/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialTextBox.java index 2670f94b4..a0627b56e 100644 --- a/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialTextBox.java +++ b/gwt-material/src/main/java/gwt/material/design/client/ui/MaterialTextBox.java @@ -19,8 +19,13 @@ */ package gwt.material.design.client.ui; +import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.ui.TextBox; import gwt.material.design.client.constants.InputType; +import gwt.material.design.client.sanitizer.HasValueSanitizer; +import gwt.material.design.client.sanitizer.ValueSanitizer; +import gwt.material.design.client.sanitizer.ValueSanitizerException; +import gwt.material.design.client.sanitizer.handler.ValueSanitizerErrorEvent; //@formatter:off @@ -38,7 +43,10 @@ * @see Material Design Specification */ //@formatter:on -public class MaterialTextBox extends MaterialValueBox { +//TODO: Sanitizer on TextArea +public class MaterialTextBox extends MaterialValueBox implements HasValueSanitizer { + + protected ValueSanitizer valueSanitizer; public MaterialTextBox() { super(new TextBox()); @@ -50,6 +58,27 @@ public MaterialTextBox(String placeholder) { setPlaceholder(placeholder); } + @Override + protected void onLoad() { + super.onLoad(); + + if (valueSanitizer != null) { + registerHandler(addValueChangeHandler(valueChangeEvent -> { + try { + clearErrorText(); + valueSanitizer.sanitize(valueChangeEvent.getValue()); + } catch (Exception e) { + if (e instanceof ValueSanitizerException) { + setErrorText(e.getLocalizedMessage()); + fireEvent(new ValueSanitizerErrorEvent(e.getLocalizedMessage())); + } else { + setErrorText("Invalid input value"); + } + } + })); + } + } + public void setMaxLength(int length) { asTextBox().setMaxLength(length); } @@ -66,6 +95,21 @@ public int getVisibleLength() { return asTextBox().getVisibleLength(); } + @Override + public ValueSanitizer getValueSanitizer() { + return valueSanitizer; + } + + @Override + public void setValueSanitizer(ValueSanitizer valueSanitizer) { + this.valueSanitizer = valueSanitizer; + } + + @Override + public HandlerRegistration addSanitizationErrorHandler(ValueSanitizerErrorEvent.ValueSanitizerErrorHandler handler) { + return addHandler(handler, ValueSanitizerErrorEvent.TYPE); + } + @Ignore public TextBox asTextBox() { return (TextBox) valueBoxBase; diff --git a/gwt-material/src/test/java/gwt/material/design/client/ui/MaterialChipTest.java b/gwt-material/src/test/java/gwt/material/design/client/ui/MaterialChipTest.java index c0f70408c..df69ff834 100644 --- a/gwt-material/src/test/java/gwt/material/design/client/ui/MaterialChipTest.java +++ b/gwt-material/src/test/java/gwt/material/design/client/ui/MaterialChipTest.java @@ -63,7 +63,7 @@ public void testStructure() { assertEquals(Color.RED, chip.getIconColor()); assertEquals(chip.getChipLabel(), chip.getWidget(0)); - assertEquals(chip.getIcon(), chip.getWidget(1)); + assertEquals(chip.getPrefixIcon(), chip.getWidget(1)); } public void testLetter() { diff --git a/pom.xml b/pom.xml index 9c62fcf27..004d9eb78 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.github.gwtmaterialdesign gwt-material-parent - 2.6.1 + 2.7.0 pom gwt-material @@ -75,7 +75,7 @@ scm:git:git@github.com:GwtMaterialDesign/gwt-material.git scm:git:git@github.com:GwtMaterialDesign/gwt-material.git http://github.com/GwtMaterialDesign/gwt-material - v2.6.1 + v2.7.0