feat: Only use fully-qualified emojis

This commit is contained in:
jawira 2022-11-06 15:02:43 +01:00
parent a690f8075b
commit cc467e4a2d
16 changed files with 7500 additions and 7598 deletions

View File

@ -14,3 +14,7 @@ indent_size = 4
[*.{md, markdown}]
trim_trailing_whitespace = false
max_line_length = 80
[.gitattributes]
indent_style = tab
tab_width = 4

4
.gitattributes vendored
View File

@ -1,11 +1,13 @@
/.idea export-ignore
/docs export-ignore
/tasks export-ignore
/tests export-ignore
/resources export-ignore
/.editorconfig export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/build.svg export-ignore
/build.png export-ignore
/build.xml export-ignore
/CHANGELOG.md export-ignore
/changelog-linker.yaml export-ignore
/README.md export-ignore

BIN
build.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 44 KiB

107
build.xml
View File

@ -1,20 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="jawira/emoji-catalog" default="help" phingVersion="3">
<defaultexcludes default="true"/><!--Initializing default excludes-->
<defaultexcludes add="**/.idea"/>
<defaultexcludes add="**/.idea/**"/>
<property name="phing.http.proxy" value="${env.http_proxy}"/>
<property name="emoji.source" value="https://unicode.org/Public/emoji/15.0/emoji-test.txt"/>
<target name="setup" description="Prepare project for dev" depends="composer:install"/>
<target name="qa" description="Quality assurance" depends="composer:validate,php:lint"/>
<target name="update" description="Update class and catalog" depends="emoji:update,catalog:update,emoji:count"/>
<target name="emoji:update" description="Update Emoji.php"
depends="emoji-list:download,emoji:parse,emoji:build"/>
<target name="catalog:update" description="Update catalog.md"
depends="emoji-list:download,catalog:parse,catalog:build"/>
<target name="qa" description="Quality assurance"
depends="composer:normalize,composer:validate,php:lint,emoji:tests"/>
<target name="update" description="Update class and catalog"
depends="emoji:download-source,emoji:update,doc:update,emoji:count"/>
<target name="composer:validate" description="Validate composer.json">
@ -26,10 +21,6 @@
</composer>
</target>
<target name="visualizer">
<visualizer/>
</target>
<target name="composer:install" description="Install for dev">
<composer command="install">
<arg value="--quiet"/>
@ -40,62 +31,31 @@
</composer>
</target>
<target name="emoji-list:download">
<target name="composer:normalize" description="Normalize composer.json">
<composer command="normalize">
<arg value="--ansi"/>
<arg value="--no-interaction"/>
<arg value="--diff"/>
<arg value="--indent-size=2"/>
<arg value="--indent-style=space"/>
</composer>
</target>
<target name="emoji:download-source">
<mkdir dir="resources/unicode"/>
<httpget dir="resources/unicode" url="https://unicode.org/emoji/charts/full-emoji-list.html"/>
<httpget dir="resources/unicode" url="https://unicode.org/emoji/charts/full-emoji-modifiers.html"/>
<httpget dir="resources/unicode" url="${emoji.source}"/>
</target>
<target name="emoji:parse">
<mkdir dir="resources/output"/>
<delete file="resources/output/emoji-1.txt"/>
<xslt file="resources/unicode/full-emoji-list.html"
tofile="resources/output/emoji-1.txt"
style="resources/xslt/emoji.xsl"
haltonerror="false"
overwrite="true"
html="true"/>
<delete file="resources/output/emoji-2.txt"/>
<xslt file="resources/unicode/full-emoji-modifiers.html"
tofile="resources/output/emoji-2.txt"
style="resources/xslt/emoji.xsl"
haltonerror="false"
overwrite="true"
html="true"/>
<target name="emoji:update" description="Generate Emoji class">
<autoloader autoloaderpath="vendor/autoload.php"/>
<taskdef name="emoji-update" classname="\Jawira\EmojiTask\EmojiUpdateTask"/>
<emoji-update/>
</target>
<target name="emoji:build">
<append file="resources/templates/emoji-header.php.dist" destFile="src/Emoji.php" append="false" overwrite="true"/>
<append file="resources/output/emoji-1.txt" destFile="src/Emoji.php"/>
<append file="resources/output/emoji-2.txt" destFile="src/Emoji.php"/>
<append file="resources/templates/emoji-footer.php.dist" destFile="src/Emoji.php"/>
</target>
<target name="catalog:parse">
<mkdir dir="resources/output"/>
<delete file="resources/output/catalog-1.txt"/>
<xslt file="resources/unicode/full-emoji-list.html"
tofile="resources/output/catalog-1.txt"
style="resources/xslt/catalog.xsl"
haltonerror="false"
overwrite="true"
html="true"/>
<delete file="resources/output/catalog-2.txt"/>
<xslt file="resources/unicode/full-emoji-modifiers.html"
tofile="resources/output/catalog-2.txt"
style="resources/xslt/catalog.xsl"
haltonerror="false"
overwrite="true"
html="true"/>
</target>
<target name="catalog:build">
<append file="resources/templates/catalog-header.md.dist" destFile="docs/catalog.md" append="false"
overwrite="true"/>
<append file="resources/output/catalog-1.txt" destFile="docs/catalog.md"/>
<append file="resources/output/catalog-2.txt" destFile="docs/catalog.md"/>
<target name="doc:update">
<autoloader autoloaderpath="vendor/autoload.php"/>
<taskdef name="catalog-update" classname="\Jawira\EmojiTask\CatalogUpdateTask"/>
<catalog-update/>
</target>
<target name="php:lint" description="Check PHP syntax">
@ -106,19 +66,24 @@
</phplint>
</target>
<target name="emoji:tests" description="Test some fully-qualified emojis">
<autoloader autoloaderpath="vendor/autoload.php"/>
<php function="vanilla"/>
</target>
<target name="emoji:count" description="Count constants in Emoji class">
<autoloader autoloaderpath="vendor/autoload.php"/>
<adhoc-task name="emoji-count"><![CDATA[
<adhoc-task name="emoji-count">
class EmojiCountTask extends \Phing\Task {
function main() {
$emojiReflection = new ReflectionClass(\Jawira\EmojiCatalog\Emoji::class);
$constants = $emojiReflection->getConstants();
$constants = $emojiReflection-&gt;getConstants();
$count = count($constants);
$this->log("Emoji count: $count");
$this->project->setProperty('emoji-count', $count);
$this-&gt;log("Emoji count: $count");
$this-&gt;project-&gt;setProperty('emoji-count', $count);
}
}
]]></adhoc-task>
</adhoc-task>
<emoji-count/>
</target>

