Ver Fonte

add wj-project

animeic há 2 anos atrás
commit
a0c88520f8
100 ficheiros alterados com 14485 adições e 0 exclusões
  1. 29 0
      wj-pack/backend/.autod.conf.js
  2. 1 0
      wj-pack/backend/.eslintignore
  3. 3 0
      wj-pack/backend/.eslintrc
  4. 15 0
      wj-pack/backend/.gitignore
  5. 12 0
      wj-pack/backend/.travis.yml
  6. 33 0
      wj-pack/backend/README.md
  7. 35 0
      wj-pack/backend/app/const.js
  8. 100 0
      wj-pack/backend/app/controller/admin/company.js
  9. 54 0
      wj-pack/backend/app/controller/admin/course.js
  10. 115 0
      wj-pack/backend/app/controller/admin/dict.js
  11. 35 0
      wj-pack/backend/app/controller/admin/icon.js
  12. 85 0
      wj-pack/backend/app/controller/admin/index.js
  13. 43 0
      wj-pack/backend/app/controller/admin/logs.js
  14. 61 0
      wj-pack/backend/app/controller/admin/record.js
  15. 97 0
      wj-pack/backend/app/controller/admin/user.js
  16. 43 0
      wj-pack/backend/app/controller/admin/weapon.js
  17. 29 0
      wj-pack/backend/app/controller/app/course.js
  18. 18 0
      wj-pack/backend/app/controller/app/icon.js
  19. 214 0
      wj-pack/backend/app/controller/app/insurant.js
  20. 34 0
      wj-pack/backend/app/controller/app/logs.js
  21. 30 0
      wj-pack/backend/app/controller/app/map.js
  22. 23 0
      wj-pack/backend/app/controller/app/message.js
  23. 103 0
      wj-pack/backend/app/controller/app/other.js
  24. 50 0
      wj-pack/backend/app/controller/app/record.js
  25. 40 0
      wj-pack/backend/app/controller/app/user.js
  26. 23 0
      wj-pack/backend/app/controller/app/weapon.js
  27. 143 0
      wj-pack/backend/app/controller/baidu/index.js
  28. 13 0
      wj-pack/backend/app/controller/home.js
  29. 38 0
      wj-pack/backend/app/controller/oss.js
  30. 150 0
      wj-pack/backend/app/controller/sys/common.js
  31. 57 0
      wj-pack/backend/app/controller/sys/device.js
  32. 43 0
      wj-pack/backend/app/controller/sys/perm.js
  33. 136 0
      wj-pack/backend/app/controller/sys/user.js
  34. 281 0
      wj-pack/backend/app/extend/context.js
  35. 29 0
      wj-pack/backend/app/middleware/error_handler.js
  36. 25 0
      wj-pack/backend/app/middleware/loginAdmin.js
  37. 28 0
      wj-pack/backend/app/middleware/loginUser.js
  38. 13 0
      wj-pack/backend/app/model/admin.js
  39. 23 0
      wj-pack/backend/app/model/dict.js
  40. 74 0
      wj-pack/backend/app/model/insurance.js
  41. 35 0
      wj-pack/backend/app/model/user.js
  42. 0 0
      wj-pack/backend/app/public/message/check/css/app.96265e40.css
  43. BIN
      wj-pack/backend/app/public/message/check/favicon.ico
  44. BIN
      wj-pack/backend/app/public/message/check/img/logo.82b9c7a5.png
  45. 28 0
      wj-pack/backend/app/public/message/check/index.html
  46. 1 0
      wj-pack/backend/app/public/message/check/js/about.6a60e643.js
  47. 0 0
      wj-pack/backend/app/public/message/check/js/app.edc03535.js
  48. 6 0
      wj-pack/backend/app/public/message/check/js/chunk-vendors.f81017bd.js
  49. 1645 0
      wj-pack/backend/app/public/message/check/tinymce/changelog.txt
  50. 0 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/icons/default/icons.min.js
  51. 92 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/jquery.tinymce.min.js
  52. 3 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/langs/readme.md
  53. 410 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/langs/zh_CN.js
  54. 504 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/license.txt
  55. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/advlist/plugin.min.js
  56. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/anchor/plugin.min.js
  57. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/autolink/plugin.min.js
  58. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/autoresize/plugin.min.js
  59. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/autosave/plugin.min.js
  60. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/bbcode/plugin.min.js
  61. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/charmap/plugin.min.js
  62. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/code/plugin.min.js
  63. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/codesample/plugin.min.js
  64. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/colorpicker/plugin.min.js
  65. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/contextmenu/plugin.min.js
  66. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/directionality/plugin.min.js
  67. 9015 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/emoticons/js/emojis.js
  68. 1 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/emoticons/js/emojis.min.js
  69. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/emoticons/plugin.min.js
  70. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/fullpage/plugin.min.js
  71. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/fullscreen/plugin.min.js
  72. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/help/plugin.min.js
  73. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/hr/plugin.min.js
  74. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/image/plugin.min.js
  75. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/imagetools/plugin.min.js
  76. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/importcss/plugin.min.js
  77. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/insertdatetime/plugin.min.js
  78. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/legacyoutput/plugin.min.js
  79. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/link/plugin.min.js
  80. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/lists/plugin.min.js
  81. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/media/plugin.min.js
  82. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/nonbreaking/plugin.min.js
  83. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/noneditable/plugin.min.js
  84. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/pagebreak/plugin.min.js
  85. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/paste/plugin.min.js
  86. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/preview/plugin.min.js
  87. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/print/plugin.min.js
  88. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/quickbars/plugin.min.js
  89. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/save/plugin.min.js
  90. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/searchreplace/plugin.min.js
  91. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/spellchecker/plugin.min.js
  92. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/tabfocus/plugin.min.js
  93. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/table/plugin.min.js
  94. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/template/plugin.min.js
  95. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/textcolor/plugin.min.js
  96. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/textpattern/plugin.min.js
  97. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/toc/plugin.min.js
  98. 9 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/visualblocks/plugin.min.js
  99. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/visualchars/plugin.min.js
  100. 8 0
      wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/wordcount/plugin.min.js

+ 29 - 0
wj-pack/backend/.autod.conf.js

@@ -0,0 +1,29 @@
+'use strict';
+
+module.exports = {
+  write: true,
+  prefix: '^',
+  plugin: 'autod-egg',
+  test: [
+    'test',
+    'benchmark',
+  ],
+  dep: [
+    'egg',
+    'egg-scripts',
+  ],
+  devdep: [
+    'egg-ci',
+    'egg-bin',
+    'egg-mock',
+    'autod',
+    'autod-egg',
+    'eslint',
+    'eslint-config-egg',
+  ],
+  exclude: [
+    './test/fixtures',
+    './dist',
+  ],
+};
+

+ 1 - 0
wj-pack/backend/.eslintignore

@@ -0,0 +1 @@
+coverage

+ 3 - 0
wj-pack/backend/.eslintrc

@@ -0,0 +1,3 @@
+{
+  "extends": "eslint-config-egg"
+}

+ 15 - 0
wj-pack/backend/.gitignore

@@ -0,0 +1,15 @@
+logs/
+npm-debug.log
+yarn-error.log
+node_modules/
+package-lock.json
+yarn.lock
+coverage/
+.idea/
+run/
+.DS_Store
+*.sw*
+*.un~
+typings/
+.nyc_output/
+.github/

+ 12 - 0
wj-pack/backend/.travis.yml

@@ -0,0 +1,12 @@
+
+language: node_js
+node_js:
+  - '10'
+before_install:
+  - npm i npminstall -g
+install:
+  - npminstall
+script:
+  - npm run ci
+after_script:
+  - npminstall codecov && codecov

+ 33 - 0
wj-pack/backend/README.md

@@ -0,0 +1,33 @@
+# qianpangpang
+
+qianpangpang rn app
+
+## QuickStart
+
+<!-- add docs here for user -->
+
+see [egg docs][egg] for more detail.
+
+### Development
+
+```bash
+$ npm i
+$ npm run dev
+$ open http://localhost:7001/
+```
+
+### Deploy
+
+```bash
+$ npm start
+$ npm stop
+```
+
+### npm scripts
+
+- Use `npm run lint` to check code style.
+- Use `npm test` to run unit test.
+- Use `npm run autod` to auto detect dependencies upgrade, see [autod](https://www.npmjs.com/package/autod) for more detail.
+
+
+[egg]: https://eggjs.org

+ 35 - 0
wj-pack/backend/app/const.js

@@ -0,0 +1,35 @@
+
+module.exports = {
+    PayFreqUnit: {
+        Day:0,
+        Manth:1,
+        Year:2,
+        Dun:3,
+    },
+    CoverageDurationType:{
+       //保险期限单位 0-天 1-月 2-年 3-至**岁 4-终身
+       Day: 0 ,
+       Month:1,
+       Year:2,
+       ToAge:3,
+       Life: 4,
+       Other:5,
+    },
+    InsanceState:{
+        UnEffect: 0,
+        Effective: 1,
+        Expired: 2,
+    },
+    RoleNames:["未定义","总参谋长","支队长","融合力量","远航终端","参谋终端","航管员","气象员","战勤","导调",
+        "领航","未定义","未定义","未定义","未定义","未定义","未定义","未定义","未定义","未定义",    //10-19
+        "飞行员","机务"
+    ],
+    Weathers:["雨天","晴天","雪天","沙尘","雷暴"],
+    Times: ["白天","黑夜"],
+    
+    VehicleNames: ["直8","直9","直11","米171","运12","运7"],
+    MapNames:["舟山普陀机场","喀什机场","阿坝红原机场","太谷机场","博鳌机场","昌都机场","山东聊城军事机场","湘阴机场","中江机场"],
+    WeaponNames:["震爆弹","语音喊话","机枪","绳索","全轮着陆人员","索降人员","悬停速降人员","灭火","空投"],
+    StatisName: ['empty',"坠毁次数","接收故障总数量", "成功排查故障次数", "灭火任务完成时间","舱门射击任务完成时间", "搜索任务完成时间","空中投送成功次数","悬停索降成功次数", "悬停索降失败次数", "机降成功次数","机降失败次数", "抢险救援完成时间"]
+    
+}

+ 100 - 0
wj-pack/backend/app/controller/admin/company.js

@@ -0,0 +1,100 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+class CompanyController extends Controller {
+
+    async list() {
+        const {ctx} = this;
+        
+        let {pageNo, pageSize, _t, name} = ctx.request.query;
+
+        if( !pageNo ) pageNo = 1;
+        if( !pageSize ) pageSize = 10;
+        
+        pageNo = parseInt( pageNo );
+        pageSize = parseInt( pageSize );
+        
+        let ret = await ctx.service.company.listPage( pageNo, pageSize, name);
+        
+        ctx.adminOK(ret, _t);
+    }
+
+    async listProd() {
+        const {ctx} = this;
+        
+        let {pageNo, pageSize, _t, cmpy_id, name} = ctx.request.query;
+
+        if( !pageNo ) pageNo = 1;
+        if( !pageSize ) pageSize = 10;
+        
+        pageNo = parseInt( pageNo );
+        pageSize = parseInt( pageSize );
+        
+        let ret = await ctx.service.company.listProdPage( pageNo, pageSize, name, cmpy_id);
+        
+        ctx.adminOK(ret, _t);
+    }
+
+    async delete() {
+
+        const {ctx} = this;
+        let {id} = ctx.request.query;
+        
+        let ret = await ctx.service.company.deleteCompany( id );
+        
+
+        ctx.adminOK(ret, "删除成功");
+    }
+
+    async deleteProd() {
+
+        const {ctx} = this;
+        let {id} = ctx.request.query;
+        
+        let ret = await ctx.service.company.deleteProd( id );
+        
+        ctx.adminOK(ret, "删除成功");
+    }
+
+    async add() {
+
+        const {ctx} = this;
+
+        let data = ctx.request.body;
+        
+        let ret = await ctx.service.company.addCompany( data );
+        
+        
+        ctx.adminOK(ret, "添加成功");
+    }
+
+    async addProd() {
+
+        const {ctx} = this;
+        let data = ctx.request.body;
+        let ret = await ctx.service.company.addProd( data );
+        ctx.adminOK(ret, "添加成功");
+    }
+
+    async edit() {
+        const {ctx} = this;
+
+        let data = ctx.request.body;
+        let ret = await ctx.service.company.editCompany( data );
+    
+        ctx.adminOK(ret, "更新成功");
+    }
+
+    async editProd() {
+        const {ctx} = this;
+
+        let data = ctx.request.body;
+        let ret = await ctx.service.company.editProd( data );
+    
+        ctx.adminOK(ret, "更新成功");
+    }
+    
+}
+
+module.exports = CompanyController;

+ 54 - 0
wj-pack/backend/app/controller/admin/course.js

@@ -0,0 +1,54 @@
+'use strict';
+
+const await = require('await-stream-ready/lib/await');
+const { bodyHandleByService } = require('../../extend/context');
+
+const Controller = require('egg').Controller;
+
+class CourseController extends Controller {
+
+  async list() {
+
+    const {ctx, service} = this;
+    let query = ctx.request.query;
+    let ret = await service.course.adminList(query);
+    ctx.adminOK(ret);
+  }
+
+  async delete() {
+    const {ctx, service} = this;
+    let id = ctx.request.query.id;
+    let ret = await service.course.delete(id);
+
+    ctx.adminOK(ret, "删除成功");
+  }
+
+  async edit() {
+    const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.course.edit( data );
+    ctx.adminOK(ret, "更新成功");
+  }
+
+  async add() {
+    const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.course.add( data );
+    ctx.adminOK(ret, "添加成功");
+  }
+  async exportXls() {
+    const {ctx, service} = this;
+    ctx.set("Content-Type", "application/vnd.openxmlformats");
+    ctx.set("Content-Disposition","attachment;filename*=UTF-8 xx.xlsx");
+    let ret = await service.course.exportXls( ctx.request.query );
+    ctx.body = ret;
+  }
+
+  async lock () {
+    const {ctx, service} = this;
+    
+    await ctx.bodyHandleByService(service.course, "lock", "操作成功");
+  }
+}
+
+module.exports = CourseController;

+ 115 - 0
wj-pack/backend/app/controller/admin/dict.js

@@ -0,0 +1,115 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+class DictController extends Controller {
+
+  async list() {
+   
+    const {ctx} = this;
+    
+    let {pageNo, pageSize, _t, dictName, dictCode} = ctx.request.query;
+    if( !pageNo ) pageNo = 1;
+    if( !pageSize ) pageSize = 10;
+    
+    pageNo = parseInt( pageNo );
+    pageSize = parseInt( pageSize );
+
+    let ret = await ctx.service.dict.listPage( pageNo, pageSize, dictName, dictCode);
+
+    ctx.adminOK(ret, _t);
+  }
+
+  async edit(){
+    const {ctx} = this;
+  
+    let data = ctx.request.body;
+    let ret = await ctx.service.dict.updateDict( data );
+
+    ctx.adminOK(ret, "更新成功");
+  }
+  async editItem(){
+    const {ctx} = this;
+  
+    let {id, data} = ctx.request.body;
+
+    console.log( "adding", ctx.request.body );
+
+    let ret = await ctx.service.dict.editItem(id, data);
+
+    ctx.adminOK(ret, "编辑成功");
+  }
+  
+  async delete(){
+    const {ctx} = this;
+  
+    let {id} = ctx.request.query;
+    
+    let ret = await ctx.service.dict.deleteDict( id );
+
+    ctx.adminOK(ret, "删除成功");
+  }
+
+  async deleteItem() {
+
+    const {ctx} = this;
+  
+    let {id, itemValue} = ctx.request.query;
+
+    let ret = await ctx.service.dict.deleteDictItem( id, itemValue);
+
+    ctx.adminOK(ret, "删除成功");
+  }
+
+  async add() {
+    const {ctx} = this;
+  
+    let data = ctx.request.body;
+
+    let ret = await ctx.service.dict.addDict( data );
+
+    ctx.adminOK(ret, "添加成功");
+  }
+
+  async addItem() {
+    const {ctx} = this;
+  
+    let {id, data} = ctx.request.body;
+
+    console.log( "adding", ctx.request.body );
+
+    let ret = await ctx.service.dict.addItem(id, data);
+
+    ctx.adminOK(ret, "添加成功");
+  }
+  async check () {
+    const {ctx} = this;
+  
+    let data = ctx.request.query;
+
+    let ok  = await ctx.service.dict.check( data );
+
+    if( ok ) {
+      ctx.adminOK(true);
+      return;
+    }
+
+    ctx.adminFail("dictCode已经存在!");
+  }
+  async listItems(){
+    const {ctx} = this;
+ 
+    let {pageNo, pageSize, _t, itemText, status, dictId} = ctx.request.query;
+    if( !pageNo ) pageNo = 1;
+    if( !pageSize ) pageSize = 10;
+    
+    pageNo = parseInt( pageNo );
+    pageSize = parseInt( pageSize );
+
+    let ret = await ctx.service.dict.listItems( pageNo, pageSize,dictId, itemText, status);
+
+    ctx.adminOK(ret, _t);
+  }
+}
+
+module.exports = DictController;

+ 35 - 0
wj-pack/backend/app/controller/admin/icon.js

@@ -0,0 +1,35 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+/*
+军标库请求处理
+*/
+class CoinController extends Controller {
+
+  async list() {
+
+    const {ctx, service} = this;
+
+    await ctx.queryHandleByService( service.icon, "list");
+  }
+
+  async delete() {
+    const {ctx, service} = this;
+
+    await ctx.queryHandleByService( service.icon, "delete");
+  }
+
+  async edit() {
+    const {ctx, service} = this;
+
+    await ctx.bodyHandleByService( service.icon, "edit", "更新成功");
+  }
+
+  async add() {
+    const {ctx, service} = this;
+    await ctx.bodyHandleByService( service.icon, "add", "添加成功");
+  }
+}
+
+module.exports = CoinController;

+ 85 - 0
wj-pack/backend/app/controller/admin/index.js

@@ -0,0 +1,85 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+const svgCaptcha = require('svg-captcha');
+const md5 = require('md5-node');
+
+class AdminController extends Controller {
+
+  async login() {
+   
+    const {ctx, service} = this;
+    let {username , password, captcha, checkKey} = ctx.request.body;
+
+    let error = null;
+    if( !username ) error = '用户名为空!';
+    if( !password ) error = '密码为空!';
+    if( !checkKey ) error = 'checkKey为空!';
+    if( !captcha ) error = "验证码无效";
+
+    if( error ) {
+      ctx.adminFail(error);
+      return;
+    }
+
+    captcha = captcha.toLowerCase();
+    let cacheKey =  md5(captcha + checkKey);
+    let code =  await ctx.service.cache.getString( cacheKey )
+
+    if( !code || code != captcha) {
+      ctx.adminFail("验证码无效");
+      return;
+    }
+    // await ctx.service.cache.removeCache( cacheKey );
+
+    let ret = await service.adminUser.login(username, password);
+
+    ctx.adminOK(ret, '登录成功!');
+  }
+
+  async loginOut() {
+    const { ctx } = this;
+
+    throw "error test";
+    // ctx.body = 'admin loginOut';
+  }
+
+  async captcha() {
+    const { ctx , app} = this;
+
+    const captcha = svgCaptcha.create({
+        size: 4,
+        fontSize: 50,
+        width: 100,
+        height: 40,
+        bacground: '#cc9966'
+    });
+    //ctx.session.captcha = captcha.text;
+    let key = ctx.params.key;
+     if( !key ) {
+       ctx.adminFail("no key");
+       return;
+     }
+
+     let code = captcha.text;
+     let lowerCaseCode = code.toLowerCase();
+     let realKey = md5(lowerCaseCode+key);
+     
+     await ctx.service.cache.setString(realKey, lowerCaseCode, 60);
+
+    ctx.adminOK({type: 'image/svg+xml', svg: captcha.data});
+  }
+
+  async duplicateCheck(){
+    let {ctx, service} = this;
+    let query = ctx.request.query;
+    let ok = await service.sys.duplicateCheckOk( query );
+    if( ok ) {
+      ctx.adminOK(true);
+      return;
+    }
+    ctx.adminFail(false);
+  }
+}
+
+module.exports = AdminController;

+ 43 - 0
wj-pack/backend/app/controller/admin/logs.js

@@ -0,0 +1,43 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+class LogsController extends Controller {
+    
+    async listNormal(){
+        let {ctx, service} = this;
+
+        let data = ctx.request.query;
+        let ret = await service.logs.adminListLogs(data);
+        ctx.adminOK( ret );
+    }
+
+    async listFlyPosture() {
+
+        let {ctx, service} = this;
+        let data = ctx.request.query;
+        let ret = await service.logs.adminListFlyPosture(data);
+        ctx.adminOK( ret );
+    }
+
+    async listMessage() {
+
+         let {ctx, service} = this;
+        let data = ctx.request.query;
+        let ret = await service.logs.adminListMessage(data);
+
+        ctx.adminOK( ret );
+    }
+
+
+    async exportXls(){
+        const {ctx, service} = this;
+        ctx.set("Content-Type", "application/vnd.openxmlformats");
+        ctx.set("Content-Disposition","attachment;filename*=UTF-8 xx.xlsx");
+        let ret = await service.logs.exportXls( ctx.request.query );
+        ctx.body = ret;
+    }
+    
+}
+
+module.exports = LogsController;

+ 61 - 0
wj-pack/backend/app/controller/admin/record.js

@@ -0,0 +1,61 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+class RecordController extends Controller {
+
+  async list() {
+
+    const {ctx, service} = this;
+    let query = ctx.request.query;
+    let ret = await service.record.adminList(query);
+
+    ctx.adminOK(ret);
+  }
+  async detail() {
+
+    const {ctx, service} = this;
+    let query = ctx.request.query;
+    let ret = await service.record.detail(query);
+    ctx.adminOK(ret);
+  }
+
+  async delete() {
+    const {ctx, service} = this;
+    let id = ctx.request.query.id;
+    let ret = await service.record.delete(id);
+
+    ctx.adminOK(ret, "删除成功");
+  }
+
+  async edit() {
+    const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.record.edit( data );
+    ctx.adminOK(ret, "更新成功");
+  }
+
+  async add() {
+    const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.record.add( data );
+    ctx.adminOK(ret, "添加成功");
+  }
+
+  async exportXls() {
+    const {ctx, service} = this;
+    ctx.set("Content-Type", "application/vnd.openxmlformats");
+    ctx.set("Content-Disposition","attachment;filename*=UTF-8 xx.xlsx");
+    let ret = await service.record.exportXls( ctx.request.query );
+    ctx.body = ret;    
+  }
+  async itemExportXls() {
+    const {ctx, service} = this;
+    ctx.set("Content-Type", "application/vnd.openxmlformats");
+    ctx.set("Content-Disposition","attachment;filename*=UTF-8 xx.xlsx");
+    let ret = await service.record.itemExportXls( ctx.request.query );
+    ctx.body = ret;   
+  }
+}
+
+module.exports = RecordController;

+ 97 - 0
wj-pack/backend/app/controller/admin/user.js

@@ -0,0 +1,97 @@
+'use strict';
+
+const await = require('await-stream-ready/lib/await');
+
+const Controller = require('egg').Controller;
+
+class UserController extends Controller {
+
+  async list() {
+
+    const {ctx, service} = this;
+    let query = ctx.request.query;
+    let ret = await service.adminUser.list(query);
+    ctx.adminOK(ret);
+  }
+
+  async delete() {
+    const {ctx, service} = this;
+    let id = ctx.request.query.id;
+    let ret = await service.adminUser.delete(id);
+
+    ctx.adminOK(ret, "删除成功");
+  }
+
+  async edit() {
+    const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.adminUser.edit( data );
+    ctx.adminOK(ret, "更新成功");
+  }
+
+  async add() {
+    const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.adminUser.add( data );
+    ctx.adminOK(ret, "添加成功");
+  }
+
+  async resetpwd() {
+     const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.adminUser.resetpwd( data );
+    ctx.adminOK(ret, "重置成功");
+  }
+
+  async lock() {
+    const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.adminUser.lockUser( data );
+    ctx.adminOK(ret, "冻结成功");
+  }
+  
+  async teachers() {
+    const {ctx, service} = this;
+    let query = ctx.request.query;
+    query.role = 1;
+    let ret = await service.adminUser.list(query);
+    
+    ctx.adminOK(ret);
+  }
+
+  async getProfile() {
+    const {ctx, service} = this;
+    await ctx.queryHandleByService(service.adminUser, "getUserProfile");
+  }
+
+  async getUserRecord() {
+    const {ctx, service} = this;
+    await ctx.queryHandleByService(service.record, "getUserRecord");
+  }
+
+  async getUserRecordList() {
+    const {ctx, service} = this;
+    await ctx.queryHandleByService(service.record, "getUserRecordList");
+  }
+  async commentUserRecord() {
+    const {ctx, service} = this;
+    await ctx.bodyHandleByService(service.adminUser, "commentUserRecord", "提交成功");
+  }
+
+  async exportXls() {
+    const {ctx, service} = this;
+    ctx.set("Content-Type", "application/vnd.openxmlformats");
+    ctx.set("Content-Disposition","attachment;filename*=UTF-8 xx.xlsx");
+    let ret = await service.adminUser.exportUserListXls( ctx.request.query );
+    ctx.body = ret;
+  }
+  async exportProfileXls() {
+    const {ctx, service} = this;
+    ctx.set("Content-Type", "application/vnd.openxmlformats");
+    ctx.set("Content-Disposition","attachment;filename*=UTF-8 xx.xlsx");
+    let ret = await service.adminUser.exportProfileXls( ctx.request.query );
+    ctx.body = ret;
+  }
+}
+
+module.exports = UserController;

+ 43 - 0
wj-pack/backend/app/controller/admin/weapon.js

@@ -0,0 +1,43 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+/*
+军标库请求处理
+*/
+class WeaponController extends Controller {
+
+  async list() {
+
+    const {ctx, service} = this;
+
+    await ctx.queryHandleByService( service.weapon, "list");
+  }
+
+  async delete() {
+    const {ctx, service} = this;
+
+    await ctx.queryHandleByService( service.weapon, "delete", "删除成功");
+  }
+
+  async edit() {
+    const {ctx, service} = this;
+
+    await ctx.bodyHandleByService( service.weapon, "edit", "更新成功");
+  }
+
+  async add() {
+    const {ctx, service} = this;
+    await ctx.bodyHandleByService( service.weapon, "add", "添加成功");
+  }
+
+  async exportXls( ) {
+    const {ctx, service} = this;
+    ctx.set("Content-Type", "application/vnd.openxmlformats");
+    ctx.set("Content-Disposition","attachment;filename*=UTF-8 xx.xlsx");
+    let ret = await service.weapon.exportXls( ctx.request.query );
+    ctx.body = ret;
+  }
+}
+
+module.exports = WeaponController;

+ 29 - 0
wj-pack/backend/app/controller/app/course.js

@@ -0,0 +1,29 @@
+'use strict';
+
+const md5 = require('md5-node');
+
+const Controller = require('egg').Controller;
+class CourseController extends Controller {
+    
+    async list() {
+        let {ctx, service} = this;
+        let ret = await service.course.list();
+        ctx.resultOK( ret );
+    }
+
+    async add() {
+        let {ctx, service} = this;
+        let data = ctx.request.body;
+        let ret = await service.course.add(data);
+        ctx.resultOK( ret );
+    }
+
+    async save() {
+        let {ctx, service} = this;
+        let data = ctx.request.body;
+        let ret = await service.course.save(data);
+        ctx.resultOK( ret );
+    }
+}
+
+module.exports = CourseController;

+ 18 - 0
wj-pack/backend/app/controller/app/icon.js

@@ -0,0 +1,18 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+/*
+军标库请求处理
+*/
+class CoinController extends Controller {
+
+  async list() {
+
+    const {ctx, service} = this;
+
+    await ctx.queryHandleByServiceInApp( service.icon, "listInApp");
+  }
+}
+
+module.exports = CoinController;

+ 214 - 0
wj-pack/backend/app/controller/app/insurant.js

@@ -0,0 +1,214 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+class InsurantController extends Controller {
+
+    async addPicture() {
+        let {ctx } = this;
+        let { pictures } = ctx.request.body;
+        let id = ctx.state.user.id;
+
+        if( !pictures || pictures.length < 1 ) {
+            ctx.resultFail("图片数据有误");
+            return;
+        }
+
+        let ret = await ctx.service.insurant.addPictures(id, pictures);
+
+        ctx.resultOK(ret, "添加成功");
+    }
+    async getExtendinfo() {
+        let {ctx } = this;
+        let { _id} = ctx.request.query;
+        if( !_id ) {
+            ctx.resultFail("id为空!");
+            return;
+        }
+        let ret = await ctx.service.insurant.getExtendinfo(_id)
+        ctx.resultOK(ret, "获取成功");
+    }
+
+    async getPicture() {
+        let {ctx } = this;
+        let { id } = ctx.request.query;
+        if( !id ) {
+            ctx.resultFail("id为空!");
+            return;
+        }
+        let ret = await ctx.service.insurant.getInfo(id, {pictures:1});
+
+        ctx.resultOK(ret, "获取成功");
+    }
+    async policyList() {
+        let {ctx, service } = this;
+        let id = ctx.state.user.id;
+        let type = ctx.request.query.type;
+        let ret = await service.insurant.policyList(id, type);
+
+        ctx.resultOK( ret );
+    }
+
+
+    async list(){
+        let {ctx, service } = this;
+        let id = ctx.state.user.id;
+
+        //列表条件 被保险人,保单类型,保障状态, 排序规则 0-距离下次缴费时间降序 1-距离下次缴费时间升序 2到期时间降序 3 到期时间升序
+        let {uid, type, state, order, page, size} = ctx.request.query;
+        if( page == undefined ) page = 0;
+        if( size == undefined ) size = 10;
+        page = parseInt( page );
+        size = parseInt( size );
+        if( order != undefined ) order = parseInt( order );
+        
+        console.log( uid, type, state, order, page, size);
+
+        let ret = await service.insurant.list(id, {uid, type, state, order, page, size});
+
+        ctx.resultOK( ret );
+    }
+
+    async policyStatics(){
+        let {ctx, service } = this;
+        let id = ctx.state.user.id;
+
+        let ret = await service.insurant.policyStatics(id);
+
+        ctx.resultOK( ret );
+    }
+
+    async pictureList(){
+        let {ctx, service } = this;
+        let id = ctx.state.user.id;
+
+        let ret = await service.insurant.pictureList(id);
+
+        ctx.resultOK( ret );
+    }
+
+    async detail() {
+        let {ctx } = this;
+        let { id } = ctx.request.query;
+        if( !id ) {
+            ctx.resultFail("id为空!");
+            return;
+        }
+        let ret = await ctx.service.insurant.getDetail(id);
+
+        ctx.resultOK(ret, "获取成功");
+    }
+    
+    async extendinfo() {
+        let {ctx } = this;
+        let { coverageItems, additionalInsurance, payBank, payBankCard,agent,agentPhone,remarks, _id} = ctx.request.body;
+        if( !_id ) {
+            ctx.resultFail("id为空!");
+            return;
+        }
+        let data = {};
+        if( coverageItems ) data.coverageItems = coverageItems;
+        if( additionalInsurance ) data.additionalInsurance = additionalInsurance;
+        if( payBank ) data.payBank = payBank;
+        if( payBankCard ) data.payBankCard = payBankCard;
+        if( agent ) data.agent = agent;
+        if( agentPhone ) data.agentPhone = agentPhone;
+        if( remarks ) data.remarks = remarks;
+
+        if( Object.keys(data).length < 1 ) {
+            ctx.resultFail("更新字段为空!");
+            return;
+        }
+    
+        let ret = await ctx.service.insurant.updateInfoById(_id, data)
+
+        ctx.resultOK(ret, "更新成功");
+    }
+
+    async addbase() {
+        let {ctx } = this;
+        let  data = ctx.request.body;
+        let id = ctx.state.user.id;
+
+        let ret = await ctx.service.insurant.addbase(id, data);
+
+        ctx.resultOK(ret, "添加成功");
+    }
+
+    //更新图片
+    async updatePicture() {
+        let {ctx } = this;
+        let { pictures, id} = ctx.request.body;
+        if( !id ) {
+            ctx.resultFail("id为空!");
+            return;
+        }
+        let data = {};
+        if( !pictures ) {
+            ctx.resultFail("图片字段为空!");
+            return;
+        }
+        let ret = await ctx.service.insurant.updateInfoById(id, {pictures});
+
+        ctx.resultOK(ret, "更新成功");
+    }
+
+
+    async updatePayInfo() {
+        let {ctx } = this;
+        let { effectiveTime, coverageDuration, payMethod, payAmount,payDuration, _id} = ctx.request.body;
+        if( !_id ) {
+            ctx.resultFail("id为空!");
+            return;
+        }
+        let data = {};
+        if( effectiveTime ) data.effectiveTime = effectiveTime;
+        if( coverageDuration ) data.coverageDuration = coverageDuration;
+        if( payMethod ) data.payMethod = payMethod;
+        if( payAmount ) data.payAmount = payAmount;
+        if( payDuration ) data.payDuration = payDuration;
+
+
+        if( Object.keys(data).length < 1 ) {
+            ctx.resultFail("更新字段为空!");
+            return;
+        }
+        let ret = await ctx.service.insurant.updateInfoById(_id, data)
+
+        ctx.resultOK(ret, "更新成功");
+    }
+
+    //添加保单
+    async add() {
+        let {ctx } = this;
+        let  data = ctx.request.body;
+        let id = ctx.state.user.id;
+
+        let ret = await ctx.service.insurant.add(id, data);
+
+        ctx.resultOK(ret, "添加成功");
+    }
+
+    async update() {
+        let {ctx } = this;
+        let  data = ctx.request.body;
+
+        let id = ctx.state.user.id;
+        
+        let ret = await ctx.service.insurant.update(id, data);
+
+        ctx.resultOK(ret, "更新成功");
+    }
+
+    //首页保单,完成保单缴费
+    async payed() {
+        let {ctx } = this;
+
+        let  id = ctx.request.body.id;
+        let ret = await ctx.service.insurant.payed(id);
+        ctx.resultOK(ret, "设置成功");
+    }
+
+}
+
+module.exports = InsurantController;

+ 34 - 0
wj-pack/backend/app/controller/app/logs.js

@@ -0,0 +1,34 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+class LogsController extends Controller {
+    
+    async add(){
+        let {ctx, service} = this;
+
+        let data = ctx.request.body;
+        let ret = await service.logs.add(data);
+
+        ctx.resultOK( ret );
+    }
+
+    async flyPosture() {
+
+        let {ctx, service} = this;
+        let data = ctx.request.body;
+        let ret = await service.logs.flyPosture( data );
+        ctx.resultOK( ret );
+    }
+
+    async flyState() {
+
+        let {ctx, service} = this;
+        let data = ctx.request.body;
+        let ret = await service.logs.flyState( data );
+        ctx.resultOK( ret );
+    }
+    
+}
+
+module.exports = LogsController;

+ 30 - 0
wj-pack/backend/app/controller/app/map.js

@@ -0,0 +1,30 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+class MapController extends Controller {
+
+    async points(){
+        let {ctx, service} = this;
+
+        let adcode = ctx.request.query.adcode;
+
+        let ret = await service.map.points( adcode );
+        
+        ctx.resultOK(ret);
+    }
+
+    async search() {
+        let {ctx, service} = this;
+
+        await ctx.queryHandleByServiceInApp(service.map, "search");
+    }
+
+    async updateNaviConfig() {
+        let {ctx, service} = this;
+        
+        await ctx.bodyHandleByServiceInApp(service.map, "updateNaviConfig");
+    }
+}
+
+module.exports = MapController;

+ 23 - 0
wj-pack/backend/app/controller/app/message.js

@@ -0,0 +1,23 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+/**
+ * 文书管理器
+ */
+class MessageController extends Controller {
+
+    //发送文书
+    async add() {
+        let {ctx, service} = this;
+
+        let data = ctx.request.body;
+
+
+        let ret = await service.message.add(data);
+
+        ctx.resultOK( ret );
+    }
+}
+
+module.exports = MessageController;

+ 103 - 0
wj-pack/backend/app/controller/app/other.js

@@ -0,0 +1,103 @@
+'use strict';
+
+const await = require('await-stream-ready/lib/await');
+
+const Controller = require('egg').Controller;
+
+class HelpController extends Controller {
+
+    async list() {
+        let {ctx, service} = this;
+        let {page, size} = ctx.request.query;
+        if( page == undefined || page == "" ) page = 0;
+        if( size == undefined || size == "") size = 30;
+
+        let ret = await service.help.search("", page, size);
+        ctx.resultOK( ret );
+    }
+
+    async search() {
+        let {ctx, service} = this;
+        let {page, size, name} = ctx.request.query;
+        if( page == undefined || page == "") page = 0;
+        if(  size == undefined || size == "" ) size = 30;
+        page = parseInt( page );
+        size = parseInt( size );
+
+        let ret = await service.help.search(name, page, size);
+        ctx.resultOK( ret );
+    }
+
+    async receiverList() {
+        let {ctx, service} = this;
+        let uid = ctx.state.user.id;
+        let ret = await service.help.receiverList(uid);
+        ctx.resultOK( ret );
+    }
+
+    async receiverAdd() {
+        let {ctx, service} = this;
+        let uid = ctx.state.user.id;
+        let ret = await service.help.receiverAdd(uid, ctx.request.body);
+
+        ctx.resultOK( ret );
+    }
+
+    async receiverDelete(){
+        let {ctx, service} = this;
+        let id = ctx.request.body.id;
+        let ret = await service.help.receiverDelete( id );
+        ctx.resultOK( ret );
+    }
+
+    async getSyncPolicy() {
+        let {ctx, service} = this;
+        let id = ctx.state.user.id;
+
+        let ret = await service.help.getSyncPolicy( id );
+        ctx.resultOK( ret );
+    }
+    
+    async hasSyncPolicy() {
+        let {ctx, service} = this;
+        let id = ctx.state.user.id;
+
+        let ret = await service.help.hasSyncPolicy( id );
+        ctx.resultOK( ret );
+    }
+
+    async syncUpdate() {
+        let {ctx, service} = this;
+
+        let {reject, recieve} = ctx.request.body;
+
+        let ret = await service.help.syncUpdate(reject, recieve);
+        
+        ctx.resultOK( ret );
+    }
+    async bigScreen() {
+        let {ctx, service} = this;
+
+        await ctx.queryHandleByService(service.help, "bigScreen");
+    }
+
+    async naviConfig() {
+        let {ctx, service} = this;
+
+        await ctx.queryHandleByService(service.help, "getNaviConfigLine");
+    }
+
+    async twolines() {
+        let {ctx, service} = this;
+
+        await ctx.queryHandleByService(service.help, "getTwoLines");
+    }
+
+    async pilotFlyLines() {
+        let {ctx, service} = this;
+        await ctx.queryHandleByService(service.help, "getUserNaviLines");
+    }
+}
+
+
+module.exports = HelpController;

+ 50 - 0
wj-pack/backend/app/controller/app/record.js

@@ -0,0 +1,50 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+class RecordController extends Controller {
+    
+    async create() {
+
+        let {ctx, service} = this;
+        let {teacherId, templateId, title} = ctx.request.body;
+
+        let ret = await service.record.create(teacherId, templateId, title);
+
+        ctx.resultOK( ret );
+    }
+
+    async update() {
+        let {ctx, service} = this;
+
+        let data = ctx.request.body;
+        let ret = await service.record.update( data );
+        ctx.resultOK( ret );
+    }
+    
+    async complete() {
+        let {ctx, service} = this;
+
+        let data = ctx.request.body;
+        let ret = await service.record.complete( data );
+        ctx.resultOK( ret );
+    }
+
+    //回放列表
+    async playbackList() {
+
+        let {ctx, service} = this;
+        let query = ctx.request.query;
+        let ret = await service.record.playbackList( query );
+        ctx.resultOK( ret );
+    }
+
+    //添加回放
+    async addPlayback() {
+        let {ctx, service} = this;
+        let body = ctx.request.body;
+        let ret = await service.record.addPlayback( body );
+        ctx.resultOK( ret );
+    }
+}
+
+module.exports = RecordController;

+ 40 - 0
wj-pack/backend/app/controller/app/user.js

@@ -0,0 +1,40 @@
+'use strict';
+
+const md5 = require('md5-node');
+
+const Controller = require('egg').Controller;
+
+class UserController extends Controller {
+
+  async loginPassword() {
+    const {ctx, app} = this;
+    let {name,pwd} = ctx.request.body;
+    console.log( ctx.request.body );
+
+    if( !name ) {
+      ctx.resultFail("登陆用户名不能为空");
+        return;
+    }
+    let md5pwd = md5(pwd);
+    console.log( md5pwd );
+
+    let user = await app.mysql.get("users", {name, pwd:md5pwd}, {columns:["id","name","realname","code","role"]});
+
+    if( user && user.id ) {
+      
+      await app.mysql.query("update users set last_login_time=now(), last_login_ip=? where id=?",[ctx.ip, user.id]);
+
+      let config = app.config.loginUser;
+
+      //let token = await ctx.jwtSign({name:user.name, id:user.id}, config.secret, { expiresIn: config.expiresIn });
+
+      ctx.resultOK(user, "登录成功");
+      // ctx.resultFail("错误提示");
+      return;
+    }
+
+    ctx.resultFail("账号密码不对");
+  }
+}
+
+module.exports = UserController;

+ 23 - 0
wj-pack/backend/app/controller/app/weapon.js

@@ -0,0 +1,23 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+/*
+军标库请求处理
+*/
+class WeaponController extends Controller {
+
+  async supportedPlane() {
+
+    const {ctx, service} = this;
+
+    await ctx.queryHandleByServiceInApp( service.weapon, "supportedPlane");
+  }
+  async getPlaneInfo() {
+    const {ctx, service} = this;
+
+    await ctx.queryHandleByServiceInApp( service.weapon, "getPlaneInfo");
+  }
+}
+
+module.exports = WeaponController;

+ 143 - 0
wj-pack/backend/app/controller/baidu/index.js

@@ -0,0 +1,143 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+const urlencode = require('urlencode');
+const Insurance_reg_host = "https://aip.baidubce.com/rest/2.0/ocr/v1/insurance_documents";
+const client_id = "ijsEjPQODRIZjdrh3Q3YvhpO";
+const client_secret = "ZM1Bq2UH4NuEllsV07LLbL5XTqtqcWr2";
+
+const TokenCacheName = "baidu#token";
+
+function meargeObj(result, src)
+{
+    if( !src ) return;
+
+    for( let k in src) {
+        let v = src[k];
+        if( !v ) continue;
+
+        if( Array.isArray(v) ) {
+
+            if( !result[k] || result[k].length < 1) {
+
+                let validArr = [];
+               
+                v.forEach(el=>{
+                    let ok = false;
+                    for(let k2 in el) {
+                        if( el[k2] ) ok = true;
+                    }
+                    validArr.push( el );
+                })
+
+                if( validArr.length > 0 ) {
+                    result[k] = validArr;
+                }
+            }
+        } else if( !result[k] ) {
+            result[k] = src[k];
+        }
+    }
+    return result;
+}
+
+class BaiduController extends Controller {
+    
+    async getBaiduToken(){
+        let {ctx, app} = this;
+
+        let token = await ctx.service.cache.getString(TokenCacheName);
+        if( token ) return token;
+
+        let ret = await app.curl(`https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=${client_id}&client_secret=${client_secret}`, {method:"POST", dataType:"json"});
+        // {
+        //     "refresh_token": "25.b55fe1d287227ca97aab219bb249b8ab.315360000.1798284651.282335-8574074",
+        //     "expires_in": 2592000,
+        //     "scope": "public wise_adapt",
+        //     "session_key": "9mzdDZXu3dENdFZQurfg0Vz8slgSgvvOAUebNFzyzcpQ5EnbxbF+hfG9DQkpUVQdh4p6HbQcAiz5RmuBAja1JJGgIdJI",
+        //     "access_token": "24.6c5e1ff107f0e8bcef8c46d3424a0e78.2592000.1485516651.282335-8574074",
+        //     "session_secret": "dfac94a3489fe9fca7c3221cbf7525ff"
+        //   }
+        console.log("token", ret.data);
+
+        if( ret.status == 200 )  {
+            let data = ret.data;
+            await ctx.service.cache.setString(TokenCacheName, data.access_token, data.expires_in);
+            return data.access_token;
+        }
+        
+        throw ret.data;
+    }
+
+    async picRecognition(){
+        let {ctx, app} = this;
+        let { pictures } = ctx.request.body;
+        if( !pictures || pictures.length < 1 ) {
+            ctx.resultFail("图片数据有误");
+            return;
+        }
+
+        let result = {
+            BenPerLst:	[], //array[]受益人信息
+            BenCltNa: "",	//string    受益人姓名
+            BenPerPro:"",   //string	受益比例
+            BenPerOrd:"",	//string	受益顺序
+            BenPerTyp:"",	//string	受益人类型
+            InsBilCom:"",	//string	公司名称
+            InsBilNo:"",	//string	保险单号码
+            InsBilTim:"",	//string	保单生效日期
+            InsCltGd1:"",	//string	投保人性别
+            InsCltNa1:"",	//string	投保人
+            InsIdcNb1:"",	//string	投保人证件号码
+            InsIdcTy1:"",	//string	投保人证件类型
+            InsPerLst:[],	//array[]	被保人信息
+            InsCltGd2:"",	//string	被保人性别
+            InsCltNa2:"",	//string	被保险人
+            InsBthDa2:"",	//string	被保险人出生日期
+            InsIdcNb2:"",	//string	被保险人证件号码
+            InsIdcTy2:"",	//string	被保险人证件类型
+            InsPrdList:[],	//array[]	保险信息
+            InsCovDur:"",	//string	保险期限
+            InsIcvAmt:"",	//string	基本保险金额
+            InsPayDur:"",	//string	交费期间
+            InsPayFeq:"",	//string	缴费频率
+            InsPerAmt:"",	//string	每期交费金额
+            InsPrdNam:"",	//string	产品名称
+        };
+
+        let n = pictures.length;
+
+        while( n-- ) {
+           let ret = await app.curl(pictures[n]);
+           console.log(pictures[n], ret.status);
+           
+           if( ret.status >= 200 && ret.status < 300 ) {
+            // let type = ret.headers["content-type"];
+            // let prefix = "data:" + type + ";base64,";
+            let base64 = Buffer.from( ret.data ).toString("base64");
+            let image =  urlencode(base64, 'utf8');
+            let token = await this.getBaiduToken();
+
+            console.log(base64.length / 1024 );
+            
+            try {
+                ret = await app.curl(Insurance_reg_host+"?access_token=" + token, {method: "POST", dataType:'json', data:"image="+image, headers:{
+                    "content-type":"application/x-www-form-urlencoded"
+                 }});    
+                 let words_result = ret.data.words_result;
+                 meargeObj(result,  words_result);
+
+            } catch (error) {
+                console.warn(error.message);
+            }
+           }
+        }
+
+        console.log( result );
+        //todo 把result 转为我们自己的格式
+        
+        ctx.resultOK( result );
+    }
+}
+
+module.exports = BaiduController;

+ 13 - 0
wj-pack/backend/app/controller/home.js

@@ -0,0 +1,13 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+class HomeController extends Controller {
+  async index() {
+    const { ctx , app} = this;
+    console.log( ctx.request.URL );
+    ctx.resultOK( 'hi, training app ' + ctx.request.URL );
+  }
+}
+
+module.exports = HomeController;

+ 38 - 0
wj-pack/backend/app/controller/oss.js

@@ -0,0 +1,38 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+const moment = require("moment");
+const crypto = require("crypto");
+
+const HOST = "https://infish-oss.oss-cn-beijing.aliyuncs.com";
+
+class AliOssController extends Controller {
+
+  async policy() {
+        const { ctx } = this;
+        let dir = ctx.request.query.dir;
+        let time = moment(Date.now() + 30000).format("YYYY-MM-DDTHH:mm:ss.SSS") + "Z";
+            
+            let policyObj = JSON.stringify({
+                "expiration": time,
+                "conditions": [
+                    ["content-length-range", 0, 1048576000],
+                    ["starts-with", "$key", dir]
+                ]
+            })
+            let policy = new Buffer(policyObj).toString('base64');
+            let signature = crypto.createHmac('sha1', 'AHubozYEzXzi4fBL0ttLJ5sN1HMKA6').update(policy).digest().toString('base64');
+            ctx.resultOK(
+                {
+                    accessid: 'LTAI4GHqGdgY3b14jVRTzL2w',
+                    host:HOST,
+                    dir,
+                    policy,
+                    expire:time,
+                    signature
+                }
+            );
+    }
+}
+
+module.exports = AliOssController;

+ 150 - 0
wj-pack/backend/app/controller/sys/common.js

@@ -0,0 +1,150 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+const path = require("path");
+const uuid = require('uuid');
+const fs =  require("fs");
+const awaitWriteStream = require("await-stream-ready").write;
+const sendToWormhole = require("stream-wormhole");
+const dayjs = require("dayjs");
+
+class CommonController extends Controller {
+    
+    async upload() {
+        let {ctx } = this;
+
+        // const parts = ctx.multipart({ autoFields: true });
+        // const files = [];
+        // let stream;
+        // while ((stream = await parts()) != null) {
+        //     const filename = stream.filename.toLowerCase();
+        //     // const target = path.join(this.config.baseDir, 'app/public', filename);
+        //     // const writeStream = fs.createWriteStream(target);
+        //     // await pump(stream, writeStream);
+
+        //     console.log("xxx, ok11", filename);
+        //     files.push(filename);
+        // }
+
+        const stream = await this.ctx.getFileStream();
+        // 基础的目录
+        const uplaodBasePath = 'app/public/uploads';
+        // 生成文件名
+        const filename = `${Date.now()}${Number.parseInt( Math.random() * 1000)}${path.extname(stream.filename).toLocaleLowerCase()}`;
+
+        // 生成文件夹
+        const dirname = dayjs(Date.now()).format('YYYY-MM-DD');
+
+        function mkdirsSync(dirname) {
+            if (fs.existsSync(dirname)) {
+                return true;
+            } else {
+                if (mkdirsSync(path.dirname(dirname))) {
+                    fs.mkdirSync(dirname);
+                    return true;
+                }
+            }
+        }
+        mkdirsSync(path.join(uplaodBasePath, dirname));
+
+        // 生成写入路径
+        const target = path.join(uplaodBasePath, dirname, filename);
+        // 写入流
+        const writeStream = fs.createWriteStream(target);
+
+        try {
+            //异步把文件流 写入
+            await awaitWriteStream(stream.pipe(writeStream));
+        } catch (err) {
+            //如果出现错误,关闭管道
+            await sendToWormhole(stream);
+            
+            throw err;
+        }
+
+        let url = `uploads/${dirname}/${filename}`;
+        ctx.adminOK(true, url);
+    }
+
+    async sendSms() {
+        let { ctx } = this;
+        let {phone, use} = ctx.request.body;
+        if( !use || !phone ) {
+            ctx.resultFail("error");
+            return;
+        }
+        console.log("sendSms", use);
+        
+        let code = await ctx.service.sms.send(phone);
+
+        await ctx.service.cache.setString(`sms#${phone}#${use}`, code, 180);//3分钟后失效
+
+        ctx.resultOK("发送成功");
+    }
+
+    async bindThirdparty() {
+        let { ctx , app} = this;
+
+        let {mobile, wechatCode, alipayCode, code} = ctx.request.body;
+
+        if( !alipayCode && !wechatCode ) {
+            ctx.resultFail("授权码不能为空");
+            return;
+        }
+
+        if( !mobile ) {
+            ctx.resultFail("手机号码不能为空");
+            return;
+        }
+        if( !code ) {
+            ctx.resultFail("验证码不能为空");
+            return;
+        }
+
+        let cacheKey = `sms#${mobile}#bind`;
+        let cacheCode = await ctx.service.cache.getString(cacheKey);//3分钟后失效
+        if( cacheCode != code) {
+            ctx.resultFail("验证码错误");
+            return;
+        }
+        await ctx.service.cache.removeCache(cacheKey);
+
+        let thirdUser = {userId:"", nickName: "", avatar:""};
+
+        if( alipayCode ) {
+            thirdUser = await ctx.service.alipay.getUserInfo( alipayCode );
+        }
+
+        //更新用户
+        let user = await app.mysql.get("app_user", {tel: mobile}, {columns:["id","name","avatar"]});
+        if( user && user.id ) {
+            let v = {};
+            if( wechatCode ) v.wechat = thirdUser.userId;
+            else if( alipayCode ) v.alipay = thirdUser.userId;
+
+            if( !user.name ) v.name = thirdUser.nickName;
+            if( !user.avatar ) v.avatar = thirdUser.avatar;
+            
+            await app.mysql.update("app_user", v, {where:{id: user.id} });
+
+            let token = await ctx.jwtSign({name:user.name, tel:mobile, id:user.id}, app.config.loginUser.secret, { expiresIn: app.config.loginUser.expiresIn });
+
+            ctx.resultOK({id: user.id, username: user.name, avatar:user.avatar,tel:mobile, token}, "绑定成功");
+            return;
+        }
+
+        //创建用户
+       let res = await app.mysql.query(`insert into app_user (name, avatar, tel,${alipayCode?"alipay":"wechat"}, add_time, last_login, last_login_ip) values (?,?,?,?,now(),now(), ?)`, [thirdUser.nickName, thirdUser.avatar, mobile, thirdUser.userId, ctx.ip]);
+
+       let id = res.insertId;
+        if( id ) {
+            let token = await ctx.jwtSign({name:thirdUser.nickName, id, tel:mobile}, app.config.loginUser.secret, { expiresIn: 24 * 60 * 60 });
+            ctx.resultOK({id: id, tel:mobile, username: thirdUser.nickName, avatar: thirdUser.avatar, token}, "绑定成功");
+            return;
+        }
+
+        ctx.resultFail("绑定失败");
+    }
+}
+
+module.exports = CommonController;

+ 57 - 0
wj-pack/backend/app/controller/sys/device.js

@@ -0,0 +1,57 @@
+'use strict';
+const Controller = require('egg').Controller;
+
+class DeviceController extends Controller {
+    
+   //获取服务器状态
+   async getServerState() {
+      await this.train("/train/device/state", "get");
+   }
+
+   async shutdownServer() {
+        await this.train("/train/device/shutdownServer");
+   }
+   async startServer() {
+        let {ctx } = this;
+        await this.train("/train/device/startServer");
+   }
+   async restartServer() {
+        let {ctx } = this;
+        await this.train("/train/device/restartServer");
+   }
+
+   async mysql() {
+        let {ctx } = this;
+        let ret = await this.app.mysql.query("select id from admin_user where id=4");
+        ctx.adminOK(ret,"ok");
+   }
+
+   async train( uri, get ) {
+        let {ctx , app} = this;
+        let cfg = app.config.serverhosts;
+        let url = cfg.train + uri;
+
+        try {
+            console.log("====>", url);
+            let ret = await ctx.curl(url, {headers:{
+                    "Content-Type":"application/json"
+                },
+		method:get?get:'post',
+                dataType:"json"
+            });
+             console.log( ret.data );
+            if( ret.data && ret.data.code == 200 ) {
+                ctx.adminOK( ret.data.result, ret.data.message );
+                return;
+            }
+
+            ctx.adminFail(ret.data.message);
+
+        } catch (error) {
+            console.log("curl train server error")
+	    ctx.adminFail("未启动");
+        }
+   }
+}
+
+module.exports = DeviceController;

+ 43 - 0
wj-pack/backend/app/controller/sys/perm.js

@@ -0,0 +1,43 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+class PermsController extends Controller {
+    
+    async add() {
+        let {service, ctx } = this;
+
+        await ctx.bodyHandleByService(service.sysPerm, "addPerm", "添加成功");
+    }
+
+    async list() {
+
+        let {service, ctx } = this;
+        await ctx.queryHandleByService(service.sysPerm, "listPerm");
+    }
+    async delete() {
+        let {service, ctx } = this;
+        await ctx.queryHandleByService(service.sysPerm, "deletePerm","删除成功!");
+    }
+
+    async edit() {
+        let {service, ctx } = this;
+        await ctx.bodyHandleByService(service.sysPerm, "editPerm","更新成功!");
+    }
+
+    async deleteBatch() {
+        let {service, ctx } = this;
+        await ctx.queryHandleByService(service.sysPerm, "deleteBatch","删除成功!");
+    }
+    async getUserPermissionByToken() {
+        let {service, ctx } = this;
+        await ctx.queryHandleByService(service.sysPerm, "getUserPermissionByToken");
+    }
+
+    async queryallrole() {
+        let {service, ctx } = this;
+        await ctx.queryHandleByService(service.sysPerm, "queryallrole");
+    }
+}
+
+module.exports = PermsController;

+ 136 - 0
wj-pack/backend/app/controller/sys/user.js

@@ -0,0 +1,136 @@
+'use strict';
+
+const Controller = require('egg').Controller;
+
+class SysUserController extends Controller {
+
+  async list() {
+
+    const {ctx, service} = this;
+    let query = ctx.request.query;
+    let ret = await service.sysUser.list(query);
+    ctx.adminOK(ret);
+  }
+  async roleList() {
+    const {ctx, service} = this;
+    let query = ctx.request.query;
+    let ret = await service.sysUser.roleList(query);
+    ctx.adminOK(ret);
+  }
+  async userRoleList() {
+    const {ctx, service} = this;
+    let query = ctx.request.query;
+    let ret = await service.sysUser.userRoleList(query);
+    ctx.adminOK(ret);
+  }
+
+  async delete() {
+    const {ctx, service} = this;
+    let id = ctx.request.query.id;
+    let ret = await service.sysUser.delete(id);
+
+    ctx.adminOK(ret, "删除成功");
+  }
+  async deleteRole() {
+    const {ctx, service} = this;
+    let id = ctx.request.query.id;
+    let ret = await service.sysUser.deleteRole(id);
+
+    ctx.adminOK(ret, "删除成功");
+  }
+  
+  async deleteUserRole() {
+    const {ctx, service} = this;
+    let data = ctx.request.query;
+    let ret = await service.sysUser.deleteUserRole(data);
+
+    ctx.adminOK(ret, "删除成功");
+  }
+  async deleteUserRoleBatch ()
+  {
+    const {ctx, service} = this;
+    let data = ctx.request.query;
+    let ret = await service.sysUser.deleteUserRoleBatch(data);
+    ctx.adminOK(ret, "删除成功");
+  }
+
+  async edit() {
+    const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.sysUser.edit( data );
+    ctx.adminOK(ret, "更新成功");
+  }
+  async editRole() {
+    const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.sysUser.editRole( data );
+    ctx.adminOK(ret, "更新成功");
+  }
+
+  async add() {
+    const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.sysUser.add( data );
+    ctx.adminOK(ret, "添加成功");
+  }
+
+  async addRole() {
+    const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.sysUser.addRole( data );
+    ctx.adminOK(ret, "添加成功");
+  }
+  async addSysUserRole() {
+    const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.sysUser.addSysUserRole( data );
+    ctx.adminOK(ret, "添加成功");
+  }
+  async resetpwd() {
+     const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.sysUser.resetpwd( data );
+    ctx.adminOK(ret, "重置成功");
+  }
+
+  async frozenBatch() {
+    const {ctx, service} = this;
+    let data = ctx.request.body;
+    let ret = await service.sysUser.frozenBatch( data );
+    ctx.adminOK(ret, "冻结成功");
+  }
+
+  async queryUserRole() {
+    const {ctx, service} = this;
+    let data = ctx.request.query;
+    let ret = await service.sysUser.queryUserRole( data );
+    ctx.adminOK(ret);
+  }
+
+  async checkOnlyUser() {
+    const {ctx, service} = this;
+    let data = ctx.request.query;
+    let ret = await service.sysUser.checkOnlyUser( data );
+    ctx.adminOK(ret);
+  }
+
+  async queryTreeList() {
+    const {ctx, service} = this;
+
+    await ctx.queryHandleByService(service.sysUser, "queryTreeList");
+  }
+  async saveRolePermission()
+  {
+    //sys/permission/saveRolePermission
+    const {ctx, service} = this;
+    await ctx.bodyHandleByService(service.sysUser, "saveRolePermission", "保存成功");
+  }
+  
+  async queryRolePermission() {
+    const {ctx, service} = this;
+
+    await ctx.queryHandleByService(service.sysUser, "queryRolePermission");
+  }
+}
+
+module.exports = SysUserController;

+ 281 - 0
wj-pack/backend/app/extend/context.js

@@ -0,0 +1,281 @@
+'use strict';
+
+const jwt = require('jsonwebtoken');
+// const { parse } = require('urlencode');
+
+module.exports = {
+
+    resultOK(result, desc) {
+        this.body = { errorNo: 0, result, errorDesc: desc };
+        this.status = 200;
+    },
+    resultFail(desc) {
+        this.body = { errorNo: 500, errorDesc: desc };
+        this.status = 200;
+    },
+
+    adminFail(desc) {
+        this.body = { code: 500, success: false, result: null, message: desc };
+        this.status = 200;
+    },
+
+    adminOK(result, desc) {
+        this.body = { code: 200, success: true, result, message: desc };
+        this.status = 200;
+    },
+
+    bodyResult(code, result, desc) {
+        this.body = { errorNo: code, result, errorDesc: desc };
+        this.status = 200;
+    },
+
+    async jwtSign(payload, secret, options) {
+        return jwt.sign(payload, secret, options);
+    },
+
+    async jwtVerify(token, secret, options) {
+        function verify() {
+            return new Promise((resolve, reject) => {
+                jwt.verify(token, secret, options, function(err, decoded) {
+                    let result = {};
+                    if (err) {
+                        result.verify = false;
+                        result.message = err.message;
+                    } else {
+                        result.verify = true;
+                        result.message = decoded;
+                    }
+                    resolve(result);
+                });
+            });
+        }
+        let ret = await verify();
+
+        return ret;
+    },
+
+    SqlFmtTime(field, target) {
+        return `date_format(${field},'%Y-%m-%d') as ${target?target:field}`;
+    },
+
+    async pageSelect(query, table, field, filter, it) {
+        let mysql = this.app.mysql;
+
+        let pageNo = query.pageNo;
+        let pageSize = query.pageSize;
+
+        if (pageNo == undefined) pageNo = 1;
+        if (pageSize == undefined) pageSize = 10;
+
+        pageNo = parseInt(pageNo);
+        pageSize = parseInt(pageSize);
+
+        let ret = { records: [], total: 0, };
+
+        let where = filter;
+
+        let sql = `select ${field} from ${table} ${where}`
+
+        console.log(sql);
+
+        let total = await mysql.query(`select count(*) as count from ${table} ` + where);
+        ret.total = total[0].count;
+
+        let data = await mysql.query(`${sql} limit ${(pageNo-1)*pageSize},${pageSize}`);
+        if (it) {
+            data.forEach(element => {
+                it(element);
+            });
+        }
+        ret.records = data;
+
+        return ret;
+    },
+
+    async queryHandleByService(service, fnName) {
+        let ctx = this;
+        let data = ctx.request.query;
+        let ret = await service[fnName](data);
+        ctx.adminOK(ret);
+    },
+
+    async queryHandleByServiceInApp(service, fnName) {
+        let ctx = this;
+        let data = ctx.request.query;
+        let ret = await service[fnName](data);
+        ctx.resultOK(ret);
+    },
+
+    async bodyHandleByService(service, fnName, desc) {
+        let ctx = this;
+        let data = ctx.request.body;
+        let ret = await service[fnName](data);
+        ctx.adminOK(ret, desc);
+    },
+    async bodyHandleByServiceInApp(service, fnName, desc) {
+        let ctx = this;
+        let data = ctx.request.body;
+        let ret = await service[fnName](data);
+        ctx.resultOK(ret, desc);
+    },
+
+    nameFmt2Camel(v) {
+
+        function parse(obj) {
+            if (typeof obj != 'object') return;
+            let keys = Object.keys(obj);
+            keys.forEach(k => {
+                let ks = k.split("_");
+                if (ks.length > 1) {
+                    let n = ks.length;
+                    for (let i = 1; i < n; i++) {
+                        let kname = ks[i];
+                        ks[i] = kname[0].toUpperCase() + kname.slice(1);
+                    }
+                    let camelKey = ks.join("");
+                    obj[camelKey] = obj[k];
+                    delete obj[k];
+                }
+            });
+        }
+        let isArr = Array.isArray(v);
+        if (isArr) {
+            v.forEach(c => parse(c));
+            return;
+        }
+        parse(v);
+    },
+
+    nameFmtCamel2UnderLine(v) {
+
+        function parse(obj) {
+            if (typeof obj != 'object') return;
+            let keys = Object.keys(obj);
+            keys.forEach(k => {
+                let ks = k.split("_");
+                if (ks.length == 1) { //下划线模式的不用转
+
+                    let n = k.length;
+                    let words = [];
+                    let lastStart = 0;
+
+                    for (let i = 0; i < n; i++) {
+                        let char = k[i];
+                        if (char >= 'A' && char <= 'Z') {
+                            if (i > 0) {
+                                let s = k.substr(lastStart, i - lastStart);
+                                words.push(s.toLocaleLowerCase());
+                                lastStart = i;
+                            }
+                        }
+                        if (i == n - 1 && lastStart > 0) {
+                            let s = k.substr(lastStart, i - lastStart + 1);
+                            words.push(s.toLocaleLowerCase());
+                        }
+                    }
+
+                    if (words.length > 1) {
+                        let nkey = words.join("_");
+                        obj[nkey] = obj[k];
+                        delete obj[k];
+                    }
+                }
+            });
+        }
+        let isArr = Array.isArray(v);
+        if (isArr) {
+            v.forEach(c => parse(c));
+            return;
+        }
+        parse(v);
+    },
+
+    //要求数据结构id, parent_id=0 
+    fmt2Tree(ret, fn) {
+
+        let nodes = {};
+        ret.forEach(r => {
+            nodes[r.id] = r;
+        });
+
+        let treeList = [];
+        let cacheNodes = {};
+
+        function parseNode(node) {
+
+            let extObj = fn(node);
+            if (!extObj) return;
+
+            let parentId = node.parent_id;
+            if (parentId == undefined) parentId = node.parentId;
+
+            if (parentId == 0) { //根节点
+                let cnode = cacheNodes[node.id];
+                if (treeList.indexOf(cnode) < 0) { //还没有加入List
+                    let curNode = { children: [], ...extObj };
+                    treeList.push(curNode);
+                    cacheNodes[node.id] = curNode;
+                    return curNode;
+                }
+                return cnode;
+            } else {
+                //处理父亲节点
+                let parentId = node.parent_id;
+                if (parentId == undefined) parentId = node.parentId;
+
+                let parentNode = nodes[parentId];
+                let parent = cacheNodes[parentNode.id];
+                if (!parent) {
+                    parent = parseNode(parentNode);
+                    if (!parent) return;
+                }
+                //处理自己
+                let curNode = { children: [], ...extObj };
+
+                parent.children.push(curNode);
+
+                cacheNodes[node.id] = curNode;
+
+                return curNode;
+            }
+        }
+
+        ret.forEach(node => {
+            parseNode(node);
+        });
+
+        function checkNode(node) {
+
+            node.isLeaf = node.children.length < 1;
+            if (node.children.length < 1) {
+                node.children = null;
+                node.isLeaf = true;
+                return;
+            }
+            node.children.forEach(c => checkNode(c));
+        }
+        treeList.forEach(c => checkNode(c));
+
+        return treeList;
+    },
+
+    getStaticUrl(uri) {
+        let config = this.app.config;
+        return config.server.publicHost + uri;
+    },
+
+    async getLoginedUser() {
+        let ctx = this;
+
+        let authToken = ctx.header.authorization;
+        if (!authToken) {
+            return null;
+        }
+        let config = this.app.config.loginAdmin;
+        let ret = await ctx.jwtVerify(authToken, config.secret);
+        if (!ret.verify) {
+            null;
+        }
+        return ret.message;
+    }
+};

+ 29 - 0
wj-pack/backend/app/middleware/error_handler.js

@@ -0,0 +1,29 @@
+module.exports = () => {
+  return async function errorHandler(ctx, next) {
+    try {
+      await next();
+    } catch (err) {
+      // 所有的异常都在 app 上触发一个 error 事件,框架会记录一条错误日志
+      ctx.app.emit('error', err, ctx);
+
+      console.log("--->xxxxxxxxxxxxxxxxxxxxxxxxx" , err );
+
+
+      const status = err.status || 500;
+      // 生产环境时 500 错误的详细错误内容不返回给客户端,因为可能包含敏感信息
+      let error = err;
+      if( typeof error != "string")
+      {
+          error = (status === 500 && ctx.app.config.env === 'prod')  ? 'Internal Server Error' : err.message;
+      }
+         
+      ctx.logger.info(status);
+      
+      if (status === 422) {
+        error = err.errors;
+      }
+      ctx.body = {errorNo: status, success:false, message:error,result:null};
+      ctx.status = 200;
+    }
+  };
+};

+ 25 - 0
wj-pack/backend/app/middleware/loginAdmin.js

@@ -0,0 +1,25 @@
+const jsonWebToken = require('jsonwebtoken');
+
+module.exports = (options) => {
+    return async function jwt(ctx, next) {
+
+        let authToken = ctx.header.authorization;
+
+        if (!authToken) {
+            ctx.bodyResult(401, null,'no header.authorization!');
+            return;
+        }
+        console.log("login adim xx=>", options);
+        
+        let ret = await ctx.jwtVerify(authToken, options.secret, options.options);
+        if( !ret.verify )
+        {
+            ctx.bodyResult(401, null,ret.message);
+            return;
+        }
+        
+        ctx.state.admin = ret.message;
+        
+        await next();
+    };
+  };

+ 28 - 0
wj-pack/backend/app/middleware/loginUser.js

@@ -0,0 +1,28 @@
+const jsonWebToken = require('jsonwebtoken');
+
+module.exports = (options, app) => {
+    return async function jwt(ctx, next) {
+
+        // if( app.config.env == 'local' || true) { //本地测试环境,设置一个fake用户,跳过登录
+        //     ctx.state.user =  { id: 1} 
+        //     await next();
+        //     return;
+        // }
+        let authToken = ctx.header.authorization;
+
+        if (!authToken) {
+            ctx.bodyResult(401, null,'no header.authorization!');
+            return;
+        }
+        let ret = await ctx.jwtVerify(authToken, options.secret, options.options);
+        if( !ret.verify )
+        {
+            ctx.bodyResult(401, null,ret.message);
+            return;
+        }
+        
+        ctx.state.user = ret.message;
+
+        await next();
+    };
+  };

+ 13 - 0
wj-pack/backend/app/model/admin.js

@@ -0,0 +1,13 @@
+module.exports = app=>{
+    const mongoose = app.mongoose;
+    const Schema = mongoose.Schema;
+
+    const AdminUser = new Schema({
+        name:     { type: String},
+        password: { type: String},
+        lastLogin: {type: Date },
+    });
+
+    //todo why 查询表admins;
+    return mongoose.model("Admin", AdminUser);
+};

+ 23 - 0
wj-pack/backend/app/model/dict.js

@@ -0,0 +1,23 @@
+module.exports = app=>{
+    const mongoose = app.mongoose;
+    const Schema = mongoose.Schema;
+
+    const Dist = new Schema({
+        dictCode:     String,
+        dictName:     String,
+        description:  String,
+        type: Number,
+
+        dictItems: [{
+            itemValue: String,
+            itemText: String,
+            // letter: String,
+            sortOrder:String,
+            status:Number,
+            description:String
+        }]
+    },{
+        collection:'dict'
+    });
+    return mongoose.model("Dict", Dist);
+};

+ 74 - 0
wj-pack/backend/app/model/insurance.js

@@ -0,0 +1,74 @@
+
+//保险单
+module.exports = app=>{
+    const mongoose = app.mongoose;
+    const Schema = mongoose.Schema;
+
+    const Insurance = new Schema({
+        no:{ type: String}, //保单号
+        userid: { type: mongoose.Types.ObjectId },
+        company: { type: String}, //保险公司
+        product: {type: String }, //保险产品
+        prodType:{ type: String}, //保险产品类型
+        coverage:{ 
+            num: Number, //保额
+            unit:String, //单位 万元 元 美元 份
+        },
+        coveragePeoples:[String],
+        applicant:String, //投保人
+        beneficiary:[
+            {
+                name:String, //名字
+                percent:Number, //比例
+            }
+        ], //受益人,
+        effectiveTime: Date,//生效时间
+        coverageDuration: {
+            num: Number, //保证时间
+            unit: String //单位 天月年 至**岁 终身 其他
+        },
+        payMethod:String,//缴费方式 每年交一次, 每月交一次,趸交(一次交清) 其他
+        payAmount:{ //每次缴费金额
+            num: Number,
+            unit: String, //元,美元
+        },
+        payDuration:{ //缴费总时长
+            num:Number,
+            unit:String, //年 月 天 至**岁
+        },
+        coverageItems:[{ //保障项目
+            name:String, //保障项目名称
+            coverage:{ //保额
+                num:Number,
+                unit:String,
+            },
+            remarks:String,//备注
+         }
+        ],
+        additionalInsurance:[ //附加险
+            {
+                name:String, //附加险名字
+                type:String, //附加险类型
+                coveragePeople:String, //被保人
+                coverage:{ //保额
+                    num:Number,
+                    unit:String,
+                },
+                payment:{ //保费
+                    num:Number, 
+                    unit:String,
+                }
+            }
+        ],
+        payBank:String, //缴费银行
+        payBankCard:String,//缴费银行卡
+        agent: String, //经纪人
+        agentPhone: String, //经纪人电话
+        remarks: String, //备注
+        pictures:[String],//保单照片
+    },{
+        collection:'insurance'
+    });
+    //todo why 查询表admins;
+    return mongoose.model("Insurance", Insurance);
+};

+ 35 - 0
wj-pack/backend/app/model/user.js

@@ -0,0 +1,35 @@
+module.exports = app=>{
+    const mongoose = app.mongoose;
+    const Schema = mongoose.Schema;
+
+    const User = new Schema({
+        name:{ type: String},
+        tel: { type: String},
+        isboy: {type: Boolean },
+        wechat:{ type: String},
+        address:{ type: String},
+        avatar:{ type: String},
+        birthday: {type: Date },
+       
+        //被保人列表
+        family: [{
+            id:Schema.Types.ObjectId,
+            avatar:String, 
+            name:String,
+            tag:String,
+            insured_orders:Number, //保单数量
+            total:Number, //总保额度
+
+            birthday: {type: Date }, 
+            career:{ type: String},
+            income: { type: Number }, //年收入
+            loan: { type: String },
+        }],
+        password:String,
+        create_time:Date,
+    },{
+        collection:'users'
+    });
+    //todo why 查询表admins;
+    return mongoose.model("User", User);
+};

Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
wj-pack/backend/app/public/message/check/css/app.96265e40.css


BIN
wj-pack/backend/app/public/message/check/favicon.ico


BIN
wj-pack/backend/app/public/message/check/img/logo.82b9c7a5.png


+ 28 - 0
wj-pack/backend/app/public/message/check/index.html

@@ -0,0 +1,28 @@
+<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>htmldoc</title><style>* {
+        margin: 0;
+        padding: 0;
+        user-select:none; 
+      }</style><script>(function setRootFont() {
+          var _self = window;
+
+          _self.selfFontSize  = undefined;
+          _self.width = 1207; //设置默认最大宽度
+          _self.fontSize = 100;  //默认字体大小
+
+          _self.widthProportion = function () {
+              var p = ((document.body && document.documentElement.clientWidth) || document.getElementsByTagName("html")[0].offsetWidth) / _self.width;
+              return p > 1 ? 1 : p < 0.25 ? 0.25 : p;
+              // var p = ((document.body && document.documentElement.clientHeight) || document.getElementsByTagName("html")[0].offsetHeight) / _self.height;
+              // return p < 0.25 ? 0.25 : p;
+          };
+        
+          _self.changePage = function () {
+              _self.selfFontSize =  _self.widthProportion() * _self.fontSize;
+              document.getElementsByTagName("html")[0].setAttribute("style",
+                  "font-size:" + _self.selfFontSize + "px");
+          };
+          _self.changePage();
+          window.addEventListener('resize', function () {
+              _self.changePage();
+          }, false);
+      })();</script><script src="./tinymce/js/tinymce/tinymce.min.js"></script><link href="js/about.6a60e643.js" rel="prefetch"><link href="css/app.96265e40.css" rel="preload" as="style"><link href="js/app.edc03535.js" rel="preload" as="script"><link href="js/chunk-vendors.f81017bd.js" rel="preload" as="script"><link href="css/app.96265e40.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but htmldoc doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="js/chunk-vendors.f81017bd.js"></script><script src="js/app.edc03535.js"></script></body></html>

+ 1 - 0
wj-pack/backend/app/public/message/check/js/about.6a60e643.js

@@ -0,0 +1 @@
+(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["about"],{f820:function(t,n,s){"use strict";s.r(n);var a=function(){var t=this;t._self._c;return t._m(0)},u=[function(){var t=this,n=t._self._c;return n("div",{staticClass:"about"},[n("h1",[t._v("This is an about page")])])}],i=s("2877"),e={},o=Object(i["a"])(e,a,u,!1,null,null,null);n["default"]=o.exports}}]);

Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
wj-pack/backend/app/public/message/check/js/app.edc03535.js


Diff do ficheiro suprimidas por serem muito extensas
+ 6 - 0
wj-pack/backend/app/public/message/check/js/chunk-vendors.f81017bd.js


+ 1645 - 0
wj-pack/backend/app/public/message/check/tinymce/changelog.txt

@@ -0,0 +1,1645 @@
+Version 5.4.1 (2020-07-08)
+    Fixed the Search and Replace plugin incorrectly including zero-width caret characters in search results #TINY-4599
+    Fixed dragging and dropping unsupported files navigating the browser away from the editor #TINY-6027
+    Fixed undo levels not created on browser handled drop or paste events #TINY-6027
+    Fixed content in an iframe element parsing as DOM elements instead of text content #TINY-5943
+    Fixed Oxide checklist styles not showing when printing #TINY-5139
+    Fixed bug with `scope` attribute not being added to the cells of header rows #TINY-6206
+Version 5.4.0 (2020-06-30)
+    Added keyboard navigation support to menus and toolbars when the editor is in a ShadowRoot #TINY-6152
+    Added the ability for menus to be clicked when the editor is in an open shadow root #TINY-6091
+    Added the `Editor.ui.styleSheetLoader` API for loading stylesheets within the Document or ShadowRoot containing the editor UI #TINY-6089
+    Added the `StyleSheetLoader` module to the public API #TINY-6100
+    Added Oxide variables for styling the `select` element and headings in dialog content #TINY-6070
+    Added icons for `table` column and row cut, copy, and paste toolbar buttons #TINY-6062
+    Added all `table` menu items to the UI registry, so they can be used by name in other menus #TINY-4866
+    Added new `mceTableApplyCellStyle` command to the `table` plugin #TINY-6004
+    Added new `table` cut, copy, and paste column editor commands and menu items #TINY-6006
+    Added font related Oxide variables for secondary buttons, allowing for custom styling #TINY-6061
+    Added new `table_header_type` setting to control how table header rows are structured #TINY-6007
+    Added new `table_sizing_mode` setting to replace the `table_responsive_width` setting, which has now been deprecated #TINY-6051
+    Added new `mceTableSizingMode` command for changing the sizing mode of a table #TINY-6000
+    Added new `mceTableRowType`, `mceTableColType`, and `mceTableCellType` commands and value queries #TINY-6150
+    Changed `advlist` toolbar buttons to only show a dropdown list if there is more than one option #TINY-3194
+    Changed `mceInsertTable` command and `insertTable` API method to take optional header rows and columns arguments #TINY-6012
+    Changed stylesheet loading, so that UI skin stylesheets can load in a ShadowRoot if required #TINY-6089
+    Changed the DOM location of menus so that they display correctly when the editor is in a ShadowRoot #TINY-6093
+    Changed the table plugin to correctly detect all valid header row structures #TINY-6007
+    Fixed tables with no defined width being converted to a `fixed` width table when modifying the table #TINY-6051
+    Fixed the `autosave` `isEmpty` API incorrectly detecting non-empty content as empty #TINY-5953
+    Fixed table `Paste row after` and `Paste row before` menu items not disabled when nothing was available to paste #TINY-6006
+    Fixed a selection performance issue with large tables on Microsoft Internet Explorer and Edge #TINY-6057
+    Fixed filters for screening commands from the undo stack to be case-insensitive #TINY-5946
+    Fixed `fullscreen` plugin now removes all classes when the editor is closed #TINY-4048
+    Fixed handling of mixed-case icon identifiers (names) for UI elements #TINY-3854
+    Fixed leading and trailing spaces lost when using `editor.selection.getContent({ format: 'text' })` #TINY-5986
+    Fixed an issue where changing the URL with the quicklink toolbar caused unexpected undo behavior #TINY-5952
+    Fixed an issue where removing formatting within a table cell would cause Internet Explorer 11 to scroll to the end of the table #TINY-6049
+    Fixed an issue where the `allow_html_data_urls` setting was not correctly applied #TINY-5951
+    Fixed the `autolink` feature so that it no longer treats a string with multiple "@" characters as an email address #TINY-4773
+    Fixed an issue where removing the editor would leave unexpected attributes on the target element #TINY-4001
+    Fixed the `link` plugin now suggest `mailto:` when the text contains an '@' and no slashes (`/`) #TINY-5941
+    Fixed the `valid_children` check of custom elements now allows a wider range of characters in names #TINY-5971
+Version 5.3.2 (2020-06-10)
+    Fixed a regression introduced in 5.3.0, where `images_dataimg_filter` was no-longer called #TINY-6086
+Version 5.3.1 (2020-05-27)
+    Fixed the image upload error alert also incorrectly closing the image dialog #TINY-6020
+    Fixed editor content scrolling incorrectly on focus in Firefox by reverting default content CSS html and body heights added in 5.3.0 #TINY-6019
+Version 5.3.0 (2020-05-21)
+    Added html and body height styles to the default oxide content CSS #TINY-5978
+    Added `uploadUri` and `blobInfo` to the data returned by `editor.uploadImages()` #TINY-4579
+    Added a new function to the `BlobCache` API to lookup a blob based on the base64 data and mime type #TINY-5988
+    Added the ability to search and replace within a selection #TINY-4549
+    Added the ability to set the list start position for ordered lists and added new `lists` context menu item #TINY-3915
+    Added `icon` as an optional config option to the toggle menu item API #TINY-3345
+    Added `auto` mode for `toolbar_location` which positions the toolbar and menu bar at the bottom if there is no space at the top #TINY-3161
+    Changed the default `toolbar_location` to `auto` #TINY-3161
+    Changed toggle menu items and choice menu items to have a dedicated icon with the checkmark displayed on the far right side of the menu item #TINY-3345
+    Changed the `link`, `image`, and `paste` plugins to use Promises to reduce the bundle size #TINY-4710
+    Changed the default icons to be lazy loaded during initialization #TINY-4729
+    Changed the parsing of content so base64 encoded urls are converted to blob urls #TINY-4727
+    Changed context toolbars so they concatenate when more than one is suitable for the current selection #TINY-4495
+    Changed inline style element formats (strong, b, em, i, u, strike) to convert to a span on format removal if a `style` or `class` attribute is present #TINY-4741
+    Fixed the `selection.setContent()` API not running parser filters #TINY-4002
+    Fixed formats incorrectly applied or removed when table cells were selected #TINY-4709
+    Fixed the `quickimage` button not restricting the file types to images #TINY-4715
+    Fixed search and replace ignoring text in nested contenteditable elements #TINY-5967
+    Fixed resize handlers displaying in the wrong location sometimes for remote images #TINY-4732
+    Fixed table picker breaking in Firefox on low zoom levels #TINY-4728
+    Fixed issue with loading or pasting contents with large base64 encoded images on Safari #TINY-4715
+    Fixed supplementary special characters being truncated when inserted into the editor. Patch contributed by mlitwin. #TINY-4791
+    Fixed toolbar buttons not set to disabled when the editor is in readonly mode #TINY-4592
+    Fixed the editor selection incorrectly changing when removing caret format containers #TINY-3438
+    Fixed bug where title, width, and height would be set to empty string values when updating an image and removing those attributes using the image dialog #TINY-4786
+    Fixed `ObjectResized` event firing when an object wasn't resized #TINY-4161
+    Fixed `ObjectResized` and `ObjectResizeStart` events incorrectly fired when adding or removing table rows and columns #TINY-4829
+    Fixed the placeholder not hiding when pasting content into the editor #TINY-4828
+    Fixed an issue where the editor would fail to load if local storage was disabled #TINY-5935
+    Fixed an issue where an uploaded image would reuse a cached image with a different mime type #TINY-5988
+    Fixed bug where toolbars and dialogs would not show if the body element was replaced (e.g. with Turbolinks). Patch contributed by spohlenz #GH-5653
+    Fixed an issue where multiple formats would be removed when removing a single format at the end of lines or on empty lines #TINY-1170
+    Fixed zero-width spaces incorrectly included in the `wordcount` plugin character count #TINY-5991
+    Fixed a regression introduced in 5.2.0 whereby the desktop `toolbar_mode` setting would incorrectly override the mobile default setting #TINY-5998
+    Fixed an issue where deleting all content in a single cell table would delete the entire table #TINY-1044
+Version 5.2.2 (2020-04-23)
+    Fixed an issue where anchors could not be inserted on empty lines #TINY-2788
+    Fixed text decorations (underline, strikethrough) not consistently inheriting the text color #TINY-4757
+    Fixed `format` menu alignment buttons inconsistently applying to images #TINY-4057
+    Fixed the floating toolbar drawer height collapsing when the editor is rendered in modal dialogs or floating containers #TINY-4837
+    Fixed `media` embed content not processing safely in some cases #TINY-4857
+Version 5.2.1 (2020-03-25)
+    Fixed the "is decorative" checkbox in the image dialog clearing after certain dialog events #FOAM-11
+    Fixed possible uncaught exception when a `style` attribute is removed using a content filter on `setContent` #TINY-4742
+    Fixed the table selection not functioning correctly in Microsoft Edge 44 or higher #TINY-3862
+    Fixed the table resize handles not functioning correctly in Microsoft Edge 44 or higher #TINY-4160
+    Fixed the floating toolbar drawer disconnecting from the toolbar when adding content in inline mode #TINY-4725 #TINY-4765
+    Fixed `readonly` mode not returning the appropriate boolean value #TINY-3948
+    Fixed the `forced_root_block_attrs` setting not applying attributes to new blocks consistently #TINY-4564
+    Fixed the editor incorrectly stealing focus during initialization in Microsoft Internet Explorer #TINY-4697
+    Fixed dialogs stealing focus when opening an alert or confirm dialog using an `onAction` callback #TINY-4014
+    Fixed inline dialogs incorrectly closing when clicking on an opened alert or confirm dialog #TINY-4012
+    Fixed the context toolbar overlapping the menu bar and toolbar #TINY-4586
+    Fixed notification and inline dialog positioning issues when using `toolbar_location: 'bottom'` #TINY-4586
+    Fixed the `colorinput` popup appearing offscreen on mobile devices #TINY-4711
+    Fixed special characters not being found when searching by "whole words only" #TINY-4522
+    Fixed an issue where dragging images could cause them to be duplicated #TINY-4195
+    Fixed context toolbars activating without the editor having focus #TINY-4754
+    Fixed an issue where removing the background color of text did not always work #TINY-4770
+    Fixed an issue where new rows and columns in a table did not retain the style of the previous row or column #TINY-4788
+Version 5.2.0 (2020-02-13)
+    Added the ability to apply formats to spaces #TINY-4200
+    Added new `toolbar_location` setting to allow for positioning the menu and toolbar at the bottom of the editor #TINY-4210
+    Added new `toolbar_groups` setting to allow a custom floating toolbar group to be added to the toolbar when using `floating` toolbar mode #TINY-4229
+    Added new `link_default_protocol` setting to `link` and `autolink` plugin to allow a protocol to be used by default #TINY-3328
+    Added new `placeholder` setting to allow a placeholder to be shown when the editor is empty #TINY-3917
+    Added new `tinymce.dom.TextSeeker` API to allow searching text across different DOM nodes #TINY-4200
+    Added a drop shadow below the toolbar while in sticky mode and introduced Oxide variables to customize it when creating a custom skin #TINY-4343
+    Added `quickbars_image_toolbar` setting to allow for the image quickbar to be turned off #TINY-4398
+    Added iframe and img `loading` attribute to the default schema. Patch contributed by ataylor32. #GH-5112
+    Added new `getNodeFilters`/`getAttributeFilters` functions to the `editor.serializer` instance #TINY-4344
+    Added new `a11y_advanced_options` setting to allow additional accessibility options to be added #FOAM-11
+    Added new accessibility options and behaviours to the image dialog using `a11y_advanced_options` #FOAM-11
+    Added the ability to use the window `PrismJS` instance for the `codesample` plugin instead of the bundled version to allow for styling custom languages #TINY-4504
+    Added error message events that fire when a resource loading error occurs #TINY-4509
+    Changed the default schema to disallow `onchange` for select elements #TINY-4614
+    Changed default `toolbar_mode` value from false to `wrap`. The value false has been deprecated #TINY-4617
+    Changed `toolbar_drawer` setting to `toolbar_mode`. `toolbar_drawer` has been deprecated #TINY-4416
+    Changed iframe mode to set selection on content init if selection doesn't exist #TINY-4139
+    Changed table related icons to align them with the visual style of the other icons #TINY-4341
+    Changed and improved the visual appearance of the color input field #TINY-2917
+    Changed fake caret container to use `forced_root_block` when possible #TINY-4190
+    Changed the `requireLangPack` API to wait until the plugin has been loaded before loading the language pack #TINY-3716
+    Changed the formatter so `style_formats` are registered before the initial content is loaded into the editor #TINY-4238
+    Changed media plugin to use https protocol for media urls by default #TINY-4577
+    Changed the parser to treat CDATA nodes as bogus HTML comments to match the HTML parsing spec. A new `preserve_cdata` setting has been added to preserve CDATA nodes if required #TINY-4625
+    Fixed incorrect parsing of malformed/bogus HTML comments #TINY-4625
+    Fixed `quickbars` selection toolbar appearing on non-editable elements #TINY-4359
+    Fixed bug with alignment toolbar buttons sometimes not changing state correctly #TINY-4139
+    Fixed the `codesample` toolbar button not toggling when selecting code samples other than HTML #TINY-4504
+    Fixed content incorrectly scrolling to the top or bottom when pressing enter if when the content was already in view #TINY-4162
+    Fixed `scrollIntoView` potentially hiding elements behind the toolbar #TINY-4162
+    Fixed editor not respecting the `resize_img_proportional` setting due to legacy code #TINY-4236
+    Fixed flickering floating toolbar drawer in inline mode #TINY-4210
+    Fixed an issue where the template plugin dialog would be indefinitely blocked on a failed template load #TINY-2766
+    Fixed the `mscontrolselect` event not being unbound on IE/Edge #TINY-4196
+    Fixed Confirm dialog footer buttons so only the "Yes" button is highlighted #TINY-4310
+    Fixed `file_picker_callback` functionality for Image, Link and Media plugins #TINY-4163
+    Fixed issue where floating toolbar drawer sometimes would break if the editor is resized while the drawer is open #TINY-4439
+    Fixed incorrect `external_plugins` loading error message #TINY-4503
+    Fixed resize handler was not hidden for ARIA purposes. Patch contributed by Parent5446. #GH-5195
+    Fixed an issue where content could be lost if a misspelled word was selected and spellchecking was disabled #TINY-3899
+    Fixed validation errors in the CSS where certain properties had the wrong default value #TINY-4491
+    Fixed an issue where forced root block attributes were not applied when removing a list #TINY-4272
+    Fixed an issue where the element path isn't being cleared when there are no parents #TINY-4412
+    Fixed an issue where width and height in svg icons containing `rect` elements were overridden by the CSS reset #TINY-4408
+    Fixed an issue where uploading images with `images_reuse_filename` enabled and that included a query parameter would generate an invalid URL #TINY-4638
+    Fixed the `closeButton` property not working when opening notifications #TINY-4674
+    Fixed keyboard flicker when opening a context menu on mobile #TINY-4540
+    Fixed issue where plus icon svg contained strokes #TINY-4681
+Version 5.1.6 (2020-01-28)
+    Fixed `readonly` mode not blocking all clicked links #TINY-4572
+    Fixed legacy font sizes being calculated inconsistently for the `FontSize` query command value #TINY-4555
+    Fixed changing a tables row from `Header` to `Body` incorrectly moving the row to the bottom of the table #TINY-4593
+    Fixed the context menu not showing in certain cases with hybrid devices #TINY-4569
+    Fixed the context menu opening in the wrong location when the target is the editor body #TINY-4568
+    Fixed the `image` plugin not respecting the `automatic_uploads` setting when uploading local images #TINY-4287
+    Fixed security issue related to parsing HTML comments and CDATA #TINY-4544
+Version 5.1.5 (2019-12-19)
+    Fixed the UI not working with hybrid devices that accept both touch and mouse events #TNY-4521
+    Fixed the `charmap` dialog initially focusing the first tab of the dialog instead of the search input field #TINY-4342
+    Fixed an exception being raised when inserting content if the caret was directly before or after a `contenteditable="false"` element #TINY-4528
+    Fixed a bug with pasting image URLs when paste as text is enabled #TINY-4523
+Version 5.1.4 (2019-12-11)
+    Fixed dialog contents disappearing when clicking a checkbox for right-to-left languages #TINY-4518
+    Fixed the `legacyoutput` plugin registering legacy formats after editior initialization, causing legacy content to be stripped on the initial load #TINY-4447
+    Fixed search and replace not cycling through results when searching using special characters #TINY-4506
+    Fixed the `visualchars` plugin converting HTML-like text to DOM elements in certain cases #TINY-4507
+    Fixed an issue with the `paste` plugin not sanitizing content in some cases #TINY-4510
+    Fixed HTML comments incorrectly being parsed in certain cases #TINY-4511
+Version 5.1.3 (2019-12-04)
+    Fixed sticky toolbar not undocking when fullscreen mode is activated #TINY-4390
+    Fixed the "Current Window" target not applying when updating links using the link dialog #TINY-4063
+    Fixed disabled menu items not highlighting when focused #TINY-4339
+    Fixed touch events passing through dialog collection items to the content underneath on Android devices #TINY-4431
+    Fixed keyboard navigation of the Help dialog's Keyboard Navigation tab #TINY-4391
+    Fixed search and replace dialog disappearing when finding offscreen matches on iOS devices #TINY-4350
+    Fixed performance issues where sticky toolbar was jumping while scrolling on slower browsers #TINY-4475
+Version 5.1.2 (2019-11-19)
+    Fixed desktop touch devices using `mobile` configuration overrides #TINY-4345
+    Fixed unable to disable the new scrolling toolbar feature #TINY-4345
+    Fixed touch events passing through any pop-up items to the content underneath on Android devices #TINY-4367
+    Fixed the table selector handles throwing JavaScript exceptions for non-table selections #TINY-4338
+    Fixed `cut` operations not removing selected content on Android devices when the `paste` plugin is enabled #TINY-4362
+    Fixed inline toolbar not constrained to the window width by default #TINY-4314
+    Fixed context toolbar split button chevrons pointing right when they should be pointing down #TINY-4257
+    Fixed unable to access the dialog footer in tabbed dialogs on small screens #TINY-4360
+    Fixed mobile table selectors were hard to select with touch by increasing the size #TINY-4366
+    Fixed mobile table selectors moving when moving outside the editor #TINY-4366
+    Fixed inline toolbars collapsing when using sliding toolbars #TINY-4389
+    Fixed block textpatterns not treating NBSPs as spaces #TINY-4378
+    Fixed backspace not merging blocks when the last element in the preceding block was a `contenteditable="false"` element #TINY-4235
+    Fixed toolbar buttons that only contain text labels overlapping on mobile devices #TINY-4395
+    Fixed quickbars quickimage picker not working on mobile #TINY-4377
+    Fixed fullscreen not resizing in an iOS WKWebView component #TINY-4413
+Version 5.1.1 (2019-10-28)
+    Fixed font formats containing spaces being wrapped in `&quot;` entities instead of single quotes #TINY-4275
+    Fixed alert and confirm dialogs losing focus when clicked #TINY-4248
+    Fixed clicking outside a modal dialog focusing on the document body #TINY-4249
+    Fixed the context toolbar not hiding when scrolled out of view #TINY-4265
+Version 5.1.0 (2019-10-17)
+    Added touch selector handles for table selections on touch devices #TINY-4097
+    Added border width field to Table Cell dialog #TINY-4028
+    Added touch event listener to media plugin to make embeds playable #TINY-4093
+    Added oxide styling options to notifications and tweaked the default variables #TINY-4153
+    Added additional padding to split button chevrons on touch devices, to make them easier to interact with #TINY-4223
+    Added new platform detection functions to `Env` and deprecated older detection properties #TINY-4184
+    Added `inputMode` config field to specify inputmode attribute of `input` dialog components #TINY-4062
+    Added new `inputMode` property to relevant plugins/dialogs #TINY-4102
+    Added new `toolbar_sticky` setting to allow the iframe menubar/toolbar to stick to the top of the window when scrolling #TINY-3982
+    Changed default setting for `toolbar_drawer` to `floating` #TINY-3634
+    Changed mobile phones to use the `silver` theme by default #TINY-3634
+    Changed some editor settings to default to `false` on touch devices:
+        - `menubar`(phones only) #TINY-4077
+        - `table_grid` #TINY-4075
+        - `resize` #TINY-4157
+        - `object_resizing` #TINY-4157
+    Changed toolbars and context toolbars to sidescroll on mobile #TINY-3894 #TINY-4107
+    Changed context menus to render as horizontal menus on touch devices #TINY-4107
+    Changed the editor to use the `VisualViewport` API of the browser where possible #TINY-4078
+    Changed visualblocks toolbar button icon and renamed `paragraph` icon to `visualchars` #TINY-4074
+    Changed Oxide default for `@toolbar-button-chevron-color` to follow toolbar button icon color #TINY-4153
+    Changed the `urlinput` dialog component to use the `url` type attribute #TINY-4102
+    Fixed Safari desktop visual viewport fires resize on fullscreen breaking the restore function #TINY-3976
+    Fixed scroll issues on mobile devices #TINY-3976
+    Fixed context toolbar unable to refresh position on iOS12 #TINY-4107
+    Fixed ctrl+left click not opening links on readonly mode and the preview dialog #TINY-4138
+    Fixed Slider UI component not firing `onChange` event on touch devices #TINY-4092
+    Fixed notifications overlapping instead of stacking #TINY-3478
+    Fixed inline dialogs positioning incorrectly when the page is scrolled #TINY-4018
+    Fixed inline dialogs and menus not repositioning when resizing #TINY-3227
+    Fixed inline toolbar incorrectly stretching to the full width when a width value was provided #TINY-4066
+    Fixed menu chevrons color to follow the menu text color #TINY-4153
+    Fixed table menu selection grid from staying black when using dark skins, now follows border color #TINY-4153
+    Fixed Oxide using the wrong text color variable for menubar button focused state #TINY-4146
+    Fixed the autoresize plugin not keeping the selection in view when resizing #TINY-4094
+    Fixed textpattern plugin throwing exceptions when using `forced_root_block: false` #TINY-4172
+    Fixed missing CSS fill styles for toolbar button icon active state #TINY-4147
+    Fixed an issue where the editor selection could end up inside a short ended element (such as `br`) #TINY-3999
+    Fixed browser selection being lost in inline mode when opening split dropdowns #TINY-4197
+    Fixed backspace throwing an exception when using `forced_root_block: false` #TINY-4099
+    Fixed floating toolbar drawer expanding outside the bounds of the editor #TINY-3941
+    Fixed the autocompleter not activating immediately after a `br` or `contenteditable=false` element #TINY-4194
+    Fixed an issue where the autocompleter would incorrectly close on IE 11 in certain edge cases #TINY-4205
+Version 5.0.16 (2019-09-24)
+    Added new `referrer_policy` setting to add the `referrerpolicy` attribute when loading scripts or stylesheets #TINY-3978
+    Added a slight background color to dialog tab links when focused to aid keyboard navigation #TINY-3877
+    Fixed media poster value not updating on change #TINY-4013
+    Fixed openlink was not registered as a toolbar button #TINY-4024
+    Fixed failing to initialize if a script tag was used inside a SVG #TINY-4087
+    Fixed double top border showing on toolbar without menubar when toolbar_drawer is enabled #TINY-4118
+    Fixed unable to drag inline dialogs to the bottom of the screen when scrolled #TINY-4154
+    Fixed notifications appearing on top of the toolbar when scrolled in inline mode #TINY-4159
+    Fixed notifications displaying incorrectly on IE 11 #TINY-4169
+Version 5.0.15 (2019-09-02)
+    Added a dark `content_css` skin to go with the dark UI skin #TINY-3743
+    Changed the enabled state on toolbar buttons so they don't get the hover effect #TINY-3974
+    Fixed missing CSS active state on toolbar buttons #TINY-3966
+    Fixed `onChange` callback not firing for the colorinput dialog component #TINY-3968
+    Fixed context toolbars not showing in fullscreen mode #TINY-4023
+Version 5.0.14 (2019-08-19)
+    Added an API to reload the autocompleter menu with additional fetch metadata #MENTIONS-17
+    Fixed missing toolbar button border styling options #TINY-3965
+    Fixed image upload progress notification closing before the upload is complete #TINY-3963
+    Fixed inline dialogs not closing on escape when no dialog component is in focus #TINY-3936
+    Fixed plugins not being filtered when defaulting to mobile on phones #TINY-3537
+    Fixed toolbar more drawer showing the content behind it when transitioning between opened and closed states #TINY-3878
+    Fixed focus not returning to the dialog after pressing the "Replace all" button in the search and replace dialog #TINY-3961
+    Removed Oxide variable `@menubar-select-disabled-border-color` and replaced it with `@menubar-select-disabled-border` #TINY-3965
+Version 5.0.13 (2019-08-06)
+    Changed modal dialogs to prevent dragging by default and added new `draggable_modal` setting to restore dragging #TINY-3873
+    Changed the nonbreaking plugin to insert nbsp characters wrapped in spans to aid in filtering. This can be disabled using the `nonbreaking_wrap` setting #TINY-3647
+    Changed backspace behaviour in lists to outdent nested list items when the cursor is at the start of the list item #TINY-3651
+    Fixed sidebar growing beyond editor bounds in IE 11 #TINY-3937
+    Fixed issue with being unable to keyboard navigate disabled toolbar buttons #TINY-3350
+    Fixed issues with backspace and delete in nested contenteditable true and false elements #TINY-3868
+    Fixed issue with losing keyboard navigation in dialogs due to disabled buttons #TINY-3914
+    Fixed `MouseEvent.mozPressure is deprecated` warning in Firefox #TINY-3919
+    Fixed `default_link_target` not being respected when `target_list` is disabled #TINY-3757
+    Fixed mobile plugin filter to only apply to the mobile theme, rather than all mobile platforms #TINY-3405
+    Fixed focus switching to another editor during mode changes #TINY-3852
+    Fixed an exception being thrown when clicking on an uninitialized inline editor #TINY-3925
+    Fixed unable to keyboard navigate to dialog menu buttons #TINY-3933
+    Fixed dialogs being able to be dragged outside the window viewport #TINY-3787
+    Fixed inline dialogs appearing above modal dialogs #TINY-3932
+Version 5.0.12 (2019-07-18)
+    Added ability to utilize UI dialog panels inside other panels #TINY-3305
+    Added help dialog tab explaining keyboard navigation of the editor #TINY-3603
+    Changed the "Find and Replace" design to an inline dialog #TINY-3054
+    Fixed issue where autolink spacebar event was not being fired on Edge #TINY-3891
+    Fixed table selection missing the background color #TINY-3892
+    Fixed removing shortcuts not working for function keys #TINY-3871
+    Fixed non-descriptive UI component type names #TINY-3349
+    Fixed UI registry components rendering as the wrong type when manually specifying a different type #TINY-3385
+    Fixed an issue where dialog checkbox, input, selectbox, textarea and urlinput components couldn't be disabled #TINY-3708
+    Fixed the context toolbar not using viable screen space in inline/distraction free mode #TINY-3717
+    Fixed the context toolbar overlapping the toolbar in various conditions #TINY-3205
+    Fixed IE11 edge case where items were being inserted into the wrong location #TINY-3884
+Version 5.0.11 (2019-07-04)
+    Fixed packaging errors caused by a rollup treeshaking bug (https://github.com/rollup/rollup/issues/2970) #TINY-3866
+    Fixed the customeditor component not able to get data from the dialog api #TINY-3866
+    Fixed collection component tooltips not being translated #TINY-3855
+Version 5.0.10 (2019-07-02)
+    Added support for all HTML color formats in `color_map` setting #TINY-3837
+    Changed backspace key handling to outdent content in appropriate circumstances #TINY-3685
+    Changed default palette for forecolor and backcolor to include some lighter colors suitable for highlights #TINY-2865
+    Changed the search and replace plugin to cycle through results #TINY-3800
+    Fixed inconsistent types causing some properties to be unable to be used in dialog components #TINY-3778
+    Fixed an issue in the Oxide skin where dialog content like outlines and shadows were clipped because of overflow hidden #TINY-3566
+    Fixed the search and replace plugin not resetting state when changing the search query #TINY-3800
+    Fixed backspace in lists not creating an undo level #TINY-3814
+    Fixed the editor to cancel loading in quirks mode where the UI is not supported #TINY-3391
+    Fixed applying fonts not working when the name contained spaces and numbers #TINY-3801
+    Fixed so that initial content is retained when initializing on list items #TINY-3796
+    Fixed inefficient font name and font size current value lookup during rendering #TINY-3813
+    Fixed mobile font copied into the wrong folder for the oxide-dark skin #TINY-3816
+    Fixed an issue where resizing the width of tables would produce inaccurate results #TINY-3827
+    Fixed a memory leak in the Silver theme #TINY-3797
+    Fixed alert and confirm dialogs using incorrect markup causing inconsistent padding #TINY-3835
+    Fixed an issue in the Table plugin with `table_responsive_width` not enforcing units when resizing #TINY-3790
+    Fixed leading, trailing and sequential spaces being lost when pasting plain text #TINY-3726
+    Fixed exception being thrown when creating relative URIs #TINY-3851
+    Fixed focus is no longer set to the editor content during mode changes unless the editor already had focus #TINY-3852
+Version 5.0.9 (2019-06-26)
+    Fixed print plugin not working in Firefox #TINY-3834
+Version 5.0.8 (2019-06-18)
+    Added back support for multiple toolbars #TINY-2195
+    Added support for .m4a files to the media plugin #TINY-3750
+    Added new base_url and suffix editor init options #TINY-3681
+    Fixed incorrect padding for select boxes with visible values #TINY-3780
+    Fixed selection incorrectly changing when programmatically setting selection on contenteditable false elements #TINY-3766
+    Fixed sidebar background being transparent #TINY-3727
+    Fixed the build to remove duplicate iife wrappers #TINY-3689
+    Fixed bogus autocompleter span appearing in content when the autocompleter menu is shown #TINY-3752
+    Fixed toolbar font size select not working with legacyoutput plugin #TINY-2921
+    Fixed the legacyoutput plugin incorrectly aligning images #TINY-3660
+    Fixed remove color not working when using the legacyoutput plugin #TINY-3756
+    Fixed the font size menu applying incorrect sizes when using the legacyoutput plugin #TINY-3773
+    Fixed scrollIntoView not working when the parent window was out of view #TINY-3663
+    Fixed the print plugin printing from the wrong window in IE11 #TINY-3762
+    Fixed content CSS loaded over CORS not loading in the preview plugin with content_css_cors enabled #TINY-3769
+    Fixed the link plugin missing the default "None" option for link list #TINY-3738
+    Fixed small dot visible with menubar and toolbar disabled in inline mode #TINY-3623
+    Fixed space key properly inserts a nbsp before/after block elements #TINY-3745
+    Fixed native context menu not showing with images in IE11 #TINY-3392
+    Fixed inconsistent browser context menu image selection #TINY-3789
+Version 5.0.7 (2019-06-05)
+    Added new toolbar button and menu item for inserting tables via dialog #TINY-3636
+    Added new API for adding/removing/changing tabs in the Help dialog #TINY-3535
+    Added highlighting of matched text in autocompleter items #TINY-3687
+    Added the ability for autocompleters to work with matches that include spaces #TINY-3704
+    Added new `imagetools_fetch_image` callback to allow custom implementations for cors loading of images #TINY-3658
+    Added `'http'` and `https` options to `link_assume_external_targets` to prepend `http://` or `https://` prefixes when URL does not contain a protocol prefix. Patch contributed by francoisfreitag. #GH-4335
+    Changed annotations navigation to work the same as inline boundaries #TINY-3396
+    Changed tabpanel API by adding a `name` field and changing relevant methods to use it #TINY-3535
+    Fixed text color not updating all color buttons when choosing a color #TINY-3602
+    Fixed the autocompleter not working with fragmented text #TINY-3459
+    Fixed the autosave plugin no longer overwrites window.onbeforeunload #TINY-3688
+    Fixed infinite loop in the paste plugin when IE11 takes a long time to process paste events. Patch contributed by lRawd. #GH-4987
+    Fixed image handle locations when using `fixed_toolbar_container`. Patch contributed by t00. #GH-4966
+    Fixed the autoresize plugin not firing `ResizeEditor` events #TINY-3587
+    Fixed editor in fullscreen mode not extending to the bottom of the screen #TINY-3701
+    Fixed list removal when pressing backspace after the start of the list item #TINY-3697
+    Fixed autocomplete not triggering from compositionend events #TINY-3711
+    Fixed `file_picker_callback` could not set the caption field on the insert image dialog #TINY-3172
+    Fixed the autocompleter menu showing up after a selection had been made #TINY-3718
+    Fixed an exception being thrown when a file or number input has focus during initialization. Patch contributed by t00 #GH-2194
+Version 5.0.6 (2019-05-22)
+    Added `icons_url` editor settings to enable icon packs to be loaded from a custom url #TINY-3585
+    Added `image_uploadtab` editor setting to control the visibility of the upload tab in the image dialog #TINY-3606
+    Added new api endpoints to the wordcount plugin and improved character count logic #TINY-3578
+    Changed plugin, language and icon loading errors to log in the console instead of a notification #TINY-3585
+    Fixed the textpattern plugin not working with fragmented text #TINY-3089
+    Fixed various toolbar drawer accessibility issues and added an animation #TINY-3554
+    Fixed issues with selection and ui components when toggling readonly mode #TINY-3592
+    Fixed so readonly mode works with inline editors #TINY-3592
+    Fixed docked inline toolbar positioning when scrolled #TINY-3621
+    Fixed initial value not being set on bespoke select in quickbars and toolbar drawer #TINY-3591
+    Fixed so that nbsp entities aren't trimmed in white-space: pre-line elements #TINY-3642
+    Fixed `mceInsertLink` command inserting spaces instead of url encoded characters #GH-4990
+    Fixed text content floating on top of dialogs in IE11 #TINY-3640
+Version 5.0.5 (2019-05-09)
+    Added menu items to match the forecolor/backcolor toolbar buttons #TINY-2878
+    Added default directionality based on the configured language #TINY-2621
+    Added styles, icons and tests for rtl mode #TINY-2621
+    Fixed autoresize not working with floating elements or when media elements finished loading #TINY-3545
+    Fixed incorrect vertical caret positioning in IE 11 #TINY-3188
+    Fixed submenu anchoring hiding overflowed content #TINY-3564
+    Removed unused and hidden validation icons to avoid displaying phantom tooltips #TINY-2329
+Version 5.0.4 (2019-04-23)
+    Added back URL dialog functionality, which is now available via `editor.windowManager.openUrl()` #TINY-3382
+    Added the missing throbber functionality when calling `editor.setProgressState(true)` #TINY-3453
+    Added function to reset the editor content and undo/dirty state via `editor.resetContent()` #TINY-3435
+    Added the ability to set menu buttons as active #TINY-3274
+    Added `editor.mode` API, featuring a custom editor mode API #TINY-3406
+    Added better styling to floating toolbar drawer #TINY-3479
+    Added the new premium plugins to the Help dialog plugins tab #TINY-3496
+    Added the linkchecker context menu items to the default configuration #TINY-3543
+    Fixed image context menu items showing on placeholder images #TINY-3280
+    Fixed dialog labels and text color contrast within notifications/alert banners to satisfy WCAG 4.5:1 contrast ratio for accessibility #TINY-3351
+    Fixed selectbox and colorpicker items not being translated #TINY-3546
+    Fixed toolbar drawer sliding mode to correctly focus the editor when tabbing via keyboard navigation #TINY-3533
+    Fixed positioning of the styleselect menu in iOS while using the mobile theme #TINY-3505
+    Fixed the menubutton `onSetup` callback to be correctly executed when rendering the menu buttons #TINY-3547
+    Fixed `default_link_target` setting to be correctly utilized when creating a link #TINY-3508
+    Fixed colorpicker floating marginally outside its container #TINY-3026
+    Fixed disabled menu items displaying as active when hovered #TINY-3027
+    Removed redundant mobile wrapper #TINY-3480
+Version 5.0.3 (2019-03-19)
+    Changed empty nested-menu items within the style formats menu to be disabled or hidden if the value of `style_formats_autohide` is `true` #TINY-3310
+    Changed the entire phrase 'Powered by Tiny' in the status bar to be a link instead of just the word 'Tiny' #TINY-3366
+    Changed `formatselect`, `styleselect` and `align` menus to use the `mceToggleFormat` command internally #TINY-3428
+    Fixed toolbar keyboard navigation to work as expected when `toolbar_drawer` is configured #TINY-3432
+    Fixed text direction buttons to display the correct pressed state in selections that have no explicit `dir` property #TINY-3138
+    Fixed the mobile editor to clean up properly when removed #TINY-3445
+    Fixed quickbar toolbars to add an empty box to the screen when it is set to `false` #TINY-3439
+    Fixed an issue where pressing the **Delete/Backspace** key at the edge of tables was creating incorrect selections #TINY-3371
+    Fixed an issue where dialog collection items (emoticon and special character dialogs) couldn't be selected with touch devices #TINY-3444
+    Fixed a type error introduced in TinyMCE version 5.0.2 when calling `editor.getContent()` with nested bookmarks #TINY-3400
+    Fixed an issue that prevented default icons from being overridden #TINY-3449
+    Fixed an issue where **Home/End** keys wouldn't move the caret correctly before or after `contenteditable=false` inline elements #TINY-2995
+    Fixed styles to be preserved in IE 11 when editing via the `fullpage` plugin #TINY-3464
+    Fixed the `link` plugin context toolbar missing the open link button #TINY-3461
+    Fixed inconsistent dialog component spacing #TINY-3436
+Version 5.0.2 (2019-03-05)
+    Added presentation and document presets to `htmlpanel` dialog component #TINY-2694
+    Added missing fixed_toolbar_container setting has been reimplemented in the Silver theme #TINY-2712
+    Added a new toolbar setting `toolbar_drawer` that moves toolbar groups which overflow the editor width into either a `sliding` or `floating` toolbar section #TINY-2874
+    Updated the build process to include package lock files in the dev distribution archive #TINY-2870
+    Fixed inline dialogs did not have aria attributes #TINY-2694
+    Fixed default icons are now available in the UI registry, allowing use outside of toolbar buttons #TINY-3307
+    Fixed a memory leak related to select toolbar items #TINY-2874
+    Fixed a memory leak due to format changed listeners that were never unbound #TINY-3191
+    Fixed an issue where content may have been lost when using permanent bookmarks #TINY-3400
+    Fixed the quicklink toolbar button not rendering in the quickbars plugin #TINY-3125
+    Fixed an issue where menus were generating invalid HTML in some cases #TINY-3323
+    Fixed an issue that could cause the mobile theme to show a blank white screen when the editor was inside an `overflow:hidden` element #TINY-3407
+    Fixed mobile theme using a transparent background and not taking up the full width on iOS #TINY-3414
+    Fixed the template plugin dialog missing the description field #TINY-3337
+    Fixed input dialog components using an invalid default type attribute #TINY-3424
+    Fixed an issue where backspace/delete keys after/before pagebreak elements wouldn't move the caret #TINY-3097
+    Fixed an issue in the table plugin where menu items and toolbar buttons weren't showing correctly based on the selection #TINY-3423
+    Fixed inconsistent button focus styles in Firefox #TINY-3377
+    Fixed the resize icon floating left when all status bar elements were disabled #TINY-3340
+    Fixed the resize handle to not show in fullscreen mode #TINY-3404
+Version 5.0.1 (2019-02-21)
+    Removed paste as text notification banner and paste_plaintext_inform setting #POW-102
+    Fixed an issue where adding links to images would replace the image with text #TINY-3356
+    Fixed an issue where the inline editor could use fractional pixels for positioning #TINY-3202
+    Fixed an issue where uploading non-image files in the Image Plugin upload tab threw an error. #TINY-3244
+    Added H1-H6 toggle button registration to the silver theme #TINY-3070
+    Fixed an issue in the media plugin that was causing the source url and height/width to be lost in certain circumstances #TINY-2858
+    Fixed an issue with the Context Toolbar not being removed when clicking outside of the editor #TINY-2804
+    Fixed an issue where clicking 'Remove link' wouldn't remove the link in certain circumstances #TINY-3199
+    Added code sample toolbar button will now toggle on when the cursor is in a code section #TINY-3040
+    Fixed an issue where the media plugin would fail when parsing dialog data #TINY-3218
+    Fixed an issue where retrieving the selected content as text didn't create newlines #TINY-3197
+    Fixed incorrect keyboard shortcuts in the Help dialog for Windows #TINY-3292
+    Fixed an issue where JSON serialization could produce invalid JSON #TINY-3281
+    Fixed production CSS including references to source maps #TINY-3920
+    Fixed development CSS was not included in the development zip #TINY-3920
+    Fixed the autocompleter matches predicate not matching on the start of words by default #TINY-3306
+    Added new settings to the emoticons plugin to allow additional emoticons to be added #TINY-3088
+    Fixed an issue where the page could be scrolled with modal dialogs open #TINY-2252
+    Fixed an issue where autocomplete menus would show an icon margin when no items had icons #TINY-3329
+    Fixed an issue in the quickbars plugin where images incorrectly showed the text selection toolbar #TINY-3338
+    Fixed an issue that caused the inline editor to fail to render when the target element already had focus #TINY-3353
+Version 5.0.0 (2019-02-04)
+    Full documentation for the version 5 features and changes is available at https://www.tiny.cloud/docs/release-notes/
+
+    Changes since RC2:
+    Fixed an issue where tab panel heights weren't sizing properly on smaller screens and weren't updating on resize #TINY-3242
+    Added links and registered names with * to denote premium plugins in Plugins tab of Help dialog #TINY-3223
+    Changed Tiny 5 mobile skin to look more uniform with desktop #TINY-2650
+    Fixed image tools not having any padding between the label and slider #TINY-3220
+    Blacklisted table, th and td as inline editor target #TINY-717
+    Fixed context toolbar toggle buttons not showing the correct state #TINY-3022
+    Fixed missing separators in the spellchecker context menu between the suggestions and actions #TINY-3217
+    Fixed notification icon positioning in alert banners #TINY-2196
+    Fixed a typo in the word count plugin name #TINY-3062
+    Fixed charmap and emoticons dialogs not having a primary button #TINY-3233
+    Fixed an issue where resizing wouldn't work correctly depending on the box-sizing model #TINY-3278
+Version 5.0.0-rc-2 (2019-01-22)
+    Fixed the link dialog such that it will now retain class attributes when updating links #TINY-2825
+    Added screen reader accessibility for sidebar and statusbar #TINY-2699
+    Updated Emoticons and Charmap dialogs to be screen reader accessible #TINY-2693
+    Fixed "Find and replace" not showing in the "Edit" menu by default #TINY-3061
+    Updated the textpattern plugin to properly support nested patterns and to allow running a command with a value for a pattern with a start and an end #TINY-2991
+    Removed unnecessary 'flex' and unused 'colspan' properties from the new dialog APIs #TINY-2973
+    Changed checkboxes to use a boolean for its state, instead of a string #TINY-2848
+    Fixed dropdown buttons missing the 'type' attribute, which could cause forms to be incorrectly submitted #TINY-2826
+    Fixed emoticon and charmap search not returning expected results in certain cases #TINY-3084
+    Changed formatting menus so they are registered and made the align toolbar button use an icon instead of text #TINY-2880
+    Fixed blank rel_list values throwing an exception in the link plugin #TINY-3149
+Version 5.0.0-rc-1 (2019-01-08)
+    Updated the font select dropdown logic to try to detect the system font stack and show "System Font" as the font name #TINY-2710
+    Fixed readonly mode not fully disabling editing content #TINY-2287
+    Updated the autocompleter to only show when it has matched items #TINY-2350
+    Added editor settings functionality to specify title attributes for toolbar groups #TINY-2690
+    Added icons instead of button text to improve Search and Replace dialog footer appearance #TINY-2654
+    Added `tox-dialog__table` instead of `mce-table-striped` class to enhance Help dialog appearance #TINY-2360
+    Added title attribute to iframes so, screen readers can announce iframe labels #TINY-2692
+    Updated SizeInput labels to "Height" and "Width" instead of Dimensions #TINY-2833
+    Fixed accessibility issues with the font select, font size, style select and format select toolbar dropdowns #TINY-2713
+    Fixed accessibility issues with split dropdowns #TINY-2697
+    Added a wordcount menu item, that defaults to appearing in the tools menu #TINY-2877
+    Fixed the legacyoutput plugin to be compatible with TinyMCE 5.0 #TINY-2301
+    Updated the build process to minify and generate ASCII only output for the emoticons database #TINY-2744
+    Fixed icons not showing correctly in the autocompleter popup #TINY-3029
+    Fixed an issue where preview wouldn't show anything in Edge under certain circumstances #TINY-3035
+    Fixed the height being incorrectly calculated for the autoresize plugin #TINY-2807
+Version 5.0.0-beta-1 (2018-11-30)
+    Changed the name of the "inlite" plugin to "quickbars" #TINY-2831
+    Fixed an inline mode issue where the save plugin upon saving can cause content loss #TINY-2659
+    Changed the background color icon to highlight background icon #TINY-2258
+    Added a new `addNestedMenuItem()` UI registry function and changed all nested menu items to use the new registry functions #TINY-2230
+    Changed Help dialog to be accessible to screen readers #TINY-2687
+    Changed the color swatch to save selected custom colors to local storage for use across sessions #TINY-2722
+    Added title attribute to color swatch colors #TINY-2669
+    Added anchorbar component to anchor inline toolbar dialogs to instead of the toolbar #TINY-2040
+    Added support for toolbar<n> and toolbar array config options to be squashed into a single toolbar and not create multiple toolbars #TINY-2195
+    Added error handling for when forced_root_block config option is set to true #TINY-2261
+    Added functionality for the removed_menuitems config option #TINY-2184
+    Fixed an issue in IE 11 where calling selection.getContent() would return an empty string when the editor didn't have focus #TINY-2325
+    Added the ability to use a string to reference menu items in menu buttons and submenu items #TINY-2253
+    Removed compat3x plugin #TINY-2815
+    Changed `WindowManager` API - methods `getParams`, `setParams` and `getWindows`, and the legacy `windows` property, have been removed. `alert` and `confirm` dialogs are no longer tracked in the window list. #TINY-2603
+Version 5.0.0-preview-4 (2018-11-12)
+    Fixed distraction free plugin #AP-470
+    Removed the tox-custom-editor class that was added to the wrapping element of codemirror #TINY-2211
+    Fixed contents of the input field being selected on focus instead of just recieving an outline highlight #AP-464
+    Added width and height placeholder text to image and media dialog dimensions input #AP-296
+    Fixed styling issues with dialogs and menus in IE 11 #AP-456
+    Fixed custom style format control not honoring custom formats #AP-393
+    Fixed context menu not appearing when clicking an image with a caption #AP-382
+    Fixed directionality of UI when using an RTL language #AP-423
+    Fixed page responsiveness with multiple inline editors #AP-430
+    Added the ability to keyboard navigate through menus, toolbars, sidebar and the status bar sequentially #AP-381
+    Fixed empty toolbar groups appearing through invalid configuration of the `toolbar` property #AP-450
+    Fixed text not being retained when updating links through the link dialog #AP-293
+    Added translation capability back to the editor's UI #AP-282
+    Fixed edit image context menu, context toolbar and toolbar items being incorrectly enabled when selecting invalid images #AP-323
+    Fixed emoji type ahead being shown when typing URLs #AP-366
+    Fixed toolbar configuration properties incorrectly expecting string arrays instead of strings #AP-342
+    Changed the editor resize handle so that it should be disabled when the autoresize plugin is turned on #AP-424
+    Fixed the block formatting toolbar item not showing a "Formatting" title when there is no selection #AP-321
+    Fixed clicking disabled toolbar buttons hiding the toolbar in inline mode #AP-380
+    Fixed `EditorResize` event not being fired upon editor resize #AP-327
+    Fixed tables losing styles when updating through the dialog #AP-368
+    Fixed context toolbar positioning to be more consistent near the edges of the editor #AP-318
+    Added `label` component type for dialogs to group components under a label
+    Fixed table of contents plugin now works with v5 toolbar APIs correctly #AP-347
+    Fixed the `link_context_toolbar` configuration not disabling the context toolbar #AP-458
+    Fixed the link context toolbar showing incorrect relative links #AP-435
+    Fixed the alignment of the icon in alert banner dialog components #TINY-2220
+    Changed UI text for microcopy improvements #TINY-2281
+    Fixed the visual blocks and visual char menu options not displaying their toggled state #TINY-2238
+    Fixed the editor not displaying as fullscreen when toggled #TINY-2237
+Version 5.0.0-preview-3 (2018-10-18)
+    Changed editor layout to use modern CSS properties over manually calculating dimensions #AP-324
+    Changed `autoresize_min_height` and `autoresize_max_height` configurations to `min_height` and `max_height` #AP-324
+    Fixed bugs with editor width jumping when resizing and the iframe not resizing to smaller than 150px in height #AP-324
+    Fixed mobile theme bug that prevented the editor from loading #AP-404
+    Fixed long toolbar groups extending outside of the editor instead of wrapping
+    Changed `Whole word` label in Search and Replace dialog to `Find whole words only` #AP-387
+    Fixed dialog titles so they are now proper case #AP-384
+    Fixed color picker default to be #000000 instead of #ff00ff #AP-216
+    Fixed "match case" option on the Find and Replace dialog is no longer selected by default #AP-298
+    Fixed vertical alignment of toolbar icons #DES-134
+    Fixed toolbar icons not appearing on IE11 #DES-133
+Version 5.0.0-preview-2 (2018-10-10)
+    Changed configuration of color options has been simplified to `color_map`, `color_cols`, and `custom_colors` #AP-328
+    Added swatch is now shown for colorinput fields, instead of the colorpicker directly #AP-328
+    Removed `colorpicker` plugin, it is now in the theme #AP-328
+    Removed `textcolor` plugin, it is now in the theme #AP-328
+    Fixed styleselect not updating the displayed item as the cursor moved #AP-388
+    Changed `height` configuration to apply to the editor frame (including menubar, toolbar, status bar) instead of the content area #AP-324
+    Added fontformats and fontsizes menu items #AP-390
+    Fixed preview iframe not expanding to the dialog size #AP-252
+    Fixed 'meta' shortcuts not translated into platform-specific text #AP-270
+    Fixed tabbed dialogs (Charmap and Emoticons) shrinking when no search results returned
+    Fixed a bug where alert banner icons were not retrieved from icon pack. #AP-330
+    Fixed component styles to flex so they fill large dialogs. #AP-252
+    Fixed editor flashing unstyled during load (still in progress). #AP-349
+Version 5.0.0-preview-1 (2018-10-01)
+    Developer preview 1
+    Initial list of features and changes is available at https://tiny.cloud/docs-preview/release-notes/new-features/
+Version 4.9.3 (2019-01-31)
+    Added a visualchars_default_state setting to the Visualchars Plugin. Patch contributed by mat3e.
+    Fixed a bug where scrolling on a page with more than one editor would cause a ResizeWindow event to fire. #TINY-3247
+    Fixed a bug where if a plugin threw an error during initialisation the whole editor would fail to load. #TINY-3243
+    Fixed a bug where getContent would include bogus elements when valid_elements setting was set up in a specific way. #TINY-3213
+    Fixed a bug where only a few function key names could be used when creating keyboard shortcuts. #TINY-3146
+    Fixed a bug where it wasn't possible to enter spaces into an editor after pressing shift+enter. #TINY-3099
+    Fixed a bug where no caret would be rendered after backspacing to a contenteditable false element. #TINY-2998
+    Fixed a bug where deletion to/from indented lists would leave list fragments in the editor. #TINY-2981
+Version 4.9.2 (2018-12-17)
+    Fixed a bug with pressing the space key on IE 11 would result in nbsp characters being inserted between words at the end of a block. #TINY-2996
+    Fixed a bug where character composition using quote and space on US International keyboards would produce a space instead of a quote. #TINY-2999
+    Fixed a bug where remove format wouldn't remove the inner most inline element in some situations. #TINY-2982
+    Fixed a bug where outdenting an list item would affect attributes on other list items within the same list. #TINY-2971
+    Fixed a bug where the DomParser filters wouldn't be applied for elements created when parsing invalid html. #TINY-2978
+    Fixed a bug where setProgressState wouldn't automatically close floating ui elements like menus. #TINY-2896
+    Fixed a bug where it wasn't possible to navigate out of a figcaption element using the arrow keys. #TINY-2894
+    Fixed a bug where enter key before an image inside a link would remove the image. #TINY-2780
+Version 4.9.1 (2018-12-04)
+    Added functionality to insert html to the replacement feature of the Textpattern Plugin. #TINY-2839
+    Fixed a bug where `editor.selection.getContent({format: 'text'})` didn't work as expected in IE11 on an unfocused editor. #TINY-2862
+    Fixed a bug in the Textpattern Plugin where the editor would get an incorrect selection after inserting a text pattern on Safari. #TINY-2838
+    Fixed a bug where the space bar didn't work correctly in editors with the forced_root_block setting set to false. #TINY-2816
+Version 4.9.0 (2018-11-27)
+    Added a replace feature to the Textpattern Plugin. #TINY-1908
+    Added functionality to the Lists Plugin that improves the indentation logic. #TINY-1790
+    Fixed a bug where it wasn't possible to delete/backspace when the caret was between a contentEditable=false element and a BR. #TINY-2372
+    Fixed a bug where copying table cells without a text selection would fail to copy anything. #TINY-1789
+    Implemented missing `autosave_restore_when_empty` functionality in the Autosave Plugin. Patch contributed by gzzo. #GH-4447
+    Reduced insertion of unnecessary nonbreaking spaces in the editor. #TINY-1879
+Version 4.8.5 (2018-10-30)
+    Added a content_css_cors setting to the editor that adds the crossorigin="anonymous" attribute to link tags added by the StyleSheetLoader. #TINY-1909
+    Fixed a bug where trying to remove formatting with a collapsed selection range would throw an exception. #GH-4636
+    Fixed a bug in the image plugin that caused updating figures to split contenteditable elements. #GH-4563
+    Fixed a bug that was causing incorrect viewport calculations for fixed position UI elements. #TINY-1897
+    Fixed a bug where inline formatting would cause the delete key to do nothing. #TINY-1900
+Version 4.8.4 (2018-10-23)
+    Added support for the HTML5 `main` element. #TINY-1877
+    Changed the keyboard shortcut to move focus to contextual toolbars to Ctrl+F9. #TINY-1812
+    Fixed a bug where content css could not be loaded from another domain. #TINY-1891
+    Fixed a bug on FireFox where the cursor would get stuck between two contenteditable false inline elements located inside of the same block element divided by a BR. #TINY-1878
+    Fixed a bug with the insertContent method where nonbreaking spaces would be inserted incorrectly. #TINY-1868
+    Fixed a bug where the toolbar of the inline editor would not be visible in some scenarios. #TINY-1862
+    Fixed a bug where removing the editor while more than one notification was open would throw an error. #TINY-1845
+    Fixed a bug where the menubutton would be rendered on top of the menu if the viewport didn't have enough height. #TINY-1678
+    Fixed a bug with the annotations api where annotating collapsed selections caused problems. #TBS-2449
+    Fixed a bug where wbr elements were being transformed into whitespace when using the Paste Plugin's paste as text setting. #GH-4638
+    Fixed a bug where the Search and Replace didn't replace spaces correctly. #GH-4632
+    Fixed a bug with sublist items not persisting selection. #GH-4628
+    Fixed a bug with mceInsertRawHTML command not working as expected. #GH-4625
+Version 4.8.3 (2018-09-13)
+    Fixed a bug where the Wordcount Plugin didn't correctly count words within tables on IE11. #TINY-1770
+    Fixed a bug where it wasn't possible to move the caret out of a table on IE11 and Firefox. #TINY-1682
+    Fixed a bug where merging empty blocks didn't work as expected, sometimes causing content to be deleted. #TINY-1781
+    Fixed a bug where the Textcolor Plugin didn't show the correct current color. #TINY-1810
+    Fixed a bug where clear formatting with a collapsed selection would sometimes clear formatting from more content than expected. #TINY-1813 #TINY-1821
+    Fixed a bug with the Table Plugin where it wasn't possible to keyboard navigate to the caption. #TINY-1818
+Version 4.8.2 (2018-08-09)
+    Moved annotator from "experimental" to "annotator" object on editor. #TBS-2398
+    Improved the multiclick normalization across browsers. #TINY-1788
+    Fixed a bug where running getSelectedBlocks with a collapsed selection between block elements would produce incorrect results. #TINY-1787
+    Fixed a bug where the ScriptLoaders loadScript method would not work as expected in FireFox when loaded on the same page as a ShadowDOM polyfill. #TINY-1786
+    Removed reference to ShadowDOM event.path as Blink based browsers now support event.composedPath. #TINY-1785
+    Fixed a bug where a reference to localStorage would throw an "access denied" error in IE11 with strict security settings. #TINY-1782
+    Fixed a bug where pasting using the toolbar button on an inline editor in IE11 would cause a looping behaviour. #TINY-1768
+Version 4.8.1 (2018-07-26)
+    Fixed a bug where the content of inline editors was being cleaned on every call of `editor.save()`. #TINY-1783
+    Fixed a bug where the arrow of the Inlite Theme toolbar was being rendered incorrectly in RTL mode. #TINY-1776
+    Fixed a bug with the Paste Plugin where pasting after inline contenteditable false elements moved the caret to the end of the line. #TINY-1758
+Version 4.8.0 (2018-06-27)
+    Added new "experimental" object in editor, with initial Annotator API. #TBS-2374
+    Fixed a bug where deleting paragraphs inside of table cells would delete the whole table cell. #TINY-1759
+    Fixed a bug in the Table Plugin where removing row height set on the row properties dialog did not update the table. #TINY-1730
+    Fixed a bug with the font select toolbar item didn't update correctly. #TINY-1683
+    Fixed a bug where all bogus elements would not be deleted when removing an inline editor. #TINY-1669
+Version 4.7.13 (2018-05-16)
+    Fixed a bug where Edge 17 wouldn't be able to select images or tables. #TINY-1679
+    Fixed issue where whitespace wasn't preserved when the editor was initialized on pre elements. #TINY-1649
+    Fixed a bug with the fontselect dropdowns throwing an error if the editor was hidden in Firefox. #TINY-1664
+    Fixed a bug where it wasn't possible to merge table cells on IE 11. #TINY-1671
+    Fixed a bug where textcolor wasn't applying properly on IE 11 in some situations. #TINY-1663
+    Fixed a bug where the justifyfull command state wasn't working correctly. #TINY-1677
+    Fixed a bug where the styles wasn't updated correctly when resizing some tables. #TINY-1668
+    Added missing code menu item from the default menu config. #TINY-1648
+    Added new align button for combining the separate align buttons into a menu button. #TINY-1652
+Version 4.7.12 (2018-05-03)
+    Added an option to filter out image svg data urls.
+    Added support for html5 details and summary elements.
+    Changed so the mce-abs-layout-item css rule targets html instead of body. Patch contributed by nazar-pc.
+    Fixed a bug where the "read" step on the mobile theme was still present on android mobile browsers.
+    Fixed a bug where all images in the editor document would reload on any editor change.
+    Fixed a bug with the Table Plugin where ObjectResized event wasn't being triggered on column resize.
+    Fixed so the selection is set to the first suitable caret position after editor.setContent called.
+    Fixed so links with xlink:href attributes are filtered correctly to prevent XSS.
+    Fixed a bug on IE11 where pasting content into an inline editor initialized on a heading element would create new editable elements.
+    Fixed a bug where readonly mode would not work as expected when the editor contained contentEditable=true elements.
+    Fixed a bug where the Link Plugin would throw an error when used together with the webcomponents polyfill. Patch contributed by 4esnog.
+    Fixed a bug where the "Powered by TinyMCE" branding link would break on XHTML pages. Patch contributed by tistre.
+    Fixed a bug where the same id would be used in the blobcache for all pasted images. Patch contributed by thorn0.
+Version 4.7.11 (2018-04-11)
+    Added a new imagetools_credentials_hosts option to the Imagetools Plugin.
+    Fixed a bug where toggling a list containing empty LIs would throw an error. Patch contributed by bradleyke.
+    Fixed a bug where applying block styles to a text with the caret at the end of the paragraph would select all text in the paragraph.
+    Fixed a bug where toggling on the Spellchecker Plugin would trigger isDirty on the editor.
+    Fixed a bug where it was possible to enter content into selection bookmark spans.
+    Fixed a bug where if a non paragraph block was configured in forced_root_block the editor.getContent method would return incorrect values with an empty editor.
+    Fixed a bug where dropdown menu panels stayed open and fixed in position when dragging dialog windows.
+    Fixed a bug where it wasn't possible to extend table cells with the space button in Safari.
+    Fixed a bug where the setupeditor event would thrown an error when using the Compat3x Plugin.
+    Fixed a bug where an error was thrown in FontInfo when called on a detached element.
+Version 4.7.10 (2018-04-03)
+    Removed the "read" step from the mobile theme.
+    Added normalization of triple clicks across browsers in the editor.
+    Added a `hasFocus` method to the editor that checks if the editor has focus.
+    Added correct icon to the Nonbreaking Plugin menu item.
+    Fixed so the `getContent`/`setContent` methods work even if the editor is not initialized.
+    Fixed a bug with the Media Plugin where query strings were being stripped from youtube links.
+    Fixed a bug where image styles were changed/removed when opening and closing the Image Plugin dialog.
+    Fixed a bug in the Table Plugin where some table cell styles were not correctly added to the content html.
+    Fixed a bug in the Spellchecker Plugin where it wasn't possible to change the spellchecker language.
+    Fixed so the the unlink action in the Link Plugin has a menu item and can be added to the contextmenu.
+    Fixed a bug where it wasn't possible to keyboard navigate to the start of an inline element on a new line within the same block element.
+    Fixed a bug with the Text Color Plugin where if used with an inline editor located at the bottom of the screen the colorpicker could appear off screen.
+    Fixed a bug with the UndoManager where undo levels were being added for nbzwsp characters.
+    Fixed a bug with the Table Plugin where the caret would sometimes be lost when keyboard navigating up through a table.
+    Fixed a bug where FontInfo.getFontFamily would throw an error when called on a removed editor.
+    Fixed a bug in Firefox where undo levels were not being added correctly for some specific operations.
+    Fixed a bug where initializing an inline editor inside of a table would make the whole table resizeable.
+    Fixed a bug where the fake cursor that appears next to tables on Firefox was positioned incorrectly when switching to fullscreen.
+    Fixed a bug where zwsp's weren't trimmed from the output from `editor.getContent({ format: 'text' })`.
+    Fixed a bug where the fontsizeselect/fontselect toolbar items showed the body info rather than the first possible caret position info on init.
+    Fixed a bug where it wasn't possible to select all content if the editor only contained an inline boundary element.
+    Fixed a bug where `content_css` urls with query strings wasn't working.
+    Fixed a bug in the Table Plugin where some table row styles were removed when changing other styles in the row properties dialog.
+Version 4.7.9 (2018-02-27)
+    Fixed a bug where the editor target element didn't get the correct style when removing the editor.
+Version 4.7.8 (2018-02-26)
+    Fixed an issue with the Help Plugin where the menuitem name wasn't lowercase.
+    Fixed an issue on MacOS where text and bold text did not have the same line-height in the autocomplete dropdown in the Link Plugin dialog.
+    Fixed a bug where the "paste as text" option in the Paste Plugin didn't work.
+    Fixed a bug where dialog list boxes didn't get positioned correctly in documents with scroll.
+    Fixed a bug where the Inlite Theme didn't use the Table Plugin api to insert correct tables.
+    Fixed a bug where the Inlite Theme panel didn't hide on blur in a correct way.
+    Fixed a bug where placing the cursor before a table in Firefox would scroll to the bottom of the table.
+    Fixed a bug where selecting partial text in table cells with rowspans and deleting would produce faulty tables.
+    Fixed a bug where the Preview Plugin didn't work on Safari due to sandbox security.
+    Fixed a bug where table cell selection using the keyboard threw an error.
+    Fixed so the font size and font family doesn't toggle the text but only sets the selected format on the selected text.
+    Fixed so the built-in spellchecking on Chrome and Safari creates an undo level when replacing words.
+Version 4.7.7 (2018-02-19)
+    Added a border style selector to the advanced tab of the Image Plugin.
+    Added better controls for default table inserted by the Table Plugin.
+    Added new `table_responsive_width` option to the Table Plugin that controls whether to use pixel or percentage widths.
+    Fixed a bug where the Link Plugin text didn't update when a URL was pasted using the context menu.
+    Fixed a bug with the Spellchecker Plugin where using "Add to dictionary" in the context menu threw an error.
+    Fixed a bug in the Media Plugin where the preview node for iframes got default width and height attributes that interfered with width/height styles.
+    Fixed a bug where backslashes were being added to some font family names in Firefox in the fontselect toolbar item.
+    Fixed a bug where errors would be thrown when trying to remove an editor that had not yet been fully initialized.
+    Fixed a bug where the Imagetools Plugin didn't update the images atomically.
+    Fixed a bug where the Fullscreen Plugin was throwing errors when being used on an inline editor.
+    Fixed a bug where drop down menus weren't positioned correctly in inline editors on scroll.
+    Fixed a bug with a semicolon missing at the end of the bundled javascript files.
+    Fixed a bug in the Table Plugin with cursor navigation inside of tables where the cursor would sometimes jump into an incorrect table cells.
+    Fixed a bug where indenting a table that is a list item using the "Increase indent" button would create a nested table.
+    Fixed a bug where text nodes containing only whitespace were being wrapped by paragraph elements.
+    Fixed a bug where whitespace was being inserted after br tags inside of paragraph tags.
+    Fixed a bug where converting an indented paragraph to a list item would cause the list item to have extra padding.
+    Fixed a bug where Copy/Paste in an editor with a lot of content would cause the editor to scroll to the top of the content in IE11.
+    Fixed a bug with a memory leak in the DragHelper. Path contributed by ben-mckernan.
+    Fixed a bug where the advanced tab in the Media Plugin was being shown even if it didn't contain anything. Patch contributed by gabrieeel.
+    Fixed an outdated eventname in the EventUtils. Patch contributed by nazar-pc.
+    Fixed an issue where the Json.parse function would throw an error when being used on a page with strict CSP settings.
+    Fixed so you can place the curser before and after table elements within the editor in Firefox and Edge/IE.
+Version 4.7.6 (2018-01-29)
+    Fixed a bug in the jquery integration where it threw an error saying that "global is not defined".
+    Fixed a bug where deleting a table cell whose previous sibling was set to contenteditable false would create a corrupted table.
+    Fixed a bug where highlighting text in an unfocused editor did not work correctly in IE11/Edge.
+    Fixed a bug where the table resize handles were not being repositioned when activating the Fullscreen Plugin.
+    Fixed a bug where the Imagetools Plugin dialog didn't honor editor RTL settings.
+    Fixed a bug where block elements weren't being merged correctly if you deleted from after a contenteditable false element to the beginning of another block element.
+    Fixed a bug where TinyMCE didn't work with module loaders like webpack.
+Version 4.7.5 (2018-01-22)
+    Fixed bug with the Codesample Plugin where it wasn't possible to edit codesamples when the editor was in inline mode.
+    Fixed bug where focusing on the status bar broke the keyboard navigation functionality.
+    Fixed bug where an error would be thrown on Edge by the Table Plugin when pasting using the PowerPaste Plugin.
+    Fixed bug in the Table Plugin where selecting row border style from the dropdown menu in advanced row properties would throw an error.
+    Fixed bug with icons being rendered incorrectly on Chrome on Mac OS.
+    Fixed bug in the Textcolor Plugin where the font color and background color buttons wouldn't trigger an ExecCommand event.
+    Fixed bug in the Link Plugin where the url field wasn't forced LTR.
+    Fixed bug where the Nonbreaking Plugin incorrectly inserted spaces into tables.
+    Fixed bug with the inline theme where the toolbar wasn't repositioned on window resize.
+Version 4.7.4 (2017-12-05)
+    Fixed bug in the Nonbreaking Plugin where the nonbreaking_force_tab setting was being ignored.
+    Fixed bug in the Table Plugin where changing row height incorrectly converted column widths to pixels.
+    Fixed bug in the Table Plugin on Edge and IE11 where resizing the last column after resizing the table would cause invalid column heights.
+    Fixed bug in the Table Plugin where keyboard navigation was not normalized between browsers.
+    Fixed bug in the Table Plugin where the colorpicker button would show even without defining the colorpicker_callback.
+    Fixed bug in the Table Plugin where it wasn't possible to set the cell background color.
+    Fixed bug where Firefox would throw an error when intialising an editor on an element that is hidden or not yet added to the DOM.
+    Fixed bug where Firefox would throw an error when intialising an editor inside of a hidden iframe.
+Version 4.7.3 (2017-11-23)
+    Added functionality to open the Codesample Plugin dialog when double clicking on a codesample. Patch contributed by dakuzen.
+    Fixed bug where undo/redo didn't work correctly with some formats and caret positions.
+    Fixed bug where the color picker didn't show up in Table Plugin dialogs.
+    Fixed bug where it wasn't possible to change the width of a table through the Table Plugin dialog.
+    Fixed bug where the Charmap Plugin couldn't insert some special characters.
+    Fixed bug where editing a newly inserted link would not actually edit the link but insert a new link next to it.
+    Fixed bug where deleting all content in a table cell made it impossible to place the caret into it.
+    Fixed bug where the vertical alignment field in the Table Plugin cell properties dialog didn't do anything.
+    Fixed bug where an image with a caption showed two sets of resize handles in IE11.
+    Fixed bug where pressing the enter button inside of an h1 with contenteditable set to true would sometimes produce a p tag.
+    Fixed bug with backspace not working as expected before a noneditable element.
+    Fixed bug where operating on tables with invalid rowspans would cause an error to be thrown.
+    Fixed so a real base64 representation of the image is available on the blobInfo that the images_upload_handler gets called with.
+    Fixed so the image upload tab is available when the images_upload_handler is defined (and not only when the images_upload_url is defined).
+Version 4.7.2 (2017-11-07)
+    Added newly rewritten Table Plugin.
+    Added support for attributes with colon in valid_elements and addValidElements.
+    Added support for dailymotion short url in the Media Plugin. Patch contributed by maat8.
+    Added support for converting to half pt when converting font size from px to pt. Patch contributed by danny6514.
+    Added support for location hash to the Autosave plugin to make it work better with SPAs using hash routing.
+    Added support for merging table cells when pasting a table into another table.
+    Changed so the language packs are only loaded once. Patch contributed by 0xor1.
+    Simplified the css for inline boundaries selection by switching to an attribute selector.
+    Fixed bug where an error would be thrown on editor initialization if the window.getSelection() returned null.
+    Fixed bug where holding down control or alt keys made the keyboard navigation inside an inline boundary not work as expected.
+    Fixed bug where applying formats in IE11 produced extra, empty paragraphs in the editor.
+    Fixed bug where the Word Count Plugin didn't count some mathematical operators correctly.
+    Fixed bug where removing an inline editor removed the element that the editor had been initialized on.
+    Fixed bug where setting the selection to the end of an editable container caused some formatting problems.
+    Fixed bug where an error would be thrown sometimes when an editor was removed because of the selection bookmark was being stored asynchronously.
+    Fixed a bug where an editor initialized on an empty list did not contain any valid cursor positions.
+    Fixed a bug with the Context Menu Plugin and webkit browsers on Mac where right-clicking inside a table would produce an incorrect selection.
+    Fixed bug where the Image Plugin constrain proportions setting wasn't working as expected.
+    Fixed bug where deleting the last character in a span with decorations produced an incorrect element when typing.
+    Fixed bug where focusing on inline editors made the toolbar flicker when moving between elements quickly.
+    Fixed bug where the selection would be stored incorrectly in inline editors when the mouseup event was fired outside the editor body.
+    Fixed bug where toggling bold at the end of an inline boundary would toggle off the whole word.
+    Fixed bug where setting the skin to false would not stop the loading of some skin css files.
+    Fixed bug in mobile theme where pinch-to-zoom would break after exiting the editor.
+    Fixed bug where sublists of a fully selected list would not be switched correctly when changing list style.
+    Fixed bug where inserting media by source would break the UndoManager.
+    Fixed bug where inserting some content into the editor with a specific selection would replace some content incorrectly.
+    Fixed bug where selecting all content with ctrl+a in IE11 caused problems with untoggling some formatting.
+    Fixed bug where the Search and Replace Plugin left some marker spans in the editor when undoing and redoing after replacing some content.
+    Fixed bug where the editor would not get a scrollbar when using the Fullscreen and Autoresize plugins together.
+    Fixed bug where the font selector would stop working correctly after selecting fonts three times.
+    Fixed so pressing the enter key inside of an inline boundary inserts a br after the inline boundary element.
+    Fixed a bug where it wasn't possible to use tab navigation inside of a table that was inside of a list.
+    Fixed bug where end_container_on_empty_block would incorrectly remove elements.
+    Fixed bug where content_styles weren't added to the Preview Plugin iframe.
+    Fixed so the beforeSetContent/beforeGetContent events are preventable.
+    Fixed bug where changing height value in Table Plugin advanced tab didn't do anything.
+    Fixed bug where it wasn't possible to remove formatting from content in beginning of table cell.
+Version 4.7.1 (2017-10-09)
+    Fixed bug where theme set to false on an inline editor produced an extra div element after the target element.
+    Fixed bug where the editor drag icon was misaligned with the branding set to false.
+    Fixed bug where doubled menu items were not being removed as expected with the removed_menuitems setting.
+    Fixed bug where the Table of contents plugin threw an error when initialized.
+    Fixed bug where it wasn't possible to add inline formats to text selected right to left.
+    Fixed bug where the paste from plain text mode did not work as expected.
+    Fixed so the style previews do not set color and background color when selected.
+    Fixed bug where the Autolink plugin didn't work as expected with some formats applied on an empty editor.
+    Fixed bug where the Textpattern plugin were throwing errors on some patterns.
+    Fixed bug where the Save plugin saved all editors instead of only the active editor. Patch contributed by dannoe.
+Version 4.7.0 (2017-10-03)
+    Added new mobile ui that is specifically designed for mobile devices.
+    Updated the default skin to be more modern and white since white is preferred by most implementations.
+    Restructured the default menus to be more similar to common office suites like Google Docs.
+    Fixed so theme can be set to false on both inline and iframe editor modes.
+    Fixed bug where inline editor would add/remove the visualblocks css multiple times.
+    Fixed bug where selection wouldn't be properly restored when editor lost focus and commands where invoked.
+    Fixed bug where toc plugin would generate id:s for headers even though a toc wasn't inserted into the content.
+    Fixed bug where is wasn't possible to drag/drop contents within the editor if paste_data_images where set to true.
+    Fixed bug where getParam and close in WindowManager would get the first opened window instead of the last opened window.
+    Fixed bug where delete would delete between cells inside a table in Firefox.
+Version 4.6.7 (2017-09-18)
+    Fixed bug where paste wasn't working in IOS.
+    Fixed bug where the Word Count Plugin didn't count some mathematical operators correctly.
+    Fixed bug where inserting a list in a table caused the cell to expand in height.
+    Fixed bug where pressing enter in a list located inside of a table deleted list items instead of inserting new list item.
+    Fixed bug where copy and pasting table cells produced inconsistent results.
+    Fixed bug where initializing an editor with an ID of 'length' would throw an exception.
+    Fixed bug where it was possible to split a non merged table cell.
+    Fixed bug where copy and pasting a list with a very specific selection into another list would produce a nested list.
+    Fixed bug where copy and pasting ordered lists sometimes produced unordered lists.
+    Fixed bug where padded elements inside other elements would be treated as empty.
+    Added some missing translations to Image, Link and Help plugins.
+    Fixed so you can resize images inside a figure element.
+    Fixed bug where an inline TinyMCE editor initialized on a table did not set selection on load in Chrome.
+    Fixed the positioning of the inlite toolbar when the target element wasn't big enough to fit the toolbar.
+Version 4.6.6 (2017-08-30)
+    Fixed so that notifications wrap long text content instead of bleeding outside the notification element.
+    Fixed so the content_style css is added after the skin and custom stylesheets.
+    Fixed bug where it wasn't possible to remove a table with the Cut button.
+    Fixed bug where the center format wasn't getting the same font size as the other formats in the format preview.
+    Fixed bug where the wordcount plugin wasn't counting hyphenated words correctly.
+    Fixed bug where all content pasted into the editor was added to the end of the editor.
+    Fixed bug where enter keydown on list item selection only deleted content and didn't create a new line.
+    Fixed bug where destroying the editor while the content css was still loading caused error notifications on Firefox.
+    Fixed bug where undoing cut operation in IE11 left some unwanted html in the editor content.
+    Fixed bug where enter keydown would throw an error in IE11.
+    Fixed bug where duplicate instances of an editor were added to the editors array when using the createEditor API.
+    Fixed bug where the formatter applied formats on the wrong content when spellchecker was activated.
+    Fixed bug where switching formats would reset font size on child nodes.
+    Fixed bug where the table caption element weren't always the first descendant to the table tag.
+    Fixed bug where pasting some content into the editor on chrome some newlines were removed.
+    Fixed bug where it wasn't possible to remove a list if a list item was a table element.
+    Fixed bug where copy/pasting partial selections of tables wouldn't produce a proper table.
+    Fixed bug where the searchreplace plugin could not find consecutive spaces.
+    Fixed bug where background color wasn't applied correctly on some partially selected contents.
+Version 4.6.5 (2017-08-02)
+    Added new inline_boundaries_selector that allows you to specify the elements that should have boundaries.
+    Added new local upload feature this allows the user to upload images directly from the image dialog.
+    Added a new api for providing meta data for plugins. It will show up in the help dialog if it's provided.
+    Fixed so that the notifications created by the notification manager are more screen reader accessible.
+    Fixed bug where changing the list format on multiple selected lists didn't change all of the lists.
+    Fixed bug where the nonbreaking plugin would insert multiple undo levels when pressing the tab key.
+    Fixed bug where delete/backspace wouldn't render a caret when all editor contents where deleted.
+    Fixed bug where delete/backspace wouldn't render a caret if the deleted element was a single contentEditable false element.
+    Fixed bug where the wordcount plugin wouldn't count words correctly if word where typed after applying a style format.
+    Fixed bug where the wordcount plugin would count mathematical formulas as multiple words for example 1+1=2.
+    Fixed bug where formatting of triple clicked blocks on Chrome/Safari would result in styles being added outside the visual selection.
+    Fixed bug where paste would add the contents to the end of the editor area when inline mode was used.
+    Fixed bug where toggling off bold formatting on text entered in a new paragraph would add an extra line break.
+    Fixed bug where autolink plugin would only produce a link on every other consecutive link on Firefox.
+    Fixed bug where it wasn't possible to select all contents if the content only had one pre element.
+    Fixed bug where sizzle would produce lagging behavior on some sites due to repaints caused by feature detection.
+    Fixed bug where toggling off inline formats wouldn't include the space on selected contents with leading or trailing spaces.
+    Fixed bug where the cut operation in UI wouldn't work in Chrome.
+    Fixed bug where some legacy editor initialization logic would throw exceptions about editor settings not being defined.
+    Fixed bug where it wasn't possible to apply text color to links if they where part of a non collapsed selection.
+    Fixed bug where an exception would be thrown if the user selected a video element and then moved the focus outside the editor.
+    Fixed bug where list operations didn't work if there where block elements inside the list items.
+    Fixed bug where applying block formats to lists wrapped in block elements would apply to all elements in that wrapped block.
+Version 4.6.4 (2017-06-13)
+    Fixed bug where the editor would move the caret when clicking on the scrollbar next to a content editable false block.
+    Fixed bug where the text color select dropdowns wasn't placed correctly when they didn't fit the width of the screen.
+    Fixed bug where the default editor line height wasn't working for mixed font size contents.
+    Fixed bug where the content css files for inline editors were loaded multiple times for multiple editor instances.
+    Fixed bug where the initial value of the font size/font family dropdowns wasn't displayed.
+    Fixed bug where the I18n api was not supporting arrays as the translation replacement values.
+    Fixed bug where chrome would display "The given range isn't in document." errors for invalid ranges passed to setRng.
+    Fixed bug where the compat3x plugin wasn't working since the global tinymce references wasn't resolved correctly.
+    Fixed bug where the preview plugin wasn't encoding the base url passed into the iframe contents producing a xss bug.
+    Fixed bug where the dom parser/serializer wasn't handling some special elements like noframes, title and xmp.
+    Fixed bug where the dom parser/serializer wasn't handling cdata sections with comments inside.
+    Fixed bug where the editor would scroll to the top of the editable area if a dialog was closed in inline mode.
+    Fixed bug where the link dialog would not display the right rel value if rel_list was configured.
+    Fixed bug where the context menu would select images on some platforms but not others.
+    Fixed bug where the filenames of images were not retained on dragged and drop into the editor from the desktop.
+    Fixed bug where the paste plugin would misrepresent newlines when pasting plain text and having forced_root_block configured.
+    Fixed so that the error messages for the imagetools plugin is more human readable.
+    Fixed so the internal validate setting for the parser/serializer can't be set from editor initialization settings.
+Version 4.6.3 (2017-05-30)
+    Fixed bug where the arrow keys didn't work correctly when navigating on nested inline boundary elements.
+    Fixed bug where delete/backspace didn't work correctly on nested inline boundary elements.
+    Fixed bug where image editing didn't work on subsequent edits of the same image.
+    Fixed bug where charmap descriptions wouldn't properly wrap if they exceeded the width of the box.
+    Fixed bug where the default image upload handler only accepted 200 as a valid http status code.
+    Fixed so rel on target=_blank links gets forced with only noopener instead of both noopener and noreferrer.
+Version 4.6.2 (2017-05-23)
+    Fixed bug where the SaxParser would run out of memory on very large documents.
+    Fixed bug with formatting like font size wasn't applied to del elements.
+    Fixed bug where various api calls would be throwing exceptions if they where invoked on a removed editor instance.
+    Fixed bug where the branding position would be incorrect if the editor was inside a hidden tab and then later showed.
+    Fixed bug where the color levels feature in the imagetools dialog wasn't working properly.
+    Fixed bug where imagetools dialog wouldn't pre-load images from CORS domains, before trying to prepare them for editing.
+    Fixed bug where the tab key would move the caret to the next table cell if being pressed inside a list inside a table.
+    Fixed bug where the cut/copy operations would loose parent context like the current format etc.
+    Fixed bug with format preview not working on invalid elements excluded by valid_elements.
+    Fixed bug where blocks would be merged in incorrect order on backspace/delete.
+    Fixed bug where zero length text nodes would cause issues with the undo logic if there where iframes present.
+    Fixed bug where the font size/family select lists would throw errors if the first node was a comment.
+    Fixed bug with csp having to allow local script evaluation since it was used to detect global scope.
+    Fixed bug where CSP required a relaxed option for javascript: URLs in unsupported legacy browsers.
+    Fixed bug where a fake caret would be rendered for td with the contenteditable=false.
+    Fixed bug where typing would be blocked on IE 11 when within a nested contenteditable=true/false structure.
+Version 4.6.1 (2017-05-10)
+    Added configuration option to list plugin to disable tab indentation.
+    Fixed bug where format change on very specific content could cause the selection to change.
+    Fixed bug where TinyMCE could not be lazyloaded through jquery integration.
+    Fixed bug where entities in style attributes weren't decoded correctly on paste in webkit.
+    Fixed bug where fontsize_formats option had been renamed incorrectly.
+    Fixed bug with broken backspace/delete behaviour between contenteditable=false blocks.
+    Fixed bug where it wasn't possible to backspace to the previous line with the inline boundaries functionality turned on.
+    Fixed bug where is wasn't possible to move caret left and right around a linked image with the inline boundaries functionality turned on.
+    Fixed bug where pressing enter after/before hr element threw exception. Patch contributed bradleyke.
+    Fixed so the CSS in the visualblocks plugin doesn't overwrite background color. Patch contributed by Christian Rank.
+    Fixed bug where multibyte characters weren't encoded correctly. Patch contributed by James Tarkenton.
+    Fixed bug where shift-click to select within contenteditable=true fields wasn't working.
+Version 4.6.0 (2017-05-04)
+    Dropped support for IE 8-10 due to market share and lack of support from Microsoft. See tinymce docs for details.
+    Added an inline boundary caret position feature that makes it easier to type at the beginning/end of links/code elements.
+    Added a help plugin that adds a button and a dialog showing the editor shortcuts and loaded plugins.
+    Added an inline_boundaries option that allows you to disable the inline boundary feature if it's not desired.
+    Added a new ScrollIntoView event that allows you to override the default scroll to element behavior.
+    Added role and aria- attributes as valid elements in the default valid elements config.
+    Added new internal flag for PastePreProcess/PastePostProcess this is useful to know if the paste was coming from an external source.
+    Added new ignore function to UndoManager this works similar to transact except that it doesn't add an undo level by default.
+    Fixed so that urls gets retained for images when being edited. This url is then passed on to the upload handler.
+    Fixed so that the editors would be initialized on readyState interactive instead of complete.
+    Fixed so that the init event of the editor gets fired once all contentCSS files have been properly loaded.
+    Fixed so that width/height of the editor gets taken from the textarea element if it's explicitly specified in styles.
+    Fixed so that keep_styles set to false no longer clones class/style from the previous paragraph on enter.
+    Fixed so that the default line-height is 1.2em to avoid zwnbsp characters from producing text rendering glitches on Windows.
+    Fixed so that loading errors of content css gets presented by a notification message.
+    Fixed so figure image elements can be linked when selected this wraps the figure image in a anchor element.
+    Fixed bug where it wasn't possible to copy/paste rows with colspans by using the table copy/paste feature.
+    Fixed bug where the protect setting wasn't properly applied to header/footer parts when using the fullpage plugin.
+    Fixed bug where custom formats that specified upper case element names where not applied correctly.
+    Fixed bug where some screen readers weren't reading buttons due to an aria specific fix for IE 8.
+    Fixed bug where cut wasn't working correctly on iOS due to it's clipboard API not working correctly.
+    Fixed bug where Edge would paste div elements instead of paragraphs when pasting plain text.
+    Fixed bug where the textpattern plugin wasn't dealing with trailing punctuations correctly.
+    Fixed bug where image editing would some times change the image format from jpg to png.
+    Fixed bug where some UI elements could be inserted into the toolbar even if they where not registered.
+    Fixed bug where it was possible to click the TD instead of the character in the character map and that caused an exception.
+    Fixed bug where the font size/font family dropdowns would sometimes show an incorrect value due to css not being loaded in time.
+    Fixed bug with the media plugin inserting undefined instead of retaining size when media_dimensions was set to false.
+    Fixed bug with deleting images when forced_root_blocks where set to false.
+    Fixed bug where input focus wasn't properly handled on nested content editable elements.
+    Fixed bug where Chrome/Firefox would throw an exception when selecting images due to recent change of setBaseAndExtent support.
+    Fixed bug where malformed blobs would throw exceptions now they are simply ignored.
+    Fixed bug where backspace/delete wouldn't work properly in some cases where all contents was selected in WebKit.
+    Fixed bug with Angular producing errors since it was expecting events objects to be patched with their custom properties.
+    Fixed bug where the formatter would apply formatting to spellchecker errors now all bogus elements are excluded.
+    Fixed bug with backspace/delete inside table caption elements wouldn't behave properly on IE 11.
+    Fixed bug where typing after a contenteditable false inline element could move the caret to the end of that element.
+    Fixed bug where backspace before/after contenteditable false blocks wouldn't properly remove the right element.
+    Fixed bug where backspace before/after contenteditable false inline elements wouldn't properly empty the current block element.
+    Fixed bug where vertical caret navigation with a custom line-height would sometimes match incorrect positions.
+    Fixed bug with paste on Edge where character encoding wasn't handled properly due to a browser bug.
+    Fixed bug with paste on Edge where extra fragment data was inserted into the contents when pasting.
+    Fixed bug with pasting contents when having a whole block element selected on WebKit could cause WebKit spans to appear.
+    Fixed bug where the visualchars plugin wasn't working correctly showing invisible nbsp characters.
+    Fixed bug where browsers would hang if you tried to load some malformed html contents.
+    Fixed bug where the init call promise wouldn't resolve if the specified selector didn't find any matching elements.
+    Fixed bug where the Schema isValidChild function was case sensitive.
+Version 4.5.3 (2017-02-01)
+    Added keyboard navigation for menu buttons when the menu is in focus.
+    Added api to the list plugin for setting custom classes/attributes on lists.
+    Added validation for the anchor plugin input field according to W3C id naming specifications.
+    Fixed bug where media placeholders were removed after resize with the forced_root_block setting set to false.
+    Fixed bug where deleting selections with similar sibling nodes sometimes deleted the whole document.
+    Fixed bug with inlite theme where several toolbars would appear scrolling when more than one instance of the editor was in use.
+    Fixed bug where the editor would throw error with the fontselect plugin on hidden editor instances in Firefox.
+    Fixed bug where the background color would not stretch to the font size.
+    Fixed bug where font size would be removed when changing background color.
+    Fixed bug where the undomanager trimmed away whitespace between nodes on undo/redo.
+    Fixed bug where media_dimensions=false in media plugin caused the editor to throw an error.
+    Fixed bug where IE was producing font/u elements within links on paste.
+    Fixed bug where some button tooltips were broken when compat3x was in use.
+    Fixed bug where backspace/delete/typeover would remove the caption element.
+    Fixed bug where powerspell failed to function when compat3x was enabled.
+    Fixed bug where it wasn't possible to apply sub/sup on text with large font size.
+    Fixed bug where pre tags with spaces weren't treated as content.
+    Fixed bug where Meta+A would select the entire document instead of all contents in nested ce=true elements.
+Version 4.5.2 (2017-01-04)
+    Added missing keyboard shortcut description for the underline menu item in the format menu.
+    Fixed bug where external blob urls wasn't properly handled by editor upload logic. Patch contributed by David Oviedo.
+    Fixed bug where urls wasn't treated as a single word by the wordcount plugin.
+    Fixed bug where nbsp characters wasn't treated as word delimiters by the wordcount plugin.
+    Fixed bug where editor instance wasn't properly passed to the format preview logic. Patch contributed by NullQuery.
+    Fixed bug where the fake caret wasn't hidden when you moved selection to a cE=false element.
+    Fixed bug where it wasn't possible to edit existing code sample blocks.
+    Fixed bug where it wasn't possible to delete editor contents if the selection included an empty block.
+    Fixed bug where the formatter wasn't expanding words on some international characters. Patch contributed by Martin Larochelle.
+    Fixed bug where the open link feature wasn't working correctly on IE 11.
+    Fixed bug where enter before/after a cE=false block wouldn't properly padd the paragraph with an br element.
+    Fixed so font size and font family select boxes always displays a value by using the runtime style as a fallback.
+    Fixed so missing plugins will be logged to console as warnings rather than halting the initialization of the editor.
+    Fixed so splitbuttons become normal buttons in advlist plugin if styles are empty. Patch contributed by René Schleusner.
+    Fixed so you can multi insert rows/cols by selecting table cells and using insert rows/columns.
+Version 4.5.1 (2016-12-07)
+    Fixed bug where the lists plugin wouldn't initialize without the advlist plugins if served from cdn.
+    Fixed bug where selectors with "*" would cause the style format preview to throw an error.
+    Fixed bug with toggling lists off on lists with empty list items would throw an error.
+    Fixed bug where editing images would produce non existing blob uris.
+    Fixed bug where the offscreen toc selection would be treated as the real toc element.
+    Fixed bug where the aria level attribute for element path would have an incorrect start index.
+    Fixed bug where the offscreen selection of cE=false that where very wide would be shown onscreen. Patch contributed by Steven Bufton.
+    Fixed so the default_link_target gets applied to links created by the autolink plugin.
+    Fixed so that the name attribute gets removed by the anchor plugin if editing anchors.
+Version 4.5.0 (2016-11-23)
+    Added new toc plugin allows you to insert table of contents based on editor headings.
+    Added new auto complete menu to all url fields. Adds history, link to anchors etc.
+    Added new sidebar api that allows you to add custom sidebar panels and buttons to toggle these.
+    Added new insert menu button that allows you to have multiple insert functions under the same menu button.
+    Added new open link feature to ctrl+click, alt+enter and context menu.
+    Added new media_embed_handler option to allow the media plugin to be populated with custom embeds.
+    Added new support for editing transparent images using the image tools dialog.
+    Added new images_reuse_filename option to allow filenames of images to be retained for upload.
+    Added new security feature where links with target="_blank" will by default get rel="noopener noreferrer".
+    Added new allow_unsafe_link_target to allow you to opt-out of the target="_blank" security feature.
+    Added new style_formats_autohide option to automatically hide styles based on context.
+    Added new codesample_content_css option to specify where the code sample prism css is loaded from.
+    Added new support for Japanese/Chinese word count following the unicode standards on this.
+    Added new fragmented undo levels this dramatically reduces flicker on contents with iframes.
+    Added new live previews for complex elements like table or lists.
+    Fixed bug where it wasn't possible to properly tab between controls in a dialog with a disabled form item control.
+    Fixed bug where firefox would generate a rectangle on elements produced after/before a cE=false elements.
+    Fixed bug with advlist plugin not switching list element format properly in some edge cases.
+    Fixed bug where col/rowspans wasn't correctly computed by the table plugin in some cases.
+    Fixed bug where the table plugin would thrown an error if object_resizing was disabled.
+    Fixed bug where some invalid markup would cause issues when running in XHTML mode. Patch contributed by Charles Bourasseau.
+    Fixed bug where the fullscreen class wouldn't be removed properly when closing dialogs.
+    Fixed bug where the PastePlainTextToggle event wasn't fired by the paste plugin when the state changed.
+    Fixed bug where table the row type wasn't properly updated in table row dialog. Patch contributed by Matthias Balmer.
+    Fixed bug where select all and cut wouldn't place caret focus back to the editor in WebKit. Patch contributed by Daniel Jalkut.
+    Fixed bug where applying cell/row properties to multiple cells/rows would reset other unchanged properties.
+    Fixed bug where some elements in the schema would have redundant/incorrect children.
+    Fixed bug where selector and target options would cause issues if used together.
+    Fixed bug where drag/drop of images from desktop on chrome would thrown an error.
+    Fixed bug where cut on WebKit/Blink wouldn't add an undo level.
+    Fixed bug where IE 11 would scroll to the cE=false elements when they where selected.
+    Fixed bug where keys like F5 wouldn't work when a cE=false element was selected.
+    Fixed bug where the undo manager wouldn't stop the typing state when commands where executed.
+    Fixed bug where unlink on wrapped links wouldn't work properly.
+    Fixed bug with drag/drop of images on WebKit where the image would be deleted form the source editor.
+    Fixed bug where the visual characters mode would be disabled when contents was extracted from the editor.
+    Fixed bug where some browsers would toggle of formats applied to the caret when clicking in the editor toolbar.
+    Fixed bug where the custom theme function wasn't working correctly.
+    Fixed bug where image option for custom buttons required you to have icon specified as well.
+    Fixed bug where the context menu and contextual toolbars would be visible at the same time and sometimes overlapping.
+    Fixed bug where the noneditable plugin would double wrap elements when using the noneditable_regexp option.
+    Fixed bug where tables would get padding instead of margin when you used the indent button.
+    Fixed bug where the charmap plugin wouldn't properly insert non breaking spaces.
+    Fixed bug where the color previews in color input boxes wasn't properly updated.
+    Fixed bug where the list items of previous lists wasn't merged in the right order.
+    Fixed bug where it wasn't possible to drag/drop inline-block cE=false elements on IE 11.
+    Fixed bug where some table cell merges would produce incorrect rowspan/colspan.
+    Fixed so the font size of the editor defaults to 14px instead of 11px this can be overridden by custom css.
+    Fixed so wordcount is debounced to reduce cpu hogging on larger texts.
+    Fixed so tinymce global gets properly exported as a module when used with some module bundlers.
+    Fixed so it's possible to specify what css properties you want to preview on specific formats.
+    Fixed so anchors are contentEditable=false while within the editor.
+    Fixed so selected contents gets wrapped in a inline code element by the codesample plugin.
+    Fixed so conditional comments gets properly stripped independent of case. Patch contributed by Georgii Dolzhykov.
+    Fixed so some escaped css sequences gets properly handled. Patch contributed by Georgii Dolzhykov.
+    Fixed so notifications with the same message doesn't get displayed at the same time.
+    Fixed so F10 can be used as an alternative key to focus to the toolbar.
+    Fixed various api documentation issues and typos.
+    Removed layer plugin since it wasn't really ported from 3.x and there doesn't seem to be much use for it.
+    Removed moxieplayer.swf from the media plugin since it wasn't used by the media plugin.
+    Removed format state from the advlist plugin to be more consistent with common word processors.
+Version 4.4.3 (2016-09-01)
+    Fixed bug where copy would produce an exception on Chrome.
+    Fixed bug where deleting lists on IE 11 would merge in correct text nodes.
+    Fixed bug where deleting partial lists with indentation wouldn't cause proper normalization.
+Version 4.4.2 (2016-08-25)
+    Added new importcss_exclusive option to disable unique selectors per group.
+    Added new group specific selector_converter option to importcss plugin.
+    Added new codesample_languages option to apply custom languages to codesample plugin.
+    Added new codesample_dialog_width/codesample_dialog_height options.
+    Fixed bug where fullscreen button had an incorrect keyboard shortcut.
+    Fixed bug where backspace/delete wouldn't work correctly from a block to a cE=false element.
+    Fixed bug where smartpaste wasn't detecting links with special characters in them like tilde.
+    Fixed bug where the editor wouldn't get proper focus if you clicked on a cE=false element.
+    Fixed bug where it wasn't possible to copy/paste table rows that had merged cells.
+    Fixed bug where merging cells could some times produce invalid col/rowspan attibute values.
+    Fixed bug where getBody would sometimes thrown an exception now it just returns null if the iframe is clobbered.
+    Fixed bug where drag/drop of cE=false element wasn't properly constrained to viewport.
+    Fixed bug where contextmenu on Mac would collapse any selection to a caret.
+    Fixed bug where rtl mode wasn't rendered properly when loading a language pack with the rtl flag.
+    Fixed bug where Kamer word bounderies would be stripped from contents.
+    Fixed bug where lists would sometimes render two dots or numbers on the same line.
+    Fixed bug where the skin_url wasn't used by the inlite theme.
+    Fixed so data attributes are ignored when comparing formats in the formatter.
+    Fixed so it's possible to disable inline toolbars in the inlite theme.
+    Fixed so template dialog gets resized if it doesn't fit the window viewport.
+Version 4.4.1 (2016-07-26)
+    Added smart_paste option to paste plugin to allow disabling the paste behavior if needed.
+    Fixed bug where png urls wasn't properly detected by the smart paste logic.
+    Fixed bug where the element path wasn't working properly when multiple editor instances where used.
+    Fixed bug with creating lists out of multiple paragraphs would just create one list item instead of multiple.
+    Fixed bug where scroll position wasn't properly handled by the inlite theme to place the toolbar properly.
+    Fixed bug where multiple instances of the editor using the inlite theme didn't render the toolbar properly.
+    Fixed bug where the shortcut label for fullscreen mode didn't match the actual shortcut key.
+    Fixed bug where it wasn't possible to select cE=false blocks using touch devices on for example iOS.
+    Fixed bug where it was possible to select the child image within a cE=false on IE 11.
+    Fixed so inserts of html containing lists doesn't merge with any existing lists unless it's a paste operation.
+Version 4.4.0 (2016-06-30)
+    Added new inlite theme this is a more lightweight inline UI.
+    Added smarter paste logic that auto detects urls in the clipboard and inserts images/links based on that.
+    Added a better image resize algorithm for better image quality in the imagetools plugin.
+    Fixed bug where it wasn't possible to drag/dropping cE=false elements on FF.
+    Fixed bug where backspace/delete before/after a cE=false block would produce a new paragraph.
+    Fixed bug where list style type css property wasn't preserved when indenting lists.
+    Fixed bug where merging of lists where done even if the list style type was different.
+    Fixed bug where the image_dataimg_filter function wasn't used when pasting images.
+    Fixed bug where nested editable within a non editable element would cause scroll on focus in Chrome.
+    Fixed so invalid targets for inline mode is blocked on initialization. We only support elements that can have children.
+Version 4.3.13 (2016-06-08)
+    Added characters with a diacritical mark to charmap plugin. Patch contributed by Dominik Schilling.
+    Added better error handling if the image proxy service would produce errors.
+    Fixed issue with pasting list items into list items would produce nested list rather than a merged list.
+    Fixed bug where table selection could get stuck in selection mode for inline editors.
+    Fixed bug where it was possible to place the caret inside the resize grid elements.
+    Fixed bug where it wasn't possible to place in elements horizontally adjacent cE=false blocks.
+    Fixed bug where multiple notifications wouldn't be properly placed on screen.
+    Fixed bug where multiple editor instance of the same id could be produces in some specific integrations.
+Version 4.3.12 (2016-05-10)
+    Fixed bug where focus calls couldn't be made inside the editors PostRender event handler.
+    Fixed bug where some translations wouldn't work as expected due to a bug in editor.translate.
+    Fixed bug where the node change event could fire with a node out side the root of the editor.
+    Fixed bug where Chrome wouldn't properly present the keyboard paste clipboard details when paste was clicked.
+    Fixed bug where merged cells in tables couldn't be selected from right to left.
+    Fixed bug where insert row wouldn't properly update a merged cells rowspan property.
+    Fixed bug where the color input boxes preview field wasn't properly set on initialization.
+    Fixed bug where IME composition inside table cells wouldn't work as expected on IE 11.
+    Fixed so all shadow dom support is under and experimental flag due to flaky browser support.
+Version 4.3.11 (2016-04-25)
+    Fixed bug where it wasn't possible to insert empty blocks though the API unless they where padded.
+    Fixed bug where you couldn't type the Euro character on Windows.
+    Fixed bug where backspace/delete from a cE=false element to a text block didn't work properly.
+    Fixed bug where the text color default grid would render incorrectly.
+    Fixed bug where the codesample plugin wouldn't load the css in the editor for multiple editors.
+    Fixed so the codesample plugin textarea gets focused by default.
+Version 4.3.10 (2016-04-12)
+    Fixed bug where the key "y" on WebKit couldn't be entered due to conflict with keycode for F10 on keypress.
+Version 4.3.9 (2016-04-12)
+    Added support for focusing the contextual toolbars using keyboard.
+    Added keyboard support for slider UI controls. You can no increase/decrease using arrow keys.
+    Added url pattern matching for Dailymotion to media plugin. Patch contributed by Bertrand Darbon.
+    Added body_class to template plugin preview. Patch contributed by Milen Petrinski.
+    Added options to better override textcolor pickers with custom colors. Patch contributed by Xavier Boubert.
+    Added visual arrows to inline contextual toolbars so that they point to the element being active.
+    Fixed so toolbars for tables or other larger elements get better positioned below the scrollable viewport.
+    Fixed bug where it was possible to click links inside cE=false blocks.
+    Fixed bug where event targets wasn't properly handled in Safari Technical Preview.
+    Fixed bug where drag/drop text in FF 45 would make the editor caret invisible.
+    Fixed bug where the remove state wasn't properly set on editor instances when detected as clobbered.
+    Fixed bug where offscreen selection of some cE=false elements would render onscreen. Patch contributed by Steven Bufton
+    Fixed bug where enter would clone styles out side the root on editors inside a span. Patch contributed by ChristophKaser.
+    Fixed bug where drag/drop of images into the editor didn't work correctly in FF.
+    Fixed so the first item in panels for the imagetools dialog gets proper keyboard focus.
+    Changed the Meta+Shift+F shortcut to Ctrl+Shift+F since Czech, Slovak, Polish languages used the first one for input.
+Version 4.3.8 (2016-03-15)
+    Fixed bug where inserting HR at the end of a block element would produce an extra empty block.
+    Fixed bug where links would be clickable when readonly mode was enabled.
+    Fixed bug where the formatter would normalize to the wrong node on very specific content.
+    Fixed bug where some nested list items couldn't be indented properly.
+    Fixed bug where links where clickable in the preview dialog.
+    Fixed so the alt attribute doesn't get padded with an empty value by default.
+    Fixed so nested alignment works more correctly. You will now alter the alignment to the closest block parent.
+Version 4.3.7 (2016-03-02)
+    Fixed bug where incorrect icons would be rendered for imagetools edit and color levels.
+    Fixed bug where navigation using arrow keys inside a SelectBox didn't move up/down.
+    Fixed bug where the visualblocks plugin would render borders round internal UI elements.
+Version 4.3.6 (2016-03-01)
+    Added new paste_remember_plaintext_info option to allow a global disable of the plain text mode notification.
+    Added new PastePlainTextToggle event that fires when plain text mode toggles on/off.
+    Fixed bug where it wasn't possible to select media elements since the drag logic would snap it to mouse cursor.
+    Fixed bug where it was hard to place the caret inside nested cE=true elements when the outer cE=false element was focused.
+    Fixed bug where editors wouldn't properly initialize if both selector and mode where used.
+    Fixed bug where IME input inside table cells would switch the IME off.
+    Fixed bug where selection inside the first table cell would cause the whole table cell to get selected.
+    Fixed bug where error handling of images being uploaded wouldn't properly handle faulty statuses.
+    Fixed bug where inserting contents before a HR would cause an exception to be thrown.
+    Fixed bug where copy/paste of Excel data would be inserted as an image.
+    Fixed caret position issues with copy/paste of inline block cE=false elements.
+    Fixed issues with various menu item focus bugs in Chrome. Where the focused menu bar item wasn't properly blurred.
+    Fixed so the notifications have a solid background since it would be hard to read if there where text under it.
+    Fixed so notifications gets animated similar to the ones used by dialogs.
+    Fixed so larger images that gets pasted is handled better.
+    Fixed so the window close button is more uniform on various platform and also increased it's hit area.
+Version 4.3.5 (2016-02-11)
+    Npm version bump due to package not being fully updated.
+Version 4.3.4 (2016-02-11)
+    Added new OpenWindow/CloseWindow events that gets fired when windows open/close.
+    Added new NewCell/NewRow events that gets fired when table cells/rows are created.
+    Added new Promise return value to tinymce.init makes it easier to handle initialization.
+    Removed the jQuery version the jQuery plugin is now moved into the main package.
+    Removed jscs from build process since eslint can now handle code style checking.
+    Fixed various bugs with drag/drop of contentEditable:false elements.
+    Fixed bug where deleting of very specific nested list items would result in an odd list.
+    Fixed bug where lists would get merged with adjacent lists outside the editable inline root.
+    Fixed bug where MS Edge would crash when closing a dialog then clicking a menu item.
+    Fixed bug where table cell selection would add undo levels.
+    Fixed bug where table cell selection wasn't removed when inline editor where removed.
+    Fixed bug where table cell selection wouldn't work properly on nested tables.
+    Fixed bug where table merge menu would be available when merging between thead and tbody.
+    Fixed bug where table row/column resize wouldn't get properly removed when the editor was removed.
+    Fixed bug where Chrome would scroll to the editor if there where a empty hash value in document url.
+    Fixed bug where the cache suffix wouldn't work correctly with the importcss plugin.
+    Fixed bug where selection wouldn't work properly on MS Edge on Windows Phone 10.
+    Fixed so adjacent pre blocks gets joined into one pre block since that seems like the user intent.
+    Fixed so events gets properly dispatched in shadow dom. Patch provided by Nazar Mokrynskyi.
+Version 4.3.3 (2016-01-14)
+    Added new table_resize_bars configuration setting.  This setting allows you to disable the table resize bars.
+    Added new beforeInitialize event to tinymce.util.XHR lets you modify XHR properties before open. Patch contributed by Brent Clintel.
+    Added new autolink_pattern setting to autolink plugin. Enables you to override the default autolink formats. Patch contributed by Ben Tiedt.
+    Added new charmap option that lets you override the default charmap of the charmap plugin.
+    Added new charmap_append option that lets you add new characters to the default charmap of the charmap plugin.
+    Added new insertCustomChar event that gets fired when a character is inserted by the charmap plugin.
+    Fixed bug where table cells started with a superfluous &nbsp; in IE10+.
+    Fixed bug where table plugin would retain all BR tags when cells were merged.
+    Fixed bug where media plugin would strip underscores from youtube urls.
+    Fixed bug where IME input would fail on IE 11 if you typed within a table.
+    Fixed bug where double click selection of a word would remove the space before the word on insert contents.
+    Fixed bug where table plugin would produce exceptions when hovering tables with invalid structure.
+    Fixed bug where fullscreen wouldn't scroll back to it's original position when untoggled.
+    Fixed so the template plugins templates setting can be a function that gets a callback that can provide templates.
+Version 4.3.2 (2015-12-14)
+    Fixed bug where the resize bars for table cells were not affected by the object_resizing property.
+    Fixed bug where the contextual table toolbar would appear incorrectly if TinyMCE was initialized inline inside a table.
+    Fixed bug where resizing table cells did not fire a node change event or add an undo level.
+    Fixed bug where double click selection of text on IE 11 wouldn't work properly.
+    Fixed bug where codesample plugin would incorrectly produce br elements inside code elements.
+    Fixed bug where media plugin would strip dashes from youtube urls.
+    Fixed bug where it was possible to move the caret into the table resize bars.
+    Fixed bug where drag/drop into a cE=false element was possible on IE.
+Version 4.3.1 (2015-11-30)
+    Fixed so it's possible to disable the table inline toolbar by setting it to false or an empty string.
+    Fixed bug where it wasn't possible to resize some tables using the drag handles.
+    Fixed bug where unique id:s would clash for multiple editor instances and cE=false selections.
+    Fixed bug where the same plugin could be initialized multiple times.
+    Fixed bug where the table inline toolbars would be displayed at the same time as the image toolbars.
+    Fixed bug where the table selection rect wouldn't be removed when selecting another control element.
+Version 4.3.0 (2015-11-23)
+    Added new table column/row resize support. Makes it a lot more easy to resize the columns/rows in a table.
+    Added new table inline toolbar. Makes it easier to for example add new rows or columns to a table.
+    Added new notification API. Lets you display floating notifications to the end user.
+    Added new codesample plugin that lets you insert syntax highlighted pre elements into the editor.
+    Added new image_caption to images. Lets you create images with captions using a HTML5 figure/figcaption elements.
+    Added new live previews of embeded videos. Lets you play the video right inside the editor.
+    Added new setDirty method and "dirty" event to the editor. Makes it easier to track the dirty state change.
+    Added new setMode method to Editor instances that lets you dynamically switch between design/readonly.
+    Added new core support for contentEditable=false elements within the editor overrides the browsers broken behavior.
+    Rewrote the noneditable plugin to use the new contentEditable false core logic.
+    Fixed so the dirty state doesn't set to false automatically when the undo index is set to 0.
+    Fixed the Selection.placeCaretAt so it works better on IE when the coordinate is between paragraphs.
+    Fixed bug where data-mce-bogus="all" element contents where counted by the word count plugin.
+    Fixed bug where contentEditable=false elements would be indented by the indent buttons.
+    Fixed bug where images within contentEditable=false would be selected in WebKit on mouse click.
+    Fixed bug in DOMUntils split method where the replacement parameter wouldn't work on specific cases.
+    Fixed bug where the importcss plugin would import classes from the skin content css file.
+    Fixed so all button variants have a wrapping span for it's text to make it easier to skin.
+    Fixed so it's easier to exit pre block using the arrow keys.
+    Fixed bug where listboxes with fix widths didn't render correctly.
+Version 4.2.8 (2015-11-13)
+    Fixed bug where it was possible to delete tables as the inline root element if all columns where selected.
+    Fixed bug where the UI buttons active state wasn't properly updated due to recent refactoring of that logic.
+Version 4.2.7 (2015-10-27)
+    Fixed bug where backspace/delete would remove all formats on the last paragraph character in WebKit/Blink.
+    Fixed bug where backspace within a inline format element with a bogus caret container would move the caret.
+    Fixed bug where backspace/delete on selected table cells wouldn't add an undo level.
+    Fixed bug where script tags embedded within the editor could sometimes get a mce- prefix prepended to them
+    Fixed bug where validate: false option could produce an error to be thrown from the Serialization step.
+    Fixed bug where inline editing of a table as the root element could let the user delete that table.
+    Fixed bug where inline editing of a table as the root element wouldn't properly handle enter key.
+    Fixed bug where inline editing of a table as the root element would normalize the selection incorrectly.
+    Fixed bug where inline editing of a list as the root element could let the user delete that list.
+    Fixed bug where inline editing of a list as the root element could let the user split that list.
+    Fixed bug where resize handles would be rendered on editable root elements such as table.
+Version 4.2.6 (2015-09-28)
+    Added capability to set request headers when using XHRs.
+    Added capability to upload local images automatically default delay is set to 30 seconds after editing images.
+    Added commands ids mceEditImage, mceAchor and mceMedia to be avaiable from execCommand.
+    Added Edge browser to saucelabs grunt task. Patch contributed by John-David Dalton.
+    Fixed bug where blob uris not produced by tinymce would produce HTML invalid markup.
+    Fixed bug where selection of contents of a nearly empty editor in Edge would sometimes fail.
+    Fixed bug where color styles woudln't be retained on copy/paste in Blink/Webkit.
+    Fixed bug where the table plugin would throw an error when inserting rows after a child table.
+    Fixed bug where the template plugin wouldn't handle functions as variable replacements.
+    Fixed bug where undo/redo sometimes wouldn't work properly when applying formatting collapsed ranges.
+    Fixed bug where shift+delete wouldn't do a cut operation on Blink/WebKit.
+    Fixed bug where cut action wouldn't properly store the before selection bookmark for the undo level.
+    Fixed bug where backspace in side an empty list element on IE would loose editor focus.
+    Fixed bug where the save plugin wouldn't enable the buttons when a change occurred.
+    Fixed bug where Edge wouldn't initialize the editor if a document.domain was specified.
+    Fixed bug where enter key before nested images would sometimes not properly expand the previous block.
+    Fixed bug where the inline toolbars wouldn't get properly hidden when blurring the editor instance.
+    Fixed bug where Edge would paste Chinese characters on some Windows 10 installations.
+    Fixed bug where IME would loose focus on IE 11 due to the double trailing br bug fix.
+    Fixed bug where the proxy url in imagetools was incorrect. Patch contributed by Wong Ho Wang.
+Version 4.2.5 (2015-08-31)
+    Added fullscreen capability to embedded youtube and vimeo videos.
+    Fixed bug where the uploadImages call didn't work on IE 10.
+    Fixed bug where image place holders would be uploaded by uploadImages call.
+    Fixed bug where images marked with bogus would be uploaded by the uploadImages call.
+    Fixed bug where multiple calls to uploadImages would result in decreased performance.
+    Fixed bug where pagebreaks were editable to imagetools patch contributed by Rasmus Wallin.
+    Fixed bug where the element path could cause too much recursion exception.
+    Fixed bug for domains containing ".min". Patch contributed by Loïc Février.
+    Fixed so validation of external links to accept a number after www. Patch contributed by Victor Carvalho.
+    Fixed so the charmap is exposed though execCommand. Patch contributed by Matthew Will.
+    Fixed so that the image uploads are concurrent for improved performance.
+    Fixed various grammar problems in inline documentation. Patches provided by nikolas.
+Version 4.2.4 (2015-08-17)
+    Added picture as a valid element to the HTML 5 schema. Patch contributed by Adam Taylor.
+    Fixed bug where contents would be duplicated on drag/drop within the same editor.
+    Fixed bug where floating/alignment of images on Edge wouldn't work properly.
+    Fixed bug where it wasn't possible to drag images on IE 11.
+    Fixed bug where image selection on Edge would sometimes fail.
+    Fixed bug where contextual toolbars icons wasn't rendered properly when using the toolbar_items_size.
+    Fixed bug where searchreplace dialog doesn't get prefilled with the selected text.
+    Fixed bug where fragmented matches wouldn't get properly replaced by the searchreplace plugin.
+    Fixed bug where enter key wouldn't place the caret if was after a trailing space within an inline element.
+    Fixed bug where the autolink plugin could produce multiple links for the same text on Gecko.
+    Fixed bug where EditorUpload could sometimes throw an exception if the blob wasn't found.
+    Fixed xss issues with media plugin not properly filtering out some script attributes.
+Version 4.2.3 (2015-07-30)
+    Fixed bug where image selection wasn't possible on Edge due to incompatible setBaseAndExtend API.
+    Fixed bug where image blobs urls where not properly destroyed by the imagetools plugin.
+    Fixed bug where keyboard shortcuts wasn't working correctly on IE 8.
+    Fixed skin issue where the borders of panels where not visible on IE 8.
+Version 4.2.2 (2015-07-22)
+    Fixed bug where float panels were not being hidden on inline editor blur when fixed_toolbar_container config option was in use.
+    Fixed bug where combobox states wasn't properly updated if contents where updated without keyboard.
+    Fixed bug where pasting into textbox or combobox would move the caret to the end of text.
+    Fixed bug where removal of bogus span elements before block elements would remove whitespace between nodes.
+    Fixed bug where repositioning of inline toolbars where async and producing errors if the editor was removed from DOM to early. Patch by iseulde.
+    Fixed bug where element path wasn't working correctly. Patch contributed by iseulde.
+    Fixed bug where menus wasn't rendered correctly when custom images where added to a menu. Patch contributed by Naim Hammadi.
+Version 4.2.1 (2015-06-29)
+    Fixed bug where back/forward buttons in the browser would render blob images as broken images.
+    Fixed bug where Firefox would throw regexp to big error when replacing huge base64 chunks.
+    Fixed bug rendering issues with resize and context toolbars not being placed properly until next animation frame.
+    Fixed bug where the rendering of the image while cropping would some times not be centered correctly.
+    Fixed bug where listbox items with submenus would me selected as active.
+    Fixed bug where context menu where throwing an error when rendering.
+    Fixed bug where resize both option wasn't working due to resent addClass API change. Patch contributed by Jogai.
+    Fixed bug where a hideAll call for container rendered inline toolbars would throw an error.
+    Fixed bug where onclick event handler on combobox could cause issues if element.id was a function by some polluting libraries.
+    Fixed bug where listboxes wouldn't get proper selected sub menu item when using link_list or image_list.
+    Fixed so the UI controls are as wide as 4.1.x to avoid wrapping controls in toolbars.
+    Fixed so the imagetools dialog is adaptive for smaller screen sizes.
+Version 4.2.0 (2015-06-25)
+    Added new flat default skin to make the UI more modern.
+    Added new imagetools plugin, lets you crop/resize and apply filters to images.
+    Added new contextual toolbars support to the API lets you add floating toolbars for specific CSS selectors.
+    Added new promise feature fill as tinymce.util.Promise.
+    Added new built in image upload feature lets you upload any base64 encoded image within the editor as files.
+    Fixed bug where resize handles would appear in the right position in the wrong editor when switching between resizable content in different inline editors.
+    Fixed bug where tables would not be inserted in inline mode due to previous float panel fix.
+    Fixed bug where floating panels would remain open when focus was lost on inline editors.
+    Fixed bug where cut command on Chrome would thrown a browser security exception.
+    Fixed bug where IE 11 sometimes would report an incorrect size for images in the image dialog.
+    Fixed bug where it wasn't possible to remove inline formatting at the end of block elements.
+    Fixed bug where it wasn't possible to delete table cell contents when cell selection was vertical.
+    Fixed bug where table cell wasn't emptied from block elements if delete/backspace where pressed in empty cell.
+    Fixed bug where cmd+shift+arrow didn't work correctly on Firefox mac when selecting to start/end of line.
+    Fixed bug where removal of bogus elements would sometimes remove whitespace between nodes.
+    Fixed bug where the resize handles wasn't updated when the main window was resized.
+    Fixed so script elements gets removed by default to prevent possible XSS issues in default config implementations.
+    Fixed so the UI doesn't need manual reflows when using non native layout managers.
+    Fixed so base64 encoded images doesn't slow down the editor on modern browsers while editing.
+    Fixed so all UI elements uses touch events to improve mobile device support.
+    Removed the touch click quirks patch for iOS since it did more harm than good.
+    Removed the non proportional resize handles since. Unproportional resize can still be done by holding the shift key.
+Version 4.1.10 (2015-05-05)
+    Fixed bug where plugins loaded with compat3x would sometimes throw errors when loading using the jQuery version.
+    Fixed bug where extra empty paragraphs would get deleted in WebKit/Blink due to recent Quriks fix.
+    Fixed bug where the editor wouldn't work properly on IE 12 due to some required browser sniffing.
+    Fixed bug where formatting shortcut keys where interfering with Mac OS X screenshot keys.
+    Fixed bug where the caret wouldn't move to the next/previous line boundary on Cmd+Left/Right on Gecko.
+    Fixed bug where it wasn't possible to remove formats from very specific nested contents.
+    Fixed bug where undo levels wasn't produced when typing letters using the shift or alt+ctrl modifiers.
+    Fixed bug where the dirty state wasn't properly updated when typing using the shift or alt+ctrl modifiers.
+    Fixed bug where an error would be thrown if an autofocused editor was destroyed quickly after its initialization. Patch provided by thorn0.
+    Fixed issue with dirty state not being properly updated on redo operation.
+    Fixed issue with entity decoder not handling incorrectly written numeric entities.
+    Fixed issue where some PI element values wouldn't be properly encoded.
+Version 4.1.9 (2015-03-10)
+    Fixed bug where indentation wouldn't work properly for non list elements.
+    Fixed bug with image plugin not pulling the image dimensions out correctly if a custom document_base_url was used.
+    Fixed bug where ctrl+alt+[1-9] would conflict with the AltGr+[1-9] on Windows. New shortcuts is ctrl+shift+[1-9].
+    Fixed bug with removing formatting on nodes in inline mode would sometimes include nodes outside the editor body.
+    Fixed bug where extra nbsp:s would be inserted when you replaced a word surrounded by spaces using insertContent.
+    Fixed bug with pasting from Google Docs would produce extra strong elements and line feeds.
+Version 4.1.8 (2015-03-05)
+    Added new html5 sizes attribute to img elements used together with srcset.
+    Added new elementpath option that makes it possible to disable the element path but keep the statusbar.
+    Added new option table_style_by_css for the table plugin to set table styling with css rather than table attributes.
+    Added new link_assume_external_targets option to prompt the user to prepend http:// prefix if the supplied link does not contain a protocol prefix.
+    Added new image_prepend_url option to allow a custom base path/url to be added to images.
+    Added new table_appearance_options option to make it possible to disable some options.
+    Added new image_title option to make it possible to alter the title of the image, disabled by default.
+    Fixed bug where selection starting from out side of the body wouldn't produce a proper selection range on IE 11.
+    Fixed bug where pressing enter twice before a table moves the cursor in the table and causes a javascript error.
+    Fixed bug where advanced image styles were not respected.
+    Fixed bug where the less common Shift+Delete didn't produce a proper cut operation on WebKit browsers.
+    Fixed bug where image/media size constrain logic would produce NaN when handling non number values.
+    Fixed bug where internal classes where removed by the removeformat command.
+    Fixed bug with creating links table cell contents with a specific selection would throw a exceptions on WebKit/Blink.
+    Fixed bug where valid_classes option didn't work as expected according to docs. Patch provided by thorn0.
+    Fixed bug where jQuery plugin would patch the internal methods multiple times. Patch provided by Drew Martin.
+    Fixed bug where backspace key wouldn't delete the current selection of newly formatted content.
+    Fixed bug where type over of inline formatting elements wouldn't properly keep the format on WebKit/Blink.
+    Fixed bug where selection needed to be properly normalized on modern IE versions.
+    Fixed bug where Command+Backspace didn't properly delete the whole line of text but the previous word.
+    Fixed bug where UI active states wheren't properly updated on IE if you placed caret within the current range.
+    Fixed bug where delete/backspace on WebKit/Blink would remove span elements created by the user.
+    Fixed bug where delete/backspace would produce incorrect results when deleting between two text blocks with br elements.
+    Fixed bug where captions where removed when pasting from MS Office.
+    Fixed bug where lists plugin wouldn't properly remove fully selected nested lists.
+    Fixed bug where the ttf font used for icons would throw an warning message on Gecko on Mac OS X.
+    Fixed a bug where applying a color to text did not update the undo/redo history.
+    Fixed so shy entities gets displayed when using the visualchars plugin.
+    Fixed so removeformat removes ins/del by default since these might be used for strikethough.
+    Fixed so multiple language packs can be loaded and added to the global I18n data structure.
+    Fixed so transparent color selection gets treated as a normal color selection. Patch contributed by Alexander Hofbauer.
+    Fixed so it's possible to disable autoresize_overflow_padding, autoresize_bottom_margin options by setting them to false.
+    Fixed so the charmap plugin shows the description of the character in the dialog. Patch contributed by Jelle Hissink.
+    Removed address from the default list of block formats since it tends to be missused.
+    Fixed so the pre block format is called preformatted to make it more verbose.
+    Fixed so it's possible to context scope translation strings this isn't needed most of the time.
+    Fixed so the max length of the width/height input fields of the media dialog is 5 instead of 3.
+    Fixed so drag/dropped contents gets properly processed by paste plugin since it's basically a paste. Patch contributed by Greg Fairbanks.
+    Fixed so shortcut keys for headers is ctrl+alt+[1-9] instead of ctrl+[1-9] since these are for switching tabs in the browsers.
+    Fixed so "u" doesn't get converted into a span element by the legacy input filter. Since this is now a valid HTML5 element.
+    Fixed font families in order to provide appropriate web-safe fonts.
+Version 4.1.7 (2014-11-27)
+    Added HTML5 schema support for srcset, source and picture. Patch contributed by mattheu.
+    Added new cache_suffix setting to enable cache busting by producing unique urls.
+    Added new paste_convert_word_fake_lists option to enable users to disable the fake lists convert logic.
+    Fixed so advlist style changes adds undo levels for each change.
+    Fixed bug where WebKit would sometimes produce an exception when the autolink plugin where looking for URLs.
+    Fixed bug where IE 7 wouldn't be rendered properly due to aggressive css compression.
+    Fixed bug where DomQuery wouldn't accept window as constructor element.
+    Fixed bug where the color picker in 3.x dialogs wouldn't work properly. Patch contributed by Callidior.
+    Fixed bug where the image plugin wouldn't respect the document_base_url.
+    Fixed bug where the jQuery plugin would fail to append to elements named array prototype names.
+Version 4.1.6 (2014-10-08)
+    Fixed bug with clicking on the scrollbar of the iframe would cause a JS error to be thrown.
+    Fixed bug where null would produce an exception if you passed it to selection.setRng.
+    Fixed bug where Ctrl/Cmd+Tab would indent the current list item if you switched tabs in the browser.
+    Fixed bug where pasting empty cells from Excel would result in a broken table.
+    Fixed bug where it wasn't possible to switch back to default list style type.
+    Fixed issue where the select all quirk fix would fire for other modifiers than Ctrl/Cmd combinations.
+    Replaced jake with grunt since it is more mainstream and has better plugin support.
+Version 4.1.5 (2014-09-09)
+    Fixed bug where sometimes the resize rectangles wouldn't properly render on images on WebKit/Blink.
+    Fixed bug in list plugin where delete/backspace would merge empty LI elements in lists incorrectly.
+    Fixed bug where empty list elements would result in empty LI elements without it's parent container.
+    Fixed bug where backspace in empty caret formatted element could produce an type error exception of Gecko.
+    Fixed bug where lists pasted from word with a custom start index above 9 wouldn't be properly handled.
+    Fixed bug where tabfocus plugin would tab out of the editor instance even if the default action was prevented.
+    Fixed bug where tabfocus wouldn't tab properly to other adjacent editor instances.
+    Fixed bug where the DOMUtils setStyles wouldn't properly removed or update the data-mce-style attribute.
+    Fixed bug where dialog select boxes would be placed incorrectly if document.body wasn't statically positioned.
+    Fixed bug where pasting would sometimes scroll to the top of page if the user was using the autoresize plugin.
+    Fixed bug where caret wouldn't be properly rendered by Chrome when clicking on the iframes documentElement.
+    Fixed so custom images for menubutton/splitbutton can be provided. Patch contributed by Naim Hammadi.
+    Fixed so the default action of windows closing can be prevented by blocking the default action of the close event.
+    Fixed so nodeChange and focus of the editor isn't automatically performed when opening sub dialogs.
+Version 4.1.4 (2014-08-21)
+    Added new media_filter_html option to media plugin that blocks any conditional comments, scripts etc within a video element.
+    Added new content_security_policy option allows you to set custom policy for iframe contents. Patch contributed by Francois Chagnon.
+    Fixed bug where activate/deactivate events wasn't firing properly when switching between editors.
+    Fixed bug where placing the caret on iOS was difficult due to a WebKit bug with touch events.
+    Fixed bug where the resize helper wouldn't render properly on older IE versions.
+    Fixed bug where resizing images inside tables on older IE versions would sometimes fail depending mouse position.
+    Fixed bug where editor.insertContent would produce an exception when inserting select/option elements.
+    Fixed bug where extra empty paragraphs would be produced if block elements where inserted inside span elements.
+    Fixed bug where the spellchecker menu item wouldn't be properly checked if spell checking was started before it was rendered.
+    Fixed bug where the DomQuery filter function wouldn't remove non elements from collection.
+    Fixed bug where document with custom document.domain wouldn't properly render the editor.
+    Fixed bug where IE 8 would throw exception when trying to enter invalid color values into colorboxes.
+    Fixed bug where undo manager could incorrectly add an extra undo level when custom resize handles was removed.
+    Fixed bug where it wouldn't be possible to alter cell properties properly on table cells on IE 8.
+    Fixed so the color picker button in table dialog isn't shown unless you include the colorpicker plugin or add your own custom color picker.
+    Fixed so activate/deactivate events fire when windowManager opens a window since.
+    Fixed so the table advtab options isn't separated by an underscore to normalize naming with image_advtab option.
+    Fixed so the table cell dialog has proper padding when the advanced tab in disabled.
+Version 4.1.3 (2014-07-29)
+    Added event binding logic to tinymce.util.XHR making it possible to override headers and settings before any request is made.
+    Fixed bug where drag events wasn't fireing properly on older IE versions since the event handlers where bound to document.
+    Fixed bug where drag/dropping contents within the editor on IE would force the contents into plain text mode even if it was internal content.
+    Fixed bug where IE 7 wouldn't open menus properly due to a resize bug in the browser auto closing them immediately.
+    Fixed bug where the DOMUtils getPos logic wouldn't produce a valid coordinate inside the body if the body was positioned non static.
+    Fixed bug where the element path and format state wasn't properly updated if you had the wordcount plugin enabled.
+    Fixed bug where a comment at the beginning of source would produce an exception in the formatter logic.
+    Fixed bug where setAttrib/getAttrib on null would throw exception together with any hooked attributes like style.
+    Fixed bug where table sizes wasn't properly retained when copy/pasting on WebKit/Blink.
+    Fixed bug where WebKit/Blink would produce colors in RGB format instead of the forced HEX format when deleting contents.
+    Fixed bug where the width attribute wasn't updated on tables if you changed the size inside the table dialog.
+    Fixed bug where control selection wasn't properly handled when the caret was placed directly after an image.
+    Fixed bug where selecting the contents of table cells using the selection.select method wouldn't place the caret properly.
+    Fixed bug where the selection state for images wasn't removed when placing the caret right after an image on WebKit/Blink.
+    Fixed bug where all events wasn't properly unbound when and editor instance was removed or destroyed by some external innerHTML call.
+    Fixed bug where it wasn't possible or very hard to select images on iOS when the onscreen keyboard was visible.
+    Fixed so auto_focus can take a boolean argument this will auto focus the last initialized editor might be useful for single inits.
+    Fixed so word auto detect lists logic works better for faked lists that doesn't have specific markup.
+    Fixed so nodeChange gets fired on mouseup as it used to before 4.1.1 we optimized that event to fire less often.
+    Removed the finish menu item from spellchecker menu since it's redundant you can stop spellchecking by toggling menu item or button.
+Version 4.1.2 (2014-07-15)
+    Added offset/grep to DomQuery class works basically the same as it's jQuery equivalent.
+    Fixed bug where backspace/delete or setContent with an empty string would remove header data when using the fullpage plugin.
+    Fixed bug where tinymce.remove with a selector not matching any editors would remove all editors.
+    Fixed bug where resizing of the editor didn't work since the theme was calling setStyles instead of setStyle.
+    Fixed bug where IE 7 would fail to append html fragments to iframe document when using DomQuery.
+    Fixed bug where the getStyle DOMUtils method would produce an exception if it was called with null as it's element.
+    Fixed bug where the paste plugin would remove the element if the none of the paste_webkit_styles rules matched the current style.
+    Fixed bug where contextmenu table items wouldn't work properly on IE since it would some times fire an incorrect selection change.
+    Fixed bug where the padding/border values wasn't used in the size calculation for the body size when using autoresize. Patch contributed by Matt Whelan.
+    Fixed bug where conditional word comments wouldn't be properly removed when pasting plain text.
+    Fixed bug where resizing would sometime fail on IE 11 when the mouseup occurred inside the resizable element.
+    Fixed so the iframe gets initialized without any inline event handlers for better CSP support. Patch contributed by Matt Whelan.
+    Fixed so the tinymce.dom.Sizzle is the latest version of sizzle this resolves the document context bug.
+Version 4.1.1 (2014-07-08)
+    Fixed bug where pasting plain text on some WebKit versions would result in an empty line.
+    Fixed bug where resizing images inside tables on IE 11 wouldn't work properly.
+    Fixed bug where IE 11 would sometimes throw "Invalid argument" exception when editor contents was set to an empty string.
+    Fixed bug where document.activeElement would throw exceptions on IE 9 when that element was hidden or removed from dom.
+    Fixed bug where WebKit/Blink sometimes produced br elements with the Apple-interchange-newline class.
+    Fixed bug where table cell selection wasn't properly removed when copy/pasting table cells.
+    Fixed bug where pasting nested list items from Word wouldn't produce proper semantic nested lists.
+    Fixed bug where right clicking using the contextmenu plugin on WebKit/Blink on Mac OS X would select the target current word or line.
+    Fixed bug where it wasn't possible to alter table cell properties on IE 8 using the context menu.
+    Fixed bug where the resize helper wouldn't be correctly positioned on older IE versions.
+    Fixed bug where fullpage plugin would produce an error if you didn't specify a doctype encoding.
+    Fixed bug where anchor plugin would get the name/id of the current element even if it wasn't anchor element.
+    Fixed bug where visual aids for tables wouldn't be properly disabled when changing the border size.
+    Fixed bug where some control selection events wasn't properly fired on older IE versions.
+    Fixed bug where table cell selection on older IE versions would prevent resizing of images.
+    Fixed bug with paste_data_images paste option not working properly on modern IE versions.
+    Fixed bug where custom elements with underscores in the name wasn't properly parsed/serialized.
+    Fixed bug where applying inline formats to nested list elements would produce an incorrect formatting result.
+    Fixed so it's possible to hide items from elements path by using preventDefault/stopPropagation.
+    Fixed so inline mode toolbar gets rendered right aligned if the editable element positioned to the documents right edge.
+    Fixed so empty inline elements inside empty block elements doesn't get removed if configured to be kept intact.
+    Fixed so DomQuery parentsUntil/prevUntil/nextUntil supports selectors/elements/filters etc.
+    Fixed so legacyoutput plugin overrides fontselect and fontsizeselect controls and handles font elements properly.
+Version 4.1.0 (2014-06-18)
+    Added new file_picker_callback option to replace the old file_browser_callback the latter will still work though.
+    Added new custom colors to textcolor plugin will be displayed if a color picker is provided also shows the latest colors.
+    Added new color_picker_callback option to enable you to add custom color pickers to the editor.
+    Added new advanced tabs to table/cell/row dialogs to enable you to select colors for border/background.
+    Added new colorpicker plugin that lets you select colors from a hsv color picker.
+    Added new tinymce.util.Color class to handle color parsing and converting.
+    Added new colorpicker UI widget element lets you add a hsv color picker to any form/window.
+    Added new textpattern plugin that allows you to use markdown like text patterns to format contents.
+    Added new resize helper element that shows the current width & height while resizing.
+    Added new "once" method to Editor and EventDispatcher enables since callback execution events.
+    Added new jQuery like class under tinymce.dom.DomQuery it's exposed on editor instances (editor.$) and globally under (tinymce.$).
+    Fixed so the default resize method for images are proportional shift/ctrl can be used to make an unproportional size.
+    Fixed bug where the image_dimensions option of the image plugin would cause exceptions when it tried to update the size.
+    Fixed bug where table cell dialog class field wasn't properly updated when editing an a table cell with an existing class.
+    Fixed bug where Safari on Mac would produce webkit-fake-url for pasted images so these are now removed.
+    Fixed bug where the nodeChange event would get fired before the selection was changed when clicking inside the current selection range.
+    Fixed bug where valid_classes option would cause exception when it removed internal prefixed classes like mce-item-.
+    Fixed bug where backspace would cause navigation in IE 8 on an inline element and after a caret formatting was applied.
+    Fixed so placeholder images produced by the media plugin gets selected when inserted/edited.
+    Fixed so it's possible to drag in images when the paste_data_images option is enabled. Might be useful for mail clients.
+    Fixed so images doesn't get a width/height applied if the image_dimensions option is set to false useful for responsive contents.
+    Fixed so it's possible to pass in an optional arguments object for the nodeChanged function to be passed to all nodechange event listeners.
+    Fixed bug where media plugin embed code didn't update correctly.

Diff do ficheiro suprimidas por serem muito extensas
+ 0 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/icons/default/icons.min.js


+ 92 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/jquery.tinymce.min.js

@@ -0,0 +1,92 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ */
+/**
+ * Jquery integration plugin.
+ *
+ * @class tinymce.core.JqueryIntegration
+ * @private
+ */
+!function(){var f,c,u,p,d,s=[];d="undefined"!=typeof global?global:window,p=d.jQuery;var v=function(){
+// Reference to tinymce needs to be lazily evaluated since tinymce
+// might be loaded through the compressor or other means
+return d.tinymce};p.fn.tinymce=function(o){var e,t,i,l=this,r="";
+// No match then just ignore the call
+if(!l.length)return l;
+// Get editor instance
+if(!o)return v()?v().get(l[0].id):null;l.css("visibility","hidden");// Hide textarea to avoid flicker
+var n=function(){var a=[],c=0;
+// Apply patches to the jQuery object, only once
+u||(m(),u=!0),
+// Create an editor instance for each matched node
+l.each(function(e,t){var n,i=t.id,r=o.oninit;
+// Generate unique id for target element if needed
+i||(t.id=i=v().DOM.uniqueId()),
+// Only init the editor once
+v().get(i)||(
+// Create editor instance and render it
+n=v().createEditor(i,o),a.push(n),n.on("init",function(){var e,t=r;l.css("visibility",""),
+// Run this if the oninit setting is defined
+// this logic will fire the oninit callback ones each
+// matched editor instance is initialized
+r&&++c==a.length&&("string"==typeof t&&(e=-1===t.indexOf(".")?null:v().resolve(t.replace(/\.\w+$/,"")),t=v().resolve(t)),
+// Call the oninit function with the object
+t.apply(e||v(),a))}))}),
+// Render the editor instances in a separate loop since we
+// need to have the full editors array used in the onInit calls
+p.each(a,function(e,t){t.render()})};
+// Load TinyMCE on demand, if we need to
+if(d.tinymce||c||!(e=o.script_url))
+// Delay the init call until tinymce is loaded
+1===c?s.push(n):n();else{c=1,t=e.substring(0,e.lastIndexOf("/")),
+// Check if it's a dev/src version they want to load then
+// make sure that all plugins, themes etc are loaded in source mode as well
+-1!=e.indexOf(".min")&&(r=".min"),
+// Setup tinyMCEPreInit object this will later be used by the TinyMCE
+// core script to locate other resources like CSS files, dialogs etc
+// You can also predefined a tinyMCEPreInit object and then it will use that instead
+d.tinymce=d.tinyMCEPreInit||{base:t,suffix:r},
+// url contains gzip then we assume it's a compressor
+-1!=e.indexOf("gzip")&&(i=o.language||"en",e=e+(/\?/.test(e)?"&":"?")+"js=true&core=true&suffix="+escape(r)+"&themes="+escape(o.theme||"modern")+"&plugins="+escape(o.plugins||"")+"&languages="+(i||""),
+// Check if compressor script is already loaded otherwise setup a basic one
+d.tinyMCE_GZ||(d.tinyMCE_GZ={start:function(){var n=function(e){v().ScriptLoader.markDone(v().baseURI.toAbsolute(e))};
+// Add core languages
+n("langs/"+i+".js"),
+// Add themes with languages
+n("themes/"+o.theme+"/theme"+r+".js"),n("themes/"+o.theme+"/langs/"+i+".js"),
+// Add plugins with languages
+p.each(o.plugins.split(","),function(e,t){t&&(n("plugins/"+t+"/plugin"+r+".js"),n("plugins/"+t+"/langs/"+i+".js"))})},end:function(){}}));var a=document.createElement("script");a.type="text/javascript",a.onload=a.onreadystatechange=function(e){e=e||window.event,2===c||"load"!=e.type&&!/complete|loaded/.test(a.readyState)||(v().dom.Event.domLoaded=1,c=2,
+// Execute callback after mainscript has been loaded and before the initialization occurs
+o.script_loaded&&o.script_loaded(),n(),p.each(s,function(e,t){t()}))},a.src=e,document.body.appendChild(a)}return l},
+// Add :tinymce pseudo selector this will select elements that has been converted into editor instances
+// it's now possible to use things like $('*:tinymce') to get all TinyMCE bound elements.
+p.extend(p.expr[":"],{tinymce:function(e){var t;return!!(e.id&&"tinymce"in d&&(t=v().get(e.id))&&t.editorManager===v())}});
+// This function patches internal jQuery functions so that if
+// you for example remove an div element containing an editor it's
+// automatically destroyed by the TinyMCE API
+var m=function(){
+// Removes any child editor instances by looking for editor wrapper elements
+var r=function(e){
+// If the function is remove
+"remove"===e&&this.each(function(e,t){var n=l(t);n&&n.remove()}),this.find("span.mceEditor,div.mceEditor").each(function(e,t){var n=v().get(t.id.replace(/_parent$/,""));n&&n.remove()})},o=function(i){var e,t=this;
+// Handle set value
+/*jshint eqnull:true */if(null!=i)r.call(t),
+// Saves the contents before get/set value of textarea/div
+t.each(function(e,t){var n;(n=v().get(t.id))&&n.setContent(i)});else if(0<t.length&&(e=v().get(t[0].id)))return e.getContent()},l=function(e){var t=null;return e&&e.id&&d.tinymce&&(t=v().get(e.id)),t},u=function(e){return!!(e&&e.length&&d.tinymce&&e.is(":tinymce"))},s={};
+// Loads or saves contents from/to textarea if the value
+// argument is defined it will set the TinyMCE internal contents
+// Patch some setter/getter functions these will
+// now be able to set/get the contents of editor instances for
+// example $('#editorid').html('Content'); will update the TinyMCE iframe instance
+p.each(["text","html","val"],function(e,t){var a=s[t]=p.fn[t],c="text"===t;p.fn[t]=function(e){var t=this;if(!u(t))return a.apply(t,arguments);if(e!==f)return o.call(t.filter(":tinymce"),e),a.apply(t.not(":tinymce"),arguments),t;// return original set for chaining
+var i="",r=arguments;return(c?t:t.eq(0)).each(function(e,t){var n=l(t);i+=n?c?n.getContent().replace(/<(?:"[^"]*"|'[^']*'|[^'">])*>/g,""):n.getContent({save:!0}):a.apply(p(t),r)}),i}}),
+// Makes it possible to use $('#id').append("content"); to append contents to the TinyMCE editor iframe
+p.each(["append","prepend"],function(e,t){var n=s[t]=p.fn[t],r="prepend"===t;p.fn[t]=function(i){var e=this;return u(e)?i!==f?("string"==typeof i&&e.filter(":tinymce").each(function(e,t){var n=l(t);n&&n.setContent(r?i+n.getContent():n.getContent()+i)}),n.apply(e.not(":tinymce"),arguments),e):void 0:n.apply(e,arguments)}}),
+// Makes sure that the editor instance gets properly destroyed when the parent element is removed
+p.each(["remove","replaceWith","replaceAll","empty"],function(e,t){var n=s[t]=p.fn[t];p.fn[t]=function(){return r.call(this,t),n.apply(this,arguments)}}),s.attr=p.fn.attr,
+// Makes sure that $('#tinymce_id').attr('value') gets the editors current HTML contents
+p.fn.attr=function(e,t){var n=this,i=arguments;if(!e||"value"!==e||!u(n))return s.attr.apply(n,i);if(t!==f)return o.call(n.filter(":tinymce"),t),s.attr.apply(n.not(":tinymce"),i),n;// return original set for chaining
+var r=n[0],a=l(r);return a?a.getContent({save:!0}):s.attr.apply(p(r),i)}}}();

+ 3 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/langs/readme.md

@@ -0,0 +1,3 @@
+This is where language files should be placed.
+
+Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/

+ 410 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/langs/zh_CN.js

@@ -0,0 +1,410 @@
+tinymce.addI18n('zh_CN',{
+"Redo": "恢复",
+"Undo": "撤销",
+"Cut": "剪切",
+"Copy": "复制",
+"Paste": "粘贴",
+"Select all": "全选",
+"New document": "新建文档",
+"Ok": "确定",
+"Cancel": "取消",
+"Visual aids": "网格线",
+"Bold": "粗体",
+"Italic": "斜体",
+"Underline": "下划线",
+"Strikethrough": "删除线",
+"Superscript": "上标",
+"Subscript": "下标",
+"Clear formatting": "清除格式",
+"Align left": "左对齐",
+"Align center": "居中",
+"Align right": "右对齐",
+"Justify": "两端对齐",
+"Bullet list": "符号列表",
+"Numbered list": "数字列表",
+"Decrease indent": "减少缩进",
+"Increase indent": "增加缩进",
+"Close": "关闭",
+"Formats": "格式",
+"Your browser doesn't support direct access to the clipboard. Please use the Ctrl+X\/C\/V keyboard shortcuts instead.": "当前浏览器不支持访问剪贴板,请使用快捷键Ctrl+X/C/V复制粘贴",
+"Headers": "标题",
+"Header 1": "标题1",
+"Header 2": "标题2",
+"Header 3": "标题3",
+"Header 4": "标题4",
+"Header 5": "标题5",
+"Header 6": "标题6",
+"Headings": "标题",
+"Heading 1": "标题1",
+"Heading 2": "标题2",
+"Heading 3": "标题3",
+"Heading 4": "标题4",
+"Heading 5": "标题5",
+"Heading 6": "标题6",
+"Preformatted": "预格式化",
+"Div": "Div区块",
+"Pre": "预格式文本",
+"Code": "代码",
+"Paragraph": "段落",
+"Blockquote": "引用",
+"Inline": "文本",
+"Blocks": "区块",
+"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "当前为纯文本粘贴模式,再次点击可以回到普通粘贴模式。",
+"Fonts": "字体",
+"Font Sizes": "字号",
+"Class": "Class",
+"Browse for an image": "浏览图像",
+"OR": "或",
+"Drop an image here": "拖放一张图片文件至此",
+"Upload": "上传",
+"Block": "块",
+"Align": "对齐",
+"Default": "默认",
+"Circle": "空心圆",
+"Disc": "实心圆",
+"Square": "方块",
+"Lower Alpha": "小写英文字母",
+"Lower Greek": "小写希腊字母",
+"Lower Roman": "小写罗马字母",
+"Upper Alpha": "大写英文字母",
+"Upper Roman": "大写罗马字母",
+"Anchor...": "锚点...",
+"Name": "名称",
+"Id": "id",
+"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "id应该以字母开头,后跟字母、数字、横线、点、冒号或下划线。",
+"You have unsaved changes are you sure you want to navigate away?": "你对文档的修改尚未保存,确定离开吗?",
+"Restore last draft": "恢复上次的草稿",
+"Special characters...": "特殊字符...",
+"Source code": "HTML源码",
+"Insert\/Edit code sample": "插入/编辑代码示例",
+"Language": "语言",
+"Code sample...": "代码示例...",
+"Color Picker": "选取颜色",
+"R": "R",
+"G": "G",
+"B": "B",
+"Left to right": "从左到右",
+"Right to left": "从右到左",
+"Emoticons...": "表情符号...",
+"Metadata and Document Properties": "元数据和文档属性",
+"Title": "标题",
+"Keywords": "关键词",
+"Description": "描述",
+"Robots": "机器人",
+"Author": "作者",
+"Encoding": "编码",
+"Fullscreen": "全屏",
+"Action": "操作",
+"Shortcut": "快捷键",
+"Help": "帮助",
+"Address": "地址",
+"Focus to menubar": "移动焦点到菜单栏",
+"Focus to toolbar": "移动焦点到工具栏",
+"Focus to element path": "移动焦点到元素路径",
+"Focus to contextual toolbar": "移动焦点到上下文菜单",
+"Insert link (if link plugin activated)": "插入链接 (如果链接插件已激活)",
+"Save (if save plugin activated)": "保存(如果保存插件已激活)",
+"Find (if searchreplace plugin activated)": "查找(如果查找替换插件已激活)",
+"Plugins installed ({0}):": "已安装插件 ({0}):",
+"Premium plugins:": "优秀插件:",
+"Learn more...": "了解更多...",
+"You are using {0}": "你正在使用 {0}",
+"Plugins": "插件",
+"Handy Shortcuts": "快捷键",
+"Horizontal line": "水平分割线",
+"Insert\/edit image": "插入/编辑图片",
+"Image description": "图片描述",
+"Source": "地址",
+"Dimensions": "大小",
+"Constrain proportions": "保持宽高比",
+"General": "常规",
+"Advanced": "高级",
+"Style": "样式",
+"Vertical space": "垂直边距",
+"Horizontal space": "水平边距",
+"Border": "边框",
+"Insert image": "插入图片",
+"Image...": "图片...",
+"Image list": "图片列表",
+"Rotate counterclockwise": "逆时针旋转",
+"Rotate clockwise": "顺时针旋转",
+"Flip vertically": "垂直翻转",
+"Flip horizontally": "水平翻转",
+"Edit image": "编辑图片",
+"Image options": "图片选项",
+"Zoom in": "放大",
+"Zoom out": "缩小",
+"Crop": "裁剪",
+"Resize": "调整大小",
+"Orientation": "方向",
+"Brightness": "亮度",
+"Sharpen": "锐化",
+"Contrast": "对比度",
+"Color levels": "色阶",
+"Gamma": "伽马值",
+"Invert": "反转",
+"Apply": "应用",
+"Back": "后退",
+"Insert date\/time": "插入日期/时间",
+"Date\/time": "日期/时间",
+"Insert\/Edit Link": "插入/编辑链接",
+"Insert\/edit link": "插入/编辑链接",
+"Text to display": "显示文字",
+"Url": "地址",
+"Open link in...": "链接打开方式...",
+"Current window": "当前窗口打开",
+"None": "在当前窗口/框架打开",
+"New window": "在新窗口打开",
+"Remove link": "删除链接",
+"Anchors": "锚点",
+"Link...": "链接...",
+"Paste or type a link": "粘贴或输入链接",
+"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "你所填写的URL地址为邮件地址,需要加上mailto:前缀吗?",
+"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "你所填写的URL地址属于外部链接,需要加上http://:前缀吗?",
+"Link list": "链接列表",
+"Insert video": "插入视频",
+"Insert\/edit video": "插入/编辑视频",
+"Insert\/edit media": "插入/编辑媒体",
+"Alternative source": "替代资源",
+"Alternative image URL": "资源备用地址",
+"Media poster (Image URL)": "封面(图片地址)",
+"Paste your embed code below:": "将内嵌代码粘贴在下面:",
+"Embed": "内嵌",
+"Media...": "多媒体...",
+"Nonbreaking space": "不间断空格",
+"Page break": "分页符",
+"Paste as text": "粘贴为文本",
+"Preview": "预览",
+"Print...": "打印...",
+"Save": "保存",
+"Find": "查找",
+"Replace with": "替换为",
+"Replace": "替换",
+"Replace all": "替换全部",
+"Previous": "上一个",
+"Next": "下一个",
+"Find and replace...": "查找并替换...",
+"Could not find the specified string.": "未找到搜索内容。",
+"Match case": "区分大小写",
+"Find whole words only": "全单词匹配",
+"Spell check": "拼写检查",
+"Ignore": "忽略",
+"Ignore all": "忽略全部",
+"Finish": "完成",
+"Add to Dictionary": "添加到字典",
+"Insert table": "插入表格",
+"Table properties": "表格属性",
+"Delete table": "删除表格",
+"Cell": "单元格",
+"Row": "行",
+"Column": "列",
+"Cell properties": "单元格属性",
+"Merge cells": "合并单元格",
+"Split cell": "拆分单元格",
+"Insert row before": "在上方插入",
+"Insert row after": "在下方插入",
+"Delete row": "删除行",
+"Row properties": "行属性",
+"Cut row": "剪切行",
+"Copy row": "复制行",
+"Paste row before": "粘贴到上方",
+"Paste row after": "粘贴到下方",
+"Insert column before": "在左侧插入",
+"Insert column after": "在右侧插入",
+"Delete column": "删除列",
+"Cols": "列",
+"Rows": "行",
+"Width": "宽",
+"Height": "高",
+"Cell spacing": "单元格外间距",
+"Cell padding": "单元格内边距",
+"Show caption": "显示标题",
+"Left": "左对齐",
+"Center": "居中",
+"Right": "右对齐",
+"Cell type": "单元格类型",
+"Scope": "范围",
+"Alignment": "对齐方式",
+"H Align": "水平对齐",
+"V Align": "垂直对齐",
+"Top": "顶部对齐",
+"Middle": "垂直居中",
+"Bottom": "底部对齐",
+"Header cell": "表头单元格",
+"Row group": "行组",
+"Column group": "列组",
+"Row type": "行类型",
+"Header": "表头",
+"Body": "表体",
+"Footer": "表尾",
+"Border color": "边框颜色",
+"Insert template...": "插入模板...",
+"Templates": "模板",
+"Template": "模板",
+"Text color": "文字颜色",
+"Background color": "背景色",
+"Custom...": "自定义...",
+"Custom color": "自定义颜色",
+"No color": "无",
+"Remove color": "删除颜色",
+"Table of Contents": "目录",
+"Show blocks": "显示区块边框",
+"Show invisible characters": "显示不可见字符",
+"Word count": "字数统计",
+"Words: {0}": "字数:{0}",
+"{0} words": "{0} 个字",
+"File": "文件",
+"Edit": "编辑",
+"Insert": "插入",
+"View": "查看",
+"Format": "格式",
+"Table": "表格",
+"Tools": "工具",
+"Powered by {0}": "Powered by {0}",
+"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "在编辑区按ALT+F9打开菜单,按ALT+F10打开工具栏,按ALT+0查看帮助",
+"Image title": "图片标题",
+"Border width": "边框宽度",
+"Border style": "边框样式",
+"Error": "错误",
+"Warn": "警告",
+"Valid": "有效",
+"To open the popup, press Shift+Enter": "此快捷为软回车(插入<br>)",
+"Rich Text Area. Press ALT-0 for help.": "编辑区. 按Alt+0键打开帮助",
+"System Font": "默认字体",
+"Failed to upload image: {0}": "图片上传失败: {0}",
+"Failed to load plugin: {0} from url {1}": "插件加载失败: {0} - {1}",
+"Failed to load plugin url: {0}": "插件加载失败: {0}",
+"Failed to initialize plugin: {0}": "插件初始化失败: {0}",
+"example": "示例",
+"Search": "查找",
+"All": "全部",
+"Currency": "货币",
+"Text": "文本",
+"Quotations": "引用",
+"Mathematical": "数学运算符",
+"Extended Latin": "拉丁语扩充",
+"Symbols": "符号",
+"Arrows": "箭头",
+"User Defined": "自定义",
+"dollar sign": "美元",
+"currency sign": "货币",
+"euro-currency sign": "欧元",
+"colon sign": "冒号",
+"cruzeiro sign": "克鲁赛罗币",
+"french franc sign": "法郎",
+"lira sign": "里拉",
+"mill sign": "密尔",
+"naira sign": "奈拉",
+"peseta sign": "比塞塔",
+"rupee sign": "卢比",
+"won sign": "韩元",
+"new sheqel sign": "新谢克尔",
+"dong sign": "越南盾",
+"kip sign": "老挝基普",
+"tugrik sign": "图格里克",
+"drachma sign": "德拉克马",
+"german penny symbol": "德国便士",
+"peso sign": "比索",
+"guarani sign": "瓜拉尼",
+"austral sign": "澳元",
+"hryvnia sign": "格里夫尼亚",
+"cedi sign": "塞地",
+"livre tournois sign": "里弗弗尔",
+"spesmilo sign": "一千spesoj的货币符号,该货币未使用",
+"tenge sign": "坚戈",
+"indian rupee sign": "印度卢比",
+"turkish lira sign": "土耳其里拉",
+"nordic mark sign": "北欧马克",
+"manat sign": "马纳特",
+"ruble sign": "卢布",
+"yen character": "日元",
+"yuan character": "人民币元",
+"yuan character, in hong kong and taiwan": "元的繁体字",
+"yen\/yuan character variant one": "元(大写)",
+"Loading emoticons...": "正在加载表情文字...",
+"Could not load emoticons": "不能加载表情文字",
+"People": "人类",
+"Animals and Nature": "动物和自然",
+"Food and Drink": "食物和饮品",
+"Activity": "活动",
+"Travel and Places": "旅游和地点",
+"Objects": "物件",
+"Flags": "旗帜",
+"Characters": "字数",
+"Characters (no spaces)": "字数(不含空格)",
+"Error: Form submit field collision.": "错误: 表单提交字段冲突.",
+"Error: No form element found.": "错误: 未找到可用的form.",
+"Update": "更新",
+"Color swatch": "颜色样本",
+"Turquoise": "青绿",
+"Green": "绿色",
+"Blue": "蓝色",
+"Purple": "紫色",
+"Navy Blue": "海军蓝",
+"Dark Turquoise": "深蓝绿色",
+"Dark Green": "暗绿",
+"Medium Blue": "中蓝",
+"Medium Purple": "中紫",
+"Midnight Blue": "深蓝",
+"Yellow": "黄色",
+"Orange": "橙色",
+"Red": "红色",
+"Light Gray": "浅灰",
+"Gray": "灰色",
+"Dark Yellow": "暗黄",
+"Dark Orange": "暗橙",
+"Dark Red": "暗红",
+"Medium Gray": "中灰",
+"Dark Gray": "深灰",
+"Black": "黑色",
+"White": "白色",
+"Switch to or from fullscreen mode": "切换全屏模式",
+"Open help dialog": "打开帮助对话框",
+"history": "历史",
+"styles": "样式",
+"formatting": "格式化",
+"alignment": "对齐",
+"indentation": "缩进",
+"permanent pen": "记号笔",
+"comments": "注释",
+"Anchor": "锚点",
+"Special character": "特殊字符",
+"Code sample": "代码示例",
+"Color": "颜色",
+"Emoticons": "表情",
+"Document properties": "文档属性",
+"Image": "图片",
+"Insert link": "插入链接",
+"Target": "目标",
+"Link": "链接",
+"Poster": "封面",
+"Media": "音视频",
+"Print": "打印",
+"Prev": "上一个",
+"Find and replace": "查找并替换",
+"Whole words": "全字匹配",
+"Spellcheck": "拼写检查",
+"Caption": "标题",
+"Insert template": "插入模板",
+//以下为补充汉化内容 by 莫若卿
+"Code view": "代码区域",
+"Select...": "选择...",
+"Format Painter": "格式刷",
+"No templates defined.": "无内置模板",
+"Special character...": "特殊字符...",
+"Open link": "打开链接",
+"None": "无",
+"Count": "统计",
+"Document": "整个文档",
+"Selection": "选取部分",
+"Words": "字词数",
+"{0} characters": "{0} 个字符",
+"Alternative source URL": "替代资源地址",
+"Alternative description": "替代说明文字",
+"Accessibility": "可访问性",
+"Image is decorative": "仅用于装饰",
+//帮助窗口内的文字
+"Version": "版本",
+"Keyboard Navigation": "键盘导航",
+"Open popup menu for split buttons": "该组合键的作用是软回车(插入br)",
+});

+ 504 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/license.txt

@@ -0,0 +1,504 @@
+      GNU LESSER GENERAL PUBLIC LICENSE
+           Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+          Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+      GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+  
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+          NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+         END OF TERMS AND CONDITIONS
+
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
+
+

Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/advlist/plugin.min.js


+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/anchor/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=function(e,t){return"A"===t.tagName&&""===e.dom.getAttrib(t,"href")},r=function(e,t){return/^[A-Za-z][A-Za-z0-9\-:._]*$/.test(t)?(o=t,r=(n=e).selection.getNode(),a(n,r)?(r.removeAttribute("name"),r.id=o,n.undoManager.add()):(n.focus(),n.selection.collapse(!0),n.insertContent(n.dom.createHTML("a",{id:o}))),!0):(e.windowManager.alert("Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores."),!1);var n,o,r},i=function(t){var e,n,o=(n=(e=t).selection.getNode(),a(e,n)?n.getAttribute("id")||n.getAttribute("name"):"");t.windowManager.open({title:"Anchor",size:"normal",body:{type:"panel",items:[{name:"id",type:"input",label:"ID",placeholder:"example"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{id:o},onSubmit:function(e){r(t,e.getData().id)&&e.close()}})},c=function(o){return function(e){for(var t=0;t<e.length;t++)(n=e[t]).attr("href")||!n.attr("id")&&!n.attr("name")||n.firstChild||e[t].attr("contenteditable",o);var n}};!function t(){e.add("anchor",function(e){var t,n,o;(t=e).on("PreInit",function(){t.parser.addNodeFilter("a",c("false")),t.serializer.addNodeFilter("a",c(null))}),(n=e).addCommand("mceAnchor",function(){i(n)}),(o=e).ui.registry.addToggleButton("anchor",{icon:"bookmark",tooltip:"Anchor",onAction:function(){return o.execCommand("mceAnchor")},onSetup:function(e){return o.selection.selectorChangedWithUnbind("a:not([href])",e.setActive).unbind}}),o.ui.registry.addMenuItem("anchor",{icon:"bookmark",text:"Anchor...",onAction:function(){return o.execCommand("mceAnchor")}})})}()}();

Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/autolink/plugin.min.js


+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/autoresize/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),h=tinymce.util.Tools.resolve("tinymce.Env"),r=tinymce.util.Tools.resolve("tinymce.util.Delay"),v=function(e){return e.getParam("min_height",e.getElement().offsetHeight,"number")},s=function(e,t,n,i,o){r.setEditorTimeout(e,function(){b(e,t),n--?s(e,t,n,i,o):o&&o()},i)},y=function(e,t){var n=e.getBody();n&&(n.style.overflowY=t?"":"hidden",t||(n.scrollTop=0))},p=function(e,t,n,i){var o=parseInt(e.getStyle(t,n,i),10);return isNaN(o)?0:o},b=function(e,t){var n,i,o,r=e.dom,a=e.getDoc();if(a)if((s=e).plugins.fullscreen&&s.plugins.fullscreen.isFullscreen())y(e,!0);else{var s,u=a.documentElement,g=e.getParam("autoresize_bottom_margin",50,"number");i=v(e);var l=p(r,u,"margin-top",!0),f=p(r,u,"margin-bottom",!0);(o=u.offsetHeight+l+f+g)<0&&(o=0);var c=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight;o+c>v(e)&&(i=o+c);var m=e.getParam("max_height",0,"number");if(m&&m<i?(i=m,y(e,!0)):y(e,!1),i!==t.get()){if(n=i-t.get(),r.setStyle(e.getContainer(),"height",i+"px"),t.set(i),e.fire("ResizeEditor"),h.browser.isSafari()&&h.mac){var d=e.getWin();d.scrollTo(d.pageXOffset,d.pageYOffset)}e.hasFocus()&&e.selection.scrollIntoView(e.selection.getNode()),h.webkit&&n<0&&b(e,t)}}};!function t(){e.add("autoresize",function(e){if(e.settings.hasOwnProperty("resize")||(e.settings.resize=!1),!e.inline){var t=(a=0,{get:function(){return a},set:function(e){a=e}});r=t,(o=e).addCommand("mceAutoResize",function(){b(o,r)}),i=t,(n=e).on("init",function(){var e=n.getParam("autoresize_overflow_padding",1,"number"),t=n.dom;t.setStyles(n.getDoc().documentElement,{height:"auto"}),t.setStyles(n.getBody(),{paddingLeft:e,paddingRight:e,"min-height":0})}),n.on("NodeChange SetContent keyup FullscreenStateChanged ResizeContent",function(){b(n,i)}),n.getParam("autoresize_on_init",!0,"boolean")&&n.on("init",function(){s(n,i,20,100,function(){s(n,i,5,1e3)})})}var n,i,o,r,a})}()}();

Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/autosave/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/bbcode/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/charmap/plugin.min.js


+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/code/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),o=function(o){var e=o.getContent({source_view:!0});o.windowManager.open({title:"Source Code",size:"large",body:{type:"panel",items:[{type:"textarea",name:"code"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{code:e},onSubmit:function(e){var t,n;t=o,n=e.getData().code,t.focus(),t.undoManager.transact(function(){t.setContent(n)}),t.selection.setCursorLocation(),t.nodeChanged(),e.close()}})};!function t(){e.add("code",function(e){var t,n;return(t=e).addCommand("mceCodeEditor",function(){o(t)}),(n=e).ui.registry.addButton("code",{icon:"sourcecode",tooltip:"Source code",onAction:function(){return o(n)}}),n.ui.registry.addMenuItem("code",{icon:"sourcecode",text:"Source code",onAction:function(){return o(n)}}),{}})}()}();

Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/codesample/plugin.min.js


+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/colorpicker/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(o){"use strict";var i=tinymce.util.Tools.resolve("tinymce.PluginManager");!function n(){i.add("colorpicker",function(){o.console.warn("Color picker plugin is now built in to the core editor, please remove it from your editor configuration")})}()}(window);

+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/contextmenu/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(n){"use strict";var o=tinymce.util.Tools.resolve("tinymce.PluginManager");!function e(){o.add("contextmenu",function(){n.console.warn("Context menu plugin is now built in to the core editor, please remove it from your editor configuration")})}()}(window);

Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/directionality/plugin.min.js


+ 9015 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/emoticons/js/emojis.js

@@ -0,0 +1,9015 @@
+// NOTE: Source: npm package: emojilib, file:emojis.json
+window.tinymce.Resource.add("tinymce.plugins.emoticons", {
+  grinning: {
+    keywords: [ "face", "smile", "happy", "joy", ":D", "grin" ],
+    "char": "\ud83d\ude00",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  grimacing: {
+    keywords: [ "face", "grimace", "teeth" ],
+    "char": "\ud83d\ude2c",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  grin: {
+    keywords: [ "face", "happy", "smile", "joy", "kawaii" ],
+    "char": "\ud83d\ude01",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  joy: {
+    keywords: [ "face", "cry", "tears", "weep", "happy", "happytears", "haha" ],
+    "char": "\ud83d\ude02",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  rofl: {
+    keywords: [ "face", "rolling", "floor", "laughing", "lol", "haha" ],
+    "char": "\ud83e\udd23",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  smiley: {
+    keywords: [ "face", "happy", "joy", "haha", ":D", ":)", "smile", "funny" ],
+    "char": "\ud83d\ude03",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  smile: {
+    keywords: [ "face", "happy", "joy", "funny", "haha", "laugh", "like", ":D", ":)" ],
+    "char": "\ud83d\ude04",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  sweat_smile: {
+    keywords: [ "face", "hot", "happy", "laugh", "sweat", "smile", "relief" ],
+    "char": "\ud83d\ude05",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  laughing: {
+    keywords: [ "happy", "joy", "lol", "satisfied", "haha", "face", "glad", "XD", "laugh" ],
+    "char": "\ud83d\ude06",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  innocent: {
+    keywords: [ "face", "angel", "heaven", "halo" ],
+    "char": "\ud83d\ude07",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  wink: {
+    keywords: [ "face", "happy", "mischievous", "secret", ";)", "smile", "eye" ],
+    "char": "\ud83d\ude09",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  blush: {
+    keywords: [ "face", "smile", "happy", "flushed", "crush", "embarrassed", "shy", "joy" ],
+    "char": "\ud83d\ude0a",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  slightly_smiling_face: {
+    keywords: [ "face", "smile" ],
+    "char": "\ud83d\ude42",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  upside_down_face: {
+    keywords: [ "face", "flipped", "silly", "smile" ],
+    "char": "\ud83d\ude43",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  relaxed: {
+    keywords: [ "face", "blush", "massage", "happiness" ],
+    "char": "\u263a\ufe0f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  yum: {
+    keywords: [ "happy", "joy", "tongue", "smile", "face", "silly", "yummy", "nom", "delicious", "savouring" ],
+    "char": "\ud83d\ude0b",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  relieved: {
+    keywords: [ "face", "relaxed", "phew", "massage", "happiness" ],
+    "char": "\ud83d\ude0c",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  heart_eyes: {
+    keywords: [ "face", "love", "like", "affection", "valentines", "infatuation", "crush", "heart" ],
+    "char": "\ud83d\ude0d",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  kissing_heart: {
+    keywords: [ "face", "love", "like", "affection", "valentines", "infatuation", "kiss" ],
+    "char": "\ud83d\ude18",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  kissing: {
+    keywords: [ "love", "like", "face", "3", "valentines", "infatuation", "kiss" ],
+    "char": "\ud83d\ude17",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  kissing_smiling_eyes: {
+    keywords: [ "face", "affection", "valentines", "infatuation", "kiss" ],
+    "char": "\ud83d\ude19",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  kissing_closed_eyes: {
+    keywords: [ "face", "love", "like", "affection", "valentines", "infatuation", "kiss" ],
+    "char": "\ud83d\ude1a",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  stuck_out_tongue_winking_eye: {
+    keywords: [ "face", "prank", "childish", "playful", "mischievous", "smile", "wink", "tongue" ],
+    "char": "\ud83d\ude1c",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  zany: {
+    keywords: [ "face", "goofy", "crazy" ],
+    "char": "\ud83e\udd2a",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  raised_eyebrow: {
+    keywords: [ "face", "distrust", "scepticism", "disapproval", "disbelief", "surprise" ],
+    "char": "\ud83e\udd28",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  monocle: {
+    keywords: [ "face", "stuffy", "wealthy" ],
+    "char": "\ud83e\uddd0",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  stuck_out_tongue_closed_eyes: {
+    keywords: [ "face", "prank", "playful", "mischievous", "smile", "tongue" ],
+    "char": "\ud83d\ude1d",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  stuck_out_tongue: {
+    keywords: [ "face", "prank", "childish", "playful", "mischievous", "smile", "tongue" ],
+    "char": "\ud83d\ude1b",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  money_mouth_face: {
+    keywords: [ "face", "rich", "dollar", "money" ],
+    "char": "\ud83e\udd11",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  nerd_face: {
+    keywords: [ "face", "nerdy", "geek", "dork" ],
+    "char": "\ud83e\udd13",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  sunglasses: {
+    keywords: [ "face", "cool", "smile", "summer", "beach", "sunglass" ],
+    "char": "\ud83d\ude0e",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  star_struck: {
+    keywords: [ "face", "smile", "starry", "eyes", "grinning" ],
+    "char": "\ud83e\udd29",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  clown_face: {
+    keywords: [ "face" ],
+    "char": "\ud83e\udd21",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  cowboy_hat_face: {
+    keywords: [ "face", "cowgirl", "hat" ],
+    "char": "\ud83e\udd20",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  hugs: {
+    keywords: [ "face", "smile", "hug" ],
+    "char": "\ud83e\udd17",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  smirk: {
+    keywords: [ "face", "smile", "mean", "prank", "smug", "sarcasm" ],
+    "char": "\ud83d\ude0f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  no_mouth: {
+    keywords: [ "face", "hellokitty" ],
+    "char": "\ud83d\ude36",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  neutral_face: {
+    keywords: [ "indifference", "meh", ":|", "neutral" ],
+    "char": "\ud83d\ude10",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  expressionless: {
+    keywords: [ "face", "indifferent", "-_-", "meh", "deadpan" ],
+    "char": "\ud83d\ude11",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  unamused: {
+    keywords: [ "indifference", "bored", "straight face", "serious", "sarcasm", "unimpressed", "skeptical", "dubious", "side_eye" ],
+    "char": "\ud83d\ude12",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  roll_eyes: {
+    keywords: [ "face", "eyeroll", "frustrated" ],
+    "char": "\ud83d\ude44",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  thinking: {
+    keywords: [ "face", "hmmm", "think", "consider" ],
+    "char": "\ud83e\udd14",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  lying_face: {
+    keywords: [ "face", "lie", "pinocchio" ],
+    "char": "\ud83e\udd25",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  hand_over_mouth: {
+    keywords: [ "face", "whoops", "shock", "surprise" ],
+    "char": "\ud83e\udd2d",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  shushing: {
+    keywords: [ "face", "quiet", "shhh" ],
+    "char": "\ud83e\udd2b",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  symbols_over_mouth: {
+    keywords: [ "face", "swearing", "cursing", "cussing", "profanity", "expletive" ],
+    "char": "\ud83e\udd2c",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  exploding_head: {
+    keywords: [ "face", "shocked", "mind", "blown" ],
+    "char": "\ud83e\udd2f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  flushed: {
+    keywords: [ "face", "blush", "shy", "flattered" ],
+    "char": "\ud83d\ude33",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  disappointed: {
+    keywords: [ "face", "sad", "upset", "depressed", ":(" ],
+    "char": "\ud83d\ude1e",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  worried: {
+    keywords: [ "face", "concern", "nervous", ":(" ],
+    "char": "\ud83d\ude1f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  angry: {
+    keywords: [ "mad", "face", "annoyed", "frustrated" ],
+    "char": "\ud83d\ude20",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  rage: {
+    keywords: [ "angry", "mad", "hate", "despise" ],
+    "char": "\ud83d\ude21",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  pensive: {
+    keywords: [ "face", "sad", "depressed", "upset" ],
+    "char": "\ud83d\ude14",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  confused: {
+    keywords: [ "face", "indifference", "huh", "weird", "hmmm", ":/" ],
+    "char": "\ud83d\ude15",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  slightly_frowning_face: {
+    keywords: [ "face", "frowning", "disappointed", "sad", "upset" ],
+    "char": "\ud83d\ude41",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  frowning_face: {
+    keywords: [ "face", "sad", "upset", "frown" ],
+    "char": "\u2639",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  persevere: {
+    keywords: [ "face", "sick", "no", "upset", "oops" ],
+    "char": "\ud83d\ude23",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  confounded: {
+    keywords: [ "face", "confused", "sick", "unwell", "oops", ":S" ],
+    "char": "\ud83d\ude16",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  tired_face: {
+    keywords: [ "sick", "whine", "upset", "frustrated" ],
+    "char": "\ud83d\ude2b",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  weary: {
+    keywords: [ "face", "tired", "sleepy", "sad", "frustrated", "upset" ],
+    "char": "\ud83d\ude29",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  triumph: {
+    keywords: [ "face", "gas", "phew", "proud", "pride" ],
+    "char": "\ud83d\ude24",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  open_mouth: {
+    keywords: [ "face", "surprise", "impressed", "wow", "whoa", ":O" ],
+    "char": "\ud83d\ude2e",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  scream: {
+    keywords: [ "face", "munch", "scared", "omg" ],
+    "char": "\ud83d\ude31",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  fearful: {
+    keywords: [ "face", "scared", "terrified", "nervous", "oops", "huh" ],
+    "char": "\ud83d\ude28",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  cold_sweat: {
+    keywords: [ "face", "nervous", "sweat" ],
+    "char": "\ud83d\ude30",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  hushed: {
+    keywords: [ "face", "woo", "shh" ],
+    "char": "\ud83d\ude2f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  frowning: {
+    keywords: [ "face", "aw", "what" ],
+    "char": "\ud83d\ude26",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  anguished: {
+    keywords: [ "face", "stunned", "nervous" ],
+    "char": "\ud83d\ude27",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  cry: {
+    keywords: [ "face", "tears", "sad", "depressed", "upset", ":'(" ],
+    "char": "\ud83d\ude22",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  disappointed_relieved: {
+    keywords: [ "face", "phew", "sweat", "nervous" ],
+    "char": "\ud83d\ude25",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  drooling_face: {
+    keywords: [ "face" ],
+    "char": "\ud83e\udd24",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  sleepy: {
+    keywords: [ "face", "tired", "rest", "nap" ],
+    "char": "\ud83d\ude2a",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  sweat: {
+    keywords: [ "face", "hot", "sad", "tired", "exercise" ],
+    "char": "\ud83d\ude13",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  sob: {
+    keywords: [ "face", "cry", "tears", "sad", "upset", "depressed" ],
+    "char": "\ud83d\ude2d",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  dizzy_face: {
+    keywords: [ "spent", "unconscious", "xox", "dizzy" ],
+    "char": "\ud83d\ude35",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  astonished: {
+    keywords: [ "face", "xox", "surprised", "poisoned" ],
+    "char": "\ud83d\ude32",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  zipper_mouth_face: {
+    keywords: [ "face", "sealed", "zipper", "secret" ],
+    "char": "\ud83e\udd10",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  nauseated_face: {
+    keywords: [ "face", "vomit", "gross", "green", "sick", "throw up", "ill" ],
+    "char": "\ud83e\udd22",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  sneezing_face: {
+    keywords: [ "face", "gesundheit", "sneeze", "sick", "allergy" ],
+    "char": "\ud83e\udd27",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  vomiting: {
+    keywords: [ "face", "sick" ],
+    "char": "\ud83e\udd2e",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  mask: {
+    keywords: [ "face", "sick", "ill", "disease" ],
+    "char": "\ud83d\ude37",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  face_with_thermometer: {
+    keywords: [ "sick", "temperature", "thermometer", "cold", "fever" ],
+    "char": "\ud83e\udd12",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  face_with_head_bandage: {
+    keywords: [ "injured", "clumsy", "bandage", "hurt" ],
+    "char": "\ud83e\udd15",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  sleeping: {
+    keywords: [ "face", "tired", "sleepy", "night", "zzz" ],
+    "char": "\ud83d\ude34",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  zzz: {
+    keywords: [ "sleepy", "tired", "dream" ],
+    "char": "\ud83d\udca4",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  poop: {
+    keywords: [ "hankey", "shitface", "fail", "turd", "shit" ],
+    "char": "\ud83d\udca9",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  smiling_imp: {
+    keywords: [ "devil", "horns" ],
+    "char": "\ud83d\ude08",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  imp: {
+    keywords: [ "devil", "angry", "horns" ],
+    "char": "\ud83d\udc7f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  japanese_ogre: {
+    keywords: [ "monster", "red", "mask", "halloween", "scary", "creepy", "devil", "demon", "japanese", "ogre" ],
+    "char": "\ud83d\udc79",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  japanese_goblin: {
+    keywords: [ "red", "evil", "mask", "monster", "scary", "creepy", "japanese", "goblin" ],
+    "char": "\ud83d\udc7a",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  skull: {
+    keywords: [ "dead", "skeleton", "creepy", "death" ],
+    "char": "\ud83d\udc80",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  ghost: {
+    keywords: [ "halloween", "spooky", "scary" ],
+    "char": "\ud83d\udc7b",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  alien: {
+    keywords: [ "UFO", "paul", "weird", "outer_space" ],
+    "char": "\ud83d\udc7d",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  robot: {
+    keywords: [ "computer", "machine", "bot" ],
+    "char": "\ud83e\udd16",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  smiley_cat: {
+    keywords: [ "animal", "cats", "happy", "smile" ],
+    "char": "\ud83d\ude3a",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  smile_cat: {
+    keywords: [ "animal", "cats", "smile" ],
+    "char": "\ud83d\ude38",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  joy_cat: {
+    keywords: [ "animal", "cats", "haha", "happy", "tears" ],
+    "char": "\ud83d\ude39",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  heart_eyes_cat: {
+    keywords: [ "animal", "love", "like", "affection", "cats", "valentines", "heart" ],
+    "char": "\ud83d\ude3b",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  smirk_cat: {
+    keywords: [ "animal", "cats", "smirk" ],
+    "char": "\ud83d\ude3c",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  kissing_cat: {
+    keywords: [ "animal", "cats", "kiss" ],
+    "char": "\ud83d\ude3d",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  scream_cat: {
+    keywords: [ "animal", "cats", "munch", "scared", "scream" ],
+    "char": "\ud83d\ude40",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  crying_cat_face: {
+    keywords: [ "animal", "tears", "weep", "sad", "cats", "upset", "cry" ],
+    "char": "\ud83d\ude3f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  pouting_cat: {
+    keywords: [ "animal", "cats" ],
+    "char": "\ud83d\ude3e",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  palms_up: {
+    keywords: [ "hands", "gesture", "cupped", "prayer" ],
+    "char": "\ud83e\udd32",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  raised_hands: {
+    keywords: [ "gesture", "hooray", "yea", "celebration", "hands" ],
+    "char": "\ud83d\ude4c",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  clap: {
+    keywords: [ "hands", "praise", "applause", "congrats", "yay" ],
+    "char": "\ud83d\udc4f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  wave: {
+    keywords: [ "hands", "gesture", "goodbye", "solong", "farewell", "hello", "hi", "palm" ],
+    "char": "\ud83d\udc4b",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  call_me_hand: {
+    keywords: [ "hands", "gesture" ],
+    "char": "\ud83e\udd19",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  "+1": {
+    keywords: [ "thumbsup", "yes", "awesome", "good", "agree", "accept", "cool", "hand", "like" ],
+    "char": "\ud83d\udc4d",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  "-1": {
+    keywords: [ "thumbsdown", "no", "dislike", "hand" ],
+    "char": "\ud83d\udc4e",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  facepunch: {
+    keywords: [ "angry", "violence", "fist", "hit", "attack", "hand" ],
+    "char": "\ud83d\udc4a",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  fist: {
+    keywords: [ "fingers", "hand", "grasp" ],
+    "char": "\u270a",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  fist_left: {
+    keywords: [ "hand", "fistbump" ],
+    "char": "\ud83e\udd1b",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  fist_right: {
+    keywords: [ "hand", "fistbump" ],
+    "char": "\ud83e\udd1c",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  v: {
+    keywords: [ "fingers", "ohyeah", "hand", "peace", "victory", "two" ],
+    "char": "\u270c",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  ok_hand: {
+    keywords: [ "fingers", "limbs", "perfect", "ok", "okay" ],
+    "char": "\ud83d\udc4c",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  raised_hand: {
+    keywords: [ "fingers", "stop", "highfive", "palm", "ban" ],
+    "char": "\u270b",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  raised_back_of_hand: {
+    keywords: [ "fingers", "raised", "backhand" ],
+    "char": "\ud83e\udd1a",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  open_hands: {
+    keywords: [ "fingers", "butterfly", "hands", "open" ],
+    "char": "\ud83d\udc50",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  muscle: {
+    keywords: [ "arm", "flex", "hand", "summer", "strong", "biceps" ],
+    "char": "\ud83d\udcaa",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  pray: {
+    keywords: [ "please", "hope", "wish", "namaste", "highfive" ],
+    "char": "\ud83d\ude4f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  handshake: {
+    keywords: [ "agreement", "shake" ],
+    "char": "\ud83e\udd1d",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  point_up: {
+    keywords: [ "hand", "fingers", "direction", "up" ],
+    "char": "\u261d",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  point_up_2: {
+    keywords: [ "fingers", "hand", "direction", "up" ],
+    "char": "\ud83d\udc46",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  point_down: {
+    keywords: [ "fingers", "hand", "direction", "down" ],
+    "char": "\ud83d\udc47",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  point_left: {
+    keywords: [ "direction", "fingers", "hand", "left" ],
+    "char": "\ud83d\udc48",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  point_right: {
+    keywords: [ "fingers", "hand", "direction", "right" ],
+    "char": "\ud83d\udc49",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  fu: {
+    keywords: [ "hand", "fingers", "rude", "middle", "flipping" ],
+    "char": "\ud83d\udd95",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  raised_hand_with_fingers_splayed: {
+    keywords: [ "hand", "fingers", "palm" ],
+    "char": "\ud83d\udd90",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  love_you: {
+    keywords: [ "hand", "fingers", "gesture" ],
+    "char": "\ud83e\udd1f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  metal: {
+    keywords: [ "hand", "fingers", "evil_eye", "sign_of_horns", "rock_on" ],
+    "char": "\ud83e\udd18",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  crossed_fingers: {
+    keywords: [ "good", "lucky" ],
+    "char": "\ud83e\udd1e",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  vulcan_salute: {
+    keywords: [ "hand", "fingers", "spock", "star trek" ],
+    "char": "\ud83d\udd96",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  writing_hand: {
+    keywords: [ "lower_left_ballpoint_pen", "stationery", "write", "compose" ],
+    "char": "\u270d",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  selfie: {
+    keywords: [ "camera", "phone" ],
+    "char": "\ud83e\udd33",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  nail_care: {
+    keywords: [ "beauty", "manicure", "finger", "fashion", "nail" ],
+    "char": "\ud83d\udc85",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  lips: {
+    keywords: [ "mouth", "kiss" ],
+    "char": "\ud83d\udc44",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  tongue: {
+    keywords: [ "mouth", "playful" ],
+    "char": "\ud83d\udc45",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  ear: {
+    keywords: [ "face", "hear", "sound", "listen" ],
+    "char": "\ud83d\udc42",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  nose: {
+    keywords: [ "smell", "sniff" ],
+    "char": "\ud83d\udc43",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  eye: {
+    keywords: [ "face", "look", "see", "watch", "stare" ],
+    "char": "\ud83d\udc41",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  eyes: {
+    keywords: [ "look", "watch", "stalk", "peek", "see" ],
+    "char": "\ud83d\udc40",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  brain: {
+    keywords: [ "smart", "intelligent" ],
+    "char": "\ud83e\udde0",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  bust_in_silhouette: {
+    keywords: [ "user", "person", "human" ],
+    "char": "\ud83d\udc64",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  busts_in_silhouette: {
+    keywords: [ "user", "person", "human", "group", "team" ],
+    "char": "\ud83d\udc65",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  speaking_head: {
+    keywords: [ "user", "person", "human", "sing", "say", "talk" ],
+    "char": "\ud83d\udde3",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  baby: {
+    keywords: [ "child", "boy", "girl", "toddler" ],
+    "char": "\ud83d\udc76",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  child: {
+    keywords: [ "gender-neutral", "young" ],
+    "char": "\ud83e\uddd2",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  boy: {
+    keywords: [ "man", "male", "guy", "teenager" ],
+    "char": "\ud83d\udc66",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  girl: {
+    keywords: [ "female", "woman", "teenager" ],
+    "char": "\ud83d\udc67",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  adult: {
+    keywords: [ "gender-neutral", "person" ],
+    "char": "\ud83e\uddd1",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man: {
+    keywords: [ "mustache", "father", "dad", "guy", "classy", "sir", "moustache" ],
+    "char": "\ud83d\udc68",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman: {
+    keywords: [ "female", "girls", "lady" ],
+    "char": "\ud83d\udc69",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  blonde_woman: {
+    keywords: [ "woman", "female", "girl", "blonde", "person" ],
+    "char": "\ud83d\udc71\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  blonde_man: {
+    keywords: [ "man", "male", "boy", "blonde", "guy", "person" ],
+    "char": "\ud83d\udc71",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  bearded_person: {
+    keywords: [ "person", "bewhiskered" ],
+    "char": "\ud83e\uddd4",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  older_adult: {
+    keywords: [ "human", "elder", "senior", "gender-neutral" ],
+    "char": "\ud83e\uddd3",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  older_man: {
+    keywords: [ "human", "male", "men", "old", "elder", "senior" ],
+    "char": "\ud83d\udc74",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  older_woman: {
+    keywords: [ "human", "female", "women", "lady", "old", "elder", "senior" ],
+    "char": "\ud83d\udc75",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_with_gua_pi_mao: {
+    keywords: [ "male", "boy", "chinese" ],
+    "char": "\ud83d\udc72",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_with_headscarf: {
+    keywords: [ "female", "hijab", "mantilla", "tichel" ],
+    "char": "\ud83e\uddd5",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_with_turban: {
+    keywords: [ "female", "indian", "hinduism", "arabs", "woman" ],
+    "char": "\ud83d\udc73\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_with_turban: {
+    keywords: [ "male", "indian", "hinduism", "arabs" ],
+    "char": "\ud83d\udc73",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  policewoman: {
+    keywords: [ "woman", "police", "law", "legal", "enforcement", "arrest", "911", "female" ],
+    "char": "\ud83d\udc6e\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  policeman: {
+    keywords: [ "man", "police", "law", "legal", "enforcement", "arrest", "911" ],
+    "char": "\ud83d\udc6e",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  construction_worker_woman: {
+    keywords: [ "female", "human", "wip", "build", "construction", "worker", "labor", "woman" ],
+    "char": "\ud83d\udc77\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  construction_worker_man: {
+    keywords: [ "male", "human", "wip", "guy", "build", "construction", "worker", "labor" ],
+    "char": "\ud83d\udc77",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  guardswoman: {
+    keywords: [ "uk", "gb", "british", "female", "royal", "woman" ],
+    "char": "\ud83d\udc82\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  guardsman: {
+    keywords: [ "uk", "gb", "british", "male", "guy", "royal" ],
+    "char": "\ud83d\udc82",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  female_detective: {
+    keywords: [ "human", "spy", "detective", "female", "woman" ],
+    "char": "\ud83d\udd75\ufe0f\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  male_detective: {
+    keywords: [ "human", "spy", "detective" ],
+    "char": "\ud83d\udd75",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_health_worker: {
+    keywords: [ "doctor", "nurse", "therapist", "healthcare", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\u2695\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_health_worker: {
+    keywords: [ "doctor", "nurse", "therapist", "healthcare", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\u2695\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_farmer: {
+    keywords: [ "rancher", "gardener", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\ud83c\udf3e",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_farmer: {
+    keywords: [ "rancher", "gardener", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\ud83c\udf3e",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_cook: {
+    keywords: [ "chef", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\ud83c\udf73",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_cook: {
+    keywords: [ "chef", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\ud83c\udf73",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_student: {
+    keywords: [ "graduate", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\ud83c\udf93",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_student: {
+    keywords: [ "graduate", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\ud83c\udf93",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_singer: {
+    keywords: [ "rockstar", "entertainer", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\ud83c\udfa4",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_singer: {
+    keywords: [ "rockstar", "entertainer", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\ud83c\udfa4",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_teacher: {
+    keywords: [ "instructor", "professor", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\ud83c\udfeb",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_teacher: {
+    keywords: [ "instructor", "professor", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\ud83c\udfeb",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_factory_worker: {
+    keywords: [ "assembly", "industrial", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\ud83c\udfed",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_factory_worker: {
+    keywords: [ "assembly", "industrial", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\ud83c\udfed",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_technologist: {
+    keywords: [ "coder", "developer", "engineer", "programmer", "software", "woman", "human", "laptop", "computer" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udcbb",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_technologist: {
+    keywords: [ "coder", "developer", "engineer", "programmer", "software", "man", "human", "laptop", "computer" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udcbb",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_office_worker: {
+    keywords: [ "business", "manager", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udcbc",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_office_worker: {
+    keywords: [ "business", "manager", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udcbc",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_mechanic: {
+    keywords: [ "plumber", "woman", "human", "wrench" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udd27",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_mechanic: {
+    keywords: [ "plumber", "man", "human", "wrench" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udd27",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_scientist: {
+    keywords: [ "biologist", "chemist", "engineer", "physicist", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udd2c",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_scientist: {
+    keywords: [ "biologist", "chemist", "engineer", "physicist", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udd2c",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_artist: {
+    keywords: [ "painter", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\ud83c\udfa8",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_artist: {
+    keywords: [ "painter", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\ud83c\udfa8",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_firefighter: {
+    keywords: [ "fireman", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\ud83d\ude92",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_firefighter: {
+    keywords: [ "fireman", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\ud83d\ude92",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_pilot: {
+    keywords: [ "aviator", "plane", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\u2708\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_pilot: {
+    keywords: [ "aviator", "plane", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\u2708\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_astronaut: {
+    keywords: [ "space", "rocket", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\ud83d\ude80",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_astronaut: {
+    keywords: [ "space", "rocket", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\ud83d\ude80",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_judge: {
+    keywords: [ "justice", "court", "woman", "human" ],
+    "char": "\ud83d\udc69\u200d\u2696\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_judge: {
+    keywords: [ "justice", "court", "man", "human" ],
+    "char": "\ud83d\udc68\u200d\u2696\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  mrs_claus: {
+    keywords: [ "woman", "female", "xmas", "mother christmas" ],
+    "char": "\ud83e\udd36",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  santa: {
+    keywords: [ "festival", "man", "male", "xmas", "father christmas" ],
+    "char": "\ud83c\udf85",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  sorceress: {
+    keywords: [ "woman", "female", "mage", "witch" ],
+    "char": "\ud83e\uddd9\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  wizard: {
+    keywords: [ "man", "male", "mage", "sorcerer" ],
+    "char": "\ud83e\uddd9\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_elf: {
+    keywords: [ "woman", "female" ],
+    "char": "\ud83e\udddd\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_elf: {
+    keywords: [ "man", "male" ],
+    "char": "\ud83e\udddd\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_vampire: {
+    keywords: [ "woman", "female" ],
+    "char": "\ud83e\udddb\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_vampire: {
+    keywords: [ "man", "male", "dracula" ],
+    "char": "\ud83e\udddb\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_zombie: {
+    keywords: [ "woman", "female", "undead", "walking dead" ],
+    "char": "\ud83e\udddf\u200d\u2640\ufe0f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  man_zombie: {
+    keywords: [ "man", "male", "dracula", "undead", "walking dead" ],
+    "char": "\ud83e\udddf\u200d\u2642\ufe0f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  woman_genie: {
+    keywords: [ "woman", "female" ],
+    "char": "\ud83e\uddde\u200d\u2640\ufe0f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  man_genie: {
+    keywords: [ "man", "male" ],
+    "char": "\ud83e\uddde\u200d\u2642\ufe0f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  mermaid: {
+    keywords: [ "woman", "female", "merwoman", "ariel" ],
+    "char": "\ud83e\udddc\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  merman: {
+    keywords: [ "man", "male", "triton" ],
+    "char": "\ud83e\udddc\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_fairy: {
+    keywords: [ "woman", "female" ],
+    "char": "\ud83e\uddda\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_fairy: {
+    keywords: [ "man", "male" ],
+    "char": "\ud83e\uddda\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  angel: {
+    keywords: [ "heaven", "wings", "halo" ],
+    "char": "\ud83d\udc7c",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  pregnant_woman: {
+    keywords: [ "baby" ],
+    "char": "\ud83e\udd30",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  breastfeeding: {
+    keywords: [ "nursing", "baby" ],
+    "char": "\ud83e\udd31",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  princess: {
+    keywords: [ "girl", "woman", "female", "blond", "crown", "royal", "queen" ],
+    "char": "\ud83d\udc78",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  prince: {
+    keywords: [ "boy", "man", "male", "crown", "royal", "king" ],
+    "char": "\ud83e\udd34",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  bride_with_veil: {
+    keywords: [ "couple", "marriage", "wedding", "woman", "bride" ],
+    "char": "\ud83d\udc70",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_in_tuxedo: {
+    keywords: [ "couple", "marriage", "wedding", "groom" ],
+    "char": "\ud83e\udd35",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  running_woman: {
+    keywords: [ "woman", "walking", "exercise", "race", "running", "female" ],
+    "char": "\ud83c\udfc3\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  running_man: {
+    keywords: [ "man", "walking", "exercise", "race", "running" ],
+    "char": "\ud83c\udfc3",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  walking_woman: {
+    keywords: [ "human", "feet", "steps", "woman", "female" ],
+    "char": "\ud83d\udeb6\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  walking_man: {
+    keywords: [ "human", "feet", "steps" ],
+    "char": "\ud83d\udeb6",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  dancer: {
+    keywords: [ "female", "girl", "woman", "fun" ],
+    "char": "\ud83d\udc83",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_dancing: {
+    keywords: [ "male", "boy", "fun", "dancer" ],
+    "char": "\ud83d\udd7a",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  dancing_women: {
+    keywords: [ "female", "bunny", "women", "girls" ],
+    "char": "\ud83d\udc6f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  dancing_men: {
+    keywords: [ "male", "bunny", "men", "boys" ],
+    "char": "\ud83d\udc6f\u200d\u2642\ufe0f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  couple: {
+    keywords: [ "pair", "people", "human", "love", "date", "dating", "like", "affection", "valentines", "marriage" ],
+    "char": "\ud83d\udc6b",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  two_men_holding_hands: {
+    keywords: [ "pair", "couple", "love", "like", "bromance", "friendship", "people", "human" ],
+    "char": "\ud83d\udc6c",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  two_women_holding_hands: {
+    keywords: [ "pair", "friendship", "couple", "love", "like", "female", "people", "human" ],
+    "char": "\ud83d\udc6d",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  bowing_woman: {
+    keywords: [ "woman", "female", "girl" ],
+    "char": "\ud83d\ude47\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  bowing_man: {
+    keywords: [ "man", "male", "boy" ],
+    "char": "\ud83d\ude47",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_facepalming: {
+    keywords: [ "man", "male", "boy", "disbelief" ],
+    "char": "\ud83e\udd26",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_facepalming: {
+    keywords: [ "woman", "female", "girl", "disbelief" ],
+    "char": "\ud83e\udd26\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_shrugging: {
+    keywords: [ "woman", "female", "girl", "confused", "indifferent", "doubt" ],
+    "char": "\ud83e\udd37",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_shrugging: {
+    keywords: [ "man", "male", "boy", "confused", "indifferent", "doubt" ],
+    "char": "\ud83e\udd37\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  tipping_hand_woman: {
+    keywords: [ "female", "girl", "woman", "human", "information" ],
+    "char": "\ud83d\udc81",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  tipping_hand_man: {
+    keywords: [ "male", "boy", "man", "human", "information" ],
+    "char": "\ud83d\udc81\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  no_good_woman: {
+    keywords: [ "female", "girl", "woman", "nope" ],
+    "char": "\ud83d\ude45",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  no_good_man: {
+    keywords: [ "male", "boy", "man", "nope" ],
+    "char": "\ud83d\ude45\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  ok_woman: {
+    keywords: [ "women", "girl", "female", "pink", "human", "woman" ],
+    "char": "\ud83d\ude46",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  ok_man: {
+    keywords: [ "men", "boy", "male", "blue", "human", "man" ],
+    "char": "\ud83d\ude46\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  raising_hand_woman: {
+    keywords: [ "female", "girl", "woman" ],
+    "char": "\ud83d\ude4b",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  raising_hand_man: {
+    keywords: [ "male", "boy", "man" ],
+    "char": "\ud83d\ude4b\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  pouting_woman: {
+    keywords: [ "female", "girl", "woman" ],
+    "char": "\ud83d\ude4e",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  pouting_man: {
+    keywords: [ "male", "boy", "man" ],
+    "char": "\ud83d\ude4e\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  frowning_woman: {
+    keywords: [ "female", "girl", "woman", "sad", "depressed", "discouraged", "unhappy" ],
+    "char": "\ud83d\ude4d",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  frowning_man: {
+    keywords: [ "male", "boy", "man", "sad", "depressed", "discouraged", "unhappy" ],
+    "char": "\ud83d\ude4d\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  haircut_woman: {
+    keywords: [ "female", "girl", "woman" ],
+    "char": "\ud83d\udc87",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  haircut_man: {
+    keywords: [ "male", "boy", "man" ],
+    "char": "\ud83d\udc87\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  massage_woman: {
+    keywords: [ "female", "girl", "woman", "head" ],
+    "char": "\ud83d\udc86",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  massage_man: {
+    keywords: [ "male", "boy", "man", "head" ],
+    "char": "\ud83d\udc86\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  woman_in_steamy_room: {
+    keywords: [ "female", "woman", "spa", "steamroom", "sauna" ],
+    "char": "\ud83e\uddd6\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  man_in_steamy_room: {
+    keywords: [ "male", "man", "spa", "steamroom", "sauna" ],
+    "char": "\ud83e\uddd6\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "people"
+  },
+  couple_with_heart_woman_man: {
+    keywords: [ "pair", "love", "like", "affection", "human", "dating", "valentines", "marriage" ],
+    "char": "\ud83d\udc91",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  couple_with_heart_woman_woman: {
+    keywords: [ "pair", "love", "like", "affection", "human", "dating", "valentines", "marriage" ],
+    "char": "\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc69",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  couple_with_heart_man_man: {
+    keywords: [ "pair", "love", "like", "affection", "human", "dating", "valentines", "marriage" ],
+    "char": "\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc68",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  couplekiss_man_woman: {
+    keywords: [ "pair", "valentines", "love", "like", "dating", "marriage" ],
+    "char": "\ud83d\udc8f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  couplekiss_woman_woman: {
+    keywords: [ "pair", "valentines", "love", "like", "dating", "marriage" ],
+    "char": "\ud83d\udc69\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc69",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  couplekiss_man_man: {
+    keywords: [ "pair", "valentines", "love", "like", "dating", "marriage" ],
+    "char": "\ud83d\udc68\u200d\u2764\ufe0f\u200d\ud83d\udc8b\u200d\ud83d\udc68",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_woman_boy: {
+    keywords: [ "home", "parents", "child", "mom", "dad", "father", "mother", "people", "human" ],
+    "char": "\ud83d\udc6a",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_woman_girl: {
+    keywords: [ "home", "parents", "people", "human", "child" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_woman_girl_boy: {
+    keywords: [ "home", "parents", "people", "human", "children" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_woman_boy_boy: {
+    keywords: [ "home", "parents", "people", "human", "children" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_woman_girl_girl: {
+    keywords: [ "home", "parents", "people", "human", "children" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_woman_woman_boy: {
+    keywords: [ "home", "parents", "people", "human", "children" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_woman_woman_girl: {
+    keywords: [ "home", "parents", "people", "human", "children" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_woman_woman_girl_boy: {
+    keywords: [ "home", "parents", "people", "human", "children" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_woman_woman_boy_boy: {
+    keywords: [ "home", "parents", "people", "human", "children" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_woman_woman_girl_girl: {
+    keywords: [ "home", "parents", "people", "human", "children" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_man_boy: {
+    keywords: [ "home", "parents", "people", "human", "children" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_man_girl: {
+    keywords: [ "home", "parents", "people", "human", "children" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_man_girl_boy: {
+    keywords: [ "home", "parents", "people", "human", "children" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_man_boy_boy: {
+    keywords: [ "home", "parents", "people", "human", "children" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_man_girl_girl: {
+    keywords: [ "home", "parents", "people", "human", "children" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_woman_boy: {
+    keywords: [ "home", "parent", "people", "human", "child" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_woman_girl: {
+    keywords: [ "home", "parent", "people", "human", "child" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udc67",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_woman_girl_boy: {
+    keywords: [ "home", "parent", "people", "human", "children" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_woman_boy_boy: {
+    keywords: [ "home", "parent", "people", "human", "children" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udc66\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_woman_girl_girl: {
+    keywords: [ "home", "parent", "people", "human", "children" ],
+    "char": "\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_boy: {
+    keywords: [ "home", "parent", "people", "human", "child" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_girl: {
+    keywords: [ "home", "parent", "people", "human", "child" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc67",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_girl_boy: {
+    keywords: [ "home", "parent", "people", "human", "children" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_boy_boy: {
+    keywords: [ "home", "parent", "people", "human", "children" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc66\u200d\ud83d\udc66",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  family_man_girl_girl: {
+    keywords: [ "home", "parent", "people", "human", "children" ],
+    "char": "\ud83d\udc68\u200d\ud83d\udc67\u200d\ud83d\udc67",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  coat: {
+    keywords: [ "jacket" ],
+    "char": "\ud83e\udde5",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  womans_clothes: {
+    keywords: [ "fashion", "shopping_bags", "female" ],
+    "char": "\ud83d\udc5a",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  tshirt: {
+    keywords: [ "fashion", "cloth", "casual", "shirt", "tee" ],
+    "char": "\ud83d\udc55",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  jeans: {
+    keywords: [ "fashion", "shopping" ],
+    "char": "\ud83d\udc56",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  necktie: {
+    keywords: [ "shirt", "suitup", "formal", "fashion", "cloth", "business" ],
+    "char": "\ud83d\udc54",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  dress: {
+    keywords: [ "clothes", "fashion", "shopping" ],
+    "char": "\ud83d\udc57",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  bikini: {
+    keywords: [ "swimming", "female", "woman", "girl", "fashion", "beach", "summer" ],
+    "char": "\ud83d\udc59",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  kimono: {
+    keywords: [ "dress", "fashion", "women", "female", "japanese" ],
+    "char": "\ud83d\udc58",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  lipstick: {
+    keywords: [ "female", "girl", "fashion", "woman" ],
+    "char": "\ud83d\udc84",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  kiss: {
+    keywords: [ "face", "lips", "love", "like", "affection", "valentines" ],
+    "char": "\ud83d\udc8b",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  footprints: {
+    keywords: [ "feet", "tracking", "walking", "beach" ],
+    "char": "\ud83d\udc63",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  high_heel: {
+    keywords: [ "fashion", "shoes", "female", "pumps", "stiletto" ],
+    "char": "\ud83d\udc60",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  sandal: {
+    keywords: [ "shoes", "fashion", "flip flops" ],
+    "char": "\ud83d\udc61",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  boot: {
+    keywords: [ "shoes", "fashion" ],
+    "char": "\ud83d\udc62",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  mans_shoe: {
+    keywords: [ "fashion", "male" ],
+    "char": "\ud83d\udc5e",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  athletic_shoe: {
+    keywords: [ "shoes", "sports", "sneakers" ],
+    "char": "\ud83d\udc5f",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  socks: {
+    keywords: [ "stockings", "clothes" ],
+    "char": "\ud83e\udde6",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  gloves: {
+    keywords: [ "hands", "winter", "clothes" ],
+    "char": "\ud83e\udde4",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  scarf: {
+    keywords: [ "neck", "winter", "clothes" ],
+    "char": "\ud83e\udde3",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  womans_hat: {
+    keywords: [ "fashion", "accessories", "female", "lady", "spring" ],
+    "char": "\ud83d\udc52",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  tophat: {
+    keywords: [ "magic", "gentleman", "classy", "circus" ],
+    "char": "\ud83c\udfa9",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  billed_hat: {
+    keywords: [ "cap", "baseball" ],
+    "char": "\ud83e\udde2",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  rescue_worker_helmet: {
+    keywords: [ "construction", "build" ],
+    "char": "\u26d1",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  mortar_board: {
+    keywords: [ "school", "college", "degree", "university", "graduation", "cap", "hat", "legal", "learn", "education" ],
+    "char": "\ud83c\udf93",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  crown: {
+    keywords: [ "king", "kod", "leader", "royalty", "lord" ],
+    "char": "\ud83d\udc51",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  school_satchel: {
+    keywords: [ "student", "education", "bag", "backpack" ],
+    "char": "\ud83c\udf92",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  pouch: {
+    keywords: [ "bag", "accessories", "shopping" ],
+    "char": "\ud83d\udc5d",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  purse: {
+    keywords: [ "fashion", "accessories", "money", "sales", "shopping" ],
+    "char": "\ud83d\udc5b",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  handbag: {
+    keywords: [ "fashion", "accessory", "accessories", "shopping" ],
+    "char": "\ud83d\udc5c",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  briefcase: {
+    keywords: [ "business", "documents", "work", "law", "legal", "job", "career" ],
+    "char": "\ud83d\udcbc",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  eyeglasses: {
+    keywords: [ "fashion", "accessories", "eyesight", "nerdy", "dork", "geek" ],
+    "char": "\ud83d\udc53",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  dark_sunglasses: {
+    keywords: [ "face", "cool", "accessories" ],
+    "char": "\ud83d\udd76",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  ring: {
+    keywords: [ "wedding", "propose", "marriage", "valentines", "diamond", "fashion", "jewelry", "gem", "engagement" ],
+    "char": "\ud83d\udc8d",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  closed_umbrella: {
+    keywords: [ "weather", "rain", "drizzle" ],
+    "char": "\ud83c\udf02",
+    fitzpatrick_scale: false,
+    category: "people"
+  },
+  dog: {
+    keywords: [ "animal", "friend", "nature", "woof", "puppy", "pet", "faithful" ],
+    "char": "\ud83d\udc36",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  cat: {
+    keywords: [ "animal", "meow", "nature", "pet", "kitten" ],
+    "char": "\ud83d\udc31",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  mouse: {
+    keywords: [ "animal", "nature", "cheese_wedge", "rodent" ],
+    "char": "\ud83d\udc2d",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  hamster: {
+    keywords: [ "animal", "nature" ],
+    "char": "\ud83d\udc39",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  rabbit: {
+    keywords: [ "animal", "nature", "pet", "spring", "magic", "bunny" ],
+    "char": "\ud83d\udc30",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  fox_face: {
+    keywords: [ "animal", "nature", "face" ],
+    "char": "\ud83e\udd8a",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  bear: {
+    keywords: [ "animal", "nature", "wild" ],
+    "char": "\ud83d\udc3b",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  panda_face: {
+    keywords: [ "animal", "nature", "panda" ],
+    "char": "\ud83d\udc3c",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  koala: {
+    keywords: [ "animal", "nature" ],
+    "char": "\ud83d\udc28",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  tiger: {
+    keywords: [ "animal", "cat", "danger", "wild", "nature", "roar" ],
+    "char": "\ud83d\udc2f",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  lion: {
+    keywords: [ "animal", "nature" ],
+    "char": "\ud83e\udd81",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  cow: {
+    keywords: [ "beef", "ox", "animal", "nature", "moo", "milk" ],
+    "char": "\ud83d\udc2e",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  pig: {
+    keywords: [ "animal", "oink", "nature" ],
+    "char": "\ud83d\udc37",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  pig_nose: {
+    keywords: [ "animal", "oink" ],
+    "char": "\ud83d\udc3d",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  frog: {
+    keywords: [ "animal", "nature", "croak", "toad" ],
+    "char": "\ud83d\udc38",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  squid: {
+    keywords: [ "animal", "nature", "ocean", "sea" ],
+    "char": "\ud83e\udd91",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  octopus: {
+    keywords: [ "animal", "creature", "ocean", "sea", "nature", "beach" ],
+    "char": "\ud83d\udc19",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  shrimp: {
+    keywords: [ "animal", "ocean", "nature", "seafood" ],
+    "char": "\ud83e\udd90",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  monkey_face: {
+    keywords: [ "animal", "nature", "circus" ],
+    "char": "\ud83d\udc35",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  gorilla: {
+    keywords: [ "animal", "nature", "circus" ],
+    "char": "\ud83e\udd8d",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  see_no_evil: {
+    keywords: [ "monkey", "animal", "nature", "haha" ],
+    "char": "\ud83d\ude48",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  hear_no_evil: {
+    keywords: [ "animal", "monkey", "nature" ],
+    "char": "\ud83d\ude49",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  speak_no_evil: {
+    keywords: [ "monkey", "animal", "nature", "omg" ],
+    "char": "\ud83d\ude4a",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  monkey: {
+    keywords: [ "animal", "nature", "banana", "circus" ],
+    "char": "\ud83d\udc12",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  chicken: {
+    keywords: [ "animal", "cluck", "nature", "bird" ],
+    "char": "\ud83d\udc14",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  penguin: {
+    keywords: [ "animal", "nature" ],
+    "char": "\ud83d\udc27",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  bird: {
+    keywords: [ "animal", "nature", "fly", "tweet", "spring" ],
+    "char": "\ud83d\udc26",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  baby_chick: {
+    keywords: [ "animal", "chicken", "bird" ],
+    "char": "\ud83d\udc24",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  hatching_chick: {
+    keywords: [ "animal", "chicken", "egg", "born", "baby", "bird" ],
+    "char": "\ud83d\udc23",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  hatched_chick: {
+    keywords: [ "animal", "chicken", "baby", "bird" ],
+    "char": "\ud83d\udc25",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  duck: {
+    keywords: [ "animal", "nature", "bird", "mallard" ],
+    "char": "\ud83e\udd86",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  eagle: {
+    keywords: [ "animal", "nature", "bird" ],
+    "char": "\ud83e\udd85",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  owl: {
+    keywords: [ "animal", "nature", "bird", "hoot" ],
+    "char": "\ud83e\udd89",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  bat: {
+    keywords: [ "animal", "nature", "blind", "vampire" ],
+    "char": "\ud83e\udd87",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  wolf: {
+    keywords: [ "animal", "nature", "wild" ],
+    "char": "\ud83d\udc3a",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  boar: {
+    keywords: [ "animal", "nature" ],
+    "char": "\ud83d\udc17",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  horse: {
+    keywords: [ "animal", "brown", "nature" ],
+    "char": "\ud83d\udc34",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  unicorn: {
+    keywords: [ "animal", "nature", "mystical" ],
+    "char": "\ud83e\udd84",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  honeybee: {
+    keywords: [ "animal", "insect", "nature", "bug", "spring", "honey" ],
+    "char": "\ud83d\udc1d",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  bug: {
+    keywords: [ "animal", "insect", "nature", "worm" ],
+    "char": "\ud83d\udc1b",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  butterfly: {
+    keywords: [ "animal", "insect", "nature", "caterpillar" ],
+    "char": "\ud83e\udd8b",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  snail: {
+    keywords: [ "slow", "animal", "shell" ],
+    "char": "\ud83d\udc0c",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  beetle: {
+    keywords: [ "animal", "insect", "nature", "ladybug" ],
+    "char": "\ud83d\udc1e",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  ant: {
+    keywords: [ "animal", "insect", "nature", "bug" ],
+    "char": "\ud83d\udc1c",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  grasshopper: {
+    keywords: [ "animal", "cricket", "chirp" ],
+    "char": "\ud83e\udd97",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  spider: {
+    keywords: [ "animal", "arachnid" ],
+    "char": "\ud83d\udd77",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  scorpion: {
+    keywords: [ "animal", "arachnid" ],
+    "char": "\ud83e\udd82",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  crab: {
+    keywords: [ "animal", "crustacean" ],
+    "char": "\ud83e\udd80",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  snake: {
+    keywords: [ "animal", "evil", "nature", "hiss", "python" ],
+    "char": "\ud83d\udc0d",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  lizard: {
+    keywords: [ "animal", "nature", "reptile" ],
+    "char": "\ud83e\udd8e",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  "t-rex": {
+    keywords: [ "animal", "nature", "dinosaur", "tyrannosaurus", "extinct" ],
+    "char": "\ud83e\udd96",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  sauropod: {
+    keywords: [ "animal", "nature", "dinosaur", "brachiosaurus", "brontosaurus", "diplodocus", "extinct" ],
+    "char": "\ud83e\udd95",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  turtle: {
+    keywords: [ "animal", "slow", "nature", "tortoise" ],
+    "char": "\ud83d\udc22",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  tropical_fish: {
+    keywords: [ "animal", "swim", "ocean", "beach", "nemo" ],
+    "char": "\ud83d\udc20",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  fish: {
+    keywords: [ "animal", "food", "nature" ],
+    "char": "\ud83d\udc1f",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  blowfish: {
+    keywords: [ "animal", "nature", "food", "sea", "ocean" ],
+    "char": "\ud83d\udc21",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  dolphin: {
+    keywords: [ "animal", "nature", "fish", "sea", "ocean", "flipper", "fins", "beach" ],
+    "char": "\ud83d\udc2c",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  shark: {
+    keywords: [ "animal", "nature", "fish", "sea", "ocean", "jaws", "fins", "beach" ],
+    "char": "\ud83e\udd88",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  whale: {
+    keywords: [ "animal", "nature", "sea", "ocean" ],
+    "char": "\ud83d\udc33",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  whale2: {
+    keywords: [ "animal", "nature", "sea", "ocean" ],
+    "char": "\ud83d\udc0b",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  crocodile: {
+    keywords: [ "animal", "nature", "reptile", "lizard", "alligator" ],
+    "char": "\ud83d\udc0a",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  leopard: {
+    keywords: [ "animal", "nature" ],
+    "char": "\ud83d\udc06",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  zebra: {
+    keywords: [ "animal", "nature", "stripes", "safari" ],
+    "char": "\ud83e\udd93",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  tiger2: {
+    keywords: [ "animal", "nature", "roar" ],
+    "char": "\ud83d\udc05",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  water_buffalo: {
+    keywords: [ "animal", "nature", "ox", "cow" ],
+    "char": "\ud83d\udc03",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  ox: {
+    keywords: [ "animal", "cow", "beef" ],
+    "char": "\ud83d\udc02",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  cow2: {
+    keywords: [ "beef", "ox", "animal", "nature", "moo", "milk" ],
+    "char": "\ud83d\udc04",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  deer: {
+    keywords: [ "animal", "nature", "horns", "venison" ],
+    "char": "\ud83e\udd8c",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  dromedary_camel: {
+    keywords: [ "animal", "hot", "desert", "hump" ],
+    "char": "\ud83d\udc2a",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  camel: {
+    keywords: [ "animal", "nature", "hot", "desert", "hump" ],
+    "char": "\ud83d\udc2b",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  giraffe: {
+    keywords: [ "animal", "nature", "spots", "safari" ],
+    "char": "\ud83e\udd92",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  elephant: {
+    keywords: [ "animal", "nature", "nose", "th", "circus" ],
+    "char": "\ud83d\udc18",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  rhinoceros: {
+    keywords: [ "animal", "nature", "horn" ],
+    "char": "\ud83e\udd8f",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  goat: {
+    keywords: [ "animal", "nature" ],
+    "char": "\ud83d\udc10",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  ram: {
+    keywords: [ "animal", "sheep", "nature" ],
+    "char": "\ud83d\udc0f",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  sheep: {
+    keywords: [ "animal", "nature", "wool", "shipit" ],
+    "char": "\ud83d\udc11",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  racehorse: {
+    keywords: [ "animal", "gamble", "luck" ],
+    "char": "\ud83d\udc0e",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  pig2: {
+    keywords: [ "animal", "nature" ],
+    "char": "\ud83d\udc16",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  rat: {
+    keywords: [ "animal", "mouse", "rodent" ],
+    "char": "\ud83d\udc00",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  mouse2: {
+    keywords: [ "animal", "nature", "rodent" ],
+    "char": "\ud83d\udc01",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  rooster: {
+    keywords: [ "animal", "nature", "chicken" ],
+    "char": "\ud83d\udc13",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  turkey: {
+    keywords: [ "animal", "bird" ],
+    "char": "\ud83e\udd83",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  dove: {
+    keywords: [ "animal", "bird" ],
+    "char": "\ud83d\udd4a",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  dog2: {
+    keywords: [ "animal", "nature", "friend", "doge", "pet", "faithful" ],
+    "char": "\ud83d\udc15",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  poodle: {
+    keywords: [ "dog", "animal", "101", "nature", "pet" ],
+    "char": "\ud83d\udc29",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  cat2: {
+    keywords: [ "animal", "meow", "pet", "cats" ],
+    "char": "\ud83d\udc08",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  rabbit2: {
+    keywords: [ "animal", "nature", "pet", "magic", "spring" ],
+    "char": "\ud83d\udc07",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  chipmunk: {
+    keywords: [ "animal", "nature", "rodent", "squirrel" ],
+    "char": "\ud83d\udc3f",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  hedgehog: {
+    keywords: [ "animal", "nature", "spiny" ],
+    "char": "\ud83e\udd94",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  paw_prints: {
+    keywords: [ "animal", "tracking", "footprints", "dog", "cat", "pet", "feet" ],
+    "char": "\ud83d\udc3e",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  dragon: {
+    keywords: [ "animal", "myth", "nature", "chinese", "green" ],
+    "char": "\ud83d\udc09",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  dragon_face: {
+    keywords: [ "animal", "myth", "nature", "chinese", "green" ],
+    "char": "\ud83d\udc32",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  cactus: {
+    keywords: [ "vegetable", "plant", "nature" ],
+    "char": "\ud83c\udf35",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  christmas_tree: {
+    keywords: [ "festival", "vacation", "december", "xmas", "celebration" ],
+    "char": "\ud83c\udf84",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  evergreen_tree: {
+    keywords: [ "plant", "nature" ],
+    "char": "\ud83c\udf32",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  deciduous_tree: {
+    keywords: [ "plant", "nature" ],
+    "char": "\ud83c\udf33",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  palm_tree: {
+    keywords: [ "plant", "vegetable", "nature", "summer", "beach", "mojito", "tropical" ],
+    "char": "\ud83c\udf34",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  seedling: {
+    keywords: [ "plant", "nature", "grass", "lawn", "spring" ],
+    "char": "\ud83c\udf31",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  herb: {
+    keywords: [ "vegetable", "plant", "medicine", "weed", "grass", "lawn" ],
+    "char": "\ud83c\udf3f",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  shamrock: {
+    keywords: [ "vegetable", "plant", "nature", "irish", "clover" ],
+    "char": "\u2618",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  four_leaf_clover: {
+    keywords: [ "vegetable", "plant", "nature", "lucky", "irish" ],
+    "char": "\ud83c\udf40",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  bamboo: {
+    keywords: [ "plant", "nature", "vegetable", "panda", "pine_decoration" ],
+    "char": "\ud83c\udf8d",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  tanabata_tree: {
+    keywords: [ "plant", "nature", "branch", "summer" ],
+    "char": "\ud83c\udf8b",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  leaves: {
+    keywords: [ "nature", "plant", "tree", "vegetable", "grass", "lawn", "spring" ],
+    "char": "\ud83c\udf43",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  fallen_leaf: {
+    keywords: [ "nature", "plant", "vegetable", "leaves" ],
+    "char": "\ud83c\udf42",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  maple_leaf: {
+    keywords: [ "nature", "plant", "vegetable", "ca", "fall" ],
+    "char": "\ud83c\udf41",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  ear_of_rice: {
+    keywords: [ "nature", "plant" ],
+    "char": "\ud83c\udf3e",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  hibiscus: {
+    keywords: [ "plant", "vegetable", "flowers", "beach" ],
+    "char": "\ud83c\udf3a",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  sunflower: {
+    keywords: [ "nature", "plant", "fall" ],
+    "char": "\ud83c\udf3b",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  rose: {
+    keywords: [ "flowers", "valentines", "love", "spring" ],
+    "char": "\ud83c\udf39",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  wilted_flower: {
+    keywords: [ "plant", "nature", "flower" ],
+    "char": "\ud83e\udd40",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  tulip: {
+    keywords: [ "flowers", "plant", "nature", "summer", "spring" ],
+    "char": "\ud83c\udf37",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  blossom: {
+    keywords: [ "nature", "flowers", "yellow" ],
+    "char": "\ud83c\udf3c",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  cherry_blossom: {
+    keywords: [ "nature", "plant", "spring", "flower" ],
+    "char": "\ud83c\udf38",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  bouquet: {
+    keywords: [ "flowers", "nature", "spring" ],
+    "char": "\ud83d\udc90",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  mushroom: {
+    keywords: [ "plant", "vegetable" ],
+    "char": "\ud83c\udf44",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  chestnut: {
+    keywords: [ "food", "squirrel" ],
+    "char": "\ud83c\udf30",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  jack_o_lantern: {
+    keywords: [ "halloween", "light", "pumpkin", "creepy", "fall" ],
+    "char": "\ud83c\udf83",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  shell: {
+    keywords: [ "nature", "sea", "beach" ],
+    "char": "\ud83d\udc1a",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  spider_web: {
+    keywords: [ "animal", "insect", "arachnid", "silk" ],
+    "char": "\ud83d\udd78",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  earth_americas: {
+    keywords: [ "globe", "world", "USA", "international" ],
+    "char": "\ud83c\udf0e",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  earth_africa: {
+    keywords: [ "globe", "world", "international" ],
+    "char": "\ud83c\udf0d",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  earth_asia: {
+    keywords: [ "globe", "world", "east", "international" ],
+    "char": "\ud83c\udf0f",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  full_moon: {
+    keywords: [ "nature", "yellow", "twilight", "planet", "space", "night", "evening", "sleep" ],
+    "char": "\ud83c\udf15",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  waning_gibbous_moon: {
+    keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep", "waxing_gibbous_moon" ],
+    "char": "\ud83c\udf16",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  last_quarter_moon: {
+    keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ],
+    "char": "\ud83c\udf17",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  waning_crescent_moon: {
+    keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ],
+    "char": "\ud83c\udf18",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  new_moon: {
+    keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ],
+    "char": "\ud83c\udf11",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  waxing_crescent_moon: {
+    keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ],
+    "char": "\ud83c\udf12",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  first_quarter_moon: {
+    keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ],
+    "char": "\ud83c\udf13",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  waxing_gibbous_moon: {
+    keywords: [ "nature", "night", "sky", "gray", "twilight", "planet", "space", "evening", "sleep" ],
+    "char": "\ud83c\udf14",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  new_moon_with_face: {
+    keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ],
+    "char": "\ud83c\udf1a",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  full_moon_with_face: {
+    keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ],
+    "char": "\ud83c\udf1d",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  first_quarter_moon_with_face: {
+    keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ],
+    "char": "\ud83c\udf1b",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  last_quarter_moon_with_face: {
+    keywords: [ "nature", "twilight", "planet", "space", "night", "evening", "sleep" ],
+    "char": "\ud83c\udf1c",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  sun_with_face: {
+    keywords: [ "nature", "morning", "sky" ],
+    "char": "\ud83c\udf1e",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  crescent_moon: {
+    keywords: [ "night", "sleep", "sky", "evening", "magic" ],
+    "char": "\ud83c\udf19",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  star: {
+    keywords: [ "night", "yellow" ],
+    "char": "\u2b50",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  star2: {
+    keywords: [ "night", "sparkle", "awesome", "good", "magic" ],
+    "char": "\ud83c\udf1f",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  dizzy: {
+    keywords: [ "star", "sparkle", "shoot", "magic" ],
+    "char": "\ud83d\udcab",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  sparkles: {
+    keywords: [ "stars", "shine", "shiny", "cool", "awesome", "good", "magic" ],
+    "char": "\u2728",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  comet: {
+    keywords: [ "space" ],
+    "char": "\u2604",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  sunny: {
+    keywords: [ "weather", "nature", "brightness", "summer", "beach", "spring" ],
+    "char": "\u2600\ufe0f",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  sun_behind_small_cloud: {
+    keywords: [ "weather" ],
+    "char": "\ud83c\udf24",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  partly_sunny: {
+    keywords: [ "weather", "nature", "cloudy", "morning", "fall", "spring" ],
+    "char": "\u26c5",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  sun_behind_large_cloud: {
+    keywords: [ "weather" ],
+    "char": "\ud83c\udf25",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  sun_behind_rain_cloud: {
+    keywords: [ "weather" ],
+    "char": "\ud83c\udf26",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  cloud: {
+    keywords: [ "weather", "sky" ],
+    "char": "\u2601\ufe0f",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  cloud_with_rain: {
+    keywords: [ "weather" ],
+    "char": "\ud83c\udf27",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  cloud_with_lightning_and_rain: {
+    keywords: [ "weather", "lightning" ],
+    "char": "\u26c8",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  cloud_with_lightning: {
+    keywords: [ "weather", "thunder" ],
+    "char": "\ud83c\udf29",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  zap: {
+    keywords: [ "thunder", "weather", "lightning bolt", "fast" ],
+    "char": "\u26a1",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  fire: {
+    keywords: [ "hot", "cook", "flame" ],
+    "char": "\ud83d\udd25",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  boom: {
+    keywords: [ "bomb", "explode", "explosion", "collision", "blown" ],
+    "char": "\ud83d\udca5",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  snowflake: {
+    keywords: [ "winter", "season", "cold", "weather", "christmas", "xmas" ],
+    "char": "\u2744\ufe0f",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  cloud_with_snow: {
+    keywords: [ "weather" ],
+    "char": "\ud83c\udf28",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  snowman: {
+    keywords: [ "winter", "season", "cold", "weather", "christmas", "xmas", "frozen", "without_snow" ],
+    "char": "\u26c4",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  snowman_with_snow: {
+    keywords: [ "winter", "season", "cold", "weather", "christmas", "xmas", "frozen" ],
+    "char": "\u2603",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  wind_face: {
+    keywords: [ "gust", "air" ],
+    "char": "\ud83c\udf2c",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  dash: {
+    keywords: [ "wind", "air", "fast", "shoo", "fart", "smoke", "puff" ],
+    "char": "\ud83d\udca8",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  tornado: {
+    keywords: [ "weather", "cyclone", "twister" ],
+    "char": "\ud83c\udf2a",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  fog: {
+    keywords: [ "weather" ],
+    "char": "\ud83c\udf2b",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  open_umbrella: {
+    keywords: [ "weather", "spring" ],
+    "char": "\u2602",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  umbrella: {
+    keywords: [ "rainy", "weather", "spring" ],
+    "char": "\u2614",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  droplet: {
+    keywords: [ "water", "drip", "faucet", "spring" ],
+    "char": "\ud83d\udca7",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  sweat_drops: {
+    keywords: [ "water", "drip", "oops" ],
+    "char": "\ud83d\udca6",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  ocean: {
+    keywords: [ "sea", "water", "wave", "nature", "tsunami", "disaster" ],
+    "char": "\ud83c\udf0a",
+    fitzpatrick_scale: false,
+    category: "animals_and_nature"
+  },
+  green_apple: {
+    keywords: [ "fruit", "nature" ],
+    "char": "\ud83c\udf4f",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  apple: {
+    keywords: [ "fruit", "mac", "school" ],
+    "char": "\ud83c\udf4e",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  pear: {
+    keywords: [ "fruit", "nature", "food" ],
+    "char": "\ud83c\udf50",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  tangerine: {
+    keywords: [ "food", "fruit", "nature", "orange" ],
+    "char": "\ud83c\udf4a",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  lemon: {
+    keywords: [ "fruit", "nature" ],
+    "char": "\ud83c\udf4b",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  banana: {
+    keywords: [ "fruit", "food", "monkey" ],
+    "char": "\ud83c\udf4c",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  watermelon: {
+    keywords: [ "fruit", "food", "picnic", "summer" ],
+    "char": "\ud83c\udf49",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  grapes: {
+    keywords: [ "fruit", "food", "wine" ],
+    "char": "\ud83c\udf47",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  strawberry: {
+    keywords: [ "fruit", "food", "nature" ],
+    "char": "\ud83c\udf53",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  melon: {
+    keywords: [ "fruit", "nature", "food" ],
+    "char": "\ud83c\udf48",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  cherries: {
+    keywords: [ "food", "fruit" ],
+    "char": "\ud83c\udf52",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  peach: {
+    keywords: [ "fruit", "nature", "food" ],
+    "char": "\ud83c\udf51",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  pineapple: {
+    keywords: [ "fruit", "nature", "food" ],
+    "char": "\ud83c\udf4d",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  coconut: {
+    keywords: [ "fruit", "nature", "food", "palm" ],
+    "char": "\ud83e\udd65",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  kiwi_fruit: {
+    keywords: [ "fruit", "food" ],
+    "char": "\ud83e\udd5d",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  avocado: {
+    keywords: [ "fruit", "food" ],
+    "char": "\ud83e\udd51",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  broccoli: {
+    keywords: [ "fruit", "food", "vegetable" ],
+    "char": "\ud83e\udd66",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  tomato: {
+    keywords: [ "fruit", "vegetable", "nature", "food" ],
+    "char": "\ud83c\udf45",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  eggplant: {
+    keywords: [ "vegetable", "nature", "food", "aubergine" ],
+    "char": "\ud83c\udf46",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  cucumber: {
+    keywords: [ "fruit", "food", "pickle" ],
+    "char": "\ud83e\udd52",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  carrot: {
+    keywords: [ "vegetable", "food", "orange" ],
+    "char": "\ud83e\udd55",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  hot_pepper: {
+    keywords: [ "food", "spicy", "chilli", "chili" ],
+    "char": "\ud83c\udf36",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  potato: {
+    keywords: [ "food", "tuber", "vegatable", "starch" ],
+    "char": "\ud83e\udd54",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  corn: {
+    keywords: [ "food", "vegetable", "plant" ],
+    "char": "\ud83c\udf3d",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  sweet_potato: {
+    keywords: [ "food", "nature" ],
+    "char": "\ud83c\udf60",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  peanuts: {
+    keywords: [ "food", "nut" ],
+    "char": "\ud83e\udd5c",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  honey_pot: {
+    keywords: [ "bees", "sweet", "kitchen" ],
+    "char": "\ud83c\udf6f",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  croissant: {
+    keywords: [ "food", "bread", "french" ],
+    "char": "\ud83e\udd50",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  bread: {
+    keywords: [ "food", "wheat", "breakfast", "toast" ],
+    "char": "\ud83c\udf5e",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  baguette_bread: {
+    keywords: [ "food", "bread", "french" ],
+    "char": "\ud83e\udd56",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  pretzel: {
+    keywords: [ "food", "bread", "twisted" ],
+    "char": "\ud83e\udd68",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  cheese: {
+    keywords: [ "food", "chadder" ],
+    "char": "\ud83e\uddc0",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  egg: {
+    keywords: [ "food", "chicken", "breakfast" ],
+    "char": "\ud83e\udd5a",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  bacon: {
+    keywords: [ "food", "breakfast", "pork", "pig", "meat" ],
+    "char": "\ud83e\udd53",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  steak: {
+    keywords: [ "food", "cow", "meat", "cut", "chop", "lambchop", "porkchop" ],
+    "char": "\ud83e\udd69",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  pancakes: {
+    keywords: [ "food", "breakfast", "flapjacks", "hotcakes" ],
+    "char": "\ud83e\udd5e",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  poultry_leg: {
+    keywords: [ "food", "meat", "drumstick", "bird", "chicken", "turkey" ],
+    "char": "\ud83c\udf57",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  meat_on_bone: {
+    keywords: [ "good", "food", "drumstick" ],
+    "char": "\ud83c\udf56",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  fried_shrimp: {
+    keywords: [ "food", "animal", "appetizer", "summer" ],
+    "char": "\ud83c\udf64",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  fried_egg: {
+    keywords: [ "food", "breakfast", "kitchen", "egg" ],
+    "char": "\ud83c\udf73",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  hamburger: {
+    keywords: [ "meat", "fast food", "beef", "cheeseburger", "mcdonalds", "burger king" ],
+    "char": "\ud83c\udf54",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  fries: {
+    keywords: [ "chips", "snack", "fast food" ],
+    "char": "\ud83c\udf5f",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  stuffed_flatbread: {
+    keywords: [ "food", "flatbread", "stuffed", "gyro" ],
+    "char": "\ud83e\udd59",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  hotdog: {
+    keywords: [ "food", "frankfurter" ],
+    "char": "\ud83c\udf2d",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  pizza: {
+    keywords: [ "food", "party" ],
+    "char": "\ud83c\udf55",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  sandwich: {
+    keywords: [ "food", "lunch", "bread" ],
+    "char": "\ud83e\udd6a",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  canned_food: {
+    keywords: [ "food", "soup" ],
+    "char": "\ud83e\udd6b",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  spaghetti: {
+    keywords: [ "food", "italian", "noodle" ],
+    "char": "\ud83c\udf5d",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  taco: {
+    keywords: [ "food", "mexican" ],
+    "char": "\ud83c\udf2e",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  burrito: {
+    keywords: [ "food", "mexican" ],
+    "char": "\ud83c\udf2f",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  green_salad: {
+    keywords: [ "food", "healthy", "lettuce" ],
+    "char": "\ud83e\udd57",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  shallow_pan_of_food: {
+    keywords: [ "food", "cooking", "casserole", "paella" ],
+    "char": "\ud83e\udd58",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  ramen: {
+    keywords: [ "food", "japanese", "noodle", "chopsticks" ],
+    "char": "\ud83c\udf5c",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  stew: {
+    keywords: [ "food", "meat", "soup" ],
+    "char": "\ud83c\udf72",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  fish_cake: {
+    keywords: [ "food", "japan", "sea", "beach", "narutomaki", "pink", "swirl", "kamaboko", "surimi", "ramen" ],
+    "char": "\ud83c\udf65",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  fortune_cookie: {
+    keywords: [ "food", "prophecy" ],
+    "char": "\ud83e\udd60",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  sushi: {
+    keywords: [ "food", "fish", "japanese", "rice" ],
+    "char": "\ud83c\udf63",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  bento: {
+    keywords: [ "food", "japanese", "box" ],
+    "char": "\ud83c\udf71",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  curry: {
+    keywords: [ "food", "spicy", "hot", "indian" ],
+    "char": "\ud83c\udf5b",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  rice_ball: {
+    keywords: [ "food", "japanese" ],
+    "char": "\ud83c\udf59",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  rice: {
+    keywords: [ "food", "china", "asian" ],
+    "char": "\ud83c\udf5a",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  rice_cracker: {
+    keywords: [ "food", "japanese" ],
+    "char": "\ud83c\udf58",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  oden: {
+    keywords: [ "food", "japanese" ],
+    "char": "\ud83c\udf62",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  dango: {
+    keywords: [ "food", "dessert", "sweet", "japanese", "barbecue", "meat" ],
+    "char": "\ud83c\udf61",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  shaved_ice: {
+    keywords: [ "hot", "dessert", "summer" ],
+    "char": "\ud83c\udf67",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  ice_cream: {
+    keywords: [ "food", "hot", "dessert" ],
+    "char": "\ud83c\udf68",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  icecream: {
+    keywords: [ "food", "hot", "dessert", "summer" ],
+    "char": "\ud83c\udf66",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  pie: {
+    keywords: [ "food", "dessert", "pastry" ],
+    "char": "\ud83e\udd67",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  cake: {
+    keywords: [ "food", "dessert" ],
+    "char": "\ud83c\udf70",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  birthday: {
+    keywords: [ "food", "dessert", "cake" ],
+    "char": "\ud83c\udf82",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  custard: {
+    keywords: [ "dessert", "food" ],
+    "char": "\ud83c\udf6e",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  candy: {
+    keywords: [ "snack", "dessert", "sweet", "lolly" ],
+    "char": "\ud83c\udf6c",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  lollipop: {
+    keywords: [ "food", "snack", "candy", "sweet" ],
+    "char": "\ud83c\udf6d",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  chocolate_bar: {
+    keywords: [ "food", "snack", "dessert", "sweet" ],
+    "char": "\ud83c\udf6b",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  popcorn: {
+    keywords: [ "food", "movie theater", "films", "snack" ],
+    "char": "\ud83c\udf7f",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  dumpling: {
+    keywords: [ "food", "empanada", "pierogi", "potsticker" ],
+    "char": "\ud83e\udd5f",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  doughnut: {
+    keywords: [ "food", "dessert", "snack", "sweet", "donut" ],
+    "char": "\ud83c\udf69",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  cookie: {
+    keywords: [ "food", "snack", "oreo", "chocolate", "sweet", "dessert" ],
+    "char": "\ud83c\udf6a",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  milk_glass: {
+    keywords: [ "beverage", "drink", "cow" ],
+    "char": "\ud83e\udd5b",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  beer: {
+    keywords: [ "relax", "beverage", "drink", "drunk", "party", "pub", "summer", "alcohol", "booze" ],
+    "char": "\ud83c\udf7a",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  beers: {
+    keywords: [ "relax", "beverage", "drink", "drunk", "party", "pub", "summer", "alcohol", "booze" ],
+    "char": "\ud83c\udf7b",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  clinking_glasses: {
+    keywords: [ "beverage", "drink", "party", "alcohol", "celebrate", "cheers", "wine", "champagne", "toast" ],
+    "char": "\ud83e\udd42",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  wine_glass: {
+    keywords: [ "drink", "beverage", "drunk", "alcohol", "booze" ],
+    "char": "\ud83c\udf77",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  tumbler_glass: {
+    keywords: [ "drink", "beverage", "drunk", "alcohol", "liquor", "booze", "bourbon", "scotch", "whisky", "glass", "shot" ],
+    "char": "\ud83e\udd43",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  cocktail: {
+    keywords: [ "drink", "drunk", "alcohol", "beverage", "booze", "mojito" ],
+    "char": "\ud83c\udf78",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  tropical_drink: {
+    keywords: [ "beverage", "cocktail", "summer", "beach", "alcohol", "booze", "mojito" ],
+    "char": "\ud83c\udf79",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  champagne: {
+    keywords: [ "drink", "wine", "bottle", "celebration" ],
+    "char": "\ud83c\udf7e",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  sake: {
+    keywords: [ "wine", "drink", "drunk", "beverage", "japanese", "alcohol", "booze" ],
+    "char": "\ud83c\udf76",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  tea: {
+    keywords: [ "drink", "bowl", "breakfast", "green", "british" ],
+    "char": "\ud83c\udf75",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  cup_with_straw: {
+    keywords: [ "drink", "soda" ],
+    "char": "\ud83e\udd64",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  coffee: {
+    keywords: [ "beverage", "caffeine", "latte", "espresso" ],
+    "char": "\u2615",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  baby_bottle: {
+    keywords: [ "food", "container", "milk" ],
+    "char": "\ud83c\udf7c",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  spoon: {
+    keywords: [ "cutlery", "kitchen", "tableware" ],
+    "char": "\ud83e\udd44",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  fork_and_knife: {
+    keywords: [ "cutlery", "kitchen" ],
+    "char": "\ud83c\udf74",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  plate_with_cutlery: {
+    keywords: [ "food", "eat", "meal", "lunch", "dinner", "restaurant" ],
+    "char": "\ud83c\udf7d",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  bowl_with_spoon: {
+    keywords: [ "food", "breakfast", "cereal", "oatmeal", "porridge" ],
+    "char": "\ud83e\udd63",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  takeout_box: {
+    keywords: [ "food", "leftovers" ],
+    "char": "\ud83e\udd61",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  chopsticks: {
+    keywords: [ "food" ],
+    "char": "\ud83e\udd62",
+    fitzpatrick_scale: false,
+    category: "food_and_drink"
+  },
+  soccer: {
+    keywords: [ "sports", "football" ],
+    "char": "\u26bd",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  basketball: {
+    keywords: [ "sports", "balls", "NBA" ],
+    "char": "\ud83c\udfc0",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  football: {
+    keywords: [ "sports", "balls", "NFL" ],
+    "char": "\ud83c\udfc8",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  baseball: {
+    keywords: [ "sports", "balls" ],
+    "char": "\u26be",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  tennis: {
+    keywords: [ "sports", "balls", "green" ],
+    "char": "\ud83c\udfbe",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  volleyball: {
+    keywords: [ "sports", "balls" ],
+    "char": "\ud83c\udfd0",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  rugby_football: {
+    keywords: [ "sports", "team" ],
+    "char": "\ud83c\udfc9",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  "8ball": {
+    keywords: [ "pool", "hobby", "game", "luck", "magic" ],
+    "char": "\ud83c\udfb1",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  golf: {
+    keywords: [ "sports", "business", "flag", "hole", "summer" ],
+    "char": "\u26f3",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  golfing_woman: {
+    keywords: [ "sports", "business", "woman", "female" ],
+    "char": "\ud83c\udfcc\ufe0f\u200d\u2640\ufe0f",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  golfing_man: {
+    keywords: [ "sports", "business" ],
+    "char": "\ud83c\udfcc",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  ping_pong: {
+    keywords: [ "sports", "pingpong" ],
+    "char": "\ud83c\udfd3",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  badminton: {
+    keywords: [ "sports" ],
+    "char": "\ud83c\udff8",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  goal_net: {
+    keywords: [ "sports" ],
+    "char": "\ud83e\udd45",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  ice_hockey: {
+    keywords: [ "sports" ],
+    "char": "\ud83c\udfd2",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  field_hockey: {
+    keywords: [ "sports" ],
+    "char": "\ud83c\udfd1",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  cricket: {
+    keywords: [ "sports" ],
+    "char": "\ud83c\udfcf",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  ski: {
+    keywords: [ "sports", "winter", "cold", "snow" ],
+    "char": "\ud83c\udfbf",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  skier: {
+    keywords: [ "sports", "winter", "snow" ],
+    "char": "\u26f7",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  snowboarder: {
+    keywords: [ "sports", "winter" ],
+    "char": "\ud83c\udfc2",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  person_fencing: {
+    keywords: [ "sports", "fencing", "sword" ],
+    "char": "\ud83e\udd3a",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  women_wrestling: {
+    keywords: [ "sports", "wrestlers" ],
+    "char": "\ud83e\udd3c\u200d\u2640\ufe0f",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  men_wrestling: {
+    keywords: [ "sports", "wrestlers" ],
+    "char": "\ud83e\udd3c\u200d\u2642\ufe0f",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  woman_cartwheeling: {
+    keywords: [ "gymnastics" ],
+    "char": "\ud83e\udd38\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  man_cartwheeling: {
+    keywords: [ "gymnastics" ],
+    "char": "\ud83e\udd38\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  woman_playing_handball: {
+    keywords: [ "sports" ],
+    "char": "\ud83e\udd3e\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  man_playing_handball: {
+    keywords: [ "sports" ],
+    "char": "\ud83e\udd3e\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  ice_skate: {
+    keywords: [ "sports" ],
+    "char": "\u26f8",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  curling_stone: {
+    keywords: [ "sports" ],
+    "char": "\ud83e\udd4c",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  sled: {
+    keywords: [ "sleigh", "luge", "toboggan" ],
+    "char": "\ud83d\udef7",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  bow_and_arrow: {
+    keywords: [ "sports" ],
+    "char": "\ud83c\udff9",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  fishing_pole_and_fish: {
+    keywords: [ "food", "hobby", "summer" ],
+    "char": "\ud83c\udfa3",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  boxing_glove: {
+    keywords: [ "sports", "fighting" ],
+    "char": "\ud83e\udd4a",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  martial_arts_uniform: {
+    keywords: [ "judo", "karate", "taekwondo" ],
+    "char": "\ud83e\udd4b",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  rowing_woman: {
+    keywords: [ "sports", "hobby", "water", "ship", "woman", "female" ],
+    "char": "\ud83d\udea3\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  rowing_man: {
+    keywords: [ "sports", "hobby", "water", "ship" ],
+    "char": "\ud83d\udea3",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  climbing_woman: {
+    keywords: [ "sports", "hobby", "woman", "female", "rock" ],
+    "char": "\ud83e\uddd7\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  climbing_man: {
+    keywords: [ "sports", "hobby", "man", "male", "rock" ],
+    "char": "\ud83e\uddd7\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  swimming_woman: {
+    keywords: [ "sports", "exercise", "human", "athlete", "water", "summer", "woman", "female" ],
+    "char": "\ud83c\udfca\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  swimming_man: {
+    keywords: [ "sports", "exercise", "human", "athlete", "water", "summer" ],
+    "char": "\ud83c\udfca",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  woman_playing_water_polo: {
+    keywords: [ "sports", "pool" ],
+    "char": "\ud83e\udd3d\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  man_playing_water_polo: {
+    keywords: [ "sports", "pool" ],
+    "char": "\ud83e\udd3d\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  woman_in_lotus_position: {
+    keywords: [ "woman", "female", "meditation", "yoga", "serenity", "zen", "mindfulness" ],
+    "char": "\ud83e\uddd8\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  man_in_lotus_position: {
+    keywords: [ "man", "male", "meditation", "yoga", "serenity", "zen", "mindfulness" ],
+    "char": "\ud83e\uddd8\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  surfing_woman: {
+    keywords: [ "sports", "ocean", "sea", "summer", "beach", "woman", "female" ],
+    "char": "\ud83c\udfc4\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  surfing_man: {
+    keywords: [ "sports", "ocean", "sea", "summer", "beach" ],
+    "char": "\ud83c\udfc4",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  bath: {
+    keywords: [ "clean", "shower", "bathroom" ],
+    "char": "\ud83d\udec0",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  basketball_woman: {
+    keywords: [ "sports", "human", "woman", "female" ],
+    "char": "\u26f9\ufe0f\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  basketball_man: {
+    keywords: [ "sports", "human" ],
+    "char": "\u26f9",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  weight_lifting_woman: {
+    keywords: [ "sports", "training", "exercise", "woman", "female" ],
+    "char": "\ud83c\udfcb\ufe0f\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  weight_lifting_man: {
+    keywords: [ "sports", "training", "exercise" ],
+    "char": "\ud83c\udfcb",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  biking_woman: {
+    keywords: [ "sports", "bike", "exercise", "hipster", "woman", "female" ],
+    "char": "\ud83d\udeb4\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  biking_man: {
+    keywords: [ "sports", "bike", "exercise", "hipster" ],
+    "char": "\ud83d\udeb4",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  mountain_biking_woman: {
+    keywords: [ "transportation", "sports", "human", "race", "bike", "woman", "female" ],
+    "char": "\ud83d\udeb5\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  mountain_biking_man: {
+    keywords: [ "transportation", "sports", "human", "race", "bike" ],
+    "char": "\ud83d\udeb5",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  horse_racing: {
+    keywords: [ "animal", "betting", "competition", "gambling", "luck" ],
+    "char": "\ud83c\udfc7",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  business_suit_levitating: {
+    keywords: [ "suit", "business", "levitate", "hover", "jump" ],
+    "char": "\ud83d\udd74",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  trophy: {
+    keywords: [ "win", "award", "contest", "place", "ftw", "ceremony" ],
+    "char": "\ud83c\udfc6",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  running_shirt_with_sash: {
+    keywords: [ "play", "pageant" ],
+    "char": "\ud83c\udfbd",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  medal_sports: {
+    keywords: [ "award", "winning" ],
+    "char": "\ud83c\udfc5",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  medal_military: {
+    keywords: [ "award", "winning", "army" ],
+    "char": "\ud83c\udf96",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  "1st_place_medal": {
+    keywords: [ "award", "winning", "first" ],
+    "char": "\ud83e\udd47",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  "2nd_place_medal": {
+    keywords: [ "award", "second" ],
+    "char": "\ud83e\udd48",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  "3rd_place_medal": {
+    keywords: [ "award", "third" ],
+    "char": "\ud83e\udd49",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  reminder_ribbon: {
+    keywords: [ "sports", "cause", "support", "awareness" ],
+    "char": "\ud83c\udf97",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  rosette: {
+    keywords: [ "flower", "decoration", "military" ],
+    "char": "\ud83c\udff5",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  ticket: {
+    keywords: [ "event", "concert", "pass" ],
+    "char": "\ud83c\udfab",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  tickets: {
+    keywords: [ "sports", "concert", "entrance" ],
+    "char": "\ud83c\udf9f",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  performing_arts: {
+    keywords: [ "acting", "theater", "drama" ],
+    "char": "\ud83c\udfad",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  art: {
+    keywords: [ "design", "paint", "draw", "colors" ],
+    "char": "\ud83c\udfa8",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  circus_tent: {
+    keywords: [ "festival", "carnival", "party" ],
+    "char": "\ud83c\udfaa",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  woman_juggling: {
+    keywords: [ "juggle", "balance", "skill", "multitask" ],
+    "char": "\ud83e\udd39\u200d\u2640\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  man_juggling: {
+    keywords: [ "juggle", "balance", "skill", "multitask" ],
+    "char": "\ud83e\udd39\u200d\u2642\ufe0f",
+    fitzpatrick_scale: true,
+    category: "activity"
+  },
+  microphone: {
+    keywords: [ "sound", "music", "PA", "sing", "talkshow" ],
+    "char": "\ud83c\udfa4",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  headphones: {
+    keywords: [ "music", "score", "gadgets" ],
+    "char": "\ud83c\udfa7",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  musical_score: {
+    keywords: [ "treble", "clef", "compose" ],
+    "char": "\ud83c\udfbc",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  musical_keyboard: {
+    keywords: [ "piano", "instrument", "compose" ],
+    "char": "\ud83c\udfb9",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  drum: {
+    keywords: [ "music", "instrument", "drumsticks", "snare" ],
+    "char": "\ud83e\udd41",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  saxophone: {
+    keywords: [ "music", "instrument", "jazz", "blues" ],
+    "char": "\ud83c\udfb7",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  trumpet: {
+    keywords: [ "music", "brass" ],
+    "char": "\ud83c\udfba",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  guitar: {
+    keywords: [ "music", "instrument" ],
+    "char": "\ud83c\udfb8",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  violin: {
+    keywords: [ "music", "instrument", "orchestra", "symphony" ],
+    "char": "\ud83c\udfbb",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  clapper: {
+    keywords: [ "movie", "film", "record" ],
+    "char": "\ud83c\udfac",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  video_game: {
+    keywords: [ "play", "console", "PS4", "controller" ],
+    "char": "\ud83c\udfae",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  space_invader: {
+    keywords: [ "game", "arcade", "play" ],
+    "char": "\ud83d\udc7e",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  dart: {
+    keywords: [ "game", "play", "bar", "target", "bullseye" ],
+    "char": "\ud83c\udfaf",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  game_die: {
+    keywords: [ "dice", "random", "tabletop", "play", "luck" ],
+    "char": "\ud83c\udfb2",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  slot_machine: {
+    keywords: [ "bet", "gamble", "vegas", "fruit machine", "luck", "casino" ],
+    "char": "\ud83c\udfb0",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  bowling: {
+    keywords: [ "sports", "fun", "play" ],
+    "char": "\ud83c\udfb3",
+    fitzpatrick_scale: false,
+    category: "activity"
+  },
+  red_car: {
+    keywords: [ "red", "transportation", "vehicle" ],
+    "char": "\ud83d\ude97",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  taxi: {
+    keywords: [ "uber", "vehicle", "cars", "transportation" ],
+    "char": "\ud83d\ude95",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  blue_car: {
+    keywords: [ "transportation", "vehicle" ],
+    "char": "\ud83d\ude99",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  bus: {
+    keywords: [ "car", "vehicle", "transportation" ],
+    "char": "\ud83d\ude8c",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  trolleybus: {
+    keywords: [ "bart", "transportation", "vehicle" ],
+    "char": "\ud83d\ude8e",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  racing_car: {
+    keywords: [ "sports", "race", "fast", "formula", "f1" ],
+    "char": "\ud83c\udfce",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  police_car: {
+    keywords: [ "vehicle", "cars", "transportation", "law", "legal", "enforcement" ],
+    "char": "\ud83d\ude93",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  ambulance: {
+    keywords: [ "health", "911", "hospital" ],
+    "char": "\ud83d\ude91",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  fire_engine: {
+    keywords: [ "transportation", "cars", "vehicle" ],
+    "char": "\ud83d\ude92",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  minibus: {
+    keywords: [ "vehicle", "car", "transportation" ],
+    "char": "\ud83d\ude90",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  truck: {
+    keywords: [ "cars", "transportation" ],
+    "char": "\ud83d\ude9a",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  articulated_lorry: {
+    keywords: [ "vehicle", "cars", "transportation", "express" ],
+    "char": "\ud83d\ude9b",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  tractor: {
+    keywords: [ "vehicle", "car", "farming", "agriculture" ],
+    "char": "\ud83d\ude9c",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  kick_scooter: {
+    keywords: [ "vehicle", "kick", "razor" ],
+    "char": "\ud83d\udef4",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  motorcycle: {
+    keywords: [ "race", "sports", "fast" ],
+    "char": "\ud83c\udfcd",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  bike: {
+    keywords: [ "sports", "bicycle", "exercise", "hipster" ],
+    "char": "\ud83d\udeb2",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  motor_scooter: {
+    keywords: [ "vehicle", "vespa", "sasha" ],
+    "char": "\ud83d\udef5",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  rotating_light: {
+    keywords: [ "police", "ambulance", "911", "emergency", "alert", "error", "pinged", "law", "legal" ],
+    "char": "\ud83d\udea8",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  oncoming_police_car: {
+    keywords: [ "vehicle", "law", "legal", "enforcement", "911" ],
+    "char": "\ud83d\ude94",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  oncoming_bus: {
+    keywords: [ "vehicle", "transportation" ],
+    "char": "\ud83d\ude8d",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  oncoming_automobile: {
+    keywords: [ "car", "vehicle", "transportation" ],
+    "char": "\ud83d\ude98",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  oncoming_taxi: {
+    keywords: [ "vehicle", "cars", "uber" ],
+    "char": "\ud83d\ude96",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  aerial_tramway: {
+    keywords: [ "transportation", "vehicle", "ski" ],
+    "char": "\ud83d\udea1",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  mountain_cableway: {
+    keywords: [ "transportation", "vehicle", "ski" ],
+    "char": "\ud83d\udea0",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  suspension_railway: {
+    keywords: [ "vehicle", "transportation" ],
+    "char": "\ud83d\ude9f",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  railway_car: {
+    keywords: [ "transportation", "vehicle" ],
+    "char": "\ud83d\ude83",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  train: {
+    keywords: [ "transportation", "vehicle", "carriage", "public", "travel" ],
+    "char": "\ud83d\ude8b",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  monorail: {
+    keywords: [ "transportation", "vehicle" ],
+    "char": "\ud83d\ude9d",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  bullettrain_side: {
+    keywords: [ "transportation", "vehicle" ],
+    "char": "\ud83d\ude84",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  bullettrain_front: {
+    keywords: [ "transportation", "vehicle", "speed", "fast", "public", "travel" ],
+    "char": "\ud83d\ude85",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  light_rail: {
+    keywords: [ "transportation", "vehicle" ],
+    "char": "\ud83d\ude88",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  mountain_railway: {
+    keywords: [ "transportation", "vehicle" ],
+    "char": "\ud83d\ude9e",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  steam_locomotive: {
+    keywords: [ "transportation", "vehicle", "train" ],
+    "char": "\ud83d\ude82",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  train2: {
+    keywords: [ "transportation", "vehicle" ],
+    "char": "\ud83d\ude86",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  metro: {
+    keywords: [ "transportation", "blue-square", "mrt", "underground", "tube" ],
+    "char": "\ud83d\ude87",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  tram: {
+    keywords: [ "transportation", "vehicle" ],
+    "char": "\ud83d\ude8a",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  station: {
+    keywords: [ "transportation", "vehicle", "public" ],
+    "char": "\ud83d\ude89",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  flying_saucer: {
+    keywords: [ "transportation", "vehicle", "ufo" ],
+    "char": "\ud83d\udef8",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  helicopter: {
+    keywords: [ "transportation", "vehicle", "fly" ],
+    "char": "\ud83d\ude81",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  small_airplane: {
+    keywords: [ "flight", "transportation", "fly", "vehicle" ],
+    "char": "\ud83d\udee9",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  airplane: {
+    keywords: [ "vehicle", "transportation", "flight", "fly" ],
+    "char": "\u2708\ufe0f",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  flight_departure: {
+    keywords: [ "airport", "flight", "landing" ],
+    "char": "\ud83d\udeeb",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  flight_arrival: {
+    keywords: [ "airport", "flight", "boarding" ],
+    "char": "\ud83d\udeec",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  sailboat: {
+    keywords: [ "ship", "summer", "transportation", "water", "sailing" ],
+    "char": "\u26f5",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  motor_boat: {
+    keywords: [ "ship" ],
+    "char": "\ud83d\udee5",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  speedboat: {
+    keywords: [ "ship", "transportation", "vehicle", "summer" ],
+    "char": "\ud83d\udea4",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  ferry: {
+    keywords: [ "boat", "ship", "yacht" ],
+    "char": "\u26f4",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  passenger_ship: {
+    keywords: [ "yacht", "cruise", "ferry" ],
+    "char": "\ud83d\udef3",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  rocket: {
+    keywords: [ "launch", "ship", "staffmode", "NASA", "outer space", "outer_space", "fly" ],
+    "char": "\ud83d\ude80",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  artificial_satellite: {
+    keywords: [ "communication", "gps", "orbit", "spaceflight", "NASA", "ISS" ],
+    "char": "\ud83d\udef0",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  seat: {
+    keywords: [ "sit", "airplane", "transport", "bus", "flight", "fly" ],
+    "char": "\ud83d\udcba",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  canoe: {
+    keywords: [ "boat", "paddle", "water", "ship" ],
+    "char": "\ud83d\udef6",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  anchor: {
+    keywords: [ "ship", "ferry", "sea", "boat" ],
+    "char": "\u2693",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  construction: {
+    keywords: [ "wip", "progress", "caution", "warning" ],
+    "char": "\ud83d\udea7",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  fuelpump: {
+    keywords: [ "gas station", "petroleum" ],
+    "char": "\u26fd",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  busstop: {
+    keywords: [ "transportation", "wait" ],
+    "char": "\ud83d\ude8f",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  vertical_traffic_light: {
+    keywords: [ "transportation", "driving" ],
+    "char": "\ud83d\udea6",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  traffic_light: {
+    keywords: [ "transportation", "signal" ],
+    "char": "\ud83d\udea5",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  checkered_flag: {
+    keywords: [ "contest", "finishline", "race", "gokart" ],
+    "char": "\ud83c\udfc1",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  ship: {
+    keywords: [ "transportation", "titanic", "deploy" ],
+    "char": "\ud83d\udea2",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  ferris_wheel: {
+    keywords: [ "photo", "carnival", "londoneye" ],
+    "char": "\ud83c\udfa1",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  roller_coaster: {
+    keywords: [ "carnival", "playground", "photo", "fun" ],
+    "char": "\ud83c\udfa2",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  carousel_horse: {
+    keywords: [ "photo", "carnival" ],
+    "char": "\ud83c\udfa0",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  building_construction: {
+    keywords: [ "wip", "working", "progress" ],
+    "char": "\ud83c\udfd7",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  foggy: {
+    keywords: [ "photo", "mountain" ],
+    "char": "\ud83c\udf01",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  tokyo_tower: {
+    keywords: [ "photo", "japanese" ],
+    "char": "\ud83d\uddfc",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  factory: {
+    keywords: [ "building", "industry", "pollution", "smoke" ],
+    "char": "\ud83c\udfed",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  fountain: {
+    keywords: [ "photo", "summer", "water", "fresh" ],
+    "char": "\u26f2",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  rice_scene: {
+    keywords: [ "photo", "japan", "asia", "tsukimi" ],
+    "char": "\ud83c\udf91",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  mountain: {
+    keywords: [ "photo", "nature", "environment" ],
+    "char": "\u26f0",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  mountain_snow: {
+    keywords: [ "photo", "nature", "environment", "winter", "cold" ],
+    "char": "\ud83c\udfd4",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  mount_fuji: {
+    keywords: [ "photo", "mountain", "nature", "japanese" ],
+    "char": "\ud83d\uddfb",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  volcano: {
+    keywords: [ "photo", "nature", "disaster" ],
+    "char": "\ud83c\udf0b",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  japan: {
+    keywords: [ "nation", "country", "japanese", "asia" ],
+    "char": "\ud83d\uddfe",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  camping: {
+    keywords: [ "photo", "outdoors", "tent" ],
+    "char": "\ud83c\udfd5",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  tent: {
+    keywords: [ "photo", "camping", "outdoors" ],
+    "char": "\u26fa",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  national_park: {
+    keywords: [ "photo", "environment", "nature" ],
+    "char": "\ud83c\udfde",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  motorway: {
+    keywords: [ "road", "cupertino", "interstate", "highway" ],
+    "char": "\ud83d\udee3",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  railway_track: {
+    keywords: [ "train", "transportation" ],
+    "char": "\ud83d\udee4",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  sunrise: {
+    keywords: [ "morning", "view", "vacation", "photo" ],
+    "char": "\ud83c\udf05",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  sunrise_over_mountains: {
+    keywords: [ "view", "vacation", "photo" ],
+    "char": "\ud83c\udf04",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  desert: {
+    keywords: [ "photo", "warm", "saharah" ],
+    "char": "\ud83c\udfdc",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  beach_umbrella: {
+    keywords: [ "weather", "summer", "sunny", "sand", "mojito" ],
+    "char": "\ud83c\udfd6",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  desert_island: {
+    keywords: [ "photo", "tropical", "mojito" ],
+    "char": "\ud83c\udfdd",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  city_sunrise: {
+    keywords: [ "photo", "good morning", "dawn" ],
+    "char": "\ud83c\udf07",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  city_sunset: {
+    keywords: [ "photo", "evening", "sky", "buildings" ],
+    "char": "\ud83c\udf06",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  cityscape: {
+    keywords: [ "photo", "night life", "urban" ],
+    "char": "\ud83c\udfd9",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  night_with_stars: {
+    keywords: [ "evening", "city", "downtown" ],
+    "char": "\ud83c\udf03",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  bridge_at_night: {
+    keywords: [ "photo", "sanfrancisco" ],
+    "char": "\ud83c\udf09",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  milky_way: {
+    keywords: [ "photo", "space", "stars" ],
+    "char": "\ud83c\udf0c",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  stars: {
+    keywords: [ "night", "photo" ],
+    "char": "\ud83c\udf20",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  sparkler: {
+    keywords: [ "stars", "night", "shine" ],
+    "char": "\ud83c\udf87",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  fireworks: {
+    keywords: [ "photo", "festival", "carnival", "congratulations" ],
+    "char": "\ud83c\udf86",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  rainbow: {
+    keywords: [ "nature", "happy", "unicorn_face", "photo", "sky", "spring" ],
+    "char": "\ud83c\udf08",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  houses: {
+    keywords: [ "buildings", "photo" ],
+    "char": "\ud83c\udfd8",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  european_castle: {
+    keywords: [ "building", "royalty", "history" ],
+    "char": "\ud83c\udff0",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  japanese_castle: {
+    keywords: [ "photo", "building" ],
+    "char": "\ud83c\udfef",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  stadium: {
+    keywords: [ "photo", "place", "sports", "concert", "venue" ],
+    "char": "\ud83c\udfdf",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  statue_of_liberty: {
+    keywords: [ "american", "newyork" ],
+    "char": "\ud83d\uddfd",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  house: {
+    keywords: [ "building", "home" ],
+    "char": "\ud83c\udfe0",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  house_with_garden: {
+    keywords: [ "home", "plant", "nature" ],
+    "char": "\ud83c\udfe1",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  derelict_house: {
+    keywords: [ "abandon", "evict", "broken", "building" ],
+    "char": "\ud83c\udfda",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  office: {
+    keywords: [ "building", "bureau", "work" ],
+    "char": "\ud83c\udfe2",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  department_store: {
+    keywords: [ "building", "shopping", "mall" ],
+    "char": "\ud83c\udfec",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  post_office: {
+    keywords: [ "building", "envelope", "communication" ],
+    "char": "\ud83c\udfe3",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  european_post_office: {
+    keywords: [ "building", "email" ],
+    "char": "\ud83c\udfe4",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  hospital: {
+    keywords: [ "building", "health", "surgery", "doctor" ],
+    "char": "\ud83c\udfe5",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  bank: {
+    keywords: [ "building", "money", "sales", "cash", "business", "enterprise" ],
+    "char": "\ud83c\udfe6",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  hotel: {
+    keywords: [ "building", "accomodation", "checkin" ],
+    "char": "\ud83c\udfe8",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  convenience_store: {
+    keywords: [ "building", "shopping", "groceries" ],
+    "char": "\ud83c\udfea",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  school: {
+    keywords: [ "building", "student", "education", "learn", "teach" ],
+    "char": "\ud83c\udfeb",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  love_hotel: {
+    keywords: [ "like", "affection", "dating" ],
+    "char": "\ud83c\udfe9",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  wedding: {
+    keywords: [ "love", "like", "affection", "couple", "marriage", "bride", "groom" ],
+    "char": "\ud83d\udc92",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  classical_building: {
+    keywords: [ "art", "culture", "history" ],
+    "char": "\ud83c\udfdb",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  church: {
+    keywords: [ "building", "religion", "christ" ],
+    "char": "\u26ea",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  mosque: {
+    keywords: [ "islam", "worship", "minaret" ],
+    "char": "\ud83d\udd4c",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  synagogue: {
+    keywords: [ "judaism", "worship", "temple", "jewish" ],
+    "char": "\ud83d\udd4d",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  kaaba: {
+    keywords: [ "mecca", "mosque", "islam" ],
+    "char": "\ud83d\udd4b",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  shinto_shrine: {
+    keywords: [ "temple", "japan", "kyoto" ],
+    "char": "\u26e9",
+    fitzpatrick_scale: false,
+    category: "travel_and_places"
+  },
+  watch: {
+    keywords: [ "time", "accessories" ],
+    "char": "\u231a",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  iphone: {
+    keywords: [ "technology", "apple", "gadgets", "dial" ],
+    "char": "\ud83d\udcf1",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  calling: {
+    keywords: [ "iphone", "incoming" ],
+    "char": "\ud83d\udcf2",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  computer: {
+    keywords: [ "technology", "laptop", "screen", "display", "monitor" ],
+    "char": "\ud83d\udcbb",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  keyboard: {
+    keywords: [ "technology", "computer", "type", "input", "text" ],
+    "char": "\u2328",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  desktop_computer: {
+    keywords: [ "technology", "computing", "screen" ],
+    "char": "\ud83d\udda5",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  printer: {
+    keywords: [ "paper", "ink" ],
+    "char": "\ud83d\udda8",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  computer_mouse: {
+    keywords: [ "click" ],
+    "char": "\ud83d\uddb1",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  trackball: {
+    keywords: [ "technology", "trackpad" ],
+    "char": "\ud83d\uddb2",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  joystick: {
+    keywords: [ "game", "play" ],
+    "char": "\ud83d\udd79",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  clamp: {
+    keywords: [ "tool" ],
+    "char": "\ud83d\udddc",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  minidisc: {
+    keywords: [ "technology", "record", "data", "disk", "90s" ],
+    "char": "\ud83d\udcbd",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  floppy_disk: {
+    keywords: [ "oldschool", "technology", "save", "90s", "80s" ],
+    "char": "\ud83d\udcbe",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  cd: {
+    keywords: [ "technology", "dvd", "disk", "disc", "90s" ],
+    "char": "\ud83d\udcbf",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  dvd: {
+    keywords: [ "cd", "disk", "disc" ],
+    "char": "\ud83d\udcc0",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  vhs: {
+    keywords: [ "record", "video", "oldschool", "90s", "80s" ],
+    "char": "\ud83d\udcfc",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  camera: {
+    keywords: [ "gadgets", "photography" ],
+    "char": "\ud83d\udcf7",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  camera_flash: {
+    keywords: [ "photography", "gadgets" ],
+    "char": "\ud83d\udcf8",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  video_camera: {
+    keywords: [ "film", "record" ],
+    "char": "\ud83d\udcf9",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  movie_camera: {
+    keywords: [ "film", "record" ],
+    "char": "\ud83c\udfa5",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  film_projector: {
+    keywords: [ "video", "tape", "record", "movie" ],
+    "char": "\ud83d\udcfd",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  film_strip: {
+    keywords: [ "movie" ],
+    "char": "\ud83c\udf9e",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  telephone_receiver: {
+    keywords: [ "technology", "communication", "dial" ],
+    "char": "\ud83d\udcde",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  phone: {
+    keywords: [ "technology", "communication", "dial", "telephone" ],
+    "char": "\u260e\ufe0f",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  pager: {
+    keywords: [ "bbcall", "oldschool", "90s" ],
+    "char": "\ud83d\udcdf",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  fax: {
+    keywords: [ "communication", "technology" ],
+    "char": "\ud83d\udce0",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  tv: {
+    keywords: [ "technology", "program", "oldschool", "show", "television" ],
+    "char": "\ud83d\udcfa",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  radio: {
+    keywords: [ "communication", "music", "podcast", "program" ],
+    "char": "\ud83d\udcfb",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  studio_microphone: {
+    keywords: [ "sing", "recording", "artist", "talkshow" ],
+    "char": "\ud83c\udf99",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  level_slider: {
+    keywords: [ "scale" ],
+    "char": "\ud83c\udf9a",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  control_knobs: {
+    keywords: [ "dial" ],
+    "char": "\ud83c\udf9b",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  stopwatch: {
+    keywords: [ "time", "deadline" ],
+    "char": "\u23f1",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  timer_clock: {
+    keywords: [ "alarm" ],
+    "char": "\u23f2",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  alarm_clock: {
+    keywords: [ "time", "wake" ],
+    "char": "\u23f0",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  mantelpiece_clock: {
+    keywords: [ "time" ],
+    "char": "\ud83d\udd70",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  hourglass_flowing_sand: {
+    keywords: [ "oldschool", "time", "countdown" ],
+    "char": "\u23f3",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  hourglass: {
+    keywords: [ "time", "clock", "oldschool", "limit", "exam", "quiz", "test" ],
+    "char": "\u231b",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  satellite: {
+    keywords: [ "communication", "future", "radio", "space" ],
+    "char": "\ud83d\udce1",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  battery: {
+    keywords: [ "power", "energy", "sustain" ],
+    "char": "\ud83d\udd0b",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  electric_plug: {
+    keywords: [ "charger", "power" ],
+    "char": "\ud83d\udd0c",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  bulb: {
+    keywords: [ "light", "electricity", "idea" ],
+    "char": "\ud83d\udca1",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  flashlight: {
+    keywords: [ "dark", "camping", "sight", "night" ],
+    "char": "\ud83d\udd26",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  candle: {
+    keywords: [ "fire", "wax" ],
+    "char": "\ud83d\udd6f",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  wastebasket: {
+    keywords: [ "bin", "trash", "rubbish", "garbage", "toss" ],
+    "char": "\ud83d\uddd1",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  oil_drum: {
+    keywords: [ "barrell" ],
+    "char": "\ud83d\udee2",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  money_with_wings: {
+    keywords: [ "dollar", "bills", "payment", "sale" ],
+    "char": "\ud83d\udcb8",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  dollar: {
+    keywords: [ "money", "sales", "bill", "currency" ],
+    "char": "\ud83d\udcb5",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  yen: {
+    keywords: [ "money", "sales", "japanese", "dollar", "currency" ],
+    "char": "\ud83d\udcb4",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  euro: {
+    keywords: [ "money", "sales", "dollar", "currency" ],
+    "char": "\ud83d\udcb6",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  pound: {
+    keywords: [ "british", "sterling", "money", "sales", "bills", "uk", "england", "currency" ],
+    "char": "\ud83d\udcb7",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  moneybag: {
+    keywords: [ "dollar", "payment", "coins", "sale" ],
+    "char": "\ud83d\udcb0",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  credit_card: {
+    keywords: [ "money", "sales", "dollar", "bill", "payment", "shopping" ],
+    "char": "\ud83d\udcb3",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  gem: {
+    keywords: [ "blue", "ruby", "diamond", "jewelry" ],
+    "char": "\ud83d\udc8e",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  balance_scale: {
+    keywords: [ "law", "fairness", "weight" ],
+    "char": "\u2696",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  wrench: {
+    keywords: [ "tools", "diy", "ikea", "fix", "maintainer" ],
+    "char": "\ud83d\udd27",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  hammer: {
+    keywords: [ "tools", "build", "create" ],
+    "char": "\ud83d\udd28",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  hammer_and_pick: {
+    keywords: [ "tools", "build", "create" ],
+    "char": "\u2692",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  hammer_and_wrench: {
+    keywords: [ "tools", "build", "create" ],
+    "char": "\ud83d\udee0",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  pick: {
+    keywords: [ "tools", "dig" ],
+    "char": "\u26cf",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  nut_and_bolt: {
+    keywords: [ "handy", "tools", "fix" ],
+    "char": "\ud83d\udd29",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  gear: {
+    keywords: [ "cog" ],
+    "char": "\u2699",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  chains: {
+    keywords: [ "lock", "arrest" ],
+    "char": "\u26d3",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  gun: {
+    keywords: [ "violence", "weapon", "pistol", "revolver" ],
+    "char": "\ud83d\udd2b",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  bomb: {
+    keywords: [ "boom", "explode", "explosion", "terrorism" ],
+    "char": "\ud83d\udca3",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  hocho: {
+    keywords: [ "knife", "blade", "cutlery", "kitchen", "weapon" ],
+    "char": "\ud83d\udd2a",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  dagger: {
+    keywords: [ "weapon" ],
+    "char": "\ud83d\udde1",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  crossed_swords: {
+    keywords: [ "weapon" ],
+    "char": "\u2694",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  shield: {
+    keywords: [ "protection", "security" ],
+    "char": "\ud83d\udee1",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  smoking: {
+    keywords: [ "kills", "tobacco", "cigarette", "joint", "smoke" ],
+    "char": "\ud83d\udeac",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  skull_and_crossbones: {
+    keywords: [ "poison", "danger", "deadly", "scary", "death", "pirate", "evil" ],
+    "char": "\u2620",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  coffin: {
+    keywords: [ "vampire", "dead", "die", "death", "rip", "graveyard", "cemetery", "casket", "funeral", "box" ],
+    "char": "\u26b0",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  funeral_urn: {
+    keywords: [ "dead", "die", "death", "rip", "ashes" ],
+    "char": "\u26b1",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  amphora: {
+    keywords: [ "vase", "jar" ],
+    "char": "\ud83c\udffa",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  crystal_ball: {
+    keywords: [ "disco", "party", "magic", "circus", "fortune_teller" ],
+    "char": "\ud83d\udd2e",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  prayer_beads: {
+    keywords: [ "dhikr", "religious" ],
+    "char": "\ud83d\udcff",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  barber: {
+    keywords: [ "hair", "salon", "style" ],
+    "char": "\ud83d\udc88",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  alembic: {
+    keywords: [ "distilling", "science", "experiment", "chemistry" ],
+    "char": "\u2697",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  telescope: {
+    keywords: [ "stars", "space", "zoom", "science", "astronomy" ],
+    "char": "\ud83d\udd2d",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  microscope: {
+    keywords: [ "laboratory", "experiment", "zoomin", "science", "study" ],
+    "char": "\ud83d\udd2c",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  hole: {
+    keywords: [ "embarrassing" ],
+    "char": "\ud83d\udd73",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  pill: {
+    keywords: [ "health", "medicine", "doctor", "pharmacy", "drug" ],
+    "char": "\ud83d\udc8a",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  syringe: {
+    keywords: [ "health", "hospital", "drugs", "blood", "medicine", "needle", "doctor", "nurse" ],
+    "char": "\ud83d\udc89",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  thermometer: {
+    keywords: [ "weather", "temperature", "hot", "cold" ],
+    "char": "\ud83c\udf21",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  label: {
+    keywords: [ "sale", "tag" ],
+    "char": "\ud83c\udff7",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  bookmark: {
+    keywords: [ "favorite", "label", "save" ],
+    "char": "\ud83d\udd16",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  toilet: {
+    keywords: [ "restroom", "wc", "washroom", "bathroom", "potty" ],
+    "char": "\ud83d\udebd",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  shower: {
+    keywords: [ "clean", "water", "bathroom" ],
+    "char": "\ud83d\udebf",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  bathtub: {
+    keywords: [ "clean", "shower", "bathroom" ],
+    "char": "\ud83d\udec1",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  key: {
+    keywords: [ "lock", "door", "password" ],
+    "char": "\ud83d\udd11",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  old_key: {
+    keywords: [ "lock", "door", "password" ],
+    "char": "\ud83d\udddd",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  couch_and_lamp: {
+    keywords: [ "read", "chill" ],
+    "char": "\ud83d\udecb",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  sleeping_bed: {
+    keywords: [ "bed", "rest" ],
+    "char": "\ud83d\udecc",
+    fitzpatrick_scale: true,
+    category: "objects"
+  },
+  bed: {
+    keywords: [ "sleep", "rest" ],
+    "char": "\ud83d\udecf",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  door: {
+    keywords: [ "house", "entry", "exit" ],
+    "char": "\ud83d\udeaa",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  bellhop_bell: {
+    keywords: [ "service" ],
+    "char": "\ud83d\udece",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  framed_picture: {
+    keywords: [ "photography" ],
+    "char": "\ud83d\uddbc",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  world_map: {
+    keywords: [ "location", "direction" ],
+    "char": "\ud83d\uddfa",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  parasol_on_ground: {
+    keywords: [ "weather", "summer" ],
+    "char": "\u26f1",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  moyai: {
+    keywords: [ "rock", "easter island", "moai" ],
+    "char": "\ud83d\uddff",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  shopping: {
+    keywords: [ "mall", "buy", "purchase" ],
+    "char": "\ud83d\udecd",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  shopping_cart: {
+    keywords: [ "trolley" ],
+    "char": "\ud83d\uded2",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  balloon: {
+    keywords: [ "party", "celebration", "birthday", "circus" ],
+    "char": "\ud83c\udf88",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  flags: {
+    keywords: [ "fish", "japanese", "koinobori", "carp", "banner" ],
+    "char": "\ud83c\udf8f",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  ribbon: {
+    keywords: [ "decoration", "pink", "girl", "bowtie" ],
+    "char": "\ud83c\udf80",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  gift: {
+    keywords: [ "present", "birthday", "christmas", "xmas" ],
+    "char": "\ud83c\udf81",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  confetti_ball: {
+    keywords: [ "festival", "party", "birthday", "circus" ],
+    "char": "\ud83c\udf8a",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  tada: {
+    keywords: [ "party", "congratulations", "birthday", "magic", "circus", "celebration" ],
+    "char": "\ud83c\udf89",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  dolls: {
+    keywords: [ "japanese", "toy", "kimono" ],
+    "char": "\ud83c\udf8e",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  wind_chime: {
+    keywords: [ "nature", "ding", "spring", "bell" ],
+    "char": "\ud83c\udf90",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  crossed_flags: {
+    keywords: [ "japanese", "nation", "country", "border" ],
+    "char": "\ud83c\udf8c",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  izakaya_lantern: {
+    keywords: [ "light", "paper", "halloween", "spooky" ],
+    "char": "\ud83c\udfee",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  email: {
+    keywords: [ "letter", "postal", "inbox", "communication" ],
+    "char": "\u2709\ufe0f",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  envelope_with_arrow: {
+    keywords: [ "email", "communication" ],
+    "char": "\ud83d\udce9",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  incoming_envelope: {
+    keywords: [ "email", "inbox" ],
+    "char": "\ud83d\udce8",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  "e-mail": {
+    keywords: [ "communication", "inbox" ],
+    "char": "\ud83d\udce7",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  love_letter: {
+    keywords: [ "email", "like", "affection", "envelope", "valentines" ],
+    "char": "\ud83d\udc8c",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  postbox: {
+    keywords: [ "email", "letter", "envelope" ],
+    "char": "\ud83d\udcee",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  mailbox_closed: {
+    keywords: [ "email", "communication", "inbox" ],
+    "char": "\ud83d\udcea",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  mailbox: {
+    keywords: [ "email", "inbox", "communication" ],
+    "char": "\ud83d\udceb",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  mailbox_with_mail: {
+    keywords: [ "email", "inbox", "communication" ],
+    "char": "\ud83d\udcec",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  mailbox_with_no_mail: {
+    keywords: [ "email", "inbox" ],
+    "char": "\ud83d\udced",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  "package": {
+    keywords: [ "mail", "gift", "cardboard", "box", "moving" ],
+    "char": "\ud83d\udce6",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  postal_horn: {
+    keywords: [ "instrument", "music" ],
+    "char": "\ud83d\udcef",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  inbox_tray: {
+    keywords: [ "email", "documents" ],
+    "char": "\ud83d\udce5",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  outbox_tray: {
+    keywords: [ "inbox", "email" ],
+    "char": "\ud83d\udce4",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  scroll: {
+    keywords: [ "documents", "ancient", "history", "paper" ],
+    "char": "\ud83d\udcdc",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  page_with_curl: {
+    keywords: [ "documents", "office", "paper" ],
+    "char": "\ud83d\udcc3",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  bookmark_tabs: {
+    keywords: [ "favorite", "save", "order", "tidy" ],
+    "char": "\ud83d\udcd1",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  bar_chart: {
+    keywords: [ "graph", "presentation", "stats" ],
+    "char": "\ud83d\udcca",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  chart_with_upwards_trend: {
+    keywords: [ "graph", "presentation", "stats", "recovery", "business", "economics", "money", "sales", "good", "success" ],
+    "char": "\ud83d\udcc8",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  chart_with_downwards_trend: {
+    keywords: [ "graph", "presentation", "stats", "recession", "business", "economics", "money", "sales", "bad", "failure" ],
+    "char": "\ud83d\udcc9",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  page_facing_up: {
+    keywords: [ "documents", "office", "paper", "information" ],
+    "char": "\ud83d\udcc4",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  date: {
+    keywords: [ "calendar", "schedule" ],
+    "char": "\ud83d\udcc5",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  calendar: {
+    keywords: [ "schedule", "date", "planning" ],
+    "char": "\ud83d\udcc6",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  spiral_calendar: {
+    keywords: [ "date", "schedule", "planning" ],
+    "char": "\ud83d\uddd3",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  card_index: {
+    keywords: [ "business", "stationery" ],
+    "char": "\ud83d\udcc7",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  card_file_box: {
+    keywords: [ "business", "stationery" ],
+    "char": "\ud83d\uddc3",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  ballot_box: {
+    keywords: [ "election", "vote" ],
+    "char": "\ud83d\uddf3",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  file_cabinet: {
+    keywords: [ "filing", "organizing" ],
+    "char": "\ud83d\uddc4",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  clipboard: {
+    keywords: [ "stationery", "documents" ],
+    "char": "\ud83d\udccb",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  spiral_notepad: {
+    keywords: [ "memo", "stationery" ],
+    "char": "\ud83d\uddd2",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  file_folder: {
+    keywords: [ "documents", "business", "office" ],
+    "char": "\ud83d\udcc1",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  open_file_folder: {
+    keywords: [ "documents", "load" ],
+    "char": "\ud83d\udcc2",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  card_index_dividers: {
+    keywords: [ "organizing", "business", "stationery" ],
+    "char": "\ud83d\uddc2",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  newspaper_roll: {
+    keywords: [ "press", "headline" ],
+    "char": "\ud83d\uddde",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  newspaper: {
+    keywords: [ "press", "headline" ],
+    "char": "\ud83d\udcf0",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  notebook: {
+    keywords: [ "stationery", "record", "notes", "paper", "study" ],
+    "char": "\ud83d\udcd3",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  closed_book: {
+    keywords: [ "read", "library", "knowledge", "textbook", "learn" ],
+    "char": "\ud83d\udcd5",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  green_book: {
+    keywords: [ "read", "library", "knowledge", "study" ],
+    "char": "\ud83d\udcd7",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  blue_book: {
+    keywords: [ "read", "library", "knowledge", "learn", "study" ],
+    "char": "\ud83d\udcd8",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  orange_book: {
+    keywords: [ "read", "library", "knowledge", "textbook", "study" ],
+    "char": "\ud83d\udcd9",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  notebook_with_decorative_cover: {
+    keywords: [ "classroom", "notes", "record", "paper", "study" ],
+    "char": "\ud83d\udcd4",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  ledger: {
+    keywords: [ "notes", "paper" ],
+    "char": "\ud83d\udcd2",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  books: {
+    keywords: [ "literature", "library", "study" ],
+    "char": "\ud83d\udcda",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  open_book: {
+    keywords: [ "book", "read", "library", "knowledge", "literature", "learn", "study" ],
+    "char": "\ud83d\udcd6",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  link: {
+    keywords: [ "rings", "url" ],
+    "char": "\ud83d\udd17",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  paperclip: {
+    keywords: [ "documents", "stationery" ],
+    "char": "\ud83d\udcce",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  paperclips: {
+    keywords: [ "documents", "stationery" ],
+    "char": "\ud83d\udd87",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  scissors: {
+    keywords: [ "stationery", "cut" ],
+    "char": "\u2702\ufe0f",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  triangular_ruler: {
+    keywords: [ "stationery", "math", "architect", "sketch" ],
+    "char": "\ud83d\udcd0",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  straight_ruler: {
+    keywords: [ "stationery", "calculate", "length", "math", "school", "drawing", "architect", "sketch" ],
+    "char": "\ud83d\udccf",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  pushpin: {
+    keywords: [ "stationery", "mark", "here" ],
+    "char": "\ud83d\udccc",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  round_pushpin: {
+    keywords: [ "stationery", "location", "map", "here" ],
+    "char": "\ud83d\udccd",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  triangular_flag_on_post: {
+    keywords: [ "mark", "milestone", "place" ],
+    "char": "\ud83d\udea9",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  white_flag: {
+    keywords: [ "losing", "loser", "lost", "surrender", "give up", "fail" ],
+    "char": "\ud83c\udff3",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  black_flag: {
+    keywords: [ "pirate" ],
+    "char": "\ud83c\udff4",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  rainbow_flag: {
+    keywords: [ "flag", "rainbow", "pride", "gay", "lgbt", "glbt", "queer", "homosexual", "lesbian", "bisexual", "transgender" ],
+    "char": "\ud83c\udff3\ufe0f\u200d\ud83c\udf08",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  closed_lock_with_key: {
+    keywords: [ "security", "privacy" ],
+    "char": "\ud83d\udd10",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  lock: {
+    keywords: [ "security", "password", "padlock" ],
+    "char": "\ud83d\udd12",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  unlock: {
+    keywords: [ "privacy", "security" ],
+    "char": "\ud83d\udd13",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  lock_with_ink_pen: {
+    keywords: [ "security", "secret" ],
+    "char": "\ud83d\udd0f",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  pen: {
+    keywords: [ "stationery", "writing", "write" ],
+    "char": "\ud83d\udd8a",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  fountain_pen: {
+    keywords: [ "stationery", "writing", "write" ],
+    "char": "\ud83d\udd8b",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  black_nib: {
+    keywords: [ "pen", "stationery", "writing", "write" ],
+    "char": "\u2712\ufe0f",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  memo: {
+    keywords: [ "write", "documents", "stationery", "pencil", "paper", "writing", "legal", "exam", "quiz", "test", "study", "compose" ],
+    "char": "\ud83d\udcdd",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  pencil2: {
+    keywords: [ "stationery", "write", "paper", "writing", "school", "study" ],
+    "char": "\u270f\ufe0f",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  crayon: {
+    keywords: [ "drawing", "creativity" ],
+    "char": "\ud83d\udd8d",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  paintbrush: {
+    keywords: [ "drawing", "creativity", "art" ],
+    "char": "\ud83d\udd8c",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  mag: {
+    keywords: [ "search", "zoom", "find", "detective" ],
+    "char": "\ud83d\udd0d",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  mag_right: {
+    keywords: [ "search", "zoom", "find", "detective" ],
+    "char": "\ud83d\udd0e",
+    fitzpatrick_scale: false,
+    category: "objects"
+  },
+  heart: {
+    keywords: [ "love", "like", "valentines" ],
+    "char": "\u2764\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  orange_heart: {
+    keywords: [ "love", "like", "affection", "valentines" ],
+    "char": "\ud83e\udde1",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  yellow_heart: {
+    keywords: [ "love", "like", "affection", "valentines" ],
+    "char": "\ud83d\udc9b",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  green_heart: {
+    keywords: [ "love", "like", "affection", "valentines" ],
+    "char": "\ud83d\udc9a",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  blue_heart: {
+    keywords: [ "love", "like", "affection", "valentines" ],
+    "char": "\ud83d\udc99",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  purple_heart: {
+    keywords: [ "love", "like", "affection", "valentines" ],
+    "char": "\ud83d\udc9c",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  black_heart: {
+    keywords: [ "evil" ],
+    "char": "\ud83d\udda4",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  broken_heart: {
+    keywords: [ "sad", "sorry", "break", "heart", "heartbreak" ],
+    "char": "\ud83d\udc94",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  heavy_heart_exclamation: {
+    keywords: [ "decoration", "love" ],
+    "char": "\u2763",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  two_hearts: {
+    keywords: [ "love", "like", "affection", "valentines", "heart" ],
+    "char": "\ud83d\udc95",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  revolving_hearts: {
+    keywords: [ "love", "like", "affection", "valentines" ],
+    "char": "\ud83d\udc9e",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  heartbeat: {
+    keywords: [ "love", "like", "affection", "valentines", "pink", "heart" ],
+    "char": "\ud83d\udc93",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  heartpulse: {
+    keywords: [ "like", "love", "affection", "valentines", "pink" ],
+    "char": "\ud83d\udc97",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  sparkling_heart: {
+    keywords: [ "love", "like", "affection", "valentines" ],
+    "char": "\ud83d\udc96",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  cupid: {
+    keywords: [ "love", "like", "heart", "affection", "valentines" ],
+    "char": "\ud83d\udc98",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  gift_heart: {
+    keywords: [ "love", "valentines" ],
+    "char": "\ud83d\udc9d",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  heart_decoration: {
+    keywords: [ "purple-square", "love", "like" ],
+    "char": "\ud83d\udc9f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  peace_symbol: {
+    keywords: [ "hippie" ],
+    "char": "\u262e",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  latin_cross: {
+    keywords: [ "christianity" ],
+    "char": "\u271d",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  star_and_crescent: {
+    keywords: [ "islam" ],
+    "char": "\u262a",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  om: {
+    keywords: [ "hinduism", "buddhism", "sikhism", "jainism" ],
+    "char": "\ud83d\udd49",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  wheel_of_dharma: {
+    keywords: [ "hinduism", "buddhism", "sikhism", "jainism" ],
+    "char": "\u2638",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  star_of_david: {
+    keywords: [ "judaism" ],
+    "char": "\u2721",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  six_pointed_star: {
+    keywords: [ "purple-square", "religion", "jewish", "hexagram" ],
+    "char": "\ud83d\udd2f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  menorah: {
+    keywords: [ "hanukkah", "candles", "jewish" ],
+    "char": "\ud83d\udd4e",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  yin_yang: {
+    keywords: [ "balance" ],
+    "char": "\u262f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  orthodox_cross: {
+    keywords: [ "suppedaneum", "religion" ],
+    "char": "\u2626",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  place_of_worship: {
+    keywords: [ "religion", "church", "temple", "prayer" ],
+    "char": "\ud83d\uded0",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  ophiuchus: {
+    keywords: [ "sign", "purple-square", "constellation", "astrology" ],
+    "char": "\u26ce",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  aries: {
+    keywords: [ "sign", "purple-square", "zodiac", "astrology" ],
+    "char": "\u2648",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  taurus: {
+    keywords: [ "purple-square", "sign", "zodiac", "astrology" ],
+    "char": "\u2649",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  gemini: {
+    keywords: [ "sign", "zodiac", "purple-square", "astrology" ],
+    "char": "\u264a",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  cancer: {
+    keywords: [ "sign", "zodiac", "purple-square", "astrology" ],
+    "char": "\u264b",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  leo: {
+    keywords: [ "sign", "purple-square", "zodiac", "astrology" ],
+    "char": "\u264c",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  virgo: {
+    keywords: [ "sign", "zodiac", "purple-square", "astrology" ],
+    "char": "\u264d",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  libra: {
+    keywords: [ "sign", "purple-square", "zodiac", "astrology" ],
+    "char": "\u264e",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  scorpius: {
+    keywords: [ "sign", "zodiac", "purple-square", "astrology", "scorpio" ],
+    "char": "\u264f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  sagittarius: {
+    keywords: [ "sign", "zodiac", "purple-square", "astrology" ],
+    "char": "\u2650",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  capricorn: {
+    keywords: [ "sign", "zodiac", "purple-square", "astrology" ],
+    "char": "\u2651",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  aquarius: {
+    keywords: [ "sign", "purple-square", "zodiac", "astrology" ],
+    "char": "\u2652",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  pisces: {
+    keywords: [ "purple-square", "sign", "zodiac", "astrology" ],
+    "char": "\u2653",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  id: {
+    keywords: [ "purple-square", "words" ],
+    "char": "\ud83c\udd94",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  atom_symbol: {
+    keywords: [ "science", "physics", "chemistry" ],
+    "char": "\u269b",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  u7a7a: {
+    keywords: [ "kanji", "japanese", "chinese", "empty", "sky", "blue-square" ],
+    "char": "\ud83c\ude33",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  u5272: {
+    keywords: [ "cut", "divide", "chinese", "kanji", "pink-square" ],
+    "char": "\ud83c\ude39",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  radioactive: {
+    keywords: [ "nuclear", "danger" ],
+    "char": "\u2622",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  biohazard: {
+    keywords: [ "danger" ],
+    "char": "\u2623",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  mobile_phone_off: {
+    keywords: [ "mute", "orange-square", "silence", "quiet" ],
+    "char": "\ud83d\udcf4",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  vibration_mode: {
+    keywords: [ "orange-square", "phone" ],
+    "char": "\ud83d\udcf3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  u6709: {
+    keywords: [ "orange-square", "chinese", "have", "kanji" ],
+    "char": "\ud83c\ude36",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  u7121: {
+    keywords: [ "nothing", "chinese", "kanji", "japanese", "orange-square" ],
+    "char": "\ud83c\ude1a",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  u7533: {
+    keywords: [ "chinese", "japanese", "kanji", "orange-square" ],
+    "char": "\ud83c\ude38",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  u55b6: {
+    keywords: [ "japanese", "opening hours", "orange-square" ],
+    "char": "\ud83c\ude3a",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  u6708: {
+    keywords: [ "chinese", "month", "moon", "japanese", "orange-square", "kanji" ],
+    "char": "\ud83c\ude37\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  eight_pointed_black_star: {
+    keywords: [ "orange-square", "shape", "polygon" ],
+    "char": "\u2734\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  vs: {
+    keywords: [ "words", "orange-square" ],
+    "char": "\ud83c\udd9a",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  accept: {
+    keywords: [ "ok", "good", "chinese", "kanji", "agree", "yes", "orange-circle" ],
+    "char": "\ud83c\ude51",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  white_flower: {
+    keywords: [ "japanese", "spring" ],
+    "char": "\ud83d\udcae",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  ideograph_advantage: {
+    keywords: [ "chinese", "kanji", "obtain", "get", "circle" ],
+    "char": "\ud83c\ude50",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  secret: {
+    keywords: [ "privacy", "chinese", "sshh", "kanji", "red-circle" ],
+    "char": "\u3299\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  congratulations: {
+    keywords: [ "chinese", "kanji", "japanese", "red-circle" ],
+    "char": "\u3297\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  u5408: {
+    keywords: [ "japanese", "chinese", "join", "kanji", "red-square" ],
+    "char": "\ud83c\ude34",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  u6e80: {
+    keywords: [ "full", "chinese", "japanese", "red-square", "kanji" ],
+    "char": "\ud83c\ude35",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  u7981: {
+    keywords: [ "kanji", "japanese", "chinese", "forbidden", "limit", "restricted", "red-square" ],
+    "char": "\ud83c\ude32",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  a: {
+    keywords: [ "red-square", "alphabet", "letter" ],
+    "char": "\ud83c\udd70\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  b: {
+    keywords: [ "red-square", "alphabet", "letter" ],
+    "char": "\ud83c\udd71\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  ab: {
+    keywords: [ "red-square", "alphabet" ],
+    "char": "\ud83c\udd8e",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  cl: {
+    keywords: [ "alphabet", "words", "red-square" ],
+    "char": "\ud83c\udd91",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  o2: {
+    keywords: [ "alphabet", "red-square", "letter" ],
+    "char": "\ud83c\udd7e\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  sos: {
+    keywords: [ "help", "red-square", "words", "emergency", "911" ],
+    "char": "\ud83c\udd98",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  no_entry: {
+    keywords: [ "limit", "security", "privacy", "bad", "denied", "stop", "circle" ],
+    "char": "\u26d4",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  name_badge: {
+    keywords: [ "fire", "forbid" ],
+    "char": "\ud83d\udcdb",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  no_entry_sign: {
+    keywords: [ "forbid", "stop", "limit", "denied", "disallow", "circle" ],
+    "char": "\ud83d\udeab",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  x: {
+    keywords: [ "no", "delete", "remove", "cancel" ],
+    "char": "\u274c",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  o: {
+    keywords: [ "circle", "round" ],
+    "char": "\u2b55",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  stop_sign: {
+    keywords: [ "stop" ],
+    "char": "\ud83d\uded1",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  anger: {
+    keywords: [ "angry", "mad" ],
+    "char": "\ud83d\udca2",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  hotsprings: {
+    keywords: [ "bath", "warm", "relax" ],
+    "char": "\u2668\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  no_pedestrians: {
+    keywords: [ "rules", "crossing", "walking", "circle" ],
+    "char": "\ud83d\udeb7",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  do_not_litter: {
+    keywords: [ "trash", "bin", "garbage", "circle" ],
+    "char": "\ud83d\udeaf",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  no_bicycles: {
+    keywords: [ "cyclist", "prohibited", "circle" ],
+    "char": "\ud83d\udeb3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  "non-potable_water": {
+    keywords: [ "drink", "faucet", "tap", "circle" ],
+    "char": "\ud83d\udeb1",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  underage: {
+    keywords: [ "18", "drink", "pub", "night", "minor", "circle" ],
+    "char": "\ud83d\udd1e",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  no_mobile_phones: {
+    keywords: [ "iphone", "mute", "circle" ],
+    "char": "\ud83d\udcf5",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  exclamation: {
+    keywords: [ "heavy_exclamation_mark", "danger", "surprise", "punctuation", "wow", "warning" ],
+    "char": "\u2757",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  grey_exclamation: {
+    keywords: [ "surprise", "punctuation", "gray", "wow", "warning" ],
+    "char": "\u2755",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  question: {
+    keywords: [ "doubt", "confused" ],
+    "char": "\u2753",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  grey_question: {
+    keywords: [ "doubts", "gray", "huh", "confused" ],
+    "char": "\u2754",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  bangbang: {
+    keywords: [ "exclamation", "surprise" ],
+    "char": "\u203c\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  interrobang: {
+    keywords: [ "wat", "punctuation", "surprise" ],
+    "char": "\u2049\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  100: {
+    keywords: [ "score", "perfect", "numbers", "century", "exam", "quiz", "test", "pass", "hundred" ],
+    "char": "\ud83d\udcaf",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  low_brightness: {
+    keywords: [ "sun", "afternoon", "warm", "summer" ],
+    "char": "\ud83d\udd05",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  high_brightness: {
+    keywords: [ "sun", "light" ],
+    "char": "\ud83d\udd06",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  trident: {
+    keywords: [ "weapon", "spear" ],
+    "char": "\ud83d\udd31",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  fleur_de_lis: {
+    keywords: [ "decorative", "scout" ],
+    "char": "\u269c",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  part_alternation_mark: {
+    keywords: [ "graph", "presentation", "stats", "business", "economics", "bad" ],
+    "char": "\u303d\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  warning: {
+    keywords: [ "exclamation", "wip", "alert", "error", "problem", "issue" ],
+    "char": "\u26a0\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  children_crossing: {
+    keywords: [ "school", "warning", "danger", "sign", "driving", "yellow-diamond" ],
+    "char": "\ud83d\udeb8",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  beginner: {
+    keywords: [ "badge", "shield" ],
+    "char": "\ud83d\udd30",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  recycle: {
+    keywords: [ "arrow", "environment", "garbage", "trash" ],
+    "char": "\u267b\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  u6307: {
+    keywords: [ "chinese", "point", "green-square", "kanji" ],
+    "char": "\ud83c\ude2f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  chart: {
+    keywords: [ "green-square", "graph", "presentation", "stats" ],
+    "char": "\ud83d\udcb9",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  sparkle: {
+    keywords: [ "stars", "green-square", "awesome", "good", "fireworks" ],
+    "char": "\u2747\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  eight_spoked_asterisk: {
+    keywords: [ "star", "sparkle", "green-square" ],
+    "char": "\u2733\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  negative_squared_cross_mark: {
+    keywords: [ "x", "green-square", "no", "deny" ],
+    "char": "\u274e",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  white_check_mark: {
+    keywords: [ "green-square", "ok", "agree", "vote", "election", "answer", "tick" ],
+    "char": "\u2705",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  diamond_shape_with_a_dot_inside: {
+    keywords: [ "jewel", "blue", "gem", "crystal", "fancy" ],
+    "char": "\ud83d\udca0",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  cyclone: {
+    keywords: [ "weather", "swirl", "blue", "cloud", "vortex", "spiral", "whirlpool", "spin", "tornado", "hurricane", "typhoon" ],
+    "char": "\ud83c\udf00",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  loop: {
+    keywords: [ "tape", "cassette" ],
+    "char": "\u27bf",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  globe_with_meridians: {
+    keywords: [ "earth", "international", "world", "internet", "interweb", "i18n" ],
+    "char": "\ud83c\udf10",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  m: {
+    keywords: [ "alphabet", "blue-circle", "letter" ],
+    "char": "\u24c2\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  atm: {
+    keywords: [ "money", "sales", "cash", "blue-square", "payment", "bank" ],
+    "char": "\ud83c\udfe7",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  sa: {
+    keywords: [ "japanese", "blue-square", "katakana" ],
+    "char": "\ud83c\ude02\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  passport_control: {
+    keywords: [ "custom", "blue-square" ],
+    "char": "\ud83d\udec2",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  customs: {
+    keywords: [ "passport", "border", "blue-square" ],
+    "char": "\ud83d\udec3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  baggage_claim: {
+    keywords: [ "blue-square", "airport", "transport" ],
+    "char": "\ud83d\udec4",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  left_luggage: {
+    keywords: [ "blue-square", "travel" ],
+    "char": "\ud83d\udec5",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  wheelchair: {
+    keywords: [ "blue-square", "disabled", "a11y", "accessibility" ],
+    "char": "\u267f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  no_smoking: {
+    keywords: [ "cigarette", "blue-square", "smell", "smoke" ],
+    "char": "\ud83d\udead",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  wc: {
+    keywords: [ "toilet", "restroom", "blue-square" ],
+    "char": "\ud83d\udebe",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  parking: {
+    keywords: [ "cars", "blue-square", "alphabet", "letter" ],
+    "char": "\ud83c\udd7f\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  potable_water: {
+    keywords: [ "blue-square", "liquid", "restroom", "cleaning", "faucet" ],
+    "char": "\ud83d\udeb0",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  mens: {
+    keywords: [ "toilet", "restroom", "wc", "blue-square", "gender", "male" ],
+    "char": "\ud83d\udeb9",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  womens: {
+    keywords: [ "purple-square", "woman", "female", "toilet", "loo", "restroom", "gender" ],
+    "char": "\ud83d\udeba",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  baby_symbol: {
+    keywords: [ "orange-square", "child" ],
+    "char": "\ud83d\udebc",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  restroom: {
+    keywords: [ "blue-square", "toilet", "refresh", "wc", "gender" ],
+    "char": "\ud83d\udebb",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  put_litter_in_its_place: {
+    keywords: [ "blue-square", "sign", "human", "info" ],
+    "char": "\ud83d\udeae",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  cinema: {
+    keywords: [ "blue-square", "record", "film", "movie", "curtain", "stage", "theater" ],
+    "char": "\ud83c\udfa6",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  signal_strength: {
+    keywords: [ "blue-square", "reception", "phone", "internet", "connection", "wifi", "bluetooth", "bars" ],
+    "char": "\ud83d\udcf6",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  koko: {
+    keywords: [ "blue-square", "here", "katakana", "japanese", "destination" ],
+    "char": "\ud83c\ude01",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  ng: {
+    keywords: [ "blue-square", "words", "shape", "icon" ],
+    "char": "\ud83c\udd96",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  ok: {
+    keywords: [ "good", "agree", "yes", "blue-square" ],
+    "char": "\ud83c\udd97",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  up: {
+    keywords: [ "blue-square", "above", "high" ],
+    "char": "\ud83c\udd99",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  cool: {
+    keywords: [ "words", "blue-square" ],
+    "char": "\ud83c\udd92",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  "new": {
+    keywords: [ "blue-square", "words", "start" ],
+    "char": "\ud83c\udd95",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  free: {
+    keywords: [ "blue-square", "words" ],
+    "char": "\ud83c\udd93",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  zero: {
+    keywords: [ "0", "numbers", "blue-square", "null" ],
+    "char": "0\ufe0f\u20e3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  one: {
+    keywords: [ "blue-square", "numbers", "1" ],
+    "char": "1\ufe0f\u20e3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  two: {
+    keywords: [ "numbers", "2", "prime", "blue-square" ],
+    "char": "2\ufe0f\u20e3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  three: {
+    keywords: [ "3", "numbers", "prime", "blue-square" ],
+    "char": "3\ufe0f\u20e3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  four: {
+    keywords: [ "4", "numbers", "blue-square" ],
+    "char": "4\ufe0f\u20e3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  five: {
+    keywords: [ "5", "numbers", "blue-square", "prime" ],
+    "char": "5\ufe0f\u20e3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  six: {
+    keywords: [ "6", "numbers", "blue-square" ],
+    "char": "6\ufe0f\u20e3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  seven: {
+    keywords: [ "7", "numbers", "blue-square", "prime" ],
+    "char": "7\ufe0f\u20e3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  eight: {
+    keywords: [ "8", "blue-square", "numbers" ],
+    "char": "8\ufe0f\u20e3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  nine: {
+    keywords: [ "blue-square", "numbers", "9" ],
+    "char": "9\ufe0f\u20e3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  keycap_ten: {
+    keywords: [ "numbers", "10", "blue-square" ],
+    "char": "\ud83d\udd1f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  asterisk: {
+    keywords: [ "star", "keycap" ],
+    "char": "*\u20e3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  1234: {
+    keywords: [ "numbers", "blue-square" ],
+    "char": "\ud83d\udd22",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  eject_button: {
+    keywords: [ "blue-square" ],
+    "char": "\u23cf\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_forward: {
+    keywords: [ "blue-square", "right", "direction", "play" ],
+    "char": "\u25b6\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  pause_button: {
+    keywords: [ "pause", "blue-square" ],
+    "char": "\u23f8",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  next_track_button: {
+    keywords: [ "forward", "next", "blue-square" ],
+    "char": "\u23ed",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  stop_button: {
+    keywords: [ "blue-square" ],
+    "char": "\u23f9",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  record_button: {
+    keywords: [ "blue-square" ],
+    "char": "\u23fa",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  play_or_pause_button: {
+    keywords: [ "blue-square", "play", "pause" ],
+    "char": "\u23ef",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  previous_track_button: {
+    keywords: [ "backward" ],
+    "char": "\u23ee",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  fast_forward: {
+    keywords: [ "blue-square", "play", "speed", "continue" ],
+    "char": "\u23e9",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  rewind: {
+    keywords: [ "play", "blue-square" ],
+    "char": "\u23ea",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  twisted_rightwards_arrows: {
+    keywords: [ "blue-square", "shuffle", "music", "random" ],
+    "char": "\ud83d\udd00",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  repeat: {
+    keywords: [ "loop", "record" ],
+    "char": "\ud83d\udd01",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  repeat_one: {
+    keywords: [ "blue-square", "loop" ],
+    "char": "\ud83d\udd02",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_backward: {
+    keywords: [ "blue-square", "left", "direction" ],
+    "char": "\u25c0\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_up_small: {
+    keywords: [ "blue-square", "triangle", "direction", "point", "forward", "top" ],
+    "char": "\ud83d\udd3c",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_down_small: {
+    keywords: [ "blue-square", "direction", "bottom" ],
+    "char": "\ud83d\udd3d",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_double_up: {
+    keywords: [ "blue-square", "direction", "top" ],
+    "char": "\u23eb",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_double_down: {
+    keywords: [ "blue-square", "direction", "bottom" ],
+    "char": "\u23ec",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_right: {
+    keywords: [ "blue-square", "next" ],
+    "char": "\u27a1\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_left: {
+    keywords: [ "blue-square", "previous", "back" ],
+    "char": "\u2b05\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_up: {
+    keywords: [ "blue-square", "continue", "top", "direction" ],
+    "char": "\u2b06\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_down: {
+    keywords: [ "blue-square", "direction", "bottom" ],
+    "char": "\u2b07\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_upper_right: {
+    keywords: [ "blue-square", "point", "direction", "diagonal", "northeast" ],
+    "char": "\u2197\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_lower_right: {
+    keywords: [ "blue-square", "direction", "diagonal", "southeast" ],
+    "char": "\u2198\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_lower_left: {
+    keywords: [ "blue-square", "direction", "diagonal", "southwest" ],
+    "char": "\u2199\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_upper_left: {
+    keywords: [ "blue-square", "point", "direction", "diagonal", "northwest" ],
+    "char": "\u2196\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_up_down: {
+    keywords: [ "blue-square", "direction", "way", "vertical" ],
+    "char": "\u2195\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  left_right_arrow: {
+    keywords: [ "shape", "direction", "horizontal", "sideways" ],
+    "char": "\u2194\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrows_counterclockwise: {
+    keywords: [ "blue-square", "sync", "cycle" ],
+    "char": "\ud83d\udd04",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_right_hook: {
+    keywords: [ "blue-square", "return", "rotate", "direction" ],
+    "char": "\u21aa\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  leftwards_arrow_with_hook: {
+    keywords: [ "back", "return", "blue-square", "undo", "enter" ],
+    "char": "\u21a9\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_heading_up: {
+    keywords: [ "blue-square", "direction", "top" ],
+    "char": "\u2934\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrow_heading_down: {
+    keywords: [ "blue-square", "direction", "bottom" ],
+    "char": "\u2935\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  hash: {
+    keywords: [ "symbol", "blue-square", "twitter" ],
+    "char": "#\ufe0f\u20e3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  information_source: {
+    keywords: [ "blue-square", "alphabet", "letter" ],
+    "char": "\u2139\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  abc: {
+    keywords: [ "blue-square", "alphabet" ],
+    "char": "\ud83d\udd24",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  abcd: {
+    keywords: [ "blue-square", "alphabet" ],
+    "char": "\ud83d\udd21",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  capital_abcd: {
+    keywords: [ "alphabet", "words", "blue-square" ],
+    "char": "\ud83d\udd20",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  symbols: {
+    keywords: [ "blue-square", "music", "note", "ampersand", "percent", "glyphs", "characters" ],
+    "char": "\ud83d\udd23",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  musical_note: {
+    keywords: [ "score", "tone", "sound" ],
+    "char": "\ud83c\udfb5",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  notes: {
+    keywords: [ "music", "score" ],
+    "char": "\ud83c\udfb6",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  wavy_dash: {
+    keywords: [ "draw", "line", "moustache", "mustache", "squiggle", "scribble" ],
+    "char": "\u3030\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  curly_loop: {
+    keywords: [ "scribble", "draw", "shape", "squiggle" ],
+    "char": "\u27b0",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  heavy_check_mark: {
+    keywords: [ "ok", "nike", "answer", "yes", "tick" ],
+    "char": "\u2714\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  arrows_clockwise: {
+    keywords: [ "sync", "cycle", "round", "repeat" ],
+    "char": "\ud83d\udd03",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  heavy_plus_sign: {
+    keywords: [ "math", "calculation", "addition", "more", "increase" ],
+    "char": "\u2795",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  heavy_minus_sign: {
+    keywords: [ "math", "calculation", "subtract", "less" ],
+    "char": "\u2796",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  heavy_division_sign: {
+    keywords: [ "divide", "math", "calculation" ],
+    "char": "\u2797",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  heavy_multiplication_x: {
+    keywords: [ "math", "calculation" ],
+    "char": "\u2716\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  heavy_dollar_sign: {
+    keywords: [ "money", "sales", "payment", "currency", "buck" ],
+    "char": "\ud83d\udcb2",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  currency_exchange: {
+    keywords: [ "money", "sales", "dollar", "travel" ],
+    "char": "\ud83d\udcb1",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  copyright: {
+    keywords: [ "ip", "license", "circle", "law", "legal" ],
+    "char": "\xa9\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  registered: {
+    keywords: [ "alphabet", "circle" ],
+    "char": "\xae\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  tm: {
+    keywords: [ "trademark", "brand", "law", "legal" ],
+    "char": "\u2122\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  end: {
+    keywords: [ "words", "arrow" ],
+    "char": "\ud83d\udd1a",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  back: {
+    keywords: [ "arrow", "words", "return" ],
+    "char": "\ud83d\udd19",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  on: {
+    keywords: [ "arrow", "words" ],
+    "char": "\ud83d\udd1b",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  top: {
+    keywords: [ "words", "blue-square" ],
+    "char": "\ud83d\udd1d",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  soon: {
+    keywords: [ "arrow", "words" ],
+    "char": "\ud83d\udd1c",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  ballot_box_with_check: {
+    keywords: [ "ok", "agree", "confirm", "black-square", "vote", "election", "yes", "tick" ],
+    "char": "\u2611\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  radio_button: {
+    keywords: [ "input", "old", "music", "circle" ],
+    "char": "\ud83d\udd18",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  white_circle: {
+    keywords: [ "shape", "round" ],
+    "char": "\u26aa",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  black_circle: {
+    keywords: [ "shape", "button", "round" ],
+    "char": "\u26ab",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  red_circle: {
+    keywords: [ "shape", "error", "danger" ],
+    "char": "\ud83d\udd34",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  large_blue_circle: {
+    keywords: [ "shape", "icon", "button" ],
+    "char": "\ud83d\udd35",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  small_orange_diamond: {
+    keywords: [ "shape", "jewel", "gem" ],
+    "char": "\ud83d\udd38",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  small_blue_diamond: {
+    keywords: [ "shape", "jewel", "gem" ],
+    "char": "\ud83d\udd39",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  large_orange_diamond: {
+    keywords: [ "shape", "jewel", "gem" ],
+    "char": "\ud83d\udd36",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  large_blue_diamond: {
+    keywords: [ "shape", "jewel", "gem" ],
+    "char": "\ud83d\udd37",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  small_red_triangle: {
+    keywords: [ "shape", "direction", "up", "top" ],
+    "char": "\ud83d\udd3a",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  black_small_square: {
+    keywords: [ "shape", "icon" ],
+    "char": "\u25aa\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  white_small_square: {
+    keywords: [ "shape", "icon" ],
+    "char": "\u25ab\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  black_large_square: {
+    keywords: [ "shape", "icon", "button" ],
+    "char": "\u2b1b",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  white_large_square: {
+    keywords: [ "shape", "icon", "stone", "button" ],
+    "char": "\u2b1c",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  small_red_triangle_down: {
+    keywords: [ "shape", "direction", "bottom" ],
+    "char": "\ud83d\udd3b",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  black_medium_square: {
+    keywords: [ "shape", "button", "icon" ],
+    "char": "\u25fc\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  white_medium_square: {
+    keywords: [ "shape", "stone", "icon" ],
+    "char": "\u25fb\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  black_medium_small_square: {
+    keywords: [ "icon", "shape", "button" ],
+    "char": "\u25fe",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  white_medium_small_square: {
+    keywords: [ "shape", "stone", "icon", "button" ],
+    "char": "\u25fd",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  black_square_button: {
+    keywords: [ "shape", "input", "frame" ],
+    "char": "\ud83d\udd32",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  white_square_button: {
+    keywords: [ "shape", "input" ],
+    "char": "\ud83d\udd33",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  speaker: {
+    keywords: [ "sound", "volume", "silence", "broadcast" ],
+    "char": "\ud83d\udd08",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  sound: {
+    keywords: [ "volume", "speaker", "broadcast" ],
+    "char": "\ud83d\udd09",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  loud_sound: {
+    keywords: [ "volume", "noise", "noisy", "speaker", "broadcast" ],
+    "char": "\ud83d\udd0a",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  mute: {
+    keywords: [ "sound", "volume", "silence", "quiet" ],
+    "char": "\ud83d\udd07",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  mega: {
+    keywords: [ "sound", "speaker", "volume" ],
+    "char": "\ud83d\udce3",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  loudspeaker: {
+    keywords: [ "volume", "sound" ],
+    "char": "\ud83d\udce2",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  bell: {
+    keywords: [ "sound", "notification", "christmas", "xmas", "chime" ],
+    "char": "\ud83d\udd14",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  no_bell: {
+    keywords: [ "sound", "volume", "mute", "quiet", "silent" ],
+    "char": "\ud83d\udd15",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  black_joker: {
+    keywords: [ "poker", "cards", "game", "play", "magic" ],
+    "char": "\ud83c\udccf",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  mahjong: {
+    keywords: [ "game", "play", "chinese", "kanji" ],
+    "char": "\ud83c\udc04",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  spades: {
+    keywords: [ "poker", "cards", "suits", "magic" ],
+    "char": "\u2660\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clubs: {
+    keywords: [ "poker", "cards", "magic", "suits" ],
+    "char": "\u2663\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  hearts: {
+    keywords: [ "poker", "cards", "magic", "suits" ],
+    "char": "\u2665\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  diamonds: {
+    keywords: [ "poker", "cards", "magic", "suits" ],
+    "char": "\u2666\ufe0f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  flower_playing_cards: {
+    keywords: [ "game", "sunset", "red" ],
+    "char": "\ud83c\udfb4",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  thought_balloon: {
+    keywords: [ "bubble", "cloud", "speech", "thinking", "dream" ],
+    "char": "\ud83d\udcad",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  right_anger_bubble: {
+    keywords: [ "caption", "speech", "thinking", "mad" ],
+    "char": "\ud83d\uddef",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  speech_balloon: {
+    keywords: [ "bubble", "words", "message", "talk", "chatting" ],
+    "char": "\ud83d\udcac",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  left_speech_bubble: {
+    keywords: [ "words", "message", "talk", "chatting" ],
+    "char": "\ud83d\udde8",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock1: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd50",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock2: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd51",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock3: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd52",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock4: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd53",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock5: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd54",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock6: {
+    keywords: [ "time", "late", "early", "schedule", "dawn", "dusk" ],
+    "char": "\ud83d\udd55",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock7: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd56",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock8: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd57",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock9: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd58",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock10: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd59",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock11: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd5a",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock12: {
+    keywords: [ "time", "noon", "midnight", "midday", "late", "early", "schedule" ],
+    "char": "\ud83d\udd5b",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock130: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd5c",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock230: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd5d",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock330: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd5e",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock430: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd5f",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock530: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd60",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock630: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd61",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock730: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd62",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock830: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd63",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock930: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd64",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock1030: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd65",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock1130: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd66",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  clock1230: {
+    keywords: [ "time", "late", "early", "schedule" ],
+    "char": "\ud83d\udd67",
+    fitzpatrick_scale: false,
+    category: "symbols"
+  },
+  afghanistan: {
+    keywords: [ "af", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddeb",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  aland_islands: {
+    keywords: [ "\xc5land", "islands", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddfd",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  albania: {
+    keywords: [ "al", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddf1",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  algeria: {
+    keywords: [ "dz", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde9\ud83c\uddff",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  american_samoa: {
+    keywords: [ "american", "ws", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddf8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  andorra: {
+    keywords: [ "ad", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\udde9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  angola: {
+    keywords: [ "ao", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddf4",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  anguilla: {
+    keywords: [ "ai", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddee",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  antarctica: {
+    keywords: [ "aq", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddf6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  antigua_barbuda: {
+    keywords: [ "antigua", "barbuda", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddec",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  argentina: {
+    keywords: [ "ar", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  armenia: {
+    keywords: [ "am", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  aruba: {
+    keywords: [ "aw", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddfc",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  australia: {
+    keywords: [ "au", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddfa",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  austria: {
+    keywords: [ "at", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddf9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  azerbaijan: {
+    keywords: [ "az", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddff",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  bahamas: {
+    keywords: [ "bs", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddf8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  bahrain: {
+    keywords: [ "bh", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\udded",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  bangladesh: {
+    keywords: [ "bd", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\udde9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  barbados: {
+    keywords: [ "bb", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\udde7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  belarus: {
+    keywords: [ "by", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddfe",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  belgium: {
+    keywords: [ "be", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  belize: {
+    keywords: [ "bz", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddff",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  benin: {
+    keywords: [ "bj", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddef",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  bermuda: {
+    keywords: [ "bm", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  bhutan: {
+    keywords: [ "bt", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddf9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  bolivia: {
+    keywords: [ "bo", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddf4",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  caribbean_netherlands: {
+    keywords: [ "bonaire", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddf6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  bosnia_herzegovina: {
+    keywords: [ "bosnia", "herzegovina", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\udde6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  botswana: {
+    keywords: [ "bw", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddfc",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  brazil: {
+    keywords: [ "br", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  british_indian_ocean_territory: {
+    keywords: [ "british", "indian", "ocean", "territory", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddee\ud83c\uddf4",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  british_virgin_islands: {
+    keywords: [ "british", "virgin", "islands", "bvi", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfb\ud83c\uddec",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  brunei: {
+    keywords: [ "bn", "darussalam", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddf3",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  bulgaria: {
+    keywords: [ "bg", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddec",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  burkina_faso: {
+    keywords: [ "burkina", "faso", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddeb",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  burundi: {
+    keywords: [ "bi", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddee",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  cape_verde: {
+    keywords: [ "cabo", "verde", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddfb",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  cambodia: {
+    keywords: [ "kh", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf0\ud83c\udded",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  cameroon: {
+    keywords: [ "cm", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  canada: {
+    keywords: [ "ca", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\udde6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  canary_islands: {
+    keywords: [ "canary", "islands", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddee\ud83c\udde8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  cayman_islands: {
+    keywords: [ "cayman", "islands", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf0\ud83c\uddfe",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  central_african_republic: {
+    keywords: [ "central", "african", "republic", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddeb",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  chad: {
+    keywords: [ "td", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\udde9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  chile: {
+    keywords: [ "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddf1",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  cn: {
+    keywords: [ "china", "chinese", "prc", "flag", "country", "nation", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddf3",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  christmas_island: {
+    keywords: [ "christmas", "island", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddfd",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  cocos_islands: {
+    keywords: [ "cocos", "keeling", "islands", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\udde8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  colombia: {
+    keywords: [ "co", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddf4",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  comoros: {
+    keywords: [ "km", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf0\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  congo_brazzaville: {
+    keywords: [ "congo", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddec",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  congo_kinshasa: {
+    keywords: [ "congo", "democratic", "republic", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\udde9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  cook_islands: {
+    keywords: [ "cook", "islands", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddf0",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  costa_rica: {
+    keywords: [ "costa", "rica", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  croatia: {
+    keywords: [ "hr", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udded\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  cuba: {
+    keywords: [ "cu", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddfa",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  curacao: {
+    keywords: [ "cura\xe7ao", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddfc",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  cyprus: {
+    keywords: [ "cy", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddfe",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  czech_republic: {
+    keywords: [ "cz", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddff",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  denmark: {
+    keywords: [ "dk", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde9\ud83c\uddf0",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  djibouti: {
+    keywords: [ "dj", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde9\ud83c\uddef",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  dominica: {
+    keywords: [ "dm", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde9\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  dominican_republic: {
+    keywords: [ "dominican", "republic", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde9\ud83c\uddf4",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  ecuador: {
+    keywords: [ "ec", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddea\ud83c\udde8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  egypt: {
+    keywords: [ "eg", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddea\ud83c\uddec",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  el_salvador: {
+    keywords: [ "el", "salvador", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddfb",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  equatorial_guinea: {
+    keywords: [ "equatorial", "gn", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddf6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  eritrea: {
+    keywords: [ "er", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddea\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  estonia: {
+    keywords: [ "ee", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddea\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  ethiopia: {
+    keywords: [ "et", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddea\ud83c\uddf9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  eu: {
+    keywords: [ "european", "union", "flag", "banner" ],
+    "char": "\ud83c\uddea\ud83c\uddfa",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  falkland_islands: {
+    keywords: [ "falkland", "islands", "malvinas", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddeb\ud83c\uddf0",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  faroe_islands: {
+    keywords: [ "faroe", "islands", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddeb\ud83c\uddf4",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  fiji: {
+    keywords: [ "fj", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddeb\ud83c\uddef",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  finland: {
+    keywords: [ "fi", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddeb\ud83c\uddee",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  fr: {
+    keywords: [ "banner", "flag", "nation", "france", "french", "country" ],
+    "char": "\ud83c\uddeb\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  french_guiana: {
+    keywords: [ "french", "guiana", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddeb",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  french_polynesia: {
+    keywords: [ "french", "polynesia", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\uddeb",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  french_southern_territories: {
+    keywords: [ "french", "southern", "territories", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\uddeb",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  gabon: {
+    keywords: [ "ga", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\udde6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  gambia: {
+    keywords: [ "gm", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  georgia: {
+    keywords: [ "ge", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  de: {
+    keywords: [ "german", "nation", "flag", "country", "banner" ],
+    "char": "\ud83c\udde9\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  ghana: {
+    keywords: [ "gh", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\udded",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  gibraltar: {
+    keywords: [ "gi", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddee",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  greece: {
+    keywords: [ "gr", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  greenland: {
+    keywords: [ "gl", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddf1",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  grenada: {
+    keywords: [ "gd", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\udde9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  guadeloupe: {
+    keywords: [ "gp", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddf5",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  guam: {
+    keywords: [ "gu", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddfa",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  guatemala: {
+    keywords: [ "gt", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddf9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  guernsey: {
+    keywords: [ "gg", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddec",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  guinea: {
+    keywords: [ "gn", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddf3",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  guinea_bissau: {
+    keywords: [ "gw", "bissau", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddfc",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  guyana: {
+    keywords: [ "gy", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddfe",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  haiti: {
+    keywords: [ "ht", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udded\ud83c\uddf9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  honduras: {
+    keywords: [ "hn", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udded\ud83c\uddf3",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  hong_kong: {
+    keywords: [ "hong", "kong", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udded\ud83c\uddf0",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  hungary: {
+    keywords: [ "hu", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udded\ud83c\uddfa",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  iceland: {
+    keywords: [ "is", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddee\ud83c\uddf8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  india: {
+    keywords: [ "in", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddee\ud83c\uddf3",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  indonesia: {
+    keywords: [ "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddee\ud83c\udde9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  iran: {
+    keywords: [ "iran,", "islamic", "republic", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddee\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  iraq: {
+    keywords: [ "iq", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddee\ud83c\uddf6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  ireland: {
+    keywords: [ "ie", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddee\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  isle_of_man: {
+    keywords: [ "isle", "man", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddee\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  israel: {
+    keywords: [ "il", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddee\ud83c\uddf1",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  it: {
+    keywords: [ "italy", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddee\ud83c\uddf9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  cote_divoire: {
+    keywords: [ "ivory", "coast", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\uddee",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  jamaica: {
+    keywords: [ "jm", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddef\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  jp: {
+    keywords: [ "japanese", "nation", "flag", "country", "banner" ],
+    "char": "\ud83c\uddef\ud83c\uddf5",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  jersey: {
+    keywords: [ "je", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddef\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  jordan: {
+    keywords: [ "jo", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddef\ud83c\uddf4",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  kazakhstan: {
+    keywords: [ "kz", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf0\ud83c\uddff",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  kenya: {
+    keywords: [ "ke", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf0\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  kiribati: {
+    keywords: [ "ki", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf0\ud83c\uddee",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  kosovo: {
+    keywords: [ "xk", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfd\ud83c\uddf0",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  kuwait: {
+    keywords: [ "kw", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf0\ud83c\uddfc",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  kyrgyzstan: {
+    keywords: [ "kg", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf0\ud83c\uddec",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  laos: {
+    keywords: [ "lao", "democratic", "republic", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf1\ud83c\udde6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  latvia: {
+    keywords: [ "lv", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf1\ud83c\uddfb",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  lebanon: {
+    keywords: [ "lb", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf1\ud83c\udde7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  lesotho: {
+    keywords: [ "ls", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf1\ud83c\uddf8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  liberia: {
+    keywords: [ "lr", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf1\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  libya: {
+    keywords: [ "ly", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf1\ud83c\uddfe",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  liechtenstein: {
+    keywords: [ "li", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf1\ud83c\uddee",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  lithuania: {
+    keywords: [ "lt", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf1\ud83c\uddf9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  luxembourg: {
+    keywords: [ "lu", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf1\ud83c\uddfa",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  macau: {
+    keywords: [ "macao", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddf4",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  macedonia: {
+    keywords: [ "macedonia,", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddf0",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  madagascar: {
+    keywords: [ "mg", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddec",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  malawi: {
+    keywords: [ "mw", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddfc",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  malaysia: {
+    keywords: [ "my", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddfe",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  maldives: {
+    keywords: [ "mv", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddfb",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  mali: {
+    keywords: [ "ml", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddf1",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  malta: {
+    keywords: [ "mt", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddf9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  marshall_islands: {
+    keywords: [ "marshall", "islands", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\udded",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  martinique: {
+    keywords: [ "mq", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddf6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  mauritania: {
+    keywords: [ "mr", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  mauritius: {
+    keywords: [ "mu", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddfa",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  mayotte: {
+    keywords: [ "yt", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfe\ud83c\uddf9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  mexico: {
+    keywords: [ "mx", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddfd",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  micronesia: {
+    keywords: [ "micronesia,", "federated", "states", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddeb\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  moldova: {
+    keywords: [ "moldova,", "republic", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\udde9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  monaco: {
+    keywords: [ "mc", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\udde8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  mongolia: {
+    keywords: [ "mn", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddf3",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  montenegro: {
+    keywords: [ "me", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  montserrat: {
+    keywords: [ "ms", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddf8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  morocco: {
+    keywords: [ "ma", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\udde6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  mozambique: {
+    keywords: [ "mz", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddff",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  myanmar: {
+    keywords: [ "mm", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  namibia: {
+    keywords: [ "na", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf3\ud83c\udde6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  nauru: {
+    keywords: [ "nr", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf3\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  nepal: {
+    keywords: [ "np", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf3\ud83c\uddf5",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  netherlands: {
+    keywords: [ "nl", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf3\ud83c\uddf1",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  new_caledonia: {
+    keywords: [ "new", "caledonia", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf3\ud83c\udde8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  new_zealand: {
+    keywords: [ "new", "zealand", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf3\ud83c\uddff",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  nicaragua: {
+    keywords: [ "ni", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf3\ud83c\uddee",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  niger: {
+    keywords: [ "ne", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf3\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  nigeria: {
+    keywords: [ "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf3\ud83c\uddec",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  niue: {
+    keywords: [ "nu", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf3\ud83c\uddfa",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  norfolk_island: {
+    keywords: [ "norfolk", "island", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf3\ud83c\uddeb",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  northern_mariana_islands: {
+    keywords: [ "northern", "mariana", "islands", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf2\ud83c\uddf5",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  north_korea: {
+    keywords: [ "north", "korea", "nation", "flag", "country", "banner" ],
+    "char": "\ud83c\uddf0\ud83c\uddf5",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  norway: {
+    keywords: [ "no", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf3\ud83c\uddf4",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  oman: {
+    keywords: [ "om_symbol", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf4\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  pakistan: {
+    keywords: [ "pk", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\uddf0",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  palau: {
+    keywords: [ "pw", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\uddfc",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  palestinian_territories: {
+    keywords: [ "palestine", "palestinian", "territories", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\uddf8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  panama: {
+    keywords: [ "pa", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\udde6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  papua_new_guinea: {
+    keywords: [ "papua", "new", "guinea", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\uddec",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  paraguay: {
+    keywords: [ "py", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\uddfe",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  peru: {
+    keywords: [ "pe", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  philippines: {
+    keywords: [ "ph", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\udded",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  pitcairn_islands: {
+    keywords: [ "pitcairn", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\uddf3",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  poland: {
+    keywords: [ "pl", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\uddf1",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  portugal: {
+    keywords: [ "pt", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\uddf9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  puerto_rico: {
+    keywords: [ "puerto", "rico", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  qatar: {
+    keywords: [ "qa", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf6\ud83c\udde6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  reunion: {
+    keywords: [ "r\xe9union", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf7\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  romania: {
+    keywords: [ "ro", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf7\ud83c\uddf4",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  ru: {
+    keywords: [ "russian", "federation", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf7\ud83c\uddfa",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  rwanda: {
+    keywords: [ "rw", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf7\ud83c\uddfc",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  st_barthelemy: {
+    keywords: [ "saint", "barth\xe9lemy", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde7\ud83c\uddf1",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  st_helena: {
+    keywords: [ "saint", "helena", "ascension", "tristan", "cunha", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\udded",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  st_kitts_nevis: {
+    keywords: [ "saint", "kitts", "nevis", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf0\ud83c\uddf3",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  st_lucia: {
+    keywords: [ "saint", "lucia", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf1\ud83c\udde8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  st_pierre_miquelon: {
+    keywords: [ "saint", "pierre", "miquelon", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf5\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  st_vincent_grenadines: {
+    keywords: [ "saint", "vincent", "grenadines", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfb\ud83c\udde8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  samoa: {
+    keywords: [ "ws", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfc\ud83c\uddf8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  san_marino: {
+    keywords: [ "san", "marino", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  sao_tome_principe: {
+    keywords: [ "sao", "tome", "principe", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddf9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  saudi_arabia: {
+    keywords: [ "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\udde6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  senegal: {
+    keywords: [ "sn", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddf3",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  serbia: {
+    keywords: [ "rs", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf7\ud83c\uddf8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  seychelles: {
+    keywords: [ "sc", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\udde8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  sierra_leone: {
+    keywords: [ "sierra", "leone", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddf1",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  singapore: {
+    keywords: [ "sg", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddec",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  sint_maarten: {
+    keywords: [ "sint", "maarten", "dutch", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddfd",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  slovakia: {
+    keywords: [ "sk", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddf0",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  slovenia: {
+    keywords: [ "si", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddee",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  solomon_islands: {
+    keywords: [ "solomon", "islands", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\udde7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  somalia: {
+    keywords: [ "so", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddf4",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  south_africa: {
+    keywords: [ "south", "africa", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddff\ud83c\udde6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  south_georgia_south_sandwich_islands: {
+    keywords: [ "south", "georgia", "sandwich", "islands", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddec\ud83c\uddf8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  kr: {
+    keywords: [ "south", "korea", "nation", "flag", "country", "banner" ],
+    "char": "\ud83c\uddf0\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  south_sudan: {
+    keywords: [ "south", "sd", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddf8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  es: {
+    keywords: [ "spain", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddea\ud83c\uddf8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  sri_lanka: {
+    keywords: [ "sri", "lanka", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf1\ud83c\uddf0",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  sudan: {
+    keywords: [ "sd", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\udde9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  suriname: {
+    keywords: [ "sr", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  swaziland: {
+    keywords: [ "sz", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddff",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  sweden: {
+    keywords: [ "se", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  switzerland: {
+    keywords: [ "ch", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde8\ud83c\udded",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  syria: {
+    keywords: [ "syrian", "arab", "republic", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf8\ud83c\uddfe",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  taiwan: {
+    keywords: [ "tw", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\uddfc",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  tajikistan: {
+    keywords: [ "tj", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\uddef",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  tanzania: {
+    keywords: [ "tanzania,", "united", "republic", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\uddff",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  thailand: {
+    keywords: [ "th", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\udded",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  timor_leste: {
+    keywords: [ "timor", "leste", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\uddf1",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  togo: {
+    keywords: [ "tg", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\uddec",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  tokelau: {
+    keywords: [ "tk", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\uddf0",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  tonga: {
+    keywords: [ "to", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\uddf4",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  trinidad_tobago: {
+    keywords: [ "trinidad", "tobago", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\uddf9",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  tunisia: {
+    keywords: [ "tn", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\uddf3",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  tr: {
+    keywords: [ "turkey", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\uddf7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  turkmenistan: {
+    keywords: [ "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  turks_caicos_islands: {
+    keywords: [ "turks", "caicos", "islands", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\udde8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  tuvalu: {
+    keywords: [ "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddf9\ud83c\uddfb",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  uganda: {
+    keywords: [ "ug", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfa\ud83c\uddec",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  ukraine: {
+    keywords: [ "ua", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfa\ud83c\udde6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  united_arab_emirates: {
+    keywords: [ "united", "arab", "emirates", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\udde6\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  uk: {
+    keywords: [ "united", "kingdom", "great", "britain", "northern", "ireland", "flag", "nation", "country", "banner", "british", "UK", "english", "england", "union jack" ],
+    "char": "\ud83c\uddec\ud83c\udde7",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  england: {
+    keywords: [ "flag", "english" ],
+    "char": "\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc65\udb40\udc6e\udb40\udc67\udb40\udc7f",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  scotland: {
+    keywords: [ "flag", "scottish" ],
+    "char": "\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc73\udb40\udc63\udb40\udc74\udb40\udc7f",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  wales: {
+    keywords: [ "flag", "welsh" ],
+    "char": "\ud83c\udff4\udb40\udc67\udb40\udc62\udb40\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  us: {
+    keywords: [ "united", "states", "america", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfa\ud83c\uddf8",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  us_virgin_islands: {
+    keywords: [ "virgin", "islands", "us", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfb\ud83c\uddee",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  uruguay: {
+    keywords: [ "uy", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfa\ud83c\uddfe",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  uzbekistan: {
+    keywords: [ "uz", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfa\ud83c\uddff",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  vanuatu: {
+    keywords: [ "vu", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfb\ud83c\uddfa",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  vatican_city: {
+    keywords: [ "vatican", "city", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfb\ud83c\udde6",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  venezuela: {
+    keywords: [ "ve", "bolivarian", "republic", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfb\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  vietnam: {
+    keywords: [ "viet", "nam", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfb\ud83c\uddf3",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  wallis_futuna: {
+    keywords: [ "wallis", "futuna", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfc\ud83c\uddeb",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  western_sahara: {
+    keywords: [ "western", "sahara", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddea\ud83c\udded",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  yemen: {
+    keywords: [ "ye", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddfe\ud83c\uddea",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  zambia: {
+    keywords: [ "zm", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddff\ud83c\uddf2",
+    fitzpatrick_scale: false,
+    category: "flags"
+  },
+  zimbabwe: {
+    keywords: [ "zw", "flag", "nation", "country", "banner" ],
+    "char": "\ud83c\uddff\ud83c\uddfc",
+    fitzpatrick_scale: false,
+    category: "flags"
+  }
+});

Diff do ficheiro suprimidas por serem muito extensas
+ 1 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/emoticons/js/emojis.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/emoticons/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/fullpage/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/fullscreen/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/help/plugin.min.js


+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/hr/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager");!function o(){n.add("hr",function(n){var o,t;(o=n).addCommand("InsertHorizontalRule",function(){o.execCommand("mceInsertContent",!1,"<hr />")}),(t=n).ui.registry.addButton("hr",{icon:"horizontal-rule",tooltip:"Horizontal line",onAction:function(){return t.execCommand("InsertHorizontalRule")}}),t.ui.registry.addMenuItem("hr",{icon:"horizontal-rule",text:"Horizontal line",onAction:function(){return t.execCommand("InsertHorizontalRule")}})})}()}();

Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/image/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/imagetools/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/importcss/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/insertdatetime/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/legacyoutput/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/link/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/lists/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/media/plugin.min.js


+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/nonbreaking/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),i=function(n,e){for(var a="",o=0;o<e;o++)a+=n;return a},r=function(n,e){var a,o=n.getParam("nonbreaking_wrap",!0,"boolean")||n.plugins.visualchars?'<span class="'+((a=n).plugins.visualchars&&a.plugins.visualchars.isEnabled()?"mce-nbsp-wrap mce-nbsp":"mce-nbsp-wrap")+'" contenteditable="false">'+i("&nbsp;",e)+"</span>":i("&nbsp;",e);n.undoManager.transact(function(){return n.insertContent(o)})},c=tinymce.util.Tools.resolve("tinymce.util.VK");!function e(){n.add("nonbreaking",function(n){var e,a,o,i,t;(e=n).addCommand("mceNonBreaking",function(){r(e,1)}),(a=n).ui.registry.addButton("nonbreaking",{icon:"non-breaking",tooltip:"Nonbreaking space",onAction:function(){return a.execCommand("mceNonBreaking")}}),a.ui.registry.addMenuItem("nonbreaking",{icon:"non-breaking",text:"Nonbreaking space",onAction:function(){return a.execCommand("mceNonBreaking")}}),0<(t="boolean"==typeof(i=(o=n).getParam("nonbreaking_force_tab",0))?!0===i?3:0:i)&&o.on("keydown",function(n){if(n.keyCode===c.TAB&&!n.isDefaultPrevented()){if(n.shiftKey)return;n.preventDefault(),n.stopImmediatePropagation(),r(o,t)}})})}()}();

+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/noneditable/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),l=tinymce.util.Tools.resolve("tinymce.util.Tools"),u=function(t){return t.getParam("noneditable_noneditable_class","mceNonEditable")},f=function(n){return function(t){return-1!==(" "+t.attr("class")+" ").indexOf(n)}},s=function(i,o,c){return function(t){var n=arguments,e=n[n.length-2],r=0<e?o.charAt(e-1):"";if('"'===r)return t;if(">"===r){var a=o.lastIndexOf("<",e);if(-1!==a)if(-1!==o.substring(a,e).indexOf('contenteditable="false"'))return t}return'<span class="'+c+'" data-mce-content="'+i.dom.encode(n[0])+'">'+i.dom.encode("string"==typeof n[1]?n[1]:n[0])+"</span>"}},n=function(n){var t,r="contenteditable",e=" "+l.trim(n.getParam("noneditable_editable_class","mceEditable"))+" ",a=" "+l.trim(u(n))+" ",i=f(e),o=f(a),c=(t=n.getParam("noneditable_regexp",[]))&&t.constructor===RegExp?[t]:t;n.on("PreInit",function(){0<c.length&&n.on("BeforeSetContent",function(t){!function(t,n,e){var r=n.length,a=e.content;if("raw"!==e.format){for(;r--;)a=a.replace(n[r],s(t,a,u(t)));e.content=a}}(n,c,t)}),n.parser.addAttributeFilter("class",function(t){for(var n,e=t.length;e--;)n=t[e],i(n)?n.attr(r,"true"):o(n)&&n.attr(r,"false")}),n.serializer.addAttributeFilter(r,function(t){for(var n,e=t.length;e--;)n=t[e],(i(n)||o(n))&&(0<c.length&&n.attr("data-mce-content")?(n.name="#text",n.type=3,n.raw=!0,n.value=n.attr("data-mce-content")):n.attr(r,null))})})};!function e(){t.add("noneditable",function(t){n(t)})}()}();

+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/pagebreak/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=tinymce.util.Tools.resolve("tinymce.Env"),i=function(e){return e.getParam("pagebreak_split_block",!1)},g=function(){return"mce-pagebreak"},u=function(){return'<img src="'+a.transparentSrc+'" class="'+g()+'" data-mce-resize="false" data-mce-placeholder />'};!function n(){e.add("pagebreak",function(e){var a,n,o,c,t,r;(a=e).addCommand("mcePageBreak",function(){i(a)?a.insertContent("<p>"+u()+"</p>"):a.insertContent(u())}),(n=e).ui.registry.addButton("pagebreak",{icon:"page-break",tooltip:"Page break",onAction:function(){return n.execCommand("mcePageBreak")}}),n.ui.registry.addMenuItem("pagebreak",{text:"Page break",icon:"page-break",onAction:function(){return n.execCommand("mcePageBreak")}}),c=(o=e).getParam("pagebreak_separator","\x3c!-- pagebreak --\x3e"),t=new RegExp(c.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,function(e){return"\\"+e}),"gi"),o.on("BeforeSetContent",function(e){e.content=e.content.replace(t,u())}),o.on("PreInit",function(){o.serializer.addNodeFilter("img",function(e){for(var a,n,t=e.length;t--;)if((n=(a=e[t]).attr("class"))&&-1!==n.indexOf("mce-pagebreak")){var r=a.parent;if(o.schema.getBlockElements()[r.name]&&i(o)){r.type=3,r.value=c,r.raw=!0,a.remove();continue}a.type=3,a.value=c,a.raw=!0}})}),(r=e).on("ResolveName",function(e){"IMG"===e.target.nodeName&&r.dom.hasClass(e.target,g())&&(e.name="pagebreak")})})}()}();

Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/paste/plugin.min.js


+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/preview/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),g=tinymce.util.Tools.resolve("tinymce.Env"),w=tinymce.util.Tools.resolve("tinymce.util.Tools"),i=function(e){var t=function(t){var n="",i=t.dom.encode,e=t.getParam("content_style","");n+='<base href="'+i(t.documentBaseURI.getURI())+'">',e&&(n+='<style type="text/css">'+e+"</style>");var o=t.getParam("content_css_cors",!1,"boolean")?' crossorigin="anonymous"':"";w.each(t.contentCSS,function(e){n+='<link type="text/css" rel="stylesheet" href="'+i(t.documentBaseURI.toAbsolute(e))+'"'+o+">"});var r,a,c,s,d,m,l,u=-1===(s=(r=t).getParam("body_id","tinymce","string")).indexOf("=")?s:(c=(a=r).getParam("body_id","","hash"))[a.id]||c,y=-1===(l=(d=t).getParam("body_class","","string")).indexOf("=")?l:(m=d).getParam("body_class","","hash")[m.id]||"",v='<script>document.addEventListener && document.addEventListener("click", function(e) {for (var elm = e.target; elm; elm = elm.parentNode) {if (elm.nodeName === "A" && !('+(g.mac?"e.metaKey":"e.ctrlKey && !e.altKey")+")) {e.preventDefault();}}}, false);<\/script> ",f=t.getBody().dir,p=f?' dir="'+i(f)+'"':"";return"<!DOCTYPE html><html><head>"+n+'</head><body id="'+i(u)+'" class="mce-content-body '+i(y)+'"'+p+">"+t.getContent()+v+"</body></html>"}(e);e.windowManager.open({title:"Preview",size:"large",body:{type:"panel",items:[{name:"preview",type:"iframe",sandboxed:!0}]},buttons:[{type:"cancel",name:"close",text:"Close",primary:!0}],initialData:{preview:t}}).focus("close")};!function t(){e.add("preview",function(e){var t,n;(t=e).addCommand("mcePreview",function(){i(t)}),(n=e).ui.registry.addButton("preview",{icon:"preview",tooltip:"Preview",onAction:function(){return n.execCommand("mcePreview")}}),n.ui.registry.addMenuItem("preview",{icon:"preview",text:"Preview",onAction:function(){return n.execCommand("mcePreview")}})})}()}();

+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/print/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),e=tinymce.util.Tools.resolve("tinymce.Env");!function t(){n.add("print",function(n){var t,i;(t=n).addCommand("mcePrint",function(){e.browser.isIE()?t.getDoc().execCommand("print",!1,null):t.getWin().print()}),(i=n).ui.registry.addButton("print",{icon:"print",tooltip:"Print",onAction:function(){return i.execCommand("mcePrint")}}),i.ui.registry.addMenuItem("print",{text:"Print...",icon:"print",onAction:function(){return i.execCommand("mcePrint")}}),n.addShortcut("Meta+P","","mcePrint")})}()}();

Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/quickbars/plugin.min.js


+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/save/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),o=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),a=tinymce.util.Tools.resolve("tinymce.util.Tools"),i=function(e){return e.getParam("save_enablewhendirty",!0)},c=function(e,n){e.notificationManager.open({text:n,type:"error"})},t=function(t){t.addCommand("mceSave",function(){!function(e){var n=o.DOM.getParent(e.id,"form");if(!i(e)||e.isDirty()){if(e.save(),e.getParam("save_onsavecallback"))return e.execCallback("save_onsavecallback",e),e.nodeChanged();n?(e.setDirty(!1),n.onsubmit&&!n.onsubmit()||("function"==typeof n.submit?n.submit():c(e,"Error: Form submit field collision.")),e.nodeChanged()):c(e,"Error: No form element found.")}}(t)}),t.addCommand("mceCancel",function(){var e,n;e=t,n=a.trim(e.startContent),e.getParam("save_oncancelcallback")?e.execCallback("save_oncancelcallback",e):e.resetContent(n)})},r=function(t){return function(e){var n=function(){e.setDisabled(i(t)&&!t.isDirty())};return t.on("NodeChange dirty",n),function(){return t.off("NodeChange dirty",n)}}};!function n(){e.add("save",function(e){var n;(n=e).ui.registry.addButton("save",{icon:"save",tooltip:"Save",disabled:!0,onAction:function(){return n.execCommand("mceSave")},onSetup:r(n)}),n.ui.registry.addButton("cancel",{icon:"cancel",tooltip:"Cancel",disabled:!0,onAction:function(){return n.execCommand("mceCancel")},onSetup:r(n)}),n.addShortcut("Meta+S","","mceSave"),t(e)})}()}();

Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/searchreplace/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/spellchecker/plugin.min.js


+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/tabfocus/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(s){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),a=tinymce.util.Tools.resolve("tinymce.EditorManager"),y=tinymce.util.Tools.resolve("tinymce.Env"),f=tinymce.util.Tools.resolve("tinymce.util.Delay"),d=tinymce.util.Tools.resolve("tinymce.util.Tools"),m=tinymce.util.Tools.resolve("tinymce.util.VK"),v=t.DOM,n=function(e){e.keyCode!==m.TAB||e.ctrlKey||e.altKey||e.metaKey||e.preventDefault()},i=function(c){function e(n){var i,o,l;if(!(n.keyCode!==m.TAB||n.ctrlKey||n.altKey||n.metaKey||n.isDefaultPrevented())){var e,t=d.explode((e=c).getParam("tab_focus",e.getParam("tabfocus_elements",":prev,:next")));if(1===t.length&&(t[1]=t[0],t[0]=":prev"),o=n.shiftKey?":prev"===t[0]?r(-1):v.get(t[0]):":next"===t[1]?r(1):v.get(t[1])){var u=a.get(o.id||o.name);o.id&&u?u.focus():f.setTimeout(function(){y.webkit||s.window.focus(),o.focus()},10),n.preventDefault()}}function r(e){function t(e){return/INPUT|TEXTAREA|BUTTON/.test(e.tagName)&&a.get(n.id)&&-1!==e.tabIndex&&function t(e){return"BODY"===e.nodeName||"hidden"!==e.type&&"none"!==e.style.display&&"hidden"!==e.style.visibility&&t(e.parentNode)}(e)}if(o=v.select(":input:enabled,*[tabindex]:not(iframe)"),d.each(o,function(e,t){if(e.id===c.id)return i=t,!1}),0<e){for(l=i+1;l<o.length;l++)if(t(o[l]))return o[l]}else for(l=i-1;0<=l;l--)if(t(o[l]))return o[l];return null}}c.on("init",function(){c.inline&&v.setAttrib(c.getBody(),"tabIndex",null),c.on("keyup",n),y.gecko?c.on("keypress keydown",e):c.on("keydown",e)})};!function o(){e.add("tabfocus",function(e){i(e)})}()}(window);

Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/table/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/template/plugin.min.js


+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/textcolor/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(o){"use strict";var i=tinymce.util.Tools.resolve("tinymce.PluginManager");!function n(){i.add("textcolor",function(){o.console.warn("Text color plugin is now built in to the core editor, please remove it from your editor configuration")})}()}(window);

Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/textpattern/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/toc/plugin.min.js


+ 9 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/visualblocks/plugin.min.js

@@ -0,0 +1,9 @@
+/**
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
+ * Licensed under the LGPL or a commercial license.
+ * For LGPL see License.txt in the project root for license information.
+ * For commercial licenses see https://www.tiny.cloud/
+ *
+ * Version: 5.4.1 (2020-07-08)
+ */
+!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),r=function(t,o,e){var n,i;t.dom.toggleClass(t.getBody(),"mce-visualblocks"),e.set(!e.get()),n=t,i=e.get(),n.fire("VisualBlocks",{state:i})},f=function(e,n){return function(o){o.setActive(n.get());var t=function(t){return o.setActive(t.state)};return e.on("VisualBlocks",t),function(){return e.off("VisualBlocks",t)}}};!function o(){t.add("visualblocks",function(t,o){var e,n,i,s,c,u,l,a=(e=!1,{get:function(){return e},set:function(t){e=t}});i=a,(n=t).addCommand("mceVisualBlocks",function(){r(n,0,i)}),c=a,(s=t).ui.registry.addToggleButton("visualblocks",{icon:"visualblocks",tooltip:"Show blocks",onAction:function(){return s.execCommand("mceVisualBlocks")},onSetup:f(s,c)}),s.ui.registry.addToggleMenuItem("visualblocks",{text:"Show blocks",icon:"visualblocks",onAction:function(){return s.execCommand("mceVisualBlocks")},onSetup:f(s,c)}),l=a,(u=t).on("PreviewFormats AfterPreviewFormats",function(t){l.get()&&u.dom.toggleClass(u.getBody(),"mce-visualblocks","afterpreviewformats"===t.type)}),u.on("init",function(){u.getParam("visualblocks_default_state",!1,"boolean")&&r(u,0,l)})})}()}();

Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/visualchars/plugin.min.js


Diff do ficheiro suprimidas por serem muito extensas
+ 8 - 0
wj-pack/backend/app/public/message/check/tinymce/js/tinymce/plugins/wordcount/plugin.min.js


Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff