Compare commits

..

8 Commits

Author SHA1 Message Date
b160cc9789 Even better 2022-02-25 11:35:38 +01:00
5d8e380d74 WAYYYYY BETTER 2022-02-25 11:32:34 +01:00
7fd7b56f9a Extract tags 2022-02-21 21:11:31 +01:00
ba8b57e5e4 Bigger 2022-02-19 16:39:05 +01:00
2900823554 Auto fetch emoji list 2022-02-19 13:59:43 +01:00
5077d09594 Adds elm build 2022-02-05 21:24:00 +01:00
3dd3eab55e Fix bug in paths 2022-02-05 21:23:02 +01:00
c2a3647303 Remove assets 2022-02-05 21:19:46 +01:00
13 changed files with 429 additions and 36151 deletions

7
.gitignore vendored
View File

@ -1,4 +1,7 @@
node_modules
elm-stuff elm-stuff
target target
js/main.js js/*
js/main.tmp.js !js/main.min.js
elm/Emoji.elm
emoji.txt

2
Cargo.lock generated
View File

@ -43,7 +43,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]] [[package]]
name = "elmojinput" name = "emojinput"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"web-view", "web-view",

View File

@ -1,5 +1,5 @@
[package] [package]
name = "elmojinput" name = "emojinput"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"

View File

@ -15,13 +15,13 @@ BUILD_DIR=js
dev: target/debug/elmojinput dev: target/debug/elmojinput
release: target/release/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 $(ELM) make elm/Main.elm --output $(BUILD_DIR)/main.js
js/main.min.js: js/main.tmp.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 @$(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 @$(ELM) make elm/Main.elm --optimize --output $(BUILD_DIR)/main.tmp.js
target/debug/elmojinput: js/main.js src/** 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/** target/release/elmojinput: js/main.min.js src/**
cargo build --release 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: clean:
@rm -rf $(BUILD_DIR)/{main.js,main.min.js} @rm -rf $(BUILD_DIR)/{main.js,main.min.js,emoji.html} elm/Emoji.elm

File diff suppressed because it is too large Load Diff

View File

@ -3,13 +3,14 @@ port module Main exposing (..)
import Browser import Browser
import Element exposing (Element) import Element exposing (Element)
import Element.Border as Border import Element.Border as Border
import Element.Font as Font
import Element.Input as Input import Element.Input as Input
import Emoji import Emoji
import Html import Html
import Html.Attributes import Html.Attributes
import Html.Events import Html.Events
import Json.Decode as Decode import Json.Decode as Decode
import Levenshtein import Levenshtein exposing (distance)
main = main =
@ -58,15 +59,17 @@ modelEmojis model =
Search s -> Search s ->
Emoji.categories Emoji.categories
|> List.concatMap Emoji.getEmojis |> List.map Emoji.getEmojis
|> List.map (\x -> ( x, minimum ( Levenshtein.distance s x.name, List.map (\v -> Levenshtein.distance s v + 1) x.tags ) )) |> List.map (List.filter (\x -> String.contains s x.name || List.any (String.contains s) x.tags))
|> List.sortBy Tuple.second |> doubleMap (\x -> ( x, distance s x.name ))
|> List.map (List.sortBy Tuple.second)
|> mergeBy Tuple.second
|> List.map Tuple.first |> List.map Tuple.first
init : () -> ( Model, Cmd Msg ) init : () -> ( Model, Cmd Msg )
init _ = init _ =
( Category Emoji.Recent, Cmd.none ) ( Category Emoji.Smileys, Cmd.none )
type Msg type Msg
@ -108,7 +111,7 @@ update msg model =
view : Model -> Html.Html Msg view : Model -> Html.Html Msg
view model = view model =
[ header model, panel (modelEmojis 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 [] |> Element.layout []
@ -129,7 +132,7 @@ header model =
Border.width 1 Border.width 1
, Border.rounded 5 , 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) , onPress = Just (CategoryClicked x)
} }
) )
@ -150,10 +153,10 @@ header model =
panel : List Emoji.Emoji -> Element Msg panel : List Emoji.Emoji -> Element Msg
panel em = panel em =
em em
|> regroup 10 |> regroup 20
|> List.map (\x -> List.map maybeEmoji x) |> List.map (\x -> List.map maybeEmoji x)
|> List.map (Element.row [ Element.width Element.fill ]) |> 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 emoji : Emoji.Emoji -> Element Msg
@ -201,8 +204,8 @@ port copy : String -> Cmd msg
-- UTILS -- -- UTILS --
minimum : ( comparable, List comparable ) -> comparable minimum : comparable -> List comparable -> comparable
minimum ( h, t ) = minimum h t =
case List.minimum t of case List.minimum t of
Nothing -> Nothing ->
h h
@ -211,8 +214,8 @@ minimum ( h, t ) =
min h v min h v
maximum : ( comparable, List comparable ) -> comparable maximum : comparable -> List comparable -> comparable
maximum ( h, t ) = maximum h t =
case List.maximum t of case List.maximum t of
Nothing -> Nothing ->
h 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
extract.js Normal file
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
js/main.js

File diff suppressed because it is too large Load Diff

1
js/main.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

225
package-lock.json generated Normal file
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
package.json Normal file
View File

@ -0,0 +1,6 @@
{
"dependencies": {
"decode-html": "^2.0.0",
"node-html-parser": "^5.2.0"
}
}

View File

@ -5,11 +5,11 @@ use web_view::*;
fn main() { fn main() {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
let js = include_str!("../../elmoji/js/main.js"); let js = include_str!("../js/main.js");
#[cfg(not(debug_assertions))] #[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>", "<script src=\"js/main.js\"></script>",
&format!("<script>{}</script>", js), &format!("<script>{}</script>", js),
); );
@ -17,7 +17,7 @@ fn main() {
web_view::builder() web_view::builder()
.title("Elmojinput") .title("Elmojinput")
.content(Content::Html(html_content)) .content(Content::Html(html_content))
.size(512, 512) .size(1024, 768)
.resizable(false) .resizable(false)
.debug(true) .debug(true)
.user_data(()) .user_data(())