View File

@ -1,7 +1,8 @@
{
"name": "jawira/emoji-catalog",
"type": "library",
"description": "Get access to +3600 emojis as class constants",
"license": "MIT",
"type": "library",
"keywords": [
"emoji",
"emojis",
@ -11,24 +12,39 @@
"unicode",
"catalog"
],
"license": "MIT",
"authors": [
{
"name": "Jawira Portugal",
"email": "dev@tugal.be"
}
],
"require": {
"php": ">=5.6"
},
"require-dev": {},
"config": {
"preferred-install": "dist",
"sort-packages": true
"require-dev": {
"php": "^7.3 || ^8.0",
"ext-intl": "*",
"ext-mbstring": "*",
"ergebnis/composer-normalize": "^2.28",
"jawira/skeleton": "^2.16",
"phing/phing": "^2.17 || ^3"
},
"autoload": {
"psr-4": {
"Jawira\\EmojiCatalog\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Jawira\\EmojiTask\\": "tasks"
},
"files": [
"tests/vanilla.php"
]
},
"config": {
"allow-plugins": {
"ergebnis/composer-normalize": true
},
"platform-check": true,
"preferred-install": "dist",
"sort-packages": true
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +0,0 @@
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="end" select="14"/>
<xsl:variable name="increment" select="1"/>
<xsl:template match="/">
<table>
<xsl:for-each select="//record">
<tr>
<xsl:variable name="start" select="1"/>
<xsl:call-template name="loop">
<xsl:with-param name="counter" select="$start"/>
</xsl:call-template>
</tr>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template name="loop">
<xsl:param name="counter"/>
<xsl:if test="$counter &lt;= $end">
<td>
<xsl:value-of select="Merkmale/Product/Merkmal[@ColNo=$counter]/@Farbe"/>
</td>
<xsl:call-template name="loop">
<xsl:with-param name="counter" select="$counter + $increment"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

View File

@ -3,11 +3,8 @@
namespace Jawira\EmojiCatalog;
/**
* Class Emoji
*
* Get access to all emojis as class constants.
*
* @package Jawira\EmojiCatalog
* @author Jawira Portugal <dev@tugal.be>
*/
class Emoji

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" version="2.0" encoding="UTF-8" indent="no"/>
<xsl:include href="./resources/xslt/common.xsl"/>
<xsl:template match="/">
<xsl:for-each select="//table//tr[./td//img]">
<xsl:text>| </xsl:text>
<xsl:call-template name="get-name"/>
<xsl:text> </xsl:text>
<xsl:text>| </xsl:text>
<xsl:call-template name="get-emoji"/>
<xsl:text> </xsl:text>
<xsl:text>| </xsl:text>
<xsl:call-template name="get-code"/>
<xsl:text> </xsl:text>
<xsl:text>| </xsl:text>
<xsl:call-template name="get-constant-name"/>
<xsl:text> |&#10;</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,95 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="get-code">
<xsl:value-of select="./td[2]//a/text()"/>
</xsl:template>
<xsl:template name="get-name">
<xsl:variable name="short-name" select="./td[last()]/text()"/>
<xsl:variable name="removable" select="'⊛⊖'"/>
<xsl:variable name="cleaned" select="translate($short-name, $removable, '')"/>
<xsl:value-of select="normalize-space($cleaned)"/>
</xsl:template>
<xsl:template name="get-emoji">
<xsl:value-of select="./td[3]/text()"/>
</xsl:template>
<xsl:template name="get-constant-name">
<xsl:variable name="short-name" select="./td[last()]/text()"/>
<xsl:variable name="removable" select="':;.,⊛’!“”()⊖'"/>
<xsl:variable name="cleaned" select="translate($short-name, $removable, '')"/>
<xsl:variable name="lowercase" select="'Åãabcçdeéfghíijklmnñoôpqrstuvwxyz-&amp;'"/>
<xsl:variable name="uppercase" select="'AAABCCDEEFGHIIJKLMNNOOPQRSTUVWXYZ N'"/>
<xsl:variable name="no-accents" select="translate($cleaned, $lowercase, $uppercase)"/>
<xsl:variable name="normalized" select="normalize-space($no-accents)"/>
<xsl:variable name="no-spaces" select="translate($normalized, ' ', '_')"/>
<xsl:variable name="no-1st">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="$no-spaces"/>
<xsl:with-param name="replace" select="'1ST'"/>
<xsl:with-param name="by" select="'FIRST'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="no-2nd">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="$no-1st"/>
<xsl:with-param name="replace" select="'2ND'"/>
<xsl:with-param name="by" select="'SECOND'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="no-3rd">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="$no-2nd"/>
<xsl:with-param name="replace" select="'3RD'"/>
<xsl:with-param name="by" select="'THIRD'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="no-number">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="$no-3rd"/>
<xsl:with-param name="replace" select="'#'"/>
<xsl:with-param name="by" select="'NUMBER'"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="no-asterisk">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="$no-number"/>
<xsl:with-param name="replace" select="'*'"/>
<xsl:with-param name="by" select="'ASTERISK'"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$no-asterisk"/>
</xsl:template>
<!-- http://geekswithblogs.net/Erik/archive/2008/04/01/120915.aspx -->
<xsl:template name="string-replace-all">
<xsl:param name="text"/>
<xsl:param name="replace"/>
<xsl:param name="by"/>
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)"/>
<xsl:value-of select="$by"/>
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="substring-after($text,$replace)"/>
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="by" select="$by"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" version="2.0" encoding="UTF-8" indent="no"/>
<xsl:include href="./resources/xslt/common.xsl"/>
<xsl:template match="/">
<xsl:for-each select="//table//tr[./td//img]">
<xsl:text>const </xsl:text>
<xsl:call-template name="get-constant-name"/>
<xsl:text> = "</xsl:text>
<xsl:call-template name="get-emoji"/>
<xsl:text>";&#10;</xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
<?php declare(strict_types=1);
namespace Jawira\EmojiTask;
abstract class AbstractEmojiTask extends \Phing\Task
{
function codepointsToEmoji(string $codepoints): string
{
$codepointsArray = array_filter(explode(' ', $codepoints));
$reducer = function (string $carry, string $codepoint) {
return $carry . mb_chr(hexdec($codepoint), 'UTF-8');
};
return array_reduce($codepointsArray, $reducer, '');
}
function extractParts(string $line): ?array
{
preg_match('@^(?<CODEPOINTS>[0-9A-H\s]+); fully-qualified\s+#\s\S+\sE\d*\.\d*\s(?<NAME>.+)@', $line, $matches);
return empty($matches) ? null : $matches;
}
function normalizeEmojiName(string $emojiName): string
{
$rules = "'*' > asterisk ; '#' > number ; :: Any-Latin; :: NFD; :: [:Nonspacing Mark:] Remove; :: NFC; :: [^-[:^Punctuation:]] Remove; :: Upper(); [:^L:] { [-] > ; [-] } [:^L:] > ; [-[:Separator:]]+ > '_'; 1ST > FIRST ; 2ND > SECOND ; 3RD > THIRD ; ";
return \Transliterator::createFromRules($rules)->transliterate($emojiName);
}
}

View File

@ -0,0 +1,23 @@
<?php declare(strict_types=1);
namespace Jawira\EmojiTask;
use SplFileObject;
class CatalogUpdateTask extends AbstractEmojiTask
{
function main()
{
$file = new SplFileObject('docs/catalog.md', 'w+');
$file->fwrite(file_get_contents('resources/templates/catalog-header.md.dist'));
foreach (file('resources/unicode/emoji-test.txt') as $line) {
$matches = $this->extractParts($line);
if (!is_array($matches)) {
continue;
}
$emoji = $this->codepointsToEmoji($matches['CODEPOINTS']);
$constantName = $this->normalizeEmojiName($matches['NAME']);
$file->fwrite(sprintf("| %s | %s | %s | %s |%s", $matches['NAME'], $emoji, trim($matches['CODEPOINTS']), $constantName, PHP_EOL));
}
}
}

25
tasks/EmojiUpdateTask.php Normal file
View File

@ -0,0 +1,25 @@
<?php declare(strict_types=1);
namespace Jawira\EmojiTask;
use SplFileObject;
class EmojiUpdateTask extends AbstractEmojiTask
{
function main()
{
$file = new SplFileObject('src/Emoji.php', 'w+');
$file->fwrite(file_get_contents('resources/templates/emoji-header.php.dist'));
foreach (file('resources/unicode/emoji-test.txt') as $line) {
$matches = $this->extractParts($line);
if (!is_array($matches)) {
continue;
}
$emoji = $this->codepointsToEmoji($matches['CODEPOINTS']);
$constantName = $this->normalizeEmojiName($matches['NAME']);
$file->fwrite("const $constantName = '$emoji';" . PHP_EOL);
}
$file->fwrite(file_get_contents('resources/templates/emoji-footer.php.dist'));
}
}

32
tests/vanilla.php Normal file
View File

@ -0,0 +1,32 @@
<?php declare(strict_types=1);
use Jawira\EmojiCatalog\Emoji;
/**
* Simply test if some Emojis are respected.
*
* Since Emojis can have different names between versions, update tests accordingly.
*/
function vanilla()
{
$provider = [
'E0.6' => [Emoji::VICTORY_HAND, "\u{270C}\u{FE0F}"],
'E0.7' => [Emoji::MOUNTAIN, "\u{26F0}\u{FE0F}"],
'E1.0' => [Emoji::GRINNING_FACE, "\u{1F600}"],
'E2.0' => [Emoji::FLAG_EUROPEAN_UNION, "\u{1F1EA}\u{1F1FA}"],
'E3.0' => [Emoji::CALL_ME_HAND, "\u{1F919}"],
'E4.0' => [Emoji::FLAG_UNITED_NATIONS, "\u{1F1FA}\u{1F1F3}"],
'E13.1' => [Emoji::HEART_ON_FIRE, "\u{2764}\u{FE0F}\u{200D}\u{1F525}"],
'E15.0' => [Emoji::PINK_HEART, "\u{1FA77}"],
];
foreach ($provider as $key => $testCase) {
if ($testCase[0] !== $testCase[1]) {
throw new Exception("Test '$key' failed!");
}
echo $testCase[0];
}
$count = count($provider);
echo PHP_EOL, "All $count tests ok!", PHP_EOL;
}