Compare commits

...

8 Commits

Author SHA1 Message Date
tforgione b160cc9789 Even better 2022-02-25 11:35:38 +01:00
tforgione 5d8e380d74 WAYYYYY BETTER 2022-02-25 11:32:34 +01:00
tforgione 7fd7b56f9a Extract tags 2022-02-21 21:11:31 +01:00
tforgione ba8b57e5e4 Bigger 2022-02-19 16:39:05 +01:00
tforgione 2900823554 Auto fetch emoji list 2022-02-19 13:59:43 +01:00
tforgione 5077d09594 Adds elm build 2022-02-05 21:24:00 +01:00
tforgione 3dd3eab55e Fix bug in paths 2022-02-05 21:23:02 +01:00
tforgione c2a3647303 Remove assets 2022-02-05 21:19:46 +01:00
13 changed files with 429 additions and 36151 deletions
+5 -2
View File
@@ -1,4 +1,7 @@
node_modules
elm-stuff
target
js/main.js
js/main.tmp.js
js/*
!js/main.min.js
elm/Emoji.elm
emoji.txt
Generated
+1 -1
View File
@@ -43,7 +43,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]]
name = "elmojinput"
name = "emojinput"
version = "0.1.0"
dependencies = [
"web-view",
+1 -1
View File
@@ -1,5 +1,5 @@
[package]
name = "elmojinput"
name = "emojinput"
version = "0.1.0"
edition = "2021"
+9 -3
View File
@@ -15,13 +15,13 @@ BUILD_DIR=js
dev: target/debug/elmojinput
release: target/release/elmojinput
js/main.js: elm/**
js/main.js: elm/** elm/Emoji.elm
$(ELM) make elm/Main.elm --output $(BUILD_DIR)/main.js
js/main.min.js: js/main.tmp.js
@$(UGLIFYJS) $(BUILD_DIR)/main.tmp.js --compress 'pure_funcs="F2,F3,F4,F5,F6,F7,F8,F9,A2,A3,A4,A5,A6,A7,A8,A9",pure_getters,keep_fargs=false,unsafe_comps,unsafe' | $(UGLIFYJS) --mangle > $(BUILD_DIR)/main.min.js
js/main.tmp.js: elm/**
js/main.tmp.js: elm/** elm/Emoji.elm
@$(ELM) make elm/Main.elm --optimize --output $(BUILD_DIR)/main.tmp.js
target/debug/elmojinput: js/main.js src/**
@@ -30,5 +30,11 @@ target/debug/elmojinput: js/main.js src/**
target/release/elmojinput: js/main.min.js src/**
cargo build --release
js/emoji.html:
@curl https://unicode.org/emoji/charts/emoji-list.html -o $(BUILD_DIR)/emoji.html
elm/Emoji.elm: js/emoji.html extract.js
@node extract.js > elm/Emoji.elm
clean:
@rm -rf $(BUILD_DIR)/{main.js,main.min.js}
@rm -rf $(BUILD_DIR)/{main.js,main.min.js,emoji.html} elm/Emoji.elm
-1525
View File
File diff suppressed because it is too large Load Diff
+57 -13
View File
@@ -3,13 +3,14 @@ port module Main exposing (..)
import Browser
import Element exposing (Element)
import Element.Border as Border
import Element.Font as Font
import Element.Input as Input
import Emoji
import Html
import Html.Attributes
import Html.Events
import Json.Decode as Decode
import Levenshtein
import Levenshtein exposing (distance)
main =
@@ -58,15 +59,17 @@ modelEmojis model =
Search s ->
Emoji.categories
|> List.concatMap Emoji.getEmojis
|> List.map (\x -> ( x, minimum ( Levenshtein.distance s x.name, List.map (\v -> Levenshtein.distance s v + 1) x.tags ) ))
|> List.sortBy Tuple.second
|> List.map Emoji.getEmojis
|> List.map (List.filter (\x -> String.contains s x.name || List.any (String.contains s) x.tags))
|> doubleMap (\x -> ( x, distance s x.name ))
|> List.map (List.sortBy Tuple.second)
|> mergeBy Tuple.second
|> List.map Tuple.first
init : () -> ( Model, Cmd Msg )
init _ =
( Category Emoji.Recent, Cmd.none )
( Category Emoji.Smileys, Cmd.none )
type Msg
@@ -108,7 +111,7 @@ update msg model =
view : Model -> Html.Html Msg
view model =
[ header model, panel (modelEmojis model) ]
|> Element.column [ Element.width (Element.px 512), Element.height (Element.px 512) ]
|> Element.column [ Font.size 25, Element.width (Element.px 1024), Element.height (Element.px 768) ]
|> Element.layout []
@@ -129,7 +132,7 @@ header model =
Border.width 1
, Border.rounded 5
]
{ label = Element.el [] (Element.text (Emoji.categoryEmoji x).unicode)
{ label = Element.el [ Element.centerX, Element.centerY ] (Element.text (Emoji.categoryEmoji x).unicode)
, onPress = Just (CategoryClicked x)
}
)
@@ -150,10 +153,10 @@ header model =
panel : List Emoji.Emoji -> Element Msg
panel em =
em
|> regroup 10
|> regroup 20
|> List.map (\x -> List.map maybeEmoji x)
|> List.map (Element.row [ Element.width Element.fill ])
|> Element.column [ Element.width (Element.px 512), Element.height (Element.px 512), Element.scrollbarY ]
|> Element.column [ Element.width (Element.px 1024), Element.height (Element.px 748), Element.scrollbarY ]
emoji : Emoji.Emoji -> Element Msg
@@ -201,8 +204,8 @@ port copy : String -> Cmd msg
-- UTILS --
minimum : ( comparable, List comparable ) -> comparable
minimum ( h, t ) =
minimum : comparable -> List comparable -> comparable
minimum h t =
case List.minimum t of
Nothing ->
h
@@ -211,8 +214,8 @@ minimum ( h, t ) =
min h v
maximum : ( comparable, List comparable ) -> comparable
maximum ( h, t ) =
maximum : comparable -> List comparable -> comparable
maximum h t =
case List.maximum t of
Nothing ->
h
@@ -236,3 +239,44 @@ onEnter msg =
)
)
)
mergeAux : (a -> comparable) -> List a -> List a -> List a
mergeAux comparator listOne listTwo =
case ( listOne, listTwo ) of
( _, [] ) ->
listOne
( [], _ ) ->
listTwo
( frontOne :: restOne, frontTwo :: restTwo ) ->
if comparator frontOne < comparator frontTwo then
frontOne :: mergeAux comparator restOne listTwo
else
frontTwo :: mergeAux comparator listOne restTwo
mergeBy : (a -> comparable) -> List (List a) -> List a
mergeBy comparator input =
case input of
[] ->
[]
[ [] ] ->
[]
[ a ] ->
a
[ a, b ] ->
mergeAux comparator a b
a :: b :: t ->
mergeBy comparator (mergeAux comparator a b :: t)
doubleMap : (a -> b) -> List (List a) -> List (List b)
doubleMap map input =
List.map (\x -> List.map map x) input
+121
View File
@@ -0,0 +1,121 @@
const fs = require('fs');
const decode = require('decode-html');
const { parse } = require('node-html-parser');
function formatEmoji(emoji) {
return (
'{ name = "' + emoji.name +
'", unicode = "' + emoji.unicode +
'", tags = [ ' + emoji.tags.map(x => '"' + x + '"').join(', ') +
' ] }'
);
}
let html = parse(fs.readFileSync('js/emoji.html', 'utf-8'));
let table = html.getElementsByTagName('table')[0];
let emojis = {};
let currentEmojis = null;
for (let element of table.childNodes) {
// Skip text
if (element.nodeType === 3) continue;
if (element.rawTagName === 'tr') {
let cols = element.childNodes.filter(x => x.nodeType !== 3);
let firstCol = cols[0];
if (firstCol.classList.contains('bighead')) {
let name = decode(firstCol.childNodes.filter(x => x.nodeType !== 3)[0].childNodes[0]._rawText)
.split(' ')[0]
.toLowerCase();
currentEmojis = [];
emojis[name] = currentEmojis;
}
if (firstCol.rawTagName === 'td') {
// We're in an emoji line
let name = decode(cols[3].childNodes[0]._rawText);
let tags = decode(cols[4].childNodes[0]._rawText).split('|').map(x => x.trim());
let unicode = cols[2].childNodes[0].childNodes[0].rawAttrs.split("'")[1];
currentEmojis.push({
unicode, name, tags
});
}
}
}
delete(emojis.component);
// Generate elm
console.log('module Emoji exposing (..)');
console.log('\n');
console.log('type alias Emoji =');
console.log(' { name : String');
console.log(' , unicode : String');
console.log(' , tags : List String');
console.log(' }');
console.log('\n');
console.log('type alias Emojis =');
let first = true;
for (let key in emojis) {
console.log(' ' + (first ? '{' : ',') + ' ' + key + ' : List Emoji');
first = false;
}
console.log(' }')
console.log('\n');
console.log('type Category');
first = true;
for (let key in emojis) {
console.log(' ' + (first ? '=' : '|') + ' ' + key[0].toUpperCase() + key.slice(1).toLowerCase());
first = false;
}
console.log('\n');
console.log('categories : List Category');
console.log('categories =');
console.log(' [' + Object.keys(emojis).map(x => x[0].toUpperCase() + x.slice(1).toLowerCase()).join(', ') + ']');
console.log('\n');
console.log('categoryEmoji : Category -> Emoji');
console.log('categoryEmoji category =');
console.log(' case category of');
for (let key in emojis) {
console.log(' ' + key[0].toUpperCase() + key.slice(1).toLowerCase() + ' ->');
console.log(' ' + formatEmoji(emojis[key][0]) + '\n');
}
console.log();
console.log('getEmojis : Category -> List Emoji')
console.log('getEmojis category =');
console.log(' case category of');
for (let key in emojis) {
console.log(' ' + key[0].toUpperCase() + key.slice(1).toLowerCase() + ' ->');
console.log(' emojis.' + key + '\n');
}
console.log();
console.log('emojis : Emojis');
console.log('emojis =');
let first1 = true;
for (let key in emojis) {
console.log(' ' + (first1 ? '{' : ',') + ' ' + key + ' =');
let first2 = true;
for (let emoji of emojis[key]) {
console.log(' ' + (first2 ? '[' : ',') + ' ' + formatEmoji(emoji));
first2 = false;
}
console.log(' ]');
first1 = false;
}
console.log(' }');
-17312
View File
File diff suppressed because it is too large Load Diff
-1
View File
File diff suppressed because one or more lines are too long
-17289
View File
File diff suppressed because it is too large Load Diff
+225
View File
@@ -0,0 +1,225 @@
{
"name": "emojinput",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"dependencies": {
"decode-html": "^2.0.0",
"node-html-parser": "^5.2.0"
}
},
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
},
"node_modules/css-select": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz",
"integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==",
"dependencies": {
"boolbase": "^1.0.0",
"css-what": "^5.1.0",
"domhandler": "^4.3.0",
"domutils": "^2.8.0",
"nth-check": "^2.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-what": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
"integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==",
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/decode-html": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/decode-html/-/decode-html-2.0.0.tgz",
"integrity": "sha1-fQqIfORCgOYJeKcH67f4CB/WHqo="
},
"node_modules/dom-serializer": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
"dependencies": {
"domelementtype": "^2.0.1",
"domhandler": "^4.2.0",
"entities": "^2.0.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/domelementtype": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
]
},
"node_modules/domhandler": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
"integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
"dependencies": {
"domelementtype": "^2.2.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/domutils": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
"dependencies": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.2.0"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/entities": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"bin": {
"he": "bin/he"
}
},
"node_modules/node-html-parser": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-5.2.0.tgz",
"integrity": "sha512-fmiwLfQu+J2A0zjwSEkztSHexAf5qq/WoiL/Hgo1K7JpfEP+OGWY5maG0kGaM+IFVdixF/1QbyXaQ3h4cGfeLw==",
"dependencies": {
"css-select": "^4.1.3",
"he": "1.2.0"
}
},
"node_modules/nth-check": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
"integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
"dependencies": {
"boolbase": "^1.0.0"
},
"funding": {
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
}
},
"dependencies": {
"boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
},
"css-select": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.2.1.tgz",
"integrity": "sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==",
"requires": {
"boolbase": "^1.0.0",
"css-what": "^5.1.0",
"domhandler": "^4.3.0",
"domutils": "^2.8.0",
"nth-check": "^2.0.1"
}
},
"css-what": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
"integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw=="
},
"decode-html": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/decode-html/-/decode-html-2.0.0.tgz",
"integrity": "sha1-fQqIfORCgOYJeKcH67f4CB/WHqo="
},
"dom-serializer": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
"integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
"requires": {
"domelementtype": "^2.0.1",
"domhandler": "^4.2.0",
"entities": "^2.0.0"
}
},
"domelementtype": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A=="
},
"domhandler": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
"integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
"requires": {
"domelementtype": "^2.2.0"
}
},
"domutils": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
"requires": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.2.0"
}
},
"entities": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
},
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
"node-html-parser": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/node-html-parser/-/node-html-parser-5.2.0.tgz",
"integrity": "sha512-fmiwLfQu+J2A0zjwSEkztSHexAf5qq/WoiL/Hgo1K7JpfEP+OGWY5maG0kGaM+IFVdixF/1QbyXaQ3h4cGfeLw==",
"requires": {
"css-select": "^4.1.3",
"he": "1.2.0"
}
},
"nth-check": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
"integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
"requires": {
"boolbase": "^1.0.0"
}
}
}
}
+6
View File
@@ -0,0 +1,6 @@
{
"dependencies": {
"decode-html": "^2.0.0",
"node-html-parser": "^5.2.0"
}
}
+4 -4
View File
@@ -5,11 +5,11 @@ use web_view::*;
fn main() {
#[cfg(debug_assertions)]
let js = include_str!("../../elmoji/js/main.js");
let js = include_str!("../js/main.js");
#[cfg(not(debug_assertions))]
let js = include_str!("../../elmoji/js/main.min.js");
let js = include_str!("../js/main.min.js");
let html_content = include_str!("../../elmoji/index.html").replace(
let html_content = include_str!("../index.html").replace(
"<script src=\"js/main.js\"></script>",
&format!("<script>{}</script>", js),
);
@@ -17,7 +17,7 @@ fn main() {
web_view::builder()
.title("Elmojinput")
.content(Content::Html(html_content))
.size(512, 512)
.size(1024, 768)
.resizable(false)
.debug(true)
.user_data(())